aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutiny_plugin.h
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2010-09-09 16:40:39 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2010-11-17 18:45:09 -0500
commitb2c0710c464ede15e1fc52fb1e7ee9ba54cea186 (patch)
tree7524518fec8a02e53c3fab558b40a5e94f0bb5ec /kernel/rcutiny_plugin.h
parent8e8be45e8e55daa381028aec339829929ddb53a5 (diff)
rcu: move TINY_RCU from softirq to kthread
If RCU priority boosting is to be meaningful, callback invocation must be boosted in addition to preempted RCU readers. Otherwise, in presence of CPU real-time threads, the grace period ends, but the callbacks don't get invoked. If the callbacks don't get invoked, the associated memory doesn't get freed, so the system is still subject to OOM. But it is not reasonable to priority-boost RCU_SOFTIRQ, so this commit moves the callback invocations to a kthread, which can be boosted easily. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcutiny_plugin.h')
-rw-r--r--kernel/rcutiny_plugin.h15
1 files changed, 8 insertions, 7 deletions
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
index 6ceca4f745ff..95f9239df512 100644
--- a/kernel/rcutiny_plugin.h
+++ b/kernel/rcutiny_plugin.h
@@ -22,6 +22,8 @@
22 * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 22 * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
23 */ 23 */
24 24
25#include <linux/kthread.h>
26
25#ifdef CONFIG_TINY_PREEMPT_RCU 27#ifdef CONFIG_TINY_PREEMPT_RCU
26 28
27#include <linux/delay.h> 29#include <linux/delay.h>
@@ -164,9 +166,9 @@ static void rcu_preempt_cpu_qs(void)
164 if (!rcu_preempt_blocked_readers_any()) 166 if (!rcu_preempt_blocked_readers_any())
165 rcu_preempt_ctrlblk.rcb.donetail = rcu_preempt_ctrlblk.nexttail; 167 rcu_preempt_ctrlblk.rcb.donetail = rcu_preempt_ctrlblk.nexttail;
166 168
167 /* If there are done callbacks, make RCU_SOFTIRQ process them. */ 169 /* If there are done callbacks, cause them to be invoked. */
168 if (*rcu_preempt_ctrlblk.rcb.donetail != NULL) 170 if (*rcu_preempt_ctrlblk.rcb.donetail != NULL)
169 raise_softirq(RCU_SOFTIRQ); 171 invoke_rcu_cbs();
170} 172}
171 173
172/* 174/*
@@ -374,7 +376,7 @@ static void rcu_preempt_check_callbacks(void)
374 rcu_preempt_cpu_qs(); 376 rcu_preempt_cpu_qs();
375 if (&rcu_preempt_ctrlblk.rcb.rcucblist != 377 if (&rcu_preempt_ctrlblk.rcb.rcucblist !=
376 rcu_preempt_ctrlblk.rcb.donetail) 378 rcu_preempt_ctrlblk.rcb.donetail)
377 raise_softirq(RCU_SOFTIRQ); 379 invoke_rcu_cbs();
378 if (rcu_preempt_gp_in_progress() && 380 if (rcu_preempt_gp_in_progress() &&
379 rcu_cpu_blocking_cur_gp() && 381 rcu_cpu_blocking_cur_gp() &&
380 rcu_preempt_running_reader()) 382 rcu_preempt_running_reader())
@@ -383,7 +385,7 @@ static void rcu_preempt_check_callbacks(void)
383 385
384/* 386/*
385 * TINY_PREEMPT_RCU has an extra callback-list tail pointer to 387 * TINY_PREEMPT_RCU has an extra callback-list tail pointer to
386 * update, so this is invoked from __rcu_process_callbacks() to 388 * update, so this is invoked from rcu_process_callbacks() to
387 * handle that case. Of course, it is invoked for all flavors of 389 * handle that case. Of course, it is invoked for all flavors of
388 * RCU, but RCU callbacks can appear only on one of the lists, and 390 * RCU, but RCU callbacks can appear only on one of the lists, and
389 * neither ->nexttail nor ->donetail can possibly be NULL, so there 391 * neither ->nexttail nor ->donetail can possibly be NULL, so there
@@ -400,7 +402,7 @@ static void rcu_preempt_remove_callbacks(struct rcu_ctrlblk *rcp)
400 */ 402 */
401static void rcu_preempt_process_callbacks(void) 403static void rcu_preempt_process_callbacks(void)
402{ 404{
403 __rcu_process_callbacks(&rcu_preempt_ctrlblk.rcb); 405 rcu_process_callbacks(&rcu_preempt_ctrlblk.rcb);
404} 406}
405 407
406/* 408/*
@@ -599,14 +601,13 @@ static void rcu_preempt_process_callbacks(void)
599#endif /* #else #ifdef CONFIG_TINY_PREEMPT_RCU */ 601#endif /* #else #ifdef CONFIG_TINY_PREEMPT_RCU */
600 602
601#ifdef CONFIG_DEBUG_LOCK_ALLOC 603#ifdef CONFIG_DEBUG_LOCK_ALLOC
602
603#include <linux/kernel_stat.h> 604#include <linux/kernel_stat.h>
604 605
605/* 606/*
606 * During boot, we forgive RCU lockdep issues. After this function is 607 * During boot, we forgive RCU lockdep issues. After this function is
607 * invoked, we start taking RCU lockdep issues seriously. 608 * invoked, we start taking RCU lockdep issues seriously.
608 */ 609 */
609void rcu_scheduler_starting(void) 610void __init rcu_scheduler_starting(void)
610{ 611{
611 WARN_ON(nr_context_switches() > 0); 612 WARN_ON(nr_context_switches() > 0);
612 rcu_scheduler_active = 1; 613 rcu_scheduler_active = 1;