xref: /linux/kernel/rcu/tasks.h (revision 8ee18e769dd621104fecad584c84ec3c4c9ef3fa)
1eacd6f04SPaul E. McKenney /* SPDX-License-Identifier: GPL-2.0+ */
2eacd6f04SPaul E. McKenney /*
3eacd6f04SPaul E. McKenney  * Task-based RCU implementations.
4eacd6f04SPaul E. McKenney  *
5eacd6f04SPaul E. McKenney  * Copyright (C) 2020 Paul E. McKenney
6eacd6f04SPaul E. McKenney  */
7eacd6f04SPaul E. McKenney 
88fd8ca38SPaul E. McKenney #ifdef CONFIG_TASKS_RCU_GENERIC
95873b8a9SPaul E. McKenney 
105873b8a9SPaul E. McKenney ////////////////////////////////////////////////////////////////////////
115873b8a9SPaul E. McKenney //
125873b8a9SPaul E. McKenney // Generic data structures.
135873b8a9SPaul E. McKenney 
145873b8a9SPaul E. McKenney struct rcu_tasks;
155873b8a9SPaul E. McKenney typedef void (*rcu_tasks_gp_func_t)(struct rcu_tasks *rtp);
16e4fe5dd6SPaul E. McKenney typedef void (*pregp_func_t)(void);
17e4fe5dd6SPaul E. McKenney typedef void (*pertask_func_t)(struct task_struct *t, struct list_head *hop);
189796e1aeSPaul E. McKenney typedef void (*postscan_func_t)(struct list_head *hop);
19e4fe5dd6SPaul E. McKenney typedef void (*holdouts_func_t)(struct list_head *hop, bool ndrpt, bool *frptp);
20af051ca4SPaul E. McKenney typedef void (*postgp_func_t)(struct rcu_tasks *rtp);
21eacd6f04SPaul E. McKenney 
2207e10515SPaul E. McKenney /**
2385b86994SLukas Bulwahn  * struct rcu_tasks - Definition for a Tasks-RCU-like mechanism.
2407e10515SPaul E. McKenney  * @cbs_head: Head of callback list.
2507e10515SPaul E. McKenney  * @cbs_tail: Tail pointer for callback list.
26a616aec9SIngo Molnar  * @cbs_wq: Wait queue allowing new callback to get kthread's attention.
2707e10515SPaul E. McKenney  * @cbs_lock: Lock protecting callback list.
2807e10515SPaul E. McKenney  * @kthread_ptr: This flavor's grace-period/callback-invocation kthread.
295873b8a9SPaul E. McKenney  * @gp_func: This flavor's grace-period-wait function.
30af051ca4SPaul E. McKenney  * @gp_state: Grace period's most recent state transition (debugging).
314fe192dfSPaul E. McKenney  * @gp_sleep: Per-grace-period sleep to prevent CPU-bound looping.
322393a613SPaul E. McKenney  * @init_fract: Initial backoff sleep interval.
33af051ca4SPaul E. McKenney  * @gp_jiffies: Time of last @gp_state transition.
34af051ca4SPaul E. McKenney  * @gp_start: Most recent grace-period start in jiffies.
35238dbce3SPaul E. McKenney  * @n_gps: Number of grace periods completed since boot.
36238dbce3SPaul E. McKenney  * @n_ipis: Number of IPIs sent to encourage grace periods to end.
377e0669c3SPaul E. McKenney  * @n_ipis_fails: Number of IPI-send failures.
38e4fe5dd6SPaul E. McKenney  * @pregp_func: This flavor's pre-grace-period function (optional).
39e4fe5dd6SPaul E. McKenney  * @pertask_func: This flavor's per-task scan function (optional).
40e4fe5dd6SPaul E. McKenney  * @postscan_func: This flavor's post-task scan function (optional).
4185b86994SLukas Bulwahn  * @holdouts_func: This flavor's holdout-list scan function (optional).
42e4fe5dd6SPaul E. McKenney  * @postgp_func: This flavor's post-grace-period function (optional).
435873b8a9SPaul E. McKenney  * @call_func: This flavor's call_rcu()-equivalent function.
44c97d12a6SPaul E. McKenney  * @name: This flavor's textual name.
45c97d12a6SPaul E. McKenney  * @kname: This flavor's kthread name.
4607e10515SPaul E. McKenney  */
4707e10515SPaul E. McKenney struct rcu_tasks {
4807e10515SPaul E. McKenney 	struct rcu_head *cbs_head;
4907e10515SPaul E. McKenney 	struct rcu_head **cbs_tail;
5007e10515SPaul E. McKenney 	struct wait_queue_head cbs_wq;
5107e10515SPaul E. McKenney 	raw_spinlock_t cbs_lock;
52af051ca4SPaul E. McKenney 	int gp_state;
534fe192dfSPaul E. McKenney 	int gp_sleep;
542393a613SPaul E. McKenney 	int init_fract;
55af051ca4SPaul E. McKenney 	unsigned long gp_jiffies;
5688092d0cSPaul E. McKenney 	unsigned long gp_start;
57238dbce3SPaul E. McKenney 	unsigned long n_gps;
58238dbce3SPaul E. McKenney 	unsigned long n_ipis;
597e0669c3SPaul E. McKenney 	unsigned long n_ipis_fails;
6007e10515SPaul E. McKenney 	struct task_struct *kthread_ptr;
615873b8a9SPaul E. McKenney 	rcu_tasks_gp_func_t gp_func;
62e4fe5dd6SPaul E. McKenney 	pregp_func_t pregp_func;
63e4fe5dd6SPaul E. McKenney 	pertask_func_t pertask_func;
64e4fe5dd6SPaul E. McKenney 	postscan_func_t postscan_func;
65e4fe5dd6SPaul E. McKenney 	holdouts_func_t holdouts_func;
66e4fe5dd6SPaul E. McKenney 	postgp_func_t postgp_func;
675873b8a9SPaul E. McKenney 	call_rcu_func_t call_func;
68c97d12a6SPaul E. McKenney 	char *name;
69c97d12a6SPaul E. McKenney 	char *kname;
7007e10515SPaul E. McKenney };
7107e10515SPaul E. McKenney 
72c97d12a6SPaul E. McKenney #define DEFINE_RCU_TASKS(rt_name, gp, call, n)				\
73c97d12a6SPaul E. McKenney static struct rcu_tasks rt_name =					\
7407e10515SPaul E. McKenney {									\
75c97d12a6SPaul E. McKenney 	.cbs_tail = &rt_name.cbs_head,					\
76c97d12a6SPaul E. McKenney 	.cbs_wq = __WAIT_QUEUE_HEAD_INITIALIZER(rt_name.cbs_wq),	\
77c97d12a6SPaul E. McKenney 	.cbs_lock = __RAW_SPIN_LOCK_UNLOCKED(rt_name.cbs_lock),		\
785873b8a9SPaul E. McKenney 	.gp_func = gp,							\
795873b8a9SPaul E. McKenney 	.call_func = call,						\
80c97d12a6SPaul E. McKenney 	.name = n,							\
81c97d12a6SPaul E. McKenney 	.kname = #rt_name,						\
8207e10515SPaul E. McKenney }
8307e10515SPaul E. McKenney 
84eacd6f04SPaul E. McKenney /* Track exiting tasks in order to allow them to be waited for. */
85eacd6f04SPaul E. McKenney DEFINE_STATIC_SRCU(tasks_rcu_exit_srcu);
86eacd6f04SPaul E. McKenney 
87b0afa0f0SPaul E. McKenney /* Avoid IPIing CPUs early in the grace period. */
88574de876SPaul E. McKenney #define RCU_TASK_IPI_DELAY (IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB) ? HZ / 2 : 0)
89b0afa0f0SPaul E. McKenney static int rcu_task_ipi_delay __read_mostly = RCU_TASK_IPI_DELAY;
90b0afa0f0SPaul E. McKenney module_param(rcu_task_ipi_delay, int, 0644);
91b0afa0f0SPaul E. McKenney 
92eacd6f04SPaul E. McKenney /* Control stall timeouts.  Disable with <= 0, otherwise jiffies till stall. */
93eacd6f04SPaul E. McKenney #define RCU_TASK_STALL_TIMEOUT (HZ * 60 * 10)
94eacd6f04SPaul E. McKenney static int rcu_task_stall_timeout __read_mostly = RCU_TASK_STALL_TIMEOUT;
95eacd6f04SPaul E. McKenney module_param(rcu_task_stall_timeout, int, 0644);
96eacd6f04SPaul E. McKenney 
97af051ca4SPaul E. McKenney /* RCU tasks grace-period state for debugging. */
98af051ca4SPaul E. McKenney #define RTGS_INIT		 0
99af051ca4SPaul E. McKenney #define RTGS_WAIT_WAIT_CBS	 1
100af051ca4SPaul E. McKenney #define RTGS_WAIT_GP		 2
101af051ca4SPaul E. McKenney #define RTGS_PRE_WAIT_GP	 3
102af051ca4SPaul E. McKenney #define RTGS_SCAN_TASKLIST	 4
103af051ca4SPaul E. McKenney #define RTGS_POST_SCAN_TASKLIST	 5
104af051ca4SPaul E. McKenney #define RTGS_WAIT_SCAN_HOLDOUTS	 6
105af051ca4SPaul E. McKenney #define RTGS_SCAN_HOLDOUTS	 7
106af051ca4SPaul E. McKenney #define RTGS_POST_GP		 8
107af051ca4SPaul E. McKenney #define RTGS_WAIT_READERS	 9
108af051ca4SPaul E. McKenney #define RTGS_INVOKE_CBS		10
109af051ca4SPaul E. McKenney #define RTGS_WAIT_CBS		11
1108344496eSPaul E. McKenney #ifndef CONFIG_TINY_RCU
111af051ca4SPaul E. McKenney static const char * const rcu_tasks_gp_state_names[] = {
112af051ca4SPaul E. McKenney 	"RTGS_INIT",
113af051ca4SPaul E. McKenney 	"RTGS_WAIT_WAIT_CBS",
114af051ca4SPaul E. McKenney 	"RTGS_WAIT_GP",
115af051ca4SPaul E. McKenney 	"RTGS_PRE_WAIT_GP",
116af051ca4SPaul E. McKenney 	"RTGS_SCAN_TASKLIST",
117af051ca4SPaul E. McKenney 	"RTGS_POST_SCAN_TASKLIST",
118af051ca4SPaul E. McKenney 	"RTGS_WAIT_SCAN_HOLDOUTS",
119af051ca4SPaul E. McKenney 	"RTGS_SCAN_HOLDOUTS",
120af051ca4SPaul E. McKenney 	"RTGS_POST_GP",
121af051ca4SPaul E. McKenney 	"RTGS_WAIT_READERS",
122af051ca4SPaul E. McKenney 	"RTGS_INVOKE_CBS",
123af051ca4SPaul E. McKenney 	"RTGS_WAIT_CBS",
124af051ca4SPaul E. McKenney };
1258344496eSPaul E. McKenney #endif /* #ifndef CONFIG_TINY_RCU */
126af051ca4SPaul E. McKenney 
1275873b8a9SPaul E. McKenney ////////////////////////////////////////////////////////////////////////
1285873b8a9SPaul E. McKenney //
1295873b8a9SPaul E. McKenney // Generic code.
1305873b8a9SPaul E. McKenney 
131af051ca4SPaul E. McKenney /* Record grace-period phase and time. */
132af051ca4SPaul E. McKenney static void set_tasks_gp_state(struct rcu_tasks *rtp, int newstate)
133af051ca4SPaul E. McKenney {
134af051ca4SPaul E. McKenney 	rtp->gp_state = newstate;
135af051ca4SPaul E. McKenney 	rtp->gp_jiffies = jiffies;
136af051ca4SPaul E. McKenney }
137af051ca4SPaul E. McKenney 
1388344496eSPaul E. McKenney #ifndef CONFIG_TINY_RCU
139af051ca4SPaul E. McKenney /* Return state name. */
140af051ca4SPaul E. McKenney static const char *tasks_gp_state_getname(struct rcu_tasks *rtp)
141af051ca4SPaul E. McKenney {
142af051ca4SPaul E. McKenney 	int i = data_race(rtp->gp_state); // Let KCSAN detect update races
143af051ca4SPaul E. McKenney 	int j = READ_ONCE(i); // Prevent the compiler from reading twice
144af051ca4SPaul E. McKenney 
145af051ca4SPaul E. McKenney 	if (j >= ARRAY_SIZE(rcu_tasks_gp_state_names))
146af051ca4SPaul E. McKenney 		return "???";
147af051ca4SPaul E. McKenney 	return rcu_tasks_gp_state_names[j];
148af051ca4SPaul E. McKenney }
1498344496eSPaul E. McKenney #endif /* #ifndef CONFIG_TINY_RCU */
150af051ca4SPaul E. McKenney 
1515873b8a9SPaul E. McKenney // Enqueue a callback for the specified flavor of Tasks RCU.
1525873b8a9SPaul E. McKenney static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
1535873b8a9SPaul E. McKenney 				   struct rcu_tasks *rtp)
154eacd6f04SPaul E. McKenney {
155eacd6f04SPaul E. McKenney 	unsigned long flags;
156eacd6f04SPaul E. McKenney 	bool needwake;
157eacd6f04SPaul E. McKenney 
158eacd6f04SPaul E. McKenney 	rhp->next = NULL;
159eacd6f04SPaul E. McKenney 	rhp->func = func;
16007e10515SPaul E. McKenney 	raw_spin_lock_irqsave(&rtp->cbs_lock, flags);
16107e10515SPaul E. McKenney 	needwake = !rtp->cbs_head;
16207e10515SPaul E. McKenney 	WRITE_ONCE(*rtp->cbs_tail, rhp);
16307e10515SPaul E. McKenney 	rtp->cbs_tail = &rhp->next;
16407e10515SPaul E. McKenney 	raw_spin_unlock_irqrestore(&rtp->cbs_lock, flags);
165eacd6f04SPaul E. McKenney 	/* We can't create the thread unless interrupts are enabled. */
16607e10515SPaul E. McKenney 	if (needwake && READ_ONCE(rtp->kthread_ptr))
16707e10515SPaul E. McKenney 		wake_up(&rtp->cbs_wq);
168eacd6f04SPaul E. McKenney }
169eacd6f04SPaul E. McKenney 
1705873b8a9SPaul E. McKenney // Wait for a grace period for the specified flavor of Tasks RCU.
1715873b8a9SPaul E. McKenney static void synchronize_rcu_tasks_generic(struct rcu_tasks *rtp)
172eacd6f04SPaul E. McKenney {
173eacd6f04SPaul E. McKenney 	/* Complain if the scheduler has not started.  */
174eacd6f04SPaul E. McKenney 	RCU_LOCKDEP_WARN(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
175eacd6f04SPaul E. McKenney 			 "synchronize_rcu_tasks called too soon");
176eacd6f04SPaul E. McKenney 
177eacd6f04SPaul E. McKenney 	/* Wait for the grace period. */
1785873b8a9SPaul E. McKenney 	wait_rcu_gp(rtp->call_func);
179eacd6f04SPaul E. McKenney }
180eacd6f04SPaul E. McKenney 
1815873b8a9SPaul E. McKenney /* RCU-tasks kthread that detects grace periods and invokes callbacks. */
1825873b8a9SPaul E. McKenney static int __noreturn rcu_tasks_kthread(void *arg)
183eacd6f04SPaul E. McKenney {
1845873b8a9SPaul E. McKenney 	unsigned long flags;
1855873b8a9SPaul E. McKenney 	struct rcu_head *list;
1865873b8a9SPaul E. McKenney 	struct rcu_head *next;
1875873b8a9SPaul E. McKenney 	struct rcu_tasks *rtp = arg;
1885873b8a9SPaul E. McKenney 
1895873b8a9SPaul E. McKenney 	/* Run on housekeeping CPUs by default.  Sysadm can move if desired. */
1905873b8a9SPaul E. McKenney 	housekeeping_affine(current, HK_FLAG_RCU);
1915873b8a9SPaul E. McKenney 	WRITE_ONCE(rtp->kthread_ptr, current); // Let GPs start!
1925873b8a9SPaul E. McKenney 
1935873b8a9SPaul E. McKenney 	/*
1945873b8a9SPaul E. McKenney 	 * Each pass through the following loop makes one check for
1955873b8a9SPaul E. McKenney 	 * newly arrived callbacks, and, if there are some, waits for
1965873b8a9SPaul E. McKenney 	 * one RCU-tasks grace period and then invokes the callbacks.
1975873b8a9SPaul E. McKenney 	 * This loop is terminated by the system going down.  ;-)
1985873b8a9SPaul E. McKenney 	 */
1995873b8a9SPaul E. McKenney 	for (;;) {
2005873b8a9SPaul E. McKenney 
2015873b8a9SPaul E. McKenney 		/* Pick up any new callbacks. */
2025873b8a9SPaul E. McKenney 		raw_spin_lock_irqsave(&rtp->cbs_lock, flags);
20343766c3eSPaul E. McKenney 		smp_mb__after_spinlock(); // Order updates vs. GP.
2045873b8a9SPaul E. McKenney 		list = rtp->cbs_head;
2055873b8a9SPaul E. McKenney 		rtp->cbs_head = NULL;
2065873b8a9SPaul E. McKenney 		rtp->cbs_tail = &rtp->cbs_head;
2075873b8a9SPaul E. McKenney 		raw_spin_unlock_irqrestore(&rtp->cbs_lock, flags);
2085873b8a9SPaul E. McKenney 
2095873b8a9SPaul E. McKenney 		/* If there were none, wait a bit and start over. */
2105873b8a9SPaul E. McKenney 		if (!list) {
2115873b8a9SPaul E. McKenney 			wait_event_interruptible(rtp->cbs_wq,
2125873b8a9SPaul E. McKenney 						 READ_ONCE(rtp->cbs_head));
2135873b8a9SPaul E. McKenney 			if (!rtp->cbs_head) {
2145873b8a9SPaul E. McKenney 				WARN_ON(signal_pending(current));
215af051ca4SPaul E. McKenney 				set_tasks_gp_state(rtp, RTGS_WAIT_WAIT_CBS);
216ea6eed9fSPaul E. McKenney 				schedule_timeout_idle(HZ/10);
217eacd6f04SPaul E. McKenney 			}
2185873b8a9SPaul E. McKenney 			continue;
2195873b8a9SPaul E. McKenney 		}
2205873b8a9SPaul E. McKenney 
2215873b8a9SPaul E. McKenney 		// Wait for one grace period.
222af051ca4SPaul E. McKenney 		set_tasks_gp_state(rtp, RTGS_WAIT_GP);
22388092d0cSPaul E. McKenney 		rtp->gp_start = jiffies;
2245873b8a9SPaul E. McKenney 		rtp->gp_func(rtp);
225238dbce3SPaul E. McKenney 		rtp->n_gps++;
2265873b8a9SPaul E. McKenney 
2275873b8a9SPaul E. McKenney 		/* Invoke the callbacks. */
228af051ca4SPaul E. McKenney 		set_tasks_gp_state(rtp, RTGS_INVOKE_CBS);
2295873b8a9SPaul E. McKenney 		while (list) {
2305873b8a9SPaul E. McKenney 			next = list->next;
2315873b8a9SPaul E. McKenney 			local_bh_disable();
2325873b8a9SPaul E. McKenney 			list->func(list);
2335873b8a9SPaul E. McKenney 			local_bh_enable();
2345873b8a9SPaul E. McKenney 			list = next;
2355873b8a9SPaul E. McKenney 			cond_resched();
2365873b8a9SPaul E. McKenney 		}
2375873b8a9SPaul E. McKenney 		/* Paranoid sleep to keep this from entering a tight loop */
2384fe192dfSPaul E. McKenney 		schedule_timeout_idle(rtp->gp_sleep);
239af051ca4SPaul E. McKenney 
240af051ca4SPaul E. McKenney 		set_tasks_gp_state(rtp, RTGS_WAIT_CBS);
2415873b8a9SPaul E. McKenney 	}
2425873b8a9SPaul E. McKenney }
2435873b8a9SPaul E. McKenney 
2441b04fa99SUladzislau Rezki (Sony) /* Spawn RCU-tasks grace-period kthread. */
2455873b8a9SPaul E. McKenney static void __init rcu_spawn_tasks_kthread_generic(struct rcu_tasks *rtp)
2465873b8a9SPaul E. McKenney {
2475873b8a9SPaul E. McKenney 	struct task_struct *t;
2485873b8a9SPaul E. McKenney 
249c97d12a6SPaul E. McKenney 	t = kthread_run(rcu_tasks_kthread, rtp, "%s_kthread", rtp->kname);
250c97d12a6SPaul E. McKenney 	if (WARN_ONCE(IS_ERR(t), "%s: Could not start %s grace-period kthread, OOM is now expected behavior\n", __func__, rtp->name))
2515873b8a9SPaul E. McKenney 		return;
2525873b8a9SPaul E. McKenney 	smp_mb(); /* Ensure others see full kthread. */
2535873b8a9SPaul E. McKenney }
2545873b8a9SPaul E. McKenney 
2555873b8a9SPaul E. McKenney #ifndef CONFIG_TINY_RCU
2565873b8a9SPaul E. McKenney 
2575873b8a9SPaul E. McKenney /*
2585873b8a9SPaul E. McKenney  * Print any non-default Tasks RCU settings.
2595873b8a9SPaul E. McKenney  */
2605873b8a9SPaul E. McKenney static void __init rcu_tasks_bootup_oddness(void)
2615873b8a9SPaul E. McKenney {
262d5f177d3SPaul E. McKenney #if defined(CONFIG_TASKS_RCU) || defined(CONFIG_TASKS_TRACE_RCU)
2635873b8a9SPaul E. McKenney 	if (rcu_task_stall_timeout != RCU_TASK_STALL_TIMEOUT)
2645873b8a9SPaul E. McKenney 		pr_info("\tTasks-RCU CPU stall warnings timeout set to %d (rcu_task_stall_timeout).\n", rcu_task_stall_timeout);
265d5f177d3SPaul E. McKenney #endif /* #ifdef CONFIG_TASKS_RCU */
266d5f177d3SPaul E. McKenney #ifdef CONFIG_TASKS_RCU
267d5f177d3SPaul E. McKenney 	pr_info("\tTrampoline variant of Tasks RCU enabled.\n");
2685873b8a9SPaul E. McKenney #endif /* #ifdef CONFIG_TASKS_RCU */
269c84aad76SPaul E. McKenney #ifdef CONFIG_TASKS_RUDE_RCU
270c84aad76SPaul E. McKenney 	pr_info("\tRude variant of Tasks RCU enabled.\n");
271c84aad76SPaul E. McKenney #endif /* #ifdef CONFIG_TASKS_RUDE_RCU */
272d5f177d3SPaul E. McKenney #ifdef CONFIG_TASKS_TRACE_RCU
273d5f177d3SPaul E. McKenney 	pr_info("\tTracing variant of Tasks RCU enabled.\n");
274d5f177d3SPaul E. McKenney #endif /* #ifdef CONFIG_TASKS_TRACE_RCU */
2755873b8a9SPaul E. McKenney }
2765873b8a9SPaul E. McKenney 
2775873b8a9SPaul E. McKenney #endif /* #ifndef CONFIG_TINY_RCU */
2785873b8a9SPaul E. McKenney 
2798344496eSPaul E. McKenney #ifndef CONFIG_TINY_RCU
280e21408ceSPaul E. McKenney /* Dump out rcutorture-relevant state common to all RCU-tasks flavors. */
281e21408ceSPaul E. McKenney static void show_rcu_tasks_generic_gp_kthread(struct rcu_tasks *rtp, char *s)
282e21408ceSPaul E. McKenney {
2837e0669c3SPaul E. McKenney 	pr_info("%s: %s(%d) since %lu g:%lu i:%lu/%lu %c%c %s\n",
284e21408ceSPaul E. McKenney 		rtp->kname,
2857e0669c3SPaul E. McKenney 		tasks_gp_state_getname(rtp), data_race(rtp->gp_state),
286af051ca4SPaul E. McKenney 		jiffies - data_race(rtp->gp_jiffies),
2877e0669c3SPaul E. McKenney 		data_race(rtp->n_gps),
2887e0669c3SPaul E. McKenney 		data_race(rtp->n_ipis_fails), data_race(rtp->n_ipis),
289e21408ceSPaul E. McKenney 		".k"[!!data_race(rtp->kthread_ptr)],
290e21408ceSPaul E. McKenney 		".C"[!!data_race(rtp->cbs_head)],
291e21408ceSPaul E. McKenney 		s);
292e21408ceSPaul E. McKenney }
29327c0f144SPaul E. McKenney #endif // #ifndef CONFIG_TINY_RCU
294e21408ceSPaul E. McKenney 
29525246fc8SPaul E. McKenney static void exit_tasks_rcu_finish_trace(struct task_struct *t);
29625246fc8SPaul E. McKenney 
29725246fc8SPaul E. McKenney #if defined(CONFIG_TASKS_RCU) || defined(CONFIG_TASKS_TRACE_RCU)
2985873b8a9SPaul E. McKenney 
2995873b8a9SPaul E. McKenney ////////////////////////////////////////////////////////////////////////
3005873b8a9SPaul E. McKenney //
301d01aa263SPaul E. McKenney // Shared code between task-list-scanning variants of Tasks RCU.
302d01aa263SPaul E. McKenney 
303d01aa263SPaul E. McKenney /* Wait for one RCU-tasks grace period. */
304d01aa263SPaul E. McKenney static void rcu_tasks_wait_gp(struct rcu_tasks *rtp)
305d01aa263SPaul E. McKenney {
306d01aa263SPaul E. McKenney 	struct task_struct *g, *t;
307d01aa263SPaul E. McKenney 	unsigned long lastreport;
308d01aa263SPaul E. McKenney 	LIST_HEAD(holdouts);
309d01aa263SPaul E. McKenney 	int fract;
310d01aa263SPaul E. McKenney 
311af051ca4SPaul E. McKenney 	set_tasks_gp_state(rtp, RTGS_PRE_WAIT_GP);
312d01aa263SPaul E. McKenney 	rtp->pregp_func();
313d01aa263SPaul E. McKenney 
314d01aa263SPaul E. McKenney 	/*
315d01aa263SPaul E. McKenney 	 * There were callbacks, so we need to wait for an RCU-tasks
316d01aa263SPaul E. McKenney 	 * grace period.  Start off by scanning the task list for tasks
317d01aa263SPaul E. McKenney 	 * that are not already voluntarily blocked.  Mark these tasks
318d01aa263SPaul E. McKenney 	 * and make a list of them in holdouts.
319d01aa263SPaul E. McKenney 	 */
320af051ca4SPaul E. McKenney 	set_tasks_gp_state(rtp, RTGS_SCAN_TASKLIST);
321d01aa263SPaul E. McKenney 	rcu_read_lock();
322d01aa263SPaul E. McKenney 	for_each_process_thread(g, t)
323d01aa263SPaul E. McKenney 		rtp->pertask_func(t, &holdouts);
324d01aa263SPaul E. McKenney 	rcu_read_unlock();
325d01aa263SPaul E. McKenney 
326af051ca4SPaul E. McKenney 	set_tasks_gp_state(rtp, RTGS_POST_SCAN_TASKLIST);
3279796e1aeSPaul E. McKenney 	rtp->postscan_func(&holdouts);
328d01aa263SPaul E. McKenney 
329d01aa263SPaul E. McKenney 	/*
330d01aa263SPaul E. McKenney 	 * Each pass through the following loop scans the list of holdout
331d01aa263SPaul E. McKenney 	 * tasks, removing any that are no longer holdouts.  When the list
332d01aa263SPaul E. McKenney 	 * is empty, we are done.
333d01aa263SPaul E. McKenney 	 */
334d01aa263SPaul E. McKenney 	lastreport = jiffies;
335d01aa263SPaul E. McKenney 
3362393a613SPaul E. McKenney 	// Start off with initial wait and slowly back off to 1 HZ wait.
3372393a613SPaul E. McKenney 	fract = rtp->init_fract;
338d01aa263SPaul E. McKenney 
33977dc1741SPaul E. McKenney 	while (!list_empty(&holdouts)) {
340d01aa263SPaul E. McKenney 		bool firstreport;
341d01aa263SPaul E. McKenney 		bool needreport;
342d01aa263SPaul E. McKenney 		int rtst;
343d01aa263SPaul E. McKenney 
344d01aa263SPaul E. McKenney 		/* Slowly back off waiting for holdouts */
345af051ca4SPaul E. McKenney 		set_tasks_gp_state(rtp, RTGS_WAIT_SCAN_HOLDOUTS);
34675dc2da5SPaul E. McKenney 		schedule_timeout_idle(fract);
347d01aa263SPaul E. McKenney 
34875dc2da5SPaul E. McKenney 		if (fract < HZ)
34975dc2da5SPaul E. McKenney 			fract++;
350d01aa263SPaul E. McKenney 
351d01aa263SPaul E. McKenney 		rtst = READ_ONCE(rcu_task_stall_timeout);
352d01aa263SPaul E. McKenney 		needreport = rtst > 0 && time_after(jiffies, lastreport + rtst);
353d01aa263SPaul E. McKenney 		if (needreport)
354d01aa263SPaul E. McKenney 			lastreport = jiffies;
355d01aa263SPaul E. McKenney 		firstreport = true;
356d01aa263SPaul E. McKenney 		WARN_ON(signal_pending(current));
357af051ca4SPaul E. McKenney 		set_tasks_gp_state(rtp, RTGS_SCAN_HOLDOUTS);
358d01aa263SPaul E. McKenney 		rtp->holdouts_func(&holdouts, needreport, &firstreport);
359d01aa263SPaul E. McKenney 	}
360d01aa263SPaul E. McKenney 
361af051ca4SPaul E. McKenney 	set_tasks_gp_state(rtp, RTGS_POST_GP);
362af051ca4SPaul E. McKenney 	rtp->postgp_func(rtp);
363d01aa263SPaul E. McKenney }
364d01aa263SPaul E. McKenney 
36525246fc8SPaul E. McKenney #endif /* #if defined(CONFIG_TASKS_RCU) || defined(CONFIG_TASKS_TRACE_RCU) */
36625246fc8SPaul E. McKenney 
36725246fc8SPaul E. McKenney #ifdef CONFIG_TASKS_RCU
36825246fc8SPaul E. McKenney 
369d01aa263SPaul E. McKenney ////////////////////////////////////////////////////////////////////////
370d01aa263SPaul E. McKenney //
3715873b8a9SPaul E. McKenney // Simple variant of RCU whose quiescent states are voluntary context
3725873b8a9SPaul E. McKenney // switch, cond_resched_rcu_qs(), user-space execution, and idle.
3735873b8a9SPaul E. McKenney // As such, grace periods can take one good long time.  There are no
3745873b8a9SPaul E. McKenney // read-side primitives similar to rcu_read_lock() and rcu_read_unlock()
3755873b8a9SPaul E. McKenney // because this implementation is intended to get the system into a safe
3765873b8a9SPaul E. McKenney // state for some of the manipulations involved in tracing and the like.
3775873b8a9SPaul E. McKenney // Finally, this implementation does not support high call_rcu_tasks()
3785873b8a9SPaul E. McKenney // rates from multiple CPUs.  If this is required, per-CPU callback lists
3795873b8a9SPaul E. McKenney // will be needed.
38006a3ec92SPaul E. McKenney //
38106a3ec92SPaul E. McKenney // The implementation uses rcu_tasks_wait_gp(), which relies on function
38206a3ec92SPaul E. McKenney // pointers in the rcu_tasks structure.  The rcu_spawn_tasks_kthread()
38306a3ec92SPaul E. McKenney // function sets these function pointers up so that rcu_tasks_wait_gp()
38406a3ec92SPaul E. McKenney // invokes these functions in this order:
38506a3ec92SPaul E. McKenney //
38606a3ec92SPaul E. McKenney // rcu_tasks_pregp_step():
38706a3ec92SPaul E. McKenney //	Invokes synchronize_rcu() in order to wait for all in-flight
38806a3ec92SPaul E. McKenney //	t->on_rq and t->nvcsw transitions to complete.	This works because
38906a3ec92SPaul E. McKenney //	all such transitions are carried out with interrupts disabled.
39006a3ec92SPaul E. McKenney // rcu_tasks_pertask(), invoked on every non-idle task:
39106a3ec92SPaul E. McKenney //	For every runnable non-idle task other than the current one, use
39206a3ec92SPaul E. McKenney //	get_task_struct() to pin down that task, snapshot that task's
39306a3ec92SPaul E. McKenney //	number of voluntary context switches, and add that task to the
39406a3ec92SPaul E. McKenney //	holdout list.
39506a3ec92SPaul E. McKenney // rcu_tasks_postscan():
39606a3ec92SPaul E. McKenney //	Invoke synchronize_srcu() to ensure that all tasks that were
39706a3ec92SPaul E. McKenney //	in the process of exiting (and which thus might not know to
39806a3ec92SPaul E. McKenney //	synchronize with this RCU Tasks grace period) have completed
39906a3ec92SPaul E. McKenney //	exiting.
40006a3ec92SPaul E. McKenney // check_all_holdout_tasks(), repeatedly until holdout list is empty:
40106a3ec92SPaul E. McKenney //	Scans the holdout list, attempting to identify a quiescent state
40206a3ec92SPaul E. McKenney //	for each task on the list.  If there is a quiescent state, the
40306a3ec92SPaul E. McKenney //	corresponding task is removed from the holdout list.
40406a3ec92SPaul E. McKenney // rcu_tasks_postgp():
40506a3ec92SPaul E. McKenney //	Invokes synchronize_rcu() in order to ensure that all prior
40606a3ec92SPaul E. McKenney //	t->on_rq and t->nvcsw transitions are seen by all CPUs and tasks
40706a3ec92SPaul E. McKenney //	to have happened before the end of this RCU Tasks grace period.
40806a3ec92SPaul E. McKenney //	Again, this works because all such transitions are carried out
40906a3ec92SPaul E. McKenney //	with interrupts disabled.
41006a3ec92SPaul E. McKenney //
41106a3ec92SPaul E. McKenney // For each exiting task, the exit_tasks_rcu_start() and
41206a3ec92SPaul E. McKenney // exit_tasks_rcu_finish() functions begin and end, respectively, the SRCU
41306a3ec92SPaul E. McKenney // read-side critical sections waited for by rcu_tasks_postscan().
41406a3ec92SPaul E. McKenney //
41506a3ec92SPaul E. McKenney // Pre-grace-period update-side code is ordered before the grace via the
41606a3ec92SPaul E. McKenney // ->cbs_lock and the smp_mb__after_spinlock().  Pre-grace-period read-side
41706a3ec92SPaul E. McKenney // code is ordered before the grace period via synchronize_rcu() call
41806a3ec92SPaul E. McKenney // in rcu_tasks_pregp_step() and by the scheduler's locks and interrupt
41906a3ec92SPaul E. McKenney // disabling.
420eacd6f04SPaul E. McKenney 
421e4fe5dd6SPaul E. McKenney /* Pre-grace-period preparation. */
422e4fe5dd6SPaul E. McKenney static void rcu_tasks_pregp_step(void)
423e4fe5dd6SPaul E. McKenney {
424e4fe5dd6SPaul E. McKenney 	/*
425e4fe5dd6SPaul E. McKenney 	 * Wait for all pre-existing t->on_rq and t->nvcsw transitions
426e4fe5dd6SPaul E. McKenney 	 * to complete.  Invoking synchronize_rcu() suffices because all
427e4fe5dd6SPaul E. McKenney 	 * these transitions occur with interrupts disabled.  Without this
428e4fe5dd6SPaul E. McKenney 	 * synchronize_rcu(), a read-side critical section that started
429e4fe5dd6SPaul E. McKenney 	 * before the grace period might be incorrectly seen as having
430e4fe5dd6SPaul E. McKenney 	 * started after the grace period.
431e4fe5dd6SPaul E. McKenney 	 *
432e4fe5dd6SPaul E. McKenney 	 * This synchronize_rcu() also dispenses with the need for a
433e4fe5dd6SPaul E. McKenney 	 * memory barrier on the first store to t->rcu_tasks_holdout,
434e4fe5dd6SPaul E. McKenney 	 * as it forces the store to happen after the beginning of the
435e4fe5dd6SPaul E. McKenney 	 * grace period.
436e4fe5dd6SPaul E. McKenney 	 */
437e4fe5dd6SPaul E. McKenney 	synchronize_rcu();
438e4fe5dd6SPaul E. McKenney }
439e4fe5dd6SPaul E. McKenney 
440e4fe5dd6SPaul E. McKenney /* Per-task initial processing. */
441e4fe5dd6SPaul E. McKenney static void rcu_tasks_pertask(struct task_struct *t, struct list_head *hop)
442e4fe5dd6SPaul E. McKenney {
443e4fe5dd6SPaul E. McKenney 	if (t != current && READ_ONCE(t->on_rq) && !is_idle_task(t)) {
444e4fe5dd6SPaul E. McKenney 		get_task_struct(t);
445e4fe5dd6SPaul E. McKenney 		t->rcu_tasks_nvcsw = READ_ONCE(t->nvcsw);
446e4fe5dd6SPaul E. McKenney 		WRITE_ONCE(t->rcu_tasks_holdout, true);
447e4fe5dd6SPaul E. McKenney 		list_add(&t->rcu_tasks_holdout_list, hop);
448e4fe5dd6SPaul E. McKenney 	}
449e4fe5dd6SPaul E. McKenney }
450e4fe5dd6SPaul E. McKenney 
451e4fe5dd6SPaul E. McKenney /* Processing between scanning taskslist and draining the holdout list. */
45204a3c5aaSPaul E. McKenney static void rcu_tasks_postscan(struct list_head *hop)
453e4fe5dd6SPaul E. McKenney {
454e4fe5dd6SPaul E. McKenney 	/*
455e4fe5dd6SPaul E. McKenney 	 * Wait for tasks that are in the process of exiting.  This
456e4fe5dd6SPaul E. McKenney 	 * does only part of the job, ensuring that all tasks that were
457e4fe5dd6SPaul E. McKenney 	 * previously exiting reach the point where they have disabled
458e4fe5dd6SPaul E. McKenney 	 * preemption, allowing the later synchronize_rcu() to finish
459e4fe5dd6SPaul E. McKenney 	 * the job.
460e4fe5dd6SPaul E. McKenney 	 */
461e4fe5dd6SPaul E. McKenney 	synchronize_srcu(&tasks_rcu_exit_srcu);
462e4fe5dd6SPaul E. McKenney }
463e4fe5dd6SPaul E. McKenney 
464eacd6f04SPaul E. McKenney /* See if tasks are still holding out, complain if so. */
465eacd6f04SPaul E. McKenney static void check_holdout_task(struct task_struct *t,
466eacd6f04SPaul E. McKenney 			       bool needreport, bool *firstreport)
467eacd6f04SPaul E. McKenney {
468eacd6f04SPaul E. McKenney 	int cpu;
469eacd6f04SPaul E. McKenney 
470eacd6f04SPaul E. McKenney 	if (!READ_ONCE(t->rcu_tasks_holdout) ||
471eacd6f04SPaul E. McKenney 	    t->rcu_tasks_nvcsw != READ_ONCE(t->nvcsw) ||
472eacd6f04SPaul E. McKenney 	    !READ_ONCE(t->on_rq) ||
473eacd6f04SPaul E. McKenney 	    (IS_ENABLED(CONFIG_NO_HZ_FULL) &&
474eacd6f04SPaul E. McKenney 	     !is_idle_task(t) && t->rcu_tasks_idle_cpu >= 0)) {
475eacd6f04SPaul E. McKenney 		WRITE_ONCE(t->rcu_tasks_holdout, false);
476eacd6f04SPaul E. McKenney 		list_del_init(&t->rcu_tasks_holdout_list);
477eacd6f04SPaul E. McKenney 		put_task_struct(t);
478eacd6f04SPaul E. McKenney 		return;
479eacd6f04SPaul E. McKenney 	}
480eacd6f04SPaul E. McKenney 	rcu_request_urgent_qs_task(t);
481eacd6f04SPaul E. McKenney 	if (!needreport)
482eacd6f04SPaul E. McKenney 		return;
483eacd6f04SPaul E. McKenney 	if (*firstreport) {
484eacd6f04SPaul E. McKenney 		pr_err("INFO: rcu_tasks detected stalls on tasks:\n");
485eacd6f04SPaul E. McKenney 		*firstreport = false;
486eacd6f04SPaul E. McKenney 	}
487eacd6f04SPaul E. McKenney 	cpu = task_cpu(t);
488eacd6f04SPaul E. McKenney 	pr_alert("%p: %c%c nvcsw: %lu/%lu holdout: %d idle_cpu: %d/%d\n",
489eacd6f04SPaul E. McKenney 		 t, ".I"[is_idle_task(t)],
490eacd6f04SPaul E. McKenney 		 "N."[cpu < 0 || !tick_nohz_full_cpu(cpu)],
491eacd6f04SPaul E. McKenney 		 t->rcu_tasks_nvcsw, t->nvcsw, t->rcu_tasks_holdout,
492eacd6f04SPaul E. McKenney 		 t->rcu_tasks_idle_cpu, cpu);
493eacd6f04SPaul E. McKenney 	sched_show_task(t);
494eacd6f04SPaul E. McKenney }
495eacd6f04SPaul E. McKenney 
496e4fe5dd6SPaul E. McKenney /* Scan the holdout lists for tasks no longer holding out. */
497e4fe5dd6SPaul E. McKenney static void check_all_holdout_tasks(struct list_head *hop,
498e4fe5dd6SPaul E. McKenney 				    bool needreport, bool *firstreport)
499eacd6f04SPaul E. McKenney {
500e4fe5dd6SPaul E. McKenney 	struct task_struct *t, *t1;
501eacd6f04SPaul E. McKenney 
502e4fe5dd6SPaul E. McKenney 	list_for_each_entry_safe(t, t1, hop, rcu_tasks_holdout_list) {
503e4fe5dd6SPaul E. McKenney 		check_holdout_task(t, needreport, firstreport);
504eacd6f04SPaul E. McKenney 		cond_resched();
505eacd6f04SPaul E. McKenney 	}
506eacd6f04SPaul E. McKenney }
507eacd6f04SPaul E. McKenney 
508e4fe5dd6SPaul E. McKenney /* Finish off the Tasks-RCU grace period. */
509af051ca4SPaul E. McKenney static void rcu_tasks_postgp(struct rcu_tasks *rtp)
510e4fe5dd6SPaul E. McKenney {
511eacd6f04SPaul E. McKenney 	/*
5125873b8a9SPaul E. McKenney 	 * Because ->on_rq and ->nvcsw are not guaranteed to have a full
5135873b8a9SPaul E. McKenney 	 * memory barriers prior to them in the schedule() path, memory
5145873b8a9SPaul E. McKenney 	 * reordering on other CPUs could cause their RCU-tasks read-side
5155873b8a9SPaul E. McKenney 	 * critical sections to extend past the end of the grace period.
5165873b8a9SPaul E. McKenney 	 * However, because these ->nvcsw updates are carried out with
5175873b8a9SPaul E. McKenney 	 * interrupts disabled, we can use synchronize_rcu() to force the
5185873b8a9SPaul E. McKenney 	 * needed ordering on all such CPUs.
519eacd6f04SPaul E. McKenney 	 *
5205873b8a9SPaul E. McKenney 	 * This synchronize_rcu() also confines all ->rcu_tasks_holdout
5215873b8a9SPaul E. McKenney 	 * accesses to be within the grace period, avoiding the need for
5225873b8a9SPaul E. McKenney 	 * memory barriers for ->rcu_tasks_holdout accesses.
523eacd6f04SPaul E. McKenney 	 *
5245873b8a9SPaul E. McKenney 	 * In addition, this synchronize_rcu() waits for exiting tasks
5255873b8a9SPaul E. McKenney 	 * to complete their final preempt_disable() region of execution,
5265873b8a9SPaul E. McKenney 	 * cleaning up after the synchronize_srcu() above.
527eacd6f04SPaul E. McKenney 	 */
528eacd6f04SPaul E. McKenney 	synchronize_rcu();
529eacd6f04SPaul E. McKenney }
530eacd6f04SPaul E. McKenney 
5315873b8a9SPaul E. McKenney void call_rcu_tasks(struct rcu_head *rhp, rcu_callback_t func);
532c97d12a6SPaul E. McKenney DEFINE_RCU_TASKS(rcu_tasks, rcu_tasks_wait_gp, call_rcu_tasks, "RCU Tasks");
5335873b8a9SPaul E. McKenney 
5345873b8a9SPaul E. McKenney /**
5355873b8a9SPaul E. McKenney  * call_rcu_tasks() - Queue an RCU for invocation task-based grace period
5365873b8a9SPaul E. McKenney  * @rhp: structure to be used for queueing the RCU updates.
5375873b8a9SPaul E. McKenney  * @func: actual callback function to be invoked after the grace period
5385873b8a9SPaul E. McKenney  *
5395873b8a9SPaul E. McKenney  * The callback function will be invoked some time after a full grace
5405873b8a9SPaul E. McKenney  * period elapses, in other words after all currently executing RCU
5415873b8a9SPaul E. McKenney  * read-side critical sections have completed. call_rcu_tasks() assumes
5425873b8a9SPaul E. McKenney  * that the read-side critical sections end at a voluntary context
5435873b8a9SPaul E. McKenney  * switch (not a preemption!), cond_resched_rcu_qs(), entry into idle,
5445873b8a9SPaul E. McKenney  * or transition to usermode execution.  As such, there are no read-side
5455873b8a9SPaul E. McKenney  * primitives analogous to rcu_read_lock() and rcu_read_unlock() because
5465873b8a9SPaul E. McKenney  * this primitive is intended to determine that all tasks have passed
547a616aec9SIngo Molnar  * through a safe state, not so much for data-structure synchronization.
5485873b8a9SPaul E. McKenney  *
5495873b8a9SPaul E. McKenney  * See the description of call_rcu() for more detailed information on
5505873b8a9SPaul E. McKenney  * memory ordering guarantees.
5515873b8a9SPaul E. McKenney  */
5525873b8a9SPaul E. McKenney void call_rcu_tasks(struct rcu_head *rhp, rcu_callback_t func)
5535873b8a9SPaul E. McKenney {
5545873b8a9SPaul E. McKenney 	call_rcu_tasks_generic(rhp, func, &rcu_tasks);
5555873b8a9SPaul E. McKenney }
5565873b8a9SPaul E. McKenney EXPORT_SYMBOL_GPL(call_rcu_tasks);
5575873b8a9SPaul E. McKenney 
5585873b8a9SPaul E. McKenney /**
5595873b8a9SPaul E. McKenney  * synchronize_rcu_tasks - wait until an rcu-tasks grace period has elapsed.
5605873b8a9SPaul E. McKenney  *
5615873b8a9SPaul E. McKenney  * Control will return to the caller some time after a full rcu-tasks
5625873b8a9SPaul E. McKenney  * grace period has elapsed, in other words after all currently
5635873b8a9SPaul E. McKenney  * executing rcu-tasks read-side critical sections have elapsed.  These
5645873b8a9SPaul E. McKenney  * read-side critical sections are delimited by calls to schedule(),
5655873b8a9SPaul E. McKenney  * cond_resched_tasks_rcu_qs(), idle execution, userspace execution, calls
5665873b8a9SPaul E. McKenney  * to synchronize_rcu_tasks(), and (in theory, anyway) cond_resched().
5675873b8a9SPaul E. McKenney  *
5685873b8a9SPaul E. McKenney  * This is a very specialized primitive, intended only for a few uses in
5695873b8a9SPaul E. McKenney  * tracing and other situations requiring manipulation of function
5705873b8a9SPaul E. McKenney  * preambles and profiling hooks.  The synchronize_rcu_tasks() function
5715873b8a9SPaul E. McKenney  * is not (yet) intended for heavy use from multiple CPUs.
5725873b8a9SPaul E. McKenney  *
5735873b8a9SPaul E. McKenney  * See the description of synchronize_rcu() for more detailed information
5745873b8a9SPaul E. McKenney  * on memory ordering guarantees.
5755873b8a9SPaul E. McKenney  */
5765873b8a9SPaul E. McKenney void synchronize_rcu_tasks(void)
5775873b8a9SPaul E. McKenney {
5785873b8a9SPaul E. McKenney 	synchronize_rcu_tasks_generic(&rcu_tasks);
5795873b8a9SPaul E. McKenney }
5805873b8a9SPaul E. McKenney EXPORT_SYMBOL_GPL(synchronize_rcu_tasks);
5815873b8a9SPaul E. McKenney 
5825873b8a9SPaul E. McKenney /**
5835873b8a9SPaul E. McKenney  * rcu_barrier_tasks - Wait for in-flight call_rcu_tasks() callbacks.
5845873b8a9SPaul E. McKenney  *
5855873b8a9SPaul E. McKenney  * Although the current implementation is guaranteed to wait, it is not
5865873b8a9SPaul E. McKenney  * obligated to, for example, if there are no pending callbacks.
5875873b8a9SPaul E. McKenney  */
5885873b8a9SPaul E. McKenney void rcu_barrier_tasks(void)
5895873b8a9SPaul E. McKenney {
5905873b8a9SPaul E. McKenney 	/* There is only one callback queue, so this is easy.  ;-) */
5915873b8a9SPaul E. McKenney 	synchronize_rcu_tasks();
5925873b8a9SPaul E. McKenney }
5935873b8a9SPaul E. McKenney EXPORT_SYMBOL_GPL(rcu_barrier_tasks);
5945873b8a9SPaul E. McKenney 
595eacd6f04SPaul E. McKenney static int __init rcu_spawn_tasks_kthread(void)
596eacd6f04SPaul E. McKenney {
5974fe192dfSPaul E. McKenney 	rcu_tasks.gp_sleep = HZ / 10;
59875dc2da5SPaul E. McKenney 	rcu_tasks.init_fract = HZ / 10;
599e4fe5dd6SPaul E. McKenney 	rcu_tasks.pregp_func = rcu_tasks_pregp_step;
600e4fe5dd6SPaul E. McKenney 	rcu_tasks.pertask_func = rcu_tasks_pertask;
601e4fe5dd6SPaul E. McKenney 	rcu_tasks.postscan_func = rcu_tasks_postscan;
602e4fe5dd6SPaul E. McKenney 	rcu_tasks.holdouts_func = check_all_holdout_tasks;
603e4fe5dd6SPaul E. McKenney 	rcu_tasks.postgp_func = rcu_tasks_postgp;
6045873b8a9SPaul E. McKenney 	rcu_spawn_tasks_kthread_generic(&rcu_tasks);
605eacd6f04SPaul E. McKenney 	return 0;
606eacd6f04SPaul E. McKenney }
607eacd6f04SPaul E. McKenney 
60827c0f144SPaul E. McKenney #if !defined(CONFIG_TINY_RCU)
60927c0f144SPaul E. McKenney void show_rcu_tasks_classic_gp_kthread(void)
610e21408ceSPaul E. McKenney {
611e21408ceSPaul E. McKenney 	show_rcu_tasks_generic_gp_kthread(&rcu_tasks, "");
612e21408ceSPaul E. McKenney }
61327c0f144SPaul E. McKenney EXPORT_SYMBOL_GPL(show_rcu_tasks_classic_gp_kthread);
61427c0f144SPaul E. McKenney #endif // !defined(CONFIG_TINY_RCU)
615e21408ceSPaul E. McKenney 
61625246fc8SPaul E. McKenney /* Do the srcu_read_lock() for the above synchronize_srcu().  */
61725246fc8SPaul E. McKenney void exit_tasks_rcu_start(void) __acquires(&tasks_rcu_exit_srcu)
61825246fc8SPaul E. McKenney {
61925246fc8SPaul E. McKenney 	preempt_disable();
62025246fc8SPaul E. McKenney 	current->rcu_tasks_idx = __srcu_read_lock(&tasks_rcu_exit_srcu);
62125246fc8SPaul E. McKenney 	preempt_enable();
62225246fc8SPaul E. McKenney }
62325246fc8SPaul E. McKenney 
62425246fc8SPaul E. McKenney /* Do the srcu_read_unlock() for the above synchronize_srcu().  */
62525246fc8SPaul E. McKenney void exit_tasks_rcu_finish(void) __releases(&tasks_rcu_exit_srcu)
62625246fc8SPaul E. McKenney {
62725246fc8SPaul E. McKenney 	struct task_struct *t = current;
62825246fc8SPaul E. McKenney 
62925246fc8SPaul E. McKenney 	preempt_disable();
63025246fc8SPaul E. McKenney 	__srcu_read_unlock(&tasks_rcu_exit_srcu, t->rcu_tasks_idx);
63125246fc8SPaul E. McKenney 	preempt_enable();
63225246fc8SPaul E. McKenney 	exit_tasks_rcu_finish_trace(t);
63325246fc8SPaul E. McKenney }
63425246fc8SPaul E. McKenney 
635e21408ceSPaul E. McKenney #else /* #ifdef CONFIG_TASKS_RCU */
63625246fc8SPaul E. McKenney void exit_tasks_rcu_start(void) { }
63725246fc8SPaul E. McKenney void exit_tasks_rcu_finish(void) { exit_tasks_rcu_finish_trace(current); }
638e21408ceSPaul E. McKenney #endif /* #else #ifdef CONFIG_TASKS_RCU */
639c84aad76SPaul E. McKenney 
640c84aad76SPaul E. McKenney #ifdef CONFIG_TASKS_RUDE_RCU
641c84aad76SPaul E. McKenney 
642c84aad76SPaul E. McKenney ////////////////////////////////////////////////////////////////////////
643c84aad76SPaul E. McKenney //
644c84aad76SPaul E. McKenney // "Rude" variant of Tasks RCU, inspired by Steve Rostedt's trick of
645c84aad76SPaul E. McKenney // passing an empty function to schedule_on_each_cpu().  This approach
646c84aad76SPaul E. McKenney // provides an asynchronous call_rcu_tasks_rude() API and batching
647c84aad76SPaul E. McKenney // of concurrent calls to the synchronous synchronize_rcu_rude() API.
6489fc98e31SPaul E. McKenney // This invokes schedule_on_each_cpu() in order to send IPIs far and wide
6499fc98e31SPaul E. McKenney // and induces otherwise unnecessary context switches on all online CPUs,
6509fc98e31SPaul E. McKenney // whether idle or not.
6519fc98e31SPaul E. McKenney //
6529fc98e31SPaul E. McKenney // Callback handling is provided by the rcu_tasks_kthread() function.
6539fc98e31SPaul E. McKenney //
6549fc98e31SPaul E. McKenney // Ordering is provided by the scheduler's context-switch code.
655c84aad76SPaul E. McKenney 
656c84aad76SPaul E. McKenney // Empty function to allow workqueues to force a context switch.
657c84aad76SPaul E. McKenney static void rcu_tasks_be_rude(struct work_struct *work)
658c84aad76SPaul E. McKenney {
659c84aad76SPaul E. McKenney }
660c84aad76SPaul E. McKenney 
661c84aad76SPaul E. McKenney // Wait for one rude RCU-tasks grace period.
662c84aad76SPaul E. McKenney static void rcu_tasks_rude_wait_gp(struct rcu_tasks *rtp)
663c84aad76SPaul E. McKenney {
664238dbce3SPaul E. McKenney 	rtp->n_ipis += cpumask_weight(cpu_online_mask);
665c84aad76SPaul E. McKenney 	schedule_on_each_cpu(rcu_tasks_be_rude);
666c84aad76SPaul E. McKenney }
667c84aad76SPaul E. McKenney 
668c84aad76SPaul E. McKenney void call_rcu_tasks_rude(struct rcu_head *rhp, rcu_callback_t func);
669c97d12a6SPaul E. McKenney DEFINE_RCU_TASKS(rcu_tasks_rude, rcu_tasks_rude_wait_gp, call_rcu_tasks_rude,
670c97d12a6SPaul E. McKenney 		 "RCU Tasks Rude");
671c84aad76SPaul E. McKenney 
672c84aad76SPaul E. McKenney /**
673c84aad76SPaul E. McKenney  * call_rcu_tasks_rude() - Queue a callback rude task-based grace period
674c84aad76SPaul E. McKenney  * @rhp: structure to be used for queueing the RCU updates.
675c84aad76SPaul E. McKenney  * @func: actual callback function to be invoked after the grace period
676c84aad76SPaul E. McKenney  *
677c84aad76SPaul E. McKenney  * The callback function will be invoked some time after a full grace
678c84aad76SPaul E. McKenney  * period elapses, in other words after all currently executing RCU
679c84aad76SPaul E. McKenney  * read-side critical sections have completed. call_rcu_tasks_rude()
680c84aad76SPaul E. McKenney  * assumes that the read-side critical sections end at context switch,
681c84aad76SPaul E. McKenney  * cond_resched_rcu_qs(), or transition to usermode execution.  As such,
682c84aad76SPaul E. McKenney  * there are no read-side primitives analogous to rcu_read_lock() and
683c84aad76SPaul E. McKenney  * rcu_read_unlock() because this primitive is intended to determine
684c84aad76SPaul E. McKenney  * that all tasks have passed through a safe state, not so much for
685a616aec9SIngo Molnar  * data-structure synchronization.
686c84aad76SPaul E. McKenney  *
687c84aad76SPaul E. McKenney  * See the description of call_rcu() for more detailed information on
688c84aad76SPaul E. McKenney  * memory ordering guarantees.
689c84aad76SPaul E. McKenney  */
690c84aad76SPaul E. McKenney void call_rcu_tasks_rude(struct rcu_head *rhp, rcu_callback_t func)
691c84aad76SPaul E. McKenney {
692c84aad76SPaul E. McKenney 	call_rcu_tasks_generic(rhp, func, &rcu_tasks_rude);
693c84aad76SPaul E. McKenney }
694c84aad76SPaul E. McKenney EXPORT_SYMBOL_GPL(call_rcu_tasks_rude);
695c84aad76SPaul E. McKenney 
696c84aad76SPaul E. McKenney /**
697c84aad76SPaul E. McKenney  * synchronize_rcu_tasks_rude - wait for a rude rcu-tasks grace period
698c84aad76SPaul E. McKenney  *
699c84aad76SPaul E. McKenney  * Control will return to the caller some time after a rude rcu-tasks
700c84aad76SPaul E. McKenney  * grace period has elapsed, in other words after all currently
701c84aad76SPaul E. McKenney  * executing rcu-tasks read-side critical sections have elapsed.  These
702c84aad76SPaul E. McKenney  * read-side critical sections are delimited by calls to schedule(),
703c84aad76SPaul E. McKenney  * cond_resched_tasks_rcu_qs(), userspace execution, and (in theory,
704c84aad76SPaul E. McKenney  * anyway) cond_resched().
705c84aad76SPaul E. McKenney  *
706c84aad76SPaul E. McKenney  * This is a very specialized primitive, intended only for a few uses in
707c84aad76SPaul E. McKenney  * tracing and other situations requiring manipulation of function preambles
708c84aad76SPaul E. McKenney  * and profiling hooks.  The synchronize_rcu_tasks_rude() function is not
709c84aad76SPaul E. McKenney  * (yet) intended for heavy use from multiple CPUs.
710c84aad76SPaul E. McKenney  *
711c84aad76SPaul E. McKenney  * See the description of synchronize_rcu() for more detailed information
712c84aad76SPaul E. McKenney  * on memory ordering guarantees.
713c84aad76SPaul E. McKenney  */
714c84aad76SPaul E. McKenney void synchronize_rcu_tasks_rude(void)
715c84aad76SPaul E. McKenney {
716c84aad76SPaul E. McKenney 	synchronize_rcu_tasks_generic(&rcu_tasks_rude);
717c84aad76SPaul E. McKenney }
718c84aad76SPaul E. McKenney EXPORT_SYMBOL_GPL(synchronize_rcu_tasks_rude);
719c84aad76SPaul E. McKenney 
720c84aad76SPaul E. McKenney /**
721c84aad76SPaul E. McKenney  * rcu_barrier_tasks_rude - Wait for in-flight call_rcu_tasks_rude() callbacks.
722c84aad76SPaul E. McKenney  *
723c84aad76SPaul E. McKenney  * Although the current implementation is guaranteed to wait, it is not
724c84aad76SPaul E. McKenney  * obligated to, for example, if there are no pending callbacks.
725c84aad76SPaul E. McKenney  */
726c84aad76SPaul E. McKenney void rcu_barrier_tasks_rude(void)
727c84aad76SPaul E. McKenney {
728c84aad76SPaul E. McKenney 	/* There is only one callback queue, so this is easy.  ;-) */
729c84aad76SPaul E. McKenney 	synchronize_rcu_tasks_rude();
730c84aad76SPaul E. McKenney }
731c84aad76SPaul E. McKenney EXPORT_SYMBOL_GPL(rcu_barrier_tasks_rude);
732c84aad76SPaul E. McKenney 
733c84aad76SPaul E. McKenney static int __init rcu_spawn_tasks_rude_kthread(void)
734c84aad76SPaul E. McKenney {
7354fe192dfSPaul E. McKenney 	rcu_tasks_rude.gp_sleep = HZ / 10;
736c84aad76SPaul E. McKenney 	rcu_spawn_tasks_kthread_generic(&rcu_tasks_rude);
737c84aad76SPaul E. McKenney 	return 0;
738c84aad76SPaul E. McKenney }
739c84aad76SPaul E. McKenney 
74027c0f144SPaul E. McKenney #if !defined(CONFIG_TINY_RCU)
74127c0f144SPaul E. McKenney void show_rcu_tasks_rude_gp_kthread(void)
742e21408ceSPaul E. McKenney {
743e21408ceSPaul E. McKenney 	show_rcu_tasks_generic_gp_kthread(&rcu_tasks_rude, "");
744e21408ceSPaul E. McKenney }
74527c0f144SPaul E. McKenney EXPORT_SYMBOL_GPL(show_rcu_tasks_rude_gp_kthread);
74627c0f144SPaul E. McKenney #endif // !defined(CONFIG_TINY_RCU)
74727c0f144SPaul E. McKenney #endif /* #ifdef CONFIG_TASKS_RUDE_RCU */
748d5f177d3SPaul E. McKenney 
749d5f177d3SPaul E. McKenney ////////////////////////////////////////////////////////////////////////
750d5f177d3SPaul E. McKenney //
751d5f177d3SPaul E. McKenney // Tracing variant of Tasks RCU.  This variant is designed to be used
752d5f177d3SPaul E. McKenney // to protect tracing hooks, including those of BPF.  This variant
753d5f177d3SPaul E. McKenney // therefore:
754d5f177d3SPaul E. McKenney //
755d5f177d3SPaul E. McKenney // 1.	Has explicit read-side markers to allow finite grace periods
756d5f177d3SPaul E. McKenney //	in the face of in-kernel loops for PREEMPT=n builds.
757d5f177d3SPaul E. McKenney //
758d5f177d3SPaul E. McKenney // 2.	Protects code in the idle loop, exception entry/exit, and
759d5f177d3SPaul E. McKenney //	CPU-hotplug code paths, similar to the capabilities of SRCU.
760d5f177d3SPaul E. McKenney //
761d5f177d3SPaul E. McKenney // 3.	Avoids expensive read-side instruction, having overhead similar
762d5f177d3SPaul E. McKenney //	to that of Preemptible RCU.
763d5f177d3SPaul E. McKenney //
764d5f177d3SPaul E. McKenney // There are of course downsides.  The grace-period code can send IPIs to
765d5f177d3SPaul E. McKenney // CPUs, even when those CPUs are in the idle loop or in nohz_full userspace.
766d5f177d3SPaul E. McKenney // It is necessary to scan the full tasklist, much as for Tasks RCU.  There
767d5f177d3SPaul E. McKenney // is a single callback queue guarded by a single lock, again, much as for
768d5f177d3SPaul E. McKenney // Tasks RCU.  If needed, these downsides can be at least partially remedied.
769d5f177d3SPaul E. McKenney //
770d5f177d3SPaul E. McKenney // Perhaps most important, this variant of RCU does not affect the vanilla
771d5f177d3SPaul E. McKenney // flavors, rcu_preempt and rcu_sched.  The fact that RCU Tasks Trace
772d5f177d3SPaul E. McKenney // readers can operate from idle, offline, and exception entry/exit in no
773d5f177d3SPaul E. McKenney // way allows rcu_preempt and rcu_sched readers to also do so.
774a434dd10SPaul E. McKenney //
775a434dd10SPaul E. McKenney // The implementation uses rcu_tasks_wait_gp(), which relies on function
776a434dd10SPaul E. McKenney // pointers in the rcu_tasks structure.  The rcu_spawn_tasks_trace_kthread()
777a434dd10SPaul E. McKenney // function sets these function pointers up so that rcu_tasks_wait_gp()
778a434dd10SPaul E. McKenney // invokes these functions in this order:
779a434dd10SPaul E. McKenney //
780a434dd10SPaul E. McKenney // rcu_tasks_trace_pregp_step():
781a434dd10SPaul E. McKenney //	Initialize the count of readers and block CPU-hotplug operations.
782a434dd10SPaul E. McKenney // rcu_tasks_trace_pertask(), invoked on every non-idle task:
783a434dd10SPaul E. McKenney //	Initialize per-task state and attempt to identify an immediate
784a434dd10SPaul E. McKenney //	quiescent state for that task, or, failing that, attempt to
785a434dd10SPaul E. McKenney //	set that task's .need_qs flag so that task's next outermost
786a434dd10SPaul E. McKenney //	rcu_read_unlock_trace() will report the quiescent state (in which
787a434dd10SPaul E. McKenney //	case the count of readers is incremented).  If both attempts fail,
788a434dd10SPaul E. McKenney //	the task is added to a "holdout" list.
789a434dd10SPaul E. McKenney // rcu_tasks_trace_postscan():
790a434dd10SPaul E. McKenney //	Initialize state and attempt to identify an immediate quiescent
791a434dd10SPaul E. McKenney //	state as above (but only for idle tasks), unblock CPU-hotplug
792a434dd10SPaul E. McKenney //	operations, and wait for an RCU grace period to avoid races with
793a434dd10SPaul E. McKenney //	tasks that are in the process of exiting.
794a434dd10SPaul E. McKenney // check_all_holdout_tasks_trace(), repeatedly until holdout list is empty:
795a434dd10SPaul E. McKenney //	Scans the holdout list, attempting to identify a quiescent state
796a434dd10SPaul E. McKenney //	for each task on the list.  If there is a quiescent state, the
797a434dd10SPaul E. McKenney //	corresponding task is removed from the holdout list.
798a434dd10SPaul E. McKenney // rcu_tasks_trace_postgp():
799a434dd10SPaul E. McKenney //	Wait for the count of readers do drop to zero, reporting any stalls.
800a434dd10SPaul E. McKenney //	Also execute full memory barriers to maintain ordering with code
801a434dd10SPaul E. McKenney //	executing after the grace period.
802a434dd10SPaul E. McKenney //
803a434dd10SPaul E. McKenney // The exit_tasks_rcu_finish_trace() synchronizes with exiting tasks.
804a434dd10SPaul E. McKenney //
805a434dd10SPaul E. McKenney // Pre-grace-period update-side code is ordered before the grace
806a434dd10SPaul E. McKenney // period via the ->cbs_lock and barriers in rcu_tasks_kthread().
807a434dd10SPaul E. McKenney // Pre-grace-period read-side code is ordered before the grace period by
808a434dd10SPaul E. McKenney // atomic_dec_and_test() of the count of readers (for IPIed readers) and by
809a434dd10SPaul E. McKenney // scheduler context-switch ordering (for locked-down non-running readers).
810d5f177d3SPaul E. McKenney 
811d5f177d3SPaul E. McKenney // The lockdep state must be outside of #ifdef to be useful.
812d5f177d3SPaul E. McKenney #ifdef CONFIG_DEBUG_LOCK_ALLOC
813d5f177d3SPaul E. McKenney static struct lock_class_key rcu_lock_trace_key;
814d5f177d3SPaul E. McKenney struct lockdep_map rcu_trace_lock_map =
815d5f177d3SPaul E. McKenney 	STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_trace", &rcu_lock_trace_key);
816d5f177d3SPaul E. McKenney EXPORT_SYMBOL_GPL(rcu_trace_lock_map);
817d5f177d3SPaul E. McKenney #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
818d5f177d3SPaul E. McKenney 
819d5f177d3SPaul E. McKenney #ifdef CONFIG_TASKS_TRACE_RCU
820d5f177d3SPaul E. McKenney 
82130d8aa51SPaul E. McKenney static atomic_t trc_n_readers_need_end;		// Number of waited-for readers.
82230d8aa51SPaul E. McKenney static DECLARE_WAIT_QUEUE_HEAD(trc_wait);	// List of holdout tasks.
823d5f177d3SPaul E. McKenney 
824d5f177d3SPaul E. McKenney // Record outstanding IPIs to each CPU.  No point in sending two...
825d5f177d3SPaul E. McKenney static DEFINE_PER_CPU(bool, trc_ipi_to_cpu);
826d5f177d3SPaul E. McKenney 
82740471509SPaul E. McKenney // The number of detections of task quiescent state relying on
82840471509SPaul E. McKenney // heavyweight readers executing explicit memory barriers.
8296731da9eSPaul E. McKenney static unsigned long n_heavy_reader_attempts;
8306731da9eSPaul E. McKenney static unsigned long n_heavy_reader_updates;
8316731da9eSPaul E. McKenney static unsigned long n_heavy_reader_ofl_updates;
83240471509SPaul E. McKenney 
833b0afa0f0SPaul E. McKenney void call_rcu_tasks_trace(struct rcu_head *rhp, rcu_callback_t func);
834b0afa0f0SPaul E. McKenney DEFINE_RCU_TASKS(rcu_tasks_trace, rcu_tasks_wait_gp, call_rcu_tasks_trace,
835b0afa0f0SPaul E. McKenney 		 "RCU Tasks Trace");
836b0afa0f0SPaul E. McKenney 
837b38f57c1SPaul E. McKenney /*
838b38f57c1SPaul E. McKenney  * This irq_work handler allows rcu_read_unlock_trace() to be invoked
839b38f57c1SPaul E. McKenney  * while the scheduler locks are held.
840b38f57c1SPaul E. McKenney  */
841b38f57c1SPaul E. McKenney static void rcu_read_unlock_iw(struct irq_work *iwp)
842b38f57c1SPaul E. McKenney {
843b38f57c1SPaul E. McKenney 	wake_up(&trc_wait);
844b38f57c1SPaul E. McKenney }
845b38f57c1SPaul E. McKenney static DEFINE_IRQ_WORK(rcu_tasks_trace_iw, rcu_read_unlock_iw);
846b38f57c1SPaul E. McKenney 
847d5f177d3SPaul E. McKenney /* If we are the last reader, wake up the grace-period kthread. */
848276c4104SPaul E. McKenney void rcu_read_unlock_trace_special(struct task_struct *t, int nesting)
849d5f177d3SPaul E. McKenney {
850276c4104SPaul E. McKenney 	int nq = t->trc_reader_special.b.need_qs;
851276c4104SPaul E. McKenney 
8529ae58d7bSPaul E. McKenney 	if (IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB) &&
8539ae58d7bSPaul E. McKenney 	    t->trc_reader_special.b.need_mb)
854276c4104SPaul E. McKenney 		smp_mb(); // Pairs with update-side barriers.
855276c4104SPaul E. McKenney 	// Update .need_qs before ->trc_reader_nesting for irq/NMI handlers.
856276c4104SPaul E. McKenney 	if (nq)
857276c4104SPaul E. McKenney 		WRITE_ONCE(t->trc_reader_special.b.need_qs, false);
858276c4104SPaul E. McKenney 	WRITE_ONCE(t->trc_reader_nesting, nesting);
859276c4104SPaul E. McKenney 	if (nq && atomic_dec_and_test(&trc_n_readers_need_end))
860b38f57c1SPaul E. McKenney 		irq_work_queue(&rcu_tasks_trace_iw);
861d5f177d3SPaul E. McKenney }
862d5f177d3SPaul E. McKenney EXPORT_SYMBOL_GPL(rcu_read_unlock_trace_special);
863d5f177d3SPaul E. McKenney 
864d5f177d3SPaul E. McKenney /* Add a task to the holdout list, if it is not already on the list. */
865d5f177d3SPaul E. McKenney static void trc_add_holdout(struct task_struct *t, struct list_head *bhp)
866d5f177d3SPaul E. McKenney {
867d5f177d3SPaul E. McKenney 	if (list_empty(&t->trc_holdout_list)) {
868d5f177d3SPaul E. McKenney 		get_task_struct(t);
869d5f177d3SPaul E. McKenney 		list_add(&t->trc_holdout_list, bhp);
870d5f177d3SPaul E. McKenney 	}
871d5f177d3SPaul E. McKenney }
872d5f177d3SPaul E. McKenney 
873d5f177d3SPaul E. McKenney /* Remove a task from the holdout list, if it is in fact present. */
874d5f177d3SPaul E. McKenney static void trc_del_holdout(struct task_struct *t)
875d5f177d3SPaul E. McKenney {
876d5f177d3SPaul E. McKenney 	if (!list_empty(&t->trc_holdout_list)) {
877d5f177d3SPaul E. McKenney 		list_del_init(&t->trc_holdout_list);
878d5f177d3SPaul E. McKenney 		put_task_struct(t);
879d5f177d3SPaul E. McKenney 	}
880d5f177d3SPaul E. McKenney }
881d5f177d3SPaul E. McKenney 
882d5f177d3SPaul E. McKenney /* IPI handler to check task state. */
883d5f177d3SPaul E. McKenney static void trc_read_check_handler(void *t_in)
884d5f177d3SPaul E. McKenney {
885d5f177d3SPaul E. McKenney 	struct task_struct *t = current;
886d5f177d3SPaul E. McKenney 	struct task_struct *texp = t_in;
887d5f177d3SPaul E. McKenney 
888d5f177d3SPaul E. McKenney 	// If the task is no longer running on this CPU, leave.
889d5f177d3SPaul E. McKenney 	if (unlikely(texp != t)) {
890d5f177d3SPaul E. McKenney 		if (WARN_ON_ONCE(atomic_dec_and_test(&trc_n_readers_need_end)))
891d5f177d3SPaul E. McKenney 			wake_up(&trc_wait);
892d5f177d3SPaul E. McKenney 		goto reset_ipi; // Already on holdout list, so will check later.
893d5f177d3SPaul E. McKenney 	}
894d5f177d3SPaul E. McKenney 
895d5f177d3SPaul E. McKenney 	// If the task is not in a read-side critical section, and
896d5f177d3SPaul E. McKenney 	// if this is the last reader, awaken the grace-period kthread.
897d5f177d3SPaul E. McKenney 	if (likely(!t->trc_reader_nesting)) {
898d5f177d3SPaul E. McKenney 		if (WARN_ON_ONCE(atomic_dec_and_test(&trc_n_readers_need_end)))
899d5f177d3SPaul E. McKenney 			wake_up(&trc_wait);
900d5f177d3SPaul E. McKenney 		// Mark as checked after decrement to avoid false
901d5f177d3SPaul E. McKenney 		// positives on the above WARN_ON_ONCE().
902d5f177d3SPaul E. McKenney 		WRITE_ONCE(t->trc_reader_checked, true);
903d5f177d3SPaul E. McKenney 		goto reset_ipi;
904d5f177d3SPaul E. McKenney 	}
905ba3a86e4SPaul E. McKenney 	// If we are racing with an rcu_read_unlock_trace(), try again later.
906ba3a86e4SPaul E. McKenney 	if (unlikely(t->trc_reader_nesting < 0)) {
907ba3a86e4SPaul E. McKenney 		if (WARN_ON_ONCE(atomic_dec_and_test(&trc_n_readers_need_end)))
908ba3a86e4SPaul E. McKenney 			wake_up(&trc_wait);
909ba3a86e4SPaul E. McKenney 		goto reset_ipi;
910ba3a86e4SPaul E. McKenney 	}
911d5f177d3SPaul E. McKenney 	WRITE_ONCE(t->trc_reader_checked, true);
912d5f177d3SPaul E. McKenney 
913d5f177d3SPaul E. McKenney 	// Get here if the task is in a read-side critical section.  Set
914d5f177d3SPaul E. McKenney 	// its state so that it will awaken the grace-period kthread upon
915d5f177d3SPaul E. McKenney 	// exit from that critical section.
916276c4104SPaul E. McKenney 	WARN_ON_ONCE(t->trc_reader_special.b.need_qs);
917276c4104SPaul E. McKenney 	WRITE_ONCE(t->trc_reader_special.b.need_qs, true);
918d5f177d3SPaul E. McKenney 
919d5f177d3SPaul E. McKenney reset_ipi:
920d5f177d3SPaul E. McKenney 	// Allow future IPIs to be sent on CPU and for task.
921d5f177d3SPaul E. McKenney 	// Also order this IPI handler against any later manipulations of
922d5f177d3SPaul E. McKenney 	// the intended task.
923d5f177d3SPaul E. McKenney 	smp_store_release(&per_cpu(trc_ipi_to_cpu, smp_processor_id()), false); // ^^^
924d5f177d3SPaul E. McKenney 	smp_store_release(&texp->trc_ipi_to_cpu, -1); // ^^^
925d5f177d3SPaul E. McKenney }
926d5f177d3SPaul E. McKenney 
927d5f177d3SPaul E. McKenney /* Callback function for scheduler to check locked-down task.  */
928d5f177d3SPaul E. McKenney static bool trc_inspect_reader(struct task_struct *t, void *arg)
929d5f177d3SPaul E. McKenney {
9307d0c9c50SPaul E. McKenney 	int cpu = task_cpu(t);
9317d0c9c50SPaul E. McKenney 	bool in_qs = false;
9327e3b70e0SPaul E. McKenney 	bool ofl = cpu_is_offline(cpu);
9337d0c9c50SPaul E. McKenney 
9347d0c9c50SPaul E. McKenney 	if (task_curr(t)) {
93530d8aa51SPaul E. McKenney 		WARN_ON_ONCE(ofl && !is_idle_task(t));
9367e3b70e0SPaul E. McKenney 
9377d0c9c50SPaul E. McKenney 		// If no chance of heavyweight readers, do it the hard way.
9387e3b70e0SPaul E. McKenney 		if (!ofl && !IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB))
9397d0c9c50SPaul E. McKenney 			return false;
9407d0c9c50SPaul E. McKenney 
9417d0c9c50SPaul E. McKenney 		// If heavyweight readers are enabled on the remote task,
9427d0c9c50SPaul E. McKenney 		// we can inspect its state despite its currently running.
9437d0c9c50SPaul E. McKenney 		// However, we cannot safely change its state.
94440471509SPaul E. McKenney 		n_heavy_reader_attempts++;
9457e3b70e0SPaul E. McKenney 		if (!ofl && // Check for "running" idle tasks on offline CPUs.
9467e3b70e0SPaul E. McKenney 		    !rcu_dynticks_zero_in_eqs(cpu, &t->trc_reader_nesting))
9477d0c9c50SPaul E. McKenney 			return false; // No quiescent state, do it the hard way.
94840471509SPaul E. McKenney 		n_heavy_reader_updates++;
949edf3775fSPaul E. McKenney 		if (ofl)
950edf3775fSPaul E. McKenney 			n_heavy_reader_ofl_updates++;
9517d0c9c50SPaul E. McKenney 		in_qs = true;
9527d0c9c50SPaul E. McKenney 	} else {
9537d0c9c50SPaul E. McKenney 		in_qs = likely(!t->trc_reader_nesting);
9547d0c9c50SPaul E. McKenney 	}
955d5f177d3SPaul E. McKenney 
956*1d10bf55SPaul E. McKenney 	// Mark as checked so that the grace-period kthread will
957*1d10bf55SPaul E. McKenney 	// remove it from the holdout list.
958d5f177d3SPaul E. McKenney 	t->trc_reader_checked = true;
959d5f177d3SPaul E. McKenney 
9607d0c9c50SPaul E. McKenney 	if (in_qs)
9617d0c9c50SPaul E. McKenney 		return true;  // Already in quiescent state, done!!!
9627d0c9c50SPaul E. McKenney 
9637d0c9c50SPaul E. McKenney 	// The task is in a read-side critical section, so set up its
9647d0c9c50SPaul E. McKenney 	// state so that it will awaken the grace-period kthread upon exit
9657d0c9c50SPaul E. McKenney 	// from that critical section.
966d5f177d3SPaul E. McKenney 	atomic_inc(&trc_n_readers_need_end); // One more to wait on.
967276c4104SPaul E. McKenney 	WARN_ON_ONCE(t->trc_reader_special.b.need_qs);
968276c4104SPaul E. McKenney 	WRITE_ONCE(t->trc_reader_special.b.need_qs, true);
969d5f177d3SPaul E. McKenney 	return true;
970d5f177d3SPaul E. McKenney }
971d5f177d3SPaul E. McKenney 
972d5f177d3SPaul E. McKenney /* Attempt to extract the state for the specified task. */
973d5f177d3SPaul E. McKenney static void trc_wait_for_one_reader(struct task_struct *t,
974d5f177d3SPaul E. McKenney 				    struct list_head *bhp)
975d5f177d3SPaul E. McKenney {
976d5f177d3SPaul E. McKenney 	int cpu;
977d5f177d3SPaul E. McKenney 
978d5f177d3SPaul E. McKenney 	// If a previous IPI is still in flight, let it complete.
979d5f177d3SPaul E. McKenney 	if (smp_load_acquire(&t->trc_ipi_to_cpu) != -1) // Order IPI
980d5f177d3SPaul E. McKenney 		return;
981d5f177d3SPaul E. McKenney 
982d5f177d3SPaul E. McKenney 	// The current task had better be in a quiescent state.
983d5f177d3SPaul E. McKenney 	if (t == current) {
984d5f177d3SPaul E. McKenney 		t->trc_reader_checked = true;
985d5f177d3SPaul E. McKenney 		WARN_ON_ONCE(t->trc_reader_nesting);
986d5f177d3SPaul E. McKenney 		return;
987d5f177d3SPaul E. McKenney 	}
988d5f177d3SPaul E. McKenney 
989d5f177d3SPaul E. McKenney 	// Attempt to nail down the task for inspection.
990d5f177d3SPaul E. McKenney 	get_task_struct(t);
991d5f177d3SPaul E. McKenney 	if (try_invoke_on_locked_down_task(t, trc_inspect_reader, NULL)) {
992d5f177d3SPaul E. McKenney 		put_task_struct(t);
993d5f177d3SPaul E. McKenney 		return;
994d5f177d3SPaul E. McKenney 	}
995d5f177d3SPaul E. McKenney 	put_task_struct(t);
996d5f177d3SPaul E. McKenney 
997d5f177d3SPaul E. McKenney 	// If currently running, send an IPI, either way, add to list.
998d5f177d3SPaul E. McKenney 	trc_add_holdout(t, bhp);
999574de876SPaul E. McKenney 	if (task_curr(t) &&
1000574de876SPaul E. McKenney 	    time_after(jiffies + 1, rcu_tasks_trace.gp_start + rcu_task_ipi_delay)) {
1001d5f177d3SPaul E. McKenney 		// The task is currently running, so try IPIing it.
1002d5f177d3SPaul E. McKenney 		cpu = task_cpu(t);
1003d5f177d3SPaul E. McKenney 
1004d5f177d3SPaul E. McKenney 		// If there is already an IPI outstanding, let it happen.
1005d5f177d3SPaul E. McKenney 		if (per_cpu(trc_ipi_to_cpu, cpu) || t->trc_ipi_to_cpu >= 0)
1006d5f177d3SPaul E. McKenney 			return;
1007d5f177d3SPaul E. McKenney 
1008d5f177d3SPaul E. McKenney 		atomic_inc(&trc_n_readers_need_end);
1009d5f177d3SPaul E. McKenney 		per_cpu(trc_ipi_to_cpu, cpu) = true;
1010d5f177d3SPaul E. McKenney 		t->trc_ipi_to_cpu = cpu;
1011238dbce3SPaul E. McKenney 		rcu_tasks_trace.n_ipis++;
1012d5f177d3SPaul E. McKenney 		if (smp_call_function_single(cpu,
1013d5f177d3SPaul E. McKenney 					     trc_read_check_handler, t, 0)) {
1014d5f177d3SPaul E. McKenney 			// Just in case there is some other reason for
1015d5f177d3SPaul E. McKenney 			// failure than the target CPU being offline.
10167e0669c3SPaul E. McKenney 			rcu_tasks_trace.n_ipis_fails++;
1017d5f177d3SPaul E. McKenney 			per_cpu(trc_ipi_to_cpu, cpu) = false;
1018d5f177d3SPaul E. McKenney 			t->trc_ipi_to_cpu = cpu;
1019d5f177d3SPaul E. McKenney 			if (atomic_dec_and_test(&trc_n_readers_need_end)) {
1020d5f177d3SPaul E. McKenney 				WARN_ON_ONCE(1);
1021d5f177d3SPaul E. McKenney 				wake_up(&trc_wait);
1022d5f177d3SPaul E. McKenney 			}
1023d5f177d3SPaul E. McKenney 		}
1024d5f177d3SPaul E. McKenney 	}
1025d5f177d3SPaul E. McKenney }
1026d5f177d3SPaul E. McKenney 
1027d5f177d3SPaul E. McKenney /* Initialize for a new RCU-tasks-trace grace period. */
1028d5f177d3SPaul E. McKenney static void rcu_tasks_trace_pregp_step(void)
1029d5f177d3SPaul E. McKenney {
1030d5f177d3SPaul E. McKenney 	int cpu;
1031d5f177d3SPaul E. McKenney 
1032d5f177d3SPaul E. McKenney 	// Allow for fast-acting IPIs.
1033d5f177d3SPaul E. McKenney 	atomic_set(&trc_n_readers_need_end, 1);
1034d5f177d3SPaul E. McKenney 
1035d5f177d3SPaul E. McKenney 	// There shouldn't be any old IPIs, but...
1036d5f177d3SPaul E. McKenney 	for_each_possible_cpu(cpu)
1037d5f177d3SPaul E. McKenney 		WARN_ON_ONCE(per_cpu(trc_ipi_to_cpu, cpu));
103881b4a7bcSPaul E. McKenney 
103981b4a7bcSPaul E. McKenney 	// Disable CPU hotplug across the tasklist scan.
104081b4a7bcSPaul E. McKenney 	// This also waits for all readers in CPU-hotplug code paths.
104181b4a7bcSPaul E. McKenney 	cpus_read_lock();
1042d5f177d3SPaul E. McKenney }
1043d5f177d3SPaul E. McKenney 
1044d5f177d3SPaul E. McKenney /* Do first-round processing for the specified task. */
1045d5f177d3SPaul E. McKenney static void rcu_tasks_trace_pertask(struct task_struct *t,
1046d5f177d3SPaul E. McKenney 				    struct list_head *hop)
1047d5f177d3SPaul E. McKenney {
10481b04fa99SUladzislau Rezki (Sony) 	// During early boot when there is only the one boot CPU, there
10491b04fa99SUladzislau Rezki (Sony) 	// is no idle task for the other CPUs. Just return.
10501b04fa99SUladzislau Rezki (Sony) 	if (unlikely(t == NULL))
10511b04fa99SUladzislau Rezki (Sony) 		return;
10521b04fa99SUladzislau Rezki (Sony) 
1053276c4104SPaul E. McKenney 	WRITE_ONCE(t->trc_reader_special.b.need_qs, false);
105443766c3eSPaul E. McKenney 	WRITE_ONCE(t->trc_reader_checked, false);
1055d5f177d3SPaul E. McKenney 	t->trc_ipi_to_cpu = -1;
1056d5f177d3SPaul E. McKenney 	trc_wait_for_one_reader(t, hop);
1057d5f177d3SPaul E. McKenney }
1058d5f177d3SPaul E. McKenney 
10599796e1aeSPaul E. McKenney /*
10609796e1aeSPaul E. McKenney  * Do intermediate processing between task and holdout scans and
10619796e1aeSPaul E. McKenney  * pick up the idle tasks.
10629796e1aeSPaul E. McKenney  */
10639796e1aeSPaul E. McKenney static void rcu_tasks_trace_postscan(struct list_head *hop)
1064d5f177d3SPaul E. McKenney {
10659796e1aeSPaul E. McKenney 	int cpu;
10669796e1aeSPaul E. McKenney 
10679796e1aeSPaul E. McKenney 	for_each_possible_cpu(cpu)
10689796e1aeSPaul E. McKenney 		rcu_tasks_trace_pertask(idle_task(cpu), hop);
10699796e1aeSPaul E. McKenney 
107081b4a7bcSPaul E. McKenney 	// Re-enable CPU hotplug now that the tasklist scan has completed.
107181b4a7bcSPaul E. McKenney 	cpus_read_unlock();
107281b4a7bcSPaul E. McKenney 
1073d5f177d3SPaul E. McKenney 	// Wait for late-stage exiting tasks to finish exiting.
1074d5f177d3SPaul E. McKenney 	// These might have passed the call to exit_tasks_rcu_finish().
1075d5f177d3SPaul E. McKenney 	synchronize_rcu();
1076d5f177d3SPaul E. McKenney 	// Any tasks that exit after this point will set ->trc_reader_checked.
1077d5f177d3SPaul E. McKenney }
1078d5f177d3SPaul E. McKenney 
10794593e772SPaul E. McKenney /* Show the state of a task stalling the current RCU tasks trace GP. */
10804593e772SPaul E. McKenney static void show_stalled_task_trace(struct task_struct *t, bool *firstreport)
10814593e772SPaul E. McKenney {
10824593e772SPaul E. McKenney 	int cpu;
10834593e772SPaul E. McKenney 
10844593e772SPaul E. McKenney 	if (*firstreport) {
10854593e772SPaul E. McKenney 		pr_err("INFO: rcu_tasks_trace detected stalls on tasks:\n");
10864593e772SPaul E. McKenney 		*firstreport = false;
10874593e772SPaul E. McKenney 	}
10884593e772SPaul E. McKenney 	// FIXME: This should attempt to use try_invoke_on_nonrunning_task().
10894593e772SPaul E. McKenney 	cpu = task_cpu(t);
10904593e772SPaul E. McKenney 	pr_alert("P%d: %c%c%c nesting: %d%c cpu: %d\n",
10914593e772SPaul E. McKenney 		 t->pid,
10924593e772SPaul E. McKenney 		 ".I"[READ_ONCE(t->trc_ipi_to_cpu) > 0],
10934593e772SPaul E. McKenney 		 ".i"[is_idle_task(t)],
10944593e772SPaul E. McKenney 		 ".N"[cpu > 0 && tick_nohz_full_cpu(cpu)],
10954593e772SPaul E. McKenney 		 t->trc_reader_nesting,
1096276c4104SPaul E. McKenney 		 " N"[!!t->trc_reader_special.b.need_qs],
10974593e772SPaul E. McKenney 		 cpu);
10984593e772SPaul E. McKenney 	sched_show_task(t);
10994593e772SPaul E. McKenney }
11004593e772SPaul E. McKenney 
11014593e772SPaul E. McKenney /* List stalled IPIs for RCU tasks trace. */
11024593e772SPaul E. McKenney static void show_stalled_ipi_trace(void)
11034593e772SPaul E. McKenney {
11044593e772SPaul E. McKenney 	int cpu;
11054593e772SPaul E. McKenney 
11064593e772SPaul E. McKenney 	for_each_possible_cpu(cpu)
11074593e772SPaul E. McKenney 		if (per_cpu(trc_ipi_to_cpu, cpu))
11084593e772SPaul E. McKenney 			pr_alert("\tIPI outstanding to CPU %d\n", cpu);
11094593e772SPaul E. McKenney }
11104593e772SPaul E. McKenney 
1111d5f177d3SPaul E. McKenney /* Do one scan of the holdout list. */
1112d5f177d3SPaul E. McKenney static void check_all_holdout_tasks_trace(struct list_head *hop,
11134593e772SPaul E. McKenney 					  bool needreport, bool *firstreport)
1114d5f177d3SPaul E. McKenney {
1115d5f177d3SPaul E. McKenney 	struct task_struct *g, *t;
1116d5f177d3SPaul E. McKenney 
111781b4a7bcSPaul E. McKenney 	// Disable CPU hotplug across the holdout list scan.
111881b4a7bcSPaul E. McKenney 	cpus_read_lock();
111981b4a7bcSPaul E. McKenney 
1120d5f177d3SPaul E. McKenney 	list_for_each_entry_safe(t, g, hop, trc_holdout_list) {
1121d5f177d3SPaul E. McKenney 		// If safe and needed, try to check the current task.
1122d5f177d3SPaul E. McKenney 		if (READ_ONCE(t->trc_ipi_to_cpu) == -1 &&
1123d5f177d3SPaul E. McKenney 		    !READ_ONCE(t->trc_reader_checked))
1124d5f177d3SPaul E. McKenney 			trc_wait_for_one_reader(t, hop);
1125d5f177d3SPaul E. McKenney 
1126d5f177d3SPaul E. McKenney 		// If check succeeded, remove this task from the list.
1127d5f177d3SPaul E. McKenney 		if (READ_ONCE(t->trc_reader_checked))
1128d5f177d3SPaul E. McKenney 			trc_del_holdout(t);
11294593e772SPaul E. McKenney 		else if (needreport)
11304593e772SPaul E. McKenney 			show_stalled_task_trace(t, firstreport);
11314593e772SPaul E. McKenney 	}
113281b4a7bcSPaul E. McKenney 
113381b4a7bcSPaul E. McKenney 	// Re-enable CPU hotplug now that the holdout list scan has completed.
113481b4a7bcSPaul E. McKenney 	cpus_read_unlock();
113581b4a7bcSPaul E. McKenney 
11364593e772SPaul E. McKenney 	if (needreport) {
11374593e772SPaul E. McKenney 		if (firstreport)
11384593e772SPaul E. McKenney 			pr_err("INFO: rcu_tasks_trace detected stalls? (Late IPI?)\n");
11394593e772SPaul E. McKenney 		show_stalled_ipi_trace();
1140d5f177d3SPaul E. McKenney 	}
1141d5f177d3SPaul E. McKenney }
1142d5f177d3SPaul E. McKenney 
1143d5f177d3SPaul E. McKenney /* Wait for grace period to complete and provide ordering. */
1144af051ca4SPaul E. McKenney static void rcu_tasks_trace_postgp(struct rcu_tasks *rtp)
1145d5f177d3SPaul E. McKenney {
11464593e772SPaul E. McKenney 	bool firstreport;
11474593e772SPaul E. McKenney 	struct task_struct *g, *t;
11484593e772SPaul E. McKenney 	LIST_HEAD(holdouts);
11494593e772SPaul E. McKenney 	long ret;
11504593e772SPaul E. McKenney 
1151d5f177d3SPaul E. McKenney 	// Remove the safety count.
1152d5f177d3SPaul E. McKenney 	smp_mb__before_atomic();  // Order vs. earlier atomics
1153d5f177d3SPaul E. McKenney 	atomic_dec(&trc_n_readers_need_end);
1154d5f177d3SPaul E. McKenney 	smp_mb__after_atomic();  // Order vs. later atomics
1155d5f177d3SPaul E. McKenney 
1156d5f177d3SPaul E. McKenney 	// Wait for readers.
1157af051ca4SPaul E. McKenney 	set_tasks_gp_state(rtp, RTGS_WAIT_READERS);
11584593e772SPaul E. McKenney 	for (;;) {
11594593e772SPaul E. McKenney 		ret = wait_event_idle_exclusive_timeout(
11604593e772SPaul E. McKenney 				trc_wait,
11614593e772SPaul E. McKenney 				atomic_read(&trc_n_readers_need_end) == 0,
11624593e772SPaul E. McKenney 				READ_ONCE(rcu_task_stall_timeout));
11634593e772SPaul E. McKenney 		if (ret)
11644593e772SPaul E. McKenney 			break;  // Count reached zero.
1165af051ca4SPaul E. McKenney 		// Stall warning time, so make a list of the offenders.
1166f747c7e1SPaul E. McKenney 		rcu_read_lock();
11674593e772SPaul E. McKenney 		for_each_process_thread(g, t)
1168276c4104SPaul E. McKenney 			if (READ_ONCE(t->trc_reader_special.b.need_qs))
11694593e772SPaul E. McKenney 				trc_add_holdout(t, &holdouts);
1170f747c7e1SPaul E. McKenney 		rcu_read_unlock();
11714593e772SPaul E. McKenney 		firstreport = true;
1172592031ccSPaul E. McKenney 		list_for_each_entry_safe(t, g, &holdouts, trc_holdout_list) {
1173592031ccSPaul E. McKenney 			if (READ_ONCE(t->trc_reader_special.b.need_qs))
11744593e772SPaul E. McKenney 				show_stalled_task_trace(t, &firstreport);
1175592031ccSPaul E. McKenney 			trc_del_holdout(t); // Release task_struct reference.
11764593e772SPaul E. McKenney 		}
11774593e772SPaul E. McKenney 		if (firstreport)
11784593e772SPaul E. McKenney 			pr_err("INFO: rcu_tasks_trace detected stalls? (Counter/taskslist mismatch?)\n");
11794593e772SPaul E. McKenney 		show_stalled_ipi_trace();
11804593e772SPaul E. McKenney 		pr_err("\t%d holdouts\n", atomic_read(&trc_n_readers_need_end));
11814593e772SPaul E. McKenney 	}
1182d5f177d3SPaul E. McKenney 	smp_mb(); // Caller's code must be ordered after wakeup.
118343766c3eSPaul E. McKenney 		  // Pairs with pretty much every ordering primitive.
1184d5f177d3SPaul E. McKenney }
1185d5f177d3SPaul E. McKenney 
1186d5f177d3SPaul E. McKenney /* Report any needed quiescent state for this exiting task. */
118725246fc8SPaul E. McKenney static void exit_tasks_rcu_finish_trace(struct task_struct *t)
1188d5f177d3SPaul E. McKenney {
1189d5f177d3SPaul E. McKenney 	WRITE_ONCE(t->trc_reader_checked, true);
1190d5f177d3SPaul E. McKenney 	WARN_ON_ONCE(t->trc_reader_nesting);
1191d5f177d3SPaul E. McKenney 	WRITE_ONCE(t->trc_reader_nesting, 0);
1192276c4104SPaul E. McKenney 	if (WARN_ON_ONCE(READ_ONCE(t->trc_reader_special.b.need_qs)))
1193276c4104SPaul E. McKenney 		rcu_read_unlock_trace_special(t, 0);
1194d5f177d3SPaul E. McKenney }
1195d5f177d3SPaul E. McKenney 
1196d5f177d3SPaul E. McKenney /**
1197d5f177d3SPaul E. McKenney  * call_rcu_tasks_trace() - Queue a callback trace task-based grace period
1198d5f177d3SPaul E. McKenney  * @rhp: structure to be used for queueing the RCU updates.
1199d5f177d3SPaul E. McKenney  * @func: actual callback function to be invoked after the grace period
1200d5f177d3SPaul E. McKenney  *
1201d5f177d3SPaul E. McKenney  * The callback function will be invoked some time after a full grace
1202d5f177d3SPaul E. McKenney  * period elapses, in other words after all currently executing RCU
1203d5f177d3SPaul E. McKenney  * read-side critical sections have completed. call_rcu_tasks_trace()
1204d5f177d3SPaul E. McKenney  * assumes that the read-side critical sections end at context switch,
1205d5f177d3SPaul E. McKenney  * cond_resched_rcu_qs(), or transition to usermode execution.  As such,
1206d5f177d3SPaul E. McKenney  * there are no read-side primitives analogous to rcu_read_lock() and
1207d5f177d3SPaul E. McKenney  * rcu_read_unlock() because this primitive is intended to determine
1208d5f177d3SPaul E. McKenney  * that all tasks have passed through a safe state, not so much for
1209a616aec9SIngo Molnar  * data-structure synchronization.
1210d5f177d3SPaul E. McKenney  *
1211d5f177d3SPaul E. McKenney  * See the description of call_rcu() for more detailed information on
1212d5f177d3SPaul E. McKenney  * memory ordering guarantees.
1213d5f177d3SPaul E. McKenney  */
1214d5f177d3SPaul E. McKenney void call_rcu_tasks_trace(struct rcu_head *rhp, rcu_callback_t func)
1215d5f177d3SPaul E. McKenney {
1216d5f177d3SPaul E. McKenney 	call_rcu_tasks_generic(rhp, func, &rcu_tasks_trace);
1217d5f177d3SPaul E. McKenney }
1218d5f177d3SPaul E. McKenney EXPORT_SYMBOL_GPL(call_rcu_tasks_trace);
1219d5f177d3SPaul E. McKenney 
1220d5f177d3SPaul E. McKenney /**
1221d5f177d3SPaul E. McKenney  * synchronize_rcu_tasks_trace - wait for a trace rcu-tasks grace period
1222d5f177d3SPaul E. McKenney  *
1223d5f177d3SPaul E. McKenney  * Control will return to the caller some time after a trace rcu-tasks
1224c7dcf810SPaul E. McKenney  * grace period has elapsed, in other words after all currently executing
1225c7dcf810SPaul E. McKenney  * rcu-tasks read-side critical sections have elapsed.  These read-side
1226c7dcf810SPaul E. McKenney  * critical sections are delimited by calls to rcu_read_lock_trace()
1227c7dcf810SPaul E. McKenney  * and rcu_read_unlock_trace().
1228d5f177d3SPaul E. McKenney  *
1229d5f177d3SPaul E. McKenney  * This is a very specialized primitive, intended only for a few uses in
1230d5f177d3SPaul E. McKenney  * tracing and other situations requiring manipulation of function preambles
1231d5f177d3SPaul E. McKenney  * and profiling hooks.  The synchronize_rcu_tasks_trace() function is not
1232d5f177d3SPaul E. McKenney  * (yet) intended for heavy use from multiple CPUs.
1233d5f177d3SPaul E. McKenney  *
1234d5f177d3SPaul E. McKenney  * See the description of synchronize_rcu() for more detailed information
1235d5f177d3SPaul E. McKenney  * on memory ordering guarantees.
1236d5f177d3SPaul E. McKenney  */
1237d5f177d3SPaul E. McKenney void synchronize_rcu_tasks_trace(void)
1238d5f177d3SPaul E. McKenney {
1239d5f177d3SPaul E. McKenney 	RCU_LOCKDEP_WARN(lock_is_held(&rcu_trace_lock_map), "Illegal synchronize_rcu_tasks_trace() in RCU Tasks Trace read-side critical section");
1240d5f177d3SPaul E. McKenney 	synchronize_rcu_tasks_generic(&rcu_tasks_trace);
1241d5f177d3SPaul E. McKenney }
1242d5f177d3SPaul E. McKenney EXPORT_SYMBOL_GPL(synchronize_rcu_tasks_trace);
1243d5f177d3SPaul E. McKenney 
1244d5f177d3SPaul E. McKenney /**
1245d5f177d3SPaul E. McKenney  * rcu_barrier_tasks_trace - Wait for in-flight call_rcu_tasks_trace() callbacks.
1246d5f177d3SPaul E. McKenney  *
1247d5f177d3SPaul E. McKenney  * Although the current implementation is guaranteed to wait, it is not
1248d5f177d3SPaul E. McKenney  * obligated to, for example, if there are no pending callbacks.
1249d5f177d3SPaul E. McKenney  */
1250d5f177d3SPaul E. McKenney void rcu_barrier_tasks_trace(void)
1251d5f177d3SPaul E. McKenney {
1252d5f177d3SPaul E. McKenney 	/* There is only one callback queue, so this is easy.  ;-) */
1253d5f177d3SPaul E. McKenney 	synchronize_rcu_tasks_trace();
1254d5f177d3SPaul E. McKenney }
1255d5f177d3SPaul E. McKenney EXPORT_SYMBOL_GPL(rcu_barrier_tasks_trace);
1256d5f177d3SPaul E. McKenney 
1257d5f177d3SPaul E. McKenney static int __init rcu_spawn_tasks_trace_kthread(void)
1258d5f177d3SPaul E. McKenney {
12592393a613SPaul E. McKenney 	if (IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB)) {
12604fe192dfSPaul E. McKenney 		rcu_tasks_trace.gp_sleep = HZ / 10;
126175dc2da5SPaul E. McKenney 		rcu_tasks_trace.init_fract = HZ / 10;
12622393a613SPaul E. McKenney 	} else {
12634fe192dfSPaul E. McKenney 		rcu_tasks_trace.gp_sleep = HZ / 200;
12644fe192dfSPaul E. McKenney 		if (rcu_tasks_trace.gp_sleep <= 0)
12654fe192dfSPaul E. McKenney 			rcu_tasks_trace.gp_sleep = 1;
126675dc2da5SPaul E. McKenney 		rcu_tasks_trace.init_fract = HZ / 200;
12672393a613SPaul E. McKenney 		if (rcu_tasks_trace.init_fract <= 0)
12682393a613SPaul E. McKenney 			rcu_tasks_trace.init_fract = 1;
12692393a613SPaul E. McKenney 	}
1270d5f177d3SPaul E. McKenney 	rcu_tasks_trace.pregp_func = rcu_tasks_trace_pregp_step;
1271d5f177d3SPaul E. McKenney 	rcu_tasks_trace.pertask_func = rcu_tasks_trace_pertask;
1272d5f177d3SPaul E. McKenney 	rcu_tasks_trace.postscan_func = rcu_tasks_trace_postscan;
1273d5f177d3SPaul E. McKenney 	rcu_tasks_trace.holdouts_func = check_all_holdout_tasks_trace;
1274d5f177d3SPaul E. McKenney 	rcu_tasks_trace.postgp_func = rcu_tasks_trace_postgp;
1275d5f177d3SPaul E. McKenney 	rcu_spawn_tasks_kthread_generic(&rcu_tasks_trace);
1276d5f177d3SPaul E. McKenney 	return 0;
1277d5f177d3SPaul E. McKenney }
1278d5f177d3SPaul E. McKenney 
127927c0f144SPaul E. McKenney #if !defined(CONFIG_TINY_RCU)
128027c0f144SPaul E. McKenney void show_rcu_tasks_trace_gp_kthread(void)
1281e21408ceSPaul E. McKenney {
128240471509SPaul E. McKenney 	char buf[64];
1283e21408ceSPaul E. McKenney 
1284edf3775fSPaul E. McKenney 	sprintf(buf, "N%d h:%lu/%lu/%lu", atomic_read(&trc_n_readers_need_end),
1285edf3775fSPaul E. McKenney 		data_race(n_heavy_reader_ofl_updates),
128640471509SPaul E. McKenney 		data_race(n_heavy_reader_updates),
128740471509SPaul E. McKenney 		data_race(n_heavy_reader_attempts));
1288e21408ceSPaul E. McKenney 	show_rcu_tasks_generic_gp_kthread(&rcu_tasks_trace, buf);
1289e21408ceSPaul E. McKenney }
129027c0f144SPaul E. McKenney EXPORT_SYMBOL_GPL(show_rcu_tasks_trace_gp_kthread);
129127c0f144SPaul E. McKenney #endif // !defined(CONFIG_TINY_RCU)
1292e21408ceSPaul E. McKenney 
1293d5f177d3SPaul E. McKenney #else /* #ifdef CONFIG_TASKS_TRACE_RCU */
129425246fc8SPaul E. McKenney static void exit_tasks_rcu_finish_trace(struct task_struct *t) { }
1295d5f177d3SPaul E. McKenney #endif /* #else #ifdef CONFIG_TASKS_TRACE_RCU */
12968fd8ca38SPaul E. McKenney 
12978344496eSPaul E. McKenney #ifndef CONFIG_TINY_RCU
1298e21408ceSPaul E. McKenney void show_rcu_tasks_gp_kthreads(void)
1299e21408ceSPaul E. McKenney {
1300e21408ceSPaul E. McKenney 	show_rcu_tasks_classic_gp_kthread();
1301e21408ceSPaul E. McKenney 	show_rcu_tasks_rude_gp_kthread();
1302e21408ceSPaul E. McKenney 	show_rcu_tasks_trace_gp_kthread();
1303e21408ceSPaul E. McKenney }
13048344496eSPaul E. McKenney #endif /* #ifndef CONFIG_TINY_RCU */
1305e21408ceSPaul E. McKenney 
1306bfba7ed0SUladzislau Rezki (Sony) #ifdef CONFIG_PROVE_RCU
1307bfba7ed0SUladzislau Rezki (Sony) struct rcu_tasks_test_desc {
1308bfba7ed0SUladzislau Rezki (Sony) 	struct rcu_head rh;
1309bfba7ed0SUladzislau Rezki (Sony) 	const char *name;
1310bfba7ed0SUladzislau Rezki (Sony) 	bool notrun;
1311bfba7ed0SUladzislau Rezki (Sony) };
1312bfba7ed0SUladzislau Rezki (Sony) 
1313bfba7ed0SUladzislau Rezki (Sony) static struct rcu_tasks_test_desc tests[] = {
1314bfba7ed0SUladzislau Rezki (Sony) 	{
1315bfba7ed0SUladzislau Rezki (Sony) 		.name = "call_rcu_tasks()",
1316bfba7ed0SUladzislau Rezki (Sony) 		/* If not defined, the test is skipped. */
1317bfba7ed0SUladzislau Rezki (Sony) 		.notrun = !IS_ENABLED(CONFIG_TASKS_RCU),
1318bfba7ed0SUladzislau Rezki (Sony) 	},
1319bfba7ed0SUladzislau Rezki (Sony) 	{
1320bfba7ed0SUladzislau Rezki (Sony) 		.name = "call_rcu_tasks_rude()",
1321bfba7ed0SUladzislau Rezki (Sony) 		/* If not defined, the test is skipped. */
1322bfba7ed0SUladzislau Rezki (Sony) 		.notrun = !IS_ENABLED(CONFIG_TASKS_RUDE_RCU),
1323bfba7ed0SUladzislau Rezki (Sony) 	},
1324bfba7ed0SUladzislau Rezki (Sony) 	{
1325bfba7ed0SUladzislau Rezki (Sony) 		.name = "call_rcu_tasks_trace()",
1326bfba7ed0SUladzislau Rezki (Sony) 		/* If not defined, the test is skipped. */
1327bfba7ed0SUladzislau Rezki (Sony) 		.notrun = !IS_ENABLED(CONFIG_TASKS_TRACE_RCU)
1328bfba7ed0SUladzislau Rezki (Sony) 	}
1329bfba7ed0SUladzislau Rezki (Sony) };
1330bfba7ed0SUladzislau Rezki (Sony) 
1331bfba7ed0SUladzislau Rezki (Sony) static void test_rcu_tasks_callback(struct rcu_head *rhp)
1332bfba7ed0SUladzislau Rezki (Sony) {
1333bfba7ed0SUladzislau Rezki (Sony) 	struct rcu_tasks_test_desc *rttd =
1334bfba7ed0SUladzislau Rezki (Sony) 		container_of(rhp, struct rcu_tasks_test_desc, rh);
1335bfba7ed0SUladzislau Rezki (Sony) 
1336bfba7ed0SUladzislau Rezki (Sony) 	pr_info("Callback from %s invoked.\n", rttd->name);
1337bfba7ed0SUladzislau Rezki (Sony) 
1338bfba7ed0SUladzislau Rezki (Sony) 	rttd->notrun = true;
1339bfba7ed0SUladzislau Rezki (Sony) }
1340bfba7ed0SUladzislau Rezki (Sony) 
1341bfba7ed0SUladzislau Rezki (Sony) static void rcu_tasks_initiate_self_tests(void)
1342bfba7ed0SUladzislau Rezki (Sony) {
1343bfba7ed0SUladzislau Rezki (Sony) 	pr_info("Running RCU-tasks wait API self tests\n");
1344bfba7ed0SUladzislau Rezki (Sony) #ifdef CONFIG_TASKS_RCU
1345bfba7ed0SUladzislau Rezki (Sony) 	synchronize_rcu_tasks();
1346bfba7ed0SUladzislau Rezki (Sony) 	call_rcu_tasks(&tests[0].rh, test_rcu_tasks_callback);
1347bfba7ed0SUladzislau Rezki (Sony) #endif
1348bfba7ed0SUladzislau Rezki (Sony) 
1349bfba7ed0SUladzislau Rezki (Sony) #ifdef CONFIG_TASKS_RUDE_RCU
1350bfba7ed0SUladzislau Rezki (Sony) 	synchronize_rcu_tasks_rude();
1351bfba7ed0SUladzislau Rezki (Sony) 	call_rcu_tasks_rude(&tests[1].rh, test_rcu_tasks_callback);
1352bfba7ed0SUladzislau Rezki (Sony) #endif
1353bfba7ed0SUladzislau Rezki (Sony) 
1354bfba7ed0SUladzislau Rezki (Sony) #ifdef CONFIG_TASKS_TRACE_RCU
1355bfba7ed0SUladzislau Rezki (Sony) 	synchronize_rcu_tasks_trace();
1356bfba7ed0SUladzislau Rezki (Sony) 	call_rcu_tasks_trace(&tests[2].rh, test_rcu_tasks_callback);
1357bfba7ed0SUladzislau Rezki (Sony) #endif
1358bfba7ed0SUladzislau Rezki (Sony) }
1359bfba7ed0SUladzislau Rezki (Sony) 
1360bfba7ed0SUladzislau Rezki (Sony) static int rcu_tasks_verify_self_tests(void)
1361bfba7ed0SUladzislau Rezki (Sony) {
1362bfba7ed0SUladzislau Rezki (Sony) 	int ret = 0;
1363bfba7ed0SUladzislau Rezki (Sony) 	int i;
1364bfba7ed0SUladzislau Rezki (Sony) 
1365bfba7ed0SUladzislau Rezki (Sony) 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
1366bfba7ed0SUladzislau Rezki (Sony) 		if (!tests[i].notrun) {		// still hanging.
1367bfba7ed0SUladzislau Rezki (Sony) 			pr_err("%s has been failed.\n", tests[i].name);
1368bfba7ed0SUladzislau Rezki (Sony) 			ret = -1;
1369bfba7ed0SUladzislau Rezki (Sony) 		}
1370bfba7ed0SUladzislau Rezki (Sony) 	}
1371bfba7ed0SUladzislau Rezki (Sony) 
1372bfba7ed0SUladzislau Rezki (Sony) 	if (ret)
1373bfba7ed0SUladzislau Rezki (Sony) 		WARN_ON(1);
1374bfba7ed0SUladzislau Rezki (Sony) 
1375bfba7ed0SUladzislau Rezki (Sony) 	return ret;
1376bfba7ed0SUladzislau Rezki (Sony) }
1377bfba7ed0SUladzislau Rezki (Sony) late_initcall(rcu_tasks_verify_self_tests);
1378bfba7ed0SUladzislau Rezki (Sony) #else /* #ifdef CONFIG_PROVE_RCU */
1379bfba7ed0SUladzislau Rezki (Sony) static void rcu_tasks_initiate_self_tests(void) { }
1380bfba7ed0SUladzislau Rezki (Sony) #endif /* #else #ifdef CONFIG_PROVE_RCU */
1381bfba7ed0SUladzislau Rezki (Sony) 
13821b04fa99SUladzislau Rezki (Sony) void __init rcu_init_tasks_generic(void)
13831b04fa99SUladzislau Rezki (Sony) {
13841b04fa99SUladzislau Rezki (Sony) #ifdef CONFIG_TASKS_RCU
13851b04fa99SUladzislau Rezki (Sony) 	rcu_spawn_tasks_kthread();
13861b04fa99SUladzislau Rezki (Sony) #endif
13871b04fa99SUladzislau Rezki (Sony) 
13881b04fa99SUladzislau Rezki (Sony) #ifdef CONFIG_TASKS_RUDE_RCU
13891b04fa99SUladzislau Rezki (Sony) 	rcu_spawn_tasks_rude_kthread();
13901b04fa99SUladzislau Rezki (Sony) #endif
13911b04fa99SUladzislau Rezki (Sony) 
13921b04fa99SUladzislau Rezki (Sony) #ifdef CONFIG_TASKS_TRACE_RCU
13931b04fa99SUladzislau Rezki (Sony) 	rcu_spawn_tasks_trace_kthread();
13941b04fa99SUladzislau Rezki (Sony) #endif
1395bfba7ed0SUladzislau Rezki (Sony) 
1396bfba7ed0SUladzislau Rezki (Sony) 	// Run the self-tests.
1397bfba7ed0SUladzislau Rezki (Sony) 	rcu_tasks_initiate_self_tests();
13981b04fa99SUladzislau Rezki (Sony) }
13991b04fa99SUladzislau Rezki (Sony) 
14008fd8ca38SPaul E. McKenney #else /* #ifdef CONFIG_TASKS_RCU_GENERIC */
14018fd8ca38SPaul E. McKenney static inline void rcu_tasks_bootup_oddness(void) {}
14028fd8ca38SPaul E. McKenney #endif /* #else #ifdef CONFIG_TASKS_RCU_GENERIC */
1403