Skip to content

Commit e63254b

Browse files
author
Damian Duy
committed
Add OS provider tests for different bind modes
1 parent 085e4ba commit e63254b

File tree

1 file changed

+179
-4
lines changed

1 file changed

+179
-4
lines changed

test/provider_os_memory_multiple_numa_nodes.cpp

Lines changed: 179 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
#include <numa.h>
88
#include <numaif.h>
9+
#include <sched.h>
910

11+
#include "test_helpers.h"
1012
#include <umf/providers/provider_os_memory.h>
1113

1214
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() {
2830
return available_numa_nodes_numbers;
2931
}
3032

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 {
3244
void SetUp() override {
3345
if (numa_available() == -1) {
3446
GTEST_SKIP() << "Test skipped, NUMA not available";
@@ -56,10 +68,22 @@ struct testNumaNodes : public testing::TestWithParam<int> {
5668
int numa_node;
5769
int ret = get_mempolicy(&numa_node, nullptr, 0, addr,
5870
MPOL_F_NODE | MPOL_F_ADDR);
59-
EXPECT_EQ(ret, 0);
71+
UT_ASSERTeq(ret, 0);
6072
return numa_node;
6173
}
6274

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+
6387
void TearDown() override {
6488
umf_result_t umf_result;
6589
if (ptr) {
@@ -82,14 +106,16 @@ struct testNumaNodes : public testing::TestWithParam<int> {
82106
umf_memory_provider_handle_t os_memory_provider = nullptr;
83107
};
84108

109+
struct testNumaOnAllNodes : testNuma, testing::WithParamInterface<int> {};
110+
85111
INSTANTIATE_TEST_SUITE_P(
86-
testNumaNodesAllocations, testNumaNodes,
112+
testNumaNodesAllocations, testNumaOnAllNodes,
87113
::testing::ValuesIn(get_available_numa_nodes_numbers()));
88114

89115
// Test for allocations on numa nodes. This test will be executed for all numa nodes
90116
// available on the system. The available nodes are returned in vector from the
91117
// get_available_numa_nodes_numbers() function and passed to test as parameters.
92-
TEST_P(testNumaNodes, checkNumaNodesAllocations) {
118+
TEST_P(testNumaOnAllNodes, checkNumaNodesAllocations) {
93119
int numa_node_number = GetParam();
94120
umf_os_memory_provider_params_t os_memory_provider_params =
95121
UMF_OS_MEMORY_PROVIDER_PARAMS_TEST;
@@ -111,3 +137,152 @@ TEST_P(testNumaNodes, checkNumaNodesAllocations) {
111137
int retrieved_numa_node_number = retrieve_numa_node_number(ptr);
112138
ASSERT_EQ(retrieved_numa_node_number, numa_node_number);
113139
}
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

Comments
 (0)