@@ -433,8 +433,25 @@ void *critnib_remove(struct critnib *c, word key) {
433
433
goto not_found ;
434
434
}
435
435
436
- word del =
437
- (utils_atomic_increment_u64 (& c -> remove_count ) - 1 ) % DELETED_LIFE ;
436
+ word del ;
437
+ int i = 0 ;
438
+ do {
439
+ del = (utils_atomic_increment_u64 (& c -> remove_count ) - 1 ) % DELETED_LIFE ;
440
+ if (c -> pending_del_leaves [del ] &&
441
+ (c -> pending_del_leaves [del ]-> ref_count > 0 )) {
442
+ fprintf (stderr ,
443
+ "critnib_remove(): pending_del_leaves[%llu]->key = %p, "
444
+ "ref_count=%llu \n" ,
445
+ (unsigned long long )del ,
446
+ (void * )c -> pending_del_leaves [del ]-> key ,
447
+ (unsigned long long )c -> pending_del_leaves [del ]-> ref_count );
448
+ if (i ++ == DELETED_LIFE ) {
449
+ break ;
450
+ }
451
+ }
452
+ } while (c -> pending_del_leaves [del ] &&
453
+ (c -> pending_del_leaves [del ]-> ref_count > 0 ));
454
+
438
455
free_node (c , c -> pending_del_nodes [del ]);
439
456
free_leaf (c , c -> pending_del_leaves [del ]);
440
457
c -> pending_del_nodes [del ] = NULL ;
@@ -494,12 +511,18 @@ void *critnib_remove(struct critnib *c, word key) {
494
511
c -> pending_del_nodes [del ] = n ;
495
512
496
513
del_leaf :
497
- uint64_t ref_count = utils_atomic_decrement_u64 (& k -> ref_count );
498
- fprintf (stderr ,
499
- "critnib_remove(): k->ref_count = %llu of k->key = %p\n" ,
500
- (unsigned long long )ref_count , (void * )k -> key );
501
-
502
514
value = k -> value ;
515
+ uint64_t ref_count ;
516
+ if ((ref_count = utils_atomic_decrement_u64 (& k -> ref_count )) == 0 ) {
517
+ utils_atomic_store_release_ptr ((void * * )& k -> value , NULL );
518
+ if (value && c -> cb_free_leaf ) {
519
+ c -> cb_free_leaf (c -> leaf_allocator , (void * )value );
520
+ }
521
+ }
522
+
523
+ fprintf (stderr , "critnib_remove(): k->ref_count = %llu of k->key = %p\n" ,
524
+ (unsigned long long )k -> ref_count , (void * )k -> key );
525
+
503
526
c -> pending_del_leaves [del ] = k ;
504
527
505
528
not_found :
@@ -521,9 +544,14 @@ int critnib_release(struct critnib *c, void *ref) {
521
544
522
545
/* decrement the reference count */
523
546
if (utils_atomic_decrement_u64 (& k -> ref_count ) == 0 ) {
524
- fprintf (stderr , "critnib_release(): k->ref_count = %llu of k->key = %p\n" ,
525
- (unsigned long long )k -> ref_count , (void * )k -> key );
526
- free_leaf (c , k );
547
+ void * value = k -> value ;
548
+ utils_atomic_store_release_ptr ((void * * )& k -> value , NULL );
549
+ if (value && c -> cb_free_leaf ) {
550
+ c -> cb_free_leaf (c -> leaf_allocator , value );
551
+ }
552
+
553
+ fprintf (stderr , "critnib_release(): k->ref_count = 0 of k->key = %p\n" ,
554
+ (void * )k -> key );
527
555
}
528
556
529
557
return 0 ;
@@ -570,7 +598,19 @@ void *critnib_get(struct critnib *c, word key, void **ref) {
570
598
} while (wrs1 + DELETED_LIFE <= wrs2 );
571
599
572
600
if (res ) {
573
- utils_atomic_increment_u64 (& k -> ref_count );
601
+ uint64_t ref_count ;
602
+ utils_atomic_load_acquire_u64 (& k -> ref_count , & ref_count );
603
+ if (ref_count == 0 ) {
604
+ return NULL ;
605
+ }
606
+ if ((ref_count = utils_atomic_increment_u64 (& k -> ref_count )) == 1 ) {
607
+ utils_atomic_decrement_u64 (& k -> ref_count );
608
+ return NULL ;
609
+ }
610
+
611
+ fprintf (stderr , "critnib_get(): k->ref_count = %llu of k->key = %p\n" ,
612
+ (unsigned long long )ref_count , (void * )k -> key );
613
+
574
614
* ref = k ;
575
615
}
576
616
@@ -704,7 +744,20 @@ void *critnib_find_le(struct critnib *c, word key, void **ref) {
704
744
} while (wrs1 + DELETED_LIFE <= wrs2 );
705
745
706
746
if (res ) {
707
- utils_atomic_increment_u64 (& k -> ref_count );
747
+ uint64_t ref_count ;
748
+ utils_atomic_load_acquire_u64 (& k -> ref_count , & ref_count );
749
+ if (ref_count == 0 ) {
750
+ return NULL ;
751
+ }
752
+ if ((ref_count = utils_atomic_increment_u64 (& k -> ref_count )) == 1 ) {
753
+ utils_atomic_decrement_u64 (& k -> ref_count );
754
+ return NULL ;
755
+ }
756
+
757
+ fprintf (stderr ,
758
+ "critnib_find_le(): k->ref_count = %llu of k->key = %p\n" ,
759
+ (unsigned long long )ref_count , (void * )k -> key );
760
+
708
761
* ref = k ;
709
762
}
710
763
@@ -844,7 +897,19 @@ int critnib_find(struct critnib *c, uintptr_t key, enum find_dir_t dir,
844
897
} while (wrs1 + DELETED_LIFE <= wrs2 );
845
898
846
899
if (k ) {
847
- utils_atomic_increment_u64 (& k -> ref_count );
900
+ uint64_t ref_count ;
901
+ utils_atomic_load_acquire_u64 (& k -> ref_count , & ref_count );
902
+ if (ref_count == 0 ) {
903
+ return 0 ;
904
+ }
905
+ if ((ref_count = utils_atomic_increment_u64 (& k -> ref_count )) == 1 ) {
906
+ utils_atomic_decrement_u64 (& k -> ref_count );
907
+ return 0 ;
908
+ }
909
+
910
+ fprintf (stderr , "critnib_find(): k->ref_count = %llu of k->key = %p\n" ,
911
+ (unsigned long long )ref_count , (void * )k -> key );
912
+
848
913
* ref = k ;
849
914
850
915
if (rkey ) {
0 commit comments