diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 13 | ||||
-rw-r--r-- | include/linux/rcupdate.h | 6 | ||||
-rw-r--r-- | kernel/rcupdate.c | 76 |
3 files changed, 76 insertions, 19 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 75205391b335..bad5987c4727 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1284,6 +1284,19 @@ running once the system is up. | |||
1284 | New name for the ramdisk parameter. | 1284 | New name for the ramdisk parameter. |
1285 | See Documentation/ramdisk.txt. | 1285 | See Documentation/ramdisk.txt. |
1286 | 1286 | ||
1287 | rcu.blimit= [KNL,BOOT] Set maximum number of finished | ||
1288 | RCU callbacks to process in one batch. | ||
1289 | |||
1290 | rcu.qhimark= [KNL,BOOT] Set threshold of queued | ||
1291 | RCU callbacks over which batch limiting is disabled. | ||
1292 | |||
1293 | rcu.qlowmark= [KNL,BOOT] Set threshold of queued | ||
1294 | RCU callbacks below which batch limiting is re-enabled. | ||
1295 | |||
1296 | rcu.rsinterval= [KNL,BOOT,SMP] Set the number of additional | ||
1297 | RCU callbacks to queued before forcing reschedule | ||
1298 | on all cpus. | ||
1299 | |||
1287 | rdinit= [KNL] | 1300 | rdinit= [KNL] |
1288 | Format: <full_path> | 1301 | Format: <full_path> |
1289 | Run specified binary instead of /init from the ramdisk, | 1302 | Run specified binary instead of /init from the ramdisk, |
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index b87aefa082e2..c2ec6c77874e 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -98,13 +98,17 @@ struct rcu_data { | |||
98 | long batch; /* Batch # for current RCU batch */ | 98 | long batch; /* Batch # for current RCU batch */ |
99 | struct rcu_head *nxtlist; | 99 | struct rcu_head *nxtlist; |
100 | struct rcu_head **nxttail; | 100 | struct rcu_head **nxttail; |
101 | long count; /* # of queued items */ | 101 | long qlen; /* # of queued callbacks */ |
102 | struct rcu_head *curlist; | 102 | struct rcu_head *curlist; |
103 | struct rcu_head **curtail; | 103 | struct rcu_head **curtail; |
104 | struct rcu_head *donelist; | 104 | struct rcu_head *donelist; |
105 | struct rcu_head **donetail; | 105 | struct rcu_head **donetail; |
106 | long blimit; /* Upper limit on a processed batch */ | ||
106 | int cpu; | 107 | int cpu; |
107 | struct rcu_head barrier; | 108 | struct rcu_head barrier; |
109 | #ifdef CONFIG_SMP | ||
110 | long last_rs_qlen; /* qlen during the last resched */ | ||
111 | #endif | ||
108 | }; | 112 | }; |
109 | 113 | ||
110 | DECLARE_PER_CPU(struct rcu_data, rcu_data); | 114 | DECLARE_PER_CPU(struct rcu_data, rcu_data); |
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 0cf8146bd585..8cf15a569fcd 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
@@ -67,7 +67,43 @@ DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L }; | |||
67 | 67 | ||
68 | /* Fake initialization required by compiler */ | 68 | /* Fake initialization required by compiler */ |
69 | static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL}; | 69 | static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL}; |
70 | static int maxbatch = 10000; | 70 | static int blimit = 10; |
71 | static int qhimark = 10000; | ||
72 | static int qlowmark = 100; | ||
73 | #ifdef CONFIG_SMP | ||
74 | static int rsinterval = 1000; | ||
75 | #endif | ||
76 | |||
77 | static atomic_t rcu_barrier_cpu_count; | ||
78 | static struct semaphore rcu_barrier_sema; | ||
79 | static struct completion rcu_barrier_completion; | ||
80 | |||
81 | #ifdef CONFIG_SMP | ||
82 | static void force_quiescent_state(struct rcu_data *rdp, | ||
83 | struct rcu_ctrlblk *rcp) | ||
84 | { | ||
85 | int cpu; | ||
86 | cpumask_t cpumask; | ||
87 | set_need_resched(); | ||
88 | if (unlikely(rdp->qlen - rdp->last_rs_qlen > rsinterval)) { | ||
89 | rdp->last_rs_qlen = rdp->qlen; | ||
90 | /* | ||
91 | * Don't send IPI to itself. With irqs disabled, | ||
92 | * rdp->cpu is the current cpu. | ||
93 | */ | ||
94 | cpumask = rcp->cpumask; | ||
95 | cpu_clear(rdp->cpu, cpumask); | ||
96 | for_each_cpu_mask(cpu, cpumask) | ||
97 | smp_send_reschedule(cpu); | ||
98 | } | ||
99 | } | ||
100 | #else | ||
101 | static inline void force_quiescent_state(struct rcu_data *rdp, | ||
102 | struct rcu_ctrlblk *rcp) | ||
103 | { | ||
104 | set_need_resched(); | ||
105 | } | ||
106 | #endif | ||
71 | 107 | ||
72 | /** | 108 | /** |
73 | * call_rcu - Queue an RCU callback for invocation after a grace period. | 109 | * call_rcu - Queue an RCU callback for invocation after a grace period. |
@@ -92,17 +128,13 @@ void fastcall call_rcu(struct rcu_head *head, | |||
92 | rdp = &__get_cpu_var(rcu_data); | 128 | rdp = &__get_cpu_var(rcu_data); |
93 | *rdp->nxttail = head; | 129 | *rdp->nxttail = head; |
94 | rdp->nxttail = &head->next; | 130 | rdp->nxttail = &head->next; |
95 | 131 | if (unlikely(++rdp->qlen > qhimark)) { | |
96 | if (unlikely(++rdp->count > 10000)) | 132 | rdp->blimit = INT_MAX; |
97 | set_need_resched(); | 133 | force_quiescent_state(rdp, &rcu_ctrlblk); |
98 | 134 | } | |
99 | local_irq_restore(flags); | 135 | local_irq_restore(flags); |
100 | } | 136 | } |
101 | 137 | ||
102 | static atomic_t rcu_barrier_cpu_count; | ||
103 | static struct semaphore rcu_barrier_sema; | ||
104 | static struct completion rcu_barrier_completion; | ||
105 | |||
106 | /** | 138 | /** |
107 | * call_rcu_bh - Queue an RCU for invocation after a quicker grace period. | 139 | * call_rcu_bh - Queue an RCU for invocation after a quicker grace period. |
108 | * @head: structure to be used for queueing the RCU updates. | 140 | * @head: structure to be used for queueing the RCU updates. |
@@ -131,12 +163,12 @@ void fastcall call_rcu_bh(struct rcu_head *head, | |||
131 | rdp = &__get_cpu_var(rcu_bh_data); | 163 | rdp = &__get_cpu_var(rcu_bh_data); |
132 | *rdp->nxttail = head; | 164 | *rdp->nxttail = head; |
133 | rdp->nxttail = &head->next; | 165 | rdp->nxttail = &head->next; |
134 | rdp->count++; | 166 | |
135 | /* | 167 | if (unlikely(++rdp->qlen > qhimark)) { |
136 | * Should we directly call rcu_do_batch() here ? | 168 | rdp->blimit = INT_MAX; |
137 | * if (unlikely(rdp->count > 10000)) | 169 | force_quiescent_state(rdp, &rcu_bh_ctrlblk); |
138 | * rcu_do_batch(rdp); | 170 | } |
139 | */ | 171 | |
140 | local_irq_restore(flags); | 172 | local_irq_restore(flags); |
141 | } | 173 | } |
142 | 174 | ||
@@ -199,10 +231,12 @@ static void rcu_do_batch(struct rcu_data *rdp) | |||
199 | next = rdp->donelist = list->next; | 231 | next = rdp->donelist = list->next; |
200 | list->func(list); | 232 | list->func(list); |
201 | list = next; | 233 | list = next; |
202 | rdp->count--; | 234 | rdp->qlen--; |
203 | if (++count >= maxbatch) | 235 | if (++count >= rdp->blimit) |
204 | break; | 236 | break; |
205 | } | 237 | } |
238 | if (rdp->blimit == INT_MAX && rdp->qlen <= qlowmark) | ||
239 | rdp->blimit = blimit; | ||
206 | if (!rdp->donelist) | 240 | if (!rdp->donelist) |
207 | rdp->donetail = &rdp->donelist; | 241 | rdp->donetail = &rdp->donelist; |
208 | else | 242 | else |
@@ -473,6 +507,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, | |||
473 | rdp->quiescbatch = rcp->completed; | 507 | rdp->quiescbatch = rcp->completed; |
474 | rdp->qs_pending = 0; | 508 | rdp->qs_pending = 0; |
475 | rdp->cpu = cpu; | 509 | rdp->cpu = cpu; |
510 | rdp->blimit = blimit; | ||
476 | } | 511 | } |
477 | 512 | ||
478 | static void __devinit rcu_online_cpu(int cpu) | 513 | static void __devinit rcu_online_cpu(int cpu) |
@@ -567,7 +602,12 @@ void synchronize_kernel(void) | |||
567 | synchronize_rcu(); | 602 | synchronize_rcu(); |
568 | } | 603 | } |
569 | 604 | ||
570 | module_param(maxbatch, int, 0); | 605 | module_param(blimit, int, 0); |
606 | module_param(qhimark, int, 0); | ||
607 | module_param(qlowmark, int, 0); | ||
608 | #ifdef CONFIG_SMP | ||
609 | module_param(rsinterval, int, 0); | ||
610 | #endif | ||
571 | EXPORT_SYMBOL_GPL(rcu_batches_completed); | 611 | EXPORT_SYMBOL_GPL(rcu_batches_completed); |
572 | EXPORT_SYMBOL(call_rcu); /* WARNING: GPL-only in April 2006. */ | 612 | EXPORT_SYMBOL(call_rcu); /* WARNING: GPL-only in April 2006. */ |
573 | EXPORT_SYMBOL(call_rcu_bh); /* WARNING: GPL-only in April 2006. */ | 613 | EXPORT_SYMBOL(call_rcu_bh); /* WARNING: GPL-only in April 2006. */ |