Main changes from HEAD: 1) Implements GetNumaHighestNodeNumber which simulates a typical single node system. 2) Implements GetNumaNodeProcessorMask which returns the global processor affinity mask for node 0, otherwise returns an error. 3) Implements GetNumaAvailableMemoryNode which returns available physical memory for node 0, otherwise returns an error.
This much of the behavior was observed based on a single processor (4 cores) Windows 7 system. These functions are utilized by the synchronization and threading primitives incorporated in the MSVC 2012 and newer C and C++ runtime libraries. concrt.h/Concurrency::critical_section, which is used by both std::mutex and std::thread, will throw an exception the moment the object is locked if GetNumaHighestNodeNumber fails, and there are at least a few examples of software which don't bother to catch this exception and thus crash, such as the alpha version of Cube World, and certain versions of the foo_wave_seekbar component for the foobar2000 audio player. The associated scheduling code appears to make use of GetNumaNodeProcessorMask as well to control how many threads are allowed to spin up at once, or so I guess without looking very deeply into the CRT source code.
From a7ae257aed539fc72f0bc37c85030f8abc181389 Mon Sep 17 00:00:00 2001 From: Chris Moeller <kod...@gmail.com> Date: Sun, 28 Jul 2013 16:23:05 -0700 Subject: kernel32: Implemented basic NUMA functions to replace the stubs --- dlls/kernel32/process.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 6ce43d8..2513be6 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -3849,9 +3849,10 @@ HRESULT WINAPI RegisterApplicationRecoveryCallback(APPLICATION_RECOVERY_CALLBACK */ BOOL WINAPI GetNumaHighestNodeNumber(PULONG highestnode) { - FIXME("(%p): stub\n", highestnode); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + TRACE("(%p)\n", highestnode); + *highestnode = 0; + SetLastError(0); + return TRUE; } /********************************************************************** @@ -3859,9 +3860,20 @@ BOOL WINAPI GetNumaHighestNodeNumber(PULONG highestnode) */ BOOL WINAPI GetNumaNodeProcessorMask(UCHAR node, PULONGLONG mask) { - FIXME("(%c %p): stub\n", node, mask); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + TRACE("(%c %p)\n", node, mask); + if (node == 0) + { + DWORD system_mask; + GetProcessAffinityMask(GetCurrentProcess(), NULL, &system_mask); + *mask = system_mask; + SetLastError(0); + return TRUE; + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } } /********************************************************************** @@ -3869,9 +3881,21 @@ BOOL WINAPI GetNumaNodeProcessorMask(UCHAR node, PULONGLONG mask) */ BOOL WINAPI GetNumaAvailableMemoryNode(UCHAR node, PULONGLONG available_bytes) { - FIXME("(%c %p): stub\n", node, available_bytes); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + TRACE("(%c %p)\n", node, available_bytes); + if (node == 0) + { + MEMORYSTATUSEX msx; + msx.dwLength = sizeof(msx); + GlobalMemoryStatusEx(&msx); + *available_bytes = msx.ullAvailPhys; + SetLastError(0); + return TRUE; + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } } /********************************************************************** -- 1.7.10.2 (Apple Git-33)