Skip to content

Commit 2040555

Browse files
committed
Use atomics to fix ASAN data races in critnib
Signed-off-by: Lukasz Dorau <[email protected]>
1 parent d694cc8 commit 2040555

File tree

1 file changed

+33
-15
lines changed

1 file changed

+33
-15
lines changed

src/critnib/critnib.c

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,10 @@ static void free_node(struct critnib *__restrict c,
246246
}
247247

248248
ASSERT(!is_leaf(n));
249-
n->child[0] = c->deleted_node;
250-
c->deleted_node = n;
249+
// n->child[0] = c->deleted_node;
250+
utils_atomic_store_release_ptr((void **)&n->child[0], c->deleted_node);
251+
// c->deleted_node = n;
252+
utils_atomic_store_release_ptr((void **)&c->deleted_node, n);
251253
}
252254

253255
/*
@@ -277,8 +279,10 @@ static void free_leaf(struct critnib *__restrict c,
277279
return;
278280
}
279281

280-
k->value = c->deleted_leaf;
281-
c->deleted_leaf = k;
282+
// k->value = c->deleted_leaf;
283+
utils_atomic_store_release_ptr((void **)&k->value, c->deleted_leaf);
284+
// c->deleted_leaf = k;
285+
utils_atomic_store_release_ptr((void **)&c->deleted_leaf, k);
282286
}
283287

284288
/*
@@ -319,8 +323,10 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
319323

320324
utils_annotate_memory_no_check(k, sizeof(struct critnib_leaf));
321325

322-
k->key = key;
323-
k->value = value;
326+
// k->key = key;
327+
utils_atomic_store_release_ptr((void **)&k->key, (void *)key);
328+
// k->value = value;
329+
utils_atomic_store_release_ptr((void **)&k->value, value);
324330

325331
struct critnib_node *kn = (void *)((word)k | 1);
326332

@@ -358,7 +364,8 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
358364
free_leaf(c, to_leaf(kn));
359365

360366
if (update) {
361-
to_leaf(n)->value = value;
367+
// to_leaf(n)->value = value;
368+
utils_atomic_store_release_ptr(&to_leaf(n)->value, value);
362369
utils_mutex_unlock(&c->mutex);
363370
return 0;
364371
} else {
@@ -381,13 +388,18 @@ int critnib_insert(struct critnib *c, word key, void *value, int update) {
381388
utils_annotate_memory_no_check(m, sizeof(struct critnib_node));
382389

383390
for (int i = 0; i < SLNODES; i++) {
384-
m->child[i] = NULL;
391+
// m->child[i] = NULL;
392+
utils_atomic_store_release_ptr((void *)&m->child[i], NULL);
385393
}
386394

387-
m->child[slice_index(key, sh)] = kn;
388-
m->child[slice_index(path, sh)] = n;
395+
// m->child[slice_index(key, sh)] = kn;
396+
utils_atomic_store_release_ptr((void *)&m->child[slice_index(key, sh)], kn);
397+
// m->child[slice_index(path, sh)] = n;
398+
utils_atomic_store_release_ptr((void *)&m->child[slice_index(path, sh)], n);
389399
m->shift = sh;
390-
m->path = key & path_mask(sh);
400+
// m->path = key & path_mask(sh);
401+
utils_atomic_store_release_u64((void *)&m->path, key & path_mask(sh));
402+
391403
utils_atomic_store_release_ptr((void **)parent, m);
392404

393405
utils_mutex_unlock(&c->mutex);
@@ -569,12 +581,15 @@ static struct critnib_leaf *find_le(struct critnib_node *__restrict n,
569581
* that shift points at the nib's lower rather than upper edge, so it
570582
* needs to be masked away as well.
571583
*/
572-
if ((key ^ n->path) >> (n->shift) & ~NIB) {
584+
word path;
585+
sh_t shift = n->shift;
586+
utils_atomic_load_acquire_u64((uint64_t *)&n->path, (uint64_t *)&path);
587+
if ((key ^ path) >> (shift) & ~NIB) {
573588
/*
574589
* subtree is too far to the left?
575590
* -> its rightmost value is good
576591
*/
577-
if (n->path < key) {
592+
if (path < key) {
578593
return find_predecessor(n);
579594
}
580595

@@ -759,8 +774,11 @@ int critnib_find(struct critnib *c, uintptr_t key, enum find_dir_t dir,
759774
k = (n && kk->key == key) ? kk : NULL;
760775
}
761776
if (k) {
762-
_rkey = k->key;
763-
_rvalue = k->value;
777+
// _rkey = k->key;
778+
utils_atomic_load_acquire_u64((uint64_t *)&k->key,
779+
(uint64_t *)&_rkey);
780+
// _rvalue = k->value;
781+
utils_atomic_load_acquire_ptr(&k->value, (void **)&_rvalue);
764782
}
765783
utils_atomic_load_acquire_u64(&c->remove_count, &wrs2);
766784
} while (wrs1 + DELETED_LIFE <= wrs2);

0 commit comments

Comments
 (0)