X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=rculfhash.c;h=be995dfeaf5ef70795a6fd74a7bc34f4ced558c6;hb=3fb86f26cfea354e44be1099642fc88436e3edf3;hp=189f8c831237edfe205c6461babadb765b537285;hpb=a4ea2223fa701bd34b09fb3eede037908dbdd0c8;p=urcu.git diff --git a/rculfhash.c b/rculfhash.c index 189f8c8..be995df 100644 --- a/rculfhash.c +++ b/rculfhash.c @@ -787,10 +787,10 @@ void _cds_lfht_gc_bucket(struct cds_lfht_node *dummy, struct cds_lfht_node *node static int _cds_lfht_replace(struct cds_lfht *ht, unsigned long size, struct cds_lfht_node *old_node, - struct cds_lfht_node *ret_next, + struct cds_lfht_node *old_next, struct cds_lfht_node *new_node) { - struct cds_lfht_node *dummy, *old_next; + struct cds_lfht_node *dummy, *ret_next; struct _cds_lfht_node *lookup; int flagged = 0; @@ -802,9 +802,8 @@ int _cds_lfht_replace(struct cds_lfht *ht, unsigned long size, assert(!is_removed(new_node)); assert(!is_dummy(new_node)); assert(new_node != old_node); - do { + for (;;) { /* Insert after node to be replaced */ - old_next = ret_next; if (is_removed(old_next)) { /* * Too late, the old node has been removed under us @@ -827,7 +826,10 @@ int _cds_lfht_replace(struct cds_lfht *ht, unsigned long size, */ ret_next = uatomic_cmpxchg(&old_node->p.next, old_next, flag_removed(new_node)); - } while (ret_next != old_next); + if (ret_next == old_next) + break; + old_next = ret_next; + } /* We performed the replacement. */ flagged = 1; @@ -887,11 +889,15 @@ struct cds_lfht_node *_cds_lfht_add(struct cds_lfht *ht, goto insert; if (likely(clear_flag(iter)->p.reverse_hash > node->p.reverse_hash)) goto insert; + /* dummy node is the first node of the identical-hash-value chain */ + if (dummy && clear_flag(iter)->p.reverse_hash == node->p.reverse_hash) + goto insert; next = rcu_dereference(clear_flag(iter)->p.next); if (unlikely(is_removed(next))) goto gc_node; if ((mode == ADD_UNIQUE || mode == ADD_REPLACE) && !is_dummy(next) + && clear_flag(iter)->p.reverse_hash == node->p.reverse_hash && !ht->compare_fct(node->key, node->key_len, clear_flag(iter)->key, clear_flag(iter)->key_len)) { @@ -1341,6 +1347,7 @@ void cds_lfht_lookup(struct cds_lfht *ht, void *key, size_t key_len, next = rcu_dereference(node->p.next); if (likely(!is_removed(next)) && !is_dummy(next) + && clear_flag(node)->p.reverse_hash == reverse_hash && likely(!ht->compare_fct(node->key, node->key_len, key, key_len))) { break; }