Skip to content

Commit accde78

Browse files
committed
[WIP!] critnib: add refcount WIP!
Signed-off-by: Lukasz Dorau <[email protected]>
1 parent d99bba0 commit accde78

File tree

1 file changed

+42
-4
lines changed

1 file changed

+42
-4
lines changed

src/critnib/critnib.c

+42-4
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ struct critnib_node {
116116
struct critnib_leaf {
117117
word key;
118118
void *value;
119+
uint64_t ref_count;
119120
};
120121

121122
struct critnib {
@@ -336,6 +337,8 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
336337

337338
utils_atomic_store_release_ptr((void **)&k->key, (void *)key);
338339
utils_atomic_store_release_ptr((void **)&k->value, value);
340+
// set the most significant bit of the ref_count
341+
utils_atomic_store_release_u64(&k->ref_count, 1ULL << 63);
339342

340343
struct critnib_node *kn = (void *)((word)k | 1);
341344

@@ -486,6 +489,8 @@ void *critnib_remove(struct critnib *c, word key) {
486489
c->pending_del_nodes[del] = n;
487490

488491
del_leaf:
492+
// clear the most significant bit of the ref_count
493+
utils_atomic_and_u64(&k->ref_count, (1ULL << 63) - 1);
489494
value = k->value;
490495
c->pending_del_leaves[del] = k;
491496

@@ -505,12 +510,14 @@ void *critnib_remove(struct critnib *c, word key) {
505510
* we need only one that was valid at any point after the call started.
506511
*/
507512
void *critnib_get(struct critnib *c, word key) {
513+
struct critnib_leaf *k;
514+
struct critnib_node *n;
508515
uint64_t wrs1, wrs2;
509516
void *res;
510517

511-
do {
512-
struct critnib_node *n;
518+
int value_read = 0;
513519

520+
do {
514521
utils_atomic_load_acquire_u64(&c->remove_count, &wrs1);
515522
utils_atomic_load_acquire_ptr((void **)&c->root, (void **)&n);
516523

@@ -525,11 +532,31 @@ void *critnib_get(struct critnib *c, word key) {
525532
}
526533

527534
/* ... as we check it at the end. */
528-
struct critnib_leaf *k = to_leaf(n);
529-
res = (n && k->key == key) ? k->value : NULL;
535+
k = to_leaf(n);
536+
if (n && k->key == key) {
537+
res = k->value;
538+
value_read = 1;
539+
} else {
540+
res = NULL;
541+
}
530542
utils_atomic_load_acquire_u64(&c->remove_count, &wrs2);
531543
} while (wrs1 + DELETED_LIFE <= wrs2);
532544

545+
if (!value_read) {
546+
return res;
547+
}
548+
549+
// test the most significant bit of the ref_count
550+
uint64_t ref_count;
551+
utils_atomic_load_acquire_u64(&k->ref_count, &ref_count);
552+
if ((ref_count & (1ULL << 63)) == 0) {
553+
// the leaf was already removed
554+
return NULL;
555+
}
556+
557+
// the leaf is still in use, increment the refcount and return the value
558+
utils_atomic_increment_u64(&k->ref_count);
559+
533560
return res;
534561
}
535562

@@ -786,6 +813,17 @@ int critnib_find(struct critnib *c, uintptr_t key, enum find_dir_t dir,
786813
} while (wrs1 + DELETED_LIFE <= wrs2);
787814

788815
if (k) {
816+
// test the most significant bit of the ref_count
817+
uint64_t ref_count;
818+
utils_atomic_load_acquire_u64(&k->ref_count, &ref_count);
819+
if ((ref_count & (1ULL << 63)) == 0) {
820+
// the leaf was already removed
821+
return 0;
822+
}
823+
824+
// the leaf is still in use, increment the refcount and return the value
825+
utils_atomic_increment_u64(&k->ref_count);
826+
789827
if (rkey) {
790828
*rkey = _rkey;
791829
}

0 commit comments

Comments
 (0)