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