diff options
Diffstat (limited to 'kernel/rcu/update.c')
-rw-r--r-- | kernel/rcu/update.c | 89 |
1 files changed, 87 insertions, 2 deletions
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 3ef8ba58694e..e0d31a345ee6 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c | |||
@@ -306,7 +306,7 @@ struct debug_obj_descr rcuhead_debug_descr = { | |||
306 | EXPORT_SYMBOL_GPL(rcuhead_debug_descr); | 306 | EXPORT_SYMBOL_GPL(rcuhead_debug_descr); |
307 | #endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */ | 307 | #endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */ |
308 | 308 | ||
309 | #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) || defined(CONFIG_RCU_TRACE) | 309 | #if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU) || defined(CONFIG_RCU_TRACE) |
310 | void do_trace_rcu_torture_read(const char *rcutorturename, struct rcu_head *rhp, | 310 | void do_trace_rcu_torture_read(const char *rcutorturename, struct rcu_head *rhp, |
311 | unsigned long secs, | 311 | unsigned long secs, |
312 | unsigned long c_old, unsigned long c) | 312 | unsigned long c_old, unsigned long c) |
@@ -531,7 +531,8 @@ static int __noreturn rcu_tasks_kthread(void *arg) | |||
531 | struct rcu_head *next; | 531 | struct rcu_head *next; |
532 | LIST_HEAD(rcu_tasks_holdouts); | 532 | LIST_HEAD(rcu_tasks_holdouts); |
533 | 533 | ||
534 | /* FIXME: Add housekeeping affinity. */ | 534 | /* Run on housekeeping CPUs by default. Sysadm can move if desired. */ |
535 | housekeeping_affine(current); | ||
535 | 536 | ||
536 | /* | 537 | /* |
537 | * Each pass through the following loop makes one check for | 538 | * Each pass through the following loop makes one check for |
@@ -690,3 +691,87 @@ static void rcu_spawn_tasks_kthread(void) | |||
690 | } | 691 | } |
691 | 692 | ||
692 | #endif /* #ifdef CONFIG_TASKS_RCU */ | 693 | #endif /* #ifdef CONFIG_TASKS_RCU */ |
694 | |||
695 | #ifdef CONFIG_PROVE_RCU | ||
696 | |||
697 | /* | ||
698 | * Early boot self test parameters, one for each flavor | ||
699 | */ | ||
700 | static bool rcu_self_test; | ||
701 | static bool rcu_self_test_bh; | ||
702 | static bool rcu_self_test_sched; | ||
703 | |||
704 | module_param(rcu_self_test, bool, 0444); | ||
705 | module_param(rcu_self_test_bh, bool, 0444); | ||
706 | module_param(rcu_self_test_sched, bool, 0444); | ||
707 | |||
708 | static int rcu_self_test_counter; | ||
709 | |||
710 | static void test_callback(struct rcu_head *r) | ||
711 | { | ||
712 | rcu_self_test_counter++; | ||
713 | pr_info("RCU test callback executed %d\n", rcu_self_test_counter); | ||
714 | } | ||
715 | |||
716 | static void early_boot_test_call_rcu(void) | ||
717 | { | ||
718 | static struct rcu_head head; | ||
719 | |||
720 | call_rcu(&head, test_callback); | ||
721 | } | ||
722 | |||
723 | static void early_boot_test_call_rcu_bh(void) | ||
724 | { | ||
725 | static struct rcu_head head; | ||
726 | |||
727 | call_rcu_bh(&head, test_callback); | ||
728 | } | ||
729 | |||
730 | static void early_boot_test_call_rcu_sched(void) | ||
731 | { | ||
732 | static struct rcu_head head; | ||
733 | |||
734 | call_rcu_sched(&head, test_callback); | ||
735 | } | ||
736 | |||
737 | void rcu_early_boot_tests(void) | ||
738 | { | ||
739 | pr_info("Running RCU self tests\n"); | ||
740 | |||
741 | if (rcu_self_test) | ||
742 | early_boot_test_call_rcu(); | ||
743 | if (rcu_self_test_bh) | ||
744 | early_boot_test_call_rcu_bh(); | ||
745 | if (rcu_self_test_sched) | ||
746 | early_boot_test_call_rcu_sched(); | ||
747 | } | ||
748 | |||
749 | static int rcu_verify_early_boot_tests(void) | ||
750 | { | ||
751 | int ret = 0; | ||
752 | int early_boot_test_counter = 0; | ||
753 | |||
754 | if (rcu_self_test) { | ||
755 | early_boot_test_counter++; | ||
756 | rcu_barrier(); | ||
757 | } | ||
758 | if (rcu_self_test_bh) { | ||
759 | early_boot_test_counter++; | ||
760 | rcu_barrier_bh(); | ||
761 | } | ||
762 | if (rcu_self_test_sched) { | ||
763 | early_boot_test_counter++; | ||
764 | rcu_barrier_sched(); | ||
765 | } | ||
766 | |||
767 | if (rcu_self_test_counter != early_boot_test_counter) { | ||
768 | WARN_ON(1); | ||
769 | ret = -1; | ||
770 | } | ||
771 | |||
772 | return ret; | ||
773 | } | ||
774 | late_initcall(rcu_verify_early_boot_tests); | ||
775 | #else | ||
776 | void rcu_early_boot_tests(void) {} | ||
777 | #endif /* CONFIG_PROVE_RCU */ | ||