From 54ad6c624141128805f7e8004a7c5873637c25ac Mon Sep 17 00:00:00 2001 From: Mazunki Hoksaas Date: Fri, 28 Jun 2024 23:54:14 +0200 Subject: [PATCH] support notification-fd for ready state --- amdfan/commands.py | 10 +++-- amdfan/controller.py | 105 ++++++++++++++++++++++++------------------- 2 files changed, 67 insertions(+), 48 deletions(-) diff --git a/amdfan/commands.py b/amdfan/commands.py index f4e9174..082bbca 100644 --- a/amdfan/commands.py +++ b/amdfan/commands.py @@ -1,6 +1,7 @@ #!/usr/bin/env python """ entry point for amdfan """ # noqa: E501 +import os import sys import time from typing import Dict @@ -12,7 +13,7 @@ from rich.table import Table from rich.traceback import install -from .config import LOGGER +from .config import LOGGER, PIDFILE_DIR from .controller import FanController, Scanner from .defaults import DEFAULT_FAN_CONFIG, SERVICES @@ -52,9 +53,12 @@ def cli( name="daemon", help="Run the controller", ) +@click.option("--notification-fd", type=int) # @click.option("--background", is_flag=True, default=True) -def run_daemon(): - FanController.start_daemon() +def run_daemon(notification_fd): + FanController.start_daemon( + notification_fd=notification_fd, pidfile=os.path.join(PIDFILE_DIR, "amdfan.pid") + ) def show_table(cards: Dict) -> Table: diff --git a/amdfan/controller.py b/amdfan/controller.py index 650eb4d..4dcc39c 100644 --- a/amdfan/controller.py +++ b/amdfan/controller.py @@ -6,13 +6,13 @@ import signal import sys import time -from typing import Any, Callable, Dict, List, Self +from typing import Any, Callable, Dict, List, Optional, Self import numpy as np import yaml from numpy import ndarray -from .config import CONFIG_LOCATIONS, HWMON_DIR, LOGGER, PIDFILE_DIR, ROOT_DIR +from .config import CONFIG_LOCATIONS, HWMON_DIR, LOGGER, ROOT_DIR from .defaults import DEFAULT_FAN_CONFIG @@ -30,6 +30,10 @@ def remove_pidfile() -> None: LOGGER.info("Saved pidfile with running pid=%s", pid) +def report_ready(fd: int) -> None: + os.write(fd, b"READY=1\n") + + class Curve: # pylint: disable=too-few-public-methods """ creates a fan curve based on user defined points @@ -198,10 +202,11 @@ class FanController: # pylint: disable=too-few-public-methods _threshold: int _frequency: int - def __init__(self, config_path) -> None: + def __init__(self, config_path, notification_fd=None) -> None: self.config_path = config_path self.reload_config() self._last_temp = 0 + self._ready_fd = notification_fd def reload_config(self, *_) -> None: config = load_config(self.config_path) @@ -218,53 +223,62 @@ def apply(self, config) -> None: def main(self) -> None: LOGGER.info("Starting amdfan") + if self._ready_fd is not None: + report_ready(self._ready_fd) + while True: for name, card in self._scanner.cards.items(): - apply = True - temp = card.gpu_temp - speed = int(self._curve.get_speed(int(temp))) - if speed < 0: - speed = 4 # due to driver bug - - LOGGER.debug( - "%s: Temp %d, \ - last temp: %d \ - target fan speed: %d, \ - fan speed %d, \ - min: %d, max: %d", - name, - temp, - self._last_temp, - speed, - card.fan_speed, - card.fan_min, - card.fan_max, - ) - if self._threshold and self._last_temp: - - LOGGER.debug("threshold and last temp, checking") - low = self._last_temp - self._threshold - high = self._last_temp + self._threshold - - LOGGER.debug("%d and %d and %d", low, high, temp) - if int(temp) in range(int(low), int(high)): - LOGGER.debug("temp in range, doing nothing") - apply = False - else: - LOGGER.debug("temp out of range, setting") - card.set_fan_speed(speed) - self._last_temp = temp - continue - - if apply: - card.set_fan_speed(speed) - self._last_temp = temp + self.refresh_card(name, card) time.sleep(self._frequency) + def refresh_card(self, name, card): + apply = True + temp = card.gpu_temp + speed = int(self._curve.get_speed(int(temp))) + if speed < 0: + speed = 4 # due to driver bug + + LOGGER.debug( + "%s: Temp %d, \ + last temp: %d \ + target fan speed: %d, \ + fan speed %d, \ + min: %d, max: %d", + name, + temp, + self._last_temp, + speed, + card.fan_speed, + card.fan_min, + card.fan_max, + ) + if self._threshold and self._last_temp: + + LOGGER.debug("threshold and last temp, checking") + low = self._last_temp - self._threshold + high = self._last_temp + self._threshold + + LOGGER.debug("%d and %d and %d", low, high, temp) + if int(temp) in range(int(low), int(high)): + LOGGER.debug("temp in range, doing nothing") + apply = False + else: + LOGGER.debug("temp out of range, setting") + card.set_fan_speed(speed) + self._last_temp = temp + return + + if apply: + card.set_fan_speed(speed) + self._last_temp = temp + @classmethod - def start_daemon(cls) -> Self: - create_pidfile(os.path.join(PIDFILE_DIR, "amdfan.pid")) + def start_daemon( + cls, notification_fd: Optional[int], pidfile: Optional[str] = None + ) -> Self: + if pidfile: + create_pidfile(pidfile) config_path = None for location in CONFIG_LOCATIONS: @@ -278,9 +292,10 @@ def start_daemon(cls) -> Self: config_file.write(DEFAULT_FAN_CONFIG) config_file.flush() - controller = cls(config_path) + controller = cls(config_path, notification_fd=notification_fd) signal.signal(signal.SIGHUP, controller.reload_config) controller.main() + return controller