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*f16a802dSMarco Elver #include <linux/spinlock.h> 99b00c160SMarco Elver 109b00c160SMarco Elver /* 119b00c160SMarco Elver * Test that helper macros work as expected. 129b00c160SMarco Elver */ 139b00c160SMarco Elver static void __used test_common_helpers(void) 149b00c160SMarco Elver { 159b00c160SMarco Elver BUILD_BUG_ON(context_unsafe(3) != 3); /* plain expression */ 169b00c160SMarco Elver BUILD_BUG_ON(context_unsafe((void)2; 3) != 3); /* does not swallow semi-colon */ 179b00c160SMarco Elver BUILD_BUG_ON(context_unsafe((void)2, 3) != 3); /* does not swallow commas */ 189b00c160SMarco Elver context_unsafe(do { } while (0)); /* works with void statements */ 199b00c160SMarco Elver } 20*f16a802dSMarco Elver 21*f16a802dSMarco Elver #define TEST_SPINLOCK_COMMON(class, type, type_init, type_lock, type_unlock, type_trylock, op) \ 22*f16a802dSMarco Elver struct test_##class##_data { \ 23*f16a802dSMarco Elver type lock; \ 24*f16a802dSMarco Elver int counter __guarded_by(&lock); \ 25*f16a802dSMarco Elver int *pointer __pt_guarded_by(&lock); \ 26*f16a802dSMarco Elver }; \ 27*f16a802dSMarco Elver static void __used test_##class##_init(struct test_##class##_data *d) \ 28*f16a802dSMarco Elver { \ 29*f16a802dSMarco Elver type_init(&d->lock); \ 30*f16a802dSMarco Elver d->counter = 0; \ 31*f16a802dSMarco Elver } \ 32*f16a802dSMarco Elver static void __used test_##class(struct test_##class##_data *d) \ 33*f16a802dSMarco Elver { \ 34*f16a802dSMarco Elver unsigned long flags; \ 35*f16a802dSMarco Elver d->pointer++; \ 36*f16a802dSMarco Elver type_lock(&d->lock); \ 37*f16a802dSMarco Elver op(d->counter); \ 38*f16a802dSMarco Elver op(*d->pointer); \ 39*f16a802dSMarco Elver type_unlock(&d->lock); \ 40*f16a802dSMarco Elver type_lock##_irq(&d->lock); \ 41*f16a802dSMarco Elver op(d->counter); \ 42*f16a802dSMarco Elver op(*d->pointer); \ 43*f16a802dSMarco Elver type_unlock##_irq(&d->lock); \ 44*f16a802dSMarco Elver type_lock##_bh(&d->lock); \ 45*f16a802dSMarco Elver op(d->counter); \ 46*f16a802dSMarco Elver op(*d->pointer); \ 47*f16a802dSMarco Elver type_unlock##_bh(&d->lock); \ 48*f16a802dSMarco Elver type_lock##_irqsave(&d->lock, flags); \ 49*f16a802dSMarco Elver op(d->counter); \ 50*f16a802dSMarco Elver op(*d->pointer); \ 51*f16a802dSMarco Elver type_unlock##_irqrestore(&d->lock, flags); \ 52*f16a802dSMarco Elver } \ 53*f16a802dSMarco Elver static void __used test_##class##_trylock(struct test_##class##_data *d) \ 54*f16a802dSMarco Elver { \ 55*f16a802dSMarco Elver if (type_trylock(&d->lock)) { \ 56*f16a802dSMarco Elver op(d->counter); \ 57*f16a802dSMarco Elver type_unlock(&d->lock); \ 58*f16a802dSMarco Elver } \ 59*f16a802dSMarco Elver } \ 60*f16a802dSMarco Elver static void __used test_##class##_assert(struct test_##class##_data *d) \ 61*f16a802dSMarco Elver { \ 62*f16a802dSMarco Elver lockdep_assert_held(&d->lock); \ 63*f16a802dSMarco Elver op(d->counter); \ 64*f16a802dSMarco Elver } \ 65*f16a802dSMarco Elver static void __used test_##class##_guard(struct test_##class##_data *d) \ 66*f16a802dSMarco Elver { \ 67*f16a802dSMarco Elver { guard(class)(&d->lock); op(d->counter); } \ 68*f16a802dSMarco Elver { guard(class##_irq)(&d->lock); op(d->counter); } \ 69*f16a802dSMarco Elver { guard(class##_irqsave)(&d->lock); op(d->counter); } \ 70*f16a802dSMarco Elver } 71*f16a802dSMarco Elver 72*f16a802dSMarco Elver #define TEST_OP_RW(x) (x)++ 73*f16a802dSMarco Elver #define TEST_OP_RO(x) ((void)(x)) 74*f16a802dSMarco Elver 75*f16a802dSMarco Elver TEST_SPINLOCK_COMMON(raw_spinlock, 76*f16a802dSMarco Elver raw_spinlock_t, 77*f16a802dSMarco Elver raw_spin_lock_init, 78*f16a802dSMarco Elver raw_spin_lock, 79*f16a802dSMarco Elver raw_spin_unlock, 80*f16a802dSMarco Elver raw_spin_trylock, 81*f16a802dSMarco Elver TEST_OP_RW); 82*f16a802dSMarco Elver static void __used test_raw_spinlock_trylock_extra(struct test_raw_spinlock_data *d) 83*f16a802dSMarco Elver { 84*f16a802dSMarco Elver unsigned long flags; 85*f16a802dSMarco Elver 86*f16a802dSMarco Elver if (raw_spin_trylock_irq(&d->lock)) { 87*f16a802dSMarco Elver d->counter++; 88*f16a802dSMarco Elver raw_spin_unlock_irq(&d->lock); 89*f16a802dSMarco Elver } 90*f16a802dSMarco Elver if (raw_spin_trylock_irqsave(&d->lock, flags)) { 91*f16a802dSMarco Elver d->counter++; 92*f16a802dSMarco Elver raw_spin_unlock_irqrestore(&d->lock, flags); 93*f16a802dSMarco Elver } 94*f16a802dSMarco Elver scoped_cond_guard(raw_spinlock_try, return, &d->lock) { 95*f16a802dSMarco Elver d->counter++; 96*f16a802dSMarco Elver } 97*f16a802dSMarco Elver } 98*f16a802dSMarco Elver 99*f16a802dSMarco Elver TEST_SPINLOCK_COMMON(spinlock, 100*f16a802dSMarco Elver spinlock_t, 101*f16a802dSMarco Elver spin_lock_init, 102*f16a802dSMarco Elver spin_lock, 103*f16a802dSMarco Elver spin_unlock, 104*f16a802dSMarco Elver spin_trylock, 105*f16a802dSMarco Elver TEST_OP_RW); 106*f16a802dSMarco Elver static void __used test_spinlock_trylock_extra(struct test_spinlock_data *d) 107*f16a802dSMarco Elver { 108*f16a802dSMarco Elver unsigned long flags; 109*f16a802dSMarco Elver 110*f16a802dSMarco Elver if (spin_trylock_irq(&d->lock)) { 111*f16a802dSMarco Elver d->counter++; 112*f16a802dSMarco Elver spin_unlock_irq(&d->lock); 113*f16a802dSMarco Elver } 114*f16a802dSMarco Elver if (spin_trylock_irqsave(&d->lock, flags)) { 115*f16a802dSMarco Elver d->counter++; 116*f16a802dSMarco Elver spin_unlock_irqrestore(&d->lock, flags); 117*f16a802dSMarco Elver } 118*f16a802dSMarco Elver scoped_cond_guard(spinlock_try, return, &d->lock) { 119*f16a802dSMarco Elver d->counter++; 120*f16a802dSMarco Elver } 121*f16a802dSMarco Elver } 122*f16a802dSMarco Elver 123*f16a802dSMarco Elver TEST_SPINLOCK_COMMON(write_lock, 124*f16a802dSMarco Elver rwlock_t, 125*f16a802dSMarco Elver rwlock_init, 126*f16a802dSMarco Elver write_lock, 127*f16a802dSMarco Elver write_unlock, 128*f16a802dSMarco Elver write_trylock, 129*f16a802dSMarco Elver TEST_OP_RW); 130*f16a802dSMarco Elver static void __used test_write_trylock_extra(struct test_write_lock_data *d) 131*f16a802dSMarco Elver { 132*f16a802dSMarco Elver unsigned long flags; 133*f16a802dSMarco Elver 134*f16a802dSMarco Elver if (write_trylock_irqsave(&d->lock, flags)) { 135*f16a802dSMarco Elver d->counter++; 136*f16a802dSMarco Elver write_unlock_irqrestore(&d->lock, flags); 137*f16a802dSMarco Elver } 138*f16a802dSMarco Elver } 139*f16a802dSMarco Elver 140*f16a802dSMarco Elver TEST_SPINLOCK_COMMON(read_lock, 141*f16a802dSMarco Elver rwlock_t, 142*f16a802dSMarco Elver rwlock_init, 143*f16a802dSMarco Elver read_lock, 144*f16a802dSMarco Elver read_unlock, 145*f16a802dSMarco Elver read_trylock, 146*f16a802dSMarco Elver TEST_OP_RO); 147