From 95277c4d227cbdb0b6980e98fc740cba3f9d4458 Mon Sep 17 00:00:00 2001 From: Sebastian Solnica Date: Sat, 14 Dec 2024 07:02:41 +0100 Subject: [PATCH] Possible fix for NUMA nodes issue on Windows Home (#76) --- procgov/Program.cs | 10 +-- procgov/SystemInfoModule.cs | 118 ++++++++++++++++++++---------------- 2 files changed, 70 insertions(+), 58 deletions(-) diff --git a/procgov/Program.cs b/procgov/Program.cs index 8becfe5..ef1db34 100644 --- a/procgov/Program.cs +++ b/procgov/Program.cs @@ -180,6 +180,11 @@ internal static IExecutionMode ParseArgs(SystemInfo systemInfo, string[] rawArgs "terminate-job-on-exit", "background", "service", "q", "quiet", "nowait", "v", "verbose", "nomonitor", "monitor", "uninstall-all" , "h", "?", "help"], rawArgs); + if (parsedArgs.Remove("v") || parsedArgs.Remove("verbose")) + { + Logger.Switch.Level = SourceLevels.Verbose; + } + if (parsedArgs.Count == 0) { return new ShowSystemInfoAndExit(); @@ -247,11 +252,6 @@ internal static IExecutionMode ParseArgs(SystemInfo systemInfo, string[] rawArgs _ => ExitBehavior.WaitForJobCompletion }; - if (parsedArgs.Remove("v") || parsedArgs.Remove("verbose")) - { - Logger.Switch.Level = SourceLevels.Verbose; - } - var environment = parsedArgs.Remove("env", out v) ? GetCustomEnvironmentVariables(v[^1]) : []; var privileges = parsedArgs.Remove("enable-privilege", out v) ? v : []; diff --git a/procgov/SystemInfoModule.cs b/procgov/SystemInfoModule.cs index 05905ed..d1de3c8 100644 --- a/procgov/SystemInfoModule.cs +++ b/procgov/SystemInfoModule.cs @@ -23,7 +23,19 @@ static class SystemInfoModule { public static SystemInfo GetSystemInfo() { - return new(GetNumaNodes(), GetProcessorGroups(), GetProcessorCores()); + var processorGroups = GetProcessorGroups(); + NumaNode[] numaNodes = []; + try + { + numaNodes = GetNumaNodes(); + } + catch (Win32Exception ex) + { + Program.Logger.TraceInformation($"NUMA information not available (Is it Windows Home?). Error: {ex}"); + numaNodes = [new(0, processorGroups)]; + } + + return new(numaNodes, processorGroups, GetProcessorCores()); static NumaNode[] GetNumaNodes() { @@ -69,79 +81,79 @@ static NumaNode[] GetNumaNodes() } } - static ProcessorGroup[] GetProcessorGroups() - { - unsafe + static ProcessorGroup[] GetProcessorGroups() { - uint length = 0; - PInvoke.GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup, null, &length); - if (Marshal.GetLastWin32Error() is var lastError && lastError != (int)WIN32_ERROR.ERROR_INSUFFICIENT_BUFFER) + unsafe { - throw new Win32Exception(lastError); - } + uint length = 0; + PInvoke.GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup, null, &length); + if (Marshal.GetLastWin32Error() is var lastError && lastError != (int)WIN32_ERROR.ERROR_INSUFFICIENT_BUFFER) + { + throw new Win32Exception(lastError); + } - byte* infoBytes = stackalloc byte[(int)length]; - if (!PInvoke.GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup, - (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)infoBytes, &length)) - { - throw new Win32Exception(Marshal.GetLastWin32Error()); - } - var info = ((SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)infoBytes); + byte* infoBytes = stackalloc byte[(int)length]; + if (!PInvoke.GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationGroup, + (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)infoBytes, &length)) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + var info = ((SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)infoBytes); - ref var relationGroup = ref info->Anonymous.Group; + ref var relationGroup = ref info->Anonymous.Group; - var processorGroups = new ProcessorGroup[relationGroup.ActiveGroupCount]; + var processorGroups = new ProcessorGroup[relationGroup.ActiveGroupCount]; - var groupInfos = relationGroup.GroupInfo.AsSpan(relationGroup.ActiveGroupCount); + var groupInfos = relationGroup.GroupInfo.AsSpan(relationGroup.ActiveGroupCount); - for (ushort groupNumber = 0; groupNumber < relationGroup.ActiveGroupCount; groupNumber++) - { - ref var groupInfo = ref groupInfos[groupNumber]; - processorGroups[groupNumber] = new ProcessorGroup(groupNumber, groupInfo.ActiveProcessorMask); - } + for (ushort groupNumber = 0; groupNumber < relationGroup.ActiveGroupCount; groupNumber++) + { + ref var groupInfo = ref groupInfos[groupNumber]; + processorGroups[groupNumber] = new ProcessorGroup(groupNumber, groupInfo.ActiveProcessorMask); + } - return processorGroups; + return processorGroups; + } } - } - static ProcessorCore[] GetProcessorCores() - { - unsafe + static ProcessorCore[] GetProcessorCores() { - uint length = 0; - PInvoke.GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore, null, &length); - if (Marshal.GetLastWin32Error() is var lastError && lastError != (int)WIN32_ERROR.ERROR_INSUFFICIENT_BUFFER) + unsafe { - throw new Win32Exception(lastError); - } + uint length = 0; + PInvoke.GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore, null, &length); + if (Marshal.GetLastWin32Error() is var lastError && lastError != (int)WIN32_ERROR.ERROR_INSUFFICIENT_BUFFER) + { + throw new Win32Exception(lastError); + } - byte* infoBytes = stackalloc byte[(int)length]; - if (!PInvoke.GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore, - (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)infoBytes, &length)) - { - throw new Win32Exception(Marshal.GetLastWin32Error()); - } + byte* infoBytes = stackalloc byte[(int)length]; + if (!PInvoke.GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore, + (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)infoBytes, &length)) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } - var cores = new List(); - var infoBytesEndAddress = infoBytes + length; + var cores = new List(); + var infoBytesEndAddress = infoBytes + length; - while (infoBytes < infoBytesEndAddress) - { - var info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)infoBytes; + while (infoBytes < infoBytesEndAddress) + { + var info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)infoBytes; - ref var processor = ref info->Anonymous.Processor; + ref var processor = ref info->Anonymous.Processor; - var group = processor.GroupMask[0]; - cores.Add(new(processor.Flags == PInvoke.LTP_PC_SMT, new(group.Group, group.Mask))); + var group = processor.GroupMask[0]; + cores.Add(new(processor.Flags == PInvoke.LTP_PC_SMT, new(group.Group, group.Mask))); - infoBytes += info->Size; - } - Debug.Assert(infoBytes == infoBytesEndAddress, $"{(nint)infoBytes} == {(nint)infoBytesEndAddress}"); + infoBytes += info->Size; + } + Debug.Assert(infoBytes == infoBytesEndAddress, $"{(nint)infoBytes} == {(nint)infoBytesEndAddress}"); - return [.. cores]; + return [.. cores]; + } } } - } public static PerformanceInformation GetSystemPerformanceInformation() {