test_context-analysis.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Compile-only tests for common patterns that should not generate false
  4. * positive errors when compiled with Clang's context analysis.
  5. */
  6. #include <linux/bit_spinlock.h>
  7. #include <linux/build_bug.h>
  8. #include <linux/local_lock.h>
  9. #include <linux/mutex.h>
  10. #include <linux/percpu.h>
  11. #include <linux/rcupdate.h>
  12. #include <linux/rwsem.h>
  13. #include <linux/seqlock.h>
  14. #include <linux/spinlock.h>
  15. #include <linux/srcu.h>
  16. #include <linux/ww_mutex.h>
  17. /*
  18. * Test that helper macros work as expected.
  19. */
  20. static void __used test_common_helpers(void)
  21. {
  22. BUILD_BUG_ON(context_unsafe(3) != 3); /* plain expression */
  23. BUILD_BUG_ON(context_unsafe((void)2; 3) != 3); /* does not swallow semi-colon */
  24. BUILD_BUG_ON(context_unsafe((void)2, 3) != 3); /* does not swallow commas */
  25. context_unsafe(do { } while (0)); /* works with void statements */
  26. }
  27. #define TEST_SPINLOCK_COMMON(class, type, type_init, type_lock, type_unlock, type_trylock, op) \
  28. struct test_##class##_data { \
  29. type lock; \
  30. int counter __guarded_by(&lock); \
  31. int *pointer __pt_guarded_by(&lock); \
  32. }; \
  33. static void __used test_##class##_init(struct test_##class##_data *d) \
  34. { \
  35. guard(type_init)(&d->lock); \
  36. d->counter = 0; \
  37. } \
  38. static void __used test_##class(struct test_##class##_data *d) \
  39. { \
  40. unsigned long flags; \
  41. d->pointer++; \
  42. type_lock(&d->lock); \
  43. op(d->counter); \
  44. op(*d->pointer); \
  45. type_unlock(&d->lock); \
  46. type_lock##_irq(&d->lock); \
  47. op(d->counter); \
  48. op(*d->pointer); \
  49. type_unlock##_irq(&d->lock); \
  50. type_lock##_bh(&d->lock); \
  51. op(d->counter); \
  52. op(*d->pointer); \
  53. type_unlock##_bh(&d->lock); \
  54. type_lock##_irqsave(&d->lock, flags); \
  55. op(d->counter); \
  56. op(*d->pointer); \
  57. type_unlock##_irqrestore(&d->lock, flags); \
  58. } \
  59. static void __used test_##class##_trylock(struct test_##class##_data *d) \
  60. { \
  61. if (type_trylock(&d->lock)) { \
  62. op(d->counter); \
  63. type_unlock(&d->lock); \
  64. } \
  65. } \
  66. static void __used test_##class##_assert(struct test_##class##_data *d) \
  67. { \
  68. lockdep_assert_held(&d->lock); \
  69. op(d->counter); \
  70. } \
  71. static void __used test_##class##_guard(struct test_##class##_data *d) \
  72. { \
  73. { guard(class)(&d->lock); op(d->counter); } \
  74. { guard(class##_irq)(&d->lock); op(d->counter); } \
  75. { guard(class##_irqsave)(&d->lock); op(d->counter); } \
  76. }
  77. #define TEST_OP_RW(x) (x)++
  78. #define TEST_OP_RO(x) ((void)(x))
  79. TEST_SPINLOCK_COMMON(raw_spinlock,
  80. raw_spinlock_t,
  81. raw_spinlock_init,
  82. raw_spin_lock,
  83. raw_spin_unlock,
  84. raw_spin_trylock,
  85. TEST_OP_RW);
  86. static void __used test_raw_spinlock_trylock_extra(struct test_raw_spinlock_data *d)
  87. {
  88. unsigned long flags;
  89. data_race(d->counter++); /* no warning */
  90. if (raw_spin_trylock_irq(&d->lock)) {
  91. d->counter++;
  92. raw_spin_unlock_irq(&d->lock);
  93. }
  94. if (raw_spin_trylock_irqsave(&d->lock, flags)) {
  95. d->counter++;
  96. raw_spin_unlock_irqrestore(&d->lock, flags);
  97. }
  98. scoped_cond_guard(raw_spinlock_try, return, &d->lock) {
  99. d->counter++;
  100. }
  101. }
  102. TEST_SPINLOCK_COMMON(spinlock,
  103. spinlock_t,
  104. spinlock_init,
  105. spin_lock,
  106. spin_unlock,
  107. spin_trylock,
  108. TEST_OP_RW);
  109. static void __used test_spinlock_trylock_extra(struct test_spinlock_data *d)
  110. {
  111. unsigned long flags;
  112. if (spin_trylock_irq(&d->lock)) {
  113. d->counter++;
  114. spin_unlock_irq(&d->lock);
  115. }
  116. if (spin_trylock_irqsave(&d->lock, flags)) {
  117. d->counter++;
  118. spin_unlock_irqrestore(&d->lock, flags);
  119. }
  120. scoped_cond_guard(spinlock_try, return, &d->lock) {
  121. d->counter++;
  122. }
  123. }
  124. TEST_SPINLOCK_COMMON(write_lock,
  125. rwlock_t,
  126. rwlock_init,
  127. write_lock,
  128. write_unlock,
  129. write_trylock,
  130. TEST_OP_RW);
  131. static void __used test_write_trylock_extra(struct test_write_lock_data *d)
  132. {
  133. unsigned long flags;
  134. if (write_trylock_irqsave(&d->lock, flags)) {
  135. d->counter++;
  136. write_unlock_irqrestore(&d->lock, flags);
  137. }
  138. }
  139. TEST_SPINLOCK_COMMON(read_lock,
  140. rwlock_t,
  141. rwlock_init,
  142. read_lock,
  143. read_unlock,
  144. read_trylock,
  145. TEST_OP_RO);
  146. struct test_mutex_data {
  147. struct mutex mtx;
  148. int counter __guarded_by(&mtx);
  149. };
  150. static void __used test_mutex_init(struct test_mutex_data *d)
  151. {
  152. guard(mutex_init)(&d->mtx);
  153. d->counter = 0;
  154. }
  155. static void __used test_mutex_lock(struct test_mutex_data *d)
  156. {
  157. mutex_lock(&d->mtx);
  158. d->counter++;
  159. mutex_unlock(&d->mtx);
  160. mutex_lock_io(&d->mtx);
  161. d->counter++;
  162. mutex_unlock(&d->mtx);
  163. }
  164. static void __used test_mutex_trylock(struct test_mutex_data *d, atomic_t *a)
  165. {
  166. if (!mutex_lock_interruptible(&d->mtx)) {
  167. d->counter++;
  168. mutex_unlock(&d->mtx);
  169. }
  170. if (!mutex_lock_killable(&d->mtx)) {
  171. d->counter++;
  172. mutex_unlock(&d->mtx);
  173. }
  174. if (mutex_trylock(&d->mtx)) {
  175. d->counter++;
  176. mutex_unlock(&d->mtx);
  177. }
  178. if (atomic_dec_and_mutex_lock(a, &d->mtx)) {
  179. d->counter++;
  180. mutex_unlock(&d->mtx);
  181. }
  182. }
  183. static void __used test_mutex_assert(struct test_mutex_data *d)
  184. {
  185. lockdep_assert_held(&d->mtx);
  186. d->counter++;
  187. }
  188. static void __used test_mutex_guard(struct test_mutex_data *d)
  189. {
  190. guard(mutex)(&d->mtx);
  191. d->counter++;
  192. }
  193. static void __used test_mutex_cond_guard(struct test_mutex_data *d)
  194. {
  195. scoped_cond_guard(mutex_try, return, &d->mtx) {
  196. d->counter++;
  197. }
  198. scoped_cond_guard(mutex_intr, return, &d->mtx) {
  199. d->counter++;
  200. }
  201. }
  202. struct test_seqlock_data {
  203. seqlock_t sl;
  204. int counter __guarded_by(&sl);
  205. };
  206. static void __used test_seqlock_init(struct test_seqlock_data *d)
  207. {
  208. guard(seqlock_init)(&d->sl);
  209. d->counter = 0;
  210. }
  211. static void __used test_seqlock_reader(struct test_seqlock_data *d)
  212. {
  213. unsigned int seq;
  214. do {
  215. seq = read_seqbegin(&d->sl);
  216. (void)d->counter;
  217. } while (read_seqretry(&d->sl, seq));
  218. }
  219. static void __used test_seqlock_writer(struct test_seqlock_data *d)
  220. {
  221. unsigned long flags;
  222. write_seqlock(&d->sl);
  223. d->counter++;
  224. write_sequnlock(&d->sl);
  225. write_seqlock_irq(&d->sl);
  226. d->counter++;
  227. write_sequnlock_irq(&d->sl);
  228. write_seqlock_bh(&d->sl);
  229. d->counter++;
  230. write_sequnlock_bh(&d->sl);
  231. write_seqlock_irqsave(&d->sl, flags);
  232. d->counter++;
  233. write_sequnlock_irqrestore(&d->sl, flags);
  234. }
  235. static void __used test_seqlock_scoped(struct test_seqlock_data *d)
  236. {
  237. scoped_seqlock_read (&d->sl, ss_lockless) {
  238. (void)d->counter;
  239. }
  240. }
  241. struct test_rwsem_data {
  242. struct rw_semaphore sem;
  243. int counter __guarded_by(&sem);
  244. };
  245. static void __used test_rwsem_init(struct test_rwsem_data *d)
  246. {
  247. guard(rwsem_init)(&d->sem);
  248. d->counter = 0;
  249. }
  250. static void __used test_rwsem_reader(struct test_rwsem_data *d)
  251. {
  252. down_read(&d->sem);
  253. (void)d->counter;
  254. up_read(&d->sem);
  255. if (down_read_trylock(&d->sem)) {
  256. (void)d->counter;
  257. up_read(&d->sem);
  258. }
  259. }
  260. static void __used test_rwsem_writer(struct test_rwsem_data *d)
  261. {
  262. down_write(&d->sem);
  263. d->counter++;
  264. up_write(&d->sem);
  265. down_write(&d->sem);
  266. d->counter++;
  267. downgrade_write(&d->sem);
  268. (void)d->counter;
  269. up_read(&d->sem);
  270. if (down_write_trylock(&d->sem)) {
  271. d->counter++;
  272. up_write(&d->sem);
  273. }
  274. }
  275. static void __used test_rwsem_assert(struct test_rwsem_data *d)
  276. {
  277. rwsem_assert_held_nolockdep(&d->sem);
  278. d->counter++;
  279. }
  280. static void __used test_rwsem_guard(struct test_rwsem_data *d)
  281. {
  282. { guard(rwsem_read)(&d->sem); (void)d->counter; }
  283. { guard(rwsem_write)(&d->sem); d->counter++; }
  284. }
  285. static void __used test_rwsem_cond_guard(struct test_rwsem_data *d)
  286. {
  287. scoped_cond_guard(rwsem_read_try, return, &d->sem) {
  288. (void)d->counter;
  289. }
  290. scoped_cond_guard(rwsem_write_try, return, &d->sem) {
  291. d->counter++;
  292. }
  293. }
  294. struct test_bit_spinlock_data {
  295. unsigned long bits;
  296. int counter __guarded_by(__bitlock(3, &bits));
  297. };
  298. static void __used test_bit_spin_lock(struct test_bit_spinlock_data *d)
  299. {
  300. /*
  301. * Note, the analysis seems to have false negatives, because it won't
  302. * precisely recognize the bit of the fake __bitlock() token.
  303. */
  304. bit_spin_lock(3, &d->bits);
  305. d->counter++;
  306. bit_spin_unlock(3, &d->bits);
  307. bit_spin_lock(3, &d->bits);
  308. d->counter++;
  309. __bit_spin_unlock(3, &d->bits);
  310. if (bit_spin_trylock(3, &d->bits)) {
  311. d->counter++;
  312. bit_spin_unlock(3, &d->bits);
  313. }
  314. }
  315. /*
  316. * Test that we can mark a variable guarded by RCU, and we can dereference and
  317. * write to the pointer with RCU's primitives.
  318. */
  319. struct test_rcu_data {
  320. long __rcu_guarded *data;
  321. };
  322. static void __used test_rcu_guarded_reader(struct test_rcu_data *d)
  323. {
  324. rcu_read_lock();
  325. (void)rcu_dereference(d->data);
  326. rcu_read_unlock();
  327. rcu_read_lock_bh();
  328. (void)rcu_dereference(d->data);
  329. rcu_read_unlock_bh();
  330. rcu_read_lock_sched();
  331. (void)rcu_dereference(d->data);
  332. rcu_read_unlock_sched();
  333. }
  334. static void __used test_rcu_guard(struct test_rcu_data *d)
  335. {
  336. guard(rcu)();
  337. (void)rcu_dereference(d->data);
  338. }
  339. static void __used test_rcu_guarded_updater(struct test_rcu_data *d)
  340. {
  341. rcu_assign_pointer(d->data, NULL);
  342. RCU_INIT_POINTER(d->data, NULL);
  343. (void)unrcu_pointer(d->data);
  344. }
  345. static void wants_rcu_held(void) __must_hold_shared(RCU) { }
  346. static void wants_rcu_held_bh(void) __must_hold_shared(RCU_BH) { }
  347. static void wants_rcu_held_sched(void) __must_hold_shared(RCU_SCHED) { }
  348. static void __used test_rcu_lock_variants(void)
  349. {
  350. rcu_read_lock();
  351. wants_rcu_held();
  352. rcu_read_unlock();
  353. rcu_read_lock_bh();
  354. wants_rcu_held_bh();
  355. rcu_read_unlock_bh();
  356. rcu_read_lock_sched();
  357. wants_rcu_held_sched();
  358. rcu_read_unlock_sched();
  359. }
  360. static void __used test_rcu_lock_reentrant(void)
  361. {
  362. rcu_read_lock();
  363. rcu_read_lock();
  364. rcu_read_lock_bh();
  365. rcu_read_lock_bh();
  366. rcu_read_lock_sched();
  367. rcu_read_lock_sched();
  368. rcu_read_unlock_sched();
  369. rcu_read_unlock_sched();
  370. rcu_read_unlock_bh();
  371. rcu_read_unlock_bh();
  372. rcu_read_unlock();
  373. rcu_read_unlock();
  374. }
  375. static void __used test_rcu_assert_variants(void)
  376. {
  377. lockdep_assert_in_rcu_read_lock();
  378. wants_rcu_held();
  379. lockdep_assert_in_rcu_read_lock_bh();
  380. wants_rcu_held_bh();
  381. lockdep_assert_in_rcu_read_lock_sched();
  382. wants_rcu_held_sched();
  383. }
  384. struct test_srcu_data {
  385. struct srcu_struct srcu;
  386. long __rcu_guarded *data;
  387. };
  388. static void __used test_srcu(struct test_srcu_data *d)
  389. {
  390. init_srcu_struct(&d->srcu);
  391. int idx = srcu_read_lock(&d->srcu);
  392. long *data = srcu_dereference(d->data, &d->srcu);
  393. (void)data;
  394. srcu_read_unlock(&d->srcu, idx);
  395. rcu_assign_pointer(d->data, NULL);
  396. }
  397. static void __used test_srcu_guard(struct test_srcu_data *d)
  398. {
  399. { guard(srcu)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
  400. { guard(srcu_fast)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
  401. { guard(srcu_fast_notrace)(&d->srcu); (void)srcu_dereference(d->data, &d->srcu); }
  402. }
  403. struct test_local_lock_data {
  404. local_lock_t lock;
  405. int counter __guarded_by(&lock);
  406. };
  407. static DEFINE_PER_CPU(struct test_local_lock_data, test_local_lock_data) = {
  408. .lock = INIT_LOCAL_LOCK(lock),
  409. };
  410. static void __used test_local_lock_init(struct test_local_lock_data *d)
  411. {
  412. guard(local_lock_init)(&d->lock);
  413. d->counter = 0;
  414. }
  415. static void __used test_local_lock(void)
  416. {
  417. unsigned long flags;
  418. local_lock(&test_local_lock_data.lock);
  419. this_cpu_add(test_local_lock_data.counter, 1);
  420. local_unlock(&test_local_lock_data.lock);
  421. local_lock_irq(&test_local_lock_data.lock);
  422. this_cpu_add(test_local_lock_data.counter, 1);
  423. local_unlock_irq(&test_local_lock_data.lock);
  424. local_lock_irqsave(&test_local_lock_data.lock, flags);
  425. this_cpu_add(test_local_lock_data.counter, 1);
  426. local_unlock_irqrestore(&test_local_lock_data.lock, flags);
  427. local_lock_nested_bh(&test_local_lock_data.lock);
  428. this_cpu_add(test_local_lock_data.counter, 1);
  429. local_unlock_nested_bh(&test_local_lock_data.lock);
  430. }
  431. static void __used test_local_lock_guard(void)
  432. {
  433. { guard(local_lock)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
  434. { guard(local_lock_irq)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
  435. { guard(local_lock_irqsave)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
  436. { guard(local_lock_nested_bh)(&test_local_lock_data.lock); this_cpu_add(test_local_lock_data.counter, 1); }
  437. }
  438. struct test_local_trylock_data {
  439. local_trylock_t lock;
  440. int counter __guarded_by(&lock);
  441. };
  442. static DEFINE_PER_CPU(struct test_local_trylock_data, test_local_trylock_data) = {
  443. .lock = INIT_LOCAL_TRYLOCK(lock),
  444. };
  445. static void __used test_local_trylock_init(struct test_local_trylock_data *d)
  446. {
  447. guard(local_trylock_init)(&d->lock);
  448. d->counter = 0;
  449. }
  450. static void __used test_local_trylock(void)
  451. {
  452. local_lock(&test_local_trylock_data.lock);
  453. this_cpu_add(test_local_trylock_data.counter, 1);
  454. local_unlock(&test_local_trylock_data.lock);
  455. if (local_trylock(&test_local_trylock_data.lock)) {
  456. this_cpu_add(test_local_trylock_data.counter, 1);
  457. local_unlock(&test_local_trylock_data.lock);
  458. }
  459. }
  460. static DEFINE_WD_CLASS(ww_class);
  461. struct test_ww_mutex_data {
  462. struct ww_mutex mtx;
  463. int counter __guarded_by(&mtx);
  464. };
  465. static void __used test_ww_mutex_lock_noctx(struct test_ww_mutex_data *d)
  466. {
  467. if (!ww_mutex_lock(&d->mtx, NULL)) {
  468. d->counter++;
  469. ww_mutex_unlock(&d->mtx);
  470. }
  471. if (!ww_mutex_lock_interruptible(&d->mtx, NULL)) {
  472. d->counter++;
  473. ww_mutex_unlock(&d->mtx);
  474. }
  475. if (ww_mutex_trylock(&d->mtx, NULL)) {
  476. d->counter++;
  477. ww_mutex_unlock(&d->mtx);
  478. }
  479. ww_mutex_lock_slow(&d->mtx, NULL);
  480. d->counter++;
  481. ww_mutex_unlock(&d->mtx);
  482. ww_mutex_destroy(&d->mtx);
  483. }
  484. static void __used test_ww_mutex_lock_ctx(struct test_ww_mutex_data *d)
  485. {
  486. struct ww_acquire_ctx ctx;
  487. ww_acquire_init(&ctx, &ww_class);
  488. if (!ww_mutex_lock(&d->mtx, &ctx)) {
  489. d->counter++;
  490. ww_mutex_unlock(&d->mtx);
  491. }
  492. if (!ww_mutex_lock_interruptible(&d->mtx, &ctx)) {
  493. d->counter++;
  494. ww_mutex_unlock(&d->mtx);
  495. }
  496. if (ww_mutex_trylock(&d->mtx, &ctx)) {
  497. d->counter++;
  498. ww_mutex_unlock(&d->mtx);
  499. }
  500. ww_mutex_lock_slow(&d->mtx, &ctx);
  501. d->counter++;
  502. ww_mutex_unlock(&d->mtx);
  503. ww_acquire_done(&ctx);
  504. ww_acquire_fini(&ctx);
  505. ww_mutex_destroy(&d->mtx);
  506. }