Skip to content

Commit 0620d6e

Browse files
committed
Add callback for freeing a leaf
Signed-off-by: Lukasz Dorau <[email protected]>
1 parent 6b3a124 commit 0620d6e

File tree

6 files changed

+56
-18
lines changed

6 files changed

+56
-18
lines changed

src/critnib/critnib.c

+16-1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ struct critnib_leaf {
120120

121121
struct critnib {
122122
struct critnib_node *root;
123+
free_leaf_t cb_free_leaf; // callback for freeing a leaf
124+
void *leaf_allocator; // handle of allocator for leaves
123125

124126
/* pool of freed nodes: singly linked list, next at child[0] */
125127
struct critnib_node *deleted_node;
@@ -162,7 +164,7 @@ static inline unsigned slice_index(word key, sh_t shift) {
162164
/*
163165
* critnib_new -- allocates a new critnib structure
164166
*/
165-
struct critnib *critnib_new(void) {
167+
struct critnib *critnib_new(void *leaf_allocator, free_leaf_t cb_free_leaf) {
166168
struct critnib *c = umf_ba_global_alloc(sizeof(struct critnib));
167169
if (!c) {
168170
return NULL;
@@ -175,6 +177,8 @@ struct critnib *critnib_new(void) {
175177
goto err_free_critnib;
176178
}
177179

180+
c->leaf_allocator = leaf_allocator;
181+
c->cb_free_leaf = cb_free_leaf;
178182
utils_annotate_memory_no_check(&c->root, sizeof(c->root));
179183
utils_annotate_memory_no_check(&c->remove_count, sizeof(c->remove_count));
180184

@@ -189,6 +193,9 @@ struct critnib *critnib_new(void) {
189193
*/
190194
static void delete_node(struct critnib *c, struct critnib_node *__restrict n) {
191195
if (is_leaf(n)) {
196+
if (c->cb_free_leaf && to_leaf(n)) {
197+
c->cb_free_leaf(c->leaf_allocator, (void *)to_leaf(n)->value);
198+
}
192199
umf_ba_global_free(to_leaf(n));
193200
} else {
194201
for (int i = 0; i < SLNODES; i++) {
@@ -225,6 +232,10 @@ void critnib_delete(struct critnib *c) {
225232

226233
for (int i = 0; i < DELETED_LIFE; i++) {
227234
umf_ba_global_free(c->pending_del_nodes[i]);
235+
if (c->cb_free_leaf && c->pending_del_leaves[i]) {
236+
c->cb_free_leaf(c->leaf_allocator,
237+
(void *)c->pending_del_leaves[i]->value);
238+
}
228239
umf_ba_global_free(c->pending_del_leaves[i]);
229240
}
230241

@@ -277,6 +288,10 @@ static void free_leaf(struct critnib *__restrict c,
277288
return;
278289
}
279290

291+
if (c->cb_free_leaf && k) {
292+
c->cb_free_leaf(c->leaf_allocator, (void *)k->value);
293+
}
294+
280295
utils_atomic_store_release_ptr((void **)&k->value, c->deleted_leaf);
281296
utils_atomic_store_release_ptr((void **)&c->deleted_leaf, k);
282297
}

src/critnib/critnib.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2023-2024 Intel Corporation
3+
* Copyright (C) 2023-2025 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -18,6 +18,7 @@ extern "C" {
1818

1919
struct critnib;
2020
typedef struct critnib critnib;
21+
typedef void (*free_leaf_t)(void *leaf_allocator, void *ptr);
2122

2223
enum find_dir_t {
2324
FIND_L = -2,
@@ -27,7 +28,7 @@ enum find_dir_t {
2728
FIND_G = +2,
2829
};
2930

30-
critnib *critnib_new(void);
31+
critnib *critnib_new(void *leaf_allocator, free_leaf_t cb_free_leaf);
3132
void critnib_delete(critnib *c);
3233

3334
int critnib_insert(critnib *c, uintptr_t key, void *value, int update);

src/pool/pool_disjoint.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ umf_result_t disjoint_pool_initialize(umf_memory_provider_handle_t provider,
597597
disjoint_pool->provider = provider;
598598
disjoint_pool->params = *dp_params;
599599

600-
disjoint_pool->known_slabs = critnib_new();
600+
disjoint_pool->known_slabs = critnib_new(NULL, NULL);
601601
if (disjoint_pool->known_slabs == NULL) {
602602
goto err_free_disjoint_pool;
603603
}

src/provider/provider_file_memory.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -274,14 +274,14 @@ static umf_result_t file_initialize(const void *params, void **provider) {
274274
goto err_coarse_delete;
275275
}
276276

277-
file_provider->fd_offset_map = critnib_new();
277+
file_provider->fd_offset_map = critnib_new(NULL, NULL);
278278
if (!file_provider->fd_offset_map) {
279279
LOG_ERR("creating the map of file descriptor offsets failed");
280280
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
281281
goto err_mutex_destroy_not_free;
282282
}
283283

284-
file_provider->mmaps = critnib_new();
284+
file_provider->mmaps = critnib_new(NULL, NULL);
285285
if (!file_provider->mmaps) {
286286
LOG_ERR("creating the map of memory mappings failed");
287287
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;

src/provider/provider_os_memory.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ static umf_result_t os_initialize(const void *params, void **provider) {
647647
goto err_destroy_hwloc_topology;
648648
}
649649

650-
os_provider->fd_offset_map = critnib_new();
650+
os_provider->fd_offset_map = critnib_new(NULL, NULL);
651651
if (!os_provider->fd_offset_map) {
652652
LOG_ERR("creating file descriptor offset map failed");
653653
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;

src/provider/provider_tracking.c

+33-11
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,19 @@ static umf_result_t umfMemoryTrackerAdd(umf_memory_tracker_handle_t hTracker,
201201

202202
utils_atomic_load_acquire_u64((uint64_t *)&rvalue->size, &rsize);
203203

204+
// size == 0 means that the entry was removed
205+
if (rsize == 0) {
206+
// restart the search
207+
parent_value = NULL;
208+
rvalue = NULL;
209+
parent_key = 0;
210+
rkey = 0;
211+
rsize = 0;
212+
level = 0;
213+
found = 0;
214+
continue;
215+
}
216+
204217
if ((uintptr_t)ptr < rkey + rsize) {
205218
if (level == MAX_LEVELS_OF_ALLOC_SEGMENT_MAP - 1) {
206219
// TODO: we need to support an arbitrary amount of layers in the future
@@ -254,14 +267,17 @@ static umf_result_t umfMemoryTrackerRemove(umf_memory_tracker_handle_t hTracker,
254267
return UMF_RESULT_ERROR_UNKNOWN;
255268
}
256269

257-
assert(level < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP);
258-
value = critnib_remove(hTracker->alloc_segments_map[level], (uintptr_t)ptr);
259-
assert(value);
260-
261270
LOG_DEBUG("memory region removed: tracker=%p, level=%i, pool=%p, ptr=%p, "
262271
"size=%zu",
263272
(void *)hTracker, level, (void *)value->pool, ptr, value->size);
264273

274+
// size == 0 means that the entry was removed
275+
utils_atomic_store_release_u64((uint64_t *)&value->size, 0);
276+
277+
assert(level < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP);
278+
value = critnib_remove(hTracker->alloc_segments_map[level], (uintptr_t)ptr);
279+
assert(value);
280+
265281
if (parent_value) {
266282
LOG_DEBUG(
267283
"child #%zu removed from memory region: tracker=%p, level=%i, "
@@ -271,8 +287,6 @@ static umf_result_t umfMemoryTrackerRemove(umf_memory_tracker_handle_t hTracker,
271287
parent_value->n_children--;
272288
}
273289

274-
umf_ba_free(hTracker->alloc_info_allocator, value);
275-
276290
return UMF_RESULT_SUCCESS;
277291
}
278292

@@ -652,6 +666,9 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
652666
// we only need to update the size of the first part
653667
utils_atomic_store_release_u64((uint64_t *)&lowValue->size, totalSize);
654668

669+
// size == 0 means that the entry was removed
670+
utils_atomic_store_release_u64((uint64_t *)&highValue->size, 0);
671+
655672
void *erasedhighValue = critnib_remove(
656673
provider->hTracker->alloc_segments_map[highLevel], (uintptr_t)highPtr);
657674
assert(erasedhighValue == highValue);
@@ -664,8 +681,6 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
664681
lowLevel, lowPtr, lowValue->n_children, highPtr,
665682
highValue->n_children, totalSize);
666683

667-
umf_ba_free(provider->hTracker->alloc_info_allocator, highValue);
668-
669684
return UMF_RESULT_SUCCESS;
670685

671686
err_fatal:
@@ -1128,7 +1143,7 @@ umf_result_t umfTrackingMemoryProviderCreate(
11281143
return UMF_RESULT_ERROR_UNKNOWN;
11291144
}
11301145
params.pool = hPool;
1131-
params.ipcCache = critnib_new();
1146+
params.ipcCache = critnib_new(NULL, NULL);
11321147
if (!params.ipcCache) {
11331148
LOG_ERR("failed to create IPC cache");
11341149
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
@@ -1156,6 +1171,12 @@ void umfTrackingMemoryProviderGetUpstreamProvider(
11561171
*hUpstream = p->hUpstream;
11571172
}
11581173

1174+
static void free_leaf(void *leaf_allocator, void *ptr) {
1175+
if (ptr) {
1176+
umf_ba_free(leaf_allocator, ptr);
1177+
}
1178+
}
1179+
11591180
umf_memory_tracker_handle_t umfMemoryTrackerCreate(void) {
11601181
umf_memory_tracker_handle_t handle =
11611182
umf_ba_global_alloc(sizeof(struct umf_memory_tracker_t));
@@ -1180,7 +1201,8 @@ umf_memory_tracker_handle_t umfMemoryTrackerCreate(void) {
11801201

11811202
int i;
11821203
for (i = 0; i < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP; i++) {
1183-
handle->alloc_segments_map[i] = critnib_new();
1204+
handle->alloc_segments_map[i] =
1205+
critnib_new(alloc_info_allocator, free_leaf);
11841206
if (!handle->alloc_segments_map[i]) {
11851207
goto err_destroy_alloc_segments_map;
11861208
}
@@ -1192,7 +1214,7 @@ umf_memory_tracker_handle_t umfMemoryTrackerCreate(void) {
11921214
goto err_destroy_alloc_segments_map;
11931215
}
11941216

1195-
handle->ipc_segments_map = critnib_new();
1217+
handle->ipc_segments_map = critnib_new(NULL, NULL);
11961218
if (!handle->ipc_segments_map) {
11971219
goto err_destroy_ipc_info_allocator;
11981220
}

0 commit comments

Comments
 (0)