1#include <atomic.h>
2#include <bootstage.h>
3#include <cmdline.h>
4#include <enforce.h>
5#include <sync/lock_chk.h>
6
7#ifdef DEBUG_LOCK_CHK
8
9#include "internal.h"
10
11struct lock_chk_globals lock_chk_global = {0};
12
13CMDLINE_DEFINE_STATIC(lock_chk, .flags = CMDLINE_ENTRY_SYMBOLIC,
14 .desc = "Lock validator command line namespace");
15
16CMDLINE_CHILDREN_DEFINE(
17 lock_chk,
18 CMDLINE_INNER_VAR(
19 panic_on_exhaustion, lock_chk_global.panic_on_exhaustion,
20 .default_val = "true",
21 .desc = "Panic when lock validator capacity is exhausted"),
22 CMDLINE_INNER_VAR(
23 capacity_panic, lock_chk_global.panic_on_exhaustion,
24 .default_val = "true",
25 .desc = "Panic when lock validator capacity is exhausted (alias)"));
26
27void lock_chk_init(void) {
28 enforce(bootstage_get() >= BOOTSTAGE_LATE, UNINITIALIZED);
29 lock_chk_deep_activate();
30 lock_debug_activate();
31 atomic_store_release(&lock_chk_global.state, LOCK_CHK_ACTIVE);
32}
33
34bool lock_chk_tracking_active(void) {
35 return lock_chk_state_active(&lock_chk_global.state);
36}
37
38void lock_chk_note_use(struct lock_chk_lock *lock, enum lock_op_flags flags) {
39 if (!lock_chk_tracking_active())
40 return;
41
42 bool manages_irql = (flags & LOCK_OP_IRQ_MASK) != 0;
43 bool raw = flags & LOCK_OP_RAW;
44 enforce(lock->initialized, UNINITIALIZED);
45 enforce((lock->flags & ~LOCK_CHKD_FULL) == 0);
46 if (manages_irql && !raw)
47 enforce((lock->flags & LOCK_CHKD_THREAD) == 0 ||
48 (lock->flags & LOCK_CHKD_ORDER) != 0);
49
50 atomic_store_release(&lock->used, true);
51}
52
53#else /* !defined(DEBUG_LOCK_CHK) */
54
55void lock_chk_init(void) {}
56
57bool lock_chk_tracking_active(void) {
58 return false;
59}
60
61#endif /* DEBUG_LOCK_CHK */
62