|
2 | 2 | // Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
|
3 | 3 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
4 | 4 |
|
| 5 | +#include <numa.h> |
| 6 | +#include <numaif.h> |
| 7 | +#include <sys/mman.h> |
| 8 | +#include <unordered_set> |
| 9 | + |
| 10 | +#include <umf/memspace.h> |
| 11 | + |
5 | 12 | #include "memory_target_numa.h"
|
6 | 13 | #include "memspace_fixtures.hpp"
|
7 | 14 | #include "memspace_helpers.hpp"
|
|
10 | 17 | #include "test_helpers.h"
|
11 | 18 | #include "utils_sanitizers.h"
|
12 | 19 |
|
13 |
| -#include <numa.h> |
14 |
| -#include <numaif.h> |
15 |
| -#include <umf/memspace.h> |
16 |
| -#include <unordered_set> |
17 |
| - |
18 | 20 | using umf_test::test;
|
19 | 21 |
|
20 | 22 | struct memspaceHostAllTest : ::numaNodesTest {
|
@@ -88,6 +90,69 @@ TEST_F(memspaceHostAllProviderTest, allocFree) {
|
88 | 90 | UT_ASSERTeq(ret, UMF_RESULT_SUCCESS);
|
89 | 91 | }
|
90 | 92 |
|
| 93 | +TEST_F(memspaceHostAllProviderTest, hostAllDefaults) { |
| 94 | + // This testcase checks if the allocations made using the provider with |
| 95 | + // default parameters based on default memspace (HostAll) uses the fast, |
| 96 | + // default kernel path (no mbind). |
| 97 | + |
| 98 | + umf_memspace_handle_t hMemspace = umfMemspaceHostAllGet(); |
| 99 | + UT_ASSERTne(hMemspace, nullptr); |
| 100 | + |
| 101 | + umf_memory_provider_handle_t hProvider = nullptr; |
| 102 | + umf_result_t ret = umfMemoryProviderCreateFromMemspace( |
| 103 | + umfMemspaceHostAllGet(), NULL, &hProvider); |
| 104 | + ASSERT_EQ(ret, UMF_RESULT_SUCCESS); |
| 105 | + ASSERT_NE(hProvider, nullptr); |
| 106 | + |
| 107 | + // Create single allocation using the provider. |
| 108 | + void *ptr1 = nullptr; |
| 109 | + size_t size = SIZE_4K; |
| 110 | + size_t alignment = 0; |
| 111 | + |
| 112 | + ret = umfMemoryProviderAlloc(hProvider, size, alignment, &ptr1); |
| 113 | + UT_ASSERTeq(ret, UMF_RESULT_SUCCESS); |
| 114 | + UT_ASSERTne(ptr1, nullptr); |
| 115 | + memset(ptr1, 0xFF, size); |
| 116 | + |
| 117 | + // Create single allocation using mmap |
| 118 | + void *ptr2 = mmap(nullptr, size, PROT_READ | PROT_WRITE, |
| 119 | + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
| 120 | + UT_ASSERTne(ptr2, nullptr); |
| 121 | + memset(ptr2, 0xFF, size); |
| 122 | + |
| 123 | + // Compare UMF and kernel default allocation policy |
| 124 | + struct bitmask *nodemask1 = numa_allocate_nodemask(); |
| 125 | + struct bitmask *nodemask2 = numa_allocate_nodemask(); |
| 126 | + int memMode1 = -1, memMode2 = -1; |
| 127 | + |
| 128 | + int ret2 = get_mempolicy(&memMode1, nodemask1->maskp, nodemask1->size, ptr1, |
| 129 | + MPOL_F_ADDR); |
| 130 | + UT_ASSERTeq(ret2, 0); |
| 131 | + ret2 = get_mempolicy(&memMode2, nodemask2->maskp, nodemask2->size, ptr2, |
| 132 | + MPOL_F_ADDR); |
| 133 | + UT_ASSERTeq(ret2, 0); |
| 134 | + UT_ASSERTeq(memMode1, memMode2); |
| 135 | + UT_ASSERTeq(nodemask1->size, nodemask2->size); |
| 136 | + UT_ASSERTeq(numa_bitmask_equal(nodemask1, nodemask2), 1); |
| 137 | + |
| 138 | + int nodeId1 = -1, nodeId2 = -1; |
| 139 | + ret2 = get_mempolicy(&nodeId1, nullptr, 0, ptr1, MPOL_F_ADDR | MPOL_F_NODE); |
| 140 | + UT_ASSERTeq(ret2, 0); |
| 141 | + ret2 = get_mempolicy(&nodeId2, nullptr, 0, ptr2, MPOL_F_ADDR | MPOL_F_NODE); |
| 142 | + UT_ASSERTeq(ret2, 0); |
| 143 | + UT_ASSERTeq(nodeId1, nodeId2); |
| 144 | + |
| 145 | + numa_free_nodemask(nodemask2); |
| 146 | + numa_free_nodemask(nodemask1); |
| 147 | + |
| 148 | + ret2 = munmap(ptr2, size); |
| 149 | + UT_ASSERTeq(ret2, 0); |
| 150 | + |
| 151 | + ret = umfMemoryProviderFree(hProvider, ptr1, size); |
| 152 | + UT_ASSERTeq(ret, UMF_RESULT_SUCCESS); |
| 153 | + umfMemoryProviderDestroy(hProvider); |
| 154 | +} |
| 155 | + |
91 | 156 | TEST_F(memspaceHostAllProviderTest, allocsSpreadAcrossAllNumaNodes) {
|
92 | 157 | // This testcase is unsuitable for TSan.
|
93 | 158 | #ifdef __SANITIZE_THREAD__
|
@@ -141,17 +206,11 @@ TEST_F(memspaceHostAllProviderTest, allocsSpreadAcrossAllNumaNodes) {
|
141 | 206 | size_t allocNodeId = SIZE_MAX;
|
142 | 207 | getAllocationPolicy(ptr, maxNodeId, mode, boundNodeIds, allocNodeId);
|
143 | 208 |
|
144 |
| - // 'BIND' mode specifies that the memory is bound to a set of NUMA nodes. |
145 |
| - // In case of 'HOST ALL' memspace, those set of nodes should be all |
146 |
| - // available nodes. |
147 |
| - UT_ASSERTeq(mode, MPOL_BIND); |
148 |
| - |
149 |
| - // Confirm that the memory is bound to all the nodes from 'HOST ALL' |
150 |
| - // memspace. |
151 |
| - for (auto &id : nodeIds) { |
152 |
| - auto it = std::find(boundNodeIds.begin(), boundNodeIds.end(), id); |
153 |
| - UT_ASSERT(it != boundNodeIds.end()); |
154 |
| - } |
| 209 | + // In case of 'HOST ALL' memspace, the default set of nodes (that |
| 210 | + // contains all available nodes) is used but get_mempolicy() would |
| 211 | + // return an empty set of nodes. |
| 212 | + UT_ASSERTeq(mode, MPOL_DEFAULT); |
| 213 | + UT_ASSERTeq(boundNodeIds.size(), 0); |
155 | 214 |
|
156 | 215 | // Confirm that the memory is allocated on one of the nodes in
|
157 | 216 | // 'HOST ALL' memspace.
|
|
0 commit comments