1
0
Fork 0
mirror of https://github.com/anrieff/libcpuid synced 2025-01-23 20:06:41 +00:00

Restore previous thread CPU affinity before returning from cpuid_get_all_raw_data() (#184)

* Set thread instead of process CPU affinity in pre Windows 7 case

* Restore previous thread CPU affinity before returning from cpuid_get_all_raw_data()
This commit is contained in:
Robert Kausch 2023-02-17 10:07:44 +01:00 committed by GitHub
parent c7c2bd3619
commit 54ed9a0a17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -40,13 +40,15 @@
/* Implementation: */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ == 201112L
_Thread_local int _libcpuid_errno = ERR_OK;
#define INTERNAL_SCOPE _Thread_local
#elif defined(__GNUC__) // Also works for clang
__thread int _libcpuid_errno = ERR_OK;
#define INTERNAL_SCOPE __thread
#else
static int _libcpuid_errno = ERR_OK;
#define INTERNAL_SCOPE static
#endif
INTERNAL_SCOPE int _libcpuid_errno = ERR_OK;
int set_error(cpu_error_t err)
{
_libcpuid_errno = (int) err;
@ -173,6 +175,21 @@ static int get_total_cpus(void)
}
#define GET_TOTAL_CPUS_DEFINED
INTERNAL_SCOPE thread_affinity_policy_data_t saved_affinity;
static bool save_cpu_affinity()
{
mach_msg_type_number_t count = THREAD_AFFINITY_POLICY_COUNT;
boolean_t get_default = false;
return thread_policy_get(mach_thread_self(), THREAD_AFFINITY_POLICY, (thread_policy_t) &saved_affinity, &count, &get_default) == KERN_SUCCESS;
}
static bool restore_cpu_affinity()
{
return thread_policy_set(mach_thread_self(), THREAD_AFFINITY_POLICY, (thread_policy_t) &saved_affinity, THREAD_AFFINITY_POLICY_COUNT) == KERN_SUCCESS;
}
#define PRESERVE_CPU_AFFINITY
static bool set_cpu_affinity(logical_cpu_t logical_cpu)
{
thread_affinity_policy_data_t ap;
@ -196,6 +213,52 @@ static int get_total_cpus(void)
}
#define GET_TOTAL_CPUS_DEFINED
#if (_WIN32_WINNT >= 0x0601)
INTERNAL_SCOPE GROUP_AFFINITY savedGroupAffinity;
#else
INTERNAL_SCOPE DWORD_PTR savedAffinityMask = 0;
#endif
static bool save_cpu_affinity()
{
#if (_WIN32_WINNT >= 0x0601)
HANDLE thread = GetCurrentThread();
return GetThreadGroupAffinity(thread, &savedGroupAffinity);
#else
/* Credits to https://stackoverflow.com/questions/6601862/query-thread-not-process-processor-affinity#6601917 */
HANDLE thread = GetCurrentThread();
DWORD_PTR threadAffinityMask = 1;
while (threadAffinityMask) {
savedAffinityMask = SetThreadAffinityMask(thread, threadAffinityMask);
if(savedAffinityMask)
return SetThreadAffinityMask(thread, savedAffinityMask);
else if (GetLastError() != ERROR_INVALID_PARAMETER)
return false;
threadAffinityMask <<= 1; // try next CPU
}
return false;
#endif
}
static bool restore_cpu_affinity()
{
#if (_WIN32_WINNT >= 0x0601)
if (!savedGroupAffinity.Mask)
return false;
HANDLE thread = GetCurrentThread();
return SetThreadGroupAffinity(thread, &savedGroupAffinity, NULL);
#else
if (!savedAffinityMask)
return false;
HANDLE thread = GetCurrentThread();
return SetThreadAffinityMask(thread, savedAffinityMask);
#endif
}
#define PRESERVE_CPU_AFFINITY
static bool set_cpu_affinity(logical_cpu_t logical_cpu)
{
/* Credits to https://github.com/PolygonTek/BlueshiftEngine/blob/fbc374cbc391e1147c744649f405a66a27c35d89/Source/Runtime/Private/Platform/Windows/PlatformWinThread.cpp#L27 */
@ -229,9 +292,9 @@ static bool set_cpu_affinity(logical_cpu_t logical_cpu)
warnf("set_cpu_affinity for logical CPU %u is not supported in this operating system.\n", logical_cpu);
return -1;
}
HANDLE process = GetCurrentProcess();
DWORD_PTR processAffinityMask = 1ULL << logical_cpu;
return SetProcessAffinityMask(process, processAffinityMask);
HANDLE thread = GetCurrentThread();
DWORD_PTR threadAffinityMask = 1ULL << logical_cpu;
return SetThreadAffinityMask(thread, threadAffinityMask);
#endif /* (_WIN32_WINNT >= 0x0601) */
}
#define SET_CPU_AFFINITY
@ -262,6 +325,19 @@ static int get_total_cpus(void)
#if defined linux || defined __linux__
#include <sched.h>
INTERNAL_SCOPE cpu_set_t saved_affinity;
static bool save_cpu_affinity()
{
return sched_getaffinity(0, sizeof(saved_affinity), &saved_affinity) == 0;
}
static bool restore_cpu_affinity()
{
return sched_setaffinity(0, sizeof(saved_affinity), &saved_affinity) == 0;
}
#define PRESERVE_CPU_AFFINITY
static bool set_cpu_affinity(logical_cpu_t logical_cpu)
{
cpu_set_t cpuset;
@ -277,6 +353,19 @@ static bool set_cpu_affinity(logical_cpu_t logical_cpu)
#include <sys/processor.h>
#include <sys/procset.h>
INTERNAL_SCOPE processorid_t saved_binding = PBIND_NONE;
static bool save_cpu_affinity()
{
return processor_bind(P_LWPID, P_MYID, PBIND_QUERY, &saved_binding) == 0;
}
static bool restore_cpu_affinity()
{
return processor_bind(P_LWPID, P_MYID, saved_binding, NULL) == 0;
}
#define PRESERVE_CPU_AFFINITY
static bool set_cpu_affinity(logical_cpu_t logical_cpu)
{
if (logical_cpu > (sizeof(processorid_t) * 8)) {
@ -307,6 +396,19 @@ static int get_total_cpus(void)
#include <sys/param.h>
#include <sys/cpuset.h>
INTERNAL_SCOPE cpuset_t saved_affinity;
static bool save_cpu_affinity()
{
return cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(saved_affinity), &saved_affinity) == 0;
}
static bool restore_cpu_affinity()
{
return cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(saved_affinity), &saved_affinity) == 0;
}
#define PRESERVE_CPU_AFFINITY
static bool set_cpu_affinity(logical_cpu_t logical_cpu)
{
cpuset_t cpuset;
@ -321,6 +423,19 @@ static bool set_cpu_affinity(logical_cpu_t logical_cpu)
#include <pthread.h>
#include <pthread_np.h>
INTERNAL_SCOPE cpuset_t saved_affinity;
static bool save_cpu_affinity()
{
return pthread_getaffinity_np(pthread_self(), sizeof(saved_affinity), &saved_affinity) == 0;
}
static bool restore_cpu_affinity()
{
return pthread_setaffinity_np(pthread_self(), sizeof(saved_affinity), &saved_affinity) == 0;
}
#define PRESERVE_CPU_AFFINITY
static bool set_cpu_affinity(logical_cpu_t logical_cpu)
{
cpuset_t cpuset;
@ -335,6 +450,28 @@ static bool set_cpu_affinity(logical_cpu_t logical_cpu)
#include <pthread.h>
#include <sched.h>
INTERNAL_SCOPE cpuset_t *saved_affinity = NULL;
static bool save_cpu_affinity()
{
if (!saved_affinity)
saved_affinity = cpuset_create();
return pthread_getaffinity_np(pthread_self(), cpuset_size(saved_affinity), saved_affinity) == 0;
}
static bool restore_cpu_affinity()
{
if (!saved_affinity)
return false;
int ret = pthread_setaffinity_np(pthread_self(), cpuset_size(saved_affinity), saved_affinity) == 0;
cpuset_destroy(saved_affinity);
saved_affinity = NULL;
return ret == 0;
}
#define PRESERVE_CPU_AFFINITY
static bool set_cpu_affinity(logical_cpu_t logical_cpu)
{
cpuset_t *cpuset;
@ -361,6 +498,18 @@ static int get_total_cpus(void)
}
#endif /* GET_TOTAL_CPUS_DEFINED */
#ifndef PRESERVE_CPU_AFFINITY
static bool save_cpu_affinity()
{
return false;
}
static bool restore_cpu_affinity()
{
return false;
}
#endif /* PRESERVE_CPU_AFFINITY */
#ifndef SET_CPU_AFFINITY
static bool set_cpu_affinity(logical_cpu_t logical_cpu)
{
@ -924,6 +1073,8 @@ int cpuid_get_all_raw_data(struct cpu_raw_data_array_t* data)
if (data == NULL)
return set_error(ERR_HANDLE);
bool affinity_saved = save_cpu_affinity();
cpu_raw_data_array_t_constructor(data, true);
while (set_cpu_affinity(logical_cpu)) {
debugf(2, "Getting raw dump for logical CPU %i\n", logical_cpu);
@ -935,6 +1086,9 @@ int cpuid_get_all_raw_data(struct cpu_raw_data_array_t* data)
logical_cpu++;
}
if (affinity_saved)
restore_cpu_affinity();
return ret_error;
}