daemon: Vastly improved task creation

This commit is contained in:
Luke D. Jones
2022-08-21 20:15:36 +12:00
parent 92009ef96c
commit 1f697b5ff1
6 changed files with 185 additions and 225 deletions

View File

@@ -1,10 +1,8 @@
pub mod config; pub mod config;
pub mod zbus; pub mod zbus;
use ::zbus::Connection;
use async_trait::async_trait; use async_trait::async_trait;
use log::{error, info, warn}; use log::{error, info, warn};
use logind_zbus::manager::ManagerProxy;
use rog_anime::{ use rog_anime::{
error::AnimeError, error::AnimeError,
usb::{ usb::{
@@ -14,7 +12,7 @@ use rog_anime::{
ActionData, AnimeDataBuffer, AnimePacketType, AnimeType, ActionData, AnimeDataBuffer, AnimePacketType, AnimeType,
}; };
use rog_platform::{hid_raw::HidRaw, supported::AnimeSupportedFunctions, usb_raw::USBRaw}; use rog_platform::{hid_raw::HidRaw, supported::AnimeSupportedFunctions, usb_raw::USBRaw};
use smol::{stream::StreamExt, Executor}; use smol::Executor;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::{ use std::{
convert::TryFrom, convert::TryFrom,
@@ -232,14 +230,6 @@ impl CtrlAnimeTask {
#[async_trait] #[async_trait]
impl crate::CtrlTask for CtrlAnimeTask { impl crate::CtrlTask for CtrlAnimeTask {
async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
let connection = Connection::system()
.await
.expect("CtrlAnimeTask could not create dbus connection");
let manager = ManagerProxy::new(&connection)
.await
.expect("CtrlAnimeTask could not create ManagerProxy");
let run_action = let run_action =
|start: bool, lock: MutexGuard<CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| { |start: bool, lock: MutexGuard<CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
if start { if start {
@@ -251,50 +241,40 @@ impl crate::CtrlTask for CtrlAnimeTask {
} }
}; };
let inner = self.inner.clone(); let inner1 = self.inner.clone();
executor let inner2 = self.inner.clone();
.spawn(async move { let inner3 = self.inner.clone();
if let Ok(notif) = manager.receive_prepare_for_sleep().await { let inner4 = self.inner.clone();
notif self.create_sys_event_tasks(
.for_each(|event| { executor,
if let Ok(args) = event.args() { // Loop is required to try an attempt to get the mutex *without* blocking
// Loop is required to try an attempt to get the mutex *without* blocking // other threads - it is possible to end up with deadlocks otherwise.
// other threads - it is possible to end up with deadlocks otherwise. move || loop {
loop { if let Ok(lock) = inner1.clone().try_lock() {
if let Ok(lock) = inner.clone().try_lock() { run_action(true, lock, inner1.clone());
run_action(args.start, lock, inner.clone()); break;
break;
}
}
}
})
.await;
} }
}) },
.detach(); move || loop {
if let Ok(lock) = inner2.clone().try_lock() {
let manager = ManagerProxy::new(&connection) run_action(false, lock, inner2.clone());
.await break;
.expect("CtrlAnimeTask could not create ManagerProxy");
let inner = self.inner.clone();
executor
.spawn(async move {
if let Ok(notif) = manager.receive_prepare_for_shutdown().await {
notif
.for_each(|event| {
if let Ok(args) = event.args() {
loop {
if let Ok(lock) = inner.clone().try_lock() {
run_action(args.start, lock, inner.clone());
}
}
}
})
.await;
} }
}) },
.detach(); move || loop {
if let Ok(lock) = inner3.clone().try_lock() {
run_action(true, lock, inner3.clone());
break;
}
},
move || loop {
if let Ok(lock) = inner4.clone().try_lock() {
run_action(false, lock, inner4.clone());
break;
}
},
)
.await;
Ok(()) Ok(())
} }

View File

@@ -5,19 +5,17 @@ use crate::{
}; };
use async_trait::async_trait; use async_trait::async_trait;
use log::{error, info, warn}; use log::{error, info, warn};
use logind_zbus::manager::ManagerProxy;
use rog_aura::{ use rog_aura::{
usb::{AuraDevice, LED_APPLY, LED_SET}, usb::{AuraDevice, LED_APPLY, LED_SET},
AuraEffect, LedBrightness, LED_MSG_LEN, AuraEffect, LedBrightness, LED_MSG_LEN,
}; };
use rog_aura::{AuraZone, Direction, Speed, GRADIENT}; use rog_aura::{AuraZone, Direction, Speed, GRADIENT};
use rog_platform::{hid_raw::HidRaw, keyboard_led::KeyboardLed, supported::LedSupportedFunctions}; use rog_platform::{hid_raw::HidRaw, keyboard_led::KeyboardLed, supported::LedSupportedFunctions};
use smol::{stream::StreamExt, Executor}; use smol::Executor;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use std::sync::MutexGuard; use std::sync::MutexGuard;
use zbus::Connection;
use crate::GetSupported; use crate::GetSupported;
@@ -95,14 +93,6 @@ impl CtrlKbdLedTask {
#[async_trait] #[async_trait]
impl CtrlTask for CtrlKbdLedTask { impl CtrlTask for CtrlKbdLedTask {
async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
let connection = Connection::system()
.await
.expect("CtrlKbdLedTask could not create dbus connection");
let manager = ManagerProxy::new(&connection)
.await
.expect("CtrlKbdLedTask could not create ManagerProxy");
let load_save = |start: bool, mut lock: MutexGuard<CtrlKbdLed>| { let load_save = |start: bool, mut lock: MutexGuard<CtrlKbdLed>| {
// If waking up // If waking up
if !start { if !start {
@@ -121,41 +111,41 @@ impl CtrlTask for CtrlKbdLedTask {
} }
}; };
let inner = self.inner.clone(); let inner1 = self.inner.clone();
executor let inner2 = self.inner.clone();
.spawn(async move { let inner3 = self.inner.clone();
if let Ok(notif) = manager.receive_prepare_for_sleep().await { let inner4 = self.inner.clone();
notif self.create_sys_event_tasks(
.for_each(|event| { executor,
if let Ok(args) = event.args() { // Loop so that we do aquire the lock but also don't block other
loop { // threads (prevents potential deadlocks)
// Loop so that we do aquire the lock but also don't block other move || loop {
// threads (prevents potential deadlocks) if let Ok(lock) = inner1.clone().try_lock() {
if let Ok(lock) = inner.clone().try_lock() { load_save(true, lock);
load_save(args.start, lock); break;
break;
}
}
}
})
.await;
} }
if let Ok(notif) = manager.receive_prepare_for_shutdown().await { },
notif move || loop {
.for_each(|event| { if let Ok(lock) = inner2.clone().try_lock() {
if let Ok(args) = event.args() { load_save(false, lock);
loop { break;
if let Ok(lock) = inner.clone().try_lock() {
load_save(args.start, lock);
break;
}
}
}
})
.await;
} }
}) },
.detach(); move || loop {
if let Ok(lock) = inner3.clone().try_lock() {
load_save(false, lock);
break;
}
},
move || loop {
if let Ok(lock) = inner4.clone().try_lock() {
load_save(false, lock);
break;
}
},
)
.await;
Ok(()) Ok(())
} }
} }

View File

@@ -2,10 +2,8 @@ use crate::CtrlTask;
use crate::{config::Config, error::RogError, GetSupported}; use crate::{config::Config, error::RogError, GetSupported};
use async_trait::async_trait; use async_trait::async_trait;
use log::{info, warn}; use log::{info, warn};
use logind_zbus::manager::ManagerProxy;
use rog_platform::platform::{AsusPlatform, GpuMode}; use rog_platform::platform::{AsusPlatform, GpuMode};
use rog_platform::supported::RogBiosSupportedFunctions; use rog_platform::supported::RogBiosSupportedFunctions;
use smol::stream::StreamExt;
use smol::Executor; use smol::Executor;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::{Read, Write}; use std::io::{Read, Write};
@@ -260,71 +258,39 @@ impl crate::Reloadable for CtrlRogBios {
#[async_trait] #[async_trait]
impl CtrlTask for CtrlRogBios { impl CtrlTask for CtrlRogBios {
async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
let connection = Connection::system() let platform1 = self.clone();
.await let platform2 = self.clone();
.expect("CtrlRogBios could not create dbus connection"); self.create_sys_event_tasks(
executor,
let manager = ManagerProxy::new(&connection) move || {},
.await move || {
.expect("CtrlRogBios could not create ManagerProxy"); info!("CtrlRogBios reloading panel_od");
if let Ok(lock) = platform1.config.try_lock() {
let platform = self.clone(); platform1
executor .set_panel_od(lock.panel_od)
.spawn(async move { .map_err(|err| {
if let Ok(notif) = manager.receive_prepare_for_sleep().await { warn!("CtrlCharge: set_limit {}", err);
notif err
.for_each(|event| {
if let Ok(args) = event.args() {
// If waking up
if !args.start {
info!("CtrlRogBios reloading panel_od");
if let Ok(lock) = platform.config.try_lock() {
platform
.set_panel_od(lock.panel_od)
.map_err(|err| {
warn!("CtrlCharge: set_limit {}", err);
err
})
.ok();
}
}
}
}) })
.await; .ok();
} }
}) },
.detach(); move || {},
move || {
let manager = ManagerProxy::new(&connection) info!("CtrlRogBios reloading panel_od");
.await if let Ok(lock) = platform2.config.try_lock() {
.expect("CtrlCharge could not create ManagerProxy"); platform2
.set_panel_od(lock.panel_od)
let platform = self.clone(); .map_err(|err| {
executor warn!("CtrlCharge: set_limit {}", err);
.spawn(async move { err
if let Ok(notif) = manager.receive_prepare_for_shutdown().await {
notif
.for_each(|event| {
if let Ok(args) = event.args() {
// If waking up - intention is to catch hibernation event
if !args.start {
info!("CtrlRogBios reloading panel_od");
if let Ok(lock) = platform.config.try_lock() {
platform
.set_panel_od(lock.panel_od)
.map_err(|err| {
warn!("CtrlCharge: set_limit {}", err);
err
})
.ok();
}
}
}
}) })
.await; .ok();
} }
}) },
.detach(); )
.await;
Ok(()) Ok(())
} }
} }

View File

@@ -2,10 +2,8 @@ use crate::CtrlTask;
use crate::{config::Config, error::RogError, GetSupported}; use crate::{config::Config, error::RogError, GetSupported};
use async_trait::async_trait; use async_trait::async_trait;
use log::{info, warn}; use log::{info, warn};
use logind_zbus::manager::ManagerProxy;
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use rog_platform::supported::ChargeSupportedFunctions; use rog_platform::supported::ChargeSupportedFunctions;
use smol::stream::StreamExt;
use smol::Executor; use smol::Executor;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
@@ -111,71 +109,39 @@ impl CtrlPower {
#[async_trait] #[async_trait]
impl CtrlTask for CtrlPower { impl CtrlTask for CtrlPower {
async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> { async fn create_tasks(&self, executor: &mut Executor) -> Result<(), RogError> {
let connection = Connection::system() let power1 = self.clone();
.await let power2 = self.clone();
.expect("CtrlCharge could not create dbus connection"); self.create_sys_event_tasks(
executor,
let manager = ManagerProxy::new(&connection) move || {},
.await move || {
.expect("CtrlCharge could not create ManagerProxy"); info!("CtrlCharge reloading charge limit");
if let Ok(lock) = power1.config.try_lock() {
let power = self.clone(); power1
executor .set(lock.bat_charge_limit)
.spawn(async move { .map_err(|err| {
if let Ok(notif) = manager.receive_prepare_for_sleep().await { warn!("CtrlCharge: set_limit {}", err);
notif err
.for_each(|event| {
if let Ok(args) = event.args() {
// If waking up
if !args.start {
info!("CtrlCharge reloading charge limit");
if let Ok(lock) = power.config.try_lock() {
power
.set(lock.bat_charge_limit)
.map_err(|err| {
warn!("CtrlCharge: set_limit {}", err);
err
})
.ok();
}
}
}
}) })
.await; .ok();
} }
}) },
.detach(); move || {},
move || {
let manager = ManagerProxy::new(&connection) info!("CtrlCharge reloading charge limit");
.await if let Ok(lock) = power2.config.try_lock() {
.expect("CtrlCharge could not create ManagerProxy"); power2
.set(lock.bat_charge_limit)
let power = self.clone(); .map_err(|err| {
executor warn!("CtrlCharge: set_limit {}", err);
.spawn(async move { err
if let Ok(notif) = manager.receive_prepare_for_shutdown().await {
notif
.for_each(|event| {
if let Ok(args) = event.args() {
// If waking up - intention is to catch hibernation event
if !args.start {
info!("CtrlCharge reloading charge limit");
if let Ok(lock) = power.config.try_lock() {
power
.set(lock.bat_charge_limit)
.map_err(|err| {
warn!("CtrlCharge: set_limit {}", err);
err
})
.ok();
}
}
}
}) })
.await; .ok();
} }
}) },
.detach(); )
.await;
Ok(()) Ok(())
} }
} }

View File

@@ -35,6 +35,7 @@ use crate::error::RogError;
use async_trait::async_trait; use async_trait::async_trait;
use config::Config; use config::Config;
use log::warn; use log::warn;
use logind_zbus::manager::ManagerProxy;
use smol::{stream::StreamExt, Executor, Timer}; use smol::{stream::StreamExt, Executor, Timer};
use zbus::Connection; use zbus::Connection;
use zvariant::ObjectPath; use zvariant::ObjectPath;
@@ -87,6 +88,64 @@ pub trait CtrlTask {
}) })
.detach(); .detach();
} }
/// Free helper method to create tasks to run on: sleep, wake, shutdown, boot
async fn create_sys_event_tasks(
&self,
executor: &mut Executor,
mut on_sleep: impl FnMut() + Send + 'static,
mut on_wake: impl FnMut() + Send + 'static,
mut on_shutdown: impl FnMut() + Send + 'static,
mut on_boot: impl FnMut() + Send + 'static,
) {
let connection = Connection::system()
.await
.expect("Controller could not create dbus connection");
let manager = ManagerProxy::new(&connection)
.await
.expect("Controller could not create ManagerProxy");
executor
.spawn(async move {
if let Ok(notif) = manager.receive_prepare_for_sleep().await {
notif
.for_each(|event| {
if let Ok(args) = event.args() {
if args.start {
on_sleep();
} else if !args.start() {
on_wake();
}
}
})
.await;
}
})
.detach();
let manager = ManagerProxy::new(&connection)
.await
.expect("Controller could not create ManagerProxy");
executor
.spawn(async move {
if let Ok(notif) = manager.receive_prepare_for_shutdown().await {
notif
.for_each(|event| {
if let Ok(args) = event.args() {
if args.start {
on_shutdown();
} else if !args.start() {
on_boot();
}
}
})
.await;
}
})
.detach();
}
} }
pub trait CtrlTaskComplex { pub trait CtrlTaskComplex {

View File

@@ -271,8 +271,7 @@ mod tests {
"CPU: 30c:1%,49c:1%,59c:3%,69c:3%,79c:30%,89c:49%,99c:56%,109c:58%" "CPU: 30c:1%,49c:1%,59c:3%,69c:3%,79c:30%,89c:49%,99c:56%,109c:58%"
); );
let curve = let curve = CurveData::from_str("30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%");
CurveData::from_str("30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%");
assert!(curve.is_err()); assert!(curve.is_err());
} }