1/* @title: Lock Validation */
2#pragma once
3#include <compiler.h>
4#include <sch/irql.h>
5#include <stdatomic.h>
6#include <stdbool.h>
7#include <stddef.h>
8#include <stdint.h>
9
10struct lock_chk_class;
11struct lock_chk_lock;
12
13enum lock_chk_flags : uint8_t {
14 LOCK_UNCHKD = 0,
15 LOCK_CHKD_ORDER = 1 << 0,
16 LOCK_CHKD_THREAD = 1 << 1,
17 LOCK_CHKD_FULL = LOCK_CHKD_ORDER | LOCK_CHKD_THREAD,
18};
19
20enum lock_chk_type : uint8_t {
21 LOCK_CHK_TYPE_SPIN,
22 LOCK_CHK_TYPE_QSPIN,
23 LOCK_CHK_TYPE_MUTEX,
24 LOCK_CHK_TYPE_MUTEX_SIMPLE,
25 LOCK_CHK_TYPE_RWLOCK,
26};
27
28enum lock_chk_mode : uint8_t {
29 LOCK_CHK_MODE_IGNORED,
30 LOCK_CHK_MODE_SHARED,
31 LOCK_CHK_MODE_EXCLUSIVE,
32};
33
34enum lock_chk_wait_kind : uint8_t {
35 LOCK_CHK_WAIT_BLOCKING,
36 LOCK_CHK_WAIT_TRY,
37};
38
39enum lock_chk_engine_state : uint8_t {
40 LOCK_CHK_INACTIVE,
41 LOCK_CHK_ACTIVE,
42 LOCK_CHK_DEGRADED,
43};
44
45enum lock_debug_irq_usage : uint8_t {
46 LOCK_DEBUG_IRQ_NONE,
47 LOCK_DEBUG_IRQ_DISPATCH,
48 LOCK_DEBUG_IRQ_HIGH,
49};
50
51struct lock_chk_site {
52 const char *file;
53 const char *func;
54 uint32_t line;
55};
56
57struct lock_chk_class {
58 const char *name;
59 const char *file;
60 uint32_t line;
61};
62
63#ifdef DEBUG_LOCK_CHK
64
65#define LOCK_CHK_SITE_HERE() \
66 ({ \
67 static const struct lock_chk_site __site = { \
68 .file = __RELFILE__, \
69 .func = __func__, \
70 .line = __LINE__, \
71 }; \
72 &__site; \
73 })
74
75#define LOCK_CHK_CLASS(id) (&__lock_chk_class_##id)
76
77#define LOCK_CHK_CLASS_DECLARE(id) \
78 extern const struct lock_chk_class __lock_chk_class_##id; \
79 const struct lock_chk_class __lock_chk_class_##id = { \
80 .name = #id, \
81 .file = __RELFILE__, \
82 .line = __LINE__, \
83 }
84
85#define LOCK_CHK_CLASS_DECLARE_LOCAL(id) \
86 static const struct lock_chk_class __lock_chk_class_##id = { \
87 .name = #id, \
88 .file = __RELFILE__, \
89 .line = __LINE__, \
90 }
91
92#define LOCK_CHK_CLASS_DEFINE(id) \
93 extern const struct lock_chk_class __lock_chk_class_##id
94
95#else /* !defined(DEBUG_LOCK_CHK) */
96
97#define LOCK_CHK_SITE_HERE() ((const struct lock_chk_site *) NULL)
98#define LOCK_CHK_CLASS(id) ((const struct lock_chk_class *) NULL)
99#define LOCK_CHK_CLASS_DECLARE(id)
100#define LOCK_CHK_CLASS_DECLARE_LOCAL(id)
101#define LOCK_CHK_CLASS_DEFINE(id)
102
103#endif /* DEBUG_LOCK_CHK */
104
105/*
106 * Prototypes
107 */
108#ifdef DEBUG_LOCK_CHK
109
110void lock_debug_spin_classify(_Atomic uint8_t *usage,
111 enum lock_debug_irq_usage requested,
112 struct lock_chk_lock *lock,
113 const struct lock_chk_site *site);
114bool lock_debug_spin_push(struct lock_chk_lock *lock, enum irql prev_irql,
115 const struct lock_chk_site *site);
116void lock_debug_spin_validate_top(struct lock_chk_lock *lock,
117 enum irql prev_irql,
118 const struct lock_chk_site *site);
119void lock_debug_spin_pop(struct lock_chk_lock *lock);
120
121void lock_chk_note_lock_use(struct lock_chk_lock *lock, bool manages_irql,
122 bool raw_operation);
123
124void lock_chk_assert_schedulable(const struct lock_chk_site *site);
125
126#else /* !defined(DEBUG_LOCK_CHK) */
127
128static inline void lock_debug_spin_classify(_Atomic uint8_t *usage,
129 enum lock_debug_irq_usage requested,
130 void *instance,
131 enum lock_chk_type type,
132 const struct lock_chk_site *site) {
133 unused(usage, requested, instance, type, site);
134}
135
136static inline bool lock_debug_spin_push(void *instance, enum lock_chk_type type,
137 enum irql prev_irql,
138 const struct lock_chk_site *site) {
139 unused(instance, type, prev_irql, site);
140 return false;
141}
142
143static inline void
144lock_debug_spin_validate_top(void *instance, enum lock_chk_type type,
145 enum irql prev_irql,
146 const struct lock_chk_site *site) {
147 unused(instance, type, prev_irql, site);
148}
149
150static inline void lock_debug_spin_pop(void *instance,
151 enum lock_chk_type type) {
152 unused(instance, type);
153}
154
155static inline void lock_chk_note_lock_use(struct lock_chk_lock *lock,
156 bool manages_irql,
157 bool raw_operation) {
158 unused(lock, manages_irql, raw_operation);
159}
160
161static inline void
162lock_chk_assert_schedulable(const struct lock_chk_site *site) {
163 unused(site);
164}
165
166#endif /* DEBUG_LOCK_CHK */
167
168void lock_chk_init(void);
169bool lock_chk_tracking_active(void);
170