Skip to content

Commit e4b8a75

Browse files
authored
Merge pull request #140 from igchor/jemalloc_fixes_and_provider_funcs
Implement umfMemoryProviderAllocation[Split/Merge]
2 parents 09e5b81 + 3caed7c commit e4b8a75

11 files changed

+356
-31
lines changed

include/umf/memory_provider.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,34 @@ umfMemoryProviderGetName(umf_memory_provider_handle_t hProvider);
156156
///
157157
UMF_EXPORT umf_memory_provider_handle_t umfGetLastFailedMemoryProvider(void);
158158

159+
///
160+
/// @brief Splits a coarse grain allocation into 2 adjacent allocations that
161+
/// can be managed (freed) separately.
162+
/// @param hProvider handle to the memory provider
163+
/// @param ptr pointer to the beginning of the allocation
164+
/// @param totalSize total size of the allocation to be split
165+
/// @param firstSize size of the first new allocation, second allocation
166+
// has a size equal to totalSize - firstSize
167+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure
168+
///
169+
UMF_EXPORT umf_result_t
170+
umfMemoryProviderAllocationSplit(umf_memory_provider_handle_t hProvider,
171+
void *ptr, size_t totalSize, size_t firstSize);
172+
173+
///
174+
/// @brief Merges two coarse grain allocations into a single allocation that
175+
/// can be managed (freed) as a whole.
176+
/// @param hProvider handle to the memory provider
177+
/// @param lowPtr pointer to the first allocation
178+
/// @param highPtr pointer to the second allocation (should be > lowPtr)
179+
/// @param totalSize size of a new merged allocation. Should be equal
180+
/// to the sum of sizes of allocations beginning at lowPtr and highPtr
181+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure
182+
///
183+
UMF_EXPORT umf_result_t
184+
umfMemoryProviderAllocationMerge(umf_memory_provider_handle_t hProvider,
185+
void *lowPtr, void *highPtr, size_t totalSize);
186+
159187
#ifdef __cplusplus
160188
}
161189
#endif

include/umf/memory_provider_ops.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,32 @@ typedef struct umf_memory_provider_ops_t {
139139
/// @return pointer to a string containing the name of the \p provider
140140
///
141141
const char *(*get_name)(void *provider);
142+
143+
///
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
152+
///
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);
142168
} umf_memory_provider_ops_t;
143169

144170
#ifdef __cplusplus

src/memory_provider.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <umf/memory_provider.h>
1212

1313
#include <assert.h>
14+
#include <stdio.h>
1415
#include <stdlib.h>
1516

