void bindThread(uint32_t threadId, uint32_t procGroupId = 0) { #if defined(_WIN32) { GROUP_AFFINITY affinity = {}; affinity.Group = procGroupId; #if !defined(_WIN64) if (threadId >= 32) { // In a 32-bit process on Windows it is impossible to bind // to logical processors 32-63 within a processor group. // In this case set the mask to 0 and let the system assign // the processor. Hopefully it will make smart choices. affinity.Mask = 0; } else #endif { affinity.Mask = KAFFINITY(1) << threadId; } SetThreadGroupAffinity(GetCurrentThread(), &affinity, nullptr); } #else cpu_set_t cpuset; pthread_t thread = pthread_self(); CPU_ZERO(&cpuset); CPU_SET(threadId, &cpuset); pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset); #endif }
void bindThread(SWR_CONTEXT* pContext, uint32_t threadId, uint32_t procGroupId = 0, bool bindProcGroup=false) { // Only bind threads when MAX_WORKER_THREADS isn't set. if (pContext->threadInfo.SINGLE_THREADED || (pContext->threadInfo.MAX_WORKER_THREADS && bindProcGroup == false)) { return; } #if defined(_WIN32) GROUP_AFFINITY affinity = {}; affinity.Group = procGroupId; #if !defined(_WIN64) if (threadId >= 32) { // Hopefully we don't get here. Logic in CreateThreadPool should prevent this. SWR_INVALID("Shouldn't get here"); // In a 32-bit process on Windows it is impossible to bind // to logical processors 32-63 within a processor group. // In this case set the mask to 0 and let the system assign // the processor. Hopefully it will make smart choices. affinity.Mask = 0; } else #endif { // If MAX_WORKER_THREADS is set, only bind to the proc group, // Not the individual HW thread. if (!bindProcGroup && !pContext->threadInfo.MAX_WORKER_THREADS) { affinity.Mask = KAFFINITY(1) << threadId; } else { affinity.Mask = KAFFINITY(0); } } if (!SetThreadGroupAffinity(GetCurrentThread(), &affinity, nullptr)) { SWR_INVALID("Failed to set Thread Affinity"); } #elif defined(__linux__) || defined(__gnu_linux__) cpu_set_t cpuset; pthread_t thread = pthread_self(); CPU_ZERO(&cpuset); CPU_SET(threadId, &cpuset); int err = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset); if (err != 0) { fprintf(stderr, "pthread_setaffinity_np failure for tid %u: %s\n", threadId, strerror(err)); } #endif }
// Sets the calling thread's affinity to only run on the processor specified // in the GCThreadAffinity structure. // Parameters: // affinity - The requested affinity for the calling thread. At most one processor // can be provided. // Return: // true if setting the affinity was successful, false otherwise. bool GCToOSInterface::SetThreadAffinity(GCThreadAffinity* affinity) { LIMITED_METHOD_CONTRACT; assert(affinity != nullptr); if (affinity->Group != GCThreadAffinity::None) { assert(affinity->Processor != GCThreadAffinity::None); GROUP_AFFINITY ga; ga.Group = (WORD)affinity->Group; ga.Reserved[0] = 0; // reserve must be filled with zero ga.Reserved[1] = 0; // otherwise call may fail ga.Reserved[2] = 0; ga.Mask = (size_t)1 << affinity->Processor; return !!SetThreadGroupAffinity(GetCurrentThread(), &ga, nullptr); } else if (affinity->Processor != GCThreadAffinity::None) { return !!SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR)1 << affinity->Processor); } // Given affinity must specify at least one processor to use. return false; }
void bindThread(SWR_CONTEXT* pContext, uint32_t threadId, uint32_t procGroupId = 0, bool bindProcGroup=false) { // Only bind threads when MAX_WORKER_THREADS isn't set. if (pContext->threadInfo.MAX_WORKER_THREADS && bindProcGroup == false) { return; } #if defined(_WIN32) GROUP_AFFINITY affinity = {}; affinity.Group = procGroupId; #if !defined(_WIN64) if (threadId >= 32) { // Hopefully we don't get here. Logic in CreateThreadPool should prevent this. SWR_REL_ASSERT(false, "Shouldn't get here"); // In a 32-bit process on Windows it is impossible to bind // to logical processors 32-63 within a processor group. // In this case set the mask to 0 and let the system assign // the processor. Hopefully it will make smart choices. affinity.Mask = 0; } else #endif { // If MAX_WORKER_THREADS is set, only bind to the proc group, // Not the individual HW thread. if (!pContext->threadInfo.MAX_WORKER_THREADS) { affinity.Mask = KAFFINITY(1) << threadId; } } SetThreadGroupAffinity(GetCurrentThread(), &affinity, nullptr); #else cpu_set_t cpuset; pthread_t thread = pthread_self(); CPU_ZERO(&cpuset); CPU_SET(threadId, &cpuset); pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset); #endif }
ThreadGroupTempAffinity(uint32 core_id) { GROUP_AFFINITY NewGroupAffinity; memset(&NewGroupAffinity, 0, sizeof(GROUP_AFFINITY)); memset(&PreviousGroupAffinity, 0, sizeof(GROUP_AFFINITY)); uint32 currentGroupSize = 0; while (core_id >= (currentGroupSize = GetMaximumProcessorCount(NewGroupAffinity.Group))) { core_id -= currentGroupSize; ++NewGroupAffinity.Group; } NewGroupAffinity.Mask = 1ULL << core_id; SetThreadGroupAffinity(GetCurrentThread(),&NewGroupAffinity,&PreviousGroupAffinity); }
void bindThread(uint32_t threadId, uint32_t procGroupId = 0, bool bindProcGroup=false) { // Only bind threads when MAX_WORKER_THREADS isn't set. if (KNOB_MAX_WORKER_THREADS && bindProcGroup == false) { return; } #if defined(_WIN32) { GROUP_AFFINITY affinity = {}; affinity.Group = procGroupId; #if !defined(_WIN64) if (threadId >= 32) { // In a 32-bit process on Windows it is impossible to bind // to logical processors 32-63 within a processor group. // In this case set the mask to 0 and let the system assign // the processor. Hopefully it will make smart choices. affinity.Mask = 0; } else #endif { // If KNOB_MAX_WORKER_THREADS is set, only bind to the proc group, // Not the individual HW thread. if (!KNOB_MAX_WORKER_THREADS) { affinity.Mask = KAFFINITY(1) << threadId; } } SetThreadGroupAffinity(GetCurrentThread(), &affinity, nullptr); } #else cpu_set_t cpuset; pthread_t thread = pthread_self(); CPU_ZERO(&cpuset); CPU_SET(threadId, &cpuset); pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset); #endif }
tt_result_t __thread_bind_numa(IN HANDLE hThread, IN USHORT Node) { GROUP_AFFINITY ProcessorMask; // how to handle the arch in which a numa node includes more than // 64 cpus?? if (!GetNumaNodeProcessorMaskEx(Node, &ProcessorMask)) { TT_ERROR("fail to get numa node processor mask"); return TT_FAIL; } if (!SetThreadGroupAffinity(hThread, &ProcessorMask, NULL)) { TT_ERROR("fail to bind thread to numa node[%d]", Node); return TT_FAIL; } return TT_SUCCESS; }
/*! set the affinity of a given thread */ void setAffinity(HANDLE thread, ssize_t affinity) { #if (_WIN32_WINNT >= 0x0601) // FIXME: use getProcAddress to activate this feature only if supported by Windows int groups = GetActiveProcessorGroupCount(); int totalProcessors = 0, group = 0, number = 0; for (int i = 0; i<groups; i++) { int processors = GetActiveProcessorCount(i); if (totalProcessors + processors > affinity) { group = i; number = (int)affinity - totalProcessors; break; } totalProcessors += processors; } GROUP_AFFINITY groupAffinity; groupAffinity.Group = (WORD)group; groupAffinity.Mask = (KAFFINITY)(uint64(1) << number); groupAffinity.Reserved[0] = 0; groupAffinity.Reserved[1] = 0; groupAffinity.Reserved[2] = 0; if (!SetThreadGroupAffinity(thread, &groupAffinity, NULL)) THROW_RUNTIME_ERROR("cannot set thread group affinity"); PROCESSOR_NUMBER processorNumber; processorNumber.Group = group; processorNumber.Number = number; processorNumber.Reserved = 0; if (!SetThreadIdealProcessorEx(thread, &processorNumber, NULL)) THROW_RUNTIME_ERROR("cannot set ideal processor"); #else if (!SetThreadAffinityMask(thread, DWORD_PTR(uint64(1) << affinity))) THROW_RUNTIME_ERROR("cannot set thread affinity mask"); if (SetThreadIdealProcessor(thread, (DWORD)affinity) == (DWORD)-1) THROW_RUNTIME_ERROR("cannot set ideal processor"); #endif }
/*! set the affinity of a given thread */ void setAffinity(HANDLE thread, ssize_t affinity) { #if (_WIN32_WINNT >= 0x0601) int groups = GetActiveProcessorGroupCount(); int totalProcessors = 0, group = 0, number = 0; for (int i = 0; i<groups; i++) { int processors = GetActiveProcessorCount(i); if (totalProcessors + processors > affinity) { group = i; number = (int)affinity - totalProcessors; break; } totalProcessors += processors; } GROUP_AFFINITY groupAffinity; groupAffinity.Group = (WORD)group; groupAffinity.Mask = (KAFFINITY)(uint64(1) << number); groupAffinity.Reserved[0] = 0; groupAffinity.Reserved[1] = 0; groupAffinity.Reserved[2] = 0; if (!SetThreadGroupAffinity(thread, &groupAffinity, NULL)) throw std::runtime_error("cannot set thread group affinity"); PROCESSOR_NUMBER processorNumber; processorNumber.Group = group; processorNumber.Number = number; processorNumber.Reserved = 0; if (!SetThreadIdealProcessorEx(thread, &processorNumber, NULL)) throw std::runtime_error("cannot set thread ideal processor"); #else if (!SetThreadAffinityMask(thread, DWORD_PTR(uint64(1) << affinity))) throw std::runtime_error("cannot set thread affinity mask"); if (SetThreadIdealProcessor(thread, (DWORD)affinity) == (DWORD)-1) throw std::runtime_error("cannot set thread ideal processor"); #endif }
int thread_bind_native(__unused_variable struct cpuid_state_t *state, __unused_variable uint32_t id) { #ifdef TARGET_OS_WINDOWS BOOL ret; HANDLE hThread = GetCurrentThread(); #if _WIN32_WINNT >= 0x0601 GROUP_AFFINITY affinity; ZeroMemory(&affinity, sizeof(GROUP_AFFINITY)); affinity.Group = id / 64; affinity.Mask = 1 << (id % 64); ret = SetThreadGroupAffinity(hThread, &affinity, NULL); #else DWORD mask; if (id > 32) return 1; mask = (1 << id); ret = SetThreadAffinityMask(hThread, mask); #endif return (ret != FALSE) ? 0 : 1; #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_FREEBSD) int ret; #ifdef CPU_SET_S size_t setsize = CPU_ALLOC_SIZE(MAX_CPUS); CPUSET_T *set = CPU_ALLOC(MAX_CPUS); pthread_t pth; pth = pthread_self(); CPU_ZERO_S(setsize, set); CPU_SET_S(id, setsize, set); ret = pthread_setaffinity_np(pth, setsize, set); CPU_FREE(set); #else size_t bits_per_set = sizeof(CPUSET_T) * 8; size_t bits_per_subset = sizeof(CPUSET_MASK_T) * 8; size_t setsize = sizeof(CPUSET_T) * (MAX_CPUS / bits_per_set); size_t set_id, subset_id; unsigned long long mask; CPUSET_T *set = malloc(setsize); pthread_t pth; pth = pthread_self(); for (set_id = 0; set_id < (MAX_CPUS / bits_per_set); set_id++) CPU_ZERO(&set[set_id]); set_id = id / bits_per_set; id %= bits_per_set; subset_id = id / bits_per_subset; id %= bits_per_subset; mask = 1ULL << (unsigned long long)id; ((unsigned long *)set[set_id].__bits)[subset_id] |= mask; ret = pthread_setaffinity_np(pth, setsize, set); free(set); #endif return (ret == 0) ? 0 : 1; #elif defined(TARGET_OS_MACOSX) #ifdef USE_CHUD return (utilBindThreadToCPU(id) == 0) ? 0 : 1; #else return 1; #endif #else #error "thread_bind_native() not defined for this platform" #endif }
~ThreadGroupTempAffinity() { SetThreadGroupAffinity(GetCurrentThread(),&PreviousGroupAffinity,NULL); }