Skip to content

Commit 4dee8a2

Browse files
committed
x
1 parent b1ca59d commit 4dee8a2

22 files changed

+324
-28
lines changed

include/umf/memory_pool.h

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

193+
///
194+
/// @brief Trims memory pool to keep at least \p minBytesToKeep bytes of memory
195+
/// if possible.
196+
/// @param hPool specified memory pool
197+
/// @param minBytesToKeep minimum number of bytes to keep in the pool
198+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
199+
umf_result_t umfPoolTrimMemory(umf_memory_pool_handle_t hPool,
200+
size_t minBytesToKeep);
201+
193202
#ifdef __cplusplus
194203
}
195204
#endif

include/umf/memory_pool_ops.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,16 @@ typedef struct umf_memory_pool_ops_t {
161161
/// @return A constant character string representing the pool's name.
162162
///
163163
const char *(*ext_get_name)(void *pool);
164+
165+
///
166+
/// @brief Trims memory of the pool, removing resources that are not needed
167+
/// to keep the pool operational.
168+
/// @param pool pointer to the memory pool
169+
/// @param minBytesToKeep minimum number of bytes to keep in the pool if
170+
/// possible.
171+
/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
172+
///
173+
umf_result_t (*trim_memory)(void *pool, size_t minBytesToKeep);
164174
} umf_memory_pool_ops_t;
165175

166176
#ifdef __cplusplus

src/libumf.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,4 @@ EXPORTS
144144
umfJemallocPoolParamsDestroy
145145
umfJemallocPoolParamsSetNumArenas
146146
umfPoolGetName
147+
umfPoolTrimMemory

src/libumf.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,5 @@ UMF_0.12 {
144144
umfJemallocPoolParamsDestroy;
145145
umfJemallocPoolParamsSetNumArenas;
146146
umfPoolGetName;
147+
umfPoolTrimMemory;
147148
} UMF_0.11;

src/memory_pool.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
240240
}
241241

