diff options
author | Pranith Kumar <bobby.prani@gmail.com> | 2014-09-19 11:32:29 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-11-03 22:26:37 -0500 |
commit | aa23c6fbc50c4f9d8b43682f37fc4580a7851413 (patch) | |
tree | 5834d1e44228b409d03df222c5d8b92ac22d9468 | |
parent | 2f3fd499df058cb2d53170e56172ce658864050d (diff) |
rcutorture: Add early boot self tests
Add early boot self tests for RCU under CONFIG_PROVE_RCU.
Currently the only test is adding a dummy callback which increments a counter
which we then later verify after calling rcu_barrier*().
Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r-- | kernel/rcu/rcu.h | 2 | ||||
-rw-r--r-- | kernel/rcu/tiny.c | 4 | ||||
-rw-r--r-- | kernel/rcu/tree.c | 2 | ||||
-rw-r--r-- | kernel/rcu/update.c | 84 |
4 files changed, 91 insertions, 1 deletions
diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h index ff1a6de62f17..07bb02eda844 100644 --- a/kernel/rcu/rcu.h +++ b/kernel/rcu/rcu.h | |||
@@ -135,4 +135,6 @@ int rcu_jiffies_till_stall_check(void); | |||
135 | */ | 135 | */ |
136 | #define TPS(x) tracepoint_string(x) | 136 | #define TPS(x) tracepoint_string(x) |
137 | 137 | ||
138 | void rcu_early_boot_tests(void); | ||
139 | |||
138 | #endif /* __LINUX_RCU_H */ | 140 | #endif /* __LINUX_RCU_H */ |
diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c index c0623fc47125..d3d44c589122 100644 --- a/kernel/rcu/tiny.c +++ b/kernel/rcu/tiny.c | |||
@@ -380,7 +380,9 @@ void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) | |||
380 | } | 380 | } |
381 | EXPORT_SYMBOL_GPL(call_rcu_bh); | 381 | EXPORT_SYMBOL_GPL(call_rcu_bh); |
382 | 382 | ||
383 | void rcu_init(void) | 383 | void __init rcu_init(void) |
384 | { | 384 | { |
385 | open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); | 385 | open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); |
386 | |||
387 | rcu_early_boot_tests(); | ||
386 | } | 388 | } |
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 9815447d22e0..77b48f03c077 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c | |||
@@ -3766,6 +3766,8 @@ void __init rcu_init(void) | |||
3766 | pm_notifier(rcu_pm_notify, 0); | 3766 | pm_notifier(rcu_pm_notify, 0); |
3767 | for_each_online_cpu(cpu) | 3767 | for_each_online_cpu(cpu) |
3768 | rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu); | 3768 | rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu); |
3769 | |||
3770 | rcu_early_boot_tests(); | ||
3769 | } | 3771 | } |
3770 | 3772 | ||
3771 | #include "tree_plugin.h" | 3773 | #include "tree_plugin.h" |
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 3ef8ba58694e..99d47e6a280f 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c | |||
@@ -690,3 +690,87 @@ static void rcu_spawn_tasks_kthread(void) | |||
690 | } | 690 | } |
691 | 691 | ||
692 | #endif /* #ifdef CONFIG_TASKS_RCU */ | 692 | #endif /* #ifdef CONFIG_TASKS_RCU */ |
693 | |||
694 | #ifdef CONFIG_PROVE_RCU | ||
695 | |||
696 | /* | ||
697 | * Early boot self test parameters, one for each flavor | ||
698 | */ | ||
699 | static bool rcu_self_test; | ||
700 | static bool rcu_self_test_bh; | ||
701 | static bool rcu_self_test_sched; | ||
702 | |||
703 | module_param(rcu_self_test, bool, 0444); | ||
704 | module_param(rcu_self_test_bh, bool, 0444); | ||
705 | module_param(rcu_self_test_sched, bool, 0444); | ||
706 | |||
707 | static int rcu_self_test_counter; | ||
708 | |||
709 | static void test_callback(struct rcu_head *r) | ||
710 | { | ||
711 | rcu_self_test_counter++; | ||
712 | pr_info("RCU test callback executed %d\n", rcu_self_test_counter); | ||
713 | } | ||
714 | |||
715 | static void early_boot_test_call_rcu(void) | ||
716 | { | ||
717 | static struct rcu_head head; | ||
718 | |||
719 | call_rcu(&head, test_callback); | ||
720 | } | ||
721 | |||
722 | static void early_boot_test_call_rcu_bh(void) | ||
723 | { | ||
724 | static struct rcu_head head; | ||
725 | |||
726 | call_rcu_bh(&head, test_callback); | ||
727 | } | ||
728 | |||
729 | static void early_boot_test_call_rcu_sched(void) | ||
730 | { | ||
731 | static struct rcu_head head; | ||
732 | |||
733 | call_rcu_sched(&head, test_callback); | ||
734 | } | ||
735 | |||
736 | void rcu_early_boot_tests(void) | ||
737 | { | ||
738 | pr_info("Running RCU self tests\n"); | ||
739 | |||
740 | if (rcu_self_test) | ||
741 | early_boot_test_call_rcu(); | ||
742 | if (rcu_self_test_bh) | ||
743 | early_boot_test_call_rcu_bh(); | ||
744 | if (rcu_self_test_sched) | ||
745 | early_boot_test_call_rcu_sched(); | ||
746 | } | ||
747 | |||
748 | static int rcu_verify_early_boot_tests(void) | ||
749 | { | ||
750 | int ret = 0; | ||
751 | int early_boot_test_counter = 0; | ||
752 | |||
753 | if (rcu_self_test) { | ||
754 | early_boot_test_counter++; | ||
755 | rcu_barrier(); | ||
756 | } | ||
757 | if (rcu_self_test_bh) { | ||
758 | early_boot_test_counter++; | ||
759 | rcu_barrier_bh(); | ||
760 | } | ||
761 | if (rcu_self_test_sched) { | ||
762 | early_boot_test_counter++; | ||
763 | rcu_barrier_sched(); | ||
764 | } | ||
765 | |||
766 | if (rcu_self_test_counter != early_boot_test_counter) { | ||
767 | WARN_ON(1); | ||
768 | ret = -1; | ||
769 | } | ||
770 | |||
771 | return ret; | ||
772 | } | ||
773 | late_initcall(rcu_verify_early_boot_tests); | ||
774 | #else | ||
775 | void rcu_early_boot_tests(void) {} | ||
776 | #endif /* CONFIG_PROVE_RCU */ | ||