+ for (;;) {
+ iter_prev = dummy;
+ /* We can always skip the dummy node initially */
+ iter = rcu_dereference(iter_prev->p.next);
+ assert(iter_prev->p.reverse_hash <= node->p.reverse_hash);
+ for (;;) {
+ if (unlikely(!iter))
+ return;
+ if (clear_flag(iter)->p.reverse_hash > node->p.reverse_hash)
+ return;
+ next = rcu_dereference(clear_flag(iter)->p.next);
+ if (is_removed(next))
+ break;
+ iter_prev = iter;
+ iter = next;
+ }
+ assert(!is_removed(iter));
+ (void) uatomic_cmpxchg(&iter_prev->p.next, iter, clear_flag(next));
+ }
+}
+
+static
+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) {
+ assert(node->p.dummy);
+ return node; /* Initial first add (head) */
+ }
+ hash = bit_reverse_ulong(node->p.reverse_hash);