1
1
/*
2
2
*
3
- * Copyright (C) 2023-2024 Intel Corporation
3
+ * Copyright (C) 2023-2025 Intel Corporation
4
4
*
5
5
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
6
6
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -118,7 +118,8 @@ struct critnib_leaf {
118
118
};
119
119
120
120
struct critnib {
121
- struct critnib_node * root ;
121
+ CACHE_ALIGNED struct critnib_node * root ;
122
+ CACHE_ALIGNED uint64_t remove_count ;
122
123
123
124
/* pool of freed nodes: singly linked list, next at child[0] */
124
125
struct critnib_node * deleted_node ;
@@ -128,29 +129,9 @@ struct critnib {
128
129
struct critnib_node * pending_del_nodes [DELETED_LIFE ];
129
130
struct critnib_leaf * pending_del_leaves [DELETED_LIFE ];
130
131
131
- uint64_t remove_count ;
132
-
133
132
struct utils_mutex_t mutex ; /* writes/removes */
134
133
};
135
134
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
-
154
135
/*
155
136
* internal: is_leaf -- check tagged pointer for leafness
156
137
*/
@@ -180,7 +161,7 @@ static inline unsigned slice_index(word key, sh_t shift) {
180
161
* critnib_new -- allocates a new critnib structure
181
162
*/
182
163
struct 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 ), 64 );
184
165
if (!c ) {
185
166
return NULL ;
186
167
}
@@ -272,7 +253,7 @@ static void free_node(struct critnib *__restrict c,
272
253
*/
273
254
static struct critnib_node * alloc_node (struct critnib * __restrict c ) {
274
255
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 ), 64 );
276
257
}
277
258
278
259
struct critnib_node * n = c -> deleted_node ;
@@ -303,7 +284,7 @@ static void free_leaf(struct critnib *__restrict c,
303
284
*/
304
285
static struct critnib_leaf * alloc_leaf (struct critnib * __restrict c ) {
305
286
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 ), 64 );
307
288
}
308
289
309
290
struct critnib_leaf * k = c -> deleted_leaf ;
@@ -343,10 +324,8 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
343
324
344
325
struct critnib_node * n = c -> root ;
345
326
if (!n ) {
346
- store (& c -> root , kn );
347
-
327
+ utils_atomic_store_release_ptr ((void * * )& c -> root , kn );
348
328
utils_mutex_unlock (& c -> mutex );
349
-
350
329
return 0 ;
351
330
}
352
331
@@ -361,7 +340,8 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
361
340
362
341
if (!n ) {
363
342
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 );
365
345
366
346
utils_mutex_unlock (& c -> mutex );
367
347
@@ -406,7 +386,7 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
406
386
m -> child [slice_index (path , sh )] = n ;
407
387
m -> shift = sh ;
408
388
m -> path = key & path_mask (sh );
409
- store ( parent , m );
389
+ utils_atomic_store_release_ptr (( void * * ) parent , m );
410
390
411
391
utils_mutex_unlock (& c -> mutex );
412
392
@@ -427,7 +407,8 @@ void *critnib_remove(struct critnib *c, word key) {
427
407
goto not_found ;
428
408
}
429
409
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 ;
431
412
free_node (c , c -> pending_del_nodes [del ]);
432
413
free_leaf (c , c -> pending_del_leaves [del ]);
433
414
c -> pending_del_nodes [del ] = NULL ;
@@ -436,7 +417,7 @@ void *critnib_remove(struct critnib *c, word key) {
436
417
if (is_leaf (n )) {
437
418
k = to_leaf (n );
438
419
if (k -> key == key ) {
439
- store ( & c -> root , NULL );
420
+ utils_atomic_store_release_ptr (( void * * ) & c -> root , NULL );
440
421
goto del_leaf ;
441
422
}
442
423
@@ -466,7 +447,8 @@ void *critnib_remove(struct critnib *c, word key) {
466
447
goto not_found ;
467
448
}
468
449
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 );
470
452
471
453
/* Remove the node if there's only one remaining child. */
472
454
int ochild = -1 ;
@@ -482,7 +464,7 @@ void *critnib_remove(struct critnib *c, word key) {
482
464
483
465
ASSERTne (ochild , -1 );
484
466
485
- store ( n_parent , n -> child [ochild ]);
467
+ utils_atomic_store_release_ptr (( void * * ) n_parent , n -> child [ochild ]);
486
468
c -> pending_del_nodes [del ] = n ;
487
469
488
470
del_leaf :
@@ -511,22 +493,23 @@ void *critnib_get(struct critnib *c, word key) {
511
493
do {
512
494
struct critnib_node * n ;
513
495
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 );
516
498
517
499
/*
518
500
* critbit algorithm: dive into the tree, looking at nothing but
519
501
* each node's critical bit^H^H^Hnibble. This means we risk
520
502
* going wrong way if our path is missing, but that's ok...
521
503
*/
522
504
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 );
524
507
}
525
508
526
509
/* ... as we check it at the end. */
527
510
struct critnib_leaf * k = to_leaf (n );
528
511
res = (n && k -> key == key ) ? k -> value : NULL ;
529
- load64 (& c -> remove_count , & wrs2 );
512
+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs2 );
530
513
} while (wrs1 + DELETED_LIFE <= wrs2 );
531
514
532
515
return res ;
@@ -597,7 +580,7 @@ static struct critnib_leaf *find_le(struct critnib_node *__restrict n,
597
580
/* recursive call: follow the path */
598
581
{
599
582
struct critnib_node * m ;
600
- load ( & n -> child [nib ], & m );
583
+ utils_atomic_load_acquire_ptr (( void * * ) & n -> child [nib ], ( void * * ) & m );
601
584
struct critnib_leaf * k = find_le (m , key );
602
585
if (k ) {
603
586
return k ;
@@ -611,7 +594,7 @@ static struct critnib_leaf *find_le(struct critnib_node *__restrict n,
611
594
*/
612
595
for (; nib > 0 ; nib -- ) {
613
596
struct critnib_node * m ;
614
- load ( & n -> child [nib - 1 ], & m );
597
+ utils_atomic_load_acquire_ptr (( void * * ) & n -> child [nib - 1 ], ( void * * ) & m );
615
598
if (m ) {
616
599
n = m ;
617
600
if (is_leaf (n )) {
@@ -635,12 +618,12 @@ void *critnib_find_le(struct critnib *c, word key) {
635
618
void * res ;
636
619
637
620
do {
638
- load64 (& c -> remove_count , & wrs1 );
621
+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs1 );
639
622
struct critnib_node * n ; /* avoid a subtle TOCTOU */
640
- load ( & c -> root , & n );
623
+ utils_atomic_load_acquire_ptr (( void * * ) & c -> root , ( void * * ) & n );
641
624
struct critnib_leaf * k = n ? find_le (n , key ) : NULL ;
642
625
res = k ? k -> value : NULL ;
643
- load64 (& c -> remove_count , & wrs2 );
626
+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs2 );
644
627
} while (wrs1 + DELETED_LIFE <= wrs2 );
645
628
646
629
return res ;
@@ -694,7 +677,7 @@ static struct critnib_leaf *find_ge(struct critnib_node *__restrict n,
694
677
unsigned nib = slice_index (key , n -> shift );
695
678
{
696
679
struct critnib_node * m ;
697
- load ( & n -> child [nib ], & m );
680
+ utils_atomic_load_acquire_ptr (( void * * ) & n -> child [nib ], ( void * * ) & m );
698
681
struct critnib_leaf * k = find_ge (m , key );
699
682
if (k ) {
700
683
return k ;
@@ -703,7 +686,7 @@ static struct critnib_leaf *find_ge(struct critnib_node *__restrict n,
703
686
704
687
for (; nib < NIB ; nib ++ ) {
705
688
struct critnib_node * m ;
706
- load ( & n -> child [nib + 1 ], & m );
689
+ utils_atomic_load_acquire_ptr (( void * * ) & n -> child [nib + 1 ], ( void * * ) & m );
707
690
if (m ) {
708
691
n = m ;
709
692
if (is_leaf (n )) {
@@ -741,17 +724,19 @@ int critnib_find(struct critnib *c, uintptr_t key, enum find_dir_t dir,
741
724
}
742
725
743
726
do {
744
- load64 (& c -> remove_count , & wrs1 );
727
+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs1 );
745
728
struct critnib_node * n ;
746
- load ( & c -> root , & n );
729
+ utils_atomic_load_acquire_ptr (( void * * ) & c -> root , ( void * * ) & n );
747
730
748
731
if (dir < 0 ) {
749
732
k = find_le (n , key );
750
733
} else if (dir > 0 ) {
751
734
k = find_ge (n , key );
752
735
} else {
753
736
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 );
755
740
}
756
741
757
742
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,
761
746
_rkey = k -> key ;
762
747
_rvalue = k -> value ;
763
748
}
764
- load64 (& c -> remove_count , & wrs2 );
749
+ utils_atomic_load_acquire_u64 (& c -> remove_count , & wrs2 );
765
750
} while (wrs1 + DELETED_LIFE <= wrs2 );
766
751
767
752
if (k ) {
0 commit comments