@@ -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,9 @@ 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
+ static void clear_tracker_for_the_pool ( umf_memory_tracker_handle_t hTracker ,
399
+ umf_memory_pool_handle_t pool ,
400
+ bool upstreamDoesNotFree ) {
398
401
uintptr_t rkey ;
399
402
void * rvalue ;
400
403
size_t n_items = 0 ;
@@ -403,39 +406,55 @@ static void check_if_tracker_is_empty(umf_memory_tracker_handle_t hTracker,
403
406
while (1 == critnib_find ((critnib * )hTracker -> map , last_key , FIND_G , & rkey ,
404
407
& rvalue )) {
405
408
tracker_value_t * value = (tracker_value_t * )rvalue ;
406
- if (value -> pool == pool || pool == NULL ) {
407
- n_items ++ ;
409
+ if (value -> pool != pool && pool != NULL ) {
410
+ last_key = rkey ;
411
+ continue ;
408
412
}
409
413
414
+ n_items ++ ;
415
+
416
+ void * removed_value = critnib_remove (hTracker -> map , rkey );
417
+ assert (removed_value == rvalue );
418
+ umf_ba_free (hTracker -> tracker_allocator , removed_value );
419
+
410
420
last_key = rkey ;
411
421
}
412
422
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
- }
423
+ #ifndef NDEBUG
424
+ // print error messages only if provider supports the free() operation
425
+ if (n_items && !upstreamDoesNotFree ) {
426
+ if (pool ) {
427
+ LOG_ERR (
428
+ "tracking provider of pool %p is not empty! (%zu items left)" ,
429
+ (void * )pool , n_items );
430
+ } else {
431
+ LOG_ERR ("tracking provider is not empty! (%zu items left)" ,
432
+ n_items );
427
433
}
428
434
}
435
+ #else /* DEBUG */
436
+ (void )upstreamDoesNotFree ; // unused in DEBUG build
437
+ (void )n_items ; // unused in DEBUG build
438
+ #endif /* DEBUG */
439
+ }
440
+
441
+ static void clear_tracker (umf_memory_tracker_handle_t hTracker ) {
442
+ clear_tracker_for_the_pool (hTracker , NULL , false);
429
443
}
430
- #endif /* NDEBUG */
431
444
432
445
static void trackingFinalize (void * provider ) {
433
446
umf_tracking_memory_provider_t * p =
434
447
(umf_tracking_memory_provider_t * )provider ;
448
+
435
449
critnib_delete (p -> ipcCache );
436
- #ifndef NDEBUG
437
- check_if_tracker_is_empty (p -> hTracker , p -> pool );
438
- #endif /* NDEBUG */
450
+
451
+ // Do not clear the tracker if we are running in the proxy library,
452
+ // because it may need those resources till
453
+ // the very end of exiting the application.
454
+ if (!utils_is_running_in_proxy_lib ()) {
455
+ clear_tracker_for_the_pool (p -> hTracker , p -> pool ,
456
+ p -> upstreamDoesNotFree );
457
+ }
439
458
440
459
umf_ba_global_free (provider );
441
460
}
@@ -661,10 +680,11 @@ umf_memory_provider_ops_t UMF_TRACKING_MEMORY_PROVIDER_OPS = {
661
680
662
681
umf_result_t umfTrackingMemoryProviderCreate (
663
682
umf_memory_provider_handle_t hUpstream , umf_memory_pool_handle_t hPool ,
664
- umf_memory_provider_handle_t * hTrackingProvider ) {
683
+ umf_memory_provider_handle_t * hTrackingProvider , bool upstreamDoesNotFree ) {
665
684
666
685
umf_tracking_memory_provider_t params ;
667
686
params .hUpstream = hUpstream ;
687
+ params .upstreamDoesNotFree = upstreamDoesNotFree ;
668
688
params .hTracker = TRACKER ;
669
689
if (!params .hTracker ) {
670
690
LOG_ERR ("failed, TRACKER is NULL" );
@@ -739,16 +759,14 @@ void umfMemoryTrackerDestroy(umf_memory_tracker_handle_t handle) {
739
759
return ;
740
760
}
741
761
742
- // Do not destroy if we are running in the proxy library,
762
+ // Do not destroy the tracket if we are running in the proxy library,
743
763
// because it may need those resources till
744
764
// the very end of exiting the application.
745
765
if (utils_is_running_in_proxy_lib ()) {
746
766
return ;
747
767
}
748
768
749
- #ifndef NDEBUG
750
- check_if_tracker_is_empty (handle , NULL );
751
- #endif /* NDEBUG */
769
+ clear_tracker (handle );
752
770
753
771
// We have to zero all inner pointers,
754
772
// because the tracker handle can be copied
0 commit comments