Skip to content

Commit a699662

Browse files
committed
x
1 parent b7614c3 commit a699662

18 files changed

+308
-52
lines changed

include/umf/memory_pool.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,15 @@ umf_result_t umfPoolSetTag(umf_memory_pool_handle_t hPool, void *tag,
196196
/// @return UMF_RESULT_SUCCESS on success.
197197
umf_result_t umfPoolGetTag(umf_memory_pool_handle_t hPool, void **tag);
198198

199+
///
200+
/// @brief Trims memory pool to keep at least \p minBytesToKeep bytes of memory
201+
/// if possible.
202+
/// @param hPool specified memory pool
203+
/// @param minBytesToKeep minimum number of bytes to keep in the pool
204+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
205+
umf_result_t umfPoolTrimMemory(umf_memory_pool_handle_t hPool,
206+
size_t minBytesToKeep);
207+
199208
#ifdef __cplusplus
200209
}
201210
#endif

include/umf/memory_pool_ops.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,16 @@ typedef struct umf_memory_pool_ops_t {
168168
const char *name, void *arg, size_t size,
169169
umf_ctl_query_type_t queryType, va_list args);
170170

171+
///
172+
/// @brief Trims memory of the pool, removing resources that are not needed
173+
/// to keep the pool operational.
174+
/// @param pool pointer to the memory pool
175+
/// @param minBytesToKeep minimum number of bytes to keep in the pool if
176+
/// possible.
177+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on
178+
/// failure.
179+
///
180+
umf_result_t (*ext_trim_memory)(void *pool, size_t minBytesToKeep);
171181
} umf_memory_pool_ops_t;
172182

173183
#ifdef __cplusplus

src/libumf.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,5 @@ EXPORTS
144144
umfJemallocPoolParamsDestroy
145145
umfJemallocPoolParamsSetNumArenas
146146
umfPoolGetName
147+
; Added in UMF_1.1
148+
umfPoolTrimMemory

src/libumf.map

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,7 @@ UMF_1.0 {
141141
local:
142142
*;
143143
};
144+
145+
UMF_1.1 {
146+
umfPoolTrimMemory;
147+
} UMF_1.0;

src/memory_pool.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,13 @@ umfDefaultCtlPoolHandle(void *hPool, umf_ctl_query_source_t operationType,
167167
return UMF_RESULT_ERROR_NOT_SUPPORTED;
168168
}
169169

