using System.Collections.Generic;
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 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.
///
///
///
/// 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://learn.microsoft.com/en-us/windows/win32/api/systemtopologyapi/nf-systemtopologyapi-getnumanodeprocessormask2
// BOOL GetNumaNodeProcessorMask2( USHORT NodeNumber, PGROUP_AFFINITY ProcessorMasks, USHORT ProcessorMaskCount, PUSHORT RequiredMaskCount );
[PInvokeData("systemtopologyapi.h", MSDNShortId = "NF:systemtopologyapi.GetNumaNodeProcessorMask2")]
public static GROUP_AFFINITY[] GetNumaNodeProcessorMask2(ushort NodeNumber)
{
if (!GetNumaNodeProcessorMask2(NodeNumber, null, 0, out var c))
Win32Error.ThrowLastErrorUnless(Win32Error.ERROR_INSUFFICIENT_BUFFER);
GROUP_AFFINITY[] result = new GROUP_AFFINITY[c];
if (c > 0)
Win32Error.ThrowLastErrorIfFalse(GetNumaNodeProcessorMask2(NodeNumber, result, c, out _));
return result;
}
/// 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 nuint Mask;
/// The processor group number.
public ushort Group;
/// This member is reserved.
private readonly ushort Reserved1;
/// This member is reserved.
private readonly ushort Reserved2;
/// This member is reserved.
private readonly ushort Reserved3;
/// Gets or sets the affinitized processors in the field as their indexed values.
/// The affinitized processors.
public IEnumerable AffinitizedProcessors
{
get
{
ulong v = Mask;
for (uint i = 0; i < UIntPtr.Size * 8; i++)
{
if ((v & 0x1UL) == 1)
yield return i;
v >>= 1;
}
}
set
{
var v = 0UL;
foreach (var i in value)
v |= 1UL << (int)i;
Mask = (nuint)v;
}
}
}
}