1617
typedef struct umf_memory_provider_t {
@@ -129,3 +130,46 @@ const char *umfMemoryProviderGetName(umf_memory_provider_handle_t hProvider) {
129130
umf_memory_provider_handle_t umfGetLastFailedMemoryProvider(void) {
130131
return *umfGetLastFailedMemoryProviderPtr();
131132
}
133+
134+
umf_result_t
135+
umfMemoryProviderAllocationSplit(umf_memory_provider_handle_t hProvider,
136+
void *ptr, size_t totalSize,
137+
size_t firstSize) {
138+
if (!ptr) {
139+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
140+
}
141+
if (firstSize == 0 || totalSize == 0) {
142+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
143+
}
144+
if (firstSize >= totalSize) {
145+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
146+
}
147+
148+
umf_result_t res = hProvider->ops.allocation_split(
149+
hProvider->provider_priv, ptr, totalSize, firstSize);
150+
checkErrorAndSetLastProvider(res, hProvider);
151+
return res;
152+
}
153+
154+
umf_result_t
155+
umfMemoryProviderAllocationMerge(umf_memory_provider_handle_t hProvider,
156+
void *lowPtr, void *highPtr,
157+
size_t totalSize) {
158+
if (!lowPtr || !highPtr) {
159+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
160+
}
161+
if (totalSize == 0) {
162+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
163+
}
164+
if ((uintptr_t)lowPtr >= (uintptr_t)highPtr) {
165+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
166+
}
167+
if ((uintptr_t)highPtr - (uintptr_t)lowPtr > totalSize) {
168+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
169+
}
170+
171+
umf_result_t res = hProvider->ops.allocation_merge(
172+
hProvider->provider_priv, lowPtr, highPtr, totalSize);
173+
checkErrorAndSetLastProvider(res, hProvider);
174+
return res;
175+
}

src/pool/pool_jemalloc.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,15 @@ static bool arena_extent_split(extent_hooks_t *extent_hooks, void *addr,
215215
size_t size, size_t size_a, size_t size_b,
216216
bool committed, unsigned arena_ind) {
217217
(void)extent_hooks; // unused
218-
(void)addr; // unused
219-
(void)size; // unused
220-
(void)size_a; // unused
221-
(void)size_b; // unused
222218
(void)committed; // unused
223-
(void)arena_ind; // unused
219+
(void)size_b;
224220

225-
// TODO: add this function to the provider API to support Windows and USM
226-
return true; // true means failure (unsupported)
221+
assert(size_a + size_b == size);
222+
223+
jemalloc_memory_pool_t *pool = get_pool_by_arena_index(arena_ind);
224+
assert(pool);
225+
return umfMemoryProviderAllocationSplit(pool->provider, addr, size,
226+
size_a) != UMF_RESULT_SUCCESS;
227227
}
228228

229229
// arena_extent_merge - an extent merge function conforms to the extent_merge_t type and optionally
@@ -236,15 +236,13 @@ static bool arena_extent_merge(extent_hooks_t *extent_hooks, void *addr_a,
236236
size_t size_a, void *addr_b, size_t size_b,
237237
bool committed, unsigned arena_ind) {
238238
(void)extent_hooks; // unused
239-
(void)addr_a; // unused
240-
(void)addr_b; // unused
241-
(void)size_a; // unused
242-
(void)size_b; // unused
243239
(void)committed; // unused
244-
(void)arena_ind; // unused
245240

246-
// TODO: add this function to the provider API to support Windows and USM
247-
return true; // true means failure (unsupported)
241+
jemalloc_memory_pool_t *pool = get_pool_by_arena_index(arena_ind);
242+
assert(pool);
243+
return umfMemoryProviderAllocationMerge(pool->provider, addr_a, addr_b,
244+
size_a + size_b) !=
245+
UMF_RESULT_SUCCESS;
248246
}
249247

250248
// The extent_hooks_t structure comprises function pointers which are described individually below.

src/pool/pool_scalable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ static void tbb_raw_free_wrapper(intptr_t pool_id, void *ptr, size_t bytes) {
122122
TLS_last_free_error = ret;
123123
fprintf(
124124
stderr,
125-
"Memory provider failed to free memory, addr = %p, size = %lu\n",
125+
"Memory provider failed to free memory, addr = %p, size = %zu\n",
126126
ptr, bytes);
127127
}
128128
}

src/provider/provider_os_memory.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,26 @@ static const char *os_get_name(void *provider) {
449449
return "OS";
450450
}
451451

452+
static umf_result_t os_allocation_split(void *provider, void *ptr,
453+
size_t totalSize, size_t firstSize) {
454+
(void)provider;
455+
(void)ptr;
456+
(void)totalSize;
457+
(void)firstSize;
458+
// nop
459+
return UMF_RESULT_SUCCESS;
460+
}
461+
462+
static umf_result_t os_allocation_merge(void *provider, void *lowPtr,
463+
void *highPtr, size_t totalSize) {
464+
(void)provider;
465+
(void)lowPtr;
466+
(void)highPtr;
467+
(void)totalSize;
468+
// nop
469+
return UMF_RESULT_SUCCESS;
470+
}
471+
452472
umf_memory_provider_ops_t UMF_OS_MEMORY_PROVIDER_OPS = {
453473
.version = UMF_VERSION_CURRENT,
454474
.initialize = os_initialize,
@@ -461,4 +481,5 @@ umf_memory_provider_ops_t UMF_OS_MEMORY_PROVIDER_OPS = {
461481
.purge_lazy = os_purge_lazy,
462482
.purge_force = os_purge_force,
463483
.get_name = os_get_name,
464-
};
484+
.allocation_split = os_allocation_split,
485+
.allocation_merge = os_allocation_merge};

0 commit comments

Comments
 (0)