0ad/source/lib/sysdep/win/wposix/wposix.cpp
janwas 12ac1deebd wposix: add sysconf support for number of "processors"
ia32: add note on when ia32_ApicId fails; support detecting/guessing
processor topology from number of "processors" (hopefully fixes warning
on Philip's PIII system)

This was SVN commit r5209.
2007-06-23 12:59:21 +00:00

129 lines
3.4 KiB
C++

/**
* =========================================================================
* File : wposix.cpp
* Project : 0 A.D.
* Description : emulate a subset of POSIX on Win32.
* =========================================================================
*/
// license: GPL; see lib/license.txt
#include "precompiled.h"
#include "wposix.h"
#include "wposix_internal.h"
#include "crt_posix.h" // _getcwd
#include "lib/bits.h"
WINIT_REGISTER_CRITICAL_INIT(wposix_Init); // wposix -> error handling
//-----------------------------------------------------------------------------
// sysconf
// used by _SC_PAGESIZE and _SC_*_PAGES
static DWORD pageSize;
static DWORD numProcessors;
static BOOL (WINAPI *pGlobalMemoryStatusEx)(MEMORYSTATUSEX*);
static void InitSysconf()
{
SYSTEM_INFO si;
GetSystemInfo(&si); // can't fail
pageSize = si.dwPageSize; // used by _SC_PAGESIZE and _SC_*_PAGES
numProcessors = si.dwNumberOfProcessors;
// import GlobalMemoryStatusEx - it's not defined by the VC6 PSDK.
// used by _SC_*_PAGES if available (provides better results).
const HMODULE hKernel32Dll = LoadLibrary("kernel32.dll");
*(void**)&pGlobalMemoryStatusEx = GetProcAddress(hKernel32Dll, "GlobalMemoryStatusEx");
FreeLibrary(hKernel32Dll);
}
long sysconf(int name)
{
// called before InitSysconf => winit/wstartup are broken. this is
// going to cause a hard crash because debug.cpp's error reporting
// code requires the page size to be known. we'll raise an exception
// with a unique value so that this issue is immediately noticed.
if(!pageSize)
RaiseException(0xFA57FA57, 0, 0, 0);
switch(name)
{
case _SC_PAGESIZE:
// note: no separate case for _SC_PAGE_SIZE - they are
// different names but have the same value.
return pageSize;
case _SC_PHYS_PAGES:
case _SC_AVPHYS_PAGES:
{
u64 total_phys_mem;
u64 avail_phys_mem;
// first query GlobalMemoryStatus - cannot fail.
// override its results if GlobalMemoryStatusEx is available.
{
MEMORYSTATUS ms;
GlobalMemoryStatus(&ms);
total_phys_mem = ms.dwTotalPhys;
avail_phys_mem = ms.dwAvailPhys;
}
// newer API is available: use it to report correct results
// (no overflow or wraparound) on systems with > 4 GB of memory.
{
MEMORYSTATUSEX mse = { sizeof(mse) };
if(pGlobalMemoryStatusEx && pGlobalMemoryStatusEx(&mse))
{
total_phys_mem = mse.ullTotalPhys;
avail_phys_mem = mse.ullAvailPhys;
}
// else: not an error, since this isn't available before Win2k / XP.
// we have results from GlobalMemoryStatus anyway.
}
// Richter, "Programming Applications for Windows": the reported
// value doesn't include non-paged pool reserved during boot;
// it's not considered available to kernel. (size is 528 KiB on
// a 512 MiB WinXP/Win2k machine)
// something similar may happen on other OSes, so it is fixed
// by cpu.cpp instead of here.
if(name == _SC_PHYS_PAGES)
return (long)(total_phys_mem / pageSize);
else
return (long)(avail_phys_mem / pageSize);
}
case _SC_NPROCESSORS_CONF:
return numProcessors;
default:
return -1;
}
}
//-----------------------------------------------------------------------------
#ifdef REDEFINED_NEW
# include "lib/nommgr.h"
#endif
char* getcwd(char* buf, size_t buf_size)
{
return _getcwd(buf, (int)buf_size);
}
#ifdef REDEFINED_NEW
# include "lib/mmgr.h"
#endif
//-----------------------------------------------------------------------------
static LibError wposix_Init()
{
InitSysconf();
return INFO::OK;
}