lib: Add semaphores
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
// SPDX-License-Identifier: ISC
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
_Atomic(uint32_t) count;
|
||||||
|
} sem_t;
|
||||||
|
|
||||||
|
void sem_init(sem_t* sem, uint32_t count);
|
||||||
|
bool sem_trywait(sem_t* sem);
|
||||||
|
bool sem_timedwait(sem_t* sem, const uint64_t* deadline_ns);
|
||||||
|
void sem_wait(sem_t* sem);
|
||||||
|
void sem_post(sem_t* sem);
|
||||||
@@ -23,6 +23,7 @@ kernel_sources += files(
|
|||||||
'ringbuf.c',
|
'ringbuf.c',
|
||||||
'runtime.c',
|
'runtime.c',
|
||||||
'rwlock.c',
|
'rwlock.c',
|
||||||
|
'semaphore.c',
|
||||||
'spin.c',
|
'spin.c',
|
||||||
'stdlib.c',
|
'stdlib.c',
|
||||||
'string.c',
|
'string.c',
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// SPDX-License-Identifier: ISC
|
||||||
|
|
||||||
|
#include <zinnia/atomic.h>
|
||||||
|
#include <zinnia/park.h>
|
||||||
|
#include <zinnia/semaphore.h>
|
||||||
|
|
||||||
|
void sem_init(sem_t* sem, uint32_t count) {
|
||||||
|
atomic_store(&sem->count, count, ATOMIC_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sem_trywait(sem_t* sem) {
|
||||||
|
uint32_t count = atomic_load(&sem->count, ATOMIC_RELAXED);
|
||||||
|
while (count) {
|
||||||
|
if (atomic_compare_exchange_weak(&sem->count, &count, count - 1, ATOMIC_ACQUIRE, ATOMIC_RELAXED))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool sem_empty(void* ctx) {
|
||||||
|
sem_t* sem = ctx;
|
||||||
|
return atomic_load(&sem->count, ATOMIC_RELAXED) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sem_timedwait(sem_t* sem, const uint64_t* deadline_ns) {
|
||||||
|
while (!sem_trywait(sem)) {
|
||||||
|
if (park_timeout(sem, sem_empty, nullptr, sem, 0, deadline_ns).status == PARK_TIMED_OUT)
|
||||||
|
return sem_trywait(sem);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sem_wait(sem_t* sem) {
|
||||||
|
sem_timedwait(sem, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sem_post(sem_t* sem) {
|
||||||
|
atomic_fetch_add(&sem->count, 1, ATOMIC_RELEASE);
|
||||||
|
unpark_one(sem, nullptr, nullptr);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user