kernel: Add simple mutex with a wait queue
This commit is contained in:
parent
66682facad
commit
d90d6e1963
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Mutex that sleeps... and can be owned across sleeping...
|
||||
*
|
||||
* @copyright 2014-2021 K. Lange <klange@toaruos.org>
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
*/
|
||||
#include <kernel/list.h>
|
||||
#include <kernel/spinlock.h>
|
||||
#include <kernel/process.h>
|
||||
|
||||
typedef struct {
|
||||
spin_lock_t inner_lock;
|
||||
volatile int status;
|
||||
process_t * owner;
|
||||
list_t * waiters;
|
||||
} sched_mutex_t;
|
||||
|
||||
extern sched_mutex_t * mutex_init(const char * name);
|
||||
extern int mutex_acquire(sched_mutex_t * mutex);
|
||||
extern int mutex_release(sched_mutex_t * mutex);
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* Mutex that sleeps... and can be owned across sleeping...
|
||||
*
|
||||
* @copyright 2014-2021 K. Lange <klange@toaruos.org>
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
*/
|
||||
#include <kernel/types.h>
|
||||
#include <kernel/printf.h>
|
||||
#include <kernel/time.h>
|
||||
#include <kernel/string.h>
|
||||
#include <kernel/spinlock.h>
|
||||
#include <kernel/assert.h>
|
||||
#include <kernel/process.h>
|
||||
#include <kernel/list.h>
|
||||
#include <kernel/mutex.h>
|
||||
|
||||
extern int wakeup_queue_one(list_t * queue);
|
||||
|
||||
sched_mutex_t * mutex_init(const char * name) {
|
||||
sched_mutex_t * out = malloc(sizeof(sched_mutex_t));
|
||||
spin_init(out->inner_lock);
|
||||
out->status = 0;
|
||||
out->owner = NULL;
|
||||
out->waiters = list_create(name, out);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int mutex_acquire(sched_mutex_t * mutex) {
|
||||
spin_lock(mutex->inner_lock);
|
||||
while (mutex->status) {
|
||||
sleep_on_unlocking(mutex->waiters, &mutex->inner_lock);
|
||||
spin_lock(mutex->inner_lock);
|
||||
}
|
||||
mutex->status = 1;
|
||||
mutex->owner = (process_t*)this_core->current_process;
|
||||
spin_unlock(mutex->inner_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mutex_release(sched_mutex_t * mutex) {
|
||||
assert(mutex->owner == this_core->current_process);
|
||||
spin_lock(mutex->inner_lock);
|
||||
mutex->owner = NULL;
|
||||
mutex->status = 0;
|
||||
wakeup_queue_one(mutex->waiters);
|
||||
spin_unlock(mutex->inner_lock);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -786,6 +786,20 @@ int wakeup_queue_interrupted(list_t * queue) {
|
|||
return awoken_processes;
|
||||
}
|
||||
|
||||
int wakeup_queue_one(list_t * queue) {
|
||||
int awoken_processes = 0;
|
||||
spin_lock(wait_lock_tmp);
|
||||
if (queue->length > 0) {
|
||||
node_t * node = list_pop(queue);
|
||||
if (!(((process_t *)node->value)->flags & PROC_FLAG_FINISHED)) {
|
||||
make_process_ready(node->value);
|
||||
}
|
||||
awoken_processes++;
|
||||
}
|
||||
spin_unlock(wait_lock_tmp);
|
||||
return awoken_processes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for a binary semaphore.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue