mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
feat: gpu_controllers behind an RwLock
This commit is contained in:
parent
9ba8dd6588
commit
599adf63cc
@ -124,7 +124,7 @@ async fn listen_config_changes(handler: Handler) {
|
|||||||
let mut rx = config::start_watcher(handler.config_last_saved.clone());
|
let mut rx = config::start_watcher(handler.config_last_saved.clone());
|
||||||
while let Some(new_config) = rx.recv().await {
|
while let Some(new_config) = rx.recv().await {
|
||||||
info!("config file was changed, reloading");
|
info!("config file was changed, reloading");
|
||||||
handler.config.replace(new_config);
|
*handler.config.write().await = new_config;
|
||||||
match handler.apply_current_config().await {
|
match handler.apply_current_config().await {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
info!("configuration reloaded");
|
info!("configuration reloaded");
|
||||||
|
@ -131,12 +131,12 @@ async fn handle_request<'a>(request: Request<'a>, handler: &'a Handler) -> anyho
|
|||||||
match request {
|
match request {
|
||||||
Request::Ping => ok_response(ping()),
|
Request::Ping => ok_response(ping()),
|
||||||
Request::SystemInfo => ok_response(system::info().await?),
|
Request::SystemInfo => ok_response(system::info().await?),
|
||||||
Request::ListDevices => ok_response(handler.list_devices()),
|
Request::ListDevices => ok_response(handler.list_devices().await),
|
||||||
Request::DeviceInfo { id } => ok_response(handler.get_device_info(id)?),
|
Request::DeviceInfo { id } => ok_response(handler.get_device_info(id).await?),
|
||||||
Request::DeviceStats { id } => ok_response(handler.get_gpu_stats(id)?),
|
Request::DeviceStats { id } => ok_response(handler.get_gpu_stats(id).await?),
|
||||||
Request::DeviceClocksInfo { id } => ok_response(handler.get_clocks_info(id)?),
|
Request::DeviceClocksInfo { id } => ok_response(handler.get_clocks_info(id).await?),
|
||||||
Request::DevicePowerProfileModes { id } => {
|
Request::DevicePowerProfileModes { id } => {
|
||||||
ok_response(handler.get_power_profile_modes(id)?)
|
ok_response(handler.get_power_profile_modes(id).await?)
|
||||||
}
|
}
|
||||||
Request::SetFanControl(opts) => ok_response(handler.set_fan_control(opts).await?),
|
Request::SetFanControl(opts) => ok_response(handler.set_fan_control(opts).await?),
|
||||||
Request::ResetPmfw { id } => ok_response(handler.reset_pmfw(id).await?),
|
Request::ResetPmfw { id } => ok_response(handler.reset_pmfw(id).await?),
|
||||||
@ -160,13 +160,13 @@ async fn handle_request<'a>(request: Request<'a>, handler: &'a Handler) -> anyho
|
|||||||
.set_power_profile_mode(id, index, custom_heuristics)
|
.set_power_profile_mode(id, index, custom_heuristics)
|
||||||
.await?,
|
.await?,
|
||||||
),
|
),
|
||||||
Request::GetPowerStates { id } => ok_response(handler.get_power_states(id)?),
|
Request::GetPowerStates { id } => ok_response(handler.get_power_states(id).await?),
|
||||||
Request::SetEnabledPowerStates { id, kind, states } => {
|
Request::SetEnabledPowerStates { id, kind, states } => {
|
||||||
ok_response(handler.set_enabled_power_states(id, kind, states).await?)
|
ok_response(handler.set_enabled_power_states(id, kind, states).await?)
|
||||||
}
|
}
|
||||||
Request::VbiosDump { id } => ok_response(handler.vbios_dump(id)?),
|
Request::VbiosDump { id } => ok_response(handler.vbios_dump(id).await?),
|
||||||
Request::ListProfiles { include_state } => {
|
Request::ListProfiles { include_state } => {
|
||||||
ok_response(handler.list_profiles(include_state))
|
ok_response(handler.list_profiles(include_state).await)
|
||||||
}
|
}
|
||||||
Request::SetProfile { name, auto_switch } => ok_response(
|
Request::SetProfile { name, auto_switch } => ok_response(
|
||||||
handler
|
handler
|
||||||
|
@ -25,6 +25,7 @@ use std::{cell::LazyCell, collections::HashMap, fs, path::PathBuf, rc::Rc};
|
|||||||
use tokio::{sync::Notify, task::JoinHandle};
|
use tokio::{sync::Notify, task::JoinHandle};
|
||||||
use tracing::{error, warn};
|
use tracing::{error, warn};
|
||||||
|
|
||||||
|
pub type DynGpuController = Box<dyn GpuController>;
|
||||||
type FanControlHandle = (Rc<Notify>, JoinHandle<()>);
|
type FanControlHandle = (Rc<Notify>, JoinHandle<()>);
|
||||||
|
|
||||||
pub trait GpuController {
|
pub trait GpuController {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use super::{
|
use super::{
|
||||||
gpu_controller::{fan_control::FanCurve, GpuController},
|
gpu_controller::{fan_control::FanCurve, DynGpuController, GpuController},
|
||||||
profiles::ProfileWatcherCommand,
|
profiles::ProfileWatcherCommand,
|
||||||
system::{self, detect_initramfs_type, PP_FEATURE_MASK_PATH},
|
system::{self, detect_initramfs_type, PP_FEATURE_MASK_PATH},
|
||||||
};
|
};
|
||||||
@ -38,7 +38,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
process::Command,
|
process::Command,
|
||||||
sync::{mpsc, oneshot},
|
sync::{mpsc, oneshot, RwLock, RwLockReadGuard},
|
||||||
time::sleep,
|
time::sleep,
|
||||||
};
|
};
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
@ -86,8 +86,8 @@ const SNAPSHOT_FAN_CTRL_FILES: &[&str] = &[
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Handler {
|
pub struct Handler {
|
||||||
pub config: Rc<RefCell<Config>>,
|
pub config: Rc<RwLock<Config>>,
|
||||||
pub gpu_controllers: Rc<BTreeMap<String, Box<dyn GpuController>>>,
|
pub gpu_controllers: Rc<RwLock<BTreeMap<String, DynGpuController>>>,
|
||||||
confirm_config_tx: Rc<RefCell<Option<oneshot::Sender<ConfirmCommand>>>>,
|
confirm_config_tx: Rc<RefCell<Option<oneshot::Sender<ConfirmCommand>>>>,
|
||||||
pub config_last_saved: Rc<Cell<Instant>>,
|
pub config_last_saved: Rc<Cell<Instant>>,
|
||||||
pub profile_watcher_tx: Rc<RefCell<Option<mpsc::Sender<ProfileWatcherCommand>>>>,
|
pub profile_watcher_tx: Rc<RefCell<Option<mpsc::Sender<ProfileWatcherCommand>>>>,
|
||||||
@ -151,8 +151,8 @@ impl<'a> Handler {
|
|||||||
info!("initialized {} GPUs", controllers.len());
|
info!("initialized {} GPUs", controllers.len());
|
||||||
|
|
||||||
let handler = Self {
|
let handler = Self {
|
||||||
gpu_controllers: Rc::new(controllers),
|
gpu_controllers: Rc::new(RwLock::new(controllers)),
|
||||||
config: Rc::new(RefCell::new(config)),
|
config: Rc::new(RwLock::new(config)),
|
||||||
confirm_config_tx: Rc::new(RefCell::new(None)),
|
confirm_config_tx: Rc::new(RefCell::new(None)),
|
||||||
config_last_saved: Rc::new(Cell::new(Instant::now())),
|
config_last_saved: Rc::new(Cell::new(Instant::now())),
|
||||||
profile_watcher_tx: Rc::new(RefCell::new(None)),
|
profile_watcher_tx: Rc::new(RefCell::new(None)),
|
||||||
@ -162,11 +162,11 @@ impl<'a> Handler {
|
|||||||
error!("could not apply config: {err:#}");
|
error!("could not apply config: {err:#}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(profile_name) = &handler.config.borrow().current_profile {
|
if let Some(profile_name) = &handler.config.read().await.current_profile {
|
||||||
info!("using profile '{profile_name}'");
|
info!("using profile '{profile_name}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
if handler.config.borrow().auto_switch_profiles {
|
if handler.config.read().await.auto_switch_profiles {
|
||||||
handler.start_profile_watcher().await;
|
handler.start_profile_watcher().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,11 +182,12 @@ impl<'a> Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn apply_current_config(&self) -> anyhow::Result<()> {
|
pub async fn apply_current_config(&self) -> anyhow::Result<()> {
|
||||||
let config = self.config.borrow().clone(); // Clone to avoid locking the RwLock on an await point
|
let config = self.config.read().await;
|
||||||
|
|
||||||
let gpus = config.gpus()?;
|
let gpus = config.gpus()?;
|
||||||
|
let controllers = self.gpu_controllers.read().await;
|
||||||
for (id, gpu_config) in gpus {
|
for (id, gpu_config) in gpus {
|
||||||
if let Some(controller) = self.gpu_controllers.get(id) {
|
if let Some(controller) = controllers.get(id) {
|
||||||
if let Err(err) = controller.apply_config(gpu_config).await {
|
if let Err(err) = controller.apply_config(gpu_config).await {
|
||||||
error!("could not apply existing config for gpu {id}: {err}");
|
error!("could not apply existing config for gpu {id}: {err}");
|
||||||
}
|
}
|
||||||
@ -231,7 +232,7 @@ impl<'a> Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let (gpu_config, apply_timer) = {
|
let (gpu_config, apply_timer) = {
|
||||||
let config = self.config.try_borrow().map_err(|err| anyhow!("{err}"))?;
|
let config = self.config.read().await;
|
||||||
let apply_timer = config.apply_settings_timer;
|
let apply_timer = config.apply_settings_timer;
|
||||||
let gpu_config = config.gpus()?.get(&id).cloned().unwrap_or_default();
|
let gpu_config = config.gpus()?.get(&id).cloned().unwrap_or_default();
|
||||||
(gpu_config, apply_timer)
|
(gpu_config, apply_timer)
|
||||||
@ -240,7 +241,7 @@ impl<'a> Handler {
|
|||||||
let mut new_config = gpu_config.clone();
|
let mut new_config = gpu_config.clone();
|
||||||
f(&mut new_config);
|
f(&mut new_config);
|
||||||
|
|
||||||
let controller = self.controller_by_id(&id)?;
|
let controller = self.controller_by_id(&id).await?;
|
||||||
|
|
||||||
match controller.apply_config(&new_config).await {
|
match controller.apply_config(&new_config).await {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
@ -278,6 +279,7 @@ impl<'a> Handler {
|
|||||||
tokio::task::spawn_local(async move {
|
tokio::task::spawn_local(async move {
|
||||||
let controller = handler
|
let controller = handler
|
||||||
.controller_by_id(&id)
|
.controller_by_id(&id)
|
||||||
|
.await
|
||||||
.expect("GPU controller disappeared");
|
.expect("GPU controller disappeared");
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
@ -293,7 +295,7 @@ impl<'a> Handler {
|
|||||||
Ok(ConfirmCommand::Confirm) => {
|
Ok(ConfirmCommand::Confirm) => {
|
||||||
info!("saving updated config");
|
info!("saving updated config");
|
||||||
|
|
||||||
let mut config_guard = handler.config.borrow_mut();
|
let mut config_guard = handler.config.write().await;
|
||||||
match config_guard.gpus_mut() {
|
match config_guard.gpus_mut() {
|
||||||
Ok(gpus) => {
|
Ok(gpus) => {
|
||||||
gpus.insert(id, new_config);
|
gpus.insert(id, new_config);
|
||||||
@ -323,16 +325,19 @@ impl<'a> Handler {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn controller_by_id(&self, id: &str) -> anyhow::Result<&dyn GpuController> {
|
async fn controller_by_id(
|
||||||
Ok(self
|
&self,
|
||||||
.gpu_controllers
|
id: &str,
|
||||||
.get(id)
|
) -> anyhow::Result<RwLockReadGuard<'_, dyn GpuController>> {
|
||||||
.context("No controller with such id")?
|
let guard = self.gpu_controllers.read().await;
|
||||||
.as_ref())
|
RwLockReadGuard::try_map(guard, |controllers| controllers.get(id).map(Box::as_ref))
|
||||||
|
.map_err(|_| anyhow!("Controller '{id}' not found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_devices(&'a self) -> Vec<DeviceListEntry> {
|
pub async fn list_devices(&'a self) -> Vec<DeviceListEntry> {
|
||||||
self.gpu_controllers
|
self.gpu_controllers
|
||||||
|
.read()
|
||||||
|
.await
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(id, controller)| {
|
.map(|(id, controller)| {
|
||||||
let name = controller
|
let name = controller
|
||||||
@ -349,29 +354,23 @@ impl<'a> Handler {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_device_info(&'a self, id: &str) -> anyhow::Result<DeviceInfo> {
|
pub async fn get_device_info(&'a self, id: &str) -> anyhow::Result<DeviceInfo> {
|
||||||
Ok(self.controller_by_id(id)?.get_info())
|
Ok(self.controller_by_id(id).await?.get_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_gpu_stats(&'a self, id: &str) -> anyhow::Result<DeviceStats> {
|
pub async fn get_gpu_stats(&'a self, id: &str) -> anyhow::Result<DeviceStats> {
|
||||||
let config = self
|
let config = self.config.read().await;
|
||||||
.config
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|err| anyhow!("Could not read config: {err:?}"))?;
|
|
||||||
let gpu_config = config.gpus()?.get(id);
|
let gpu_config = config.gpus()?.get(id);
|
||||||
Ok(self.controller_by_id(id)?.get_stats(gpu_config))
|
Ok(self.controller_by_id(id).await?.get_stats(gpu_config))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_clocks_info(&'a self, id: &str) -> anyhow::Result<ClocksInfo> {
|
pub async fn get_clocks_info(&'a self, id: &str) -> anyhow::Result<ClocksInfo> {
|
||||||
self.controller_by_id(id)?.get_clocks_info()
|
self.controller_by_id(id).await?.get_clocks_info()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_fan_control(&'a self, opts: FanOptions<'_>) -> anyhow::Result<u64> {
|
pub async fn set_fan_control(&'a self, opts: FanOptions<'_>) -> anyhow::Result<u64> {
|
||||||
let settings = {
|
let settings = {
|
||||||
let mut config_guard = self
|
let mut config_guard = self.config.write().await;
|
||||||
.config
|
|
||||||
.try_borrow_mut()
|
|
||||||
.map_err(|err| anyhow!("{err}"))?;
|
|
||||||
let gpu_config = config_guard
|
let gpu_config = config_guard
|
||||||
.gpus_mut()?
|
.gpus_mut()?
|
||||||
.entry(opts.id.to_owned())
|
.entry(opts.id.to_owned())
|
||||||
@ -449,7 +448,7 @@ impl<'a> Handler {
|
|||||||
|
|
||||||
pub async fn reset_pmfw(&self, id: &str) -> anyhow::Result<u64> {
|
pub async fn reset_pmfw(&self, id: &str) -> anyhow::Result<u64> {
|
||||||
info!("Resetting PMFW settings");
|
info!("Resetting PMFW settings");
|
||||||
self.controller_by_id(id)?.reset_pmfw_settings();
|
self.controller_by_id(id).await?.reset_pmfw_settings();
|
||||||
|
|
||||||
self.edit_gpu_config(id.to_owned(), |config| {
|
self.edit_gpu_config(id.to_owned(), |config| {
|
||||||
config.pmfw_options = PmfwOptions::default();
|
config.pmfw_options = PmfwOptions::default();
|
||||||
@ -466,14 +465,14 @@ impl<'a> Handler {
|
|||||||
.context("Failed to edit GPU config and set power cap")
|
.context("Failed to edit GPU config and set power cap")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_power_states(&self, id: &str) -> anyhow::Result<PowerStates> {
|
pub async fn get_power_states(&self, id: &str) -> anyhow::Result<PowerStates> {
|
||||||
let config = self
|
let config = self.config.read().await;
|
||||||
.config
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|err| anyhow!("Could not read config: {err:?}"))?;
|
|
||||||
let gpu_config = config.gpus()?.get(id);
|
let gpu_config = config.gpus()?.get(id);
|
||||||
|
|
||||||
let states = self.controller_by_id(id)?.get_power_states(gpu_config);
|
let states = self
|
||||||
|
.controller_by_id(id)
|
||||||
|
.await?
|
||||||
|
.get_power_states(gpu_config);
|
||||||
Ok(states)
|
Ok(states)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,7 +498,7 @@ impl<'a> Handler {
|
|||||||
command: SetClocksCommand,
|
command: SetClocksCommand,
|
||||||
) -> anyhow::Result<u64> {
|
) -> anyhow::Result<u64> {
|
||||||
if let SetClocksCommand::Reset = command {
|
if let SetClocksCommand::Reset = command {
|
||||||
self.controller_by_id(id)?.cleanup_clocks()?;
|
self.controller_by_id(id).await?.cleanup_clocks()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.edit_gpu_config(id.to_owned(), |gpu_config| {
|
self.edit_gpu_config(id.to_owned(), |gpu_config| {
|
||||||
@ -523,8 +522,11 @@ impl<'a> Handler {
|
|||||||
.context("Failed to edit GPU config and batch set clocks")
|
.context("Failed to edit GPU config and batch set clocks")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_power_profile_modes(&self, id: &str) -> anyhow::Result<PowerProfileModesTable> {
|
pub async fn get_power_profile_modes(
|
||||||
let modes_table = self.controller_by_id(id)?.get_power_profile_modes()?;
|
&self,
|
||||||
|
id: &str,
|
||||||
|
) -> anyhow::Result<PowerProfileModesTable> {
|
||||||
|
let modes_table = self.controller_by_id(id).await?.get_power_profile_modes()?;
|
||||||
Ok(modes_table)
|
Ok(modes_table)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,8 +557,8 @@ impl<'a> Handler {
|
|||||||
.context("Failed to edit GPU config and set enabled power states")
|
.context("Failed to edit GPU config and set enabled power states")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vbios_dump(&self, id: &str) -> anyhow::Result<Vec<u8>> {
|
pub async fn vbios_dump(&self, id: &str) -> anyhow::Result<Vec<u8>> {
|
||||||
self.controller_by_id(id)?.vbios_dump()
|
self.controller_by_id(id).await?.vbios_dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn generate_snapshot(&self) -> anyhow::Result<String> {
|
pub async fn generate_snapshot(&self) -> anyhow::Result<String> {
|
||||||
@ -575,7 +577,8 @@ impl<'a> Handler {
|
|||||||
add_path_to_archive(&mut archive, path)?;
|
add_path_to_archive(&mut archive, path)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for controller in self.gpu_controllers.values() {
|
let controllers = self.gpu_controllers.read().await;
|
||||||
|
for controller in controllers.values() {
|
||||||
let controller_path = &controller.controller_info().sysfs_path;
|
let controller_path = &controller.controller_info().sysfs_path;
|
||||||
|
|
||||||
for device_file in SNAPSHOT_DEVICE_FILES {
|
for device_file in SNAPSHOT_DEVICE_FILES {
|
||||||
@ -664,7 +667,7 @@ impl<'a> Handler {
|
|||||||
let info = json!({
|
let info = json!({
|
||||||
"system_info": system_info,
|
"system_info": system_info,
|
||||||
"initramfs_type": initramfs_type,
|
"initramfs_type": initramfs_type,
|
||||||
"devices": self.generate_snapshot_device_info(),
|
"devices": self.generate_snapshot_device_info().await,
|
||||||
});
|
});
|
||||||
let info_data = serde_json::to_vec_pretty(&info).unwrap();
|
let info_data = serde_json::to_vec_pretty(&info).unwrap();
|
||||||
|
|
||||||
@ -689,37 +692,40 @@ impl<'a> Handler {
|
|||||||
Ok(out_path)
|
Ok(out_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn generate_snapshot_device_info(&self) -> BTreeMap<String, serde_json::Value> {
|
pub(crate) async fn generate_snapshot_device_info(
|
||||||
self.gpu_controllers
|
&self,
|
||||||
.iter()
|
) -> BTreeMap<String, serde_json::Value> {
|
||||||
.map(|(id, controller)| {
|
let controllers = self.gpu_controllers.read().await;
|
||||||
let config = self.config.try_borrow();
|
let config = self.config.read().await;
|
||||||
let gpu_config = config
|
|
||||||
.as_ref()
|
|
||||||
.ok()
|
|
||||||
.and_then(|config| config.gpus().ok()?.get(id));
|
|
||||||
|
|
||||||
let data = json!({
|
let mut map = BTreeMap::new();
|
||||||
"pci_info": controller.controller_info().pci_info.clone(),
|
|
||||||
"info": controller.get_info(),
|
for (id, controller) in controllers.iter() {
|
||||||
"stats": controller.get_stats(gpu_config),
|
let gpu_config = config.gpus().ok().and_then(|gpus| gpus.get(id));
|
||||||
"clocks_info": controller.get_clocks_info().ok(),
|
|
||||||
"power_profile_modes": controller.get_power_profile_modes().ok(),
|
let data = json!({
|
||||||
"power_states": controller.get_power_states(gpu_config),
|
"pci_info": controller.controller_info().pci_info.clone(),
|
||||||
});
|
"info": controller.get_info(),
|
||||||
(id.clone(), data)
|
"stats": controller.get_stats(gpu_config),
|
||||||
})
|
"clocks_info": controller.get_clocks_info().ok(),
|
||||||
.collect()
|
"power_profile_modes": controller.get_power_profile_modes().ok(),
|
||||||
|
"power_states": controller.get_power_states(gpu_config),
|
||||||
|
});
|
||||||
|
|
||||||
|
map.insert(id.clone(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
map
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_profiles(&self, include_state: bool) -> ProfilesInfo {
|
pub async fn list_profiles(&self, include_state: bool) -> ProfilesInfo {
|
||||||
let watcher_state = if include_state {
|
let watcher_state = if include_state {
|
||||||
self.profile_watcher_state.borrow().as_ref().cloned()
|
self.profile_watcher_state.borrow().as_ref().cloned()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let config = self.config.borrow();
|
let config = self.config.read().await;
|
||||||
ProfilesInfo {
|
ProfilesInfo {
|
||||||
profiles: config
|
profiles: config
|
||||||
.profiles
|
.profiles
|
||||||
@ -743,19 +749,21 @@ impl<'a> Handler {
|
|||||||
self.stop_profile_watcher().await;
|
self.stop_profile_watcher().await;
|
||||||
self.set_current_profile(name).await?;
|
self.set_current_profile(name).await?;
|
||||||
}
|
}
|
||||||
self.config.borrow_mut().auto_switch_profiles = auto_switch;
|
|
||||||
self.config.borrow_mut().save(&self.config_last_saved)?;
|
let mut config = self.config.write().await;
|
||||||
|
config.auto_switch_profiles = auto_switch;
|
||||||
|
config.save(&self.config_last_saved)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn set_current_profile(&self, name: Option<Rc<str>>) -> anyhow::Result<()> {
|
pub(super) async fn set_current_profile(&self, name: Option<Rc<str>>) -> anyhow::Result<()> {
|
||||||
if let Some(name) = &name {
|
if let Some(name) = &name {
|
||||||
self.config.borrow().profile(name)?;
|
self.config.read().await.profile(name)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cleanup().await;
|
self.cleanup().await;
|
||||||
self.config.borrow_mut().current_profile = name;
|
self.config.write().await.current_profile = name;
|
||||||
|
|
||||||
self.apply_current_config().await?;
|
self.apply_current_config().await?;
|
||||||
|
|
||||||
@ -764,7 +772,7 @@ impl<'a> Handler {
|
|||||||
|
|
||||||
pub async fn create_profile(&self, name: String, base: ProfileBase) -> anyhow::Result<()> {
|
pub async fn create_profile(&self, name: String, base: ProfileBase) -> anyhow::Result<()> {
|
||||||
{
|
{
|
||||||
let mut config = self.config.borrow_mut();
|
let mut config = self.config.write().await;
|
||||||
if config.profiles.contains_key(name.as_str()) {
|
if config.profiles.contains_key(name.as_str()) {
|
||||||
bail!("Profile {name} already exists");
|
bail!("Profile {name} already exists");
|
||||||
}
|
}
|
||||||
@ -787,15 +795,16 @@ impl<'a> Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_profile(&self, name: String) -> anyhow::Result<()> {
|
pub async fn delete_profile(&self, name: String) -> anyhow::Result<()> {
|
||||||
if self.config.borrow().current_profile.as_deref() == Some(&name) {
|
if self.config.read().await.current_profile.as_deref() == Some(&name) {
|
||||||
self.set_current_profile(None).await?;
|
self.set_current_profile(None).await?;
|
||||||
}
|
}
|
||||||
self.config
|
self.config
|
||||||
.borrow_mut()
|
.write()
|
||||||
|
.await
|
||||||
.profiles
|
.profiles
|
||||||
.shift_remove(name.as_str());
|
.shift_remove(name.as_str());
|
||||||
|
|
||||||
self.config.borrow().save(&self.config_last_saved)?;
|
self.config.write().await.save(&self.config_last_saved)?;
|
||||||
|
|
||||||
let tx = self.profile_watcher_tx.borrow().clone();
|
let tx = self.profile_watcher_tx.borrow().clone();
|
||||||
if let Some(tx) = tx {
|
if let Some(tx) = tx {
|
||||||
@ -807,7 +816,7 @@ impl<'a> Handler {
|
|||||||
|
|
||||||
pub async fn move_profile(&self, name: &str, new_position: usize) -> anyhow::Result<()> {
|
pub async fn move_profile(&self, name: &str, new_position: usize) -> anyhow::Result<()> {
|
||||||
{
|
{
|
||||||
let mut config = self.config.borrow_mut();
|
let mut config = self.config.write().await;
|
||||||
|
|
||||||
let current_index = config
|
let current_index = config
|
||||||
.profiles
|
.profiles
|
||||||
@ -836,13 +845,14 @@ impl<'a> Handler {
|
|||||||
rule: Option<ProfileRule>,
|
rule: Option<ProfileRule>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
self.config
|
self.config
|
||||||
.borrow_mut()
|
.write()
|
||||||
|
.await
|
||||||
.profiles
|
.profiles
|
||||||
.get_mut(name)
|
.get_mut(name)
|
||||||
.with_context(|| format!("Profile {name} not found"))?
|
.with_context(|| format!("Profile {name} not found"))?
|
||||||
.rule = rule;
|
.rule = rule;
|
||||||
|
|
||||||
self.config.borrow().save(&self.config_last_saved)?;
|
self.config.read().await.save(&self.config_last_saved)?;
|
||||||
|
|
||||||
let tx = self.profile_watcher_tx.borrow().clone();
|
let tx = self.profile_watcher_tx.borrow().clone();
|
||||||
if let Some(tx) = tx {
|
if let Some(tx) = tx {
|
||||||
@ -879,7 +889,7 @@ impl<'a> Handler {
|
|||||||
pub async fn reset_config(&self) {
|
pub async fn reset_config(&self) {
|
||||||
self.cleanup().await;
|
self.cleanup().await;
|
||||||
|
|
||||||
let mut config = self.config.borrow_mut();
|
let mut config = self.config.write().await;
|
||||||
config.clear();
|
config.clear();
|
||||||
|
|
||||||
if let Err(err) = config.save(&self.config_last_saved) {
|
if let Err(err) = config.save(&self.config_last_saved) {
|
||||||
@ -888,13 +898,10 @@ impl<'a> Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cleanup(&self) {
|
pub async fn cleanup(&self) {
|
||||||
let disable_clocks_cleanup = self
|
let disable_clocks_cleanup = self.config.read().await.daemon.disable_clocks_cleanup;
|
||||||
.config
|
|
||||||
.try_borrow()
|
|
||||||
.map(|config| config.daemon.disable_clocks_cleanup)
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
for (id, controller) in &*self.gpu_controllers {
|
let controllers = self.gpu_controllers.read().await;
|
||||||
|
for (id, controller) in controllers.iter() {
|
||||||
if !disable_clocks_cleanup {
|
if !disable_clocks_cleanup {
|
||||||
debug!("resetting clocks table");
|
debug!("resetting clocks table");
|
||||||
if let Err(err) = controller.cleanup_clocks() {
|
if let Err(err) = controller.cleanup_clocks() {
|
||||||
@ -912,7 +919,7 @@ impl<'a> Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// `sysfs_only` disables initialization of any external data sources, such as libdrm and nvml
|
/// `sysfs_only` disables initialization of any external data sources, such as libdrm and nvml
|
||||||
fn load_controllers(base_path: &Path) -> anyhow::Result<BTreeMap<String, Box<dyn GpuController>>> {
|
fn load_controllers(base_path: &Path) -> anyhow::Result<BTreeMap<String, DynGpuController>> {
|
||||||
let mut controllers = BTreeMap::new();
|
let mut controllers = BTreeMap::new();
|
||||||
|
|
||||||
let pci_db = Database::read().unwrap_or_else(|err| {
|
let pci_db = Database::read().unwrap_or_else(|err| {
|
||||||
|
@ -220,7 +220,7 @@ async fn handle_profile_event(event: &ProfileWatcherEvent, handler: &Handler) {
|
|||||||
|
|
||||||
async fn update_profile(handler: &Handler) {
|
async fn update_profile(handler: &Handler) {
|
||||||
let new_profile = {
|
let new_profile = {
|
||||||
let config = handler.config.borrow();
|
let config = handler.config.read().await;
|
||||||
let profile_rules = config
|
let profile_rules = config
|
||||||
.profiles
|
.profiles
|
||||||
.iter()
|
.iter()
|
||||||
@ -237,7 +237,7 @@ async fn update_profile(handler: &Handler) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if handler.config.borrow().current_profile != new_profile {
|
if handler.config.read().await.current_profile != new_profile {
|
||||||
if let Some(name) = &new_profile {
|
if let Some(name) = &new_profile {
|
||||||
info!("setting current profile to '{name}'");
|
info!("setting current profile to '{name}'");
|
||||||
} else {
|
} else {
|
||||||
|
@ -22,6 +22,7 @@ async fn snapshot_everything() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let device_info = handler
|
let device_info = handler
|
||||||
.generate_snapshot_device_info()
|
.generate_snapshot_device_info()
|
||||||
|
.await
|
||||||
.into_values()
|
.into_values()
|
||||||
.next()
|
.next()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user