aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutiny_plugin.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/rcutiny_plugin.h')
-rw-r--r--kernel/rcutiny_plugin.h135
1 files changed, 88 insertions, 47 deletions
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
index f259c676195f..2b0484a5dc28 100644
--- a/kernel/rcutiny_plugin.h
+++ b/kernel/rcutiny_plugin.h
@@ -23,32 +23,30 @@
23 */ 23 */
24 24
25#include <linux/kthread.h> 25#include <linux/kthread.h>
26#include <linux/module.h>
26#include <linux/debugfs.h> 27#include <linux/debugfs.h>
27#include <linux/seq_file.h> 28#include <linux/seq_file.h>
28 29
29#ifdef CONFIG_RCU_TRACE
30#define RCU_TRACE(stmt) stmt
31#else /* #ifdef CONFIG_RCU_TRACE */
32#define RCU_TRACE(stmt)
33#endif /* #else #ifdef CONFIG_RCU_TRACE */
34
35/* Global control variables for rcupdate callback mechanism. */ 30/* Global control variables for rcupdate callback mechanism. */
36struct rcu_ctrlblk { 31struct rcu_ctrlblk {
37 struct rcu_head *rcucblist; /* List of pending callbacks (CBs). */ 32 struct rcu_head *rcucblist; /* List of pending callbacks (CBs). */
38 struct rcu_head **donetail; /* ->next pointer of last "done" CB. */ 33 struct rcu_head **donetail; /* ->next pointer of last "done" CB. */
39 struct rcu_head **curtail; /* ->next pointer of last CB. */ 34 struct rcu_head **curtail; /* ->next pointer of last CB. */
40 RCU_TRACE(long qlen); /* Number of pending CBs. */ 35 RCU_TRACE(long qlen); /* Number of pending CBs. */
36 RCU_TRACE(char *name); /* Name of RCU type. */
41}; 37};
42 38
43/* Definition for rcupdate control block. */ 39/* Definition for rcupdate control block. */
44static struct rcu_ctrlblk rcu_sched_ctrlblk = { 40static struct rcu_ctrlblk rcu_sched_ctrlblk = {
45 .donetail = &rcu_sched_ctrlblk.rcucblist, 41 .donetail = &rcu_sched_ctrlblk.rcucblist,
46 .curtail = &rcu_sched_ctrlblk.rcucblist, 42 .curtail = &rcu_sched_ctrlblk.rcucblist,
43 RCU_TRACE(.name = "rcu_sched")
47}; 44};
48 45
49static struct rcu_ctrlblk rcu_bh_ctrlblk = { 46static struct rcu_ctrlblk rcu_bh_ctrlblk = {
50 .donetail = &rcu_bh_ctrlblk.rcucblist, 47 .donetail = &rcu_bh_ctrlblk.rcucblist,
51 .curtail = &rcu_bh_ctrlblk.rcucblist, 48 .curtail = &rcu_bh_ctrlblk.rcucblist,
49 RCU_TRACE(.name = "rcu_bh")
52}; 50};
53 51
54#ifdef CONFIG_DEBUG_LOCK_ALLOC 52#ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -131,6 +129,7 @@ static struct rcu_preempt_ctrlblk rcu_preempt_ctrlblk = {
131 .rcb.curtail = &rcu_preempt_ctrlblk.rcb.rcucblist, 129 .rcb.curtail = &rcu_preempt_ctrlblk.rcb.rcucblist,
132 .nexttail = &rcu_preempt_ctrlblk.rcb.rcucblist, 130 .nexttail = &rcu_preempt_ctrlblk.rcb.rcucblist,
133 .blkd_tasks = LIST_HEAD_INIT(rcu_preempt_ctrlblk.blkd_tasks), 131 .blkd_tasks = LIST_HEAD_INIT(rcu_preempt_ctrlblk.blkd_tasks),
132 RCU_TRACE(.rcb.name = "rcu_preempt")
134}; 133};
135 134
136static int rcu_preempted_readers_exp(void); 135static int rcu_preempted_readers_exp(void);
@@ -247,6 +246,13 @@ static void show_tiny_preempt_stats(struct seq_file *m)
247 246
248#include "rtmutex_common.h" 247#include "rtmutex_common.h"
249 248
249#define RCU_BOOST_PRIO CONFIG_RCU_BOOST_PRIO
250
251/* Controls for rcu_kthread() kthread. */
252static struct task_struct *rcu_kthread_task;
253static DECLARE_WAIT_QUEUE_HEAD(rcu_kthread_wq);
254static unsigned long have_rcu_kthread_work;
255
250/* 256/*
251 * Carry out RCU priority boosting on the task indicated by ->boost_tasks, 257 * Carry out RCU priority boosting on the task indicated by ->boost_tasks,
252 * and advance ->boost_tasks to the next task in the ->blkd_tasks list. 258 * and advance ->boost_tasks to the next task in the ->blkd_tasks list.
@@ -334,7 +340,7 @@ static int rcu_initiate_boost(void)
334 if (rcu_preempt_ctrlblk.exp_tasks == NULL) 340 if (rcu_preempt_ctrlblk.exp_tasks == NULL)
335 rcu_preempt_ctrlblk.boost_tasks = 341 rcu_preempt_ctrlblk.boost_tasks =
336 rcu_preempt_ctrlblk.gp_tasks; 342 rcu_preempt_ctrlblk.gp_tasks;
337 invoke_rcu_kthread(); 343 invoke_rcu_callbacks();
338 } else 344 } else
339 RCU_TRACE(rcu_initiate_boost_trace()); 345 RCU_TRACE(rcu_initiate_boost_trace());
340 return 1; 346 return 1;
@@ -353,14 +359,6 @@ static void rcu_preempt_boost_start_gp(void)
353#else /* #ifdef CONFIG_RCU_BOOST */ 359#else /* #ifdef CONFIG_RCU_BOOST */
354 360
355/* 361/*
356 * If there is no RCU priority boosting, we don't boost.
357 */
358static int rcu_boost(void)
359{
360 return 0;
361}
362
363/*
364 * If there is no RCU priority boosting, we don't initiate boosting, 362 * If there is no RCU priority boosting, we don't initiate boosting,
365 * but we do indicate whether there are blocked readers blocking the 363 * but we do indicate whether there are blocked readers blocking the
366 * current grace period. 364 * current grace period.
@@ -427,7 +425,7 @@ static void rcu_preempt_cpu_qs(void)
427 425
428 /* If there are done callbacks, cause them to be invoked. */ 426 /* If there are done callbacks, cause them to be invoked. */
429 if (*rcu_preempt_ctrlblk.rcb.donetail != NULL) 427 if (*rcu_preempt_ctrlblk.rcb.donetail != NULL)
430 invoke_rcu_kthread(); 428 invoke_rcu_callbacks();
431} 429}
432 430
433/* 431/*
@@ -648,7 +646,7 @@ static void rcu_preempt_check_callbacks(void)
648 rcu_preempt_cpu_qs(); 646 rcu_preempt_cpu_qs();
649 if (&rcu_preempt_ctrlblk.rcb.rcucblist != 647 if (&rcu_preempt_ctrlblk.rcb.rcucblist !=
650 rcu_preempt_ctrlblk.rcb.donetail) 648 rcu_preempt_ctrlblk.rcb.donetail)
651 invoke_rcu_kthread(); 649 invoke_rcu_callbacks();
652 if (rcu_preempt_gp_in_progress() && 650 if (rcu_preempt_gp_in_progress() &&
653 rcu_cpu_blocking_cur_gp() && 651 rcu_cpu_blocking_cur_gp() &&
654 rcu_preempt_running_reader()) 652 rcu_preempt_running_reader())
@@ -674,7 +672,7 @@ static void rcu_preempt_remove_callbacks(struct rcu_ctrlblk *rcp)
674 */ 672 */
675static void rcu_preempt_process_callbacks(void) 673static void rcu_preempt_process_callbacks(void)
676{ 674{
677 rcu_process_callbacks(&rcu_preempt_ctrlblk.rcb); 675 __rcu_process_callbacks(&rcu_preempt_ctrlblk.rcb);
678} 676}
679 677
680/* 678/*
@@ -697,20 +695,6 @@ void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
697} 695}
698EXPORT_SYMBOL_GPL(call_rcu); 696EXPORT_SYMBOL_GPL(call_rcu);
699 697
700void rcu_barrier(void)
701{
702 struct rcu_synchronize rcu;
703
704 init_rcu_head_on_stack(&rcu.head);
705 init_completion(&rcu.completion);
706 /* Will wake me after RCU finished. */
707 call_rcu(&rcu.head, wakeme_after_rcu);
708 /* Wait for it. */
709 wait_for_completion(&rcu.completion);
710 destroy_rcu_head_on_stack(&rcu.head);
711}
712EXPORT_SYMBOL_GPL(rcu_barrier);
713
714/* 698/*
715 * synchronize_rcu - wait until a grace period has elapsed. 699 * synchronize_rcu - wait until a grace period has elapsed.
716 * 700 *
@@ -864,15 +848,6 @@ static void show_tiny_preempt_stats(struct seq_file *m)
864#endif /* #ifdef CONFIG_RCU_TRACE */ 848#endif /* #ifdef CONFIG_RCU_TRACE */
865 849
866/* 850/*
867 * Because preemptible RCU does not exist, it is never necessary to
868 * boost preempted RCU readers.
869 */
870static int rcu_boost(void)
871{
872 return 0;
873}
874
875/*
876 * Because preemptible RCU does not exist, it never has any callbacks 851 * Because preemptible RCU does not exist, it never has any callbacks
877 * to check. 852 * to check.
878 */ 853 */
@@ -898,6 +873,78 @@ static void rcu_preempt_process_callbacks(void)
898 873
899#endif /* #else #ifdef CONFIG_TINY_PREEMPT_RCU */ 874#endif /* #else #ifdef CONFIG_TINY_PREEMPT_RCU */
900 875
876#ifdef CONFIG_RCU_BOOST
877
878/*
879 * Wake up rcu_kthread() to process callbacks now eligible for invocation
880 * or to boost readers.
881 */
882static void invoke_rcu_callbacks(void)
883{
884 have_rcu_kthread_work = 1;
885 wake_up(&rcu_kthread_wq);
886}
887
888/*
889 * This kthread invokes RCU callbacks whose grace periods have
890 * elapsed. It is awakened as needed, and takes the place of the
891 * RCU_SOFTIRQ that is used for this purpose when boosting is disabled.
892 * This is a kthread, but it is never stopped, at least not until
893 * the system goes down.
894 */
895static int rcu_kthread(void *arg)
896{
897 unsigned long work;
898 unsigned long morework;
899 unsigned long flags;
900
901 for (;;) {
902 wait_event_interruptible(rcu_kthread_wq,
903 have_rcu_kthread_work != 0);
904 morework = rcu_boost();
905 local_irq_save(flags);
906 work = have_rcu_kthread_work;
907 have_rcu_kthread_work = morework;
908 local_irq_restore(flags);
909 if (work)
910 rcu_process_callbacks(NULL);
911 schedule_timeout_interruptible(1); /* Leave CPU for others. */
912 }
913
914 return 0; /* Not reached, but needed to shut gcc up. */
915}
916
917/*
918 * Spawn the kthread that invokes RCU callbacks.
919 */
920static int __init rcu_spawn_kthreads(void)
921{
922 struct sched_param sp;
923
924 rcu_kthread_task = kthread_run(rcu_kthread, NULL, "rcu_kthread");
925 sp.sched_priority = RCU_BOOST_PRIO;
926 sched_setscheduler_nocheck(rcu_kthread_task, SCHED_FIFO, &sp);
927 return 0;
928}
929early_initcall(rcu_spawn_kthreads);
930
931#else /* #ifdef CONFIG_RCU_BOOST */
932
933/*
934 * Start up softirq processing of callbacks.
935 */
936void invoke_rcu_callbacks(void)
937{
938 raise_softirq(RCU_SOFTIRQ);
939}
940
941void rcu_init(void)
942{
943 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
944}
945
946#endif /* #else #ifdef CONFIG_RCU_BOOST */
947
901#ifdef CONFIG_DEBUG_LOCK_ALLOC 948#ifdef CONFIG_DEBUG_LOCK_ALLOC
902#include <linux/kernel_stat.h> 949#include <linux/kernel_stat.h>
903 950
@@ -913,12 +960,6 @@ void __init rcu_scheduler_starting(void)
913 960
914#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ 961#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
915 962
916#ifdef CONFIG_RCU_BOOST
917#define RCU_BOOST_PRIO CONFIG_RCU_BOOST_PRIO
918#else /* #ifdef CONFIG_RCU_BOOST */
919#define RCU_BOOST_PRIO 1
920#endif /* #else #ifdef CONFIG_RCU_BOOST */
921
922#ifdef CONFIG_RCU_TRACE 963#ifdef CONFIG_RCU_TRACE
923 964
924#ifdef CONFIG_RCU_BOOST 965#ifdef CONFIG_RCU_BOOST