LF OS
Hobby operating system for amd64 with high ambitions
Loading...
Searching...
No Matches
mutex.c
Go to the documentation of this file.
1#include <tpa.h>
2#include <vm.h>
3#include <panic.h>
4#include <mutex.h>
5#include <log.h>
6#include <scheduler.h>
7#include <errno.h>
8
9static tpa_t* mutexes;
11
12struct mutex_data {
14 int state;
15
18};
19
20void init_mutex(void) {
21 mutexes = tpa_new(&kernel_alloc, sizeof(struct mutex_data), 4080, 0);
22}
23
25 if(!next_mutex) {
26 panic_message("Mutex namespace overflow!");
27 }
28
29 struct mutex_data data = {
30 .state = 0,
31 .holder = 0,
32 };
33
34 tpa_set(mutexes, next_mutex, &data);
35 return next_mutex++;
36}
37
39 struct mutex_data* data = tpa_get(mutexes, mutex);
40
41 if(!data) {
42 logw("mutex", "Tried to destroy non-existing mutex %u", mutex);
43 return;
44 }
45 else if(data->state) {
46 panic_message("Tried to destroy locked mutex!");
47 }
48
50}
51
53 struct mutex_data* data = tpa_get(mutexes, mutex);
54
55 if(!data) {
56 panic_message("Tried to lock non-existing mutex!");
57 }
58 else if(data->state && data->holder != holder) {
59 return false;
60 }
61 else {
62 ++data->state;
63 data->holder = holder;
64 return true;
65 }
66}
67
69 struct mutex_data* data = tpa_get(mutexes, mutex);
70
71 if(!data) {
72 logw("mutex", "Tried to destroy non-existing mutex %u", mutex);
73 return false;
74 }
75 else if(!data->state) {
76 logw("mutex", "Tried to unlock unlocked mutex %u", mutex);
77 return false;
78 }
79 else if(data->holder != holder) {
80 panic_message("Tried to unlock stolen mutex");
81 }
82 else {
83 --data->state;
84
85 if(!data->state) {
86 union wait_data wd;
87 wd.mutex = mutex;
89 }
90
91 return true;
92 }
93}
94
96 size_t prev = 0;
97 size_t mutex = 1;
98 do {
99 logd("mutex", "Looking at the holder of %d", mutex);
100 struct mutex_data* data = tpa_get(mutexes, mutex);
101
102 // we have to check if the mutex is valid since the first
103 // iteration of this loop always looks at mutex 1 which could
104 // be invalid by now. Following iterations should be validity-
105 // checked by the condition of the loop
106 if(data && data->state && data->holder == pid) {
107 logw("mutex", "Mutex %d was held by %d but we are unlocking, probably because the process is dead - mutex leak possible",
108 mutex, pid);
109
111 }
112
113 prev = mutex;
114 } while((mutex = tpa_next(mutexes, prev)) > prev);
115}
116
118 if(!next_mutex) {
119 *error = ENOMEM;
120 logw("mutex", "Mutex namespace overflow!");
121 return;
122 }
123
124 *error = 0;
125 *mutex = mutex_create();
126}
127
129 struct mutex_data* data = tpa_get(mutexes, mutex);
130
131 if(!data) {
132 *error = EINVAL;
133 return;
134 }
135 else if(data->state) {
136 *error = EBUSY;
137 return;
138 }
139
140 *error = 0;
142}
143
145 struct mutex_data* data = tpa_get(mutexes, mutex);
146
148
149 if(!data) {
150 *error = EINVAL;
151 return;
152 }
153 else if(data->state && data->holder != holder) {
154 if(trylock) {
155 *error = EBUSY;
156 return;
157 }
158 else {
159 union wait_data wd;
160 wd.mutex = mutex;
162 }
163 }
164 else {
165 if(!mutex_lock(mutex, holder)) {
166 logw("mutex", "Unexpected mutex_lock error - we checked the same conditions. Mutex %u, new holder %d, current state %s, held by %d",
167 mutex, holder, data->state ? "locked" : "unlocked", data->holder);
168
169 if(trylock) {
170 *error = EBUSY;
171 return;
172 }
173 else {
174 union wait_data wd;
175 wd.mutex = mutex;
177 }
178 }
179 }
180
181 *error = 0;
182}
183
185 struct mutex_data* data = tpa_get(mutexes, mutex);
186
188
189 if(!data) {
190 *error = EINVAL;
191 return;
192 }
193 else if(!data->state) {
194 *error = 0;
195 return;
196 }
197 else if(data->holder != holder) {
198 *error = EPERM;
199 return;
200 }
201
202 *error = 0;
204}
allocator_t kernel_alloc
Definition vm.c:737
unsigned long uint64_t
Definition arch.h:14
int64_t pid_t
Definition arch.h:21
#define EINVAL
Definition errno-defs.h:17
#define ENOMEM
Definition errno-defs.h:11
#define EBUSY
Definition errno-defs.h:13
#define EPERM
Definition errno-defs.h:4
#define logd(component, fmt,...)
Definition log.h:28
#define logw(component, fmt,...)
Definition log.h:44
void sc_handle_locking_destroy_mutex(uint64_t mutex, uint64_t *error)
Definition mutex.c:128
void mutex_destroy(mutex_t mutex)
Definition mutex.c:38
void sc_handle_locking_unlock_mutex(uint64_t mutex, uint64_t *error)
Definition mutex.c:184
pid_t holder
PID of the process who holds the current lock.
Definition mutex.c:17
static tpa_t * mutexes
Definition mutex.c:9
mutex_t mutex_create(void)
Definition mutex.c:24
bool mutex_unlock(mutex_t mutex, pid_t holder)
Definition mutex.c:68
static uint64_t next_mutex
Definition mutex.c:10
void mutex_unlock_holder(pid_t pid)
Definition mutex.c:95
int state
Current state of this mutex, 0 = unlocked.
Definition mutex.c:14
void init_mutex(void)
Definition mutex.c:20
void sc_handle_locking_create_mutex(uint64_t *mutex, uint64_t *error)
Definition mutex.c:117
bool mutex_lock(mutex_t mutex, pid_t holder)
Definition mutex.c:52
void sc_handle_locking_lock_mutex(uint64_t mutex, bool trylock, uint64_t *error)
Definition mutex.c:144
uint64_t mutex_t
Definition mutex.h:6
void panic_message(const char *message)
Definition panic.c:64
void scheduler_wait_for(pid_t pid, enum wait_reason reason, union wait_data data)
Definition scheduler.c:353
void scheduler_waitable_done(enum wait_reason reason, union wait_data data, size_t max_amount)
Definition scheduler.c:363
volatile pid_t scheduler_current_process
Definition scheduler.c:50
mutex_t mutex
Definition scheduler.h:26
@ wait_reason_mutex
Definition scheduler.h:14
* mutex
Definition syscalls.h:171
static void pid_t * pid
Definition syscalls.h:34
static bool trylock
Definition syscalls.h:197
static uint16_t bool uint64_t * error
Definition syscalls.h:126
tpa_t * tpa_new(allocator_t *alloc, uint64_t entry_size, uint64_t page_size, tpa_t *tpa)
Definition tpa.c:48
size_t tpa_next(tpa_t *tpa, size_t cur)
Definition tpa.c:223
void * tpa_get(tpa_t *tpa, uint64_t idx)
Definition tpa.c:144
void tpa_set(tpa_t *tpa, uint64_t idx, void *data)
Definition tpa.c:174
Header of a TPA.
Definition tpa.c:34