diff --git a/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs b/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs index 9a95cd7..9fd7a66 100644 --- a/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs @@ -107,7 +107,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu _control.Control = _fanControl; } - if (NvidiaML.IsAvailable) + if (NvidiaML.IsAvailable || NvidiaML.Initialize()) { if (hasPciBusId) _nvmlDevice = NvidiaML.NvmlDeviceGetHandleByPciBusId($" 0000:{busId:X2}:00.0") ?? NvidiaML.NvmlDeviceGetHandleByIndex(_adapterIndex); diff --git a/LibreHardwareMonitorLib/Interop/NvidiaML.cs b/LibreHardwareMonitorLib/Interop/NvidiaML.cs index 8be44f6..28d6f07 100644 --- a/LibreHardwareMonitorLib/Interop/NvidiaML.cs +++ b/LibreHardwareMonitorLib/Interop/NvidiaML.cs @@ -14,6 +14,8 @@ namespace LibreHardwareMonitor.Interop private const string LinuxDllName = "nvidia-ml"; private const string WindowsDllName = "nvml.dll"; + private static readonly object SyncRoot = new object(); + private static WindowsNvmlGetHandleDelegate _windowsNvmlDeviceGetHandleByIndex; private static WindowsNvmlGetPowerUsageDelegate _windowsNvmlDeviceGetPowerUsage; private static WindowsNvmlDeviceGetPcieThroughputDelegate _windowsNvmlDeviceGetPcieThroughputDelegate; @@ -21,56 +23,64 @@ namespace LibreHardwareMonitor.Interop private static WindowsNvmlDelegate _windowsNvmlInit; private static WindowsNvmlDelegate _windowsNvmlShutdown; - private static readonly IntPtr WindowsDll; + private static IntPtr WindowsDll; - static NvidiaML() + internal static bool IsAvailable { get; private set; } + + internal static bool Initialize() { - if (Software.OperatingSystem.IsLinux) + lock (SyncRoot) { - try + if (IsAvailable) { - IsAvailable = nvmlInit() == NvmlReturn.Success; + return true; } - catch (DllNotFoundException) - { } - catch (EntryPointNotFoundException) + + if (Software.OperatingSystem.IsLinux) { try { - IsAvailable = nvmlInitLegacy() == NvmlReturn.Success; + IsAvailable = nvmlInit() == NvmlReturn.Success; } - catch (EntryPointNotFoundException) + catch (DllNotFoundException) { } + catch (EntryPointNotFoundException) + { + try + { + IsAvailable = nvmlInitLegacy() == NvmlReturn.Success; + } + catch (EntryPointNotFoundException) + { } + } } - } - else if (IsNvmlCompatibleWindowsVersion()) - { - // Attempt to load the Nvidia Management Library from the - // windows standard search order for applications. This will - // help installations that either have the library in - // %windir%/system32 or provide their own library - WindowsDll = Kernel32.LoadLibrary(WindowsDllName); - - // If there is no dll in the path, then attempt to load it - // from program files - if (WindowsDll == IntPtr.Zero) + else if (IsNvmlCompatibleWindowsVersion()) { - string programFilesDirectory = Environment.ExpandEnvironmentVariables("%ProgramW6432%"); - string dllPath = Path.Combine(programFilesDirectory, @"NVIDIA Corporation\NVSMI", WindowsDllName); + // Attempt to load the Nvidia Management Library from the + // windows standard search order for applications. This will + // help installations that either have the library in + // %windir%/system32 or provide their own library + WindowsDll = Kernel32.LoadLibrary(WindowsDllName); - WindowsDll = Kernel32.LoadLibrary(dllPath); + // If there is no dll in the path, then attempt to load it + // from program files + if (WindowsDll == IntPtr.Zero) + { + string programFilesDirectory = Environment.ExpandEnvironmentVariables("%ProgramW6432%"); + string dllPath = Path.Combine(programFilesDirectory, @"NVIDIA Corporation\NVSMI", WindowsDllName); + + WindowsDll = Kernel32.LoadLibrary(dllPath); + } + + IsAvailable = (WindowsDll != IntPtr.Zero) + && InitialiseDelegates() + && (_windowsNvmlInit() == NvmlReturn.Success); } - if (WindowsDll == IntPtr.Zero) - return; - - - IsAvailable = InitialiseDelegates() && (_windowsNvmlInit() == NvmlReturn.Success); + return IsAvailable; } } - internal static bool IsAvailable { get; } - private static bool IsNvmlCompatibleWindowsVersion() { return Software.OperatingSystem.Is64Bit && ((Environment.OSVersion.Version.Major > 6) || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1)); @@ -137,16 +147,21 @@ namespace LibreHardwareMonitor.Interop internal static void Close() { - if (IsAvailable) + lock (SyncRoot) { - if (Software.OperatingSystem.IsLinux) + if (IsAvailable) { - nvmlShutdown(); - } - else if (WindowsDll != IntPtr.Zero) - { - _windowsNvmlShutdown(); - Kernel32.FreeLibrary(WindowsDll); + if (Software.OperatingSystem.IsLinux) + { + nvmlShutdown(); + } + else if (WindowsDll != IntPtr.Zero) + { + _windowsNvmlShutdown(); + Kernel32.FreeLibrary(WindowsDll); + } + + IsAvailable = false; } } }