maybe dumb question about RCU

Jeff Haran Jeff.Haran at citrix.com
Mon Apr 13 17:13:16 EDT 2015


> -----Original Message-----
> From: Andev [mailto:debiandev at gmail.com]
> Sent: Monday, April 13, 2015 2:01 PM
> To: Jeff Haran
> Cc: kernelnewbies
> Subject: Re: maybe dumb question about RCU
> 
> 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

Sounds like we have come to the same conclusion then.

Thanks,

Jeff Haran



More information about the Kernelnewbies mailing list