#include "sn_target.h" #include "StgSharpNative.h" #if SN_IS_OS(SN_OS_WINDOWS) /* Pin the calling thread to a single logical processor. * core_id >= 0 : bind to that logical processor (global index, across groups). * core_id < 0 : clear affinity constraint within the current group. */ SN_API void SN_DECL sn_set_thread_affinity(int core_id) { if (core_id < 0) { /* Query which group the thread currently belongs to */ GROUP_AFFINITY current; GetThreadGroupAffinity(GetCurrentThread(), ¤t); /* Build a full mask for that group's actual core count */ DWORD count = GetActiveProcessorCount(current.Group); GROUP_AFFINITY ga; memset(&ga, 0, sizeof(ga)); ga.Group = current.Group; ga.Mask = (count >= 64) ? ~(KAFFINITY)0 : ((KAFFINITY)1 << count) - 1; SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL); return; } WORD group = (WORD)(core_id / 64); int index = core_id % 64; DWORD count = GetActiveProcessorCount(group); if ((DWORD)index >= count) return; GROUP_AFFINITY ga; memset(&ga, 0, sizeof(ga)); ga.Group = group; ga.Mask = (KAFFINITY)1 << index; SetThreadGroupAffinity(GetCurrentThread(), &ga, NULL); } SN_API int SN_DECL sn_get_numa_overall(int *out_numa_count, int *count_of_each_numa) { ULONG highest; if (!GetNumaHighestNodeNumber(&highest)) return 0; *out_numa_count = (int)highest + 1; for (UCHAR n = 0; n <= (UCHAR)highest; n++) { ULONGLONG mask = 0; GetNumaNodeProcessorMask(n, &mask); count_of_each_numa[n] = (int)__popcnt64(mask); } return 1; } SN_API int SN_DECL sn_get_numa_each(int numa_id, uint64_t *internal, uint64_t *global) { ULONGLONG mask = 0; if (!GetNumaNodeProcessorMask((UCHAR)numa_id, &mask)) return 0; int intra = 0; while (mask) { unsigned long idx; _BitScanForward64(&idx, mask); internal[intra] = intra; global[intra] = (int)idx; intra++; mask &= mask - 1; } return 1; } #endif