PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
mutex.c
Go to the documentation of this file.
1#include <kernel/sync/mutex.h>
2
3#include <kernel/config.h>
4#include <kernel/log/log.h>
9#include <kernel/sched/wait.h>
10#include <kernel/sync/lock.h>
11
12#include <assert.h>
13
15{
17 mtx->owner = NULL;
18 mtx->depth = 0;
19 lock_init(&mtx->lock);
20}
21
23{
24 assert(mtx->owner == NULL);
26}
27
29{
30 bool isAcquired = mutex_acquire_timeout(mtx, CLOCKS_NEVER);
31 assert(isAcquired);
32 UNUSED(isAcquired);
33}
34
36{
37 assert(mtx != NULL);
38 thread_t* self = thread_current();
39 assert(self != NULL);
40
41 if (mtx->owner == self)
42 {
43 mtx->depth++;
44 return true;
45 }
46
47 uint64_t spin = 0;
48 while (spin < CONFIG_MUTEX_MAX_SLOW_SPIN)
49 {
50 lock_acquire(&mtx->lock);
51 if (mtx->owner == NULL)
52 {
53 mtx->owner = self;
54 mtx->depth = 1;
55 lock_release(&mtx->lock);
56 return true;
57 }
58 lock_release(&mtx->lock);
59 spin++;
60 }
61
62 if (timeout == 0)
63 {
64 return false;
65 }
66
67 if (timeout == CLOCKS_NEVER)
68 {
69 lock_acquire(&mtx->lock);
70 while (WAIT_BLOCK_LOCK(&mtx->waitQueue, &mtx->lock, mtx->owner == NULL) == ERR)
71 {
72 }
73
74 mtx->owner = self;
75 mtx->depth = 1;
76 lock_release(&mtx->lock);
77 return true;
78 }
79
80 lock_acquire(&mtx->lock);
81 clock_t end = clock_uptime() + timeout;
82 while (true)
83 {
84 clock_t now = clock_uptime();
85 if (now >= end)
86 {
87 lock_release(&mtx->lock);
88 return false;
89 }
90
91 clock_t waitTime = end - now;
92 if (WAIT_BLOCK_LOCK_TIMEOUT(&mtx->waitQueue, &mtx->lock, mtx->owner == NULL, waitTime) == ERR)
93 {
94 lock_release(&mtx->lock);
95 return false;
96 }
97
98 mtx->owner = self;
99 mtx->depth = 1;
100 lock_release(&mtx->lock);
101 return true;
102 }
103}
104
106{
107 assert(mtx != NULL);
108 LOCK_SCOPE(&mtx->lock);
109
111
112 mtx->depth--;
113 if (mtx->depth == 0)
114 {
115 mtx->owner = NULL;
116 wait_unblock(&mtx->waitQueue, 1, EOK);
117 }
118}
#define assert(expression)
Definition assert.h:29
#define CLOCKS_NEVER
Definition clock_t.h:18
#define CONFIG_MUTEX_MAX_SLOW_SPIN
Maximum mutex slow spin configuration.
Definition config.h:117
clock_t clock_uptime(void)
Retrieve the time in nanoseconds since boot.
Definition clock.c:99
static thread_t * thread_current(void)
Retrieves the currently running thread.
Definition thread.h:126
static thread_t * thread_current_unsafe(void)
Retrieves the currently running thread without disabling interrupts.
Definition thread.h:137
uint64_t wait_unblock(wait_queue_t *queue, uint64_t amount, errno_t err)
Unblock threads waiting on a wait queue.
Definition wait.c:307
void wait_queue_deinit(wait_queue_t *queue)
Deinitialize wait queue.
Definition wait.c:57
void wait_queue_init(wait_queue_t *queue)
Initialize wait queue.
Definition wait.c:51
#define WAIT_BLOCK_LOCK_TIMEOUT(queue, lock, condition, timeout)
Blocks until the condition is true, condition will be tested on every wakeup. Will release the lock b...
Definition wait.h:136
#define WAIT_BLOCK_LOCK(queue, lock, condition)
Blocks until the condition is true, condition will be tested on every wakeup. Will release the lock b...
Definition wait.h:109
static void lock_init(lock_t *lock)
Initializes a lock.
Definition lock.h:79
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
Definition lock.h:58
static void lock_release(lock_t *lock)
Releases a lock.
Definition lock.h:175
static void lock_acquire(lock_t *lock)
Acquires a lock, blocking until it is available.
Definition lock.h:96
bool mutex_acquire_timeout(mutex_t *mtx, clock_t timeout)
Acquires a mutex, blocking until it is available or the timeout is reached.
Definition mutex.c:35
void mutex_release(mutex_t *mtx)
Releases a mutex.
Definition mutex.c:105
void mutex_acquire(mutex_t *mtx)
Acquires a mutex, blocking until it is available.
Definition mutex.c:28
void mutex_deinit(mutex_t *mtx)
Deinitializes a mutex.
Definition mutex.c:22
void mutex_init(mutex_t *mtx)
Initializes a mutex.
Definition mutex.c:14
#define EOK
No error.
Definition errno.h:32
#define UNUSED(x)
Mark a variable as unused.
Definition defs.h:96
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ clock_t
A nanosecond time.
Definition clock_t.h:13
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
Mutex structure.
Definition mutex.h:46
lock_t lock
Definition mutex.h:50
wait_queue_t waitQueue
Definition mutex.h:47
thread_t * owner
Definition mutex.h:48
uint32_t depth
Definition mutex.h:49
Thread of execution structure.
Definition thread.h:61