Fix GUI taking 100% of CPU core

Closes #480
This commit is contained in:
Luke D. Jones
2024-05-18 12:59:17 +12:00
parent 219bd559b6
commit ea988279a8
6 changed files with 121 additions and 95 deletions

View File

@@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Rename and recreate the default Anime config if cache setup fails - Rename and recreate the default Anime config if cache setup fails
### Fixed
- Nuke the issue of GUI taking 100% of a CPU core
## [v6.0.8] ## [v6.0.8]
### Added ### Added

View File

@@ -12,12 +12,11 @@ edition.workspace = true
default = [] default = []
mocking = [] mocking = []
x11 = ["slint/backend-winit-x11"] x11 = ["slint/backend-winit-x11"]
# Requires RUSTFLAGS="--cfg tokio_unstable"
[build] tokio-debug = ["console-subscriber"]
rustflags = ["--cfg", "tokio_unstable"]
[dependencies] [dependencies]
console-subscriber = "0.2.0" console-subscriber = { version = "0.2.0", optional = true }
nix = { version = "^0.28.0", features = ["fs"] } nix = { version = "^0.28.0", features = ["fs"] }
tempfile = "3.3.0" tempfile = "3.3.0"

View File

@@ -25,6 +25,7 @@ use tokio::runtime::Runtime;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
#[cfg(feature = "tokio-debug")]
console_subscriber::init(); console_subscriber::init();
let self_version = env!("CARGO_PKG_VERSION"); let self_version = env!("CARGO_PKG_VERSION");

View File

