xref: /linux/lib/test_context-analysis.c (revision f0b7ce22d71810c8c11abcd912fbd6f57c2e9677)
19b00c160SMarco Elver // SPDX-License-Identifier: GPL-2.0-only
29b00c160SMarco Elver /*
39b00c160SMarco Elver  * Compile-only tests for common patterns that should not generate false
49b00c160SMarco Elver  * positive errors when compiled with Clang's context analysis.
59b00c160SMarco Elver  */
69b00c160SMarco Elver 
7eb7d96a1SMarco Elver #include <linux/bit_spinlock.h>
89b00c160SMarco Elver #include <linux/build_bug.h>
9370f0a34SMarco Elver #include <linux/mutex.h>
10fe00f6e8SMarco Elver #include <linux/rcupdate.h>
118f8a55f4SMarco Elver #include <linux/seqlock.h>
12f16a802dSMarco Elver #include <linux/spinlock.h>
13*f0b7ce22SMarco Elver #include <linux/srcu.h>
149b00c160SMarco Elver 
159b00c160SMarco Elver /*
169b00c160SMarco Elver  * Test that helper macros work as expected.
179b00c160SMarco Elver  */
189b00c160SMarco Elver static void __used test_common_helpers(void)
199b00c160SMarco Elver {
209b00c160SMarco Elver 	BUILD_BUG_ON(context_unsafe(3) != 3); /* plain expression */
219b00c160SMarco Elver 	BUILD_BUG_ON(context_unsafe((void)2; 3) != 3); /* does not swallow semi-colon */
229b00c160SMarco Elver 	BUILD_BUG_ON(context_unsafe((void)2, 3) != 3); /* does not swallow commas */
239b00c160SMarco Elver 	context_unsafe(do { } while (0)); /* works with void statements */
249b00c160SMarco Elver }
25f16a802dSMarco Elver 
26f16a802dSMarco Elver #define TEST_SPINLOCK_COMMON(class, type, type_init, type_lock, type_unlock, type_trylock, op)	\
27f16a802dSMarco Elver 	struct test_##class##_data {								\
28f16a802dSMarco Elver 		type lock;									\
29f16a802dSMarco Elver 		int counter __guarded_by(&lock);						\
30f16a802dSMarco Elver 		int *pointer __pt_guarded_by(&lock);						\
31f16a802dSMarco Elver 	};											\
32f16a802dSMarco Elver 	static void __used test_##class##_init(struct test_##class##_data *d)			\
33f16a802dSMarco Elver 	{											\
34f16a802dSMarco Elver 		type_init(&d->lock);								\
35f16a802dSMarco Elver 		d->counter = 0;									\
36f16a802dSMarco Elver 	}											\
37f16a802dSMarco Elver 	static void __used test_##class(struct test_##class##_data *d)				\
38f16a802dSMarco Elver 	{											\
39f16a802dSMarco Elver 		unsigned long flags;								\
40f16a802dSMarco Elver 		d->pointer++;									\
41f16a802dSMarco Elver 		type_lock(&d->lock);								\
42f16a802dSMarco Elver 		op(d->counter);									\
43f16a802dSMarco Elver 		op(*d->pointer);								\
44f16a802dSMarco Elver 		type_unlock(&d->lock);								\
45f16a802dSMarco Elver 		type_lock##_irq(&d->lock);							\
46f16a802dSMarco Elver 		op(d->counter);									\
47f16a802dSMarco Elver 		op(*d->pointer);								\
48f16a802dSMarco Elver 		type_unlock##_irq(&d->lock);							\
49f16a802dSMarco Elver 		type_lock##_bh(&d->lock);							\
50f16a802dSMarco Elver 		op(d->counter);									\
51f16a802dSMarco Elver 		op(*d->pointer);								\
52f16a802dSMarco Elver 		type_unlock##_bh(&d->lock);							\
53f16a802dSMarco Elver 		type_lock##_irqsave(&d->lock, flags);						\
54f16a802dSMarco Elver 		op(d->counter);									\
55f16a802dSMarco Elver 		op(*d->pointer);								\
56f16a802dSMarco Elver 		type_unlock##_irqrestore(&d->lock, flags);					\
57f16a802dSMarco Elver 	}											\
58f16a802dSMarco Elver 	static void __used test_##class##_trylock(struct test_##class##_data *d)		\
59f16a802dSMarco Elver 	{											\
60f16a802dSMarco Elver 		if (type_trylock(&d->lock)) {							\
61f16a802dSMarco Elver 			op(d->counter);								\
62f16a802dSMarco Elver 			type_unlock(&d->lock);							\
63f16a802dSMarco Elver 		}										\
64f16a802dSMarco Elver 	}											\
65f16a802dSMarco Elver 	static void __used test_##class##_assert(struct test_##class##_data *d)			\
66f16a802dSMarco Elver 	{											\
67f16a802dSMarco Elver 		lockdep_assert_held(&d->lock);							\
68f16a802dSMarco Elver 		op(d->counter);									\
69f16a802dSMarco Elver 	}											\
70f16a802dSMarco Elver 	static void __used test_##class##_guard(struct test_##class##_data *d)			\
71f16a802dSMarco Elver 	{											\
72f16a802dSMarco Elver 		{ guard(class)(&d->lock);		op(d->counter); }			\
73f16a802dSMarco Elver 		{ guard(class##_irq)(&d->lock);		op(d->counter); }			\
74f16a802dSMarco Elver 		{ guard(class##_irqsave)(&d->lock);	op(d->counter); }			\
75f16a802dSMarco Elver 	}
76f16a802dSMarco Elver 
77f16a802dSMarco Elver #define TEST_OP_RW(x) (x)++
78f16a802dSMarco Elver #define TEST_OP_RO(x) ((void)(x))
79f16a802dSMarco Elver 
80f16a802dSMarco Elver TEST_SPINLOCK_COMMON(raw_spinlock,
81f16a802dSMarco Elver 		     raw_spinlock_t,
82f16a802dSMarco Elver 		     raw_spin_lock_init,
83f16a802dSMarco Elver 		     raw_spin_lock,
84f16a802dSMarco Elver 		     raw_spin_unlock,
85f16a802dSMarco Elver 		     raw_spin_trylock,
86f16a802dSMarco Elver 		     TEST_OP_RW);
87f16a802dSMarco Elver static void __used test_raw_spinlock_trylock_extra(struct test_raw_spinlock_data *d)
88f16a802dSMarco Elver {
89f16a802dSMarco Elver 	unsigned long flags;
90f16a802dSMarco Elver 
91f16a802dSMarco Elver 	if (raw_spin_trylock_irq(&d->lock)) {
92f16a802dSMarco Elver 		d->counter++;
93f16a802dSMarco Elver 		raw_spin_unlock_irq(&d->lock);
94f16a802dSMarco Elver 	}
95f16a802dSMarco Elver 	if (raw_spin_trylock_irqsave(&d->lock, flags)) {
96f16a802dSMarco Elver 		d->counter++;
97f16a802dSMarco Elver 		raw_spin_unlock_irqrestore(&d->lock, flags);
98f16a802dSMarco Elver 	}
99f16a802dSMarco Elver 	scoped_cond_guard(raw_spinlock_try, return, &d->lock) {
100f16a802dSMarco Elver 		d->counter++;
101f16a802dSMarco Elver 	}
102f16a802dSMarco Elver }
103f16a802dSMarco Elver 
104f16a802dSMarco Elver TEST_SPINLOCK_COMMON(spinlock,
105f16a802dSMarco Elver 		     spinlock_t,
106f16a802dSMarco Elver 		     spin_lock_init,
107f16a802dSMarco Elver 		     spin_lock,
108f16a802dSMarco Elver 		     spin_unlock,
109f16a802dSMarco Elver 		     spin_trylock,
110f16a802dSMarco Elver 		     TEST_OP_RW);
111f16a802dSMarco Elver static void __used test_spinlock_trylock_extra(struct test_spinlock_data *d)
112f16a802dSMarco Elver {
113f16a802dSMarco Elver 	unsigned long flags;
114f16a802dSMarco Elver 
115f16a802dSMarco Elver 	if (spin_trylock_irq(&d->lock)) {
116f16a802dSMarco Elver 		d->counter++;
117f16a802dSMarco Elver 		spin_unlock_irq(&d->lock);
118f16a802dSMarco Elver 	}
119f16a802dSMarco Elver 	if (spin_trylock_irqsave(&d->lock, flags)) {
120f16a802dSMarco Elver 		d->counter++;
121f16a802dSMarco Elver 		spin_unlock_irqrestore(&d->lock, flags);
122f16a802dSMarco Elver 	}
123f16a802dSMarco Elver 	scoped_cond_guard(spinlock_try, return, &d->lock) {
124f16a802dSMarco Elver 		d->counter++;
125f16a802dSMarco Elver 	}
126f16a802dSMarco Elver }
127f16a802dSMarco Elver 
128f16a802dSMarco Elver TEST_SPINLOCK_COMMON(write_lock,
129f16a802dSMarco Elver 		     rwlock_t,
130f16a802dSMarco Elver 		     rwlock_init,
131f16a802dSMarco Elver 		     write_lock,
132f16a802dSMarco Elver 		     write_unlock,
133f16a802dSMarco Elver 		     write_trylock,
134f16a802dSMarco Elver 		     TEST_OP_RW);
135f16a802dSMarco Elver static void __used test_write_trylock_extra(struct test_write_lock_data *d)
136f16a802dSMarco Elver {
137f16a802dSMarco Elver 	unsigned long flags;
138f16a802dSMarco Elver 
139f16a802dSMarco Elver 	if (write_trylock_irqsave(&d->lock, flags)) {
140f16a802dSMarco Elver 		d->counter++;
141f16a802dSMarco Elver 		write_unlock_irqrestore(&d->lock, flags);
142f16a802dSMarco Elver 	}
143f16a802dSMarco Elver }
144f16a802dSMarco Elver 
145f16a802dSMarco Elver TEST_SPINLOCK_COMMON(read_lock,
146f16a802dSMarco Elver 		     rwlock_t,
147f16a802dSMarco Elver 		     rwlock_init,
148f16a802dSMarco Elver 		     read_lock,
149f16a802dSMarco Elver 		     read_unlock,
150f16a802dSMarco Elver 		     read_trylock,
151f16a802dSMarco Elver 		     TEST_OP_RO);
152370f0a34SMarco Elver 
153370f0a34SMarco Elver struct test_mutex_data {
154370f0a34SMarco Elver 	struct mutex mtx;
155370f0a34SMarco Elver 	int counter __guarded_by(&mtx);
156370f0a34SMarco Elver };
157370f0a34SMarco Elver 
158370f0a34SMarco Elver static void __used test_mutex_init(struct test_mutex_data *d)
159370f0a34SMarco Elver {
160370f0a34SMarco Elver 	mutex_init(&d->mtx);
161370f0a34SMarco Elver 	d->counter = 0;
162370f0a34SMarco Elver }
163370f0a34SMarco Elver 
164370f0a34SMarco Elver static void __used test_mutex_lock(struct test_mutex_data *d)
165370f0a34SMarco Elver {
166370f0a34SMarco Elver 	mutex_lock(&d->mtx);
167370f0a34SMarco Elver 	d->counter++;
168370f0a34SMarco Elver 	mutex_unlock(&d->mtx);
169370f0a34SMarco Elver 	mutex_lock_io(&d->mtx);
170370f0a34SMarco Elver 	d->counter++;
171370f0a34SMarco Elver 	mutex_unlock(&d->mtx);
172370f0a34SMarco Elver }
173370f0a34SMarco Elver 
174370f0a34SMarco Elver static void __used test_mutex_trylock(struct test_mutex_data *d, atomic_t *a)
175370f0a34SMarco Elver {
176370f0a34SMarco Elver 	if (!mutex_lock_interruptible(&d->mtx)) {
177370f0a34SMarco Elver 		d->counter++;
178370f0a34SMarco Elver 		mutex_unlock(&d->mtx);
179370f0a34SMarco Elver 	}
180370f0a34SMarco Elver 	if (!mutex_lock_killable(&d->mtx)) {
181370f0a34SMarco Elver 		d->counter++;
182370f0a34SMarco Elver 		mutex_unlock(&d->mtx);
183370f0a34SMarco Elver 	}
184370f0a34SMarco Elver 	if (mutex_trylock(&d->mtx)) {
185370f0a34SMarco Elver 		d->counter++;
186370f0a34SMarco Elver 		mutex_unlock(&d->mtx);
187370f0a34SMarco Elver 	}
188370f0a34SMarco Elver 	if (atomic_dec_and_mutex_lock(a, &d->mtx)) {
189370f0a34SMarco Elver 		d->counter++;
190370f0a34SMarco Elver 		mutex_unlock(&d->mtx);
191370f0a34SMarco Elver 	}
192370f0a34SMarco Elver }
193370f0a34SMarco Elver 
194370f0a34SMarco Elver static void __used test_mutex_assert(struct test_mutex_data *d)
195370f0a34SMarco Elver {
196370f0a34SMarco Elver 	lockdep_assert_held(&d->mtx);
197370f0a34SMarco Elver 	d->counter++;
198370f0a34SMarco Elver }
199370f0a34SMarco Elver 
200370f0a34SMarco Elver static void __used test_mutex_guard(struct test_mutex_data *d)
201370f0a34SMarco Elver {
202370f0a34SMarco Elver 	guard(mutex)(&d->mtx);
203370f0a34SMarco Elver 	d->counter++;
204370f0a34SMarco Elver }
205370f0a34SMarco Elver 
206370f0a34SMarco Elver static void __used test_mutex_cond_guard(struct test_mutex_data *d)
207370f0a34SMarco Elver {
208370f0a34SMarco Elver 	scoped_cond_guard(mutex_try, return, &d->mtx) {
209370f0a34SMarco Elver 		d->counter++;
210370f0a34SMarco Elver 	}
211370f0a34SMarco Elver 	scoped_cond_guard(mutex_intr, return, &d->mtx) {
212370f0a34SMarco Elver 		d->counter++;
213370f0a34SMarco Elver 	}
214370f0a34SMarco Elver }
2158f8a55f4SMarco Elver 
2168f8a55f4SMarco Elver struct test_seqlock_data {
2178f8a55f4SMarco Elver 	seqlock_t sl;
2188f8a55f4SMarco Elver 	int counter __guarded_by(&sl);
2198f8a55f4SMarco Elver };
2208f8a55f4SMarco Elver 
2218f8a55f4SMarco Elver static void __used test_seqlock_init(struct test_seqlock_data *d)
2228f8a55f4SMarco Elver {
2238f8a55f4SMarco Elver 	seqlock_init(&d->sl);
2248f8a55f4SMarco Elver 	d->counter = 0;
2258f8a55f4SMarco Elver }
2268f8a55f4SMarco Elver 
2278f8a55f4SMarco Elver static void __used test_seqlock_reader(struct test_seqlock_data *d)
2288f8a55f4SMarco Elver {
2298f8a55f4SMarco Elver 	unsigned int seq;
2308f8a55f4SMarco Elver 
2318f8a55f4SMarco Elver 	do {
2328f8a55f4SMarco Elver 		seq = read_seqbegin(&d->sl);
2338f8a55f4SMarco Elver 		(void)d->counter;
2348f8a55f4SMarco Elver 	} while (read_seqretry(&d->sl, seq));
2358f8a55f4SMarco Elver }
2368f8a55f4SMarco Elver 
2378f8a55f4SMarco Elver static void __used test_seqlock_writer(struct test_seqlock_data *d)
2388f8a55f4SMarco Elver {
2398f8a55f4SMarco Elver 	unsigned long flags;
2408f8a55f4SMarco Elver 
2418f8a55f4SMarco Elver 	write_seqlock(&d->sl);
2428f8a55f4SMarco Elver 	d->counter++;
2438f8a55f4SMarco Elver 	write_sequnlock(&d->sl);
2448f8a55f4SMarco Elver 
2458f8a55f4SMarco Elver 	write_seqlock_irq(&d->sl);
2468f8a55f4SMarco Elver 	d->counter++;
2478f8a55f4SMarco Elver 	write_sequnlock_irq(&d->sl);
2488f8a55f4SMarco Elver 
2498f8a55f4SMarco Elver 	write_seqlock_bh(&d->sl);
2508f8a55f4SMarco Elver 	d->counter++;
2518f8a55f4SMarco Elver 	write_sequnlock_bh(&d->sl);
2528f8a55f4SMarco Elver 
2538f8a55f4SMarco Elver 	write_seqlock_irqsave(&d->sl, flags);
2548f8a55f4SMarco Elver 	d->counter++;
2558f8a55f4SMarco Elver 	write_sequnlock_irqrestore(&d->sl, flags);
2568f8a55f4SMarco Elver }
2578f8a55f4SMarco Elver 
2588f8a55f4SMarco Elver static void __used test_seqlock_scoped(struct test_seqlock_data *d)
2598f8a55f4SMarco Elver {
2608f8a55f4SMarco Elver 	scoped_seqlock_read (&d->sl, ss_lockless) {
2618f8a55f4SMarco Elver 		(void)d->counter;
2628f8a55f4SMarco Elver 	}
2638f8a55f4SMarco Elver }
264eb7d96a1SMarco Elver 
265eb7d96a1SMarco Elver struct test_bit_spinlock_data {
266eb7d96a1SMarco Elver 	unsigned long bits;
267eb7d96a1SMarco Elver 	int counter __guarded_by(__bitlock(3, &bits));
268eb7d96a1SMarco Elver };
269eb7d96a1SMarco Elver 
270eb7d96a1SMarco Elver static void __used test_bit_spin_lock(struct test_bit_spinlock_data *d)
271eb7d96a1SMarco Elver {
272eb7d96a1SMarco Elver 	/*
273eb7d96a1SMarco Elver 	 * Note, the analysis seems to have false negatives, because it won't
274eb7d96a1SMarco Elver 	 * precisely recognize the bit of the fake __bitlock() token.
275eb7d96a1SMarco Elver 	 */
276eb7d96a1SMarco Elver 	bit_spin_lock(3, &d->bits);
277eb7d96a1SMarco Elver 	d->counter++;
278eb7d96a1SMarco Elver 	bit_spin_unlock(3, &d->bits);
279eb7d96a1SMarco Elver 
280eb7d96a1SMarco Elver 	bit_spin_lock(3, &d->bits);
281eb7d96a1SMarco Elver 	d->counter++;
282eb7d96a1SMarco Elver 	__bit_spin_unlock(3, &d->bits);
283eb7d96a1SMarco Elver 
284eb7d96a1SMarco Elver 	if (bit_spin_trylock(3, &d->bits)) {
285eb7d96a1SMarco Elver 		d->counter++;
286eb7d96a1SMarco Elver 		bit_spin_unlock(3, &d->bits);
287eb7d96a1SMarco Elver 	}
288eb7d96a1SMarco Elver }
289fe00f6e8SMarco Elver 
290fe00f6e8SMarco Elver /*
291fe00f6e8SMarco Elver  * Test that we can mark a variable guarded by RCU, and we can dereference and
292fe00f6e8SMarco Elver  * write to the pointer with RCU's primitives.
293fe00f6e8SMarco Elver  */
294fe00f6e8SMarco Elver struct test_rcu_data {
295fe00f6e8SMarco Elver 	long __rcu_guarded *data;
296fe00f6e8SMarco Elver };
297fe00f6e8SMarco Elver 
298fe00f6e8SMarco Elver static void __used test_rcu_guarded_reader(struct test_rcu_data *d)
299fe00f6e8SMarco Elver {
300fe00f6e8SMarco Elver 	rcu_read_lock();
301fe00f6e8SMarco Elver 	(void)rcu_dereference(d->data);
302fe00f6e8SMarco Elver 	rcu_read_unlock();
303fe00f6e8SMarco Elver 
304fe00f6e8SMarco Elver 	rcu_read_lock_bh();
305fe00f6e8SMarco Elver 	(void)rcu_dereference(d->data);
306fe00f6e8SMarco Elver 	rcu_read_unlock_bh();
307fe00f6e8SMarco Elver 
308fe00f6e8SMarco Elver 	rcu_read_lock_sched();
309fe00f6e8SMarco Elver 	(void)rcu_dereference(d->data);
310fe00f6e8SMarco Elver 	rcu_read_unlock_sched();
311fe00f6e8SMarco Elver }
312fe00f6e8SMarco Elver 
313fe00f6e8SMarco Elver static void __used test_rcu_guard(struct test_rcu_data *d)
314fe00f6e8SMarco Elver {
315fe00f6e8SMarco Elver 	guard(rcu)();
316fe00f6e8SMarco Elver 	(void)rcu_dereference(d->data);
317fe00f6e8SMarco Elver }
318fe00f6e8SMarco Elver 
319fe00f6e8SMarco Elver static void __used test_rcu_guarded_updater(struct test_rcu_data *d)
320fe00f6e8SMarco Elver {
321fe00f6e8SMarco Elver 	rcu_assign_pointer(d->data, NULL);
322fe00f6e8SMarco Elver 	RCU_INIT_POINTER(d->data, NULL);
323fe00f6e8SMarco Elver 	(void)unrcu_pointer(d->data);
324fe00f6e8SMarco Elver }
325fe00f6e8SMarco Elver 
326fe00f6e8SMarco Elver static void wants_rcu_held(void)	__must_hold_shared(RCU)       { }
327fe00f6e8SMarco Elver static void wants_rcu_held_bh(void)	__must_hold_shared(RCU_BH)    { }
328fe00f6e8SMarco Elver static void wants_rcu_held_sched(void)	__must_hold_shared(RCU_SCHED) { }
329fe00f6e8SMarco Elver 
330fe00f6e8SMarco Elver static void __used test_rcu_lock_variants(void)
331fe00f6e8SMarco Elver {
332fe00f6e8SMarco Elver 	rcu_read_lock();
333fe00f6e8SMarco Elver 	wants_rcu_held();
334fe00f6e8SMarco Elver 	rcu_read_unlock();
335fe00f6e8SMarco Elver 
336fe00f6e8SMarco Elver 	rcu_read_lock_bh();
337fe00f6e8SMarco Elver 	wants_rcu_held_bh();
338fe00f6e8SMarco Elver 	rcu_read_unlock_bh();
339fe00f6e8SMarco Elver 
340fe00f6e8SMarco Elver 	rcu_read_lock_sched();
341fe00f6e8SMarco Elver 	wants_rcu_held_sched();
342fe00f6e8SMarco Elver 	rcu_read_unlock_sched();
343fe00f6e8SMarco Elver }
344fe00f6e8SMarco Elver 
345fe00f6e8SMarco Elver static void __used test_rcu_lock_reentrant(void)
346fe00f6e8SMarco Elver {
347fe00f6e8SMarco Elver 	rcu_read_lock();
348fe00f6e8SMarco Elver 	rcu_read_lock();
349fe00f6e8SMarco Elver 	rcu_read_lock_bh();
350fe00f6e8SMarco Elver 	rcu_read_lock_bh();
351fe00f6e8SMarco Elver 	rcu_read_lock_sched();
352fe00f6e8SMarco Elver 	rcu_read_lock_sched();
353fe00f6e8SMarco Elver 
354fe00f6e8SMarco Elver 	rcu_read_unlock_sched();
355fe00f6e8SMarco Elver 	rcu_read_unlock_sched();
356fe00f6e8SMarco Elver 	rcu_read_unlock_bh();
357fe00f6e8SMarco Elver 	rcu_read_unlock_bh();
358fe00f6e8SMarco Elver 	rcu_read_unlock();
359fe00f6e8SMarco Elver 	rcu_read_unlock();
360fe00f6e8SMarco Elver }
361fe00f6e8SMarco Elver 
362fe00f6e8SMarco Elver static void __used test_rcu_assert_variants(void)
363fe00f6e8SMarco Elver {
364fe00f6e8SMarco Elver 	lockdep_assert_in_rcu_read_lock();
365fe00f6e8SMarco Elver 	wants_rcu_held();
366fe00f6e8SMarco Elver 
367fe00f6e8SMarco Elver 	lockdep_assert_in_rcu_read_lock_bh();
368fe00f6e8SMarco Elver 	wants_rcu_held_bh();
369fe00f6e8SMarco Elver 
370fe00f6e8SMarco Elver 	lockdep_assert_in_rcu_read_lock_sched();
371fe00f6e8SMarco Elver 	wants_rcu_held_sched();
372fe00f6e8SMarco Elver }
373*f0b7ce22SMarco Elver 
374*f0b7ce22SMarco Elver struct test_srcu_data {
375*f0b7ce22SMarco Elver 	struct srcu_struct srcu;
376*f0b7ce22SMarco Elver 	long __rcu_guarded *data;
377*f0b7ce22SMarco Elver };
378*f0b7ce22SMarco Elver 
379*f0b7ce22SMarco Elver static void __used test_srcu(struct test_srcu_data *d)
380*f0b7ce22SMarco Elver {
381*f0b7ce22SMarco Elver 	init_srcu_struct(&d->srcu);
382*f0b7ce22SMarco Elver 
383*f0b7ce22SMarco Elver 	int idx = srcu_read_lock(&d->srcu);
384*f0b7ce22SMarco Elver 	long *data = srcu_dereference(d->data, &d->srcu);
385*f0b7ce22SMarco Elver 	(void)data;
386*f0b7ce22SMarco Elver 	srcu_read_unlock(&d->srcu, idx);
387*f0b7ce22SMarco Elver 
388*f0b7ce22SMarco Elver 	rcu_assign_pointer(d->data, NULL);
389*f0b7ce22SMarco Elver }
390*f0b7ce22SMarco Elver 
391*f0b7ce22SMarco Elver static void __used test_srcu_guard(struct test_srcu_data *d)
392*f0b7ce22SMarco Elver {
393*f0b7ce22SMarco Elver 	{ guard(srcu)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
394*f0b7ce22SMarco Elver 	{ guard(srcu_fast)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
395*f0b7ce22SMarco Elver 	{ guard(srcu_fast_notrace)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
396*f0b7ce22SMarco Elver }
397