Skip to content

Commit 3e4f65f

Browse files
authored
Merge pull request #759 from ldorau/Check_if_the_provider_supports_the_free_operation
Clear tracker for the current pool on destroy
2 parents fa0e22d + 2766a21 commit 3e4f65f

File tree

5 files changed

+64
-34
lines changed

5 files changed

+64
-34
lines changed

src/memory_pool.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
4141
assert(ops->version == UMF_VERSION_CURRENT);
4242

4343
if (!(flags & UMF_POOL_CREATE_FLAG_DISABLE_TRACKING)) {
44-
// wrap provider with memory tracking provider
45-
ret = umfTrackingMemoryProviderCreate(provider, pool, &pool->provider);
44+
// Wrap provider with memory tracking provider.
45+
// Check if the provider supports the free() operation.
46+
bool upstreamDoesNotFree = (umfMemoryProviderFree(provider, NULL, 0) ==
47+
UMF_RESULT_ERROR_NOT_SUPPORTED);
48+
ret = umfTrackingMemoryProviderCreate(provider, pool, &pool->provider,
49+
upstreamDoesNotFree);
4650
if (ret != UMF_RESULT_SUCCESS) {
4751
goto err_provider_create;
4852
}

src/provider/provider_tracking.c

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ typedef struct umf_tracking_memory_provider_t {
141141
umf_memory_tracker_handle_t hTracker;
142142
umf_memory_pool_handle_t pool;
143143
critnib *ipcCache;
144+
145+
// the upstream provider does not support the free() operation
146+
bool upstreamDoesNotFree;
144147
} umf_tracking_memory_provider_t;
145148

146149
typedef struct umf_tracking_memory_provider_t umf_tracking_memory_provider_t;
@@ -392,9 +395,11 @@ static umf_result_t trackingInitialize(void *params, void **ret) {
392395
return UMF_RESULT_SUCCESS;
393396
}
394397

395-
#ifndef NDEBUG
396-
static void check_if_tracker_is_empty(umf_memory_tracker_handle_t hTracker,
397-
umf_memory_pool_handle_t pool) {
398+
// TODO clearing the tracker is a temporary solution and should be removed.
399+
// The tracker should be cleared using the provider's free() operation.
400+
static void clear_tracker_for_the_pool(umf_memory_tracker_handle_t hTracker,
401+
umf_memory_pool_handle_t pool,
402+
bool upstreamDoesNotFree) {
398403
uintptr_t rkey;
399404
void *rvalue;
400405
size_t n_items = 0;
@@ -403,39 +408,55 @@ static void check_if_tracker_is_empty(umf_memory_tracker_handle_t hTracker,
403408
while (1 == critnib_find((critnib *)hTracker->map, last_key, FIND_G, &rkey,
404409
&rvalue)) {
405410
tracker_value_t *value = (tracker_value_t *)rvalue;
406-
if (value->pool == pool || pool == NULL) {
407-
n_items++;
411+
if (value->pool != pool && pool != NULL) {
412+
last_key = rkey;
413+
continue;
408414
}
409415

416+
n_items++;
417+
418+
void *removed_value = critnib_remove(hTracker->map, rkey);
419+
assert(removed_value == rvalue);
420+
umf_ba_free(hTracker->tracker_allocator, removed_value);
421+
410422
last_key = rkey;
411423
}
412424

413-
if (n_items) {
414-
// Do not assert if we are running in the proxy library,
415-
// because it may need those resources till
416-
// the very end of exiting the application.
417-
if (!utils_is_running_in_proxy_lib()) {
418-
if (pool) {
419-
LOG_ERR("tracking provider of pool %p is not empty! "
420-
"(%zu items left)",
421-
(void *)pool, n_items);
422-
} else {
423-
LOG_ERR("tracking provider is not empty! (%zu items "
424-
"left)",
425-
n_items);
426-
}
425+
#ifndef NDEBUG
426+
// print error messages only if provider supports the free() operation
427+
if (n_items && !upstreamDoesNotFree) {
428+
if (pool) {
429+
LOG_ERR(
430+
"tracking provider of pool %p is not empty! (%zu items left)",
431+
(void *)pool, n_items);
432+
} else {
433+
LOG_ERR("tracking provider is not empty! (%zu items left)",
434+
n_items);
427435
}
428436
}
437+
#else /* DEBUG */
438+
(void)upstreamDoesNotFree; // unused in DEBUG build
439+
(void)n_items; // unused in DEBUG build
440+
#endif /* DEBUG */
441+
}
442+
443+
static void clear_tracker(umf_memory_tracker_handle_t hTracker) {
444+
clear_tracker_for_the_pool(hTracker, NULL, false);
429445
}
430-
#endif /* NDEBUG */
431446

432447
static void trackingFinalize(void *provider) {
433448
umf_tracking_memory_provider_t *p =
434449
(umf_tracking_memory_provider_t *)provider;
450+
435451
critnib_delete(p->ipcCache);
436-
#ifndef NDEBUG
437-
check_if_tracker_is_empty(p->hTracker, p->pool);
438-
#endif /* NDEBUG */
452+
453+
// Do not clear the tracker if we are running in the proxy library,
454+
// because it may need those resources till
455+
// the very end of exiting the application.
456+
if (!utils_is_running_in_proxy_lib()) {
457+
clear_tracker_for_the_pool(p->hTracker, p->pool,
458+
p->upstreamDoesNotFree);
459+
}
439460

440461
umf_ba_global_free(provider);
441462
}
@@ -661,10 +682,11 @@ umf_memory_provider_ops_t UMF_TRACKING_MEMORY_PROVIDER_OPS = {
661682

662683
umf_result_t umfTrackingMemoryProviderCreate(
663684
umf_memory_provider_handle_t hUpstream, umf_memory_pool_handle_t hPool,
664-
umf_memory_provider_handle_t *hTrackingProvider) {
685+
umf_memory_provider_handle_t *hTrackingProvider, bool upstreamDoesNotFree) {
665686

666687
umf_tracking_memory_provider_t params;
667688
params.hUpstream = hUpstream;
689+
params.upstreamDoesNotFree = upstreamDoesNotFree;
668690
params.hTracker = TRACKER;
669691
if (!params.hTracker) {
670692
LOG_ERR("failed, TRACKER is NULL");
@@ -739,16 +761,14 @@ void umfMemoryTrackerDestroy(umf_memory_tracker_handle_t handle) {
739761
return;
740762
}
741763

742-
// Do not destroy if we are running in the proxy library,
764+
// Do not destroy the tracket if we are running in the proxy library,
743765
// because it may need those resources till
744766
// the very end of exiting the application.
745767
if (utils_is_running_in_proxy_lib()) {
746768
return;
747769
}
748770

749-
#ifndef NDEBUG
750-
check_if_tracker_is_empty(handle, NULL);
751-
#endif /* NDEBUG */
771+
clear_tracker(handle);
752772

753773
// We have to zero all inner pointers,
754774
// because the tracker handle can be copied

src/provider/provider_tracking.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define UMF_MEMORY_TRACKER_INTERNAL_H 1
1212

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

1617
#include <umf/base.h>
@@ -53,7 +54,7 @@ umf_result_t umfMemoryTrackerGetAllocInfo(const void *ptr,
5354
// forwards all requests to hUpstream memory Provider. hUpstream lifetime should be managed by the user of this function.
5455
umf_result_t umfTrackingMemoryProviderCreate(
5556
umf_memory_provider_handle_t hUpstream, umf_memory_pool_handle_t hPool,
56-
umf_memory_provider_handle_t *hTrackingProvider);
57+
umf_memory_provider_handle_t *hTrackingProvider, bool upstreamDoesNotFree);
5758

5859
void umfTrackingMemoryProviderGetUpstreamProvider(
5960
umf_memory_provider_handle_t hTrackingProvider,

test/memoryPoolAPI.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ TEST_P(umfPoolWithCreateFlagsTest, memoryPoolWithCustomProvider) {
139139
}
140140

141141
TEST_F(test, retrieveMemoryProvider) {
142-
umf_memory_provider_handle_t provider = (umf_memory_provider_handle_t)0x1;
142+
auto nullProvider = umf_test::wrapProviderUnique(nullProviderCreate());
143+
umf_memory_provider_handle_t provider = nullProvider.get();
143144

144145
auto pool =
145146
wrapPoolUnique(createPoolChecked(umfProxyPoolOps(), provider, nullptr));
@@ -258,7 +259,8 @@ TEST_P(poolInitializeTest, errorPropagation) {
258259
}
259260

260261
TEST_F(test, retrieveMemoryProvidersError) {
261-
umf_memory_provider_handle_t provider = (umf_memory_provider_handle_t)0x1;
262+
auto nullProvider = umf_test::wrapProviderUnique(nullProviderCreate());
263+
umf_memory_provider_handle_t provider = nullProvider.get();
262264

263265
auto pool =
264266
wrapPoolUnique(createPoolChecked(umfProxyPoolOps(), provider, nullptr));

test/pools/disjoint_pool.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ TEST_F(test, sharedLimits) {
8282
}
8383
umf_result_t free(void *ptr, [[maybe_unused]] size_t size) noexcept {
8484
::free(ptr);
85-
numFrees++;
85+
// umfMemoryProviderFree(provider, NULL, 0) is called inside umfPoolCreateInternal()
86+
if (ptr != NULL && size != 0) {
87+
numFrees++;
88+
}
8689
return UMF_RESULT_SUCCESS;
8790
}
8891
};

0 commit comments

Comments
 (0)