Thread (105 messages) 105 messages, 13 authors, 2008-11-24

Re: [PATCH 1/3] rcu: Introduce hlist_nulls variant of hlist

From: Paul E. McKenney <hidden>
Date: 2008-11-19 21:21:44

On Wed, Nov 19, 2008 at 09:39:57PM +0100, Eric Dumazet wrote:
Paul E. McKenney a écrit :
quoted
On Wed, Nov 19, 2008 at 06:53:20PM +0100, Eric Dumazet wrote:
quoted
Paul E. McKenney a écrit :
quoted
quoted
+
+/**
+ * hlist_nulls_del_init_rcu - deletes entry from hash list with 
re-initialization
+ * @n: the element to delete from the hash list.
+ *
+ * Note: hlist_nulls_unhashed() on the node return true after this. It 
is
+ * useful for RCU based read lockfree traversal if the writer side
+ * must know if the list entry is still hashed or already unhashed.
+ *
+ * In particular, it means that we can not poison the forward pointers
+ * that may still be used for walking the hash list and we can only
+ * zero the pprev pointer so list_unhashed() will return true after
+ * this.
+ *
+ * The caller must take whatever precautions are necessary (such as
+ * holding appropriate locks) to avoid racing with another
+ * list-mutation primitive, such as hlist_nulls_add_head_rcu() or
+ * hlist_nulls_del_rcu(), running on this same list.  However, it is
+ * perfectly legal to run concurrently with the _rcu list-traversal
+ * primitives, such as hlist_nulls_for_each_entry_rcu().
+ */
+static inline void hlist_nulls_del_init_rcu(struct hlist_nulls_node 
*n)
+{
+	if (!hlist_nulls_unhashed(n)) {
+		__hlist_nulls_del(n);
+		n->pprev = NULL;
+	}
+}
The point here is to allow an RCU reader to grab the update-side lock
while holding a reference to an hlist_nulls_node, and then be able to
blindly call hlist_nulls_del_init_rcu() without having to do any complex
check to see if the element has already been deleted?
But this only works if each free operation waits for a grace period.
If using SLAB_DESTROY_BY_RCU, the would-be deleter still needs to
revalidate after grabbing the update-side lock, right?  Hmmm...
<start a brain refresh cycle>
 <read again your questions>
   Tilt... 
hlist_nulls_del_init_rcu() is only used by a writer, exactly
like hlist_del_init_rcu().
I see nothing special about SLAB_DESTROY_BY_RCU here.

static inline void hlist_del_init_rcu(struct hlist_node *n)
{
       if (!hlist_unhashed(n)) {
               __hlist_del(n);
               n->pprev = NULL;
       }
}
Not a problem, as you don't use it the way I was thinking.
For whatever it is worth, here is a more complete use case, on the
off-chance that it becomes useful some time:
	retry:
	rcu_read_lock();
	hlist_nulls_for_each_entry_rcu(tpos, pos, head, hn_node) {
		if (!(curgen = still_valid(tpos)))
			goto retry;
		if (needs_deletion(tpos)) {
			spin_lock(&update_side_lock);
			if (still_valid(tpos) == curgen)
				hlist_nulls_del_init_rcu(pos);
			spin_unlock(&update_side_lock);
		}
	}
	rcu_read_unlock();
This approach requires that the key and a generation number be encoded
into a single word, and that the generation number be changed on each
allocation and on each free.
Hum, we should add this template in Documentation/RCU  I guess
With Arnaldo's change -- probably should prototype and test to find
the other inevitable bugs.  :-/

							Thanx, Paul
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help