From f7e3e70c2b288e7b39768ef1a5f82135e739abc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Trzci=C5=84ski?= Date: Sun, 20 Nov 2022 21:17:21 +0100 Subject: [PATCH] Use global mutex to ensure driver access are sequential --- CommonHelpers/Instance.cs | 47 ++++++++++- FanControl/FanController.cs | 24 +++++- PerformanceOverlay/Sensors.cs | 26 ++++--- PowerControl/Helpers/AMD/VangoghGPU.cs | 20 +++-- PowerControl/MenuStack.cs | 103 ++++++++++++++----------- PowerControl/Program.cs | 2 +- 6 files changed, 148 insertions(+), 74 deletions(-) diff --git a/CommonHelpers/Instance.cs b/CommonHelpers/Instance.cs index ae30ef2..152ffa1 100644 --- a/CommonHelpers/Instance.cs +++ b/CommonHelpers/Instance.cs @@ -6,6 +6,7 @@ using System.Security; using System.Security.Principal; using System.Security.AccessControl; using System.Windows.Forms; +using System.Runtime.CompilerServices; namespace CommonHelpers { @@ -21,10 +22,44 @@ namespace CommonHelpers }; private static Mutex? runOnceMutex; + private static Mutex? globalLockMutex; private const String GLOBAL_MUTEX_NAME = "Global\\SteamDeckToolsCommonHelpers"; private const int GLOBAL_DEFAULT_TIMEOUT = 5000; + public static Mutex? WaitGlobalMutex(int timeoutMs) + { + if (globalLockMutex == null) + globalLockMutex = TryCreateOrOpenExistingMutex(GLOBAL_MUTEX_NAME); + + try + { + if (globalLockMutex.WaitOne(timeoutMs)) + return globalLockMutex; + return null; + } + catch(AbandonedMutexException) + { + return globalLockMutex; + } + } + + public static T WithGlobalMutex(int timeoutMs, Func func) + { + var mutex = WaitGlobalMutex(timeoutMs); + if (mutex is null) + return default(T); + + try + { + return func(); + } + finally + { + mutex.ReleaseMutex(); + } + } + public static void Open(String title, String? runOnce = null, int runOnceTimeout = 100) { if (runOnce is not null) @@ -32,9 +67,11 @@ namespace CommonHelpers RunOnce(title, runOnce, runOnceTimeout); } - using (var globalLock = TryCreateOrOpenExistingMutex(GLOBAL_MUTEX_NAME)) + var mutex = WaitGlobalMutex(GLOBAL_DEFAULT_TIMEOUT); + + try { - if (!globalLock.WaitOne(GLOBAL_DEFAULT_TIMEOUT)) + if (mutex is null) { Fatal(title, "Failed to acquire global mutex."); } @@ -51,8 +88,10 @@ namespace CommonHelpers } HardwareComputer.Open(); - - globalLock.ReleaseMutex(); + } + finally + { + mutex.ReleaseMutex(); } } diff --git a/FanControl/FanController.cs b/FanControl/FanController.cs index 9de2281..7bdb437 100644 --- a/FanControl/FanController.cs +++ b/FanControl/FanController.cs @@ -73,11 +73,27 @@ namespace FanControl public void Update() { - foreach (var sensor in allSensors.Values) - sensor.Reset(); + var mutex = Instance.WaitGlobalMutex(200); - foreach (var hardware in Instance.HardwareComputer.Hardware) - visitHardware(hardware); + if (mutex is null) + { + // If we cannot acquire mutex slightly increase FAN to compensate just in case + Vlv0100.SetFanDesiredRPM((ushort)(Vlv0100.GetFanDesiredRPM() * 110 / 100)); + return; + } + + try + { + foreach (var sensor in allSensors.Values) + sensor.Reset(); + + foreach (var hardware in Instance.HardwareComputer.Hardware) + visitHardware(hardware); + } + finally + { + mutex.ReleaseMutex(); + } allSensors["Batt"].Update("VLV0100", Vlv0100.GetBattTemperature(), Mode); diff --git a/PerformanceOverlay/Sensors.cs b/PerformanceOverlay/Sensors.cs index 6eb0175..c99e32f 100644 --- a/PerformanceOverlay/Sensors.cs +++ b/PerformanceOverlay/Sensors.cs @@ -334,19 +334,23 @@ namespace PerformanceOverlay public void Update() { - var allSensors = new List(); - - foreach (IHardware hardware in Instance.HardwareComputer.Hardware) + Instance.WithGlobalMutex(200, () => { - try - { - hardware.Update(); - } - catch (SystemException) { } - hardware.Accept(new SensorVisitor(sensor => allSensors.Add(sensor))); - } + var allSensors = new List(); - this.AllHardwareSensors = allSensors; + foreach (IHardware hardware in Instance.HardwareComputer.Hardware) + { + try + { + hardware.Update(); + } + catch (SystemException) { } + hardware.Accept(new SensorVisitor(sensor => allSensors.Add(sensor))); + } + + this.AllHardwareSensors = allSensors; + return true; + }); } public string? GetValue(String name) diff --git a/PowerControl/Helpers/AMD/VangoghGPU.cs b/PowerControl/Helpers/AMD/VangoghGPU.cs index a98c3a4..24cb4d9 100644 --- a/PowerControl/Helpers/AMD/VangoghGPU.cs +++ b/PowerControl/Helpers/AMD/VangoghGPU.cs @@ -51,21 +51,25 @@ namespace PowerControl.Helpers.GPU return true; } - public VangoghGPU? Open() + public VangoghGPU? Open(bool validateSMU = true) { var gpu = VangoghGPU.OpenMMIO(MMIOAddress, MMIOSize); if (gpu == null) return null; - // Check supported SMU version - var smuVersion = gpu.SMUVersion; - if (smuVersion != SMUVersion) + if (validateSMU) { - Log("SMU: {0:X8} => not supported", smuVersion); - return null; + // Check supported SMU version + var smuVersion = gpu.SMUVersion; + if (smuVersion != SMUVersion) + { + Log("SMU: {0:X8} => not supported", smuVersion); + return null; + } + + Log("SMU: {0:X8} => detected", smuVersion); } - Log("SMU: {0:X8} => detected", smuVersion); return gpu; } }; @@ -85,7 +89,7 @@ namespace PowerControl.Helpers.GPU public static VangoghGPU? Open() { - return DetectedDevice?.Open(); + return DetectedDevice?.Open(false); } public static bool Detect() diff --git a/PowerControl/MenuStack.cs b/PowerControl/MenuStack.cs index df462c9..b1d1485 100644 --- a/PowerControl/MenuStack.cs +++ b/PowerControl/MenuStack.cs @@ -160,14 +160,19 @@ namespace PowerControl if (VangoghGPU.IsSupported) { - using (var sd = VangoghGPU.Open()) + return Instance.WithGlobalMutex(200, () => { - if (sd is null) - return null; + using (var sd = VangoghGPU.Open()) + { + if (sd is null) + return null; - sd.SlowTDP = mW; - sd.FastTDP = mW; - } + sd.SlowTDP = mW; + sd.FastTDP = mW; + } + + return selected; + }); } else { @@ -185,9 +190,9 @@ namespace PowerControl UseShellExecute = false, CreateNoWindow = true }); - } - return selected; + return selected; + } } }, new Menu.MenuItemWithOptions() @@ -200,20 +205,23 @@ namespace PowerControl ResetValue = () => { return "Default"; }, ApplyValue = delegate(object selected) { - using (var sd = VangoghGPU.Open()) + return Instance.WithGlobalMutex(200, () => { - if (sd is null) - return null; - - if (selected.ToString() == "Default") + using (var sd = VangoghGPU.Open()) { - sd.HardMinGfxClock = 200; + if (sd is null) + return null; + + if (selected.ToString() == "Default") + { + sd.HardMinGfxClock = 200; + return selected; + } + + sd.HardMinGfxClock = uint.Parse(selected.ToString().Replace("MHz", "")); return selected; } - - sd.HardMinGfxClock = uint.Parse(selected.ToString().Replace("MHz", "")); - return selected; - } + }); } }, new Menu.MenuItemWithOptions() @@ -226,38 +234,41 @@ namespace PowerControl ResetValue = () => { return "Default"; }, ApplyValue = delegate(object selected) { - using (var sd = VangoghGPU.Open()) + return Instance.WithGlobalMutex(200, () => { - if (sd is null) - return null; - - switch(selected.ToString()) + using (var sd = VangoghGPU.Open()) { - case "Default": - sd.MinCPUClock = 1400; - sd.MaxCPUClock = 3500; - break; - - case "Power-Save": - sd.MinCPUClock = 1400; - sd.MaxCPUClock = 1800; - break; - - case "Balanced": - sd.MinCPUClock = 2200; - sd.MaxCPUClock = 2800; - break; - - case "Max": - sd.MinCPUClock = 3000; - sd.MaxCPUClock = 3500; - break; - - default: + if (sd is null) return null; + + switch(selected.ToString()) + { + case "Default": + sd.MinCPUClock = 1400; + sd.MaxCPUClock = 3500; + break; + + case "Power-Save": + sd.MinCPUClock = 1400; + sd.MaxCPUClock = 1800; + break; + + case "Balanced": + sd.MinCPUClock = 2200; + sd.MaxCPUClock = 2800; + break; + + case "Max": + sd.MinCPUClock = 3000; + sd.MaxCPUClock = 3500; + break; + + default: + return null; + } + return selected; } - return selected; - } + }); } }, new Menu.MenuItemWithOptions() diff --git a/PowerControl/Program.cs b/PowerControl/Program.cs index ed80963..1865e82 100644 --- a/PowerControl/Program.cs +++ b/PowerControl/Program.cs @@ -20,7 +20,7 @@ namespace PowerControl { Trace.WriteLine("WinRing0 initialized=" + WinRing0.InitializeOls().ToString()); - VangoghGPU.Detect(); + Instance.WithGlobalMutex(1000, () => VangoghGPU.Detect()); } // To customize application configuration such as set high DPI settings or default font,