Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:36

0001 
0002 // Copyright 2020, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 #include <unistd.h>
0006 #include <thread>
0007 #include <typeinfo>
0008 
0009 // Note that Apple complicates things some. In particular with the
0010 // addition of Apple silicon (M1 chip) which does not seem to have
0011 // thesame CPU utilities as older Apple OS versions/hardware (ugh!)
0012 #ifdef __APPLE__
0013 #include <mach/thread_policy.h>
0014 #import <mach/thread_act.h>
0015 #ifndef __aarch64__
0016 #include <cpuid.h>
0017 #endif // __aarch64__
0018 #else //__APPLE__ (i.e. Linux)
0019 #include <sched.h>
0020 #endif //__APPLE__
0021 
0022 
0023 #include <JANA/Utils/JCpuInfo.h>
0024 
0025 extern thread_local int THREAD_ID;
0026 
0027 
0028 namespace JCpuInfo {
0029 
0030 size_t GetNumCpus() {
0031     /// Returns the number of cores that are on the computer.
0032     /// The count will be full cores+hyperthreads (or equivalent)
0033     return sysconf(_SC_NPROCESSORS_ONLN);
0034 }
0035 
0036 
0037 uint32_t GetCpuID() {
0038     /// Returns the current CPU the calling thread is running on.
0039     /// Note that unless the thread affinity has been set, this may
0040     /// change, even before returning from this call. The thread
0041     /// affinity of all threads may be fixed by setting the AFFINITY
0042     /// configuration parameter at program start up.
0043 
0044 
0045 #ifdef __APPLE__
0046 // From https://stackoverflow.com/questions/33745364/sched-getcpu-equivalent-for-os-x
0047 #define CPUID(INFO, LEAF, SUBLEAF) __cpuid_count(LEAF, SUBLEAF, INFO[0], INFO[1], INFO[2], INFO[3])
0048 #define GETCPU(CPU) {                              \
0049         uint32_t CPUInfo[4];                           \
0050         CPUID(CPUInfo, 1, 0);                          \
0051         /* CPUInfo[1] is EBX, bits 24-31 are APIC ID */ \
0052         if ( (CPUInfo[3] & (1 << 9)) == 0) {           \
0053           CPU = -1;  /* no APIC on chip */             \
0054         }                                              \
0055         else {                                         \
0056           CPU = (unsigned)CPUInfo[1] >> 24;                    \
0057         }                                              \
0058         if (CPU < 0) CPU = 0;                          \
0059         }
0060 
0061     int cpuid=0;
0062 // Apple M1 running MacOS 12.0.1 does not support __cpuid_count. Skip for now
0063 #ifdef __cpuid_count
0064     GETCPU(cpuid);
0065 #else  // __cpuid_count
0066     // cpuid_count is not defined on this system.
0067     return 0; 
0068 #endif // __cpuid_count
0069     return cpuid;
0070 
0071 #else //__APPLE__
0072     return sched_getcpu();
0073 #endif //__APPLE__
0074 }
0075 
0076 
0077 bool PinThreadToCpu(std::thread* thread, size_t cpu_id) {
0078 
0079     if (typeid(std::thread::native_handle_type) != typeid(pthread_t)) {
0080         return false;
0081     }
0082     pthread_t pthread = thread->native_handle();
0083 
0084 #ifdef __APPLE__
0085     // Mac OS X
0086     thread_affinity_policy_data_t policy = {(int) cpu_id};
0087     thread_port_t mach_thread = pthread_mach_thread_np(pthread);
0088     thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY,
0089                       (thread_policy_t) &policy,
0090                       THREAD_AFFINITY_POLICY_COUNT);
0091 #else
0092     // Linux
0093     cpu_set_t cpuset;
0094     CPU_ZERO(&cpuset);
0095     CPU_SET(cpu_id, &cpuset);
0096     int rc = pthread_setaffinity_np(pthread, sizeof(cpu_set_t), &cpuset);
0097     if (rc != 0) {
0098         return false;
0099     }
0100 #endif
0101     return true;
0102 }
0103 
0104 } // JCpuInfo namespace
0105