diff options
author | Antti P Miettinen <ananaza@iki.fi> | 2012-10-05 02:59:15 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-10-23 17:54:08 -0400 |
commit | 3705b88db0d7cc4a097c32d9e554054103d3f807 (patch) | |
tree | f3baf8c94363506964c9f944496267f74cdee47c | |
parent | ba49df4767d4fa5bbd2af3a51709fb81f94264ec (diff) |
rcu: Add a module parameter to force use of expedited RCU primitives
There have been some embedded applications that would benefit from
use of expedited grace-period primitives. In some ways, this is
similar to synchronize_net() doing either a normal or an expedited
grace period depending on lock state, but with control outside of
the kernel.
This commit therefore adds rcu_expedited boot and sysfs parameters
that cause the kernel to substitute expedited primitives for the
normal grace-period primitives.
[ paulmck: Add trace/event/rcu.h to kernel/srcu.c to avoid build error.
Get rid of infinite loop through contention path.]
Signed-off-by: Antti P Miettinen <amiettinen@nvidia.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r-- | kernel/ksysfs.c | 18 | ||||
-rw-r--r-- | kernel/rcu.h | 2 | ||||
-rw-r--r-- | kernel/rcupdate.c | 3 | ||||
-rw-r--r-- | kernel/rcutiny_plugin.h | 5 | ||||
-rw-r--r-- | kernel/rcutree.c | 12 | ||||
-rw-r--r-- | kernel/rcutree_plugin.h | 7 | ||||
-rw-r--r-- | kernel/srcu.c | 8 |
7 files changed, 48 insertions, 7 deletions
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 4e316e1acf58..8715a798aa7c 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c | |||
@@ -141,6 +141,23 @@ static ssize_t fscaps_show(struct kobject *kobj, | |||
141 | } | 141 | } |
142 | KERNEL_ATTR_RO(fscaps); | 142 | KERNEL_ATTR_RO(fscaps); |
143 | 143 | ||
144 | int rcu_expedited; | ||
145 | static ssize_t rcu_expedited_show(struct kobject *kobj, | ||
146 | struct kobj_attribute *attr, char *buf) | ||
147 | { | ||
148 | return sprintf(buf, "%d\n", rcu_expedited); | ||
149 | } | ||
150 | static ssize_t rcu_expedited_store(struct kobject *kobj, | ||
151 | struct kobj_attribute *attr, | ||
152 | const char *buf, size_t count) | ||
153 | { | ||
154 | if (kstrtoint(buf, 0, &rcu_expedited)) | ||
155 | return -EINVAL; | ||
156 | |||
157 | return count; | ||
158 | } | ||
159 | KERNEL_ATTR_RW(rcu_expedited); | ||
160 | |||
144 | /* | 161 | /* |
145 | * Make /sys/kernel/notes give the raw contents of our kernel .notes section. | 162 | * Make /sys/kernel/notes give the raw contents of our kernel .notes section. |
146 | */ | 163 | */ |
@@ -182,6 +199,7 @@ static struct attribute * kernel_attrs[] = { | |||
182 | &kexec_crash_size_attr.attr, | 199 | &kexec_crash_size_attr.attr, |
183 | &vmcoreinfo_attr.attr, | 200 | &vmcoreinfo_attr.attr, |
184 | #endif | 201 | #endif |
202 | &rcu_expedited_attr.attr, | ||
185 | NULL | 203 | NULL |
186 | }; | 204 | }; |
187 | 205 | ||
diff --git a/kernel/rcu.h b/kernel/rcu.h index 8ba99cdc6515..20dfba576c2b 100644 --- a/kernel/rcu.h +++ b/kernel/rcu.h | |||
@@ -109,4 +109,6 @@ static inline bool __rcu_reclaim(char *rn, struct rcu_head *head) | |||
109 | } | 109 | } |
110 | } | 110 | } |
111 | 111 | ||
112 | extern int rcu_expedited; | ||
113 | |||
112 | #endif /* __LINUX_RCU_H */ | 114 | #endif /* __LINUX_RCU_H */ |
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 29ca1c6da594..a2cf76177b44 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
@@ -46,12 +46,15 @@ | |||
46 | #include <linux/export.h> | 46 | #include <linux/export.h> |
47 | #include <linux/hardirq.h> | 47 | #include <linux/hardirq.h> |
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/module.h> | ||
49 | 50 | ||
50 | #define CREATE_TRACE_POINTS | 51 | #define CREATE_TRACE_POINTS |
51 | #include <trace/events/rcu.h> | 52 | #include <trace/events/rcu.h> |
52 | 53 | ||
53 | #include "rcu.h" | 54 | #include "rcu.h" |
54 | 55 | ||
56 | module_param(rcu_expedited, int, 0); | ||
57 | |||
55 | #ifdef CONFIG_PREEMPT_RCU | 58 | #ifdef CONFIG_PREEMPT_RCU |
56 | 59 | ||
57 | /* | 60 | /* |
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h index 3d0190282204..f85016a2309b 100644 --- a/kernel/rcutiny_plugin.h +++ b/kernel/rcutiny_plugin.h | |||
@@ -706,7 +706,10 @@ void synchronize_rcu(void) | |||
706 | return; | 706 | return; |
707 | 707 | ||
708 | /* Once we get past the fastpath checks, same code as rcu_barrier(). */ | 708 | /* Once we get past the fastpath checks, same code as rcu_barrier(). */ |
709 | rcu_barrier(); | 709 | if (rcu_expedited) |
710 | synchronize_rcu_expedited(); | ||
711 | else | ||
712 | rcu_barrier(); | ||
710 | } | 713 | } |
711 | EXPORT_SYMBOL_GPL(synchronize_rcu); | 714 | EXPORT_SYMBOL_GPL(synchronize_rcu); |
712 | 715 | ||
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 74df86bd9204..f9c17c399538 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -2224,7 +2224,10 @@ void synchronize_sched(void) | |||
2224 | "Illegal synchronize_sched() in RCU-sched read-side critical section"); | 2224 | "Illegal synchronize_sched() in RCU-sched read-side critical section"); |
2225 | if (rcu_blocking_is_gp()) | 2225 | if (rcu_blocking_is_gp()) |
2226 | return; | 2226 | return; |
2227 | wait_rcu_gp(call_rcu_sched); | 2227 | if (rcu_expedited) |
2228 | synchronize_sched_expedited(); | ||
2229 | else | ||
2230 | wait_rcu_gp(call_rcu_sched); | ||
2228 | } | 2231 | } |
2229 | EXPORT_SYMBOL_GPL(synchronize_sched); | 2232 | EXPORT_SYMBOL_GPL(synchronize_sched); |
2230 | 2233 | ||
@@ -2245,7 +2248,10 @@ void synchronize_rcu_bh(void) | |||
2245 | "Illegal synchronize_rcu_bh() in RCU-bh read-side critical section"); | 2248 | "Illegal synchronize_rcu_bh() in RCU-bh read-side critical section"); |
2246 | if (rcu_blocking_is_gp()) | 2249 | if (rcu_blocking_is_gp()) |
2247 | return; | 2250 | return; |
2248 | wait_rcu_gp(call_rcu_bh); | 2251 | if (rcu_expedited) |
2252 | synchronize_rcu_bh_expedited(); | ||
2253 | else | ||
2254 | wait_rcu_gp(call_rcu_bh); | ||
2249 | } | 2255 | } |
2250 | EXPORT_SYMBOL_GPL(synchronize_rcu_bh); | 2256 | EXPORT_SYMBOL_GPL(synchronize_rcu_bh); |
2251 | 2257 | ||
@@ -2328,7 +2334,7 @@ void synchronize_sched_expedited(void) | |||
2328 | if (trycount++ < 10) { | 2334 | if (trycount++ < 10) { |
2329 | udelay(trycount * num_online_cpus()); | 2335 | udelay(trycount * num_online_cpus()); |
2330 | } else { | 2336 | } else { |
2331 | synchronize_sched(); | 2337 | wait_rcu_gp(call_rcu_sched); |
2332 | return; | 2338 | return; |
2333 | } | 2339 | } |
2334 | 2340 | ||
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index f92115488187..c177ba0cce9a 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h | |||
@@ -679,7 +679,10 @@ void synchronize_rcu(void) | |||
679 | "Illegal synchronize_rcu() in RCU read-side critical section"); | 679 | "Illegal synchronize_rcu() in RCU read-side critical section"); |
680 | if (!rcu_scheduler_active) | 680 | if (!rcu_scheduler_active) |
681 | return; | 681 | return; |
682 | wait_rcu_gp(call_rcu); | 682 | if (rcu_expedited) |
683 | synchronize_rcu_expedited(); | ||
684 | else | ||
685 | wait_rcu_gp(call_rcu); | ||
683 | } | 686 | } |
684 | EXPORT_SYMBOL_GPL(synchronize_rcu); | 687 | EXPORT_SYMBOL_GPL(synchronize_rcu); |
685 | 688 | ||
@@ -831,7 +834,7 @@ void synchronize_rcu_expedited(void) | |||
831 | udelay(trycount * num_online_cpus()); | 834 | udelay(trycount * num_online_cpus()); |
832 | } else { | 835 | } else { |
833 | put_online_cpus(); | 836 | put_online_cpus(); |
834 | synchronize_rcu(); | 837 | wait_rcu_gp(call_rcu); |
835 | return; | 838 | return; |
836 | } | 839 | } |
837 | } | 840 | } |
diff --git a/kernel/srcu.c b/kernel/srcu.c index 97c465ebd844..de9074047c92 100644 --- a/kernel/srcu.c +++ b/kernel/srcu.c | |||
@@ -34,6 +34,10 @@ | |||
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/srcu.h> | 35 | #include <linux/srcu.h> |
36 | 36 | ||
37 | #include <trace/events/rcu.h> | ||
38 | |||
39 | #include "rcu.h" | ||
40 | |||
37 | /* | 41 | /* |
38 | * Initialize an rcu_batch structure to empty. | 42 | * Initialize an rcu_batch structure to empty. |
39 | */ | 43 | */ |
@@ -464,7 +468,9 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount) | |||
464 | */ | 468 | */ |
465 | void synchronize_srcu(struct srcu_struct *sp) | 469 | void synchronize_srcu(struct srcu_struct *sp) |
466 | { | 470 | { |
467 | __synchronize_srcu(sp, SYNCHRONIZE_SRCU_TRYCOUNT); | 471 | __synchronize_srcu(sp, rcu_expedited |
472 | ? SYNCHRONIZE_SRCU_EXP_TRYCOUNT | ||
473 | : SYNCHRONIZE_SRCU_TRYCOUNT); | ||
468 | } | 474 | } |
469 | EXPORT_SYMBOL_GPL(synchronize_srcu); | 475 | EXPORT_SYMBOL_GPL(synchronize_srcu); |
470 | 476 | ||