void CPUID::Go() { CoreAssert(this != NULL); #ifdef TARGET_OS_WINDOWS DWORD dThread = NULL; SYSTEM_INFO siSystem; int iCount = 0; struct GoThreadProc_Params params; params.cpuid_class = this; GetSystemInfo(&siSystem); iCount = siSystem.dwNumberOfProcessors; if (iCount > MAX_PROCESSORS) { iCount = MAX_PROCESSORS; } for (params.processor = 0; params.processor < iCount; params.processor++) { HANDLE hThread = CreateThread(NULL, 0, ( LPTHREAD_START_ROUTINE )s_GoThreadProc, ¶ms, CREATE_SUSPENDED, &dThread); SetThreadAffinityMask(hThread, ( DWORD )pow(( double )2, ( double )params. processor)); Sleep(0); /* Wait for affinity switch. */ SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); ResumeThread(hThread); WaitForSingleObject(hThread, INFINITE); } #elif defined (TARGET_OS_LINUX) int NUM_PROCS = sysconf(_SC_NPROCESSORS_CONF), i; cpu_set_t mask; cpu_set_t originalmask; sched_getaffinity(0, sizeof(originalmask), &originalmask); for (i = 0; i < NUM_PROCS; i++) { CPU_ZERO(&mask); CPU_SET(( int )pow(2, i), &mask); sched_setaffinity(0, sizeof(mask), &mask); GoThread(i); } sched_setaffinity(0, sizeof(originalmask), &originalmask); #elif defined (TARGET_OS_MACOSX) int NUM_PROCS = chudProcessorCount(); for (int i = 0; i < NUM_PROCS; i++) { utilUnbindThreadFromCPU(); utilBindThreadToCPU(i); GoThread(i); } utilUnbindThreadFromCPU(); #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 }
int thread_bind_native(__unused_variable struct cpuid_state_t *state, uint32_t id) { #ifdef TARGET_OS_WINDOWS BOOL ret = FALSE; HANDLE hThread = GetCurrentThread(); #if _WIN32_WINNT < 0x0601 if (is_windows7_or_greater()) { #endif DWORD threadsInGroup = 0; WORD groupId, groupCount; GROUP_AFFINITY affinity; ZeroMemory(&affinity, sizeof(GROUP_AFFINITY)); groupCount = GetActiveProcessorGroupCount(); for (groupId = 0; groupId < groupCount; groupId++) { threadsInGroup = GetActiveProcessorCount(groupId); if (id < threadsInGroup) break; id -= threadsInGroup; } if (groupId < groupCount && id < threadsInGroup) { affinity.Group = groupId; affinity.Mask = 1ULL << id; ret = SetThreadGroupAffinity(hThread, &affinity, NULL); } #if _WIN32_WINNT < 0x0601 } else { DWORD mask; if (id > 32) return 1; mask = (1 << id); ret = SetThreadAffinityMask(hThread, mask); } #endif if (state && ret != FALSE) state->cpu_bound_index = id; 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 if (state && ret == 0) state->cpu_bound_index = id; return (ret == 0) ? 0 : 1; #elif defined(TARGET_OS_SOLARIS) /* * This requires permissions, so can easily fail. */ if (processor_bind(P_LWPID, P_MYID, id, NULL) != 0) { fprintf(stderr, "warning: failed to bind to CPU%u: %s\n", id, strerror(errno)); return 1; } if (state) state->cpu_bound_index = id; return 0; #elif defined(TARGET_OS_MACOSX) int ret = 1; #ifdef USE_CHUD ret = (utilBindThreadToCPU(id) == 0) ? 0 : 1; #endif if (state && ret == 0) state->cpu_bound_index = id; return ret == 0 ? 0 : 1; #else #error "thread_bind_native() not defined for this platform" #endif }