6
6
7
7
#include < numa.h>
8
8
#include < numaif.h>
9
+ #include < sched.h>
9
10
11
+ #include " test_helpers.h"
10
12
#include < umf/providers/provider_os_memory.h>
11
13
12
14
static umf_os_memory_provider_params_t UMF_OS_MEMORY_PROVIDER_PARAMS_TEST =
@@ -28,7 +30,17 @@ std::vector<int> get_available_numa_nodes_numbers() {
28
30
return available_numa_nodes_numbers;
29
31
}
30
32
31
- struct testNumaNodes : public testing ::TestWithParam<int > {
33
+ void set_all_available_nodemask_bits (bitmask *nodemask) {
34
+ UT_ASSERTne (numa_available (), -1 );
35
+ UT_ASSERTne (numa_all_nodes_ptr, nullptr );
36
+
37
+ numa_bitmask_clearall (nodemask);
38
+
39
+ // Set all available NUMA nodes numbers.
40
+ copy_bitmask_to_bitmask (numa_all_nodes_ptr, nodemask);
41
+ }
42
+
43
+ struct testNuma : testing::Test {
32
44
void SetUp () override {
33
45
if (numa_available () == -1 ) {
34
46
GTEST_SKIP () << " Test skipped, NUMA not available" ;
@@ -56,10 +68,22 @@ struct testNumaNodes : public testing::TestWithParam<int> {
56
68
int numa_node;
57
69
int ret = get_mempolicy (&numa_node, nullptr , 0 , addr,
58
70
MPOL_F_NODE | MPOL_F_ADDR);
59
- EXPECT_EQ (ret, 0 );
71
+ UT_ASSERTeq (ret, 0 );
60
72
return numa_node;
61
73
}
62
74
75
+ long unsigned int retrieve_nodemask (void *addr) {
76
+ struct bitmask *retrieved_nodemask = numa_allocate_nodemask ();
77
+ UT_ASSERTne (nodemask, nullptr );
78
+ int ret = get_mempolicy (nullptr , retrieved_nodemask->maskp ,
79
+ nodemask->size , addr, MPOL_F_ADDR);
80
+ UT_ASSERTeq (ret, 0 );
81
+ long unsigned int retrieved_nodemask_value =
82
+ *(retrieved_nodemask->maskp );
83
+ numa_bitmask_free (retrieved_nodemask);
84
+ return retrieved_nodemask_value;
85
+ }
86
+
63
87
void TearDown () override {
64
88
umf_result_t umf_result;
65
89
if (ptr) {
@@ -82,14 +106,16 @@ struct testNumaNodes : public testing::TestWithParam<int> {
82
106
umf_memory_provider_handle_t os_memory_provider = nullptr ;
83
107
};
84
108
109
+ struct testNumaOnAllNodes : testNuma, testing::WithParamInterface<int > {};
110
+
85
111
INSTANTIATE_TEST_SUITE_P (
86
- testNumaNodesAllocations, testNumaNodes ,
112
+ testNumaNodesAllocations, testNumaOnAllNodes ,
87
113
::testing::ValuesIn (get_available_numa_nodes_numbers()));
88
114
89
115
// Test for allocations on numa nodes. This test will be executed for all numa nodes
90
116
// available on the system. The available nodes are returned in vector from the
91
117
// get_available_numa_nodes_numbers() function and passed to test as parameters.
92
- TEST_P (testNumaNodes , checkNumaNodesAllocations) {
118
+ TEST_P (testNumaOnAllNodes , checkNumaNodesAllocations) {
93
119
int numa_node_number = GetParam ();
94
120
umf_os_memory_provider_params_t os_memory_provider_params =
95
121
UMF_OS_MEMORY_PROVIDER_PARAMS_TEST;
@@ -111,3 +137,152 @@ TEST_P(testNumaNodes, checkNumaNodesAllocations) {
111
137
int retrieved_numa_node_number = retrieve_numa_node_number (ptr);
112
138
ASSERT_EQ (retrieved_numa_node_number, numa_node_number);
113
139
}
140
+
141
+ // Test for allocations on numa nodes with mode preferred. It runs for all available
142
+ // numa nodes obtained from the get_available_numa_nodes_numbers() function.
143
+ TEST_P (testNumaOnAllNodes, checkModePreferred) {
144
+ int numa_node_number = GetParam ();
145
+ umf_os_memory_provider_params_t os_memory_provider_params =
146
+ UMF_OS_MEMORY_PROVIDER_PARAMS_TEST;
147
+ os_memory_provider_params.maxnode = numa_node_number + 1 ;
148
+ numa_bitmask_setbit (nodemask, numa_node_number);
149
+ os_memory_provider_params.nodemask = nodemask->maskp ;
150
+ os_memory_provider_params.numa_mode = UMF_NUMA_MODE_PREFERRED;
151
+ initOsProvider (os_memory_provider_params);
152
+
153
+ umf_result_t umf_result;
154
+ umf_result =
155
+ umfMemoryProviderAlloc (os_memory_provider, alloc_size, 0 , &ptr);
156
+ ASSERT_EQ (umf_result, UMF_RESULT_SUCCESS);
157
+ ASSERT_NE (ptr, nullptr );
158
+
159
+ // This pointer must point to an initialized value before retrieving a number of
160
+ // the numa node that the pointer was allocated on (calling get_mempolicy).
161
+ memset (ptr, 0xFF , alloc_size);
162
+ int retrieved_numa_node_number = retrieve_numa_node_number (ptr);
163
+ ASSERT_EQ (retrieved_numa_node_number, numa_node_number);
164
+ }
165
+
166
+ // Test for allocation on numa node with local mode enabled. The memory is
167
+ // allocated on the node of the CPU that triggered the allocation.
168
+ TEST_F (testNuma, checkModeLocal) {
169
+ umf_os_memory_provider_params_t os_memory_provider_params =
170
+ UMF_OS_MEMORY_PROVIDER_PARAMS_TEST;
171
+ os_memory_provider_params.numa_mode = UMF_NUMA_MODE_LOCAL;
172
+ initOsProvider (os_memory_provider_params);
173
+
174
+ umf_result_t umf_result;
175
+ umf_result =
176
+ umfMemoryProviderAlloc (os_memory_provider, alloc_size, 0 , &ptr);
177
+ ASSERT_EQ (umf_result, UMF_RESULT_SUCCESS);
178
+ ASSERT_NE (ptr, nullptr );
179
+
180
+ int cpu = sched_getcpu ();
181
+ int numa_node_number = numa_node_of_cpu (cpu);
182
+
183
+ // This pointer must point to an initialized value before retrieving a number of
184
+ // the numa node that the pointer was allocated on (calling get_mempolicy).
185
+ memset (ptr, 0xFF , alloc_size);
186
+ int retrieved_numa_node_number = retrieve_numa_node_number (ptr);
187
+ ASSERT_EQ (retrieved_numa_node_number, numa_node_number);
188
+ }
189
+
190
+ // Test for allocation on numa node with default mode enabled.
191
+ // Since no policy is set by the set_mempolicy function, it should
192
+ // default to the system-wide default policy, which allocates pages
193
+ // on the node of the CPU that triggers the allocation.
194
+ TEST_F (testNuma, checkModeDefault) {
195
+ umf_os_memory_provider_params_t os_memory_provider_params =
196
+ UMF_OS_MEMORY_PROVIDER_PARAMS_TEST;
197
+ initOsProvider (os_memory_provider_params);
198
+
199
+ umf_result_t umf_result;
200
+ umf_result =
201
+ umfMemoryProviderAlloc (os_memory_provider, alloc_size, 0 , &ptr);
202
+ ASSERT_EQ (umf_result, UMF_RESULT_SUCCESS);
203
+ ASSERT_NE (ptr, nullptr );
204
+
205
+ int cpu = sched_getcpu ();
206
+ int numa_node_number = numa_node_of_cpu (cpu);
207
+
208
+ // This pointer must point to an initialized value before retrieving a number of
209
+ // the numa node that the pointer was allocated on (calling get_mempolicy).
210
+ memset (ptr, 0xFF , alloc_size);
211
+ int retrieved_numa_node_number = retrieve_numa_node_number (ptr);
212
+ ASSERT_EQ (retrieved_numa_node_number, numa_node_number);
213
+ }
214
+
215
+ // Test for allocations on numa nodes with interleave mode enabled.
216
+ // The page allocations are interleaved across the set of nodes specified in nodemask.
217
+ TEST_F (testNuma, checkModeInterleave) {
218
+ int num_page = 1024 ;
219
+ size_t page_size = sysconf (_SC_PAGE_SIZE);
220
+ umf_os_memory_provider_params_t os_memory_provider_params =
221
+ UMF_OS_MEMORY_PROVIDER_PARAMS_TEST;
222
+ os_memory_provider_params.maxnode = numa_max_node ();
223
+ set_all_available_nodemask_bits (nodemask);
224
+ os_memory_provider_params.nodemask = nodemask->maskp ;
225
+ os_memory_provider_params.numa_mode = UMF_NUMA_MODE_INTERLEAVE;
226
+ initOsProvider (os_memory_provider_params);
227
+
228
+ umf_result_t umf_result;
229
+ umf_result = umfMemoryProviderAlloc (os_memory_provider,
230
+ num_page * page_size, 0 , &ptr);
231
+ ASSERT_EQ (umf_result, UMF_RESULT_SUCCESS);
232
+ ASSERT_NE (ptr, nullptr );
233
+
234
+ // This pointer must point to an initialized value before retrieving a number of
235
+ // the numa node that the pointer was allocated on (calling get_mempolicy).
236
+ memset (ptr, 0xFF , num_page * page_size);
237
+
238
+ // Test where each page will be allocated.
239
+ std::vector<int > numa_nodes_numbers = get_available_numa_nodes_numbers ();
240
+ size_t index = 0 ;
241
+
242
+ for (size_t i = 0 ; i < (size_t )num_page; i++) {
243
+ if (index == (size_t )numa_nodes_numbers.size ()) {
244
+ index = 0 ;
245
+ }
246
+ ASSERT_EQ (numa_nodes_numbers[index],
247
+ retrieve_numa_node_number ((char *)ptr + page_size * i));
248
+ index++;
249
+ }
250
+
251
+ long unsigned int retrieved_nodemask_value = retrieve_nodemask (ptr);
252
+ ASSERT_EQ (retrieved_nodemask_value, *(nodemask->maskp ));
253
+ }
254
+
255
+ // Negative tests
256
+
257
+ // Test for allocation on numa node with local mode enabled when maxnode
258
+ // and nodemask are set. For the local mode the maxnode and nodemask must be an empty set.
259
+ TEST_F (testNuma, checkModeLocalIllegalArgSet) {
260
+ umf_os_memory_provider_params_t os_memory_provider_params =
261
+ UMF_OS_MEMORY_PROVIDER_PARAMS_TEST;
262
+ os_memory_provider_params.maxnode = numa_max_node ();
263
+ set_all_available_nodemask_bits (nodemask);
264
+ os_memory_provider_params.nodemask = nodemask->maskp ;
265
+ os_memory_provider_params.numa_mode = UMF_NUMA_MODE_LOCAL;
266
+ umf_result_t umf_result;
267
+ umf_result = umfMemoryProviderCreate (umfOsMemoryProviderOps (),
268
+ &os_memory_provider_params,
269
+ &os_memory_provider);
270
+ ASSERT_EQ (umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT);
271
+ ASSERT_EQ (os_memory_provider, nullptr );
272
+ }
273
+
274
+ // Test for allocation on numa node with default mode enabled when maxnode
275
+ // and nodemask are set. For the default mode the maxnode and nodemask must be an empty set.
276
+ TEST_F (testNuma, checkModeDefaultIllegalArgSet) {
277
+ umf_os_memory_provider_params_t os_memory_provider_params =
278
+ UMF_OS_MEMORY_PROVIDER_PARAMS_TEST;
279
+ os_memory_provider_params.maxnode = numa_max_node ();
280
+ set_all_available_nodemask_bits (nodemask);
281
+ os_memory_provider_params.nodemask = nodemask->maskp ;
282
+ umf_result_t umf_result;
283
+ umf_result = umfMemoryProviderCreate (umfOsMemoryProviderOps (),
284
+ &os_memory_provider_params,
285
+ &os_memory_provider);
286
+ ASSERT_EQ (umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT);
287
+ ASSERT_EQ (os_memory_provider, nullptr );
288
+ }
0 commit comments