diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2015-02-18 15:24:30 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2015-02-26 15:02:59 -0500 |
commit | 0d39482c3db13aae1db143d340816108dd53e443 (patch) | |
tree | dbcf5c785244bd29da2190d65a92fb1ca497a009 | |
parent | c517d838eb7d07bbe9507871fab3931deccff539 (diff) |
rcu: Provide rcu_expedite_gp() and rcu_unexpedite_gp()
Currently, expediting of normal synchronous grace-period primitives
(synchronize_rcu() and friends) is controlled by the rcu_expedited()
boot/sysfs parameter. This works well, but does not handle nesting.
This commit therefore provides rcu_expedite_gp() to enable expediting
and rcu_unexpedite_gp() to cancel a prior rcu_expedite_gp(), both of
which support nesting.
Reported-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r-- | include/linux/rcupdate.h | 20 | ||||
-rw-r--r-- | kernel/rcu/update.c | 48 |
2 files changed, 68 insertions, 0 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 78097491cd99..57a4d1f73a00 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -48,6 +48,26 @@ | |||
48 | 48 | ||
49 | extern int rcu_expedited; /* for sysctl */ | 49 | extern int rcu_expedited; /* for sysctl */ |
50 | 50 | ||
51 | #ifdef CONFIG_TINY_RCU | ||
52 | /* Tiny RCU doesn't expedite, as its purpose in life is instead to be tiny. */ | ||
53 | static inline bool rcu_gp_is_expedited(void) /* Internal RCU use. */ | ||
54 | { | ||
55 | return false; | ||
56 | } | ||
57 | |||
58 | static inline void rcu_expedite_gp(void) | ||
59 | { | ||
60 | } | ||
61 | |||
62 | static inline void rcu_unexpedite_gp(void) | ||
63 | { | ||
64 | } | ||
65 | #else /* #ifdef CONFIG_TINY_RCU */ | ||
66 | bool rcu_gp_is_expedited(void); /* Internal RCU use. */ | ||
67 | void rcu_expedite_gp(void); | ||
68 | void rcu_unexpedite_gp(void); | ||
69 | #endif /* #else #ifdef CONFIG_TINY_RCU */ | ||
70 | |||
51 | enum rcutorture_type { | 71 | enum rcutorture_type { |
52 | RCU_FLAVOR, | 72 | RCU_FLAVOR, |
53 | RCU_BH_FLAVOR, | 73 | RCU_BH_FLAVOR, |
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index e0d31a345ee6..5f850823c187 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c | |||
@@ -62,6 +62,54 @@ MODULE_ALIAS("rcupdate"); | |||
62 | 62 | ||
63 | module_param(rcu_expedited, int, 0); | 63 | module_param(rcu_expedited, int, 0); |
64 | 64 | ||
65 | #ifndef CONFIG_TINY_RCU | ||
66 | |||
67 | static atomic_t rcu_expedited_nesting; | ||
68 | |||
69 | /* | ||
70 | * Should normal grace-period primitives be expedited? Intended for | ||
71 | * use within RCU. Note that this function takes the rcu_expedited | ||
72 | * sysfs/boot variable into account as well as the rcu_expedite_gp() | ||
73 | * nesting. So looping on rcu_unexpedite_gp() until rcu_gp_is_expedited() | ||
74 | * returns false is a -really- bad idea. | ||
75 | */ | ||
76 | bool rcu_gp_is_expedited(void) | ||
77 | { | ||
78 | return rcu_expedited || atomic_read(&rcu_expedited_nesting); | ||
79 | } | ||
80 | EXPORT_SYMBOL_GPL(rcu_gp_is_expedited); | ||
81 | |||
82 | /** | ||
83 | * rcu_expedite_gp - Expedite future RCU grace periods | ||
84 | * | ||
85 | * After a call to this function, future calls to synchronize_rcu() and | ||
86 | * friends act as the corresponding synchronize_rcu_expedited() function | ||
87 | * had instead been called. | ||
88 | */ | ||
89 | void rcu_expedite_gp(void) | ||
90 | { | ||
91 | atomic_inc(&rcu_expedited_nesting); | ||
92 | } | ||
93 | EXPORT_SYMBOL_GPL(rcu_expedite_gp); | ||
94 | |||
95 | /** | ||
96 | * rcu_unexpedite_gp - Cancel prior rcu_expedite_gp() invocation | ||
97 | * | ||
98 | * Undo a prior call to rcu_expedite_gp(). If all prior calls to | ||
99 | * rcu_expedite_gp() are undone by a subsequent call to rcu_unexpedite_gp(), | ||
100 | * and if the rcu_expedited sysfs/boot parameter is not set, then all | ||
101 | * subsequent calls to synchronize_rcu() and friends will return to | ||
102 | * their normal non-expedited behavior. | ||
103 | */ | ||
104 | void rcu_unexpedite_gp(void) | ||
105 | { | ||
106 | atomic_dec(&rcu_expedited_nesting); | ||
107 | } | ||
108 | EXPORT_SYMBOL_GPL(rcu_unexpedite_gp); | ||
109 | |||
110 | #endif /* #ifndef CONFIG_TINY_RCU */ | ||
111 | |||
112 | |||
65 | #ifdef CONFIG_PREEMPT_RCU | 113 | #ifdef CONFIG_PREEMPT_RCU |
66 | 114 | ||
67 | /* | 115 | /* |