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