Skip to content

Commit 120b06d

Browse files
committed
Clear tracker for the pool if provider does not support free() operation
Clear the tracker from the current pool pointers, if the provider does not support the free() operation Signed-off-by: Lukasz Dorau <[email protected]>
1 parent 9beff47 commit 120b06d

File tree

5 files changed

+50
-7
lines changed

5 files changed

+50
-7
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 does not support 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: 34 additions & 1 deletion
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;
@@ -429,10 +432,39 @@ static void check_if_tracker_is_empty(umf_memory_tracker_handle_t hTracker,
429432
}
430433
#endif /* NDEBUG */
431434

435+
static void clear_tracker_for_the_pool(umf_memory_tracker_handle_t hTracker,
436+
umf_memory_pool_handle_t pool) {
437+
uintptr_t rkey;
438+
void *rvalue;
439+
uintptr_t last_key = 0;
440+
441+
while (1 == critnib_find((critnib *)hTracker->map, last_key, FIND_G, &rkey,
442+
&rvalue)) {
443+
tracker_value_t *value = (tracker_value_t *)rvalue;
444+
if (value->pool != pool) {
445+
last_key = rkey;
446+
continue;
447+
}
448+
449+
void *removed_value = critnib_remove(hTracker->map, rkey);
450+
assert(removed_value == rvalue);
451+
452+
umf_ba_free(hTracker->tracker_allocator, removed_value);
453+
454+
last_key = rkey;
455+
}
456+
}
457+
432458
static void trackingFinalize(void *provider) {
433459
umf_tracking_memory_provider_t *p =
434460
(umf_tracking_memory_provider_t *)provider;
461+
435462
critnib_delete(p->ipcCache);
463+
464+
if (p->upstreamDoesNotFree) {
465+
clear_tracker_for_the_pool(p->hTracker, p->pool);
466+
}
467+
436468
#ifndef NDEBUG
437469
check_if_tracker_is_empty(p->hTracker, p->pool);
438470
#endif /* NDEBUG */
@@ -661,10 +693,11 @@ umf_memory_provider_ops_t UMF_TRACKING_MEMORY_PROVIDER_OPS = {
661693

662694
umf_result_t umfTrackingMemoryProviderCreate(
663695
umf_memory_provider_handle_t hUpstream, umf_memory_pool_handle_t hPool,
664-
umf_memory_provider_handle_t *hTrackingProvider) {
696+
umf_memory_provider_handle_t *hTrackingProvider, bool upstreamDoesNotFree) {
665697

666698
umf_tracking_memory_provider_t params;
667699
params.hUpstream = hUpstream;
700+
params.upstreamDoesNotFree = upstreamDoesNotFree;
668701
params.hTracker = TRACKER;
669702
if (!params.hTracker) {
670703
LOG_ERR("failed, TRACKER is NULL");

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)