1/* @title: Lock Validator Assertions */
2#pragma once
3#include <compiler/core.h>
4#include <sync/lock_general.h>
5#include <sync/mutex.h>
6#include <sync/mutex_simple.h>
7#include <sync/qspinlock.h>
8#include <sync/rwlock.h>
9#include <sync/spinlock.h>
10
11/* Assert that the current thread holds the lock. When DEBUG_LOCK_CHK
12 * is on and the lock is checked, this actually gets to use
13 * the provable engine. But otherwise, it falls back to a naive
14 * read of the lock word. RWLOCK needs
15 * RWLOCK_READ/RWLOCK_WRITE, which is why we have
16 * _1 and _2, so all locks regardless of type can funnel through
17 * this callsite */
18
19#define LOCK_CHK_ASSERT_HELD_1(l) \
20 cc_generic((l), struct spinlock * : spinlock_assert_held_full, \
21 struct qspinlock * : qspin_assert_held_full, \
22 struct mutex * : mutex_assert_held_full, \
23 struct mutex_simple * : mutex_simple_assert_held_full)( \
24 (l), LOCK_CHK_SITE_HERE())
25
26#define LOCK_CHK_ASSERT_HELD_2(l, mode) \
27 cc_generic((l), struct rwlock * : rwlock_assert_held_full)( \
28 (l), (mode), LOCK_CHK_SITE_HERE())
29
30#define LOCK_CHK_ASSERT_HELD(...) PP_CALL(LOCK_CHK_ASSERT_HELD, __VA_ARGS__)
31
32/* Inverse of above */
33#define LOCK_CHK_ASSERT_NOT_HELD(l) \
34 cc_generic((l), struct spinlock * : spinlock_assert_not_held_full, \
35 struct qspinlock * : qspin_assert_not_held_full, \
36 struct mutex * : mutex_assert_not_held_full, \
37 struct mutex_simple * : mutex_simple_assert_not_held_full, \
38 struct rwlock * : rwlock_assert_not_held_full)( \
39 (l), LOCK_CHK_SITE_HERE())
40
41#define LOCK_CHK_ASSERT_HELD_STATE(l, m) \
42 do { \
43 if ((m) == LOCK_HELD) { \
44 LOCK_CHK_ASSERT_HELD((l)); \
45 } else if ((m) == LOCK_NOT_HELD) { \
46 LOCK_CHK_ASSERT_NOT_HELD((l)); \
47 } else { \
48 unreachable("mode %d", (m)); \
49 } \
50 } while (0)
51