using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Vanara.Extensions; namespace Vanara.PInvoke { public static partial class Kernel32 { /// Retrieves the node that currently has the highest number. /// The number of the highest node. /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // BOOL WINAPI GetNumaHighestNodeNumber( _Out_ PULONG HighestNodeNumber); https://msdn.microsoft.com/en-us/library/windows/desktop/ms683203(v=vs.85).aspx [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("systemtopology.h", MSDNShortId = "ms683203")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetNumaHighestNodeNumber(out uint HighestNodeNumber); /// Retrieves the multi-group processor mask of the specified node. /// Supplies the zero-based node number for the node of interest. /// /// An array of GROUP_AFFINITY structures, which upon successful return describes the processor mask of the specified node. /// /// Each element in the array describes a set of processors that belong to the node within a single processor group. There will be /// one element in the resulting array for each processor group this node has active processors in. /// /// /// Specifies the size of the ProcessorMasks array, in elements. /// /// On successful return, specifies the number of affinity structures written to the array. /// /// If the input array was too small, the function fails with ERROR_INSUFFICIENT_BUFFER and sets the RequiredMaskCount /// parameter to the number of elements required. /// /// The number of required elements is always less than or equal to the maximum group count returned by GetMaximumProcessorGroupCount. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero and extended error information can be retrieved by calling GetLastError. /// /// If the array supplied is too small, the error value is ERROR_INSUFFICIENT_BUFFER and the RequiredMaskCount parameter is /// set to the number of elements required. /// /// /// If the NodeNumber supplied is invalid (i.e. greater than the value returned by GetNumaHighestNodeNumber), the error value is ERROR_INVALID_PARAMETER. /// /// /// /// If the node specified does not have any processors associated with it (i.e. it only contains memory or peripherals), then the /// RequiredMaskCount returned will be 0 and no structures will be written to the array. /// // https://docs.microsoft.com/en-us/windows/win32/api/systemtopologyapi/nf-systemtopologyapi-getnumanodeprocessormask2 // BOOL GetNumaNodeProcessorMask2( USHORT NodeNumber, PGROUP_AFFINITY ProcessorMasks, USHORT ProcessorMaskCount, PUSHORT RequiredMaskCount ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("systemtopologyapi.h", MSDNShortId = "NF:systemtopologyapi.GetNumaNodeProcessorMask2")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetNumaNodeProcessorMask2(ushort NodeNumber, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] GROUP_AFFINITY[] ProcessorMasks, ushort ProcessorMaskCount, out ushort RequiredMaskCount); /// Retrieves the processor mask for a node regardless of the processor group the node belongs to. /// The node number. /// /// /// A pointer to a GROUP_AFFINITY structure that receives the processor mask for the specified node. A processor mask is a bit /// vector in which each bit represents a processor and whether it is in the node. /// /// If the specified node has no processors configured, the Mask member is zero and the Group member is undefined. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. /// // BOOL GetNumaNodeProcessorMaskEx( _In_ USHORT Node, _Out_ PGROUP_AFFINITY ProcessorMask); https://msdn.microsoft.com/en-us/library/windows/desktop/dd405493(v=vs.85).aspx [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("systemtopology.h", MSDNShortId = "dd405493")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetNumaNodeProcessorMaskEx(ushort Node, out GROUP_AFFINITY ProcessorMask); /// Retrieves the NUMA node number that corresponds to the specified proximity identifier as a USHORT value. /// The proximity identifier of the node. /// Points to a variable to receive the node number for the specified proximity identifier. /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. /// // BOOL GetNumaProximityNodeEx( _In_ ULONG ProximityId, _Out_ PUSHORT NodeNumber); https://msdn.microsoft.com/en-us/library/windows/desktop/dd405495(v=vs.85).aspx [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("systemtopology.h", MSDNShortId = "dd405495")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetNumaProximityNodeEx(uint ProximityId, out ushort NodeNumber); /// Represents a processor group-specific affinity, such as the affinity of a thread. // typedef struct _GROUP_AFFINITY { KAFFINITY Mask; WORD Group; WORD Reserved[3];} GROUP_AFFINITY, *PGROUP_AFFINITY; https://msdn.microsoft.com/en-us/library/windows/desktop/dd405500(v=vs.85).aspx [PInvokeData("WinNT.h", MSDNShortId = "dd405500")] [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct GROUP_AFFINITY { /// A bitmap that specifies the affinity for zero or more processors within the specified group. public UIntPtr Mask; /// The processor group number. public ushort Group; /// This member is reserved. private ushort Reserved1; /// This member is reserved. private ushort Reserved2; /// This member is reserved. private ushort Reserved3; /// Gets or sets the affinitized processors in the field as their indexed values. /// The affinitized processors. public IEnumerable AffinitizedProcessors { get { var v = Mask.ToUInt64(); for (uint i = 0; i < UIntPtr.Size * 8; i++) { if ((v & 0x1UL) == 1) yield return i; v = v >> 1; } } set { var v = 0UL; foreach (var i in value) v |= 1UL << (int)i; Mask = (UIntPtr)v; } } } } }