1/* 2 * Copyright 2023, J��r��me Duval, jerome.duval@gmail.com. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <sched.h> 8 9#include <syscalls.h> 10 11#ifdef __x86_64__ 12 13#include <pthread.h> 14 15#include <x86intrin.h> 16 17#define IA32_FEATURE_RDPID (1 << 22) // RDPID Instruction 18#define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction 19 20 21typedef int (*sched_cpu_func)(); 22static pthread_once_t sSchedCpuInitOnce = PTHREAD_ONCE_INIT; 23static sched_cpu_func sSchedCpuFunc = NULL; 24 25 26static int 27__sched_cpu_syscall() 28{ 29 return _kern_get_cpu(); 30} 31 32 33static int 34__sched_cpu_rdtscp() 35{ 36 uint32_t aux; 37 __rdtscp(&aux); 38 return aux; 39} 40 41 42static int 43__sched_cpu_rdpid() 44{ 45 return _rdpid_u32(); 46} 47 48 49static void 50initSchedCpuFunc() 51{ 52 cpuid_info cpuInfo; 53 get_cpuid(&cpuInfo, 0, 0); 54 if (cpuInfo.eax_0.max_eax >= 0x7) { 55 get_cpuid(&cpuInfo, 0x7, 0); 56 if ((cpuInfo.regs.ecx & IA32_FEATURE_RDPID) != 0) { 57 sSchedCpuFunc = __sched_cpu_rdpid; 58 return; 59 } 60 } 61 get_cpuid(&cpuInfo, 0x80000000, 0); 62 if (cpuInfo.eax_0.max_eax >= 0x80000001) { 63 get_cpuid(&cpuInfo, 0x80000001, 0); 64 if ((cpuInfo.regs.edx & IA32_FEATURE_AMD_EXT_RDTSCP)!= 0) { 65 sSchedCpuFunc = __sched_cpu_rdtscp; 66 return; 67 } 68 } 69 sSchedCpuFunc = __sched_cpu_syscall; 70} 71 72 73int 74sched_getcpu() 75{ 76 if (sSchedCpuFunc == NULL) { 77 pthread_once(&sSchedCpuInitOnce, &initSchedCpuFunc); 78 } 79 return sSchedCpuFunc(); 80} 81 82 83#else 84int 85sched_getcpu() 86{ 87 return _kern_get_cpu(); 88} 89#endif 90 91