rcu_nest: Fix concurrency issues

Variable "rcu_gp_ctr" is incremented by the updater and is fetched by
readers concurrently. So protect this variable by using READ_ONCE()
and WRITE_ONCE().

Per-thread variable "rcu_read_gp" is updated by the reader and is read
by the updater. So protect it by using READ_ONCE() and WRITE_ONCE().

The type of "rcu_gp_ctr" is changed to unsigned long because the behavior
of the overflow of a signed long integer is not well defined in C yet.
"rcu_gp_ctr" could wrap around. To compare it to "rcu_reader_gp" correctly,
helper function ULONG_CMP_GE() is used.

Refine the code snippet in "rcu_read_lock" that allows a reader to start
over. In this version, we add micro MAX_GP_ADV_DISTANCE which is by
default set to (RCU_GP_CTR_NEST_MASK << 8). Once a reader notices that
MAX_GP_ADV_DISTANCE grace-periods have elapsed since fetching the value of
"rcu_reader_gp", the reader starts over.

Signed-off-by: Junchang Wang <junchangwang@gmail.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>
2 files changed