1
0
forked from 0ad/0ad

(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:
janwas 2008-05-12 18:38:48 +00:00
parent ffdff6888d
commit b429c492ff
2 changed files with 194 additions and 83 deletions

View File

@ -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;
}

View File

@ -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;
}