170+
static umf_result_t umfDefaultTrimMemory(void *provider,
171+
size_t minBytesToKeep) {
172+
(void)provider;
173+
(void)minBytesToKeep;
174+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
175+
}
176+
170177
// logical sum (OR) of all umf_pool_create_flags_t flags
171178
static const umf_pool_create_flags_t UMF_POOL_CREATE_FLAG_ALL =
172179
UMF_POOL_CREATE_FLAG_OWN_PROVIDER | UMF_POOL_CREATE_FLAG_DISABLE_TRACKING;
@@ -189,9 +196,9 @@ static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
189196
const void *params,
190197
umf_pool_create_flags_t flags,
191198
umf_memory_pool_handle_t *hPool) {
192-
if (!ops || !provider || !hPool) {
193-
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
194-
}
199+
UMF_CHECK((ops != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
200+
UMF_CHECK((provider != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
201+
UMF_CHECK((hPool != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
195202

196203
// validate flags
197204
if (flags & ~UMF_POOL_CREATE_FLAG_ALL) {
@@ -234,6 +241,10 @@ static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
234241
pool->ops.ext_ctl = umfDefaultCtlPoolHandle;
235242
}
236243

244+
if (NULL == pool->ops.ext_trim_memory) {
245+
pool->ops.ext_trim_memory = umfDefaultTrimMemory;
246+
}
247+
237248
if (NULL == utils_mutex_init(&pool->lock)) {
238249
LOG_ERR("Failed to initialize mutex for pool");
239250
ret = UMF_RESULT_ERROR_UNKNOWN;
@@ -277,6 +288,8 @@ static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
277288
}
278289

279290
umf_result_t umfPoolDestroy(umf_memory_pool_handle_t hPool) {
291+
UMF_CHECK((hPool != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
292+
280293
if (umf_ba_global_is_destroyed()) {
281294
return UMF_RESULT_ERROR_UNKNOWN;
282295
}
@@ -454,3 +467,10 @@ umf_result_t umfPoolGetTag(umf_memory_pool_handle_t hPool, void **tag) {
454467
utils_mutex_unlock(&hPool->lock);
455468
return UMF_RESULT_SUCCESS;
456469
}
470+
471+
umf_result_t umfPoolTrimMemory(umf_memory_pool_handle_t hPool,
472+
size_t minBytesToKeep) {
473+
UMF_CHECK((hPool != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
474+
475+
return hPool->ops.ext_trim_memory(hPool->pool_priv, minBytesToKeep);
476+
}

src/pool/pool_disjoint.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,47 @@ static umf_result_t disjoint_pool_get_name(void *pool, const char **name) {
11331133
return UMF_RESULT_SUCCESS;
11341134
}
11351135

1136+
umf_result_t disjoint_pool_trim_memory(void *pool, size_t minBytesToKeep) {
1137+
disjoint_pool_t *hPool = (disjoint_pool_t *)pool;
1138+
if (hPool == NULL) {
1139+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
1140+
}
1141+
1142+
for (size_t i = 0; i < hPool->buckets_num; i++) {
1143+
bucket_t *bucket = hPool->buckets[i];
1144+
utils_mutex_lock(&bucket->bucket_lock);
1145+
1146+
int skip = (int)minBytesToKeep;
1147+
1148+
// remove empty slabs from the pool
1149+
slab_list_item_t *it = NULL, *tmp = NULL;
1150+
LL_FOREACH_SAFE(bucket->available_slabs, it, tmp) {
1151+
slab_t *slab = it->val;
1152+
if (slab->num_chunks_allocated == 0) {
1153+
// skip first minBytesToKeep bytes from each bucket
1154+
if (skip > 0) {
1155+
skip -= (int)slab->slab_size;
1156+
continue;
1157+
}
1158+
1159+
// remove slab
1160+
pool_unregister_slab(hPool, slab);
1161+
DL_DELETE(bucket->available_slabs, it);
1162+
assert(bucket->available_slabs_num > 0);
1163+
bucket->available_slabs_num--;
1164+
destroy_slab(slab);
1165+
1166+
// update stats
1167+
bucket_update_stats(bucket, 0, -1);
1168+
}
1169+
}
1170+
1171+
utils_mutex_unlock(&bucket->bucket_lock);
1172+
}
1173+
1174+
return UMF_RESULT_SUCCESS;
1175+
}
1176+
11361177
static umf_memory_pool_ops_t UMF_DISJOINT_POOL_OPS = {
11371178
.version = UMF_POOL_OPS_VERSION_CURRENT,
11381179
.initialize = disjoint_pool_initialize,
@@ -1146,6 +1187,7 @@ static umf_memory_pool_ops_t UMF_DISJOINT_POOL_OPS = {
11461187
.get_last_allocation_error = disjoint_pool_get_last_allocation_error,
11471188
.get_name = disjoint_pool_get_name,
11481189
.ext_ctl = disjoint_pool_ctl,
1190+
.ext_trim_memory = disjoint_pool_trim_memory,
11491191
};
11501192

11511193
const umf_memory_pool_ops_t *umfDisjointPoolOps(void) {

src/pool/pool_jemalloc.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,23 @@ static umf_result_t op_get_name(void *pool, const char **name) {
563563
return UMF_RESULT_SUCCESS;
564564
}
565565

566+
static umf_result_t op_trim_memory(void *pool, size_t minBytesToKeep) {
567+
(void)minBytesToKeep; // unused - TODO?
568+
569+
jemalloc_memory_pool_t *je_pool = (jemalloc_memory_pool_t *)pool;
570+
for (size_t i = 0; i < je_pool->n_arenas; i++) {
571+
char cmd[64];
572+
unsigned arena = je_pool->arena_index[i];
573+
snprintf(cmd, sizeof(cmd), "arena.%u.purge", arena);
574+
if (je_mallctl(cmd, NULL, NULL, NULL, 0)) {
575+
LOG_ERR("Could not purge jemalloc arena %u", arena);
576+
return UMF_RESULT_ERROR_UNKNOWN;
577+
}
578+
}
579+
580+
return UMF_RESULT_SUCCESS;
581+
}
582+
566583
static umf_memory_pool_ops_t UMF_JEMALLOC_POOL_OPS = {
567584
.version = UMF_POOL_OPS_VERSION_CURRENT,
568585
.initialize = op_initialize,
@@ -575,6 +592,7 @@ static umf_memory_pool_ops_t UMF_JEMALLOC_POOL_OPS = {
575592
.free = op_free,
576593
.get_last_allocation_error = op_get_last_allocation_error,
577594
.get_name = op_get_name,
595+
.ext_trim_memory = op_trim_memory,
578596
};
579597

580598
const umf_memory_pool_ops_t *umfJemallocPoolOps(void) {

src/pool/pool_proxy.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,14 @@ static umf_result_t proxy_get_name(void *pool, const char **name) {
136136
return UMF_RESULT_SUCCESS;
137137
}
138138

139+
// TODO remove if na
140+
static umf_result_t proxy_trim_memory(void *pool, size_t minBytesToKeep) {
141+
(void)pool;
142+
(void)minBytesToKeep;
143+
144+
return UMF_RESULT_SUCCESS;
145+
}
146+
139147
static umf_memory_pool_ops_t UMF_PROXY_POOL_OPS = {
140148
.version = UMF_POOL_OPS_VERSION_CURRENT,
141149
.initialize = proxy_pool_initialize,
@@ -147,7 +155,9 @@ static umf_memory_pool_ops_t UMF_PROXY_POOL_OPS = {
147155
.malloc_usable_size = proxy_malloc_usable_size,
148156
.free = proxy_free,
149157
.get_last_allocation_error = proxy_get_last_allocation_error,
150-
.get_name = proxy_get_name};
158+
.get_name = proxy_get_name,
159+
.ext_trim_memory = proxy_trim_memory,
160+
};
151161

152162
const umf_memory_pool_ops_t *umfProxyPoolOps(void) {
153163
return &UMF_PROXY_POOL_OPS;

src/pool/pool_scalable.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ typedef struct tbb_callbacks_t {
6060
bool (*pool_destroy)(void *);
6161
void *(*pool_identify)(void *object);
6262
size_t (*pool_msize)(void *, void *);
63+
int (*pool_allocation_command)(int, void *);
6364
#ifdef _WIN32
6465
HMODULE lib_handle;
6566
#else
@@ -422,12 +423,14 @@ static umf_result_t tbb_get_last_allocation_error(void *pool) {
422423
return TLS_last_allocation_error;
423424
}
424425

426+
static void initialize_pool_ctl(void) {}
427+
425428
static umf_result_t pool_ctl(void *hPool, umf_ctl_query_source_t operationType,
426429
const char *name, void *arg, size_t size,
427430
umf_ctl_query_type_t query_type, va_list args) {
428431
(void)operationType; // unused
429432
umf_memory_pool_handle_t pool_provider = (umf_memory_pool_handle_t)hPool;
430-
utils_init_once(&ctl_initialized, NULL);
433+
utils_init_once(&ctl_initialized, initialize_pool_ctl);
431434
return ctl_query(&pool_scallable_ctl_root, pool_provider->pool_priv,
432435
CTL_QUERY_PROGRAMMATIC, name, query_type, arg, size, args);
433436
}
@@ -438,6 +441,15 @@ static umf_result_t scalable_get_name(void *pool, const char **name) {
438441
return UMF_RESULT_SUCCESS;
439442
}
440443

444+
// TODO remove if na
445+
static umf_result_t scalable_trim_memory(void *pool, size_t minBytesToKeep) {
446+
(void)pool; // unused
447+
(void)minBytesToKeep; // unused
448+
449+
//scalable_allocation_command?
450+
return UMF_RESULT_SUCCESS;
451+
}
452+
441453
static umf_memory_pool_ops_t UMF_SCALABLE_POOL_OPS = {
442454
.version = UMF_POOL_OPS_VERSION_CURRENT,
443455
.initialize = tbb_pool_initialize,
@@ -451,6 +463,7 @@ static umf_memory_pool_ops_t UMF_SCALABLE_POOL_OPS = {
451463
.get_last_allocation_error = tbb_get_last_allocation_error,
452464
.ext_ctl = pool_ctl,
453465
.get_name = scalable_get_name,
466+
.ext_trim_memory = scalable_trim_memory,
454467
};
455468

456469
const umf_memory_pool_ops_t *umfScalablePoolOps(void) {

src/provider/provider_tracking.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ umf_result_t umfMemoryTrackerGetAllocInfo(const void *ptr,
472472
umf_alloc_info_t *pAllocInfo) {
473473
assert(pAllocInfo);
474474

475+
// TODO unlikely
475476
if (ptr == NULL) {
476477
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
477478
}

0 commit comments

Comments
 (0)