aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutiny_plugin.h
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2011-06-18 12:55:39 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2011-09-29 00:38:20 -0400
commit965a002b4f1a458c5dcb334ec29f48a0046faa25 (patch)
tree9aa3847fd44b322a73631758e7337632e5e3a32d /kernel/rcutiny_plugin.h
parent385680a9487d2f85382ad6d74e2a15837e47bfd9 (diff)
rcu: Make TINY_RCU also use softirq for RCU_BOOST=n
This patch #ifdefs TINY_RCU kthreads out of the kernel unless RCU_BOOST=y, thus eliminating context-switch overhead if RCU priority boosting has not been configured. 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.h110
1 files changed, 83 insertions, 27 deletions
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
index 791ddf7c99ab..02aa7139861c 100644
--- a/kernel/rcutiny_plugin.h
+++ b/kernel/rcutiny_plugin.h
@@ -245,6 +245,13 @@ static void show_tiny_preempt_stats(struct seq_file *m)
245 245
246#include "rtmutex_common.h" 246#include "rtmutex_common.h"
247 247
248#define RCU_BOOST_PRIO CONFIG_RCU_BOOST_PRIO
249
250/* Controls for rcu_kthread() kthread. */
251static struct task_struct *rcu_kthread_task;
252static DECLARE_WAIT_QUEUE_HEAD(rcu_kthread_wq);
253static unsigned long have_rcu_kthread_work;
254
248/* 255/*
249 * Carry out RCU priority boosting on the task indicated by ->boost_tasks, 256 * Carry out RCU priority boosting on the task indicated by ->boost_tasks,
250 * and advance ->boost_tasks to the next task in the ->blkd_tasks list. 257 * and advance ->boost_tasks to the next task in the ->blkd_tasks list.
@@ -332,7 +339,7 @@ static int rcu_initiate_boost(void)
332 if (rcu_preempt_ctrlblk.exp_tasks == NULL) 339 if (rcu_preempt_ctrlblk.exp_tasks == NULL)
333 rcu_preempt_ctrlblk.boost_tasks = 340 rcu_preempt_ctrlblk.boost_tasks =
334 rcu_preempt_ctrlblk.gp_tasks; 341 rcu_preempt_ctrlblk.gp_tasks;
335 invoke_rcu_kthread(); 342 invoke_rcu_callbacks();
336 } else 343 } else
337 RCU_TRACE(rcu_initiate_boost_trace()); 344 RCU_TRACE(rcu_initiate_boost_trace());
338 return 1; 345 return 1;
@@ -351,14 +358,6 @@ static void rcu_preempt_boost_start_gp(void)
351#else /* #ifdef CONFIG_RCU_BOOST */ 358#else /* #ifdef CONFIG_RCU_BOOST */
352 359
353/* 360/*
354 * If there is no RCU priority boosting, we don't boost.
355 */
356static int rcu_boost(void)
357{
358 return 0;
359}
360
361/*
362 * If there is no RCU priority boosting, we don't initiate boosting, 361 * If there is no RCU priority boosting, we don't initiate boosting,
363 * but we do indicate whether there are blocked readers blocking the 362 * but we do indicate whether there are blocked readers blocking the
364 * current grace period. 363 * current grace period.
@@ -425,7 +424,7 @@ static void rcu_preempt_cpu_qs(void)
425 424
426 /* If there are done callbacks, cause them to be invoked. */ 425 /* If there are done callbacks, cause them to be invoked. */
427 if (*rcu_preempt_ctrlblk.rcb.donetail != NULL) 426 if (*rcu_preempt_ctrlblk.rcb.donetail != NULL)
428 invoke_rcu_kthread(); 427 invoke_rcu_callbacks();
429} 428}
430 429
431/* 430/*
@@ -646,7 +645,7 @@ static void rcu_preempt_check_callbacks(void)
646 rcu_preempt_cpu_qs(); 645 rcu_preempt_cpu_qs();
647 if (&rcu_preempt_ctrlblk.rcb.rcucblist != 646 if (&rcu_preempt_ctrlblk.rcb.rcucblist !=
648 rcu_preempt_ctrlblk.rcb.donetail) 647 rcu_preempt_ctrlblk.rcb.donetail)
649 invoke_rcu_kthread(); 648 invoke_rcu_callbacks();
650 if (rcu_preempt_gp_in_progress() && 649 if (rcu_preempt_gp_in_progress() &&
651 rcu_cpu_blocking_cur_gp() && 650 rcu_cpu_blocking_cur_gp() &&
652 rcu_preempt_running_reader()) 651 rcu_preempt_running_reader())
@@ -672,7 +671,7 @@ static void rcu_preempt_remove_callbacks(struct rcu_ctrlblk *rcp)
672 */ 671 */
673static void rcu_preempt_process_callbacks(void) 672static void rcu_preempt_process_callbacks(void)
674{ 673{
675 rcu_process_callbacks(&rcu_preempt_ctrlblk.rcb); 674 __rcu_process_callbacks(&rcu_preempt_ctrlblk.rcb);
676} 675}
677 676
678/* 677/*
@@ -848,15 +847,6 @@ static void show_tiny_preempt_stats(struct seq_file *m)
848#endif /* #ifdef CONFIG_RCU_TRACE */ 847#endif /* #ifdef CONFIG_RCU_TRACE */
849 848
850/* 849/*
851 * Because preemptible RCU does not exist, it is never necessary to
852 * boost preempted RCU readers.
853 */
854static int rcu_boost(void)
855{
856 return 0;
857}
858
859/*
860 * Because preemptible RCU does not exist, it never has any callbacks 850 * Because preemptible RCU does not exist, it never has any callbacks
861 * to check. 851 * to check.
862 */ 852 */
@@ -882,6 +872,78 @@ static void rcu_preempt_process_callbacks(void)
882 872
883#endif /* #else #ifdef CONFIG_TINY_PREEMPT_RCU */ 873#endif /* #else #ifdef CONFIG_TINY_PREEMPT_RCU */
884 874
875#ifdef CONFIG_RCU_BOOST
876
877/*
878 * Wake up rcu_kthread() to process callbacks now eligible for invocation
879 * or to boost readers.
880 */
881static void invoke_rcu_callbacks(void)
882{
883 have_rcu_kthread_work = 1;
884 wake_up(&rcu_kthread_wq);
885}
886
887/*
888 * This kthread invokes RCU callbacks whose grace periods have
889 * elapsed. It is awakened as needed, and takes the place of the
890 * RCU_SOFTIRQ that is used for this purpose when boosting is disabled.
891 * This is a kthread, but it is never stopped, at least not until
892 * the system goes down.
893 */
894static int rcu_kthread(void *arg)
895{
896 unsigned long work;
897 unsigned long morework;
898 unsigned long flags;
899
900 for (;;) {
901 wait_event_interruptible(rcu_kthread_wq,
902 have_rcu_kthread_work != 0);
903 morework = rcu_boost();
904 local_irq_save(flags);
905 work = have_rcu_kthread_work;
906 have_rcu_kthread_work = morework;
907 local_irq_restore(flags);
908 if (work)
909 rcu_process_callbacks(NULL);
910 schedule_timeout_interruptible(1); /* Leave CPU for others. */
911 }
912
913 return 0; /* Not reached, but needed to shut gcc up. */
914}
915
916/*
917 * Spawn the kthread that invokes RCU callbacks.
918 */
919static int __init rcu_spawn_kthreads(void)
920{
921 struct sched_param sp;
922
923 rcu_kthread_task = kthread_run(rcu_kthread, NULL, "rcu_kthread");
924 sp.sched_priority = RCU_BOOST_PRIO;
925 sched_setscheduler_nocheck(rcu_kthread_task, SCHED_FIFO, &sp);
926 return 0;
927}
928early_initcall(rcu_spawn_kthreads);
929
930#else /* #ifdef CONFIG_RCU_BOOST */
931
932/*
933 * Start up softirq processing of callbacks.
934 */
935void invoke_rcu_callbacks(void)
936{
937 raise_softirq(RCU_SOFTIRQ);
938}
939
940void rcu_init(void)
941{
942 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
943}
944
945#endif /* #else #ifdef CONFIG_RCU_BOOST */
946
885#ifdef CONFIG_DEBUG_LOCK_ALLOC 947#ifdef CONFIG_DEBUG_LOCK_ALLOC
886#include <linux/kernel_stat.h> 948#include <linux/kernel_stat.h>
887 949
@@ -897,12 +959,6 @@ void __init rcu_scheduler_starting(void)
897 959
898#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ 960#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
899 961
900#ifdef CONFIG_RCU_BOOST
901#define RCU_BOOST_PRIO CONFIG_RCU_BOOST_PRIO
902#else /* #ifdef CONFIG_RCU_BOOST */
903#define RCU_BOOST_PRIO 1
904#endif /* #else #ifdef CONFIG_RCU_BOOST */
905
906#ifdef CONFIG_RCU_TRACE 962#ifdef CONFIG_RCU_TRACE
907 963
908#ifdef CONFIG_RCU_BOOST 964#ifdef CONFIG_RCU_BOOST