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