Skip to content

Commit 2766a21

Browse files
committed
Clear tracker for the current pool on destroy
Clear tracker for the current pool on destroy. Do not print error messages if provider does not support the free() operation. Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com>
1 parent 9beff47 commit 2766a21

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)