1#include <bootstage.h>
2#include <cmdline.h>
3#include <kassert.h>
4#include <stdatomic.h>
5#include <sync/lock_chk.h>
6
7#ifdef DEBUG_LOCK_CHK
8
9#include "lock_chk_internal.h"
10
11static _Atomic enum lock_chk_engine_state lock_chk_state = LOCK_CHK_INACTIVE;
12static bool lock_chk_panic_on_exhaustion = true;
13
14static CMDLINE_DECLARE(lock_chk, .flags = CMDLINE_ENTRY_SYMBOLIC,
15 .desc = "Lock validator command line namespace");
16
17CMDLINE_CHILDREN_DECLARE(
18 lock_chk,
19 CMDLINE_INNER_VAR(
20 panic_on_exhaustion, lock_chk_panic_on_exhaustion,
21 .default_val = "true",
22 .desc = "Panic when lock validator capacity is exhausted"),
23 CMDLINE_INNER_VAR(
24 capacity_panic, lock_chk_panic_on_exhaustion, .default_val = "true",
25 .desc = "Panic when lock validator capacity is exhausted (alias)"));
26
27void lock_chk_init(void) {
28 kassert(bootstage_get() >= BOOTSTAGE_LATE);
29 lock_chk_deep_activate();
30 lock_debug_activate();
31 atomic_store_explicit(&lock_chk_state, LOCK_CHK_ACTIVE,
32 memory_order_release);
33}
34
35bool lock_chk_tracking_active(void) {
36 return atomic_load_explicit(&lock_chk_state, memory_order_acquire) ==
37 LOCK_CHK_ACTIVE;
38}
39
40bool lock_chk_capacity_should_panic(void) {
41 return lock_chk_panic_on_exhaustion;
42}
43
44void lock_chk_note_lock_use(struct lock_chk_lock *lock, bool manages_irql,
45 bool raw_operation) {
46 if (!lock_chk_tracking_active())
47 return;
48
49 kassert(lock->initialized);
50 kassert((lock->flags & ~LOCK_CHKD_FULL) == 0);
51 if (manages_irql && !raw_operation)
52 kassert((lock->flags & LOCK_CHKD_THREAD) == 0 ||
53 (lock->flags & LOCK_CHKD_ORDER) != 0);
54
55 atomic_store_explicit(&lock->used, true, memory_order_release);
56}
57
58#else /* !defined(DEBUG_LOCK_CHK) */
59
60void lock_chk_init(void) {}
61
62bool lock_chk_tracking_active(void) {
63 return false;
64}
65
66#endif /* DEBUG_LOCK_CHK */
67