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