}
static
-int _ht_add(struct rcu_ht *ht, struct rcu_table *t, struct rcu_ht_node *node,
- int unique)
+struct rcu_ht_node *_ht_add(struct rcu_ht *ht, struct rcu_table *t,
+ struct rcu_ht_node *node, int unique)
{
struct rcu_ht_node *iter_prev, *dummy, *iter, *next;
unsigned long hash;
- if (!t->size)
- return 0;
+ if (!t->size) {
+ assert(node->dummy);
+ return node; /* Initial first add (head) */
+ }
hash = bit_reverse_ulong(node->reverse_hash);
for (;;) {
uint32_t chain_len = 0;
&& !ht->compare_fct(node->key, node->key_len,
clear_flag(iter)->key,
clear_flag(iter)->key_len))
- return -EEXIST;
+ return clear_flag(iter);
/* Only account for identical reverse hash once */
if (iter_prev->reverse_hash != clear_flag(iter)->reverse_hash)
check_resize(ht, t, ++chain_len);
/* Garbage collect logically removed nodes in the bucket */
dummy = rcu_dereference(t->tbl[hash & (t->size - 1)]);
_ht_gc_bucket(dummy, node);
- return 0;
+ return node;
}
static
(void) _ht_add(ht, t, node, 0);
}
-int ht_add_unique(struct rcu_ht *ht, struct rcu_ht_node *node)
+struct rcu_ht_node *ht_add_unique(struct rcu_ht *ht, struct rcu_ht_node *node)
{
struct rcu_table *t;
unsigned long hash;
void *thr_writer(void *_count)
{
- struct rcu_ht_node *node;
+ struct rcu_ht_node *node, *ret_node;
struct wr_count *count = _count;
int ret;
ht_node_init(node,
(void *)(unsigned long)(rand_r(&rand_lookup) % RAND_POOL),
sizeof(void *));
- ret = ht_add_unique(test_ht, node);
+ ret_node = ht_add_unique(test_ht, node);
rcu_read_unlock();
- if (ret) {
+ if (ret_node != node) {
free(node);
nr_addexist++;
} else
count_writer = malloc(sizeof(*count_writer) * nr_writers);
test_ht = ht_new(test_hash, test_compare, 0x42UL,
HASH_SIZE, call_rcu);
+
next_aff = 0;
for (i = 0; i < nr_readers; i++) {
/* Call with rcu_read_lock held. */
void ht_add(struct rcu_ht *ht, struct rcu_ht_node *node);
-/* Call with rcu_read_lock held. */
-int ht_add_unique(struct rcu_ht *ht, struct rcu_ht_node *node);
+/*
+ * Call with rcu_read_lock held.
+ * Returns the node added upon success.
+ * Returns the unique node already present upon failure. If ht_add_unique fails,
+ * the node passed as parameter should be freed by the caller.
+ */
+struct rcu_ht_node *ht_add_unique(struct rcu_ht *ht, struct rcu_ht_node *node);
/* Call with rcu_read_lock held. */
int ht_remove(struct rcu_ht *ht, struct rcu_ht_node *node);