// @return ratio between max/min time required to access one node's // memory from each processor. static double MeasureRelativeDistance() { const size_t size = 32*MiB; void* mem = vm::Allocate(size); ASSUME_ALIGNED(mem, pageSize); const uintptr_t previousProcessorMask = os_cpu_SetThreadAffinityMask(os_cpu_ProcessorMask()); double minTime = 1e10, maxTime = 0.0; for(size_t node = 0; node < numa_NumNodes(); node++) { const uintptr_t processorMask = numa_ProcessorMaskFromNode(node); os_cpu_SetThreadAffinityMask(processorMask); const double startTime = timer_Time(); memset(mem, 0, size); const double elapsedTime = timer_Time() - startTime; minTime = std::min(minTime, elapsedTime); maxTime = std::max(maxTime, elapsedTime); } (void)os_cpu_SetThreadAffinityMask(previousProcessorMask); vm::Free(mem, size); return maxTime / minTime; }
static Descriptors GetDescriptors() { // ensure consistency by pinning to a CPU. // (don't use a hard-coded mask because process affinity may be restricted) const uintptr_t allProcessors = os_cpu_ProcessorMask(); const uintptr_t firstProcessor = allProcessors & -intptr_t(allProcessors); const uintptr_t prevAffinityMask = os_cpu_SetThreadAffinityMask(firstProcessor); x86_x64::CpuidRegs regs = { 0 }; regs.eax = 2; if(!x86_x64::cpuid(®s)) return Descriptors(); Descriptors descriptors; size_t iterations = bits(regs.eax, 0, 7); for(;;) // abort mid-loop (invoke CPUID exactly <iterations> times) { AppendDescriptors(bits(regs.eax, 8, 31), descriptors); AppendDescriptors(regs.ebx, descriptors); AppendDescriptors(regs.ecx, descriptors); AppendDescriptors(regs.edx, descriptors); if(--iterations == 0) break; regs.eax = 2; const bool ok = x86_x64::cpuid(®s); ENSURE(ok); } os_cpu_SetThreadAffinityMask(prevAffinityMask); return descriptors; }
Status os_cpu_CallByEachCPU(OsCpuCallback cb, uintptr_t cbData) { for(size_t processor = 0; processor < os_cpu_NumProcessors(); processor++) { const uintptr_t processorMask = uintptr_t(1) << processor; os_cpu_SetThreadAffinityMask(processorMask); cb(processor, cbData); } return INFO::OK; }