| 1 | /* @title: Simple Mutex */ |
| 2 | #pragma once |
| 3 | #include <stdbool.h> |
| 4 | #include <sync/lock_chk_types.h> |
| 5 | #include <sync/spinlock.h> |
| 6 | #include <thread/queue.h> |
| 7 | |
| 8 | struct mutex_simple { |
| 9 | struct thread *owner; |
| 10 | struct thread_queue waiters; |
| 11 | struct spinlock lock; |
| 12 | |
| 13 | #ifdef DEBUG_LOCK_CHK |
| 14 | struct lock_chk_lock chk; |
| 15 | #endif /* DEBUG_LOCK_CHK */ |
| 16 | }; |
| 17 | |
| 18 | void mutex_simple_init_chk_internal(struct mutex_simple *m, |
| 19 | const struct lock_chk_class *class, |
| 20 | enum lock_chk_flags flags); |
| 21 | void mutex_simple_set_chk_flags(struct mutex_simple *m, |
| 22 | enum lock_chk_flags flags); |
| 23 | void mutex_simple_reinit_chk(struct mutex_simple *m, |
| 24 | const struct lock_chk_class *class, |
| 25 | enum lock_chk_flags flags); |
| 26 | void mutex_simple_lock_internal(struct mutex_simple *m, |
| 27 | const struct lock_chk_site *site); |
| 28 | void mutex_simple_unlock_internal(struct mutex_simple *m, |
| 29 | const struct lock_chk_site *site); |
| 30 | void mutex_simple_lock_subclass_internal(struct mutex_simple *m, |
| 31 | uint8_t subclass, |
| 32 | const struct lock_chk_site *site); |
| 33 | bool mutex_simple_locked(struct mutex_simple *m); |
| 34 | struct thread *mutex_simple_get_owner(struct mutex_simple *m); |
| 35 | void mutex_simple_assert_held_internal(struct mutex_simple *m, |
| 36 | const struct lock_chk_site *site); |
| 37 | void mutex_simple_assert_not_held_internal(struct mutex_simple *m, |
| 38 | const struct lock_chk_site *site); |
| 39 | |
| 40 | #ifdef DEBUG_LOCK_CHK |
| 41 | |
| 42 | #define MUTEX_SIMPLE_INIT_CHK(id_, class_, flags_) \ |
| 43 | ((struct mutex_simple) { \ |
| 44 | .owner = NULL, \ |
| 45 | .waiters = \ |
| 46 | { \ |
| 47 | .list = LIST_HEAD_INIT((id_).waiters.list), \ |
| 48 | .lock = SPINLOCK_INIT_CHK(NULL, LOCK_UNCHKD), \ |
| 49 | }, \ |
| 50 | .lock = SPINLOCK_INIT_CHK(NULL, LOCK_UNCHKD), \ |
| 51 | .chk = LOCK_CHK_LOCK_VALUE_INIT((class_), (flags_)), \ |
| 52 | }) |
| 53 | |
| 54 | #define mutex_simple_init_chk(mtx_, class_, flags_) \ |
| 55 | mutex_simple_init_chk_internal((mtx_), (class_), (flags_)) |
| 56 | #define mutex_simple_init_auto_internal(mtx_, flags_) \ |
| 57 | do { \ |
| 58 | static const struct lock_chk_class __auto_class = { \ |
| 59 | .name = #mtx_, \ |
| 60 | .file = __RELFILE__, \ |
| 61 | .line = __LINE__, \ |
| 62 | }; \ |
| 63 | mutex_simple_init_chk_internal((mtx_), &__auto_class, (flags_)); \ |
| 64 | } while (0) |
| 65 | |
| 66 | #else /* !defined(DEBUG_LOCK_CHK) */ |
| 67 | |
| 68 | #define MUTEX_SIMPLE_INIT_CHK(id_, class_, flags_) \ |
| 69 | ((struct mutex_simple) { \ |
| 70 | .owner = NULL, \ |
| 71 | .waiters = \ |
| 72 | { \ |
| 73 | .list = LIST_HEAD_INIT((id_).waiters.list), \ |
| 74 | .lock = SPINLOCK_INIT_CHK(NULL, LOCK_UNCHKD), \ |
| 75 | }, \ |
| 76 | .lock = SPINLOCK_INIT_CHK(NULL, LOCK_UNCHKD), \ |
| 77 | }) |
| 78 | |
| 79 | #define mutex_simple_init_chk(mtx_, class_, flags_) \ |
| 80 | mutex_simple_init_chk_internal((mtx_), NULL, LOCK_UNCHKD) |
| 81 | #define mutex_simple_init_auto_internal(mtx_, flags_) \ |
| 82 | mutex_simple_init_chk_internal((mtx_), NULL, LOCK_UNCHKD) |
| 83 | |
| 84 | #endif /* DEBUG_LOCK_CHK */ |
| 85 | |
| 86 | #define MUTEX_SIMPLE_INIT(id_) \ |
| 87 | MUTEX_SIMPLE_INIT_CHK((id_), NULL, LOCK_CHKD_FULL) |
| 88 | #define MUTEX_SIMPLE_DEFINE(id) struct mutex_simple id = MUTEX_SIMPLE_INIT(id) |
| 89 | #define MUTEX_SIMPLE_DEFINE_CHK(id, class_, flags_) \ |
| 90 | struct mutex_simple id = MUTEX_SIMPLE_INIT_CHK((id), (class_), (flags_)) |
| 91 | |
| 92 | #define mutex_simple_init_1(mtx_) \ |
| 93 | mutex_simple_init_auto_internal((mtx_), LOCK_CHKD_FULL) |
| 94 | #define mutex_simple_init_2(mtx_, flags_) \ |
| 95 | mutex_simple_init_auto_internal((mtx_), (flags_)) |
| 96 | #define mutex_simple_init(...) \ |
| 97 | _DISPATCH(mutex_simple_init, PP_NARG(__VA_ARGS__))(__VA_ARGS__) |
| 98 | |
| 99 | #define mutex_simple_lock(m_) \ |
| 100 | mutex_simple_lock_internal((m_), LOCK_CHK_SITE_HERE()) |
| 101 | #define mutex_simple_unlock(m_) \ |
| 102 | mutex_simple_unlock_internal((m_), LOCK_CHK_SITE_HERE()) |
| 103 | #define mutex_simple_lock_subclass(m_, subclass_) \ |
| 104 | mutex_simple_lock_subclass_internal((m_), (subclass_), LOCK_CHK_SITE_HERE()) |
| 105 | |
| 106 | #define MUTEX_SIMPLE_ASSERT_HELD(m) \ |
| 107 | mutex_simple_assert_held_internal((m), LOCK_CHK_SITE_HERE()) |
| 108 | #define MUTEX_SIMPLE_ASSERT_NOT_HELD(m) \ |
| 109 | mutex_simple_assert_not_held_internal((m), LOCK_CHK_SITE_HERE()) |
| 110 | |