maybe dumb question about RCU

Andev debiandev at gmail.com
Mon Apr 13 17:00:33 EDT 2015


On Fri, Apr 10, 2015 at 4:34 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?


So I looked closely at your code and found the cause for your seeing different
values for the pointer.

What is happening is as follows:


         reader                               updater
--------------------------------------------------------------------------
                                    rcu_assign_pointer(rcu_pointer, p1);
                                    synchronize_rcu(); // returns immediately
                                                    // no rcu read CS active
       rcu_read_lock();
       a = rcu_pointer;//p1         // loop again
                                    rcu_assign_pointer(rcu_pointer, p2);
                                    // this is immediately visible to reader
       b = rcu_pointer; //p2
       rcu_read_unlock();
                                    synchronize_rcu(); // returns immediately
                                    // no rcu read CS active

This is just one possible run which will cause you to see different values of
rcu_pointer. There are possibly more.

Now what can you do to prevent such updates happening to pointers?

The obvious solution is to use mutex between readers and updaters. But we want
to use RCU.

Dereference the pointer only once within the read critical section. If you are
dereferencing twice, be ready to handle the case where the pointer has been
changed.

The guarantee that RCU provides is that p1 will not be freed until the read
critical section which holds a reference to p1 has completed.

-- 
Andev



More information about the Kernelnewbies mailing list