X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=rculfhash.c;h=8644f9c3f23ed184117eb2f74264cd9df121f19d;hb=ff0d69de620eab8a49e02724efadf0278516e20d;hp=18a3cb89c8b273b81757fd763f4b472d8301e6d6;hpb=93d46c395ff595372827983e9e84bd1e49eb6fab;p=urcu.git diff --git a/rculfhash.c b/rculfhash.c index 18a3cb8..8644f9c 100644 --- a/rculfhash.c +++ b/rculfhash.c @@ -894,22 +894,38 @@ void _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; + + /* uniquely add */ if (unique_ret && !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)) { - unique_ret->node = clear_flag(iter); - unique_ret->next = next; + && clear_flag(iter)->p.reverse_hash == node->p.reverse_hash) { + struct cds_lfht_iter d_iter = { .node = node, .next = iter, }; + + /* + * uniquely adding inserts the node as the first + * node of the identical-hash-value node chain. + * + * This semantic ensures no duplicated keys + * should ever be observable in the table + * (including observe one node by one node + * by forward iterations) + */ + cds_lfht_next_duplicate(ht, &d_iter); + if (!d_iter.node) + goto insert; + + *unique_ret = d_iter; return; } + /* Only account for identical reverse hash once */ if (iter_prev->p.reverse_hash != clear_flag(iter)->p.reverse_hash && !is_dummy(next)) @@ -1250,6 +1266,45 @@ void fini_table(struct cds_lfht *ht, } } +static +void cds_lfht_create_dummy(struct cds_lfht *ht, unsigned long size) +{ + struct _cds_lfht_node *prev, *node; + unsigned long order, len, i, j; + + ht->t.tbl[0] = calloc(1, sizeof(struct _cds_lfht_node)); + assert(ht->t.tbl[0]); + + dbg_printf("create dummy: order %lu index %lu hash %lu\n", 0, 0, 0); + ht->t.tbl[0]->nodes[0].next = flag_dummy(get_end()); + ht->t.tbl[0]->nodes[0].reverse_hash = 0; + + for (order = 1; order < get_count_order_ulong(size) + 1; order++) { + len = 1UL << (order - 1); + ht->t.tbl[order] = calloc(1, len * sizeof(struct _cds_lfht_node)); + assert(ht->t.tbl[order]); + + i = 0; + prev = ht->t.tbl[i]->nodes; + for (j = 0; j < len; j++) { + if (j & (j - 1)) { /* Between power of 2 */ + prev++; + } else if (j) { /* At each power of 2 */ + i++; + prev = ht->t.tbl[i]->nodes; + } + + node = &ht->t.tbl[order]->nodes[j]; + dbg_printf("create dummy: order %lu index %lu hash %lu\n", + order, j, j + len); + node->next = prev->next; + assert(is_dummy(node->next)); + node->reverse_hash = bit_reverse_ulong(j + len); + prev->next = flag_dummy((struct cds_lfht_node *)node); + } + } +} + struct cds_lfht *_cds_lfht_new(cds_lfht_hash_fct hash_fct, cds_lfht_compare_fct compare_fct, unsigned long hash_seed, @@ -1289,14 +1344,11 @@ struct cds_lfht *_cds_lfht_new(cds_lfht_hash_fct hash_fct, ht->percpu_count = alloc_per_cpu_items_count(); /* this mutex should not nest in read-side C.S. */ pthread_mutex_init(&ht->resize_mutex, NULL); - order = get_count_order_ulong(max(init_size, MIN_TABLE_SIZE)); ht->flags = flags; - ht->cds_lfht_rcu_thread_offline(); - pthread_mutex_lock(&ht->resize_mutex); + order = get_count_order_ulong(max(init_size, MIN_TABLE_SIZE)); ht->t.resize_target = 1UL << order; - init_table(ht, 0, order); - pthread_mutex_unlock(&ht->resize_mutex); - ht->cds_lfht_rcu_thread_online(); + cds_lfht_create_dummy(ht, 1UL << order); + ht->t.size = 1UL << order; return ht; }