(hopefully correctly) port the new os_cpu functions to Linux and OSX
the OSX port lacks thread affinity (too complex, can't test), but a link to the API documentation is included. This was SVN commit r5946.
This commit is contained in:
parent
ffdff6888d
commit
b429c492ff
@ -1,77 +1,134 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "../cpu.h"
|
||||
#include "lib/sysdep/os_cpu.h
|
||||
|
||||
#if OS_LINUX
|
||||
#include "valgrind.h"
|
||||
#endif
|
||||
|
||||
|
||||
double cpu_ClockFrequency()
|
||||
double os_cpu_ClockFrequency()
|
||||
{
|
||||
return -1; // don't know
|
||||
}
|
||||
|
||||
|
||||
size_t cpu_NumProcessors()
|
||||
size_t os_cpu_NumProcessors()
|
||||
{
|
||||
long res = sysconf(_SC_NPROCESSORS_CONF);
|
||||
if (res == -1)
|
||||
return 0;
|
||||
else
|
||||
return (size_t)res;
|
||||
}
|
||||
static size_t numProcessors;
|
||||
|
||||
|
||||
size_t cpu_PageSize()
|
||||
{
|
||||
return (size_t)sysconf(_SC_PAGESIZE);
|
||||
}
|
||||
|
||||
|
||||
static int SysconfFromMemType(CpuMemoryIndicators mem_type)
|
||||
{
|
||||
switch(mem_type)
|
||||
if(numProcessors == 0)
|
||||
{
|
||||
case CPU_MEM_TOTAL:
|
||||
return _SC_PHYS_PAGES;
|
||||
case CPU_MEM_AVAILABLE:
|
||||
return _SC_AVPHYS_PAGES;
|
||||
// Valgrind reports the number of real CPUs, but only emulates a single CPU.
|
||||
// That causes problems when we expect all those CPUs to be distinct, so
|
||||
// just pretend there's only one CPU
|
||||
if (RUNNING_ON_VALGRIND)
|
||||
numProcessors = 1;
|
||||
else
|
||||
{
|
||||
long res = sysconf(_SC_NPROCESSORS_CONF);
|
||||
debug_assert(res != -1);
|
||||
numProcessors = (size_t)res;
|
||||
}
|
||||
}
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
size_t cpu_MemorySize(CpuMemoryIndicators mem_type)
|
||||
{
|
||||
const int sc_name = SysconfFromMemType(mem_type);
|
||||
const size_t pageSize = sysconf(_SC_PAGESIZE);
|
||||
const size_t memory_size = sysconf(sc_name) * pageSize;
|
||||
return memory_size;
|
||||
return numProcessors;
|
||||
}
|
||||
|
||||
|
||||
LibError cpu_CallByEachCPU(CpuCallback cb, void* param)
|
||||
uintptr_t os_cpu_ProcessorMask()
|
||||
{
|
||||
long ncpus = sysconf(_SC_NPROCESSORS_CONF);
|
||||
static uintptr_t processorMask;
|
||||
|
||||
// Valgrind reports the number of real CPUs, but only emulates a single CPU.
|
||||
// That causes problems when we expect all those CPUs to be distinct, so
|
||||
// just pretend there's only one CPU
|
||||
if (RUNNING_ON_VALGRIND)
|
||||
ncpus = 1;
|
||||
if(!processorMask)
|
||||
processorMask = bit_mask<uintptr_t>(os_cpu_NumProcessors());
|
||||
|
||||
return processorMask;
|
||||
}
|
||||
|
||||
|
||||
size_t os_cpu_PageSize()
|
||||
{
|
||||
static size_t pageSize;
|
||||
|
||||
if(!pageSize)
|
||||
pageSize = (size_t)sysconf(_SC_PAGESIZE);
|
||||
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
|
||||
size_t os_cpu_LargePageSize()
|
||||
{
|
||||
// assume they're unsupported.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t os_cpu_MemorySize()
|
||||
{
|
||||
static size_t memorySize;
|
||||
|
||||
if(!memorySize)
|
||||
memorySize = sysconf(_SC_PHYS_PAGES) * os_cpu_PageSize();
|
||||
|
||||
return memorySize;
|
||||
}
|
||||
|
||||
|
||||
size_t os_cpu_MemoryAvailable()
|
||||
{
|
||||
const size_t memoryAvailable = sysconf(_SC_AVPHYS_PAGES) * os_cpu_PageSize();
|
||||
return memoryAvailable;
|
||||
}
|
||||
|
||||
|
||||
uintptr_t os_cpu_SetThreadAffinityMask(uintptr_t processorMask)
|
||||
{
|
||||
int ret;
|
||||
cpu_set_t set;
|
||||
for (long i = 0; i < ncpus && i < CPU_SETSIZE; ++i)
|
||||
|
||||
uintptr_t previousProcessorMask = 0;
|
||||
{
|
||||
CPU_ZERO(&set);
|
||||
CPU_SET(i, &set);
|
||||
ret = sched_getaffinity(0, sizeof(set), &set);
|
||||
debug_assert(ret == 0);
|
||||
|
||||
int ret = sched_setaffinity(0, sizeof(set), &set);
|
||||
if (ret)
|
||||
WARN_RETURN(ERR::FAIL);
|
||||
// (The process gets migrated immediately by the setaffinity call)
|
||||
|
||||
cb(param);
|
||||
for(size_t processor = 0; processor < os_cpu_NumProcessors(); processor++)
|
||||
{
|
||||
if(CPU_ISSET(processor, &set))
|
||||
previousProcessorMask |= uintptr_t(1) << processor;
|
||||
}
|
||||
}
|
||||
|
||||
CPU_ZERO(&set);
|
||||
for(size_t processor = 0; processor < os_cpu_NumProcessors(); processor++)
|
||||
{
|
||||
if(IsBitSet(processorMask, processor))
|
||||
CPU_SET(processor, &set);
|
||||
}
|
||||
|
||||
ret = sched_setaffinity(0, sizeof(set), &set);
|
||||
debug_assert(ret == 0);
|
||||
// (The process gets migrated immediately by the setaffinity call)
|
||||
|
||||
return previousProcessorMask;
|
||||
}
|
||||
|
||||
|
||||
void os_cpu_SetThreadAffinity(size_t processor)
|
||||
{
|
||||
const uintptr_t processorMask = uintptr_t(1) << processor;
|
||||
(void)os_cpu_SetThreadAffinityMask(processorMask);
|
||||
}
|
||||
|
||||
|
||||
LibError cpu_CallByEachCPU(OsCpuCallback cb, uintptr_t cbData)
|
||||
{
|
||||
for(size_t processor = 0; processor < os_cpu_NumProcessors(); processor++)
|
||||
{
|
||||
os_cpu_SetThreadAffinity(processor);
|
||||
cb(processor, cbData);
|
||||
}
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
|
@ -5,55 +5,109 @@
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
|
||||
double cpu_ClockFrequency()
|
||||
double os_cpu_ClockFrequency()
|
||||
{
|
||||
return -1.0; // don't know
|
||||
return -1; // don't know
|
||||
}
|
||||
|
||||
|
||||
size_t cpu_NumProcessors()
|
||||
size_t os_cpu_NumProcessors()
|
||||
{
|
||||
// Mac OS X doesn't have sysconf(_SC_NPROCESSORS_CONF)
|
||||
int mib[]={CTL_HW, HW_NCPU};
|
||||
int ncpus;
|
||||
size_t len = sizeof(ncpus);
|
||||
if (sysctl(mib, 2, &ncpus, &len, NULL, 0) == -1)
|
||||
return -1; // don't know
|
||||
else
|
||||
return ncpus;
|
||||
}
|
||||
static size_t numProcessors;
|
||||
|
||||
|
||||
size_t cpu_PageSize()
|
||||
{
|
||||
return (size_t)sysconf(_SC_PAGESIZE);
|
||||
}
|
||||
|
||||
|
||||
static int SysctlFromMemType(CpuMemoryIndicators mem_type)
|
||||
{
|
||||
switch(mem_type)
|
||||
if(numProcessors == 0)
|
||||
{
|
||||
case CPU_MEM_TOTAL:
|
||||
return HW_PHYSMEM;
|
||||
case CPU_MEM_AVAILABLE:
|
||||
return HW_USERMEM;
|
||||
// Mac OS X doesn't have sysconf(_SC_NPROCESSORS_CONF)
|
||||
int mib[]={CTL_HW, HW_NCPU};
|
||||
int ncpus;
|
||||
size_t len = sizeof(ncpus);
|
||||
int ret = sysctl(mib, 2, &ncpus, &len, NULL, 0);
|
||||
debug_assert(ret != -1);
|
||||
numProcessors = (size_t)ncpus;
|
||||
}
|
||||
UNREACHABLE;
|
||||
|
||||
return numProcessors;
|
||||
}
|
||||
|
||||
size_t cpu_MemorySize(CpuMemoryIndicators mem_type)
|
||||
|
||||
uintptr_t os_cpu_ProcessorMask()
|
||||
{
|
||||
size_t memory_size = 0;
|
||||
size_t len = sizeof(memory_size);
|
||||
static uintptr_t processorMask;
|
||||
|
||||
if(!processorMask)
|
||||
processorMask = bit_mask<uintptr_t>(os_cpu_NumProcessors());
|
||||
|
||||
return processorMask;
|
||||
}
|
||||
|
||||
|
||||
size_t os_cpu_PageSize()
|
||||
{
|
||||
static size_t pageSize;
|
||||
|
||||
if(!pageSize)
|
||||
pageSize = (size_t)sysconf(_SC_PAGESIZE);
|
||||
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
|
||||
size_t os_cpu_LargePageSize()
|
||||
{
|
||||
// assume they're unsupported.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t os_cpu_MemorySize()
|
||||
{
|
||||
static size_t memorySize;
|
||||
|
||||
if(!memorySize)
|
||||
{
|
||||
size_t len = sizeof(memorySize);
|
||||
// Argh, the API doesn't seem to be const-correct
|
||||
/*const*/ int mib[2] = { CTL_HW, HW_PHYSMEM };
|
||||
sysctl(mib, 2, &memorySize, &len, 0, 0);
|
||||
}
|
||||
|
||||
return memorySize;
|
||||
}
|
||||
|
||||
|
||||
size_t os_cpu_MemoryAvailable()
|
||||
{
|
||||
size_t memoryAvailable = 0;
|
||||
size_t len = sizeof(memoryAvailable);
|
||||
// Argh, the API doesn't seem to be const-correct
|
||||
/*const*/ int mib[2] = { CTL_HW, SysctlFromMemType(mem_type) };
|
||||
sysctl(mib, 2, &memory_size, &len, 0, 0);
|
||||
return memory_size;
|
||||
/*const*/ int mib[2] = { CTL_HW, HW_USERMEM };
|
||||
sysctl(mib, 2, &memoryAvailable, &len, 0, 0);
|
||||
return memoryAvailable;
|
||||
}
|
||||
|
||||
LibError cpu_CallByEachCPU(CpuCallback cb, void* param)
|
||||
|
||||
uintptr_t os_cpu_SetThreadAffinityMask(uintptr_t processorMask)
|
||||
{
|
||||
// TODO: implement
|
||||
return ERR::NOT_IMPLEMENTED;
|
||||
// not yet implemented. when doing so, see http://developer.apple.com/releasenotes/Performance/RN-AffinityAPI/
|
||||
|
||||
return os_cpu_ProcessorMask();
|
||||
}
|
||||
|
||||
|
||||
void os_cpu_SetThreadAffinity(size_t processor)
|
||||
{
|
||||
const uintptr_t processorMask = uintptr_t(1) << processor;
|
||||
(void)os_cpu_SetThreadAffinityMask(processorMask);
|
||||
}
|
||||
|
||||
|
||||
LibError cpu_CallByEachCPU(OsCpuCallback cb, uintptr_t cbData)
|
||||
{
|
||||
for(size_t processor = 0; processor < os_cpu_NumProcessors(); processor++)
|
||||
{
|
||||
os_cpu_SetThreadAffinity(processor);
|
||||
cb(processor, cbData);
|
||||
}
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user