kernel: semaphores

This commit is contained in:
Matheus
2023-05-03 21:07:43 -03:00
parent 433155bb74
commit c1c84cffbb
2 changed files with 95 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
#ifndef _SEMAPHORE_H
#define _SEMAPHORE_H
#include <stdbool.h>
#include <spinlock.h>
#include <kernel/scheduler.h>
#define SEM_TAIL 0
#define SEM_HEAD 1
typedef struct {
int i;
spinlock_t lock;
thread_t *tail;
thread_t *head;
} semaphore_t;
#define SEMAPHORE_INIT(x, v) { \
(x)->val = v; \
SPINLOCK_INIT((x)->lock); \
(x)->list = NULL; \
}
int semaphore_wait(semaphore_t *sem, bool interruptible);
void semaphore_signal(semaphore_t *sem);
bool semaphore_test(semaphore_t *sem);
#endif
+67
View File
@@ -0,0 +1,67 @@
#include <semaphore.h>
#include <errno.h>
#include <logging.h>
static void insert(semaphore_t *sem, thread_t *thread) {
if (sem->head == NULL) {
sem->head = thread;
sem->tail = thread;
thread->next = NULL;
thread->prev = NULL;
return;
}
sem->tail->next = _cpu()->thread;
_cpu()->thread->prev = sem->tail;
}
static thread_t *get(semaphore_t *sem) {
thread_t *thread = sem->head;
__assert(thread);
sem->head = sem->head->next;
if (sem->head == NULL)
sem->tail = NULL;
else
sem->head->prev = NULL;
return thread;
}
int semaphore_wait(semaphore_t *sem, bool interruptible) {
int ret = 0;
spinlock_acquire(&sem->lock);
if (--sem->i < 0) {
insert(sem, _cpu()->thread);
sched_preparesleep(interruptible);
spinlock_release(&sem->lock);
return sched_yield();
}
spinlock_release(&sem->lock);
return ret;
}
void semaphore_signal(semaphore_t *sem) {
spinlock_acquire(&sem->lock);
if (++sem->i <= 0) {
thread_t *thread = get(sem);
// XXX the current method doesn't respect thread priorities
sched_wakeup(thread, 0);
}
spinlock_release(&sem->lock);
}
bool semaphore_test(semaphore_t *sem) {
bool ret = false;
spinlock_acquire(&sem->lock);
if (sem->i > 0) {
--sem->i;
ret = true;
}
spinlock_release(&sem->lock);
return ret;
}