Skip to content

Commit f2b784a

Browse files
authored
Merge pull request #232 from igchor/os_provider_docs
Add documentation to OS provider
2 parents 7043b59 + 2e25a3a commit f2b784a

File tree

4 files changed

+83
-26
lines changed

4 files changed

+83
-26
lines changed

include/umf/providers/provider_os_memory.h

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,47 +16,57 @@ extern "C" {
1616

1717
#define UMF_OS_RESULTS_START_FROM 1000
1818

19+
/// @brief Protection of the memory allocations
1920
typedef enum umf_mem_protection_flags_t {
20-
UMF_PROTECTION_NONE = (1 << 0),
21-
UMF_PROTECTION_READ = (1 << 1),
22-
UMF_PROTECTION_WRITE = (1 << 2),
23-
UMF_PROTECTION_EXEC = (1 << 3),
21+
UMF_PROTECTION_NONE = (1 << 0), ///< Memory allocations can not be accessed
22+
UMF_PROTECTION_READ = (1 << 1), ///< Memory allocations can be read.
23+
UMF_PROTECTION_WRITE = (1 << 2), ///< Memory allocations can be written.
24+
UMF_PROTECTION_EXEC = (1 << 3), ///< Memory allocations can be executed.
2425

2526
UMF_PROTECTION_MAX // must be the last one
2627
} umf_mem_protection_flags_t;
2728

29+
/// @brief Visibility of the memory allocations
2830
typedef enum umf_mem_visibility_t {
29-
UMF_VISIBILITY_SHARED,
30-
UMF_VISIBILITY_PRIVATE,
31+
UMF_VISIBILITY_SHARED, ///< Updates to the memory allocated using OS provider are visible to other processes.
32+
/// TODO: need to expose functionality to share open the mapping in other process and explicit sync?
33+
UMF_VISIBILITY_PRIVATE, ///< Updates to the memory allocated using OS provider are not visible to other processes.
3134
} umf_mem_visibility_t;
3235

36+
/// @brief Memory binding mode
37+
///
38+
/// Specifies how memory is bound to NUMA nodes on systems that support NUMA.
39+
/// Not every mode is supported on every system.
3340
typedef enum umf_numa_mode_t {
34-
UMF_NUMA_MODE_DEFAULT,
35-
UMF_NUMA_MODE_BIND,
36-
UMF_NUMA_MODE_INTERLEAVE,
37-
UMF_NUMA_MODE_PREFERRED,
38-
UMF_NUMA_MODE_LOCAL,
41+
UMF_NUMA_MODE_DEFAULT, ///< Default binding mode. Actual binding policy is system-specific.
42+
/// On linux this corresponds to MPOL_DEFAULT. If this mode is specified,
43+
/// nodemask must be NULL and maxnode must be 0.
44+
UMF_NUMA_MODE_BIND, ///< Restricts memory allocation to nodes specified in nodemask. Allocations
45+
/// might come from any of the allowed nodes. Nodemask must specify at least one node.
46+
UMF_NUMA_MODE_INTERLEAVE, ///< Interleaves memory allocations across the set of nodes specified in nodemask.
47+
/// Nodemask must specify at least one node.
48+
UMF_NUMA_MODE_PREFERRED, ///< Specifies preferred node for allocation. If allocation cannot be fulfilled,
49+
/// memory will be allocated from other nodes.
50+
UMF_NUMA_MODE_LOCAL, ///< The memory is allocated on the node of the CPU that triggered the allocation.
51+
/// If this mode is specified, nodemask must be NULL and maxnode must be 0.
52+
/// TODO: should this be a hint or strict policy?
3953
} umf_numa_mode_t;
4054

41-
typedef enum umf_purge_advise_t {
42-
UMF_PURGE_LAZY,
43-
UMF_PURGE_FORCE,
44-
} umf_purge_advise_t;
45-
4655
/// @brief Memory provider settings struct
4756
typedef struct umf_os_memory_provider_params_t {
4857
/// combination of 'umf_mem_protection_flags_t' flags
4958
unsigned protection;
59+
5060
/// shared or private visibility of memory mapped by a provider
51-
/// sets MAP_SHARED and MAP_PRIVATE flags respectively on internal mmap() calls
5261
umf_mem_visibility_t visibility;
5362

5463
// NUMA config
55-
/// nodemask used in internal mbind() calls
64+
/// points to a bit mask of nodes containing up to maxnode bits, depending on
65+
/// selected numa_mode newly allocated memory will be bound to those nodes
5666
unsigned long *nodemask;
57-
/// maximum number of nodes in \p nodemask
67+
/// max number of bits in nodemask
5868
unsigned long maxnode;
59-
/// flag that relates to one of the MPOL_* flags used in internal mbind() calls
69+
/// describes how nodemask is interpreted
6070
umf_numa_mode_t numa_mode;
6171

6272
// others

src/provider/provider_os_memory.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,16 @@ static hwloc_membind_policy_t translate_numa_mode(umf_numa_mode_t mode,
154154
}
155155
return HWLOC_MEMBIND_DEFAULT;
156156
case UMF_NUMA_MODE_BIND:
157+
if (nodemaskEmpty) {
158+
// nodeset must not be empty
159+
return -1;
160+
}
157161
return HWLOC_MEMBIND_BIND;
158162
case UMF_NUMA_MODE_INTERLEAVE:
163+
if (nodemaskEmpty) {
164+
// nodeset must not be empty
165+
return -1;
166+
}
159167
return HWLOC_MEMBIND_INTERLEAVE;
160168
case UMF_NUMA_MODE_PREFERRED:
161169
return HWLOC_MEMBIND_BIND;

src/provider/provider_os_memory_internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
extern "C" {
1616
#endif
1717

18+
typedef enum umf_purge_advise_t {
19+
UMF_PURGE_LAZY,
20+
UMF_PURGE_FORCE,
21+
} umf_purge_advise_t;
22+
1823
int os_translate_flags(unsigned in_flags, unsigned max,
1924
int (*translate_flag)(unsigned));
2025

test/provider_os_memory.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,55 @@ static void test_alloc_failure(umf_memory_provider_handle_t provider,
127127

128128
// negative tests for umfMemoryProviderCreate()
129129

130-
TEST_F(test, create_WRONG_NUMA_MODE) {
130+
static umf_result_t create_os_provider_with_mode(umf_numa_mode_t mode,
131+
unsigned long *nodemask,
132+
unsigned long maxnode) {
131133
umf_result_t umf_result;
132134
umf_memory_provider_handle_t os_memory_provider = nullptr;
133135
umf_os_memory_provider_params_t os_memory_provider_params =
134136
umfOsMemoryProviderParamsDefault();
135137

136-
// NUMA binding mode not supported for UMF_VISIBILITY_SHARED
137-
os_memory_provider_params.visibility = UMF_VISIBILITY_SHARED;
138-
os_memory_provider_params.numa_mode = UMF_NUMA_MODE_BIND;
138+
os_memory_provider_params.numa_mode = mode;
139+
os_memory_provider_params.nodemask = nodemask;
140+
os_memory_provider_params.maxnode = maxnode;
139141

140142
umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(),
141143
&os_memory_provider_params,
142144
&os_memory_provider);
143-
ASSERT_EQ(umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT);
144-
ASSERT_EQ(os_memory_provider, nullptr);
145+
if (umf_result == UMF_RESULT_SUCCESS) {
146+
EXPECT_NE(os_memory_provider, nullptr);
147+
umfMemoryProviderDestroy(os_memory_provider);
148+
} else {
149+
EXPECT_EQ(os_memory_provider, nullptr);
150+
}
151+
152+
return umf_result;
153+
}
154+
155+
static unsigned long valid_nodemask = 0x1;
156+
static unsigned long valid_maxnode = 2;
157+
158+
TEST_F(test, create_WRONG_NUMA_MODE_DEFAULT) {
159+
auto ret = create_os_provider_with_mode(UMF_NUMA_MODE_DEFAULT,
160+
&valid_nodemask, valid_maxnode);
161+
ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT);
162+
}
163+
164+
TEST_F(test, create_WRONG_NUMA_MODE_LOCAL) {
165+
auto ret = create_os_provider_with_mode(UMF_NUMA_MODE_LOCAL,
166+
&valid_nodemask, valid_maxnode);
167+
ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT);
168+
}
169+
170+
TEST_F(test, create_WRONG_NUMA_MODE_BIND) {
171+
auto ret = create_os_provider_with_mode(UMF_NUMA_MODE_BIND, nullptr, 0);
172+
ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT);
173+
}
174+
175+
TEST_F(test, create_WRONG_NUMA_MODE_INTERLEAVE) {
176+
auto ret =
177+
create_os_provider_with_mode(UMF_NUMA_MODE_INTERLEAVE, nullptr, 0);
178+
ASSERT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT);
145179
}
146180

147181
// positive tests using test_alloc_free_success

0 commit comments

Comments
 (0)