]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/test_and_benchmark/benchmark/src/porting_abstraction_layer_numa_malloc.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.1.0 / test_and_benchmark / benchmark / src / porting_abstraction_layer_numa_malloc.c
1 /***** includes *****/
2 #include "internal.h"
3
4
5
6
7
8 /****************************************************************************/
9 #if( defined _WIN32 && !defined KERNEL_MODE && NTDDI_VERSION >= NTDDI_VISTA )
10
11   #ifdef BENCHMARK_PAL_NUMA_MALLOC
12     #error More than one porting abstraction layer matches the current platform in porting_abstraction_malloc.c
13   #endif
14
15   #define BENCHMARK_PAL_NUMA_MALLOC
16
17   void *benchmark_pal_numa_malloc( lfds710_pal_uint_t numa_node_id, lfds710_pal_uint_t size_in_bytes )
18   {
19     HANDLE
20       process_handle;
21
22     LPVOID
23       memory;
24
25     // TRD : numa_node_id can be any value in its range
26     // TRD : size_in_bytes can be any value in its range
27
28     process_handle = GetCurrentProcess();
29
30     memory = VirtualAllocExNuma( process_handle, NULL, size_in_bytes, MEM_COMMIT, PAGE_READWRITE, (DWORD) numa_node_id );
31
32     return memory;
33   }
34
35 #endif
36
37
38
39
40
41 /****************************************************************************/
42 #if( defined __linux__ && defined LIBNUMA )
43
44   #ifdef BENCHMARK_PAL_NUMA_MALLOC
45     #error More than one porting abstraction layer matches the current platform in porting_abstraction_malloc.c
46   #endif
47
48   #define BENCHMARK_PAL_NUMA_MALLOC
49
50   void *benchmark_pal_numa_malloc( lfds710_pal_uint_t numa_node_id, lfds710_pal_uint_t size_in_bytes )
51   {
52     void
53       *memory;
54
55     // TRD : numa_node_id can be any value in its range
56     // TRD : size_in_bytes can be any value in its range
57
58     memory = numa_alloc_onnode( size_in_bytes, (int) numa_node_id );
59
60     /* TRD : mlock prevents paging
61              this is unfortunately necessary on Linux
62              due to serious shortcomings in the way NUMA is handled
63
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!
68
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)
74
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)
79     */
80
81     #if( defined _POSIX_MEMLOCK_RANGE > 0 )
82       mlock( memory, size_in_bytes );
83     #endif
84
85     return memory;
86   }
87
88 #endif
89