PatchworkOS
Loading...
Searching...
No Matches
lock.h
Go to the documentation of this file.
1#pragma once
2
4
5#ifndef NDEBUG
6#include <kernel/log/panic.h>
7#endif
8
9#include <kernel/defs.h>
10#include <kernel/drivers/com.h>
11#include <stdatomic.h>
12
25#define LOCK_DEADLOCK_ITERATIONS 1000000
26
30#define LOCK_CANARY 0xDEADBEEF
31
42typedef struct
43{
44 atomic_uint16_t nextTicket;
45 atomic_uint16_t nowServing;
46#ifndef NDEBUG
49#endif
50} lock_t;
51
57#define LOCK_SCOPE(lock) \
58 __attribute__((cleanup(lock_cleanup))) lock_t* CONCAT(l, __COUNTER__) = (lock); \
59 lock_acquire((lock))
60
65#ifndef NDEBUG
66#define LOCK_CREATE (lock_t){.nextTicket = ATOMIC_VAR_INIT(0), .nowServing = ATOMIC_VAR_INIT(0), .canary = 0xDEADBEEF}
67#else
68#define LOCK_CREATE \
69 (lock_t) \
70 { \
71 .nextTicket = ATOMIC_VAR_INIT(0), .nowServing = ATOMIC_VAR_INIT(0) \
72 }
73#endif
74
80static inline void lock_init(lock_t* lock)
81{
82 atomic_init(&lock->nextTicket, 0);
83 atomic_init(&lock->nowServing, 0);
84#ifndef NDEBUG
85 lock->canary = LOCK_CANARY;
86#endif
87}
88
97static inline void lock_acquire(lock_t* lock)
98{
100
101#ifndef NDEBUG
102 if (lock->canary != LOCK_CANARY)
103 {
105 panic(NULL, "Lock canary corrupted");
106 }
107 lock->calledFrom = (uintptr_t)__builtin_return_address(0);
108 uint64_t iterations = 0;
109#endif
110
112 while (atomic_load_explicit(&lock->nowServing, memory_order_acquire) != ticket)
113 {
114 asm volatile("pause");
115
116#ifndef NDEBUG
117 if (lock->canary != LOCK_CANARY)
118 {
120 panic(NULL, "Lock canary corrupted after %d iterations", iterations);
121 }
122 if (++iterations >= LOCK_DEADLOCK_ITERATIONS)
123 {
125 panic(NULL, "Deadlock detected in lock last acquired from %p", (void*)lock->calledFrom);
126 }
127#endif
128 }
129
131}
132
140static inline void lock_release(lock_t* lock)
141{
142#ifndef NDEBUG
143 if (lock->canary != LOCK_CANARY)
144 {
145 panic(NULL, "Lock canary corrupted");
146 }
147#endif
148
151}
152
153static inline void lock_cleanup(lock_t** lock)
154{
156}
157
void interrupt_disable(void)
Disable interrupts and increment the disableDepth.
Definition interrupt.c:26
void interrupt_enable(void)
Decrement the CLI depth and enable interrupts if depth reaches zero and interrupts were previously en...
Definition interrupt.c:38
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:362
static void lock_init(lock_t *lock)
Initializes a lock.
Definition lock.h:80
static void lock_cleanup(lock_t **lock)
Definition lock.h:153
static void lock_release(lock_t *lock)
Releases a lock.
Definition lock.h:140
#define LOCK_DEADLOCK_ITERATIONS
Number of iterations before we consider a deadlock has occurred in lock_acquire. This is only used in...
Definition lock.h:25
static void lock_acquire(lock_t *lock)
Acquires a lock, blocking until it is available.
Definition lock.h:97
#define LOCK_CANARY
Lock canary value to detect memory corruption.
Definition lock.h:30
#define NULL
Pointer error value.
Definition NULL.h:23
static rwlock_t lock
Definition irq.c:10
@ memory_order_seq_cst
Definition stdatomic.h:121
@ memory_order_release
Definition stdatomic.h:119
@ memory_order_relaxed
Definition stdatomic.h:116
@ memory_order_acquire
Definition stdatomic.h:118
#define atomic_fetch_add_explicit(object, operand, order)
Definition stdatomic.h:259
#define atomic_load_explicit(object, order)
Definition stdatomic.h:264
#define atomic_thread_fence(order)
Definition stdatomic.h:135
#define atomic_init(obj, value)
Definition stdatomic.h:75
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
__UINT16_TYPE__ uint16_t
Definition stdint.h:13
A simple ticket lock implementation.
Definition lock.h:43
atomic_uint16_t nextTicket
Definition lock.h:44
uintptr_t calledFrom
Definition lock.h:48
uint32_t canary
Definition lock.h:47
atomic_uint16_t nowServing
Definition lock.h:45