11/*
22 *
3- * Copyright (C) 2023-2024 Intel Corporation
3+ * Copyright (C) 2023-2025 Intel Corporation
44 *
55 * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -119,6 +119,7 @@ struct critnib_leaf {
119119
120120struct critnib {
121121 struct critnib_node * root ;
122+ uint64_t remove_count ;
122123
123124 /* pool of freed nodes: singly linked list, next at child[0] */
124125 struct critnib_node * deleted_node ;
@@ -128,29 +129,9 @@ struct critnib {
128129 struct critnib_node * pending_del_nodes [DELETED_LIFE ];
129130 struct critnib_leaf * pending_del_leaves [DELETED_LIFE ];
130131
131- uint64_t remove_count ;
132-
133132 struct utils_mutex_t mutex ; /* writes/removes */
134133};
135134
136- /*
137- * atomic load
138- */
139- static void load (void * src , void * dst ) {
140- utils_atomic_load_acquire ((word * )src , (word * )dst );
141- }
142-
143- static void load64 (uint64_t * src , uint64_t * dst ) {
144- utils_atomic_load_acquire (src , dst );
145- }
146-
147- /*
148- * atomic store
149- */
150- static void store (void * dst , void * src ) {
151- utils_atomic_store_release ((word * )dst , (word )src );
152- }
153-
154135/*
155136 * internal: is_leaf -- check tagged pointer for leafness
156137 */
@@ -180,7 +161,7 @@ static inline unsigned slice_index(word key, sh_t shift) {
180161 * critnib_new -- allocates a new critnib structure
181162 */
182163struct critnib * critnib_new (void ) {
183- struct critnib * c = umf_ba_global_alloc (sizeof (struct critnib ));
164+ struct critnib * c = umf_ba_global_aligned_alloc (sizeof (struct critnib ), 8 );
184165 if (!c ) {
185166 return NULL ;
186167 }
@@ -272,7 +253,7 @@ static void free_node(struct critnib *__restrict c,
272253 */
273254static struct critnib_node * alloc_node (struct critnib * __restrict c ) {
274255 if (!c -> deleted_node ) {
275- return umf_ba_global_alloc (sizeof (struct critnib_node ));
256+ return umf_ba_global_aligned_alloc (sizeof (struct critnib_node ), 8 );
276257 }
277258
278259 struct critnib_node * n = c -> deleted_node ;
@@ -303,7 +284,7 @@ static void free_leaf(struct critnib *__restrict c,
303284 */
304285static struct critnib_leaf * alloc_leaf (struct critnib * __restrict c ) {
305286 if (!c -> deleted_leaf ) {
306- return umf_ba_global_alloc (sizeof (struct critnib_leaf ));
287+ return umf_ba_global_aligned_alloc (sizeof (struct critnib_leaf ), 8 );
307288 }
308289
309290 struct critnib_leaf * k = c -> deleted_leaf ;
@@ -343,10 +324,8 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
343324
344325 struct critnib_node * n = c -> root ;
345326 if (!n ) {
346- store (& c -> root , kn );
347-
327+ utils_atomic_store_release_ptr ((void * * )& c -> root , kn );
348328 utils_mutex_unlock (& c -> mutex );
349-
350329 return 0 ;
351330 }
352331
@@ -361,7 +340,8 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
361340
362341 if (!n ) {
363342 n = prev ;
364- store (& n -> child [slice_index (key , n -> shift )], kn );
343+ utils_atomic_store_release_ptr (
344+ (void * * )& n -> child [slice_index (key , n -> shift )], kn );
365345
366346 utils_mutex_unlock (& c -> mutex );
367347
@@ -406,7 +386,7 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
406386 m -> child [slice_index (path , sh )] = n ;
407387 m -> shift = sh ;
408388 m -> path = key & path_mask (sh );
409- store ( parent , m );
389+ utils_atomic_store_release_ptr (( void * * ) parent , m );
410390
411391 utils_mutex_unlock (& c -> mutex );
412392
@@ -427,7 +407,8 @@ void *critnib_remove(struct critnib *c, word key) {
427407 goto not_found ;
428408 }
429409
430- word del = (utils_atomic_increment (& c -> remove_count ) - 1 ) % DELETED_LIFE ;
410+ word del =
411+ (utils_atomic_increment_u64 (& c -> remove_count ) - 1 ) % DELETED_LIFE ;
431412 free_node (c , c -> pending_del_nodes [del ]);
432413 free_leaf (c , c -> pending_del_leaves [del ]);
433414 c -> pending_del_nodes [del ] = NULL ;
@@ -436,7 +417,7 @@ void *critnib_remove(struct critnib *c, word key) {
436417 if (is_leaf (n )) {
437418 k = to_leaf (n );
438419 if (k -> key == key ) {
439- store ( & c -> root , NULL );
420+ utils_atomic_store_release_ptr (( void * * ) & c -> root , NULL );
440421 goto del_leaf ;
441422 }
442423
@@ -466,7 +447,8 @@ void *critnib_remove(struct critnib *c, word key) {
466447 goto not_found ;
467448 }
468449
469- store (& n -> child [slice_index (key , n -> shift )], NULL );
450+ utils_atomic_store_release_ptr (
451+ (void * * )& n -> child [slice_index (key , n -> shift )], NULL );
470452
471453 /* Remove the node if there's only one remaining child. */
472454 int ochild = -1 ;
@@ -482,7 +464,7 @@ void *critnib_remove(struct critnib *c, word key) {
482464
483465 ASSERTne (ochild , -1 );
484466
485- store ( n_parent , n -> child [ochild ]);
467+ utils_atomic_store_release_ptr (( void * * ) n_parent , n -> child [ochild ]);
486468 c -> pending_del_nodes [del ] = n ;
487469
488470del_leaf :
@@ -511,22 +493,23 @@ void *critnib_get(struct critnib *c, word key) {
511493 do {
512494 struct critnib_node * n ;
513495
514- load64 (& c -> remove_count , & wrs1 );
515- load ( & c -> root , & n );
496+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs1 );
497+ utils_atomic_load_acquire_ptr (( void * * ) & c -> root , ( void * * ) & n );
516498
517499 /*
518500 * critbit algorithm: dive into the tree, looking at nothing but
519501 * each node's critical bit^H^H^Hnibble. This means we risk
520502 * going wrong way if our path is missing, but that's ok...
521503 */
522504 while (n && !is_leaf (n )) {
523- load (& n -> child [slice_index (key , n -> shift )], & n );
505+ utils_atomic_load_acquire_ptr (
506+ (void * * )& n -> child [slice_index (key , n -> shift )], (void * * )& n );
524507 }
525508
526509 /* ... as we check it at the end. */
527510 struct critnib_leaf * k = to_leaf (n );
528511 res = (n && k -> key == key ) ? k -> value : NULL ;
529- load64 (& c -> remove_count , & wrs2 );
512+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs2 );
530513 } while (wrs1 + DELETED_LIFE <= wrs2 );
531514
532515 return res ;
@@ -597,7 +580,7 @@ static struct critnib_leaf *find_le(struct critnib_node *__restrict n,
597580 /* recursive call: follow the path */
598581 {
599582 struct critnib_node * m ;
600- load ( & n -> child [nib ], & m );
583+ utils_atomic_load_acquire_ptr (( void * * ) & n -> child [nib ], ( void * * ) & m );
601584 struct critnib_leaf * k = find_le (m , key );
602585 if (k ) {
603586 return k ;
@@ -611,7 +594,7 @@ static struct critnib_leaf *find_le(struct critnib_node *__restrict n,
611594 */
612595 for (; nib > 0 ; nib -- ) {
613596 struct critnib_node * m ;
614- load ( & n -> child [nib - 1 ], & m );
597+ utils_atomic_load_acquire_ptr (( void * * ) & n -> child [nib - 1 ], ( void * * ) & m );
615598 if (m ) {
616599 n = m ;
617600 if (is_leaf (n )) {
@@ -635,12 +618,12 @@ void *critnib_find_le(struct critnib *c, word key) {
635618 void * res ;
636619
637620 do {
638- load64 (& c -> remove_count , & wrs1 );
621+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs1 );
639622 struct critnib_node * n ; /* avoid a subtle TOCTOU */
640- load ( & c -> root , & n );
623+ utils_atomic_load_acquire_ptr (( void * * ) & c -> root , ( void * * ) & n );
641624 struct critnib_leaf * k = n ? find_le (n , key ) : NULL ;
642625 res = k ? k -> value : NULL ;
643- load64 (& c -> remove_count , & wrs2 );
626+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs2 );
644627 } while (wrs1 + DELETED_LIFE <= wrs2 );
645628
646629 return res ;
@@ -694,7 +677,7 @@ static struct critnib_leaf *find_ge(struct critnib_node *__restrict n,
694677 unsigned nib = slice_index (key , n -> shift );
695678 {
696679 struct critnib_node * m ;
697- load ( & n -> child [nib ], & m );
680+ utils_atomic_load_acquire_ptr (( void * * ) & n -> child [nib ], ( void * * ) & m );
698681 struct critnib_leaf * k = find_ge (m , key );
699682 if (k ) {
700683 return k ;
@@ -703,7 +686,7 @@ static struct critnib_leaf *find_ge(struct critnib_node *__restrict n,
703686
704687 for (; nib < NIB ; nib ++ ) {
705688 struct critnib_node * m ;
706- load ( & n -> child [nib + 1 ], & m );
689+ utils_atomic_load_acquire_ptr (( void * * ) & n -> child [nib + 1 ], ( void * * ) & m );
707690 if (m ) {
708691 n = m ;
709692 if (is_leaf (n )) {
@@ -741,17 +724,19 @@ int critnib_find(struct critnib *c, uintptr_t key, enum find_dir_t dir,
741724 }
742725
743726 do {
744- load64 (& c -> remove_count , & wrs1 );
727+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs1 );
745728 struct critnib_node * n ;
746- load ( & c -> root , & n );
729+ utils_atomic_load_acquire_ptr (( void * * ) & c -> root , ( void * * ) & n );
747730
748731 if (dir < 0 ) {
749732 k = find_le (n , key );
750733 } else if (dir > 0 ) {
751734 k = find_ge (n , key );
752735 } else {
753736 while (n && !is_leaf (n )) {
754- load (& n -> child [slice_index (key , n -> shift )], & n );
737+ utils_atomic_load_acquire_ptr (
738+ (void * * )& n -> child [slice_index (key , n -> shift )],
739+ (void * * )& n );
755740 }
756741
757742 struct critnib_leaf * kk = to_leaf (n );
@@ -761,7 +746,7 @@ int critnib_find(struct critnib *c, uintptr_t key, enum find_dir_t dir,
761746 _rkey = k -> key ;
762747 _rvalue = k -> value ;
763748 }
764- load64 (& c -> remove_count , & wrs2 );
749+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs2 );
765750 } while (wrs1 + DELETED_LIFE <= wrs2 );
766751
767752 if (k ) {
0 commit comments