@@ -437,8 +437,25 @@ void *critnib_remove(struct critnib *c, word key) {
437437 goto not_found ;
438438 }
439439
440- word del =
441- (utils_atomic_increment_u64 (& c -> remove_count ) - 1 ) % DELETED_LIFE ;
440+ word del ;
441+ int i = 0 ;
442+ do {
443+ del = (utils_atomic_increment_u64 (& c -> remove_count ) - 1 ) % DELETED_LIFE ;
444+ if (c -> pending_del_leaves [del ] &&
445+ (c -> pending_del_leaves [del ]-> ref_count > 0 )) {
446+ fprintf (stderr ,
447+ "critnib_remove(): pending_del_leaves[%llu]->key = %p, "
448+ "ref_count=%llu \n" ,
449+ (unsigned long long )del ,
450+ (void * )c -> pending_del_leaves [del ]-> key ,
451+ (unsigned long long )c -> pending_del_leaves [del ]-> ref_count );
452+ if (i ++ == DELETED_LIFE ) {
453+ break ;
454+ }
455+ }
456+ } while (c -> pending_del_leaves [del ] &&
457+ (c -> pending_del_leaves [del ]-> ref_count > 0 ));
458+
442459 free_node (c , c -> pending_del_nodes [del ]);
443460 free_leaf (c , c -> pending_del_leaves [del ]);
444461 c -> pending_del_nodes [del ] = NULL ;
@@ -498,12 +515,18 @@ void *critnib_remove(struct critnib *c, word key) {
498515 c -> pending_del_nodes [del ] = n ;
499516
500517del_leaf :
501- uint64_t ref_count = utils_atomic_decrement_u64 (& k -> ref_count );
502- fprintf (stderr ,
503- "critnib_remove(): k->ref_count = %llu of k->key = %p\n" ,
504- (unsigned long long )ref_count , (void * )k -> key );
505-
506518 value = k -> value ;
519+ uint64_t ref_count ;
520+ if ((ref_count = utils_atomic_decrement_u64 (& k -> ref_count )) == 0 ) {
521+ utils_atomic_store_release_ptr ((void * * )& k -> value , NULL );
522+ if (value && c -> cb_free_leaf ) {
523+ c -> cb_free_leaf (c -> leaf_allocator , (void * )value );
524+ }
525+ }
526+
527+ fprintf (stderr , "critnib_remove(): k->ref_count = %llu of k->key = %p\n" ,
528+ (unsigned long long )k -> ref_count , (void * )k -> key );
529+
507530 c -> pending_del_leaves [del ] = k ;
508531
509532not_found :
@@ -525,9 +548,14 @@ int critnib_release(struct critnib *c, void *ref) {
525548
526549 /* decrement the reference count */
527550 if (utils_atomic_decrement_u64 (& k -> ref_count ) == 0 ) {
528- fprintf (stderr , "critnib_release(): k->ref_count = %llu of k->key = %p\n" ,
529- (unsigned long long )k -> ref_count , (void * )k -> key );
530- free_leaf (c , k );
551+ void * value = k -> value ;
552+ utils_atomic_store_release_ptr ((void * * )& k -> value , NULL );
553+ if (value && c -> cb_free_leaf ) {
554+ c -> cb_free_leaf (c -> leaf_allocator , value );
555+ }
556+
557+ fprintf (stderr , "critnib_release(): k->ref_count = 0 of k->key = %p\n" ,
558+ (void * )k -> key );
531559 }
532560
533561 return 0 ;
@@ -574,7 +602,19 @@ void *critnib_get(struct critnib *c, word key, void **ref) {
574602 } while (wrs1 + DELETED_LIFE <= wrs2 );
575603
576604 if (res ) {
577- utils_atomic_increment_u64 (& k -> ref_count );
605+ uint64_t ref_count ;
606+ utils_atomic_load_acquire_u64 (& k -> ref_count , & ref_count );
607+ if (ref_count == 0 ) {
608+ return NULL ;
609+ }
610+ if ((ref_count = utils_atomic_increment_u64 (& k -> ref_count )) == 1 ) {
611+ utils_atomic_decrement_u64 (& k -> ref_count );
612+ return NULL ;
613+ }
614+
615+ fprintf (stderr , "critnib_get(): k->ref_count = %llu of k->key = %p\n" ,
616+ (unsigned long long )ref_count , (void * )k -> key );
617+
578618 * ref = k ;
579619 }
580620
@@ -708,7 +748,20 @@ void *critnib_find_le(struct critnib *c, word key, void **ref) {
708748 } while (wrs1 + DELETED_LIFE <= wrs2 );
709749
710750 if (res ) {
711- utils_atomic_increment_u64 (& k -> ref_count );
751+ uint64_t ref_count ;
752+ utils_atomic_load_acquire_u64 (& k -> ref_count , & ref_count );
753+ if (ref_count == 0 ) {
754+ return NULL ;
755+ }
756+ if ((ref_count = utils_atomic_increment_u64 (& k -> ref_count )) == 1 ) {
757+ utils_atomic_decrement_u64 (& k -> ref_count );
758+ return NULL ;
759+ }
760+
761+ fprintf (stderr ,
762+ "critnib_find_le(): k->ref_count = %llu of k->key = %p\n" ,
763+ (unsigned long long )ref_count , (void * )k -> key );
764+
712765 * ref = k ;
713766 }
714767
@@ -848,7 +901,19 @@ int critnib_find(struct critnib *c, uintptr_t key, enum find_dir_t dir,
848901 } while (wrs1 + DELETED_LIFE <= wrs2 );
849902
850903 if (k ) {
851- utils_atomic_increment_u64 (& k -> ref_count );
904+ uint64_t ref_count ;
905+ utils_atomic_load_acquire_u64 (& k -> ref_count , & ref_count );
906+ if (ref_count == 0 ) {
907+ return 0 ;
908+ }
909+ if ((ref_count = utils_atomic_increment_u64 (& k -> ref_count )) == 1 ) {
910+ utils_atomic_decrement_u64 (& k -> ref_count );
911+ return 0 ;
912+ }
913+
914+ fprintf (stderr , "critnib_find(): k->ref_count = %llu of k->key = %p\n" ,
915+ (unsigned long long )ref_count , (void * )k -> key );
916+
852917 * ref = k ;
853918
854919 if (rkey ) {
0 commit comments