@@ -141,6 +141,9 @@ typedef struct umf_tracking_memory_provider_t {
141
141
umf_memory_tracker_handle_t hTracker ;
142
142
umf_memory_pool_handle_t pool ;
143
143
critnib * ipcCache ;
144
+
145
+ // the upstream provider does not support the free() operation
146
+ bool upstreamDoesNotFree ;
144
147
} umf_tracking_memory_provider_t ;
145
148
146
149
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) {
392
395
return UMF_RESULT_SUCCESS ;
393
396
}
394
397
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 ) {
398
403
uintptr_t rkey ;
399
404
void * rvalue ;
400
405
size_t n_items = 0 ;
@@ -403,39 +408,55 @@ static void check_if_tracker_is_empty(umf_memory_tracker_handle_t hTracker,
403
408
while (1 == critnib_find ((critnib * )hTracker -> map , last_key , FIND_G , & rkey ,
404
409
& rvalue )) {
405
410
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 ;
408
414
}
409
415
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
+
410
422
last_key = rkey ;
411
423
}
412
424
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 );
427
435
}
428
436
}
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);
429
445
}
430
- #endif /* NDEBUG */
431
446
432
447
static void trackingFinalize (void * provider ) {
433
448
umf_tracking_memory_provider_t * p =
434
449
(umf_tracking_memory_provider_t * )provider ;
450
+
435
451
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
+ }
439
460
440
461
umf_ba_global_free (provider );
441
462
}
@@ -661,10 +682,11 @@ umf_memory_provider_ops_t UMF_TRACKING_MEMORY_PROVIDER_OPS = {
661
682
662
683
umf_result_t umfTrackingMemoryProviderCreate (
663
684
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 ) {
665
686
666
687
umf_tracking_memory_provider_t params ;
667
688
params .hUpstream = hUpstream ;
689
+ params .upstreamDoesNotFree = upstreamDoesNotFree ;
668
690
params .hTracker = TRACKER ;
669
691
if (!params .hTracker ) {
670
692
LOG_ERR ("failed, TRACKER is NULL" );
@@ -739,16 +761,14 @@ void umfMemoryTrackerDestroy(umf_memory_tracker_handle_t handle) {
739
761
return ;
740
762
}
741
763
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,
743
765
// because it may need those resources till
744
766
// the very end of exiting the application.
745
767
if (utils_is_running_in_proxy_lib ()) {
746
768
return ;
747
769
}
748
770
749
- #ifndef NDEBUG
750
- check_if_tracker_is_empty (handle , NULL );
751
- #endif /* NDEBUG */
771
+ clear_tracker (handle );
752
772
753
773
// We have to zero all inner pointers,
754
774
// because the tracker handle can be copied
0 commit comments