diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2006-10-04 05:17:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:31 -0400 |
commit | 20e9751bd9dd6b832fd84ada27840360f7e877f1 (patch) | |
tree | c598ff9cb9e540da7f8595f2c130f3674065e018 | |
parent | 4b6c2cca6eef9cc4a15350bf1c61839e12e08b84 (diff) |
[PATCH] rcu: simplify/improve batch tuning
Kill a hard-to-calculate 'rsinterval' boot parameter and per-cpu
rcu_data.last_rs_qlen. Instead, it adds adds a flag rcu_ctrlblk.signaled,
which records the fact that one of CPUs has sent a resched IPI since the
last rcu_start_batch().
Roughly speaking, we need two rcu_start_batch()s in order to move callbacks
from ->nxtlist to ->donelist. This means that when ->qlen exceeds qhimark
and continues to grow, we should send a resched IPI, and then do it again
after we gone through a quiescent state.
On the other hand, if it was already sent, we don't need to do it again
when another CPU detects overflow of the queue.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Acked-by: Paul E. McKenney <paulmck@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | Documentation/kernel-parameters.txt | 4 | ||||
-rw-r--r-- | include/linux/rcupdate.h | 5 | ||||
-rw-r--r-- | kernel/rcupdate.c | 11 |
3 files changed, 5 insertions, 15 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 12b3b24bfd2f..e1543a32a557 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1357,10 +1357,6 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1357 | rcu.qlowmark= [KNL,BOOT] Set threshold of queued | 1357 | rcu.qlowmark= [KNL,BOOT] Set threshold of queued |
1358 | RCU callbacks below which batch limiting is re-enabled. | 1358 | RCU callbacks below which batch limiting is re-enabled. |
1359 | 1359 | ||
1360 | rcu.rsinterval= [KNL,BOOT,SMP] Set the number of additional | ||
1361 | RCU callbacks to queued before forcing reschedule | ||
1362 | on all cpus. | ||
1363 | |||
1364 | rdinit= [KNL] | 1360 | rdinit= [KNL] |
1365 | Format: <full_path> | 1361 | Format: <full_path> |
1366 | Run specified binary instead of /init from the ramdisk, | 1362 | Run specified binary instead of /init from the ramdisk, |
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index b4ca73d65891..f6dd71bf8a4b 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -66,6 +66,8 @@ struct rcu_ctrlblk { | |||
66 | long completed; /* Number of the last completed batch */ | 66 | long completed; /* Number of the last completed batch */ |
67 | int next_pending; /* Is the next batch already waiting? */ | 67 | int next_pending; /* Is the next batch already waiting? */ |
68 | 68 | ||
69 | int signaled; | ||
70 | |||
69 | spinlock_t lock ____cacheline_internodealigned_in_smp; | 71 | spinlock_t lock ____cacheline_internodealigned_in_smp; |
70 | cpumask_t cpumask; /* CPUs that need to switch in order */ | 72 | cpumask_t cpumask; /* CPUs that need to switch in order */ |
71 | /* for current batch to proceed. */ | 73 | /* for current batch to proceed. */ |
@@ -106,9 +108,6 @@ struct rcu_data { | |||
106 | long blimit; /* Upper limit on a processed batch */ | 108 | long blimit; /* Upper limit on a processed batch */ |
107 | int cpu; | 109 | int cpu; |
108 | struct rcu_head barrier; | 110 | struct rcu_head barrier; |
109 | #ifdef CONFIG_SMP | ||
110 | long last_rs_qlen; /* qlen during the last resched */ | ||
111 | #endif | ||
112 | }; | 111 | }; |
113 | 112 | ||
114 | DECLARE_PER_CPU(struct rcu_data, rcu_data); | 113 | DECLARE_PER_CPU(struct rcu_data, rcu_data); |
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 523e46483b99..26bb5ffe1ef1 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
@@ -71,9 +71,6 @@ static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL}; | |||
71 | static int blimit = 10; | 71 | static int blimit = 10; |
72 | static int qhimark = 10000; | 72 | static int qhimark = 10000; |
73 | static int qlowmark = 100; | 73 | static int qlowmark = 100; |
74 | #ifdef CONFIG_SMP | ||
75 | static int rsinterval = 1000; | ||
76 | #endif | ||
77 | 74 | ||
78 | static atomic_t rcu_barrier_cpu_count; | 75 | static atomic_t rcu_barrier_cpu_count; |
79 | static DEFINE_MUTEX(rcu_barrier_mutex); | 76 | static DEFINE_MUTEX(rcu_barrier_mutex); |
@@ -86,8 +83,8 @@ static void force_quiescent_state(struct rcu_data *rdp, | |||
86 | int cpu; | 83 | int cpu; |
87 | cpumask_t cpumask; | 84 | cpumask_t cpumask; |
88 | set_need_resched(); | 85 | set_need_resched(); |
89 | if (unlikely(rdp->qlen - rdp->last_rs_qlen > rsinterval)) { | 86 | if (unlikely(!rcp->signaled)) { |
90 | rdp->last_rs_qlen = rdp->qlen; | 87 | rcp->signaled = 1; |
91 | /* | 88 | /* |
92 | * Don't send IPI to itself. With irqs disabled, | 89 | * Don't send IPI to itself. With irqs disabled, |
93 | * rdp->cpu is the current cpu. | 90 | * rdp->cpu is the current cpu. |
@@ -301,6 +298,7 @@ static void rcu_start_batch(struct rcu_ctrlblk *rcp) | |||
301 | smp_mb(); | 298 | smp_mb(); |
302 | cpus_andnot(rcp->cpumask, cpu_online_map, nohz_cpu_mask); | 299 | cpus_andnot(rcp->cpumask, cpu_online_map, nohz_cpu_mask); |
303 | 300 | ||
301 | rcp->signaled = 0; | ||
304 | } | 302 | } |
305 | } | 303 | } |
306 | 304 | ||
@@ -628,9 +626,6 @@ void synchronize_rcu(void) | |||
628 | module_param(blimit, int, 0); | 626 | module_param(blimit, int, 0); |
629 | module_param(qhimark, int, 0); | 627 | module_param(qhimark, int, 0); |
630 | module_param(qlowmark, int, 0); | 628 | module_param(qlowmark, int, 0); |
631 | #ifdef CONFIG_SMP | ||
632 | module_param(rsinterval, int, 0); | ||
633 | #endif | ||
634 | EXPORT_SYMBOL_GPL(rcu_batches_completed); | 629 | EXPORT_SYMBOL_GPL(rcu_batches_completed); |
635 | EXPORT_SYMBOL_GPL(rcu_batches_completed_bh); | 630 | EXPORT_SYMBOL_GPL(rcu_batches_completed_bh); |
636 | EXPORT_SYMBOL_GPL(call_rcu); | 631 | EXPORT_SYMBOL_GPL(call_rcu); |