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 79b00c160SMarco Elver #include <linux/build_bug.h> 8*370f0a34SMarco Elver #include <linux/mutex.h> 9f16a802dSMarco Elver #include <linux/spinlock.h> 109b00c160SMarco Elver 119b00c160SMarco Elver /* 129b00c160SMarco Elver * Test that helper macros work as expected. 139b00c160SMarco Elver */ 149b00c160SMarco Elver static void __used test_common_helpers(void) 159b00c160SMarco Elver { 169b00c160SMarco Elver BUILD_BUG_ON(context_unsafe(3) != 3); /* plain expression */ 179b00c160SMarco Elver BUILD_BUG_ON(context_unsafe((void)2; 3) != 3); /* does not swallow semi-colon */ 189b00c160SMarco Elver BUILD_BUG_ON(context_unsafe((void)2, 3) != 3); /* does not swallow commas */ 199b00c160SMarco Elver context_unsafe(do { } while (0)); /* works with void statements */ 209b00c160SMarco Elver } 21f16a802dSMarco Elver 22f16a802dSMarco Elver #define TEST_SPINLOCK_COMMON(class, type, type_init, type_lock, type_unlock, type_trylock, op) \ 23f16a802dSMarco Elver struct test_##class##_data { \ 24f16a802dSMarco Elver type lock; \ 25f16a802dSMarco Elver int counter __guarded_by(&lock); \ 26f16a802dSMarco Elver int *pointer __pt_guarded_by(&lock); \ 27f16a802dSMarco Elver }; \ 28f16a802dSMarco Elver static void __used test_##class##_init(struct test_##class##_data *d) \ 29f16a802dSMarco Elver { \ 30f16a802dSMarco Elver type_init(&d->lock); \ 31f16a802dSMarco Elver d->counter = 0; \ 32f16a802dSMarco Elver } \ 33f16a802dSMarco Elver static void __used test_##class(struct test_##class##_data *d) \ 34f16a802dSMarco Elver { \ 35f16a802dSMarco Elver unsigned long flags; \ 36f16a802dSMarco Elver d->pointer++; \ 37f16a802dSMarco Elver type_lock(&d->lock); \ 38f16a802dSMarco Elver op(d->counter); \ 39f16a802dSMarco Elver op(*d->pointer); \ 40f16a802dSMarco Elver type_unlock(&d->lock); \ 41f16a802dSMarco Elver type_lock##_irq(&d->lock); \ 42f16a802dSMarco Elver op(d->counter); \ 43f16a802dSMarco Elver op(*d->pointer); \ 44f16a802dSMarco Elver type_unlock##_irq(&d->lock); \ 45f16a802dSMarco Elver type_lock##_bh(&d->lock); \ 46f16a802dSMarco Elver op(d->counter); \ 47f16a802dSMarco Elver op(*d->pointer); \ 48f16a802dSMarco Elver type_unlock##_bh(&d->lock); \ 49f16a802dSMarco Elver type_lock##_irqsave(&d->lock, flags); \ 50f16a802dSMarco Elver op(d->counter); \ 51f16a802dSMarco Elver op(*d->pointer); \ 52f16a802dSMarco Elver type_unlock##_irqrestore(&d->lock, flags); \ 53f16a802dSMarco Elver } \ 54f16a802dSMarco Elver static void __used test_##class##_trylock(struct test_##class##_data *d) \ 55f16a802dSMarco Elver { \ 56f16a802dSMarco Elver if (type_trylock(&d->lock)) { \ 57f16a802dSMarco Elver op(d->counter); \ 58f16a802dSMarco Elver type_unlock(&d->lock); \ 59f16a802dSMarco Elver } \ 60f16a802dSMarco Elver } \ 61f16a802dSMarco Elver static void __used test_##class##_assert(struct test_##class##_data *d) \ 62f16a802dSMarco Elver { \ 63f16a802dSMarco Elver lockdep_assert_held(&d->lock); \ 64f16a802dSMarco Elver op(d->counter); \ 65f16a802dSMarco Elver } \ 66f16a802dSMarco Elver static void __used test_##class##_guard(struct test_##class##_data *d) \ 67f16a802dSMarco Elver { \ 68f16a802dSMarco Elver { guard(class)(&d->lock); op(d->counter); } \ 69f16a802dSMarco Elver { guard(class##_irq)(&d->lock); op(d->counter); } \ 70f16a802dSMarco Elver { guard(class##_irqsave)(&d->lock); op(d->counter); } \ 71f16a802dSMarco Elver } 72f16a802dSMarco Elver 73f16a802dSMarco Elver #define TEST_OP_RW(x) (x)++ 74f16a802dSMarco Elver #define TEST_OP_RO(x) ((void)(x)) 75f16a802dSMarco Elver 76f16a802dSMarco Elver TEST_SPINLOCK_COMMON(raw_spinlock, 77f16a802dSMarco Elver raw_spinlock_t, 78f16a802dSMarco Elver raw_spin_lock_init, 79f16a802dSMarco Elver raw_spin_lock, 80f16a802dSMarco Elver raw_spin_unlock, 81f16a802dSMarco Elver raw_spin_trylock, 82f16a802dSMarco Elver TEST_OP_RW); 83f16a802dSMarco Elver static void __used test_raw_spinlock_trylock_extra(struct test_raw_spinlock_data *d) 84f16a802dSMarco Elver { 85f16a802dSMarco Elver unsigned long flags; 86f16a802dSMarco Elver 87f16a802dSMarco Elver if (raw_spin_trylock_irq(&d->lock)) { 88f16a802dSMarco Elver d->counter++; 89f16a802dSMarco Elver raw_spin_unlock_irq(&d->lock); 90f16a802dSMarco Elver } 91f16a802dSMarco Elver if (raw_spin_trylock_irqsave(&d->lock, flags)) { 92f16a802dSMarco Elver d->counter++; 93f16a802dSMarco Elver raw_spin_unlock_irqrestore(&d->lock, flags); 94f16a802dSMarco Elver } 95f16a802dSMarco Elver scoped_cond_guard(raw_spinlock_try, return, &d->lock) { 96f16a802dSMarco Elver d->counter++; 97f16a802dSMarco Elver } 98f16a802dSMarco Elver } 99f16a802dSMarco Elver 100f16a802dSMarco Elver TEST_SPINLOCK_COMMON(spinlock, 101f16a802dSMarco Elver spinlock_t, 102f16a802dSMarco Elver spin_lock_init, 103f16a802dSMarco Elver spin_lock, 104f16a802dSMarco Elver spin_unlock, 105f16a802dSMarco Elver spin_trylock, 106f16a802dSMarco Elver TEST_OP_RW); 107f16a802dSMarco Elver static void __used test_spinlock_trylock_extra(struct test_spinlock_data *d) 108f16a802dSMarco Elver { 109f16a802dSMarco Elver unsigned long flags; 110f16a802dSMarco Elver 111f16a802dSMarco Elver if (spin_trylock_irq(&d->lock)) { 112f16a802dSMarco Elver d->counter++; 113f16a802dSMarco Elver spin_unlock_irq(&d->lock); 114f16a802dSMarco Elver } 115f16a802dSMarco Elver if (spin_trylock_irqsave(&d->lock, flags)) { 116f16a802dSMarco Elver d->counter++; 117f16a802dSMarco Elver spin_unlock_irqrestore(&d->lock, flags); 118f16a802dSMarco Elver } 119f16a802dSMarco Elver scoped_cond_guard(spinlock_try, return, &d->lock) { 120f16a802dSMarco Elver d->counter++; 121f16a802dSMarco Elver } 122f16a802dSMarco Elver } 123f16a802dSMarco Elver 124f16a802dSMarco Elver TEST_SPINLOCK_COMMON(write_lock, 125f16a802dSMarco Elver rwlock_t, 126f16a802dSMarco Elver rwlock_init, 127f16a802dSMarco Elver write_lock, 128f16a802dSMarco Elver write_unlock, 129f16a802dSMarco Elver write_trylock, 130f16a802dSMarco Elver TEST_OP_RW); 131f16a802dSMarco Elver static void __used test_write_trylock_extra(struct test_write_lock_data *d) 132f16a802dSMarco Elver { 133f16a802dSMarco Elver unsigned long flags; 134f16a802dSMarco Elver 135f16a802dSMarco Elver if (write_trylock_irqsave(&d->lock, flags)) { 136f16a802dSMarco Elver d->counter++; 137f16a802dSMarco Elver write_unlock_irqrestore(&d->lock, flags); 138f16a802dSMarco Elver } 139f16a802dSMarco Elver } 140f16a802dSMarco Elver 141f16a802dSMarco Elver TEST_SPINLOCK_COMMON(read_lock, 142f16a802dSMarco Elver rwlock_t, 143f16a802dSMarco Elver rwlock_init, 144f16a802dSMarco Elver read_lock, 145f16a802dSMarco Elver read_unlock, 146f16a802dSMarco Elver read_trylock, 147f16a802dSMarco Elver TEST_OP_RO); 148*370f0a34SMarco Elver 149*370f0a34SMarco Elver struct test_mutex_data { 150*370f0a34SMarco Elver struct mutex mtx; 151*370f0a34SMarco Elver int counter __guarded_by(&mtx); 152*370f0a34SMarco Elver }; 153*370f0a34SMarco Elver 154*370f0a34SMarco Elver static void __used test_mutex_init(struct test_mutex_data *d) 155*370f0a34SMarco Elver { 156*370f0a34SMarco Elver mutex_init(&d->mtx); 157*370f0a34SMarco Elver d->counter = 0; 158*370f0a34SMarco Elver } 159*370f0a34SMarco Elver 160*370f0a34SMarco Elver static void __used test_mutex_lock(struct test_mutex_data *d) 161*370f0a34SMarco Elver { 162*370f0a34SMarco Elver mutex_lock(&d->mtx); 163*370f0a34SMarco Elver d->counter++; 164*370f0a34SMarco Elver mutex_unlock(&d->mtx); 165*370f0a34SMarco Elver mutex_lock_io(&d->mtx); 166*370f0a34SMarco Elver d->counter++; 167*370f0a34SMarco Elver mutex_unlock(&d->mtx); 168*370f0a34SMarco Elver } 169*370f0a34SMarco Elver 170*370f0a34SMarco Elver static void __used test_mutex_trylock(struct test_mutex_data *d, atomic_t *a) 171*370f0a34SMarco Elver { 172*370f0a34SMarco Elver if (!mutex_lock_interruptible(&d->mtx)) { 173*370f0a34SMarco Elver d->counter++; 174*370f0a34SMarco Elver mutex_unlock(&d->mtx); 175*370f0a34SMarco Elver } 176*370f0a34SMarco Elver if (!mutex_lock_killable(&d->mtx)) { 177*370f0a34SMarco Elver d->counter++; 178*370f0a34SMarco Elver mutex_unlock(&d->mtx); 179*370f0a34SMarco Elver } 180*370f0a34SMarco Elver if (mutex_trylock(&d->mtx)) { 181*370f0a34SMarco Elver d->counter++; 182*370f0a34SMarco Elver mutex_unlock(&d->mtx); 183*370f0a34SMarco Elver } 184*370f0a34SMarco Elver if (atomic_dec_and_mutex_lock(a, &d->mtx)) { 185*370f0a34SMarco Elver d->counter++; 186*370f0a34SMarco Elver mutex_unlock(&d->mtx); 187*370f0a34SMarco Elver } 188*370f0a34SMarco Elver } 189*370f0a34SMarco Elver 190*370f0a34SMarco Elver static void __used test_mutex_assert(struct test_mutex_data *d) 191*370f0a34SMarco Elver { 192*370f0a34SMarco Elver lockdep_assert_held(&d->mtx); 193*370f0a34SMarco Elver d->counter++; 194*370f0a34SMarco Elver } 195*370f0a34SMarco Elver 196*370f0a34SMarco Elver static void __used test_mutex_guard(struct test_mutex_data *d) 197*370f0a34SMarco Elver { 198*370f0a34SMarco Elver guard(mutex)(&d->mtx); 199*370f0a34SMarco Elver d->counter++; 200*370f0a34SMarco Elver } 201*370f0a34SMarco Elver 202*370f0a34SMarco Elver static void __used test_mutex_cond_guard(struct test_mutex_data *d) 203*370f0a34SMarco Elver { 204*370f0a34SMarco Elver scoped_cond_guard(mutex_try, return, &d->mtx) { 205*370f0a34SMarco Elver d->counter++; 206*370f0a34SMarco Elver } 207*370f0a34SMarco Elver scoped_cond_guard(mutex_intr, return, &d->mtx) { 208*370f0a34SMarco Elver d->counter++; 209*370f0a34SMarco Elver } 210*370f0a34SMarco Elver } 211