xref: /linux-6.15/include/linux/srcu.h (revision f8b8df19)
18c366db0SPaul E. McKenney /* SPDX-License-Identifier: GPL-2.0+ */
2621934eeSPaul E. McKenney /*
3621934eeSPaul E. McKenney  * Sleepable Read-Copy Update mechanism for mutual exclusion
4621934eeSPaul E. McKenney  *
5621934eeSPaul E. McKenney  * Copyright (C) IBM Corporation, 2006
64e87b2d7SLai Jiangshan  * Copyright (C) Fujitsu, 2012
7621934eeSPaul E. McKenney  *
88c366db0SPaul E. McKenney  * Author: Paul McKenney <[email protected]>
94e87b2d7SLai Jiangshan  *	   Lai Jiangshan <[email protected]>
10621934eeSPaul E. McKenney  *
11621934eeSPaul E. McKenney  * For detailed explanation of Read-Copy Update mechanism see -
12621934eeSPaul E. McKenney  *		Documentation/RCU/ *.txt
13621934eeSPaul E. McKenney  *
14621934eeSPaul E. McKenney  */
15621934eeSPaul E. McKenney 
16eabc0694SAlan Stern #ifndef _LINUX_SRCU_H
17eabc0694SAlan Stern #define _LINUX_SRCU_H
18eabc0694SAlan Stern 
19d14aada8SPaul E. McKenney #include <linux/mutex.h>
20ff195cb6SPaul E. McKenney #include <linux/rcupdate.h>
21931ea9d1SLai Jiangshan #include <linux/workqueue.h>
228660b7d8SPaul E. McKenney #include <linux/rcu_segcblist.h>
23d14aada8SPaul E. McKenney 
24d8be8173SPaul E. McKenney struct srcu_struct;
25c2a8ec07SPaul E. McKenney 
26632ee200SPaul E. McKenney #ifdef CONFIG_DEBUG_LOCK_ALLOC
27632ee200SPaul E. McKenney 
28aacb5d91SPaul E. McKenney int __init_srcu_struct(struct srcu_struct *ssp, const char *name,
29632ee200SPaul E. McKenney 		       struct lock_class_key *key);
30632ee200SPaul E. McKenney 
31aacb5d91SPaul E. McKenney #define init_srcu_struct(ssp) \
32632ee200SPaul E. McKenney ({ \
33632ee200SPaul E. McKenney 	static struct lock_class_key __srcu_key; \
34632ee200SPaul E. McKenney 	\
35aacb5d91SPaul E. McKenney 	__init_srcu_struct((ssp), #ssp, &__srcu_key); \
36632ee200SPaul E. McKenney })
37632ee200SPaul E. McKenney 
3855c6659aSLai Jiangshan #define __SRCU_DEP_MAP_INIT(srcu_name)	.dep_map = { .name = #srcu_name },
39632ee200SPaul E. McKenney #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
40632ee200SPaul E. McKenney 
41aacb5d91SPaul E. McKenney int init_srcu_struct(struct srcu_struct *ssp);
42632ee200SPaul E. McKenney 
4355c6659aSLai Jiangshan #define __SRCU_DEP_MAP_INIT(srcu_name)
44632ee200SPaul E. McKenney #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
45632ee200SPaul E. McKenney 
460fef924eSPaul E. McKenney /* Values for SRCU Tree srcu_data ->srcu_reader_flavor, but also used by rcutorture. */
470fef924eSPaul E. McKenney #define SRCU_READ_FLAVOR_NORMAL	0x1		// srcu_read_lock().
480fef924eSPaul E. McKenney #define SRCU_READ_FLAVOR_NMI	0x2		// srcu_read_lock_nmisafe().
490fef924eSPaul E. McKenney #define SRCU_READ_FLAVOR_LITE	0x4		// srcu_read_lock_lite().
50c4020620SPaul E. McKenney #define SRCU_READ_FLAVOR_FAST	0x8		// srcu_read_lock_fast().
51b459874fSPaul E. McKenney #define SRCU_READ_FLAVOR_ALL   (SRCU_READ_FLAVOR_NORMAL | SRCU_READ_FLAVOR_NMI | \
52c4020620SPaul E. McKenney 				SRCU_READ_FLAVOR_LITE | SRCU_READ_FLAVOR_FAST) // All of the above.
53c4020620SPaul E. McKenney #define SRCU_READ_FLAVOR_SLOWGP	(SRCU_READ_FLAVOR_LITE | SRCU_READ_FLAVOR_FAST)
544d86b1e7SPaul E. McKenney 						// Flavors requiring synchronize_rcu()
554d86b1e7SPaul E. McKenney 						// instead of smp_mb().
5644397115SPaul E. McKenney void __srcu_read_unlock(struct srcu_struct *ssp, int idx) __releases(ssp);
570fef924eSPaul E. McKenney 
58d8be8173SPaul E. McKenney #ifdef CONFIG_TINY_SRCU
59d8be8173SPaul E. McKenney #include <linux/srcutiny.h>
60d8be8173SPaul E. McKenney #elif defined(CONFIG_TREE_SRCU)
61d8be8173SPaul E. McKenney #include <linux/srcutree.h>
6207f6e64bSPaul E. McKenney #else
630cd7e350SPaul E. McKenney #error "Unknown SRCU implementation specified to kernel configuration"
64d8be8173SPaul E. McKenney #endif
6555c6659aSLai Jiangshan 
66aacb5d91SPaul E. McKenney void call_srcu(struct srcu_struct *ssp, struct rcu_head *head,
67931ea9d1SLai Jiangshan 		void (*func)(struct rcu_head *head));
68f5ad3991SPaul E. McKenney void cleanup_srcu_struct(struct srcu_struct *ssp);
69aacb5d91SPaul E. McKenney void synchronize_srcu(struct srcu_struct *ssp);
70e206f33eSPaul E. McKenney 
71e206f33eSPaul E. McKenney #define SRCU_GET_STATE_COMPLETED 0x1
72e206f33eSPaul E. McKenney 
73e206f33eSPaul E. McKenney /**
74e206f33eSPaul E. McKenney  * get_completed_synchronize_srcu - Return a pre-completed polled state cookie
75e206f33eSPaul E. McKenney  *
76e206f33eSPaul E. McKenney  * Returns a value that poll_state_synchronize_srcu() will always treat
77e206f33eSPaul E. McKenney  * as a cookie whose grace period has already completed.
78e206f33eSPaul E. McKenney  */
get_completed_synchronize_srcu(void)79e206f33eSPaul E. McKenney static inline unsigned long get_completed_synchronize_srcu(void)
80e206f33eSPaul E. McKenney {
81e206f33eSPaul E. McKenney 	return SRCU_GET_STATE_COMPLETED;
82e206f33eSPaul E. McKenney }
83e206f33eSPaul E. McKenney 
848b5bd67cSPaul E. McKenney unsigned long get_state_synchronize_srcu(struct srcu_struct *ssp);
858b5bd67cSPaul E. McKenney unsigned long start_poll_synchronize_srcu(struct srcu_struct *ssp);
868b5bd67cSPaul E. McKenney bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie);
87eabc0694SAlan Stern 
88395e73bdSPaul E. McKenney // Maximum number of unsigned long values corresponding to
89395e73bdSPaul E. McKenney // not-yet-completed SRCU grace periods.
90395e73bdSPaul E. McKenney #define NUM_ACTIVE_SRCU_POLL_OLDSTATE 2
91395e73bdSPaul E. McKenney 
92e206f33eSPaul E. McKenney /**
93e206f33eSPaul E. McKenney  * same_state_synchronize_srcu - Are two old-state values identical?
94e206f33eSPaul E. McKenney  * @oldstate1: First old-state value.
95e206f33eSPaul E. McKenney  * @oldstate2: Second old-state value.
96e206f33eSPaul E. McKenney  *
97e206f33eSPaul E. McKenney  * The two old-state values must have been obtained from either
98e206f33eSPaul E. McKenney  * get_state_synchronize_srcu(), start_poll_synchronize_srcu(), or
99e206f33eSPaul E. McKenney  * get_completed_synchronize_srcu().  Returns @true if the two values are
100e206f33eSPaul E. McKenney  * identical and @false otherwise.  This allows structures whose lifetimes
101e206f33eSPaul E. McKenney  * are tracked by old-state values to push these values to a list header,
102e206f33eSPaul E. McKenney  * allowing those structures to be slightly smaller.
103e206f33eSPaul E. McKenney  */
same_state_synchronize_srcu(unsigned long oldstate1,unsigned long oldstate2)104e206f33eSPaul E. McKenney static inline bool same_state_synchronize_srcu(unsigned long oldstate1, unsigned long oldstate2)
105e206f33eSPaul E. McKenney {
106e206f33eSPaul E. McKenney 	return oldstate1 == oldstate2;
107e206f33eSPaul E. McKenney }
108e206f33eSPaul E. McKenney 
1092e83b879SPaul E. McKenney #ifdef CONFIG_NEED_SRCU_NMI_SAFE
110e29a4915SFrederic Weisbecker int __srcu_read_lock_nmisafe(struct srcu_struct *ssp) __acquires(ssp);
111e29a4915SFrederic Weisbecker void __srcu_read_unlock_nmisafe(struct srcu_struct *ssp, int idx) __releases(ssp);
1122e83b879SPaul E. McKenney #else
__srcu_read_lock_nmisafe(struct srcu_struct * ssp)113e29a4915SFrederic Weisbecker static inline int __srcu_read_lock_nmisafe(struct srcu_struct *ssp)
1142e83b879SPaul E. McKenney {
1152e83b879SPaul E. McKenney 	return __srcu_read_lock(ssp);
1162e83b879SPaul E. McKenney }
__srcu_read_unlock_nmisafe(struct srcu_struct * ssp,int idx)117e29a4915SFrederic Weisbecker static inline void __srcu_read_unlock_nmisafe(struct srcu_struct *ssp, int idx)
1182e83b879SPaul E. McKenney {
1192e83b879SPaul E. McKenney 	__srcu_read_unlock(ssp, idx);
1202e83b879SPaul E. McKenney }
1212e83b879SPaul E. McKenney #endif /* CONFIG_NEED_SRCU_NMI_SAFE */
1222e83b879SPaul E. McKenney 
1238e9c01c7SFrederic Weisbecker void srcu_init(void);
1248e9c01c7SFrederic Weisbecker 
125632ee200SPaul E. McKenney #ifdef CONFIG_DEBUG_LOCK_ALLOC
126632ee200SPaul E. McKenney 
127632ee200SPaul E. McKenney /**
128632ee200SPaul E. McKenney  * srcu_read_lock_held - might we be in SRCU read-side critical section?
129aacb5d91SPaul E. McKenney  * @ssp: The srcu_struct structure to check
130632ee200SPaul E. McKenney  *
131d20200b5SPaul E. McKenney  * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an SRCU
132d20200b5SPaul E. McKenney  * read-side critical section.  In absence of CONFIG_DEBUG_LOCK_ALLOC,
133632ee200SPaul E. McKenney  * this assumes we are in an SRCU read-side critical section unless it can
134632ee200SPaul E. McKenney  * prove otherwise.
135ff195cb6SPaul E. McKenney  *
136867f236bSPaul E. McKenney  * Checks debug_lockdep_rcu_enabled() to prevent false positives during boot
137867f236bSPaul E. McKenney  * and while lockdep is disabled.
138867f236bSPaul E. McKenney  *
139511a0868SLai Jiangshan  * Note that SRCU is based on its own statemachine and it doesn't
140511a0868SLai Jiangshan  * relies on normal RCU, it can be called from the CPU which
141511a0868SLai Jiangshan  * is in the idle loop from an RCU point of view or offline.
142632ee200SPaul E. McKenney  */
srcu_read_lock_held(const struct srcu_struct * ssp)143aacb5d91SPaul E. McKenney static inline int srcu_read_lock_held(const struct srcu_struct *ssp)
144632ee200SPaul E. McKenney {
145867f236bSPaul E. McKenney 	if (!debug_lockdep_rcu_enabled())
146632ee200SPaul E. McKenney 		return 1;
147aacb5d91SPaul E. McKenney 	return lock_is_held(&ssp->dep_map);
148632ee200SPaul E. McKenney }
149632ee200SPaul E. McKenney 
150f0f44752SBoqun Feng /*
151f0f44752SBoqun Feng  * Annotations provide deadlock detection for SRCU.
152f0f44752SBoqun Feng  *
153f0f44752SBoqun Feng  * Similar to other lockdep annotations, except there is an additional
154f0f44752SBoqun Feng  * srcu_lock_sync(), which is basically an empty *write*-side critical section,
155f0f44752SBoqun Feng  * see lock_sync() for more information.
156f0f44752SBoqun Feng  */
157f0f44752SBoqun Feng 
158f0f44752SBoqun Feng /* Annotates a srcu_read_lock() */
srcu_lock_acquire(struct lockdep_map * map)159f0f44752SBoqun Feng static inline void srcu_lock_acquire(struct lockdep_map *map)
160f0f44752SBoqun Feng {
161f0f44752SBoqun Feng 	lock_map_acquire_read(map);
162f0f44752SBoqun Feng }
163f0f44752SBoqun Feng 
164f0f44752SBoqun Feng /* Annotates a srcu_read_lock() */
srcu_lock_release(struct lockdep_map * map)165f0f44752SBoqun Feng static inline void srcu_lock_release(struct lockdep_map *map)
166f0f44752SBoqun Feng {
167f0f44752SBoqun Feng 	lock_map_release(map);
168f0f44752SBoqun Feng }
169f0f44752SBoqun Feng 
170f0f44752SBoqun Feng /* Annotates a synchronize_srcu() */
srcu_lock_sync(struct lockdep_map * map)171f0f44752SBoqun Feng static inline void srcu_lock_sync(struct lockdep_map *map)
172f0f44752SBoqun Feng {
173f0f44752SBoqun Feng 	lock_map_sync(map);
174f0f44752SBoqun Feng }
175f0f44752SBoqun Feng 
176632ee200SPaul E. McKenney #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
177632ee200SPaul E. McKenney 
srcu_read_lock_held(const struct srcu_struct * ssp)178aacb5d91SPaul E. McKenney static inline int srcu_read_lock_held(const struct srcu_struct *ssp)
179632ee200SPaul E. McKenney {
180632ee200SPaul E. McKenney 	return 1;
181632ee200SPaul E. McKenney }
182632ee200SPaul E. McKenney 
183f0f44752SBoqun Feng #define srcu_lock_acquire(m) do { } while (0)
184f0f44752SBoqun Feng #define srcu_lock_release(m) do { } while (0)
185f0f44752SBoqun Feng #define srcu_lock_sync(m) do { } while (0)
186f0f44752SBoqun Feng 
187632ee200SPaul E. McKenney #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
188632ee200SPaul E. McKenney 
189e29a4915SFrederic Weisbecker 
190632ee200SPaul E. McKenney /**
191ca5ecddfSPaul E. McKenney  * srcu_dereference_check - fetch SRCU-protected pointer for later dereferencing
192ca5ecddfSPaul E. McKenney  * @p: the pointer to fetch and protect for later dereferencing
193aacb5d91SPaul E. McKenney  * @ssp: pointer to the srcu_struct, which is used to check that we
194ca5ecddfSPaul E. McKenney  *	really are in an SRCU read-side critical section.
195ca5ecddfSPaul E. McKenney  * @c: condition to check for update-side use
196c26d34a5SPaul E. McKenney  *
197ca5ecddfSPaul E. McKenney  * If PROVE_RCU is enabled, invoking this outside of an RCU read-side
198ca5ecddfSPaul E. McKenney  * critical section will result in an RCU-lockdep splat, unless @c evaluates
199ca5ecddfSPaul E. McKenney  * to 1.  The @c argument will normally be a logical expression containing
200ca5ecddfSPaul E. McKenney  * lockdep_is_held() calls.
201c26d34a5SPaul E. McKenney  */
202aacb5d91SPaul E. McKenney #define srcu_dereference_check(p, ssp, c) \
20324ba5301SChun-Hung Tseng 	__rcu_dereference_check((p), __UNIQUE_ID(rcu), \
20424ba5301SChun-Hung Tseng 				(c) || srcu_read_lock_held(ssp), __rcu)
205ca5ecddfSPaul E. McKenney 
206ca5ecddfSPaul E. McKenney /**
207ca5ecddfSPaul E. McKenney  * srcu_dereference - fetch SRCU-protected pointer for later dereferencing
208ca5ecddfSPaul E. McKenney  * @p: the pointer to fetch and protect for later dereferencing
209aacb5d91SPaul E. McKenney  * @ssp: pointer to the srcu_struct, which is used to check that we
210ca5ecddfSPaul E. McKenney  *	really are in an SRCU read-side critical section.
211ca5ecddfSPaul E. McKenney  *
212ca5ecddfSPaul E. McKenney  * Makes rcu_dereference_check() do the dirty work.  If PROVE_RCU
213ca5ecddfSPaul E. McKenney  * is enabled, invoking this outside of an RCU read-side critical
214ca5ecddfSPaul E. McKenney  * section will result in an RCU-lockdep splat.
215ca5ecddfSPaul E. McKenney  */
216aacb5d91SPaul E. McKenney #define srcu_dereference(p, ssp) srcu_dereference_check((p), (ssp), 0)
217c26d34a5SPaul E. McKenney 
218c26d34a5SPaul E. McKenney /**
2190b764a6eSJoel Fernandes (Google)  * srcu_dereference_notrace - no tracing and no lockdep calls from here
220f3e763c3SRandy Dunlap  * @p: the pointer to fetch and protect for later dereferencing
221aacb5d91SPaul E. McKenney  * @ssp: pointer to the srcu_struct, which is used to check that we
222f3e763c3SRandy Dunlap  *	really are in an SRCU read-side critical section.
2230b764a6eSJoel Fernandes (Google)  */
224aacb5d91SPaul E. McKenney #define srcu_dereference_notrace(p, ssp) srcu_dereference_check((p), (ssp), 1)
2250b764a6eSJoel Fernandes (Google) 
2260b764a6eSJoel Fernandes (Google) /**
227632ee200SPaul E. McKenney  * srcu_read_lock - register a new reader for an SRCU-protected structure.
228aacb5d91SPaul E. McKenney  * @ssp: srcu_struct in which to register the new reader.
229632ee200SPaul E. McKenney  *
230632ee200SPaul E. McKenney  * Enter an SRCU read-side critical section.  Note that SRCU read-side
23173d4da4dSPaul E. McKenney  * critical sections may be nested.  However, it is illegal to
23273d4da4dSPaul E. McKenney  * call anything that waits on an SRCU grace period for the same
23373d4da4dSPaul E. McKenney  * srcu_struct, whether directly or indirectly.  Please note that
23473d4da4dSPaul E. McKenney  * one way to indirectly wait on an SRCU grace period is to acquire
23573d4da4dSPaul E. McKenney  * a mutex that is held elsewhere while calling synchronize_srcu() or
23673d4da4dSPaul E. McKenney  * synchronize_srcu_expedited().
2373842a083SPaul E. McKenney  *
238d465492aSPaul E. McKenney  * The return value from srcu_read_lock() is guaranteed to be
239d465492aSPaul E. McKenney  * non-negative.  This value must be passed unaltered to the matching
240d465492aSPaul E. McKenney  * srcu_read_unlock().  Note that srcu_read_lock() and the matching
241d465492aSPaul E. McKenney  * srcu_read_unlock() must occur in the same context, for example, it is
242d465492aSPaul E. McKenney  * illegal to invoke srcu_read_unlock() in an irq handler if the matching
243d465492aSPaul E. McKenney  * srcu_read_lock() was invoked in process context.  Or, for that matter to
244d465492aSPaul E. McKenney  * invoke srcu_read_unlock() from one task and the matching srcu_read_lock()
245d465492aSPaul E. McKenney  * from another.
246632ee200SPaul E. McKenney  */
srcu_read_lock(struct srcu_struct * ssp)247aacb5d91SPaul E. McKenney static inline int srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp)
248632ee200SPaul E. McKenney {
24949f5903bSPaul E. McKenney 	int retval;
250632ee200SPaul E. McKenney 
25105829be2SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
252aacb5d91SPaul E. McKenney 	retval = __srcu_read_lock(ssp);
2531da82598SPaul E. McKenney 	srcu_lock_acquire(&ssp->dep_map);
254632ee200SPaul E. McKenney 	return retval;
255632ee200SPaul E. McKenney }
256632ee200SPaul E. McKenney 
2572e83b879SPaul E. McKenney /**
258c4020620SPaul E. McKenney  * srcu_read_lock_fast - register a new reader for an SRCU-protected structure.
259c4020620SPaul E. McKenney  * @ssp: srcu_struct in which to register the new reader.
260c4020620SPaul E. McKenney  *
261c4020620SPaul E. McKenney  * Enter an SRCU read-side critical section, but for a light-weight
262c4020620SPaul E. McKenney  * smp_mb()-free reader.  See srcu_read_lock() for more information.
263c4020620SPaul E. McKenney  *
264c4020620SPaul E. McKenney  * If srcu_read_lock_fast() is ever used on an srcu_struct structure,
265c4020620SPaul E. McKenney  * then none of the other flavors may be used, whether before, during,
266c4020620SPaul E. McKenney  * or after.  Note that grace-period auto-expediting is disabled for _fast
267c4020620SPaul E. McKenney  * srcu_struct structures because auto-expedited grace periods invoke
268c4020620SPaul E. McKenney  * synchronize_rcu_expedited(), IPIs and all.
269c4020620SPaul E. McKenney  *
270c4020620SPaul E. McKenney  * Note that srcu_read_lock_fast() can be invoked only from those contexts
271c4020620SPaul E. McKenney  * where RCU is watching, that is, from contexts where it would be legal
272c4020620SPaul E. McKenney  * to invoke rcu_read_lock().  Otherwise, lockdep will complain.
273c4020620SPaul E. McKenney  */
srcu_read_lock_fast(struct srcu_struct * ssp)274c4020620SPaul E. McKenney static inline struct srcu_ctr __percpu *srcu_read_lock_fast(struct srcu_struct *ssp) __acquires(ssp)
275c4020620SPaul E. McKenney {
276c4020620SPaul E. McKenney 	struct srcu_ctr __percpu *retval;
277c4020620SPaul E. McKenney 
278c4020620SPaul E. McKenney 	srcu_check_read_flavor_force(ssp, SRCU_READ_FLAVOR_FAST);
279c4020620SPaul E. McKenney 	retval = __srcu_read_lock_fast(ssp);
280c4020620SPaul E. McKenney 	rcu_try_lock_acquire(&ssp->dep_map);
281c4020620SPaul E. McKenney 	return retval;
282c4020620SPaul E. McKenney }
283c4020620SPaul E. McKenney 
284c4020620SPaul E. McKenney /**
285*f8b8df19SPaul E. McKenney  * srcu_down_read_fast - register a new reader for an SRCU-protected structure.
286*f8b8df19SPaul E. McKenney  * @ssp: srcu_struct in which to register the new reader.
287*f8b8df19SPaul E. McKenney  *
288*f8b8df19SPaul E. McKenney  * Enter a semaphore-like SRCU read-side critical section, but for
289*f8b8df19SPaul E. McKenney  * a light-weight smp_mb()-free reader.  See srcu_read_lock_fast() and
290*f8b8df19SPaul E. McKenney  * srcu_down_read() for more information.
291*f8b8df19SPaul E. McKenney  *
292*f8b8df19SPaul E. McKenney  * The same srcu_struct may be used concurrently by srcu_down_read_fast()
293*f8b8df19SPaul E. McKenney  * and srcu_read_lock_fast().
294*f8b8df19SPaul E. McKenney  */
srcu_down_read_fast(struct srcu_struct * ssp)295*f8b8df19SPaul E. McKenney static inline struct srcu_ctr __percpu *srcu_down_read_fast(struct srcu_struct *ssp) __acquires(ssp)
296*f8b8df19SPaul E. McKenney {
297*f8b8df19SPaul E. McKenney 	WARN_ON_ONCE(IS_ENABLED(CONFIG_PROVE_RCU) && in_nmi());
298*f8b8df19SPaul E. McKenney 	srcu_check_read_flavor_force(ssp, SRCU_READ_FLAVOR_FAST);
299*f8b8df19SPaul E. McKenney 	return __srcu_read_lock_fast(ssp);
300*f8b8df19SPaul E. McKenney }
301*f8b8df19SPaul E. McKenney 
302*f8b8df19SPaul E. McKenney /**
3036364dd81SPaul E. McKenney  * srcu_read_lock_lite - register a new reader for an SRCU-protected structure.
3046364dd81SPaul E. McKenney  * @ssp: srcu_struct in which to register the new reader.
3056364dd81SPaul E. McKenney  *
3066364dd81SPaul E. McKenney  * Enter an SRCU read-side critical section, but for a light-weight
3076364dd81SPaul E. McKenney  * smp_mb()-free reader.  See srcu_read_lock() for more information.
3086364dd81SPaul E. McKenney  *
3096364dd81SPaul E. McKenney  * If srcu_read_lock_lite() is ever used on an srcu_struct structure,
3106364dd81SPaul E. McKenney  * then none of the other flavors may be used, whether before, during,
3116364dd81SPaul E. McKenney  * or after.  Note that grace-period auto-expediting is disabled for _lite
3126364dd81SPaul E. McKenney  * srcu_struct structures because auto-expedited grace periods invoke
3136364dd81SPaul E. McKenney  * synchronize_rcu_expedited(), IPIs and all.
3146364dd81SPaul E. McKenney  *
3156364dd81SPaul E. McKenney  * Note that srcu_read_lock_lite() can be invoked only from those contexts
316768b1f87SPaul E. McKenney  * where RCU is watching, that is, from contexts where it would be legal
317768b1f87SPaul E. McKenney  * to invoke rcu_read_lock().  Otherwise, lockdep will complain.
3186364dd81SPaul E. McKenney  */
srcu_read_lock_lite(struct srcu_struct * ssp)3196364dd81SPaul E. McKenney static inline int srcu_read_lock_lite(struct srcu_struct *ssp) __acquires(ssp)
3206364dd81SPaul E. McKenney {
3216364dd81SPaul E. McKenney 	int retval;
3226364dd81SPaul E. McKenney 
323780818a6SPaul E. McKenney 	srcu_check_read_flavor_force(ssp, SRCU_READ_FLAVOR_LITE);
3246364dd81SPaul E. McKenney 	retval = __srcu_read_lock_lite(ssp);
3256364dd81SPaul E. McKenney 	rcu_try_lock_acquire(&ssp->dep_map);
3266364dd81SPaul E. McKenney 	return retval;
3276364dd81SPaul E. McKenney }
3286364dd81SPaul E. McKenney 
3296364dd81SPaul E. McKenney /**
3302e83b879SPaul E. McKenney  * srcu_read_lock_nmisafe - register a new reader for an SRCU-protected structure.
3312e83b879SPaul E. McKenney  * @ssp: srcu_struct in which to register the new reader.
3322e83b879SPaul E. McKenney  *
3332e83b879SPaul E. McKenney  * Enter an SRCU read-side critical section, but in an NMI-safe manner.
3342e83b879SPaul E. McKenney  * See srcu_read_lock() for more information.
335c071b8e5SPaul E. McKenney  *
336c071b8e5SPaul E. McKenney  * If srcu_read_lock_nmisafe() is ever used on an srcu_struct structure,
337c071b8e5SPaul E. McKenney  * then none of the other flavors may be used, whether before, during,
338c071b8e5SPaul E. McKenney  * or after.
3392e83b879SPaul E. McKenney  */
srcu_read_lock_nmisafe(struct srcu_struct * ssp)3402e83b879SPaul E. McKenney static inline int srcu_read_lock_nmisafe(struct srcu_struct *ssp) __acquires(ssp)
3412e83b879SPaul E. McKenney {
3422e83b879SPaul E. McKenney 	int retval;
3432e83b879SPaul E. McKenney 
34405829be2SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NMI);
345e29a4915SFrederic Weisbecker 	retval = __srcu_read_lock_nmisafe(ssp);
3463c6b0c1cSSebastian Andrzej Siewior 	rcu_try_lock_acquire(&ssp->dep_map);
3472e83b879SPaul E. McKenney 	return retval;
3482e83b879SPaul E. McKenney }
3492e83b879SPaul E. McKenney 
3501f45a4dbSPaul McKenney /* Used by tracing, cannot be traced and cannot invoke lockdep. */
3511f45a4dbSPaul McKenney static inline notrace int
srcu_read_lock_notrace(struct srcu_struct * ssp)352aacb5d91SPaul E. McKenney srcu_read_lock_notrace(struct srcu_struct *ssp) __acquires(ssp)
3531f45a4dbSPaul McKenney {
3541f45a4dbSPaul McKenney 	int retval;
3551f45a4dbSPaul McKenney 
35605829be2SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
357aacb5d91SPaul E. McKenney 	retval = __srcu_read_lock(ssp);
3581f45a4dbSPaul McKenney 	return retval;
3591f45a4dbSPaul McKenney }
3601f45a4dbSPaul McKenney 
361632ee200SPaul E. McKenney /**
3620b1182bdSPaul E. McKenney  * srcu_down_read - register a new reader for an SRCU-protected structure.
3630b1182bdSPaul E. McKenney  * @ssp: srcu_struct in which to register the new reader.
3640b1182bdSPaul E. McKenney  *
3650b1182bdSPaul E. McKenney  * Enter a semaphore-like SRCU read-side critical section.  Note that
3660b1182bdSPaul E. McKenney  * SRCU read-side critical sections may be nested.  However, it is
3670b1182bdSPaul E. McKenney  * illegal to call anything that waits on an SRCU grace period for the
3680b1182bdSPaul E. McKenney  * same srcu_struct, whether directly or indirectly.  Please note that
3690b1182bdSPaul E. McKenney  * one way to indirectly wait on an SRCU grace period is to acquire
3700b1182bdSPaul E. McKenney  * a mutex that is held elsewhere while calling synchronize_srcu() or
3710b1182bdSPaul E. McKenney  * synchronize_srcu_expedited().  But if you want lockdep to help you
3720b1182bdSPaul E. McKenney  * keep this stuff straight, you should instead use srcu_read_lock().
3730b1182bdSPaul E. McKenney  *
3740b1182bdSPaul E. McKenney  * The semaphore-like nature of srcu_down_read() means that the matching
3750b1182bdSPaul E. McKenney  * srcu_up_read() can be invoked from some other context, for example,
3760b1182bdSPaul E. McKenney  * from some other task or from an irq handler.  However, neither
3770b1182bdSPaul E. McKenney  * srcu_down_read() nor srcu_up_read() may be invoked from an NMI handler.
3780b1182bdSPaul E. McKenney  *
3790b1182bdSPaul E. McKenney  * Calls to srcu_down_read() may be nested, similar to the manner in
380729fb748SPaul E. McKenney  * which calls to down_read() may be nested.  The same srcu_struct may be
381729fb748SPaul E. McKenney  * used concurrently by srcu_down_read() and srcu_read_lock().
3820b1182bdSPaul E. McKenney  */
srcu_down_read(struct srcu_struct * ssp)3830b1182bdSPaul E. McKenney static inline int srcu_down_read(struct srcu_struct *ssp) __acquires(ssp)
3840b1182bdSPaul E. McKenney {
3850b1182bdSPaul E. McKenney 	WARN_ON_ONCE(in_nmi());
38605829be2SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
3870b1182bdSPaul E. McKenney 	return __srcu_read_lock(ssp);
3880b1182bdSPaul E. McKenney }
3890b1182bdSPaul E. McKenney 
3900b1182bdSPaul E. McKenney /**
391632ee200SPaul E. McKenney  * srcu_read_unlock - unregister a old reader from an SRCU-protected structure.
392aacb5d91SPaul E. McKenney  * @ssp: srcu_struct in which to unregister the old reader.
393632ee200SPaul E. McKenney  * @idx: return value from corresponding srcu_read_lock().
394632ee200SPaul E. McKenney  *
395632ee200SPaul E. McKenney  * Exit an SRCU read-side critical section.
396632ee200SPaul E. McKenney  */
srcu_read_unlock(struct srcu_struct * ssp,int idx)397aacb5d91SPaul E. McKenney static inline void srcu_read_unlock(struct srcu_struct *ssp, int idx)
398aacb5d91SPaul E. McKenney 	__releases(ssp)
399632ee200SPaul E. McKenney {
400c8ca1aa7SPaul E. McKenney 	WARN_ON_ONCE(idx & ~0x1);
40105829be2SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
4021da82598SPaul E. McKenney 	srcu_lock_release(&ssp->dep_map);
403aacb5d91SPaul E. McKenney 	__srcu_read_unlock(ssp, idx);
404632ee200SPaul E. McKenney }
405632ee200SPaul E. McKenney 
4062e83b879SPaul E. McKenney /**
407c4020620SPaul E. McKenney  * srcu_read_unlock_fast - unregister a old reader from an SRCU-protected structure.
408c4020620SPaul E. McKenney  * @ssp: srcu_struct in which to unregister the old reader.
409c4020620SPaul E. McKenney  * @scp: return value from corresponding srcu_read_lock_fast().
410c4020620SPaul E. McKenney  *
411c4020620SPaul E. McKenney  * Exit a light-weight SRCU read-side critical section.
412c4020620SPaul E. McKenney  */
srcu_read_unlock_fast(struct srcu_struct * ssp,struct srcu_ctr __percpu * scp)413c4020620SPaul E. McKenney static inline void srcu_read_unlock_fast(struct srcu_struct *ssp, struct srcu_ctr __percpu *scp)
414c4020620SPaul E. McKenney 	__releases(ssp)
415c4020620SPaul E. McKenney {
416c4020620SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST);
417c4020620SPaul E. McKenney 	srcu_lock_release(&ssp->dep_map);
418c4020620SPaul E. McKenney 	__srcu_read_unlock_fast(ssp, scp);
419c4020620SPaul E. McKenney }
420c4020620SPaul E. McKenney 
421c4020620SPaul E. McKenney /**
422*f8b8df19SPaul E. McKenney  * srcu_up_read_fast - unregister a old reader from an SRCU-protected structure.
423*f8b8df19SPaul E. McKenney  * @ssp: srcu_struct in which to unregister the old reader.
424*f8b8df19SPaul E. McKenney  * @scp: return value from corresponding srcu_read_lock_fast().
425*f8b8df19SPaul E. McKenney  *
426*f8b8df19SPaul E. McKenney  * Exit an SRCU read-side critical section, but not necessarily from
427*f8b8df19SPaul E. McKenney  * the same context as the maching srcu_down_read_fast().
428*f8b8df19SPaul E. McKenney  */
srcu_up_read_fast(struct srcu_struct * ssp,struct srcu_ctr __percpu * scp)429*f8b8df19SPaul E. McKenney static inline void srcu_up_read_fast(struct srcu_struct *ssp, struct srcu_ctr __percpu *scp)
430*f8b8df19SPaul E. McKenney 	__releases(ssp)
431*f8b8df19SPaul E. McKenney {
432*f8b8df19SPaul E. McKenney 	WARN_ON_ONCE(IS_ENABLED(CONFIG_PROVE_RCU) && in_nmi());
433*f8b8df19SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_FAST);
434*f8b8df19SPaul E. McKenney 	__srcu_read_unlock_fast(ssp, scp);
435*f8b8df19SPaul E. McKenney }
436*f8b8df19SPaul E. McKenney 
437*f8b8df19SPaul E. McKenney /**
4386364dd81SPaul E. McKenney  * srcu_read_unlock_lite - unregister a old reader from an SRCU-protected structure.
4396364dd81SPaul E. McKenney  * @ssp: srcu_struct in which to unregister the old reader.
440dfe442c9SPaul E. McKenney  * @idx: return value from corresponding srcu_read_lock_lite().
4416364dd81SPaul E. McKenney  *
4426364dd81SPaul E. McKenney  * Exit a light-weight SRCU read-side critical section.
4436364dd81SPaul E. McKenney  */
srcu_read_unlock_lite(struct srcu_struct * ssp,int idx)4446364dd81SPaul E. McKenney static inline void srcu_read_unlock_lite(struct srcu_struct *ssp, int idx)
4456364dd81SPaul E. McKenney 	__releases(ssp)
4466364dd81SPaul E. McKenney {
4476364dd81SPaul E. McKenney 	WARN_ON_ONCE(idx & ~0x1);
4486364dd81SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_LITE);
4496364dd81SPaul E. McKenney 	srcu_lock_release(&ssp->dep_map);
450174dd22aSPaul E. McKenney 	__srcu_read_unlock_lite(ssp, idx);
4516364dd81SPaul E. McKenney }
4526364dd81SPaul E. McKenney 
4536364dd81SPaul E. McKenney /**
4542e83b879SPaul E. McKenney  * srcu_read_unlock_nmisafe - unregister a old reader from an SRCU-protected structure.
4552e83b879SPaul E. McKenney  * @ssp: srcu_struct in which to unregister the old reader.
456dfe442c9SPaul E. McKenney  * @idx: return value from corresponding srcu_read_lock_nmisafe().
4572e83b879SPaul E. McKenney  *
4582e83b879SPaul E. McKenney  * Exit an SRCU read-side critical section, but in an NMI-safe manner.
4592e83b879SPaul E. McKenney  */
srcu_read_unlock_nmisafe(struct srcu_struct * ssp,int idx)4602e83b879SPaul E. McKenney static inline void srcu_read_unlock_nmisafe(struct srcu_struct *ssp, int idx)
4612e83b879SPaul E. McKenney 	__releases(ssp)
4622e83b879SPaul E. McKenney {
4632e83b879SPaul E. McKenney 	WARN_ON_ONCE(idx & ~0x1);
46405829be2SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NMI);
4651da82598SPaul E. McKenney 	rcu_lock_release(&ssp->dep_map);
466e29a4915SFrederic Weisbecker 	__srcu_read_unlock_nmisafe(ssp, idx);
4672e83b879SPaul E. McKenney }
4682e83b879SPaul E. McKenney 
4691f45a4dbSPaul McKenney /* Used by tracing, cannot be traced and cannot call lockdep. */
4701f45a4dbSPaul McKenney static inline notrace void
srcu_read_unlock_notrace(struct srcu_struct * ssp,int idx)471aacb5d91SPaul E. McKenney srcu_read_unlock_notrace(struct srcu_struct *ssp, int idx) __releases(ssp)
4721f45a4dbSPaul McKenney {
47305829be2SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
474aacb5d91SPaul E. McKenney 	__srcu_read_unlock(ssp, idx);
4751f45a4dbSPaul McKenney }
4761f45a4dbSPaul McKenney 
477ce332f66SMichael S. Tsirkin /**
4780b1182bdSPaul E. McKenney  * srcu_up_read - unregister a old reader from an SRCU-protected structure.
4790b1182bdSPaul E. McKenney  * @ssp: srcu_struct in which to unregister the old reader.
4800b1182bdSPaul E. McKenney  * @idx: return value from corresponding srcu_read_lock().
4810b1182bdSPaul E. McKenney  *
4820b1182bdSPaul E. McKenney  * Exit an SRCU read-side critical section, but not necessarily from
4830b1182bdSPaul E. McKenney  * the same context as the maching srcu_down_read().
4840b1182bdSPaul E. McKenney  */
srcu_up_read(struct srcu_struct * ssp,int idx)4850b1182bdSPaul E. McKenney static inline void srcu_up_read(struct srcu_struct *ssp, int idx)
4860b1182bdSPaul E. McKenney 	__releases(ssp)
4870b1182bdSPaul E. McKenney {
4880b1182bdSPaul E. McKenney 	WARN_ON_ONCE(idx & ~0x1);
4890b1182bdSPaul E. McKenney 	WARN_ON_ONCE(in_nmi());
49005829be2SPaul E. McKenney 	srcu_check_read_flavor(ssp, SRCU_READ_FLAVOR_NORMAL);
4910b1182bdSPaul E. McKenney 	__srcu_read_unlock(ssp, idx);
4920b1182bdSPaul E. McKenney }
4930b1182bdSPaul E. McKenney 
4940b1182bdSPaul E. McKenney /**
495ce332f66SMichael S. Tsirkin  * smp_mb__after_srcu_read_unlock - ensure full ordering after srcu_read_unlock
496ce332f66SMichael S. Tsirkin  *
497ce332f66SMichael S. Tsirkin  * Converts the preceding srcu_read_unlock into a two-way memory barrier.
498ce332f66SMichael S. Tsirkin  *
499ce332f66SMichael S. Tsirkin  * Call this after srcu_read_unlock, to guarantee that all memory operations
500ce332f66SMichael S. Tsirkin  * that occur after smp_mb__after_srcu_read_unlock will appear to happen after
501ce332f66SMichael S. Tsirkin  * the preceding srcu_read_unlock.
502ce332f66SMichael S. Tsirkin  */
smp_mb__after_srcu_read_unlock(void)503ce332f66SMichael S. Tsirkin static inline void smp_mb__after_srcu_read_unlock(void)
504ce332f66SMichael S. Tsirkin {
505ce332f66SMichael S. Tsirkin 	/* __srcu_read_unlock has smp_mb() internally so nothing to do here. */
506ce332f66SMichael S. Tsirkin }
507ce332f66SMichael S. Tsirkin 
508f05eda16SYan Zhao /**
509f05eda16SYan Zhao  * smp_mb__after_srcu_read_lock - ensure full ordering after srcu_read_lock
510f05eda16SYan Zhao  *
511f05eda16SYan Zhao  * Converts the preceding srcu_read_lock into a two-way memory barrier.
512f05eda16SYan Zhao  *
513f05eda16SYan Zhao  * Call this after srcu_read_lock, to guarantee that all memory operations
514f05eda16SYan Zhao  * that occur after smp_mb__after_srcu_read_lock will appear to happen after
515f05eda16SYan Zhao  * the preceding srcu_read_lock.
516f05eda16SYan Zhao  */
smp_mb__after_srcu_read_lock(void)517f05eda16SYan Zhao static inline void smp_mb__after_srcu_read_lock(void)
518f05eda16SYan Zhao {
519f05eda16SYan Zhao 	/* __srcu_read_lock has smp_mb() internally so nothing to do here. */
520f05eda16SYan Zhao }
521f05eda16SYan Zhao 
52254da6a09SPeter Zijlstra DEFINE_LOCK_GUARD_1(srcu, struct srcu_struct,
52354da6a09SPeter Zijlstra 		    _T->idx = srcu_read_lock(_T->lock),
52454da6a09SPeter Zijlstra 		    srcu_read_unlock(_T->lock, _T->idx),
52554da6a09SPeter Zijlstra 		    int idx)
52654da6a09SPeter Zijlstra 
527eabc0694SAlan Stern #endif
528