diff options
author | Paul E. McKenney <paul.mckenney@linaro.org> | 2011-06-18 12:55:39 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2011-09-29 00:38:20 -0400 |
commit | 965a002b4f1a458c5dcb334ec29f48a0046faa25 (patch) | |
tree | 9aa3847fd44b322a73631758e7337632e5e3a32d /kernel/rcutiny_plugin.h | |
parent | 385680a9487d2f85382ad6d74e2a15837e47bfd9 (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.h | 110 |
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. */ | ||
251 | static struct task_struct *rcu_kthread_task; | ||
252 | static DECLARE_WAIT_QUEUE_HEAD(rcu_kthread_wq); | ||
253 | static 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 | */ | ||
356 | static 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 | */ |
673 | static void rcu_preempt_process_callbacks(void) | 672 | static 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 | */ | ||
854 | static 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 | */ | ||
881 | static 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 | */ | ||
894 | static 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 | */ | ||
919 | static 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 | } | ||
928 | early_initcall(rcu_spawn_kthreads); | ||
929 | |||
930 | #else /* #ifdef CONFIG_RCU_BOOST */ | ||
931 | |||
932 | /* | ||
933 | * Start up softirq processing of callbacks. | ||
934 | */ | ||
935 | void invoke_rcu_callbacks(void) | ||
936 | { | ||
937 | raise_softirq(RCU_SOFTIRQ); | ||
938 | } | ||
939 | |||
940 | void 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 |