kernel: Add simple mutex with a wait queue

This commit is contained in:
K. Lange 2021-11-17 19:13:33 +09:00
parent 66682facad
commit d90d6e1963
3 changed files with 86 additions and 0 deletions

View File

@ -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);

51
kernel/sys/mutex.c Normal file
View File

@ -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;
}

View File

@ -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.
*