On Mon, Aug 28, 2017 at 09:39:18PM +0000, Bart Van Assche wrote: > On Mon, 2017-08-28 at 14:26 -0700, Paul E. McKenney wrote: > > On Mon, Aug 28, 2017 at 01:46:13PM -0700, Bart Van Assche wrote: > > > A common pattern in RCU code is to assign a new value to an RCU > > > pointer after having read and stored the old value. Introduce a > > > macro for this pattern. > > > > > > Signed-off-by: Bart Van Assche <bart.vanassche@xxxxxxx> > > > Cc: Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx> > > > Cc: Ingo Molnar <mingo@xxxxxxxxxx> > > > Cc: Christoph Hellwig <hch@xxxxxx> > > > Cc: Hannes Reinecke <hare@xxxxxxx> > > > Cc: Johannes Thumshirn <jthumshirn@xxxxxxx> > > > Cc: Shane M Seymour <shane.seymour@xxxxxxx> > > > --- > > > include/linux/rcupdate.h | 20 ++++++++++++++++++++ > > > 1 file changed, 20 insertions(+) > > > > > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > > > index f816fc72b51e..555815ce2e57 100644 > > > --- a/include/linux/rcupdate.h > > > +++ b/include/linux/rcupdate.h > > > @@ -561,6 +561,26 @@ static inline void rcu_preempt_sleep_check(void) { } > > > */ > > > #define rcu_pointer_handoff(p) (p) > > > > > > +/** > > > + * rcu_swap_protected() - swap an RCU and a regular pointer > > > + * @rcu_ptr: RCU pointer > > > + * @ptr: regular pointer > > > + * @c: the conditions under which the dereference will take place > > > + * > > > + * Perform swap(@rcu_ptr, @ptr) where @rcu_ptr is an RCU-annotated pointer and > > > + * @c is the argument that is passed to the rcu_dereference_protected() call > > > + * used to read that pointer. > > > + */ > > > +#define rcu_swap_protected(rcu_ptr, ptr, c) do { \ > > > + typeof(ptr) __tmp; \ > > > + \ > > > + BUILD_BUG_ON(!__same_type(typeof(rcu_ptr), typeof(*(ptr)) __rcu *)); \ > > > + BUILD_BUG_ON(!__same_type(typeof(ptr), typeof(*(rcu_ptr)) *)); \ > > > > Hmmm... > > > > What kinds of bugs have these two BUILD_BUG_ON() instances have caught > > that would not be caught by the assignments below? > > Hello Paul, > > These two BUILD_BUG_ON() statements can be left out. The purpose of these > statements is to complain as early as possible if the type of rcu_ptr and/or > ptr is incorrect. As we all know error messages that are triggered by macros > used inside a macro definition can be hard to read. My hope is that these > two BUILD_BUG_ON() macros will cause the compiler to report easier to read > diagnostic messages. > > > > + __tmp = rcu_dereference_protected((rcu_ptr), (c)); \ > > > + rcu_assign_pointer((rcu_ptr), (ptr)); \ > > > + (ptr) = __tmp; \ > > > +} while (0) > > > + > > > > Could you please put this after rcu_assign_pointer() and before > > rcu_access_pointer()? That way the things that assign to RCU-protected > > pointers are together. > > Something like the patch below (compile-tested only)? Looks good! I suspect that you would like to push this with your changes, so, assuming 0day test robot and -next are OK with it: Acked-by: Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx> I am not necessarily inalterably opposed to the extra BUILD_BUG_ON() statements, and in fact I do like improved diagnostics, but those need to go up via my tree as a separate patch. That way, any unexpected gotchas can be handled without risking your rcu_swap_protected() functionality. Thanx, Paul > Thanks, > > Bart. > > > [PATCH] rcu: Introduce rcu_swap_protected() > --- > include/linux/rcupdate.h | 16 ++++++++++++++++ > 1 file changed, 16 insertions(+) > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > index f816fc72b51e..8e920f0ecb07 100644 > --- a/include/linux/rcupdate.h > +++ b/include/linux/rcupdate.h > @@ -407,6 +407,22 @@ static inline void rcu_preempt_sleep_check(void) { } > _r_a_p__v; \ > }) > > +/** > + * rcu_swap_protected() - swap an RCU and a regular pointer > + * @rcu_ptr: RCU pointer > + * @ptr: regular pointer > + * @c: the conditions under which the dereference will take place > + * > + * Perform swap(@rcu_ptr, @ptr) where @rcu_ptr is an RCU-annotated pointer and > + * @c is the argument that is passed to the rcu_dereference_protected() call > + * used to read that pointer. > + */ > +#define rcu_swap_protected(rcu_ptr, ptr, c) do { \ > + typeof(ptr) __tmp = rcu_dereference_protected((rcu_ptr), (c)); \ > + rcu_assign_pointer((rcu_ptr), (ptr)); \ > + (ptr) = __tmp; \ > +} while (0) > + > /** > * rcu_access_pointer() - fetch RCU pointer with no dereferencing > * @p: The pointer to read