8 /****************************************************************************/
9 #if( defined _WIN32 && !defined KERNEL_MODE && NTDDI_VERSION >= NTDDI_VISTA )
11 #ifdef BENCHMARK_PAL_NUMA_MALLOC
12 #error More than one porting abstraction layer matches the current platform in porting_abstraction_malloc.c
15 #define BENCHMARK_PAL_NUMA_MALLOC
17 void *benchmark_pal_numa_malloc( lfds710_pal_uint_t numa_node_id, lfds710_pal_uint_t size_in_bytes )
25 // TRD : numa_node_id can be any value in its range
26 // TRD : size_in_bytes can be any value in its range
28 process_handle = GetCurrentProcess();
30 memory = VirtualAllocExNuma( process_handle, NULL, size_in_bytes, MEM_COMMIT, PAGE_READWRITE, (DWORD) numa_node_id );
41 /****************************************************************************/
42 #if( defined __linux__ && defined LIBNUMA )
44 #ifdef BENCHMARK_PAL_NUMA_MALLOC
45 #error More than one porting abstraction layer matches the current platform in porting_abstraction_malloc.c
48 #define BENCHMARK_PAL_NUMA_MALLOC
50 void *benchmark_pal_numa_malloc( lfds710_pal_uint_t numa_node_id, lfds710_pal_uint_t size_in_bytes )
55 // TRD : numa_node_id can be any value in its range
56 // TRD : size_in_bytes can be any value in its range
58 memory = numa_alloc_onnode( size_in_bytes, (int) numa_node_id );
60 /* TRD : mlock prevents paging
61 this is unfortunately necessary on Linux
62 due to serious shortcomings in the way NUMA is handled
64 in particular that the NUMA node is re-chosen if a memory page is paged out and then paged back in
65 but also because Linux doesn't page in a single page at a time, but a line of pages
66 so another process can end up moving *your* pages into *its* NUMA node (e.g. your pages are
67 in the line of pages), because the NUMA policy for *its* pages would put them in that node!
69 it seems to me this is one of the very rare occasions
70 where Windows has something right and Linux has it wrong
71 (Windows has the notion of an ideal NUMA node for a thread, and continually works
72 to move any pages which leave that node back into that node, and on page-in will
73 try first to re-use that node)
75 since we use small amounts of memory, I address the whole sorry mess
76 simply by locking the pages into memory - this way they will stay in the NUMA node
77 they were allocated into (assuming they've not been paged out and then back in,
78 between the numa_alloc_onnode() call and the mlock() call)
81 #if( defined _POSIX_MEMLOCK_RANGE > 0 )
82 mlock( memory, size_in_bytes );