242242
umf_result_t umfPoolDestroy(umf_memory_pool_handle_t hPool) {
243+
if (hPool == NULL) {
244+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
245+
}
246+
243247
if (umf_ba_global_is_destroyed()) {
244248
return UMF_RESULT_ERROR_UNKNOWN;
245249
}
@@ -417,3 +421,13 @@ umf_result_t umfPoolGetTag(umf_memory_pool_handle_t hPool, void **tag) {
417421
utils_mutex_unlock(&hPool->lock);
418422
return UMF_RESULT_SUCCESS;
419423
}
424+
425+
umf_result_t umfPoolTrimMemory(umf_memory_pool_handle_t hPool,
426+
size_t minBytesToKeep) {
427+
UMF_CHECK((hPool != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
428+
if (hPool->ops.trim_memory == NULL) {
429+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
430+
}
431+
432+
return hPool->ops.trim_memory(hPool->pool_priv, minBytesToKeep);
433+
}

src/memory_provider.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ void assignOpsIpcDefaults(umf_memory_provider_ops_t *ops) {
165165

166166
static bool validateOps(const umf_memory_provider_ops_t *ops) {
167167
// Validate mandatory operations one by one
168+
if (ops->get_name == NULL) {
169+
LOG_ERR("missing get_name function pointer\n");
170+
return false;
171+
}
168172
CHECK_OP(ops, alloc);
169173
CHECK_OP(ops, free);
170174
CHECK_OP(ops, get_recommended_page_size);

src/pool/pool_disjoint.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,47 @@ const char *disjoint_pool_get_name(void *pool) {
10311031
return hPool->params.name;
10321032
}
10331033

1034+
umf_result_t disjoint_pool_trim_memory(void *pool, size_t minBytesToKeep) {
1035+
disjoint_pool_t *hPool = (disjoint_pool_t *)pool;
1036+
if (hPool == NULL) {
1037+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
1038+
}
1039+
1040+
for (size_t i = 0; i < hPool->buckets_num; i++) {
1041+
bucket_t *bucket = hPool->buckets[i];
1042+
utils_mutex_lock(&bucket->bucket_lock);
1043+
1044+
int skip = (int)minBytesToKeep;
1045+
1046+
// remove empty slabs from the pool
1047+
slab_list_item_t *it = NULL, *tmp = NULL;
1048+
LL_FOREACH_SAFE(bucket->available_slabs, it, tmp) {
1049+
slab_t *slab = it->val;
1050+
if (slab->num_chunks_allocated == 0) {
1051+
// skip first minBytesToKeep bytes from each bucket
1052+
if (skip > 0) {
1053+
skip -= (int)slab->slab_size;
1054+
continue;
1055+
}
1056+
1057+
// remove slab
1058+
pool_unregister_slab(hPool, slab);
1059+
DL_DELETE(bucket->available_slabs, it);
1060+
assert(bucket->available_slabs_num > 0);
1061+
bucket->available_slabs_num--;
1062+
destroy_slab(slab);
1063+
1064+
// update stats
1065+
bucket_update_stats(bucket, 0, -1);
1066+
}
1067+
}
1068+
1069+
utils_mutex_unlock(&bucket->bucket_lock);
1070+
}
1071+
1072+
return UMF_RESULT_SUCCESS;
1073+
}
1074+
10341075
static umf_memory_pool_ops_t UMF_DISJOINT_POOL_OPS = {
10351076
.version = UMF_VERSION_CURRENT,
10361077
.initialize = disjoint_pool_initialize,
@@ -1044,6 +1085,7 @@ static umf_memory_pool_ops_t UMF_DISJOINT_POOL_OPS = {
10441085
.get_last_allocation_error = disjoint_pool_get_last_allocation_error,
10451086
.ext_get_name = disjoint_pool_get_name,
10461087
.ext_ctl = disjoint_pool_ctl,
1088+
.trim_memory = disjoint_pool_trim_memory,
10471089
};
10481090

10491091
const umf_memory_pool_ops_t *umfDisjointPoolOps(void) {

src/pool/pool_jemalloc.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,28 @@ static umf_result_t op_get_last_allocation_error(void *pool) {
552552
return TLS_last_allocation_error;
553553
}
554554

555+
static const char *op_get_name(void *pool) {
556+
(void)pool; // not used
557+
return "jemalloc";
558+
}
559+
560+
static umf_result_t op_trim_memory(void *pool, size_t minBytesToKeep) {
561+
(void)minBytesToKeep; // unused - TODO?
562+
563+
jemalloc_memory_pool_t *je_pool = (jemalloc_memory_pool_t *)pool;
564+
for (size_t i = 0; i < je_pool->n_arenas; i++) {
565+
char cmd[64];
566+
unsigned arena = je_pool->arena_index[i];
567+
snprintf(cmd, sizeof(cmd), "arena.%u.purge", arena);
568+
if (je_mallctl(cmd, NULL, NULL, NULL, 0)) {
569+
LOG_ERR("Could not purge jemalloc arena %u", arena);
570+
return UMF_RESULT_ERROR_UNKNOWN;
571+
}
572+
}
573+
574+
return UMF_RESULT_SUCCESS;
575+
}
576+
555577
static umf_memory_pool_ops_t UMF_JEMALLOC_POOL_OPS = {
556578
.version = UMF_POOL_OPS_VERSION_CURRENT,
557579
.initialize = op_initialize,
@@ -563,6 +585,8 @@ static umf_memory_pool_ops_t UMF_JEMALLOC_POOL_OPS = {
563585
.malloc_usable_size = op_malloc_usable_size,
564586
.free = op_free,
565587
.get_last_allocation_error = op_get_last_allocation_error,
588+
.ext_get_name = op_get_name,
589+
.trim_memory = op_trim_memory,
566590
};
567591

568592
const umf_memory_pool_ops_t *umfJemallocPoolOps(void) {

src/pool/pool_proxy.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@ static umf_result_t proxy_get_last_allocation_error(void *pool) {
125125
return TLS_last_allocation_error;
126126
}
127127

128+
static const char *proxy_get_name(void *pool) {
129+
(void)pool; // not used
130+
return "proxy";
131+
}
132+
133+
static umf_result_t proxy_trim_memory(void *pool, size_t minBytesToKeep) {
134+
(void)pool;
135+
(void)minBytesToKeep;
136+
137+
return UMF_RESULT_SUCCESS;
138+
}
139+
128140
static umf_memory_pool_ops_t UMF_PROXY_POOL_OPS = {
129141
.version = UMF_POOL_OPS_VERSION_CURRENT,
130142
.initialize = proxy_pool_initialize,
@@ -135,7 +147,10 @@ static umf_memory_pool_ops_t UMF_PROXY_POOL_OPS = {
135147
.aligned_malloc = proxy_aligned_malloc,
136148
.malloc_usable_size = proxy_malloc_usable_size,
137149
.free = proxy_free,
138-
.get_last_allocation_error = proxy_get_last_allocation_error};
150+
.get_last_allocation_error = proxy_get_last_allocation_error,
151+
.ext_get_name = proxy_get_name,
152+
.trim_memory = proxy_trim_memory,
153+
};
139154

140155
const umf_memory_pool_ops_t *umfProxyPoolOps(void) {
141156
return &UMF_PROXY_POOL_OPS;

src/pool/pool_scalable.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@
1313
#include <stdio.h>
1414
#include <string.h>
1515

16-
#include <ctl/ctl.h>
17-
#include <memory_pool_internal.h>
1816
#include <umf/memory_pool.h>
1917
#include <umf/memory_pool_ops.h>
2018
#include <umf/memory_provider.h>
2119
#include <umf/pools/pool_scalable.h>
2220

2321
#include "base_alloc_global.h"
22+
#include "ctl/ctl.h"
2423
#include "libumf.h"
24+
#include "memory_pool_internal.h"
2525
#include "pool_scalable_internal.h"
2626
#include "utils_common.h"
2727
#include "utils_concurrency.h"
@@ -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
@@ -431,6 +432,14 @@ static const char *scalable_get_name(void *pool) {
431432
return "scalable";
432433
}
433434

435+
static umf_result_t scalable_trim_memory(void *pool, size_t minBytesToKeep) {
436+
(void)pool; // unused
437+
(void)minBytesToKeep; // unused
438+
439+
//scalable_allocation_command?
440+
return UMF_RESULT_SUCCESS;
441+
}
442+
434443
static umf_memory_pool_ops_t UMF_SCALABLE_POOL_OPS = {
435444
.version = UMF_POOL_OPS_VERSION_CURRENT,
436445
.initialize = tbb_pool_initialize,
@@ -444,6 +453,7 @@ static umf_memory_pool_ops_t UMF_SCALABLE_POOL_OPS = {
444453
.get_last_allocation_error = tbb_get_last_allocation_error,
445454
.ext_ctl = pool_ctl,
446455
.ext_get_name = scalable_get_name,
456+
.trim_memory = scalable_trim_memory,
447457
};
448458

449459
const umf_memory_pool_ops_t *umfScalablePoolOps(void) {

test/common/pool.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ typedef struct pool_base_t {
117117
umf_result_t get_last_allocation_error() noexcept {
118118
return UMF_RESULT_SUCCESS;
119119
}
120+
umf_result_t
121+
trim_memory([[maybe_unused]] size_t minBytesToKeep) noexcept {
122+
return UMF_RESULT_SUCCESS;
123+
}
120124
} pool_base_t;
121125

122126
struct malloc_pool : public pool_base_t {

test/common/pool_null.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ static umf_result_t nullGetLastStatus(void *pool) {
6666
return UMF_RESULT_SUCCESS;
6767
}
6868

69+
static const char *nullGetName(void *pool) {
70+
(void)pool; // not used
71+
return "null";
72+
}
73+
6974
umf_memory_pool_ops_t UMF_NULL_POOL_OPS = {
7075
.version = UMF_POOL_OPS_VERSION_CURRENT,
7176
.initialize = nullInitialize,
@@ -76,5 +81,6 @@ umf_memory_pool_ops_t UMF_NULL_POOL_OPS = {
7681
.aligned_malloc = nullAlignedMalloc,
7782
.malloc_usable_size = nullMallocUsableSize,
7883
.free = nullFree,
84+
.ext_get_name = nullGetName,
7985
.get_last_allocation_error = nullGetLastStatus,
8086
};

test/common/pool_trace.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ static umf_result_t traceGetLastStatus(void *pool) {
9292
return umfPoolGetLastAllocationError(trace_pool->params.hUpstreamPool);
9393
}
9494

95+
static const char *traceGetName(void *pool) {
96+
(void)pool; // not used
97+
return "trace";
98+
}
99+
95100
umf_memory_pool_ops_t UMF_TRACE_POOL_OPS = {
96101
.version = UMF_POOL_OPS_VERSION_CURRENT,
97102
.initialize = traceInitialize,
@@ -102,5 +107,6 @@ umf_memory_pool_ops_t UMF_TRACE_POOL_OPS = {
102107
.aligned_malloc = traceAlignedMalloc,
103108
.malloc_usable_size = traceMallocUsableSize,
104109
.free = traceFree,
110+
.ext_get_name = traceGetName,
105111
.get_last_allocation_error = traceGetLastStatus,
106112
};

test/common/provider.hpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ 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"; }
55+
const char *get_name(/*[[maybe_unused]] void *provider*/) noexcept {
56+
return "base";
57+
}
5658
umf_result_t ext_purge_lazy([[maybe_unused]] void *ptr,
5759
[[maybe_unused]] size_t size) noexcept {
5860
return UMF_RESULT_ERROR_UNKNOWN;
@@ -125,7 +127,9 @@ struct provider_ba_global : public provider_base_t {
125127
umf_ba_global_free(ptr);
126128
return UMF_RESULT_SUCCESS;
127129
}
128-
const char *get_name() noexcept { return "umf_ba_global"; }
130+
const char *get_name(/*[[maybe_unused]] void *provider*/) noexcept {
131+
return "umf_ba_global";
132+
}
129133
};
130134

131135
umf_memory_provider_ops_t BA_GLOBAL_PROVIDER_OPS =
@@ -150,7 +154,9 @@ struct provider_mock_out_of_mem : public provider_base_t {
150154
umf_result_t free(void *ptr, size_t size) noexcept {
151155
return helper_prov.free(ptr, size);
152156
}
153-
const char *get_name() noexcept { return "mock_out_of_mem"; }
157+
const char *get_name(/*[[maybe_unused]] void *provider*/) noexcept {
158+
return "mock_out_of_mem";
159+
}
154160
};
155161

156162
const umf_memory_provider_ops_t MOCK_OUT_OF_MEM_PROVIDER_OPS =

test/ipcAPI.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ struct provider_mock_ipc : public umf_test::provider_base_t {
4747
return ret;
4848
}
4949

50-
const char *get_name() noexcept { return "mock_ipc"; }
50+
const char *get_name(/*[[maybe_unused]] void *provider*/) noexcept {
51+
return "mock_ipc";
52+
}
5153

5254
umf_result_t ext_get_ipc_handle_size(size_t *size) noexcept {
5355
*size = sizeof(provider_ipc_data_t);

0 commit comments

Comments
 (0)