SRCU changes for 3.8
cover SRCU changes for 3.8
Hello!
This patch series contains SRCU changes allowing srcu_structs to be statically initialized. The patches are as follows:
1. Add Lai Jiangshan as author for srcu.c and srcu.h.
(Courtesy Lia Jiangshan.)
2. Export process_srcu() so that the initialization macro may
be invoked anywhere. (Courtesy Lia Jiangshan.)
3. Add DEFINE_SRCU(). (Courtesy Lia Jiangshan.)
4. Add DEFINE_STATIC_SRCU(). This cannot be emulated by
"static DEFINE_SRCU()" due to forward-reference issues. (Courtesy Lia Jiangshan.)
Thanx, Paul
b/include/linux/srcu.h | 34 ++++++++++++++++++++++++++++++++++ b/kernel/rcutorture.c | 41 ++++++----------------------------------- b/kernel/srcu.c | 8 ++++---- 3 files changed, 44 insertions(+), 39 deletions(-)
PATCH 1/4 srcu: Credit Lai Jiangshan with SRCU rewrite
From: Lai Jiangshan <[email protected]>
Lai Jiangshan rewrote SRCU, so this commit ensures that he gets his proper share of blame^Wcredit.
--- include/linux/srcu.h | 2 ++ kernel/srcu.c | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-)
include/linux/srcu.h +2 -0
@@ -16,8 +16,10 @@* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Copyright (C) IBM Corporation, 2006 +* Copyright (C) Fujitsu, 2012 * * Author: Paul McKenney <[email protected]> +* Lai Jiangshan <[email protected]> * * For detailed explanation of Read-Copy Update mechanism see - * Documentation/RCU/ *.txt
kernel/srcu.c +2 -0
@@ -16,8 +16,10 @@* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Copyright (C) IBM Corporation, 2006 +* Copyright (C) Fujitsu, 2012 * * Author: Paul McKenney <[email protected]> +* Lai Jiangshan <[email protected]> * * For detailed explanation of Read-Copy Update mechanism see - * Documentation/RCU/ *.txt
Signature · 1 line
1.7.8
PATCH 2/4 srcu: Export process_srcu()
From: Lai Jiangshan <[email protected]>
Because process_srcu() will be used in DEFINE_SRCU(), which is a macro that could be expanded pretty much anywhere, it can no longer be static. Note that process_srcu() is still internal to srcu.h.
--- include/linux/srcu.h | 2 ++ kernel/srcu.c | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-)
include/linux/srcu.h +2 -0
@@ -78,6 +78,8 @@ int init_srcu_struct(struct srcu_struct *sp);#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ +void process_srcu (struct work_struct *work); +/** * call_srcu() - Queue a callback for invocation after an SRCU grace period * @sp: srcu_struct in queue the callback
kernel/srcu.c +2 -4
@@ -94,9 +94,6 @@ static inline void rcu_batch_move(struct rcu_batch *to, struct rcu_batch *from) } } -/* single-thread state-machine */ -static void process_srcu (struct work_struct *work); -static int init_srcu_struct_fields (struct srcu_struct *sp) { sp->completed =0 ;
@@ -639,7 +636,7 @@ static void srcu_reschedule(struct srcu_struct *sp)/* * This is the work-queue function that handles SRCU grace periods. */ -static void process_srcu (struct work_struct *work) +void process_srcu (struct work_struct *work) {struct srcu_struct *sp;
@@ -650,3 +647,4 @@ static void process_srcu(struct work_struct *work)srcu_invoke_callbacks (sp);srcu_reschedule (sp); } +EXPORT_SYMBOL_GPL (process_srcu);
Signature · 1 line
1.7.8
PATCH 3/4 srcu: Add DEFINE_SRCU()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
In old days, we had two different API sets for dynamic-allocated per-CPU data and DEFINE_PER_CPU()-defined per_cpu data, and because SRCU used dynamic-allocated per-CPU data, its srcu_struct structures cannot be declared statically. This commit therefore introduces DEFINE_SRCU() and DEFINE_STATIC_SRCU() to allow statically declared SRCU structures, using the new static per-CPU interfaces.
[ paulmck: Updated for __DELAYED_WORK_INITIALIZER() added argument,
fixed whitespace issue. ]
--- include/linux/srcu.h | 30 ++++++++++++++++++++++++++++++ 1 files changed, 30 insertions(+), 0 deletions(-)
include/linux/srcu.h +30 -0
@@ -42,6 +42,8 @@ struct rcu_batch {struct rcu_head *head, **tail; }; +#define RCU_BATCH_INIT (name) { NULL, &(name.head) } +struct srcu_struct {unsigned completed;struct srcu_struct_array __percpu *per_cpu_ref;
@@ -72,14 +74,42 @@ int __init_srcu_struct(struct srcu_struct *sp, const char *name, __init_srcu_struct((sp), #sp, &__srcu_key); \ }) +#define __SRCU_DEP_MAP_INIT (srcu_name) .dep_map = { .name = #srcu_name },#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ int init_srcu_struct (struct srcu_struct *sp); +#define __SRCU_DEP_MAP_INIT (srcu_name)#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ void process_srcu (struct work_struct *work); +#define __SRCU_STRUCT_INIT (name) \ + { \ + .completed = -300, \ + .per_cpu_ref = &name##_srcu_array, \ + .queue_lock = __SPIN_LOCK_UNLOCKED(name.queue_lock), \ + .running = false, \ + .batch_queue = RCU_BATCH_INIT(name.batch_queue), \ + .batch_check0 = RCU_BATCH_INIT(name.batch_check0), \ + .batch_check1 = RCU_BATCH_INIT(name.batch_check1), \ + .batch_done = RCU_BATCH_INIT(name.batch_done), \ + .work = __DELAYED_WORK_INITIALIZER(name.work, process_srcu, 0),\ + __SRCU_DEP_MAP_INIT(name) \ + } + +/* +* define and init a srcu struct at build time. +* dont't call init_srcu_struct() nor cleanup_srcu_struct() on it. +*/ +#define DEFINE_SRCU (name) \ + static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\ + struct srcu_struct name = __SRCU_STRUCT_INIT(name); + +#define DEFINE_STATIC_SRCU (name) \ + static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\ + static struct srcu_struct name = __SRCU_STRUCT_INIT(name); +/** * call_srcu() - Queue a callback for invocation after an SRCU grace period * @sp: srcu_struct in queue the callback
Signature · 1 line
1.7.8
PATCH 4/4 rcutorture: Use DEFINE_STATIC_SRCU()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
Use DEFINE_STATIC_SRCU() to simplify the rcutorture.c SRCU test code.
--- kernel/rcutorture.c | 41 ++++++----------------------------------- 1 files changed, 6 insertions(+), 35 deletions(-)
kernel/rcutorture.c +6 -35
@@ -339,7 +339,6 @@ rcu_stutter_wait(char *title)struct rcu_torture_ops {void (*init)(void ); -void (*cleanup)(void );int (*readlock)(void );void (*read_delay)(struct rcu_random_state *rrsp);void (*readunlock)(int idx);
@@ -431,7 +430,6 @@ static void rcu_torture_deferred_free(struct rcu_torture *p)static struct rcu_torture_ops rcu_ops = { .init =NULL , - .cleanup =NULL , .readlock = rcu_torture_read_lock, .read_delay = rcu_read_delay, .readunlock = rcu_torture_read_unlock,
@@ -475,7 +473,6 @@ static void rcu_sync_torture_init(void)static struct rcu_torture_ops rcu_sync_ops = { .init = rcu_sync_torture_init, - .cleanup =NULL , .readlock = rcu_torture_read_lock, .read_delay = rcu_read_delay, .readunlock = rcu_torture_read_unlock,
@@ -493,7 +490,6 @@ static struct rcu_torture_ops rcu_sync_ops = {static struct rcu_torture_ops rcu_expedited_ops = { .init = rcu_sync_torture_init, - .cleanup =NULL , .readlock = rcu_torture_read_lock, .read_delay = rcu_read_delay,/* just reuse rcu's version. */ .readunlock = rcu_torture_read_unlock,
@@ -536,7 +532,6 @@ static void rcu_bh_torture_deferred_free(struct rcu_torture *p)static struct rcu_torture_ops rcu_bh_ops = { .init =NULL , - .cleanup =NULL , .readlock = rcu_bh_torture_read_lock, .read_delay = rcu_read_delay,/* just reuse rcu's version. */ .readunlock = rcu_bh_torture_read_unlock,
@@ -553,7 +548,6 @@ static struct rcu_torture_ops rcu_bh_ops = {static struct rcu_torture_ops rcu_bh_sync_ops = { .init = rcu_sync_torture_init, - .cleanup =NULL , .readlock = rcu_bh_torture_read_lock, .read_delay = rcu_read_delay,/* just reuse rcu's version. */ .readunlock = rcu_bh_torture_read_unlock,
@@ -570,7 +564,6 @@ static struct rcu_torture_ops rcu_bh_sync_ops = {static struct rcu_torture_ops rcu_bh_expedited_ops = { .init = rcu_sync_torture_init, - .cleanup =NULL , .readlock = rcu_bh_torture_read_lock, .read_delay = rcu_read_delay,/* just reuse rcu's version. */ .readunlock = rcu_bh_torture_read_unlock,
@@ -589,19 +582,7 @@ static struct rcu_torture_ops rcu_bh_expedited_ops = {* Definitions for srcu torture testing. */ -static struct srcu_struct srcu_ctl; - -static void srcu_torture_init (void ) -{ -init_srcu_struct (&srcu_ctl); -rcu_sync_torture_init (); -} - -static void srcu_torture_cleanup (void ) -{ -synchronize_srcu (&srcu_ctl); -cleanup_srcu_struct (&srcu_ctl); -} +DEFINE_STATIC_SRCU (srcu_ctl); static int srcu_torture_read_lock(void) __acquires(&srcu_ctl) {
@@ -672,8 +653,7 @@ static int srcu_torture_stats(char *page) }static struct rcu_torture_ops srcu_ops = { - .init = srcu_torture_init, - .cleanup = srcu_torture_cleanup, + .init = rcu_sync_torture_init, .readlock = srcu_torture_read_lock, .read_delay = srcu_read_delay, .readunlock = srcu_torture_read_unlock,
@@ -687,8 +667,7 @@ static struct rcu_torture_ops srcu_ops = { };static struct rcu_torture_ops srcu_sync_ops = { - .init = srcu_torture_init, - .cleanup = srcu_torture_cleanup, + .init = rcu_sync_torture_init, .readlock = srcu_torture_read_lock, .read_delay = srcu_read_delay, .readunlock = srcu_torture_read_unlock,
@@ -712,8 +691,7 @@ static void srcu_torture_read_unlock_raw(int idx) __releases(&srcu_ctl) }static struct rcu_torture_ops srcu_raw_ops = { - .init = srcu_torture_init, - .cleanup = srcu_torture_cleanup, + .init = rcu_sync_torture_init, .readlock = srcu_torture_read_lock_raw, .read_delay = srcu_read_delay, .readunlock = srcu_torture_read_unlock_raw,
@@ -727,8 +705,7 @@ static struct rcu_torture_ops srcu_raw_ops = { };static struct rcu_torture_ops srcu_raw_sync_ops = { - .init = srcu_torture_init, - .cleanup = srcu_torture_cleanup, + .init = rcu_sync_torture_init, .readlock = srcu_torture_read_lock_raw, .read_delay = srcu_read_delay, .readunlock = srcu_torture_read_unlock_raw,
@@ -747,8 +724,7 @@ static void srcu_torture_synchronize_expedited(void) }static struct rcu_torture_ops srcu_expedited_ops = { - .init = srcu_torture_init, - .cleanup = srcu_torture_cleanup, + .init = rcu_sync_torture_init, .readlock = srcu_torture_read_lock, .read_delay = srcu_read_delay, .readunlock = srcu_torture_read_unlock,
@@ -783,7 +759,6 @@ static void rcu_sched_torture_deferred_free(struct rcu_torture *p)static struct rcu_torture_ops sched_ops = { .init = rcu_sync_torture_init, - .cleanup =NULL , .readlock = sched_torture_read_lock, .read_delay = rcu_read_delay,/* just reuse rcu's version. */ .readunlock = sched_torture_read_unlock,
@@ -799,7 +774,6 @@ static struct rcu_torture_ops sched_ops = {static struct rcu_torture_ops sched_sync_ops = { .init = rcu_sync_torture_init, - .cleanup =NULL , .readlock = sched_torture_read_lock, .read_delay = rcu_read_delay,/* just reuse rcu's version. */ .readunlock = sched_torture_read_unlock,
@@ -814,7 +788,6 @@ static struct rcu_torture_ops sched_sync_ops = {static struct rcu_torture_ops sched_expedited_ops = { .init = rcu_sync_torture_init, - .cleanup =NULL , .readlock = sched_torture_read_lock, .read_delay = rcu_read_delay,/* just reuse rcu's version. */ .readunlock = sched_torture_read_unlock,
@@ -1936,8 +1909,6 @@ rcu_torture_cleanup(void)rcu_torture_stats_print ();/* -After- the stats thread is stopped! */ -if (cur_ops->cleanup) - cur_ops->cleanup ();if (atomic_read (&n_rcu_torture_error) || n_rcu_torture_barrier_error)rcu_torture_print_module_parms (cur_ops,"End of test: FAILURE" ); else if (n_online_successes != n_online_attempts ||
Signature · 1 line
1.7.8