blob: a64eee0db39e3642c33e69c55535619e363c0b55 [file] [log] [blame]
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -07001/*
2 * Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
Paul E. McKenney87de1cf2013-12-03 10:02:52 -080015 * along with this program; if not, you can access it online at
16 * http://www.gnu.org/licenses/gpl-2.0.html.
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070017 *
18 * Copyright IBM Corporation, 2008
19 *
20 * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
21 *
22 * For detailed explanation of Read-Copy Update mechanism see -
Ingo Molnar4ce5b902009-10-26 07:55:55 +010023 * Documentation/RCU
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070024 */
Ingo Molnar4ce5b902009-10-26 07:55:55 +010025#include <linux/completion.h>
26#include <linux/interrupt.h>
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070027#include <linux/notifier.h>
Ingo Molnarf9411eb2017-02-06 09:50:49 +010028#include <linux/rcupdate_wait.h>
Ingo Molnar4ce5b902009-10-26 07:55:55 +010029#include <linux/kernel.h>
Paul Gortmaker9984de12011-05-23 14:51:41 -040030#include <linux/export.h>
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070031#include <linux/mutex.h>
Ingo Molnar4ce5b902009-10-26 07:55:55 +010032#include <linux/sched.h>
33#include <linux/types.h>
34#include <linux/init.h>
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070035#include <linux/time.h>
Ingo Molnar4ce5b902009-10-26 07:55:55 +010036#include <linux/cpu.h>
Linus Torvalds268bb0c2011-05-20 12:50:29 -070037#include <linux/prefetch.h>
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070038
Paul E. McKenney29c00b42011-06-17 15:53:19 -070039#include "rcu.h"
40
Paul E. McKenney6d481522017-05-17 10:54:29 -070041/* Global control variables for rcupdate callback mechanism. */
42struct rcu_ctrlblk {
43 struct rcu_head *rcucblist; /* List of pending callbacks (CBs). */
44 struct rcu_head **donetail; /* ->next pointer of last "done" CB. */
45 struct rcu_head **curtail; /* ->next pointer of last CB. */
46};
47
48/* Definition for rcupdate control block. */
49static struct rcu_ctrlblk rcu_sched_ctrlblk = {
50 .donetail = &rcu_sched_ctrlblk.rcucblist,
51 .curtail = &rcu_sched_ctrlblk.rcucblist,
52};
53
54static struct rcu_ctrlblk rcu_bh_ctrlblk = {
55 .donetail = &rcu_bh_ctrlblk.rcucblist,
56 .curtail = &rcu_bh_ctrlblk.rcucblist,
57};
Paul E. McKenneya57eb942010-06-29 16:49:16 -070058
Ingo Molnarf9411eb2017-02-06 09:50:49 +010059void rcu_barrier_bh(void)
60{
61 wait_rcu_gp(call_rcu_bh);
62}
63EXPORT_SYMBOL(rcu_barrier_bh);
64
65void rcu_barrier_sched(void)
66{
67 wait_rcu_gp(call_rcu_sched);
68}
69EXPORT_SYMBOL(rcu_barrier_sched);
70
Paul E. McKenney9b2e4f12011-09-30 12:10:22 -070071/*
Eric Dumazetb554d7d2011-04-28 07:23:45 +020072 * Helper function for rcu_sched_qs() and rcu_bh_qs().
73 * Also irqs are disabled to avoid confusion due to interrupt handlers
Ingo Molnar4ce5b902009-10-26 07:55:55 +010074 * invoking call_rcu().
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070075 */
76static int rcu_qsctr_help(struct rcu_ctrlblk *rcp)
77{
Alexander Gordeev27153ac2015-02-11 15:42:37 +010078 if (rcp->donetail != rcp->curtail) {
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070079 rcp->donetail = rcp->curtail;
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070080 return 1;
81 }
Ingo Molnar4ce5b902009-10-26 07:55:55 +010082
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070083 return 0;
84}
85
86/*
87 * Record an rcu quiescent state. And an rcu_bh quiescent state while we
88 * are at it, given that any rcu quiescent state is also an rcu_bh
89 * quiescent state. Use "+" instead of "||" to defeat short circuiting.
90 */
Paul E. McKenney284a8c92014-08-14 16:38:46 -070091void rcu_sched_qs(void)
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -070092{
Eric Dumazetb554d7d2011-04-28 07:23:45 +020093 unsigned long flags;
94
95 local_irq_save(flags);
Paul E. McKenney99652b52010-03-30 15:50:01 -070096 if (rcu_qsctr_help(&rcu_sched_ctrlblk) +
97 rcu_qsctr_help(&rcu_bh_ctrlblk))
Paul E. McKenney9dc5ad32013-03-27 10:11:15 -070098 raise_softirq(RCU_SOFTIRQ);
Eric Dumazetb554d7d2011-04-28 07:23:45 +020099 local_irq_restore(flags);
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700100}
101
102/*
103 * Record an rcu_bh quiescent state.
104 */
Paul E. McKenney284a8c92014-08-14 16:38:46 -0700105void rcu_bh_qs(void)
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700106{
Eric Dumazetb554d7d2011-04-28 07:23:45 +0200107 unsigned long flags;
108
109 local_irq_save(flags);
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700110 if (rcu_qsctr_help(&rcu_bh_ctrlblk))
Paul E. McKenney9dc5ad32013-03-27 10:11:15 -0700111 raise_softirq(RCU_SOFTIRQ);
Eric Dumazetb554d7d2011-04-28 07:23:45 +0200112 local_irq_restore(flags);
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700113}
114
115/*
116 * Check to see if the scheduling-clock interrupt came from an extended
Paul E. McKenney9b2e4f12011-09-30 12:10:22 -0700117 * quiescent state, and, if so, tell RCU about it. This function must
118 * be called from hardirq context. It is normally called from the
119 * scheduling-clock interrupt.
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700120 */
Paul E. McKenneyc3377c2d2014-10-21 07:53:02 -0700121void rcu_check_callbacks(int user)
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700122{
Alexander Gordeevca9558a2014-10-31 14:55:05 +0000123 if (user)
Paul E. McKenney284a8c92014-08-14 16:38:46 -0700124 rcu_sched_qs();
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700125 else if (!in_softirq())
Paul E. McKenney284a8c92014-08-14 16:38:46 -0700126 rcu_bh_qs();
Paul E. McKenney8315f422014-06-27 13:42:20 -0700127 if (user)
128 rcu_note_voluntary_context_switch(current);
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700129}
130
131/*
Paul E. McKenneyb2c07102010-09-09 13:40:39 -0700132 * Invoke the RCU callbacks on the specified rcu_ctrlkblk structure
133 * whose grace period has elapsed.
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700134 */
Paul E. McKenney965a0022011-06-18 09:55:39 -0700135static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700136{
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700137 struct rcu_head *next, *list;
Ingo Molnar4ce5b902009-10-26 07:55:55 +0100138 unsigned long flags;
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700139
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700140 /* Move the ready-to-invoke callbacks to a local list. */
141 local_irq_save(flags);
Paul E. McKenney6e91f8c2015-05-11 11:13:05 -0700142 if (rcp->donetail == &rcp->rcucblist) {
143 /* No callbacks ready, so just leave. */
144 local_irq_restore(flags);
145 return;
146 }
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700147 list = rcp->rcucblist;
148 rcp->rcucblist = *rcp->donetail;
149 *rcp->donetail = NULL;
150 if (rcp->curtail == rcp->donetail)
151 rcp->curtail = &rcp->rcucblist;
152 rcp->donetail = &rcp->rcucblist;
153 local_irq_restore(flags);
154
155 /* Invoke the callbacks on the local list. */
156 while (list) {
157 next = list->next;
158 prefetch(next);
Mathieu Desnoyers551d55a2010-04-17 08:48:42 -0400159 debug_rcu_head_unqueue(list);
Paul E. McKenneyb2c07102010-09-09 13:40:39 -0700160 local_bh_disable();
Paul E. McKenney6d481522017-05-17 10:54:29 -0700161 __rcu_reclaim("", list);
Paul E. McKenneyb2c07102010-09-09 13:40:39 -0700162 local_bh_enable();
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700163 list = next;
164 }
165}
166
Emese Revfy0766f782016-06-20 20:42:34 +0200167static __latent_entropy void rcu_process_callbacks(struct softirq_action *unused)
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700168{
Paul E. McKenney965a0022011-06-18 09:55:39 -0700169 __rcu_process_callbacks(&rcu_sched_ctrlblk);
170 __rcu_process_callbacks(&rcu_bh_ctrlblk);
Paul E. McKenneyb2c07102010-09-09 13:40:39 -0700171}
172
173/*
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700174 * Wait for a grace period to elapse. But it is illegal to invoke
175 * synchronize_sched() from within an RCU read-side critical section.
176 * Therefore, any legal call to synchronize_sched() is a quiescent
177 * state, and so on a UP system, synchronize_sched() need do nothing.
178 * Ditto for synchronize_rcu_bh(). (But Lai Jiangshan points out the
179 * benefits of doing might_sleep() to reduce latency.)
180 *
181 * Cool, huh? (Due to Josh Triplett.)
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700182 */
183void synchronize_sched(void)
184{
Paul E. McKenneyf78f5b92015-06-18 15:50:02 -0700185 RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) ||
186 lock_is_held(&rcu_lock_map) ||
187 lock_is_held(&rcu_sched_lock_map),
188 "Illegal synchronize_sched() in RCU read-side critical section");
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700189}
190EXPORT_SYMBOL_GPL(synchronize_sched);
191
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700192/*
193 * Helper function for call_rcu() and call_rcu_bh().
194 */
195static void __call_rcu(struct rcu_head *head,
Boqun Fengb6a4ae72015-07-29 13:29:38 +0800196 rcu_callback_t func,
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700197 struct rcu_ctrlblk *rcp)
198{
199 unsigned long flags;
200
Mathieu Desnoyers551d55a2010-04-17 08:48:42 -0400201 debug_rcu_head_queue(head);
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700202 head->func = func;
203 head->next = NULL;
Ingo Molnar4ce5b902009-10-26 07:55:55 +0100204
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700205 local_irq_save(flags);
206 *rcp->curtail = head;
207 rcp->curtail = &head->next;
208 local_irq_restore(flags);
Lai Jiangshan5f6130f2014-12-09 17:53:34 +0800209
210 if (unlikely(is_idle_task(current))) {
211 /* force scheduling for rcu_sched_qs() */
212 resched_cpu(0);
213 }
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700214}
215
216/*
Paul E. McKenneya57eb942010-06-29 16:49:16 -0700217 * Post an RCU callback to be invoked after the end of an RCU-sched grace
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700218 * period. But since we have but one CPU, that would be after any
219 * quiescent state.
220 */
Boqun Fengb6a4ae72015-07-29 13:29:38 +0800221void call_rcu_sched(struct rcu_head *head, rcu_callback_t func)
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700222{
Paul E. McKenney99652b52010-03-30 15:50:01 -0700223 __call_rcu(head, func, &rcu_sched_ctrlblk);
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700224}
Paul E. McKenneya57eb942010-06-29 16:49:16 -0700225EXPORT_SYMBOL_GPL(call_rcu_sched);
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700226
227/*
228 * Post an RCU bottom-half callback to be invoked after any subsequent
229 * quiescent state.
230 */
Boqun Fengb6a4ae72015-07-29 13:29:38 +0800231void call_rcu_bh(struct rcu_head *head, rcu_callback_t func)
Paul E. McKenney9b1d82f2009-10-25 19:03:50 -0700232{
233 __call_rcu(head, func, &rcu_bh_ctrlblk);
234}
235EXPORT_SYMBOL_GPL(call_rcu_bh);
Paul E. McKenney9dc5ad32013-03-27 10:11:15 -0700236
Pranith Kumaraa23c6fbc2014-09-19 11:32:29 -0400237void __init rcu_init(void)
Paul E. McKenney9dc5ad32013-03-27 10:11:15 -0700238{
239 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
Pranith Kumaraa23c6fbc2014-09-19 11:32:29 -0400240 rcu_early_boot_tests();
Paul E. McKenney9dc5ad32013-03-27 10:11:15 -0700241}