xref: /linux/lib/test_context-analysis.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
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>
9d3febf16SMarco Elver #include <linux/local_lock.h>
10370f0a34SMarco Elver #include <linux/mutex.h>
11d3febf16SMarco Elver #include <linux/percpu.h>
12fe00f6e8SMarco Elver #include <linux/rcupdate.h>
13e4fd3be8SMarco Elver #include <linux/rwsem.h>
148f8a55f4SMarco Elver #include <linux/seqlock.h>
15f16a802dSMarco Elver #include <linux/spinlock.h>
16f0b7ce22SMarco Elver #include <linux/srcu.h>
1747907461SMarco Elver #include <linux/ww_mutex.h>
189b00c160SMarco Elver 
199b00c160SMarco Elver /*
209b00c160SMarco Elver  * Test that helper macros work as expected.
219b00c160SMarco Elver  */
229b00c160SMarco Elver static void __used test_common_helpers(void)
239b00c160SMarco Elver {
249b00c160SMarco Elver 	BUILD_BUG_ON(context_unsafe(3) != 3); /* plain expression */
259b00c160SMarco Elver 	BUILD_BUG_ON(context_unsafe((void)2; 3) != 3); /* does not swallow semi-colon */
269b00c160SMarco Elver 	BUILD_BUG_ON(context_unsafe((void)2, 3) != 3); /* does not swallow commas */
279b00c160SMarco Elver 	context_unsafe(do { } while (0)); /* works with void statements */
289b00c160SMarco Elver }
29f16a802dSMarco Elver 
30f16a802dSMarco Elver #define TEST_SPINLOCK_COMMON(class, type, type_init, type_lock, type_unlock, type_trylock, op)	\
31f16a802dSMarco Elver 	struct test_##class##_data {								\
32f16a802dSMarco Elver 		type lock;									\
33f16a802dSMarco Elver 		int counter __guarded_by(&lock);						\
34f16a802dSMarco Elver 		int *pointer __pt_guarded_by(&lock);						\
35f16a802dSMarco Elver 	};											\
36f16a802dSMarco Elver 	static void __used test_##class##_init(struct test_##class##_data *d)			\
37f16a802dSMarco Elver 	{											\
38*d084a737SMarco Elver 		guard(type_init)(&d->lock);							\
39f16a802dSMarco Elver 		d->counter = 0;									\
40f16a802dSMarco Elver 	}											\
41f16a802dSMarco Elver 	static void __used test_##class(struct test_##class##_data *d)				\
42f16a802dSMarco Elver 	{											\
43f16a802dSMarco Elver 		unsigned long flags;								\
44f16a802dSMarco Elver 		d->pointer++;									\
45f16a802dSMarco Elver 		type_lock(&d->lock);								\
46f16a802dSMarco Elver 		op(d->counter);									\
47f16a802dSMarco Elver 		op(*d->pointer);								\
48f16a802dSMarco Elver 		type_unlock(&d->lock);								\
49f16a802dSMarco Elver 		type_lock##_irq(&d->lock);							\
50f16a802dSMarco Elver 		op(d->counter);									\
51f16a802dSMarco Elver 		op(*d->pointer);								\
52f16a802dSMarco Elver 		type_unlock##_irq(&d->lock);							\
53f16a802dSMarco Elver 		type_lock##_bh(&d->lock);							\
54f16a802dSMarco Elver 		op(d->counter);									\
55f16a802dSMarco Elver 		op(*d->pointer);								\
56f16a802dSMarco Elver 		type_unlock##_bh(&d->lock);							\
57f16a802dSMarco Elver 		type_lock##_irqsave(&d->lock, flags);						\
58f16a802dSMarco Elver 		op(d->counter);									\
59f16a802dSMarco Elver 		op(*d->pointer);								\
60f16a802dSMarco Elver 		type_unlock##_irqrestore(&d->lock, flags);					\
61f16a802dSMarco Elver 	}											\
62f16a802dSMarco Elver 	static void __used test_##class##_trylock(struct test_##class##_data *d)		\
63f16a802dSMarco Elver 	{											\
64f16a802dSMarco Elver 		if (type_trylock(&d->lock)) {							\
65f16a802dSMarco Elver 			op(d->counter);								\
66f16a802dSMarco Elver 			type_unlock(&d->lock);							\
67f16a802dSMarco Elver 		}										\
68f16a802dSMarco Elver 	}											\
69f16a802dSMarco Elver 	static void __used test_##class##_assert(struct test_##class##_data *d)			\
70f16a802dSMarco Elver 	{											\
71f16a802dSMarco Elver 		lockdep_assert_held(&d->lock);							\
72f16a802dSMarco Elver 		op(d->counter);									\
73f16a802dSMarco Elver 	}											\
74f16a802dSMarco Elver 	static void __used test_##class##_guard(struct test_##class##_data *d)			\
75f16a802dSMarco Elver 	{											\
76f16a802dSMarco Elver 		{ guard(class)(&d->lock);		op(d->counter); }			\
77f16a802dSMarco Elver 		{ guard(class##_irq)(&d->lock);		op(d->counter); }			\
78f16a802dSMarco Elver 		{ guard(class##_irqsave)(&d->lock);	op(d->counter); }			\
79f16a802dSMarco Elver 	}
80f16a802dSMarco Elver 
81f16a802dSMarco Elver #define TEST_OP_RW(x) (x)++
82f16a802dSMarco Elver #define TEST_OP_RO(x) ((void)(x))
83f16a802dSMarco Elver 
84f16a802dSMarco Elver TEST_SPINLOCK_COMMON(raw_spinlock,
85f16a802dSMarco Elver 		     raw_spinlock_t,
86*d084a737SMarco Elver 		     raw_spinlock_init,
87f16a802dSMarco Elver 		     raw_spin_lock,
88f16a802dSMarco Elver 		     raw_spin_unlock,
89f16a802dSMarco Elver 		     raw_spin_trylock,
90f16a802dSMarco Elver 		     TEST_OP_RW);
91f16a802dSMarco Elver static void __used test_raw_spinlock_trylock_extra(struct test_raw_spinlock_data *d)
92f16a802dSMarco Elver {
93f16a802dSMarco Elver 	unsigned long flags;
94f16a802dSMarco Elver 
953635ad87SMarco Elver 	data_race(d->counter++); /* no warning */
963635ad87SMarco Elver 
97f16a802dSMarco Elver 	if (raw_spin_trylock_irq(&d->lock)) {
98f16a802dSMarco Elver 		d->counter++;
99f16a802dSMarco Elver 		raw_spin_unlock_irq(&d->lock);
100f16a802dSMarco Elver 	}
101f16a802dSMarco Elver 	if (raw_spin_trylock_irqsave(&d->lock, flags)) {
102f16a802dSMarco Elver 		d->counter++;
103f16a802dSMarco Elver 		raw_spin_unlock_irqrestore(&d->lock, flags);
104f16a802dSMarco Elver 	}
105f16a802dSMarco Elver 	scoped_cond_guard(raw_spinlock_try, return, &d->lock) {
106f16a802dSMarco Elver 		d->counter++;
107f16a802dSMarco Elver 	}
108f16a802dSMarco Elver }
109f16a802dSMarco Elver 
110f16a802dSMarco Elver TEST_SPINLOCK_COMMON(spinlock,
111f16a802dSMarco Elver 		     spinlock_t,
112*d084a737SMarco Elver 		     spinlock_init,
113f16a802dSMarco Elver 		     spin_lock,
114f16a802dSMarco Elver 		     spin_unlock,
115f16a802dSMarco Elver 		     spin_trylock,
116f16a802dSMarco Elver 		     TEST_OP_RW);
117f16a802dSMarco Elver static void __used test_spinlock_trylock_extra(struct test_spinlock_data *d)
118f16a802dSMarco Elver {
119f16a802dSMarco Elver 	unsigned long flags;
120f16a802dSMarco Elver 
121f16a802dSMarco Elver 	if (spin_trylock_irq(&d->lock)) {
122f16a802dSMarco Elver 		d->counter++;
123f16a802dSMarco Elver 		spin_unlock_irq(&d->lock);
124f16a802dSMarco Elver 	}
125f16a802dSMarco Elver 	if (spin_trylock_irqsave(&d->lock, flags)) {
126f16a802dSMarco Elver 		d->counter++;
127f16a802dSMarco Elver 		spin_unlock_irqrestore(&d->lock, flags);
128f16a802dSMarco Elver 	}
129f16a802dSMarco Elver 	scoped_cond_guard(spinlock_try, return, &d->lock) {
130f16a802dSMarco Elver 		d->counter++;
131f16a802dSMarco Elver 	}
132f16a802dSMarco Elver }
133f16a802dSMarco Elver 
134f16a802dSMarco Elver TEST_SPINLOCK_COMMON(write_lock,
135f16a802dSMarco Elver 		     rwlock_t,
136f16a802dSMarco Elver 		     rwlock_init,
137f16a802dSMarco Elver 		     write_lock,
138f16a802dSMarco Elver 		     write_unlock,
139f16a802dSMarco Elver 		     write_trylock,
140f16a802dSMarco Elver 		     TEST_OP_RW);
141f16a802dSMarco Elver static void __used test_write_trylock_extra(struct test_write_lock_data *d)
142f16a802dSMarco Elver {
143f16a802dSMarco Elver 	unsigned long flags;
144f16a802dSMarco Elver 
145f16a802dSMarco Elver 	if (write_trylock_irqsave(&d->lock, flags)) {
146f16a802dSMarco Elver 		d->counter++;
147f16a802dSMarco Elver 		write_unlock_irqrestore(&d->lock, flags);
148f16a802dSMarco Elver 	}
149f16a802dSMarco Elver }
150f16a802dSMarco Elver 
151f16a802dSMarco Elver TEST_SPINLOCK_COMMON(read_lock,
152f16a802dSMarco Elver 		     rwlock_t,
153f16a802dSMarco Elver 		     rwlock_init,
154f16a802dSMarco Elver 		     read_lock,
155f16a802dSMarco Elver 		     read_unlock,
156f16a802dSMarco Elver 		     read_trylock,
157f16a802dSMarco Elver 		     TEST_OP_RO);
158370f0a34SMarco Elver 
159370f0a34SMarco Elver struct test_mutex_data {
160370f0a34SMarco Elver 	struct mutex mtx;
161370f0a34SMarco Elver 	int counter __guarded_by(&mtx);
162370f0a34SMarco Elver };
163370f0a34SMarco Elver 
164370f0a34SMarco Elver static void __used test_mutex_init(struct test_mutex_data *d)
165370f0a34SMarco Elver {
166*d084a737SMarco Elver 	guard(mutex_init)(&d->mtx);
167370f0a34SMarco Elver 	d->counter = 0;
168370f0a34SMarco Elver }
169370f0a34SMarco Elver 
170370f0a34SMarco Elver static void __used test_mutex_lock(struct test_mutex_data *d)
171370f0a34SMarco Elver {
172370f0a34SMarco Elver 	mutex_lock(&d->mtx);
173370f0a34SMarco Elver 	d->counter++;
174370f0a34SMarco Elver 	mutex_unlock(&d->mtx);
175370f0a34SMarco Elver 	mutex_lock_io(&d->mtx);
176370f0a34SMarco Elver 	d->counter++;
177370f0a34SMarco Elver 	mutex_unlock(&d->mtx);
178370f0a34SMarco Elver }
179370f0a34SMarco Elver 
180370f0a34SMarco Elver static void __used test_mutex_trylock(struct test_mutex_data *d, atomic_t *a)
181370f0a34SMarco Elver {
182370f0a34SMarco Elver 	if (!mutex_lock_interruptible(&d->mtx)) {
183370f0a34SMarco Elver 		d->counter++;
184370f0a34SMarco Elver 		mutex_unlock(&d->mtx);
185370f0a34SMarco Elver 	}
186370f0a34SMarco Elver 	if (!mutex_lock_killable(&d->mtx)) {
187370f0a34SMarco Elver 		d->counter++;
188370f0a34SMarco Elver 		mutex_unlock(&d->mtx);
189370f0a34SMarco Elver 	}
190370f0a34SMarco Elver 	if (mutex_trylock(&d->mtx)) {
191370f0a34SMarco Elver 		d->counter++;
192370f0a34SMarco Elver 		mutex_unlock(&d->mtx);
193370f0a34SMarco Elver 	}
194370f0a34SMarco Elver 	if (atomic_dec_and_mutex_lock(a, &d->mtx)) {
195370f0a34SMarco Elver 		d->counter++;
196370f0a34SMarco Elver 		mutex_unlock(&d->mtx);
197370f0a34SMarco Elver 	}
198370f0a34SMarco Elver }
199370f0a34SMarco Elver 
200370f0a34SMarco Elver static void __used test_mutex_assert(struct test_mutex_data *d)
201370f0a34SMarco Elver {
202370f0a34SMarco Elver 	lockdep_assert_held(&d->mtx);
203370f0a34SMarco Elver 	d->counter++;
204370f0a34SMarco Elver }
205370f0a34SMarco Elver 
206370f0a34SMarco Elver static void __used test_mutex_guard(struct test_mutex_data *d)
207370f0a34SMarco Elver {
208370f0a34SMarco Elver 	guard(mutex)(&d->mtx);
209370f0a34SMarco Elver 	d->counter++;
210370f0a34SMarco Elver }
211370f0a34SMarco Elver 
212370f0a34SMarco Elver static void __used test_mutex_cond_guard(struct test_mutex_data *d)
213370f0a34SMarco Elver {
214370f0a34SMarco Elver 	scoped_cond_guard(mutex_try, return, &d->mtx) {
215370f0a34SMarco Elver 		d->counter++;
216370f0a34SMarco Elver 	}
217370f0a34SMarco Elver 	scoped_cond_guard(mutex_intr, return, &d->mtx) {
218370f0a34SMarco Elver 		d->counter++;
219370f0a34SMarco Elver 	}
220370f0a34SMarco Elver }
2218f8a55f4SMarco Elver 
2228f8a55f4SMarco Elver struct test_seqlock_data {
2238f8a55f4SMarco Elver 	seqlock_t sl;
2248f8a55f4SMarco Elver 	int counter __guarded_by(&sl);
2258f8a55f4SMarco Elver };
2268f8a55f4SMarco Elver 
2278f8a55f4SMarco Elver static void __used test_seqlock_init(struct test_seqlock_data *d)
2288f8a55f4SMarco Elver {
229*d084a737SMarco Elver 	guard(seqlock_init)(&d->sl);
2308f8a55f4SMarco Elver 	d->counter = 0;
2318f8a55f4SMarco Elver }
2328f8a55f4SMarco Elver 
2338f8a55f4SMarco Elver static void __used test_seqlock_reader(struct test_seqlock_data *d)
2348f8a55f4SMarco Elver {
2358f8a55f4SMarco Elver 	unsigned int seq;
2368f8a55f4SMarco Elver 
2378f8a55f4SMarco Elver 	do {
2388f8a55f4SMarco Elver 		seq = read_seqbegin(&d->sl);
2398f8a55f4SMarco Elver 		(void)d->counter;
2408f8a55f4SMarco Elver 	} while (read_seqretry(&d->sl, seq));
2418f8a55f4SMarco Elver }
2428f8a55f4SMarco Elver 
2438f8a55f4SMarco Elver static void __used test_seqlock_writer(struct test_seqlock_data *d)
2448f8a55f4SMarco Elver {
2458f8a55f4SMarco Elver 	unsigned long flags;
2468f8a55f4SMarco Elver 
2478f8a55f4SMarco Elver 	write_seqlock(&d->sl);
2488f8a55f4SMarco Elver 	d->counter++;
2498f8a55f4SMarco Elver 	write_sequnlock(&d->sl);
2508f8a55f4SMarco Elver 
2518f8a55f4SMarco Elver 	write_seqlock_irq(&d->sl);
2528f8a55f4SMarco Elver 	d->counter++;
2538f8a55f4SMarco Elver 	write_sequnlock_irq(&d->sl);
2548f8a55f4SMarco Elver 
2558f8a55f4SMarco Elver 	write_seqlock_bh(&d->sl);
2568f8a55f4SMarco Elver 	d->counter++;
2578f8a55f4SMarco Elver 	write_sequnlock_bh(&d->sl);
2588f8a55f4SMarco Elver 
2598f8a55f4SMarco Elver 	write_seqlock_irqsave(&d->sl, flags);
2608f8a55f4SMarco Elver 	d->counter++;
2618f8a55f4SMarco Elver 	write_sequnlock_irqrestore(&d->sl, flags);
2628f8a55f4SMarco Elver }
2638f8a55f4SMarco Elver 
2648f8a55f4SMarco Elver static void __used test_seqlock_scoped(struct test_seqlock_data *d)
2658f8a55f4SMarco Elver {
2668f8a55f4SMarco Elver 	scoped_seqlock_read (&d->sl, ss_lockless) {
2678f8a55f4SMarco Elver 		(void)d->counter;
2688f8a55f4SMarco Elver 	}
2698f8a55f4SMarco Elver }
270eb7d96a1SMarco Elver 
271e4fd3be8SMarco Elver struct test_rwsem_data {
272e4fd3be8SMarco Elver 	struct rw_semaphore sem;
273e4fd3be8SMarco Elver 	int counter __guarded_by(&sem);
274e4fd3be8SMarco Elver };
275e4fd3be8SMarco Elver 
276e4fd3be8SMarco Elver static void __used test_rwsem_init(struct test_rwsem_data *d)
277e4fd3be8SMarco Elver {
278*d084a737SMarco Elver 	guard(rwsem_init)(&d->sem);
279e4fd3be8SMarco Elver 	d->counter = 0;
280e4fd3be8SMarco Elver }
281e4fd3be8SMarco Elver 
282e4fd3be8SMarco Elver static void __used test_rwsem_reader(struct test_rwsem_data *d)
283e4fd3be8SMarco Elver {
284e4fd3be8SMarco Elver 	down_read(&d->sem);
285e4fd3be8SMarco Elver 	(void)d->counter;
286e4fd3be8SMarco Elver 	up_read(&d->sem);
287e4fd3be8SMarco Elver 
288e4fd3be8SMarco Elver 	if (down_read_trylock(&d->sem)) {
289e4fd3be8SMarco Elver 		(void)d->counter;
290e4fd3be8SMarco Elver 		up_read(&d->sem);
291e4fd3be8SMarco Elver 	}
292e4fd3be8SMarco Elver }
293e4fd3be8SMarco Elver 
294e4fd3be8SMarco Elver static void __used test_rwsem_writer(struct test_rwsem_data *d)
295e4fd3be8SMarco Elver {
296e4fd3be8SMarco Elver 	down_write(&d->sem);
297e4fd3be8SMarco Elver 	d->counter++;
298e4fd3be8SMarco Elver 	up_write(&d->sem);
299e4fd3be8SMarco Elver 
300e4fd3be8SMarco Elver 	down_write(&d->sem);
301e4fd3be8SMarco Elver 	d->counter++;
302e4fd3be8SMarco Elver 	downgrade_write(&d->sem);
303e4fd3be8SMarco Elver 	(void)d->counter;
304e4fd3be8SMarco Elver 	up_read(&d->sem);
305e4fd3be8SMarco Elver 
306e4fd3be8SMarco Elver 	if (down_write_trylock(&d->sem)) {
307e4fd3be8SMarco Elver 		d->counter++;
308e4fd3be8SMarco Elver 		up_write(&d->sem);
309e4fd3be8SMarco Elver 	}
310e4fd3be8SMarco Elver }
311e4fd3be8SMarco Elver 
312e4fd3be8SMarco Elver static void __used test_rwsem_assert(struct test_rwsem_data *d)
313e4fd3be8SMarco Elver {
314e4fd3be8SMarco Elver 	rwsem_assert_held_nolockdep(&d->sem);
315e4fd3be8SMarco Elver 	d->counter++;
316e4fd3be8SMarco Elver }
317e4fd3be8SMarco Elver 
318e4fd3be8SMarco Elver static void __used test_rwsem_guard(struct test_rwsem_data *d)
319e4fd3be8SMarco Elver {
320e4fd3be8SMarco Elver 	{ guard(rwsem_read)(&d->sem); (void)d->counter; }
321e4fd3be8SMarco Elver 	{ guard(rwsem_write)(&d->sem); d->counter++; }
322e4fd3be8SMarco Elver }
323e4fd3be8SMarco Elver 
324e4fd3be8SMarco Elver static void __used test_rwsem_cond_guard(struct test_rwsem_data *d)
325e4fd3be8SMarco Elver {
326e4fd3be8SMarco Elver 	scoped_cond_guard(rwsem_read_try, return, &d->sem) {
327e4fd3be8SMarco Elver 		(void)d->counter;
328e4fd3be8SMarco Elver 	}
329e4fd3be8SMarco Elver 	scoped_cond_guard(rwsem_write_try, return, &d->sem) {
330e4fd3be8SMarco Elver 		d->counter++;
331e4fd3be8SMarco Elver 	}
332e4fd3be8SMarco Elver }
333e4fd3be8SMarco Elver 
334eb7d96a1SMarco Elver struct test_bit_spinlock_data {
335eb7d96a1SMarco Elver 	unsigned long bits;
336eb7d96a1SMarco Elver 	int counter __guarded_by(__bitlock(3, &bits));
337eb7d96a1SMarco Elver };
338eb7d96a1SMarco Elver 
339eb7d96a1SMarco Elver static void __used test_bit_spin_lock(struct test_bit_spinlock_data *d)
340eb7d96a1SMarco Elver {
341eb7d96a1SMarco Elver 	/*
342eb7d96a1SMarco Elver 	 * Note, the analysis seems to have false negatives, because it won't
343eb7d96a1SMarco Elver 	 * precisely recognize the bit of the fake __bitlock() token.
344eb7d96a1SMarco Elver 	 */
345eb7d96a1SMarco Elver 	bit_spin_lock(3, &d->bits);
346eb7d96a1SMarco Elver 	d->counter++;
347eb7d96a1SMarco Elver 	bit_spin_unlock(3, &d->bits);
348eb7d96a1SMarco Elver 
349eb7d96a1SMarco Elver 	bit_spin_lock(3, &d->bits);
350eb7d96a1SMarco Elver 	d->counter++;
351eb7d96a1SMarco Elver 	__bit_spin_unlock(3, &d->bits);
352eb7d96a1SMarco Elver 
353eb7d96a1SMarco Elver 	if (bit_spin_trylock(3, &d->bits)) {
354eb7d96a1SMarco Elver 		d->counter++;
355eb7d96a1SMarco Elver 		bit_spin_unlock(3, &d->bits);
356eb7d96a1SMarco Elver 	}
357eb7d96a1SMarco Elver }
358fe00f6e8SMarco Elver 
359fe00f6e8SMarco Elver /*
360fe00f6e8SMarco Elver  * Test that we can mark a variable guarded by RCU, and we can dereference and
361fe00f6e8SMarco Elver  * write to the pointer with RCU's primitives.
362fe00f6e8SMarco Elver  */
363fe00f6e8SMarco Elver struct test_rcu_data {
364fe00f6e8SMarco Elver 	long __rcu_guarded *data;
365fe00f6e8SMarco Elver };
366fe00f6e8SMarco Elver 
367fe00f6e8SMarco Elver static void __used test_rcu_guarded_reader(struct test_rcu_data *d)
368fe00f6e8SMarco Elver {
369fe00f6e8SMarco Elver 	rcu_read_lock();
370fe00f6e8SMarco Elver 	(void)rcu_dereference(d->data);
371fe00f6e8SMarco Elver 	rcu_read_unlock();
372fe00f6e8SMarco Elver 
373fe00f6e8SMarco Elver 	rcu_read_lock_bh();
374fe00f6e8SMarco Elver 	(void)rcu_dereference(d->data);
375fe00f6e8SMarco Elver 	rcu_read_unlock_bh();
376fe00f6e8SMarco Elver 
377fe00f6e8SMarco Elver 	rcu_read_lock_sched();
378fe00f6e8SMarco Elver 	(void)rcu_dereference(d->data);
379fe00f6e8SMarco Elver 	rcu_read_unlock_sched();
380fe00f6e8SMarco Elver }
381fe00f6e8SMarco Elver 
382fe00f6e8SMarco Elver static void __used test_rcu_guard(struct test_rcu_data *d)
383fe00f6e8SMarco Elver {
384fe00f6e8SMarco Elver 	guard(rcu)();
385fe00f6e8SMarco Elver 	(void)rcu_dereference(d->data);
386fe00f6e8SMarco Elver }
387fe00f6e8SMarco Elver 
388fe00f6e8SMarco Elver static void __used test_rcu_guarded_updater(struct test_rcu_data *d)
389fe00f6e8SMarco Elver {
390fe00f6e8SMarco Elver 	rcu_assign_pointer(d->data, NULL);
391fe00f6e8SMarco Elver 	RCU_INIT_POINTER(d->data, NULL);
392fe00f6e8SMarco Elver 	(void)unrcu_pointer(d->data);
393fe00f6e8SMarco Elver }
394fe00f6e8SMarco Elver 
395fe00f6e8SMarco Elver static void wants_rcu_held(void)	__must_hold_shared(RCU)       { }
396fe00f6e8SMarco Elver static void wants_rcu_held_bh(void)	__must_hold_shared(RCU_BH)    { }
397fe00f6e8SMarco Elver static void wants_rcu_held_sched(void)	__must_hold_shared(RCU_SCHED) { }
398fe00f6e8SMarco Elver 
399fe00f6e8SMarco Elver static void __used test_rcu_lock_variants(void)
400fe00f6e8SMarco Elver {
401fe00f6e8SMarco Elver 	rcu_read_lock();
402fe00f6e8SMarco Elver 	wants_rcu_held();
403fe00f6e8SMarco Elver 	rcu_read_unlock();
404fe00f6e8SMarco Elver 
405fe00f6e8SMarco Elver 	rcu_read_lock_bh();
406fe00f6e8SMarco Elver 	wants_rcu_held_bh();
407fe00f6e8SMarco Elver 	rcu_read_unlock_bh();
408fe00f6e8SMarco Elver 
409fe00f6e8SMarco Elver 	rcu_read_lock_sched();
410fe00f6e8SMarco Elver 	wants_rcu_held_sched();
411fe00f6e8SMarco Elver 	rcu_read_unlock_sched();
412fe00f6e8SMarco Elver }
413fe00f6e8SMarco Elver 
414fe00f6e8SMarco Elver static void __used test_rcu_lock_reentrant(void)
415fe00f6e8SMarco Elver {
416fe00f6e8SMarco Elver 	rcu_read_lock();
417fe00f6e8SMarco Elver 	rcu_read_lock();
418fe00f6e8SMarco Elver 	rcu_read_lock_bh();
419fe00f6e8SMarco Elver 	rcu_read_lock_bh();
420fe00f6e8SMarco Elver 	rcu_read_lock_sched();
421fe00f6e8SMarco Elver 	rcu_read_lock_sched();
422fe00f6e8SMarco Elver 
423fe00f6e8SMarco Elver 	rcu_read_unlock_sched();
424fe00f6e8SMarco Elver 	rcu_read_unlock_sched();
425fe00f6e8SMarco Elver 	rcu_read_unlock_bh();
426fe00f6e8SMarco Elver 	rcu_read_unlock_bh();
427fe00f6e8SMarco Elver 	rcu_read_unlock();
428fe00f6e8SMarco Elver 	rcu_read_unlock();
429fe00f6e8SMarco Elver }
430fe00f6e8SMarco Elver 
431fe00f6e8SMarco Elver static void __used test_rcu_assert_variants(void)
432fe00f6e8SMarco Elver {
433fe00f6e8SMarco Elver 	lockdep_assert_in_rcu_read_lock();
434fe00f6e8SMarco Elver 	wants_rcu_held();
435fe00f6e8SMarco Elver 
436fe00f6e8SMarco Elver 	lockdep_assert_in_rcu_read_lock_bh();
437fe00f6e8SMarco Elver 	wants_rcu_held_bh();
438fe00f6e8SMarco Elver 
439fe00f6e8SMarco Elver 	lockdep_assert_in_rcu_read_lock_sched();
440fe00f6e8SMarco Elver 	wants_rcu_held_sched();
441fe00f6e8SMarco Elver }
442f0b7ce22SMarco Elver 
443f0b7ce22SMarco Elver struct test_srcu_data {
444f0b7ce22SMarco Elver 	struct srcu_struct srcu;
445f0b7ce22SMarco Elver 	long __rcu_guarded *data;
446f0b7ce22SMarco Elver };
447f0b7ce22SMarco Elver 
448f0b7ce22SMarco Elver static void __used test_srcu(struct test_srcu_data *d)
449f0b7ce22SMarco Elver {
450f0b7ce22SMarco Elver 	init_srcu_struct(&d->srcu);
451f0b7ce22SMarco Elver 
452f0b7ce22SMarco Elver 	int idx = srcu_read_lock(&d->srcu);
453f0b7ce22SMarco Elver 	long *data = srcu_dereference(d->data, &d->srcu);
454f0b7ce22SMarco Elver 	(void)data;
455f0b7ce22SMarco Elver 	srcu_read_unlock(&d->srcu, idx);
456f0b7ce22SMarco Elver 
457f0b7ce22SMarco Elver 	rcu_assign_pointer(d->data, NULL);
458f0b7ce22SMarco Elver }
459f0b7ce22SMarco Elver 
460f0b7ce22SMarco Elver static void __used test_srcu_guard(struct test_srcu_data *d)
461f0b7ce22SMarco Elver {
462f0b7ce22SMarco Elver 	{ guard(srcu)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
463f0b7ce22SMarco Elver 	{ guard(srcu_fast)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
464f0b7ce22SMarco Elver 	{ guard(srcu_fast_notrace)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
465f0b7ce22SMarco Elver }
466d3febf16SMarco Elver 
467d3febf16SMarco Elver struct test_local_lock_data {
468d3febf16SMarco Elver 	local_lock_t lock;
469d3febf16SMarco Elver 	int counter __guarded_by(&lock);
470d3febf16SMarco Elver };
471d3febf16SMarco Elver 
472d3febf16SMarco Elver static DEFINE_PER_CPU(struct test_local_lock_data, test_local_lock_data) = {
473d3febf16SMarco Elver 	.lock = INIT_LOCAL_LOCK(lock),
474d3febf16SMarco Elver };
475d3febf16SMarco Elver 
476d3febf16SMarco Elver static void __used test_local_lock_init(struct test_local_lock_data *d)
477d3febf16SMarco Elver {
478*d084a737SMarco Elver 	guard(local_lock_init)(&d->lock);
479d3febf16SMarco Elver 	d->counter = 0;
480d3febf16SMarco Elver }
481d3febf16SMarco Elver 
482d3febf16SMarco Elver static void __used test_local_lock(void)
483d3febf16SMarco Elver {
484d3febf16SMarco Elver 	unsigned long flags;
485d3febf16SMarco Elver 
486d3febf16SMarco Elver 	local_lock(&test_local_lock_data.lock);
487d3febf16SMarco Elver 	this_cpu_add(test_local_lock_data.counter, 1);
488d3febf16SMarco Elver 	local_unlock(&test_local_lock_data.lock);
489d3febf16SMarco Elver 
490d3febf16SMarco Elver 	local_lock_irq(&test_local_lock_data.lock);
491d3febf16SMarco Elver 	this_cpu_add(test_local_lock_data.counter, 1);
492d3febf16SMarco Elver 	local_unlock_irq(&test_local_lock_data.lock);
493d3febf16SMarco Elver 
494d3febf16SMarco Elver 	local_lock_irqsave(&test_local_lock_data.lock, flags);
495d3febf16SMarco Elver 	this_cpu_add(test_local_lock_data.counter, 1);
496d3febf16SMarco Elver 	local_unlock_irqrestore(&test_local_lock_data.lock, flags);
497d3febf16SMarco Elver 
498d3febf16SMarco Elver 	local_lock_nested_bh(&test_local_lock_data.lock);
499d3febf16SMarco Elver 	this_cpu_add(test_local_lock_data.counter, 1);
500d3febf16SMarco Elver 	local_unlock_nested_bh(&test_local_lock_data.lock);
501d3febf16SMarco Elver }
502d3febf16SMarco Elver 
503d3febf16SMarco Elver static void __used test_local_lock_guard(void)
504d3febf16SMarco Elver {
505d3febf16SMarco Elver 	{ guard(local_lock)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
506d3febf16SMarco Elver 	{ guard(local_lock_irq)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
507d3febf16SMarco Elver 	{ guard(local_lock_irqsave)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
508d3febf16SMarco Elver 	{ guard(local_lock_nested_bh)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
509d3febf16SMarco Elver }
510d3febf16SMarco Elver 
511d3febf16SMarco Elver struct test_local_trylock_data {
512d3febf16SMarco Elver 	local_trylock_t lock;
513d3febf16SMarco Elver 	int counter __guarded_by(&lock);
514d3febf16SMarco Elver };
515d3febf16SMarco Elver 
516d3febf16SMarco Elver static DEFINE_PER_CPU(struct test_local_trylock_data, test_local_trylock_data) = {
517d3febf16SMarco Elver 	.lock = INIT_LOCAL_TRYLOCK(lock),
518d3febf16SMarco Elver };
519d3febf16SMarco Elver 
520d3febf16SMarco Elver static void __used test_local_trylock_init(struct test_local_trylock_data *d)
521d3febf16SMarco Elver {
522*d084a737SMarco Elver 	guard(local_trylock_init)(&d->lock);
523d3febf16SMarco Elver 	d->counter = 0;
524d3febf16SMarco Elver }
525d3febf16SMarco Elver 
526d3febf16SMarco Elver static void __used test_local_trylock(void)
527d3febf16SMarco Elver {
528d3febf16SMarco Elver 	local_lock(&test_local_trylock_data.lock);
529d3febf16SMarco Elver 	this_cpu_add(test_local_trylock_data.counter, 1);
530d3febf16SMarco Elver 	local_unlock(&test_local_trylock_data.lock);
531d3febf16SMarco Elver 
532d3febf16SMarco Elver 	if (local_trylock(&test_local_trylock_data.lock)) {
533d3febf16SMarco Elver 		this_cpu_add(test_local_trylock_data.counter, 1);
534d3febf16SMarco Elver 		local_unlock(&test_local_trylock_data.lock);
535d3febf16SMarco Elver 	}
536d3febf16SMarco Elver }
53747907461SMarco Elver 
53847907461SMarco Elver static DEFINE_WD_CLASS(ww_class);
53947907461SMarco Elver 
54047907461SMarco Elver struct test_ww_mutex_data {
54147907461SMarco Elver 	struct ww_mutex mtx;
54247907461SMarco Elver 	int counter __guarded_by(&mtx);
54347907461SMarco Elver };
54447907461SMarco Elver 
54547907461SMarco Elver static void __used test_ww_mutex_lock_noctx(struct test_ww_mutex_data *d)
54647907461SMarco Elver {
54747907461SMarco Elver 	if (!ww_mutex_lock(&d->mtx, NULL)) {
54847907461SMarco Elver 		d->counter++;
54947907461SMarco Elver 		ww_mutex_unlock(&d->mtx);
55047907461SMarco Elver 	}
55147907461SMarco Elver 
55247907461SMarco Elver 	if (!ww_mutex_lock_interruptible(&d->mtx, NULL)) {
55347907461SMarco Elver 		d->counter++;
55447907461SMarco Elver 		ww_mutex_unlock(&d->mtx);
55547907461SMarco Elver 	}
55647907461SMarco Elver 
55747907461SMarco Elver 	if (ww_mutex_trylock(&d->mtx, NULL)) {
55847907461SMarco Elver 		d->counter++;
55947907461SMarco Elver 		ww_mutex_unlock(&d->mtx);
56047907461SMarco Elver 	}
56147907461SMarco Elver 
56247907461SMarco Elver 	ww_mutex_lock_slow(&d->mtx, NULL);
56347907461SMarco Elver 	d->counter++;
56447907461SMarco Elver 	ww_mutex_unlock(&d->mtx);
56547907461SMarco Elver 
56647907461SMarco Elver 	ww_mutex_destroy(&d->mtx);
56747907461SMarco Elver }
56847907461SMarco Elver 
56947907461SMarco Elver static void __used test_ww_mutex_lock_ctx(struct test_ww_mutex_data *d)
57047907461SMarco Elver {
57147907461SMarco Elver 	struct ww_acquire_ctx ctx;
57247907461SMarco Elver 
57347907461SMarco Elver 	ww_acquire_init(&ctx, &ww_class);
57447907461SMarco Elver 
57547907461SMarco Elver 	if (!ww_mutex_lock(&d->mtx, &ctx)) {
57647907461SMarco Elver 		d->counter++;
57747907461SMarco Elver 		ww_mutex_unlock(&d->mtx);
57847907461SMarco Elver 	}
57947907461SMarco Elver 
58047907461SMarco Elver 	if (!ww_mutex_lock_interruptible(&d->mtx, &ctx)) {
58147907461SMarco Elver 		d->counter++;
58247907461SMarco Elver 		ww_mutex_unlock(&d->mtx);
58347907461SMarco Elver 	}
58447907461SMarco Elver 
58547907461SMarco Elver 	if (ww_mutex_trylock(&d->mtx, &ctx)) {
58647907461SMarco Elver 		d->counter++;
58747907461SMarco Elver 		ww_mutex_unlock(&d->mtx);
58847907461SMarco Elver 	}
58947907461SMarco Elver 
59047907461SMarco Elver 	ww_mutex_lock_slow(&d->mtx, &ctx);
59147907461SMarco Elver 	d->counter++;
59247907461SMarco Elver 	ww_mutex_unlock(&d->mtx);
59347907461SMarco Elver 
59447907461SMarco Elver 	ww_acquire_done(&ctx);
59547907461SMarco Elver 	ww_acquire_fini(&ctx);
59647907461SMarco Elver 
59747907461SMarco Elver 	ww_mutex_destroy(&d->mtx);
59847907461SMarco Elver }
599