maybe dumb question about RCU

Andev debiandev at gmail.com
Fri Apr 10 16:12:44 EDT 2015


On Fri, Apr 10, 2015 at 12:47 PM, Jeff Haran <Jeff.Haran at citrix.com> wrote:
>
> The msleep() happens after the rcu_assign_pointer()/synchronize_rcu() sequence, not in the middle of it. All that msleep() is for is to make sure the updater isn't spinning that core and I chose the value so that the updater which thus runs every 1.5 seconds doesn't beat with the reader that is holding the rcu read lock for 1 second. Now one can argue that this in the reader is an atypically long time to hold a RCU read lock:
>
>                 rcu_read_lock();
>                 a = rcu_dereference(rcu_pointer);
>                 start = get_jiffies_64();
>                 while (get_jiffies_64() < (start + 1000));
>                 b = rcu_dereference(rcu_pointer);
>                 rcu_read_unlock();
>
> That causes the RCU read "lock" to be held for 1 second (at least on systems where a jiffie is a millisecond). But if that's "too long" then how long exactly is "too long"? If 1 second is too long, is 1 millisecond too long? How is the developer using this interface to know either how long is too long or how long the code they've written will take to execute given the plethora of different systems it might run on?
>
> The documentation I've seen says that the only restriction on RCU readers is that they don't block and the above doesn't so it satisfies the requirements of the interface near as I can tell.

This section of the code might still be pre-empted. Try putting a
preempt_disable() at the beginning and see if you are getting the same
value or not.

Relevant comment here:
http://lxr.free-electrons.com/source/include/linux/rcupdate.h#L837

>
> The conclusion I've come to is that the read critical section is *NOT* there to make sure that the value returned by rcu_dereference() of a given pointer doesn't change within the RCU read critical section (the code delimited by the rcu_read_lock() and rcu_read_unlock()).
>
> Rather the purpose of rcu_read_lock()/rcu_read_unlock() is there to keep synchronize_rcu() at bay so that the updater can safely free any memory block that may have been overwritten in the most recent call to rcu_assign_pointer(). The example I provided where rcu_pointer just oscillates between two different addresses of static buffers was done that way to make it simple. More typically, the pointers passed as the second parameter to rcu_assign_pointer() point to allocated memory. When updaters do that, they need to free those pointers eventually but they can't do that until they know that all readers aren't accessing them anymore. Normally, any freeing would happen after synchronize_rcu() returned and the read critical section is there to tell synchronize_rcu() when its safe to return and let the updater free the old memory block.
>
> At least that's how I read it now.
>
> Jeff Haran
>



-- 
Andev



More information about the Kernelnewbies mailing list