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> 8370f0a34SMarco Elver #include <linux/mutex.h> 9*8f8a55f4SMarco Elver #include <linux/seqlock.h> 10f16a802dSMarco Elver #include <linux/spinlock.h> 119b00c160SMarco Elver 129b00c160SMarco Elver /* 139b00c160SMarco Elver * Test that helper macros work as expected. 149b00c160SMarco Elver */ 159b00c160SMarco Elver static void __used test_common_helpers(void) 169b00c160SMarco Elver { 179b00c160SMarco Elver BUILD_BUG_ON(context_unsafe(3) != 3); /* plain expression */ 189b00c160SMarco Elver BUILD_BUG_ON(context_unsafe((void)2; 3) != 3); /* does not swallow semi-colon */ 199b00c160SMarco Elver BUILD_BUG_ON(context_unsafe((void)2, 3) != 3); /* does not swallow commas */ 209b00c160SMarco Elver context_unsafe(do { } while (0)); /* works with void statements */ 219b00c160SMarco Elver } 22f16a802dSMarco Elver 23f16a802dSMarco Elver #define TEST_SPINLOCK_COMMON(class, type, type_init, type_lock, type_unlock, type_trylock, op) \ 24f16a802dSMarco Elver struct test_##class##_data { \ 25f16a802dSMarco Elver type lock; \ 26f16a802dSMarco Elver int counter __guarded_by(&lock); \ 27f16a802dSMarco Elver int *pointer __pt_guarded_by(&lock); \ 28f16a802dSMarco Elver }; \ 29f16a802dSMarco Elver static void __used test_##class##_init(struct test_##class##_data *d) \ 30f16a802dSMarco Elver { \ 31f16a802dSMarco Elver type_init(&d->lock); \ 32f16a802dSMarco Elver d->counter = 0; \ 33f16a802dSMarco Elver } \ 34f16a802dSMarco Elver static void __used test_##class(struct test_##class##_data *d) \ 35f16a802dSMarco Elver { \ 36f16a802dSMarco Elver unsigned long flags; \ 37f16a802dSMarco Elver d->pointer++; \ 38f16a802dSMarco Elver type_lock(&d->lock); \ 39f16a802dSMarco Elver op(d->counter); \ 40f16a802dSMarco Elver op(*d->pointer); \ 41f16a802dSMarco Elver type_unlock(&d->lock); \ 42f16a802dSMarco Elver type_lock##_irq(&d->lock); \ 43f16a802dSMarco Elver op(d->counter); \ 44f16a802dSMarco Elver op(*d->pointer); \ 45f16a802dSMarco Elver type_unlock##_irq(&d->lock); \ 46f16a802dSMarco Elver type_lock##_bh(&d->lock); \ 47f16a802dSMarco Elver op(d->counter); \ 48f16a802dSMarco Elver op(*d->pointer); \ 49f16a802dSMarco Elver type_unlock##_bh(&d->lock); \ 50f16a802dSMarco Elver type_lock##_irqsave(&d->lock, flags); \ 51f16a802dSMarco Elver op(d->counter); \ 52f16a802dSMarco Elver op(*d->pointer); \ 53f16a802dSMarco Elver type_unlock##_irqrestore(&d->lock, flags); \ 54f16a802dSMarco Elver } \ 55f16a802dSMarco Elver static void __used test_##class##_trylock(struct test_##class##_data *d) \ 56f16a802dSMarco Elver { \ 57f16a802dSMarco Elver if (type_trylock(&d->lock)) { \ 58f16a802dSMarco Elver op(d->counter); \ 59f16a802dSMarco Elver type_unlock(&d->lock); \ 60f16a802dSMarco Elver } \ 61f16a802dSMarco Elver } \ 62f16a802dSMarco Elver static void __used test_##class##_assert(struct test_##class##_data *d) \ 63f16a802dSMarco Elver { \ 64f16a802dSMarco Elver lockdep_assert_held(&d->lock); \ 65f16a802dSMarco Elver op(d->counter); \ 66f16a802dSMarco Elver } \ 67f16a802dSMarco Elver static void __used test_##class##_guard(struct test_##class##_data *d) \ 68f16a802dSMarco Elver { \ 69f16a802dSMarco Elver { guard(class)(&d->lock); op(d->counter); } \ 70f16a802dSMarco Elver { guard(class##_irq)(&d->lock); op(d->counter); } \ 71f16a802dSMarco Elver { guard(class##_irqsave)(&d->lock); op(d->counter); } \ 72f16a802dSMarco Elver } 73f16a802dSMarco Elver 74f16a802dSMarco Elver #define TEST_OP_RW(x) (x)++ 75f16a802dSMarco Elver #define TEST_OP_RO(x) ((void)(x)) 76f16a802dSMarco Elver 77f16a802dSMarco Elver TEST_SPINLOCK_COMMON(raw_spinlock, 78f16a802dSMarco Elver raw_spinlock_t, 79f16a802dSMarco Elver raw_spin_lock_init, 80f16a802dSMarco Elver raw_spin_lock, 81f16a802dSMarco Elver raw_spin_unlock, 82f16a802dSMarco Elver raw_spin_trylock, 83f16a802dSMarco Elver TEST_OP_RW); 84f16a802dSMarco Elver static void __used test_raw_spinlock_trylock_extra(struct test_raw_spinlock_data *d) 85f16a802dSMarco Elver { 86f16a802dSMarco Elver unsigned long flags; 87f16a802dSMarco Elver 88f16a802dSMarco Elver if (raw_spin_trylock_irq(&d->lock)) { 89f16a802dSMarco Elver d->counter++; 90f16a802dSMarco Elver raw_spin_unlock_irq(&d->lock); 91f16a802dSMarco Elver } 92f16a802dSMarco Elver if (raw_spin_trylock_irqsave(&d->lock, flags)) { 93f16a802dSMarco Elver d->counter++; 94f16a802dSMarco Elver raw_spin_unlock_irqrestore(&d->lock, flags); 95f16a802dSMarco Elver } 96f16a802dSMarco Elver scoped_cond_guard(raw_spinlock_try, return, &d->lock) { 97f16a802dSMarco Elver d->counter++; 98f16a802dSMarco Elver } 99f16a802dSMarco Elver } 100f16a802dSMarco Elver 101f16a802dSMarco Elver TEST_SPINLOCK_COMMON(spinlock, 102f16a802dSMarco Elver spinlock_t, 103f16a802dSMarco Elver spin_lock_init, 104f16a802dSMarco Elver spin_lock, 105f16a802dSMarco Elver spin_unlock, 106f16a802dSMarco Elver spin_trylock, 107f16a802dSMarco Elver TEST_OP_RW); 108f16a802dSMarco Elver static void __used test_spinlock_trylock_extra(struct test_spinlock_data *d) 109f16a802dSMarco Elver { 110f16a802dSMarco Elver unsigned long flags; 111f16a802dSMarco Elver 112f16a802dSMarco Elver if (spin_trylock_irq(&d->lock)) { 113f16a802dSMarco Elver d->counter++; 114f16a802dSMarco Elver spin_unlock_irq(&d->lock); 115f16a802dSMarco Elver } 116f16a802dSMarco Elver if (spin_trylock_irqsave(&d->lock, flags)) { 117f16a802dSMarco Elver d->counter++; 118f16a802dSMarco Elver spin_unlock_irqrestore(&d->lock, flags); 119f16a802dSMarco Elver } 120f16a802dSMarco Elver scoped_cond_guard(spinlock_try, return, &d->lock) { 121f16a802dSMarco Elver d->counter++; 122f16a802dSMarco Elver } 123f16a802dSMarco Elver } 124f16a802dSMarco Elver 125f16a802dSMarco Elver TEST_SPINLOCK_COMMON(write_lock, 126f16a802dSMarco Elver rwlock_t, 127f16a802dSMarco Elver rwlock_init, 128f16a802dSMarco Elver write_lock, 129f16a802dSMarco Elver write_unlock, 130f16a802dSMarco Elver write_trylock, 131f16a802dSMarco Elver TEST_OP_RW); 132f16a802dSMarco Elver static void __used test_write_trylock_extra(struct test_write_lock_data *d) 133f16a802dSMarco Elver { 134f16a802dSMarco Elver unsigned long flags; 135f16a802dSMarco Elver 136f16a802dSMarco Elver if (write_trylock_irqsave(&d->lock, flags)) { 137f16a802dSMarco Elver d->counter++; 138f16a802dSMarco Elver write_unlock_irqrestore(&d->lock, flags); 139f16a802dSMarco Elver } 140f16a802dSMarco Elver } 141f16a802dSMarco Elver 142f16a802dSMarco Elver TEST_SPINLOCK_COMMON(read_lock, 143f16a802dSMarco Elver rwlock_t, 144f16a802dSMarco Elver rwlock_init, 145f16a802dSMarco Elver read_lock, 146f16a802dSMarco Elver read_unlock, 147f16a802dSMarco Elver read_trylock, 148f16a802dSMarco Elver TEST_OP_RO); 149370f0a34SMarco Elver 150370f0a34SMarco Elver struct test_mutex_data { 151370f0a34SMarco Elver struct mutex mtx; 152370f0a34SMarco Elver int counter __guarded_by(&mtx); 153370f0a34SMarco Elver }; 154370f0a34SMarco Elver 155370f0a34SMarco Elver static void __used test_mutex_init(struct test_mutex_data *d) 156370f0a34SMarco Elver { 157370f0a34SMarco Elver mutex_init(&d->mtx); 158370f0a34SMarco Elver d->counter = 0; 159370f0a34SMarco Elver } 160370f0a34SMarco Elver 161370f0a34SMarco Elver static void __used test_mutex_lock(struct test_mutex_data *d) 162370f0a34SMarco Elver { 163370f0a34SMarco Elver mutex_lock(&d->mtx); 164370f0a34SMarco Elver d->counter++; 165370f0a34SMarco Elver mutex_unlock(&d->mtx); 166370f0a34SMarco Elver mutex_lock_io(&d->mtx); 167370f0a34SMarco Elver d->counter++; 168370f0a34SMarco Elver mutex_unlock(&d->mtx); 169370f0a34SMarco Elver } 170370f0a34SMarco Elver 171370f0a34SMarco Elver static void __used test_mutex_trylock(struct test_mutex_data *d, atomic_t *a) 172370f0a34SMarco Elver { 173370f0a34SMarco Elver if (!mutex_lock_interruptible(&d->mtx)) { 174370f0a34SMarco Elver d->counter++; 175370f0a34SMarco Elver mutex_unlock(&d->mtx); 176370f0a34SMarco Elver } 177370f0a34SMarco Elver if (!mutex_lock_killable(&d->mtx)) { 178370f0a34SMarco Elver d->counter++; 179370f0a34SMarco Elver mutex_unlock(&d->mtx); 180370f0a34SMarco Elver } 181370f0a34SMarco Elver if (mutex_trylock(&d->mtx)) { 182370f0a34SMarco Elver d->counter++; 183370f0a34SMarco Elver mutex_unlock(&d->mtx); 184370f0a34SMarco Elver } 185370f0a34SMarco Elver if (atomic_dec_and_mutex_lock(a, &d->mtx)) { 186370f0a34SMarco Elver d->counter++; 187370f0a34SMarco Elver mutex_unlock(&d->mtx); 188370f0a34SMarco Elver } 189370f0a34SMarco Elver } 190370f0a34SMarco Elver 191370f0a34SMarco Elver static void __used test_mutex_assert(struct test_mutex_data *d) 192370f0a34SMarco Elver { 193370f0a34SMarco Elver lockdep_assert_held(&d->mtx); 194370f0a34SMarco Elver d->counter++; 195370f0a34SMarco Elver } 196370f0a34SMarco Elver 197370f0a34SMarco Elver static void __used test_mutex_guard(struct test_mutex_data *d) 198370f0a34SMarco Elver { 199370f0a34SMarco Elver guard(mutex)(&d->mtx); 200370f0a34SMarco Elver d->counter++; 201370f0a34SMarco Elver } 202370f0a34SMarco Elver 203370f0a34SMarco Elver static void __used test_mutex_cond_guard(struct test_mutex_data *d) 204370f0a34SMarco Elver { 205370f0a34SMarco Elver scoped_cond_guard(mutex_try, return, &d->mtx) { 206370f0a34SMarco Elver d->counter++; 207370f0a34SMarco Elver } 208370f0a34SMarco Elver scoped_cond_guard(mutex_intr, return, &d->mtx) { 209370f0a34SMarco Elver d->counter++; 210370f0a34SMarco Elver } 211370f0a34SMarco Elver } 212*8f8a55f4SMarco Elver 213*8f8a55f4SMarco Elver struct test_seqlock_data { 214*8f8a55f4SMarco Elver seqlock_t sl; 215*8f8a55f4SMarco Elver int counter __guarded_by(&sl); 216*8f8a55f4SMarco Elver }; 217*8f8a55f4SMarco Elver 218*8f8a55f4SMarco Elver static void __used test_seqlock_init(struct test_seqlock_data *d) 219*8f8a55f4SMarco Elver { 220*8f8a55f4SMarco Elver seqlock_init(&d->sl); 221*8f8a55f4SMarco Elver d->counter = 0; 222*8f8a55f4SMarco Elver } 223*8f8a55f4SMarco Elver 224*8f8a55f4SMarco Elver static void __used test_seqlock_reader(struct test_seqlock_data *d) 225*8f8a55f4SMarco Elver { 226*8f8a55f4SMarco Elver unsigned int seq; 227*8f8a55f4SMarco Elver 228*8f8a55f4SMarco Elver do { 229*8f8a55f4SMarco Elver seq = read_seqbegin(&d->sl); 230*8f8a55f4SMarco Elver (void)d->counter; 231*8f8a55f4SMarco Elver } while (read_seqretry(&d->sl, seq)); 232*8f8a55f4SMarco Elver } 233*8f8a55f4SMarco Elver 234*8f8a55f4SMarco Elver static void __used test_seqlock_writer(struct test_seqlock_data *d) 235*8f8a55f4SMarco Elver { 236*8f8a55f4SMarco Elver unsigned long flags; 237*8f8a55f4SMarco Elver 238*8f8a55f4SMarco Elver write_seqlock(&d->sl); 239*8f8a55f4SMarco Elver d->counter++; 240*8f8a55f4SMarco Elver write_sequnlock(&d->sl); 241*8f8a55f4SMarco Elver 242*8f8a55f4SMarco Elver write_seqlock_irq(&d->sl); 243*8f8a55f4SMarco Elver d->counter++; 244*8f8a55f4SMarco Elver write_sequnlock_irq(&d->sl); 245*8f8a55f4SMarco Elver 246*8f8a55f4SMarco Elver write_seqlock_bh(&d->sl); 247*8f8a55f4SMarco Elver d->counter++; 248*8f8a55f4SMarco Elver write_sequnlock_bh(&d->sl); 249*8f8a55f4SMarco Elver 250*8f8a55f4SMarco Elver write_seqlock_irqsave(&d->sl, flags); 251*8f8a55f4SMarco Elver d->counter++; 252*8f8a55f4SMarco Elver write_sequnlock_irqrestore(&d->sl, flags); 253*8f8a55f4SMarco Elver } 254*8f8a55f4SMarco Elver 255*8f8a55f4SMarco Elver static void __used test_seqlock_scoped(struct test_seqlock_data *d) 256*8f8a55f4SMarco Elver { 257*8f8a55f4SMarco Elver scoped_seqlock_read (&d->sl, ss_lockless) { 258*8f8a55f4SMarco Elver (void)d->counter; 259*8f8a55f4SMarco Elver } 260*8f8a55f4SMarco Elver } 261