aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti P Miettinen <ananaza@iki.fi>2012-10-05 02:59:15 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-10-23 17:54:08 -0400
commit3705b88db0d7cc4a097c32d9e554054103d3f807 (patch)
treef3baf8c94363506964c9f944496267f74cdee47c
parentba49df4767d4fa5bbd2af3a51709fb81f94264ec (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.c18
-rw-r--r--kernel/rcu.h2
-rw-r--r--kernel/rcupdate.c3
-rw-r--r--kernel/rcutiny_plugin.h5
-rw-r--r--kernel/rcutree.c12
-rw-r--r--kernel/rcutree_plugin.h7
-rw-r--r--kernel/srcu.c8
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}
142KERNEL_ATTR_RO(fscaps); 142KERNEL_ATTR_RO(fscaps);
143 143
144int rcu_expedited;
145static 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}
150static 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}
159KERNEL_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
112extern 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
56module_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}
711EXPORT_SYMBOL_GPL(synchronize_rcu); 714EXPORT_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}
2229EXPORT_SYMBOL_GPL(synchronize_sched); 2232EXPORT_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}
2250EXPORT_SYMBOL_GPL(synchronize_rcu_bh); 2256EXPORT_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}
684EXPORT_SYMBOL_GPL(synchronize_rcu); 687EXPORT_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 */
465void synchronize_srcu(struct srcu_struct *sp) 469void 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}
469EXPORT_SYMBOL_GPL(synchronize_srcu); 475EXPORT_SYMBOL_GPL(synchronize_srcu);
470 476