Skip to content

Commit c4f3913

Browse files
authored
Merge pull request #322 from vinser52/svinogra_optional_provider_functions
Split memory provider ops to mandatory and optional fields
2 parents 33f39be + 4d90d24 commit c4f3913

File tree

10 files changed

+351
-84
lines changed

10 files changed

+351
-84
lines changed

include/umf/memory_provider_ops.h

Lines changed: 62 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,66 @@
1616
extern "C" {
1717
#endif
1818

19+
///
20+
/// @brief This structure comprises optional function pointers used
21+
/// by corresponding umfMemoryProvider* calls. A memory provider implementation
22+
/// can keep them NULL.
23+
///
24+
typedef struct umf_memory_provider_ext_ops_t {
25+
///
26+
/// @brief Discard physical pages within the virtual memory mapping associated at the given addr
27+
/// and \p size. This call is asynchronous and may delay purging the pages indefinitely.
28+
/// @param provider pointer to the memory provider
29+
/// @param ptr beginning of the virtual memory range
30+
/// @param size size of the virtual memory range
31+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
32+
/// UMF_RESULT_ERROR_INVALID_ALIGNMENT if ptr or size is not page-aligned.
33+
/// UMF_RESULT_ERROR_NOT_SUPPORTED if operation is not supported by this provider.
34+
///
35+
umf_result_t (*purge_lazy)(void *provider, void *ptr, size_t size);
36+
37+
///
38+
/// @brief Discard physical pages within the virtual memory mapping associated at the given addr and \p size.
39+
/// This call is synchronous and if it succeeds, pages are guaranteed to be zero-filled on the next access.
40+
/// @param provider pointer to the memory provider
41+
/// @param ptr beginning of the virtual memory range
42+
/// @param size size of the virtual memory range
43+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure
44+
/// UMF_RESULT_ERROR_INVALID_ALIGNMENT if ptr or size is not page-aligned.
45+
/// UMF_RESULT_ERROR_NOT_SUPPORTED if operation is not supported by this provider.
46+
///
47+
umf_result_t (*purge_force)(void *provider, void *ptr, size_t size);
48+
49+
///
50+
/// @brief Merges two coarse grain allocations into a single allocation that
51+
/// can be managed (freed) as a whole.
52+
/// allocation_split and allocation_merge should be both set or both NULL.
53+
/// @param hProvider handle to the memory provider
54+
/// @param lowPtr pointer to the first allocation
55+
/// @param highPtr pointer to the second allocation (should be > lowPtr)
56+
/// @param totalSize size of a new merged allocation. Should be equal
57+
/// to the sum of sizes of allocations beginning at lowPtr and highPtr
58+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure
59+
///
60+
umf_result_t (*allocation_merge)(void *hProvider, void *lowPtr,
61+
void *highPtr, size_t totalSize);
62+
63+
///
64+
/// @brief Splits a coarse grain allocation into 2 adjacent allocations that
65+
/// can be managed (freed) separately.
66+
/// allocation_split and allocation_merge should be both set or both NULL.
67+
/// @param hProvider handle to the memory provider
68+
/// @param ptr pointer to the beginning of the allocation
69+
/// @param totalSize total size of the allocation to be split
70+
/// @param firstSize size of the first new allocation, second allocation
71+
// has a size equal to totalSize - firstSize
72+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure
73+
///
74+
umf_result_t (*allocation_split)(void *hProvider, void *ptr,
75+
size_t totalSize, size_t firstSize);
76+
77+
} umf_memory_provider_ext_ops_t;
78+
1979
///
2080
/// @brief This structure comprises function pointers used by corresponding
2181
/// umfMemoryProvider* calls. Each memory provider implementation should
@@ -109,30 +169,6 @@ typedef struct umf_memory_provider_ops_t {
109169
umf_result_t (*get_min_page_size)(void *provider, void *ptr,
110170
size_t *pageSize);
111171

112-
///
113-
/// @brief Discard physical pages within the virtual memory mapping associated at the given addr
114-
/// and \p size. This call is asynchronous and may delay purging the pages indefinitely.
115-
/// @param provider pointer to the memory provider
116-
/// @param ptr beginning of the virtual memory range
117-
/// @param size size of the virtual memory range
118-
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
119-
/// UMF_RESULT_ERROR_INVALID_ALIGNMENT if ptr or size is not page-aligned.
120-
/// UMF_RESULT_ERROR_NOT_SUPPORTED if operation is not supported by this provider.
121-
///
122-
umf_result_t (*purge_lazy)(void *provider, void *ptr, size_t size);
123-
124-
///
125-
/// @brief Discard physical pages within the virtual memory mapping associated at the given addr and \p size.
126-
/// This call is synchronous and if it succeeds, pages are guaranteed to be zero-filled on the next access.
127-
/// @param provider pointer to the memory provider
128-
/// @param ptr beginning of the virtual memory range
129-
/// @param size size of the virtual memory range
130-
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure
131-
/// UMF_RESULT_ERROR_INVALID_ALIGNMENT if ptr or size is not page-aligned.
132-
/// UMF_RESULT_ERROR_NOT_SUPPORTED if operation is not supported by this provider.
133-
///
134-
umf_result_t (*purge_force)(void *provider, void *ptr, size_t size);
135-
136172
///
137173
/// @brief Retrieve name of a given memory \p provider.
138174
/// @param provider pointer to the memory provider
@@ -141,30 +177,9 @@ typedef struct umf_memory_provider_ops_t {
141177
const char *(*get_name)(void *provider);
142178

143179
///
144-
/// @brief Splits a coarse grain allocation into 2 adjacent allocations that
145-
/// can be managed (freed) separately.
146-
/// @param hProvider handle to the memory provider
147-
/// @param ptr pointer to the beginning of the allocation
148-
/// @param totalSize total size of the allocation to be split
149-
/// @param firstSize size of the first new allocation, second allocation
150-
// has a size equal to totalSize - firstSize
151-
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure
180+
/// @brief Optional ops
152181
///
153-
umf_result_t (*allocation_split)(void *hProvider, void *ptr,
154-
size_t totalSize, size_t firstSize);
155-
156-
///
157-
/// @brief Merges two coarse grain allocations into a single allocation that
158-
/// can be managed (freed) as a whole.
159-
/// @param hProvider handle to the memory provider
160-
/// @param lowPtr pointer to the first allocation
161-
/// @param highPtr pointer to the second allocation (should be > lowPtr)
162-
/// @param totalSize size of a new merged allocation. Should be equal
163-
/// to the sum of sizes of allocations beginning at lowPtr and highPtr
164-
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure
165-
///
166-
umf_result_t (*allocation_merge)(void *hProvider, void *lowPtr,
167-
void *highPtr, size_t totalSize);
182+
umf_memory_provider_ext_ops_t ext;
168183
} umf_memory_provider_ops_t;
169184

170185
#ifdef __cplusplus

src/cpp_helpers.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,11 @@ template <typename T> umf_memory_provider_ops_t providerOpsBase() {
8888
UMF_ASSIGN_OP_NORETURN(ops, T, get_last_native_error);
8989
UMF_ASSIGN_OP(ops, T, get_recommended_page_size, UMF_RESULT_ERROR_UNKNOWN);
9090
UMF_ASSIGN_OP(ops, T, get_min_page_size, UMF_RESULT_ERROR_UNKNOWN);
91-
UMF_ASSIGN_OP(ops, T, purge_lazy, UMF_RESULT_ERROR_UNKNOWN);
92-
UMF_ASSIGN_OP(ops, T, purge_force, UMF_RESULT_ERROR_UNKNOWN);
9391
UMF_ASSIGN_OP(ops, T, get_name, "");
92+
UMF_ASSIGN_OP(ops.ext, T, purge_lazy, UMF_RESULT_ERROR_UNKNOWN);
93+
UMF_ASSIGN_OP(ops.ext, T, purge_force, UMF_RESULT_ERROR_UNKNOWN);
94+
UMF_ASSIGN_OP(ops.ext, T, allocation_merge, UMF_RESULT_ERROR_UNKNOWN);
95+
UMF_ASSIGN_OP(ops.ext, T, allocation_split, UMF_RESULT_ERROR_UNKNOWN);
9496
return ops;
9597
}
9698
} // namespace detail

src/memory_provider.c

Lines changed: 80 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99

1010
#include <assert.h>
11+
#include <stdbool.h>
1112
#include <stdio.h>
1213
#include <stdlib.h>
1314

@@ -24,11 +25,78 @@ typedef struct umf_memory_provider_t {
2425
void *provider_priv;
2526
} umf_memory_provider_t;
2627

28+
static umf_result_t umfDefaultPurgeLazy(void *provider, void *ptr,
29+
size_t size) {
30+
(void)provider;
31+
(void)ptr;
32+
(void)size;
33+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
34+
}
35+
36+
static umf_result_t umfDefaultPurgeForce(void *provider, void *ptr,
37+
size_t size) {
38+
(void)provider;
39+
(void)ptr;
40+
(void)size;
41+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
42+
}
43+
44+
static umf_result_t umfDefaultAllocationSplit(void *provider, void *ptr,
45+
size_t totalSize,
46+
size_t firstSize) {
47+
(void)provider;
48+
(void)ptr;
49+
(void)totalSize;
50+
(void)firstSize;
51+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
52+
}
53+
54+
static umf_result_t umfDefaultAllocationMerge(void *provider, void *lowPtr,
55+
void *highPtr, size_t totalSize) {
56+
(void)provider;
57+
(void)lowPtr;
58+
(void)highPtr;
59+
(void)totalSize;
60+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
61+
}
62+
63+
void assignOpsExtDefaults(umf_memory_provider_ops_t *ops) {
64+
if (!ops->ext.purge_lazy) {
65+
ops->ext.purge_lazy = umfDefaultPurgeLazy;
66+
}
67+
if (!ops->ext.purge_force) {
68+
ops->ext.purge_force = umfDefaultPurgeForce;
69+
}
70+
if (!ops->ext.allocation_split) {
71+
ops->ext.allocation_split = umfDefaultAllocationSplit;
72+
}
73+
if (!ops->ext.allocation_merge) {
74+
ops->ext.allocation_merge = umfDefaultAllocationMerge;
75+
}
76+
}
77+
78+
static bool validateOps(const umf_memory_provider_ops_t *ops) {
79+
// Mandatory ops should be non-NULL
80+
if (!ops->alloc || !ops->free || !ops->get_recommended_page_size ||
81+
!ops->get_min_page_size || !ops->initialize || !ops->finalize ||
82+
!ops->get_last_native_error || !ops->get_name) {
83+
return false;
84+
}
85+
86+
// allocation_split and allocation_merge should be both set or both NULL
87+
if ((ops->ext.allocation_split && !ops->ext.allocation_merge) ||
88+
(!ops->ext.allocation_split && ops->ext.allocation_merge)) {
89+
return false;
90+
}
91+
92+
return true;
93+
}
94+
2795
umf_result_t umfMemoryProviderCreate(const umf_memory_provider_ops_t *ops,
2896
void *params,
2997
umf_memory_provider_handle_t *hProvider) {
3098
libumfInit();
31-
if (!ops || !hProvider) {
99+
if (!ops || !hProvider || !validateOps(ops)) {
32100
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
33101
}
34102

@@ -42,6 +110,8 @@ umf_result_t umfMemoryProviderCreate(const umf_memory_provider_ops_t *ops,
42110

43111
provider->ops = *ops;
44112

113+
assignOpsExtDefaults(&(provider->ops));
114+
45115
void *provider_priv;
46116
umf_result_t ret = ops->initialize(params, &provider_priv);
47117
if (ret != UMF_RESULT_SUCCESS) {
@@ -119,11 +189,16 @@ umfMemoryProviderGetMinPageSize(umf_memory_provider_handle_t hProvider,
119189
return res;
120190
}
121191

192+
const char *umfMemoryProviderGetName(umf_memory_provider_handle_t hProvider) {
193+
UMF_CHECK((hProvider != NULL), NULL);
194+
return hProvider->ops.get_name(hProvider->provider_priv);
195+
}
196+
122197
umf_result_t umfMemoryProviderPurgeLazy(umf_memory_provider_handle_t hProvider,
123198
void *ptr, size_t size) {
124199
UMF_CHECK((hProvider != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
125200
umf_result_t res =
126-
hProvider->ops.purge_lazy(hProvider->provider_priv, ptr, size);
201+
hProvider->ops.ext.purge_lazy(hProvider->provider_priv, ptr, size);
127202
checkErrorAndSetLastProvider(res, hProvider);
128203
return res;
129204
}
@@ -132,16 +207,11 @@ umf_result_t umfMemoryProviderPurgeForce(umf_memory_provider_handle_t hProvider,
132207
void *ptr, size_t size) {
133208
UMF_CHECK((hProvider != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
134209
umf_result_t res =
135-
hProvider->ops.purge_force(hProvider->provider_priv, ptr, size);
210+
hProvider->ops.ext.purge_force(hProvider->provider_priv, ptr, size);
136211
checkErrorAndSetLastProvider(res, hProvider);
137212
return res;
138213
}
139214

140-
const char *umfMemoryProviderGetName(umf_memory_provider_handle_t hProvider) {
141-
UMF_CHECK((hProvider != NULL), NULL);
142-
return hProvider->ops.get_name(hProvider->provider_priv);
143-
}
144-
145215
umf_memory_provider_handle_t umfGetLastFailedMemoryProvider(void) {
146216
return *umfGetLastFailedMemoryProviderPtr();
147217
}
@@ -160,7 +230,7 @@ umfMemoryProviderAllocationSplit(umf_memory_provider_handle_t hProvider,
160230
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
161231
}
162232

163-
umf_result_t res = hProvider->ops.allocation_split(
233+
umf_result_t res = hProvider->ops.ext.allocation_split(
164234
hProvider->provider_priv, ptr, totalSize, firstSize);
165235
checkErrorAndSetLastProvider(res, hProvider);
166236
return res;
@@ -183,7 +253,7 @@ umfMemoryProviderAllocationMerge(umf_memory_provider_handle_t hProvider,
183253
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
184254
}
185255

186-
umf_result_t res = hProvider->ops.allocation_merge(
256+
umf_result_t res = hProvider->ops.ext.allocation_merge(
187257
hProvider->provider_priv, lowPtr, highPtr, totalSize);
188258
checkErrorAndSetLastProvider(res, hProvider);
189259
return res;

src/provider/provider_level_zero.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,11 @@ static struct umf_memory_provider_ops_t UMF_LEVEL_ZERO_MEMORY_PROVIDER_OPS = {
263263
.get_last_native_error = ze_memory_provider_get_last_native_error,
264264
.get_recommended_page_size = ze_memory_provider_get_recommended_page_size,
265265
.get_min_page_size = ze_memory_provider_get_min_page_size,
266-
.purge_lazy = ze_memory_provider_purge_lazy,
267-
.purge_force = ze_memory_provider_purge_force,
268266
.get_name = ze_memory_provider_get_name,
269-
.allocation_split = ze_memory_provider_allocation_split,
270-
.allocation_merge = ze_memory_provider_allocation_merge,
267+
.ext.purge_lazy = ze_memory_provider_purge_lazy,
268+
.ext.purge_force = ze_memory_provider_purge_force,
269+
.ext.allocation_merge = ze_memory_provider_allocation_merge,
270+
.ext.allocation_split = ze_memory_provider_allocation_split,
271271
};
272272

273273
umf_memory_provider_ops_t *umfLevelZeroMemoryProviderOps(void) {

src/provider/provider_os_memory.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -662,11 +662,11 @@ static umf_memory_provider_ops_t UMF_OS_MEMORY_PROVIDER_OPS = {
662662
.get_last_native_error = os_get_last_native_error,
663663
.get_recommended_page_size = os_get_recommended_page_size,
664664
.get_min_page_size = os_get_min_page_size,
665-
.purge_lazy = os_purge_lazy,
666-
.purge_force = os_purge_force,
667665
.get_name = os_get_name,
668-
.allocation_split = os_allocation_split,
669-
.allocation_merge = os_allocation_merge};
666+
.ext.purge_lazy = os_purge_lazy,
667+
.ext.purge_force = os_purge_force,
668+
.ext.allocation_merge = os_allocation_merge,
669+
.ext.allocation_split = os_allocation_split};
670670

671671
umf_memory_provider_ops_t *umfOsMemoryProviderOps(void) {
672672
return &UMF_OS_MEMORY_PROVIDER_OPS;

src/provider/provider_tracking.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -438,11 +438,11 @@ umf_memory_provider_ops_t UMF_TRACKING_MEMORY_PROVIDER_OPS = {
438438
.get_last_native_error = trackingGetLastError,
439439
.get_min_page_size = trackingGetMinPageSize,
440440
.get_recommended_page_size = trackingGetRecommendedPageSize,
441-
.purge_force = trackingPurgeForce,
442-
.purge_lazy = trackingPurgeLazy,
443441
.get_name = trackingName,
444-
.allocation_split = trackingAllocationSplit,
445-
.allocation_merge = trackingAllocationMerge};
442+
.ext.purge_force = trackingPurgeForce,
443+
.ext.purge_lazy = trackingPurgeLazy,
444+
.ext.allocation_split = trackingAllocationSplit,
445+
.ext.allocation_merge = trackingAllocationMerge};
446446

447447
umf_result_t umfTrackingMemoryProviderCreate(
448448
umf_memory_provider_handle_t hUpstream, umf_memory_pool_handle_t hPool,

test/common/provider.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ typedef struct provider_base_t {
5252
[[maybe_unused]] size_t *pageSize) noexcept {
5353
return UMF_RESULT_ERROR_UNKNOWN;
5454
}
55+
const char *get_name() noexcept { return "base"; }
5556
umf_result_t purge_lazy([[maybe_unused]] void *ptr,
5657
[[maybe_unused]] size_t size) noexcept {
5758
return UMF_RESULT_ERROR_UNKNOWN;
@@ -60,7 +61,18 @@ typedef struct provider_base_t {
6061
[[maybe_unused]] size_t size) noexcept {
6162
return UMF_RESULT_ERROR_UNKNOWN;
6263
}
63-
const char *get_name() noexcept { return "base"; }
64+
65+
umf_result_t allocation_merge([[maybe_unused]] void *lowPtr,
66+
[[maybe_unused]] void *highPtr,
67+
[[maybe_unused]] size_t totalSize) {
68+
return UMF_RESULT_ERROR_UNKNOWN;
69+
}
70+
71+
umf_result_t allocation_split([[maybe_unused]] void *ptr,
72+
[[maybe_unused]] size_t totalSize,
73+
[[maybe_unused]] size_t firstSize) {
74+
return UMF_RESULT_ERROR_UNKNOWN;
75+
}
6476
} provider_base_t;
6577

6678
umf_memory_provider_ops_t BASE_PROVIDER_OPS =

0 commit comments

Comments
 (0)