@@ -45,6 +45,44 @@ impl Default for EnabledNotifications {
} }
} }
fn start_dpu_status_mon(config: Arc<Mutex<Config>>) {
use supergfxctl::pci_device::Device;
let dev = Device::find().unwrap_or_default();
let mut found_dgpu = false; // just for logging
for dev in dev {
if dev.is_dgpu() {
let enabled_notifications_copy = config.clone();
// Plain old thread is perfectly fine since most of this is potentially blocking
std::thread::spawn(move || {
let mut last_status = GfxPower::Unknown;
loop {
std::thread::sleep(Duration::from_millis(1000));
if let Ok(status) = dev.get_runtime_status() {
if status != GfxPower::Unknown && status != last_status {
if let Ok(config) = enabled_notifications_copy.lock() {
if !config.notifications.receive_notify_gfx_status
|| !config.notifications.enabled
{
continue;
}
}
// Required check because status cycles through
// active/unknown/suspended
do_gpu_status_notif("dGPU status changed:", &status).ok();
}
last_status = status;
}
}
});
found_dgpu = true;
break;
}
}
if !found_dgpu {
warn!("Did not find a dGPU on this system, dGPU status won't be avilable");
}
}
pub fn start_notifications( pub fn start_notifications(
config: Arc<Mutex<Config>>, config: Arc<Mutex<Config>>,
rt: &Runtime, rt: &Runtime,
@@ -103,20 +141,14 @@ pub fn start_notifications(
// GPU MUX Mode notif // GPU MUX Mode notif
let enabled_notifications_copy = config.clone(); let enabled_notifications_copy = config.clone();
tokio::spawn(async move { tokio::spawn(async move {
let conn = zbus::Connection::system() let conn = zbus::Connection::system().await.map_err(|e| {
.await error!("zbus signal: receive_notify_gpu_mux_mode: {e}");
.map_err(|e| { e
error!("zbus signal: receive_notify_gpu_mux_mode: {e}"); })?;
e let proxy = PlatformProxy::new(&conn).await.map_err(|e| {
}) error!("zbus signal: receive_notify_gpu_mux_mode: {e}");
.unwrap(); e
let proxy = PlatformProxy::new(&conn) })?;
.await
.map_err(|e| {
error!("zbus signal: receive_notify_gpu_mux_mode: {e}");
e
})
.unwrap();
let mut actual_mux_mode = GpuMode::Error; let mut actual_mux_mode = GpuMode::Error;
if let Ok(mode) = proxy.gpu_mux_mode().await { if let Ok(mode) = proxy.gpu_mux_mode().await {
@@ -138,87 +170,75 @@ pub fn start_notifications(
do_mux_notification("Reboot required. BIOS GPU MUX mode set to", &mode).ok(); do_mux_notification("Reboot required. BIOS GPU MUX mode set to", &mode).ok();
} }
} }
Ok::<(), zbus::Error>(())
}); });
use supergfxctl::pci_device::Device; let enabled_notifications_copy = config.clone();
let dev = Device::find().unwrap_or_default();
let mut found_dgpu = false; // just for logging
for dev in dev {
if dev.is_dgpu() {
let enabled_notifications_copy = config.clone();
// Plain old thread is perfectly fine since most of this is potentially blocking
rt.spawn_blocking(move || {
let mut last_status = GfxPower::Unknown;
loop {
if let Ok(status) = dev.get_runtime_status() {
if status != GfxPower::Unknown && status != last_status {
if let Ok(config) = enabled_notifications_copy.lock() {
if !config.notifications.receive_notify_gfx_status
|| !config.notifications.enabled
{
continue;
}
}
// Required check because status cycles through
// active/unknown/suspended
do_gpu_status_notif("dGPU status changed:", &status).ok();
}
last_status = status;
}
std::thread::sleep(Duration::from_millis(500));
}
});
found_dgpu = true;
break;
}
}
if !found_dgpu {
warn!("Did not find a dGPU on this system, dGPU status won't be avilable");
}
// GPU Mode change/action notif // GPU Mode change/action notif
tokio::spawn(async move { tokio::spawn(async move {
let conn = zbus::Connection::system() if let Err(e) = {
.await let conn = zbus::Connection::system().await?;
.map_err(|e| { let proxy = SuperProxy::builder(&conn).build().await?;
error!("zbus signal: receive_notify_action: {e}"); let _ = proxy.mode().await?;
e
})
.unwrap();
let proxy = SuperProxy::builder(&conn)
.build()
.await
.map_err(|e| {
error!("zbus signal: receive_notify_action: {e}");
e
})
.unwrap();
if proxy.mode().await.is_err() { let proxy_copy = proxy.clone();
info!("supergfxd not running or not responding"); if let Ok(mut p) = proxy.receive_notify_action().await {
return; tokio::spawn(async move {
} info!("Started zbus signal thread: receive_notify_action");
while let Some(e) = p.next().await {
if let Ok(mut p) = proxy.receive_notify_action().await { if let Ok(out) = e.args() {
info!("Started zbus signal thread: receive_notify_action"); let action = out.action();
while let Some(e) = p.next().await { let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default());
if let Ok(out) = e.args() { match action {
let action = out.action(); supergfxctl::actions::UserActionRequired::Reboot => {
let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default()); do_mux_notification(
match action { "Graphics mode change requires reboot",
supergfxctl::actions::UserActionRequired::Reboot => { &mode,
do_mux_notification("Graphics mode change requires reboot", &mode) )
}
_ => do_gfx_action_notif(<&str>::from(action), *action, mode),
}
.map_err(|e| {
error!("zbus signal: do_gfx_action_notif: {e}");
e
})
.ok();
} }
_ => do_gfx_action_notif(<&str>::from(action), *action, mode),
} }
.map_err(|e| { });
error!("zbus signal: do_gfx_action_notif: {e}"); };
e
}) if let Ok(mut p) = proxy_copy.receive_notify_gfx_status().await {
.ok(); tokio::spawn(async move {
} info!("Started zbus signal thread: receive_notify_gfx_status");
} let mut last_status = GfxPower::Unknown;
}; while let Some(e) = p.next().await {
if let Ok(out) = e.args() {
let status = out.status;
if status != GfxPower::Unknown && status != last_status {
if let Ok(config) = enabled_notifications_copy.lock() {
if !config.notifications.receive_notify_gfx_status
|| !config.notifications.enabled
{
continue;
}
}
// Required check because status cycles through
// active/unknown/suspended
do_gpu_status_notif("dGPU status changed:", &status).ok();
}
last_status = status;
}
}
});
};
Ok::<(), zbus::Error>(())
} {
error!("zbus signal: receive_notify_gfx_status: {e}");
info!("Attempting to start plain dgpu status monitor");
start_dpu_status_mon(config.clone());
}
Ok::<(), zbus::Error>(())
}); });
Ok(vec![blocking]) Ok(vec![blocking])

View File

@@ -1,6 +1,6 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use log::{error, info}; use log::{debug, error, info};
use rog_aura::keyboard::LaptopAuraPower; use rog_aura::keyboard::LaptopAuraPower;
use rog_aura::{AuraDeviceType, PowerZones}; use rog_aura::{AuraDeviceType, PowerZones};
use rog_dbus::zbus_aura::AuraProxy; use rog_dbus::zbus_aura::AuraProxy;
@@ -76,7 +76,7 @@ pub fn setup_aura_page(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
tokio::spawn(async move { tokio::spawn(async move {
let Ok(aura) = find_aura_iface().await else { let Ok(aura) = find_aura_iface().await else {
info!("This device appears to have no aura interfaces"); info!("This device appears to have no aura interfaces");
return; return Ok::<(), zbus::Error>(());
}; };
set_ui_props_async!(handle, aura, AuraPageData, brightness); set_ui_props_async!(handle, aura, AuraPageData, brightness);
@@ -226,5 +226,7 @@ pub fn setup_aura_page(ui: &MainWindow, _states: Arc<Mutex<Config>>) {
} }
} }
}); });
debug!("Aura setup tasks complete");
Ok(())
}); });
} }

View File

@@ -2,7 +2,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2024-05-17 10:31+0000\n" "POT-Creation-Date: 2024-05-17 23:21+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"