X-Git-Url: https://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=rculfhash.c;h=4abf27a9a5dd5e9f56f97d669de88e58705e741d;hp=450b286385ab2e00db0116e78326dbb6d0c74521;hb=98f969fc5e7fcd7dcc260dde0ef788e8df50775a;hpb=3390d4701e9fec1df68bbfff42cca215b4bfee05 diff --git a/rculfhash.c b/rculfhash.c index 450b286..4abf27a 100644 --- a/rculfhash.c +++ b/rculfhash.c @@ -220,12 +220,15 @@ void _ht_add(struct rcu_ht *ht, struct rcu_table *t, struct rcu_ht_node *node) iter = clear_flag(rcu_dereference(iter_prev->next)); if (unlikely(!iter)) break; - if (iter->reverse_hash < node->reverse_hash) + if (iter->reverse_hash > node->reverse_hash) break; iter_prev = iter; check_resize(ht, t, ++chain_len); } - /* add in iter_prev->next */ + /* + * add in iter_prev->next: TODO: check for helping + * delete, for lock-freedom... + */ if (is_removed(iter)) continue; assert(node != iter); @@ -255,7 +258,7 @@ retry: iter = clear_flag(rcu_dereference(iter_prev->next)); if (unlikely(!iter)) break; - if (iter->reverse_hash < node->reverse_hash) + if (unlikely(iter->reverse_hash > node->reverse_hash)) break; if (iter == node) { found = 1; @@ -286,9 +289,13 @@ retry: flagged = 1; } /* - * Remove the element from the list. Retry if there has been a - * concurrent add (there cannot be a concurrent delete, because - * we won the deletion flag cmpxchg). + * Remove the element from the list. + * Retry if there has been a concurrent add before us. + * Retry if the prev node has been deleted. + * There cannot be a concurrent delete for our position, because + * we won the deletion flag cmpxchg. + * If there is a concurrent add after us, our deletion flag + * makes it busy-loop (FIXME: not lock-free). */ if (uatomic_cmpxchg(&iter_prev->next, iter, clear_flag(next)) != iter) goto retry; @@ -355,12 +362,12 @@ struct rcu_ht_node *ht_lookup(struct rcu_ht *ht, void *key, size_t key_len) for (;;) { if (unlikely(!node)) break; - if (node->reverse_hash > reverse_hash) { + if (unlikely(node->reverse_hash > reverse_hash)) { node = NULL; break; } if (!ht->compare_fct(node->key, node->key_len, key, key_len)) { - if (is_removed(rcu_dereference(node->next))) + if (unlikely(is_removed(rcu_dereference(node->next)))) node = NULL; break; }