From 8d7fbf911acbd4620135efc34cdc793ad529e3d5 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Sun, 21 Mar 2021 23:57:01 +0100 Subject: [PATCH] Added a simple layer for semaphores --- lib/coro.h | 12 ++++++++++++ sysdep/unix/coroutine.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/lib/coro.h b/lib/coro.h index 51712b36..c1f4ce47 100644 --- a/lib/coro.h +++ b/lib/coro.h @@ -22,5 +22,17 @@ struct coroutine; */ struct coroutine *coro_run(pool *, void (*entry)(void *), void *data); +/* Semaphores are handy to sleep and wake worker threads. */ +struct bsem; + +/* Create a semaphore. Be sure to choose such a pool that happens to be freed + * only when the semaphore can't be waited for or posted. */ +struct bsem *bsem_new(pool *); + +/* Post a semaphore (wake the worker). */ +void bsem_post(struct bsem *); + +/* Wait for a semaphore. Never do this within a locked context. */ +void bsem_wait(struct bsem *); #endif diff --git a/sysdep/unix/coroutine.c b/sysdep/unix/coroutine.c index bf5b09db..febf0511 100644 --- a/sysdep/unix/coroutine.c +++ b/sysdep/unix/coroutine.c @@ -173,3 +173,43 @@ struct coroutine *coro_run(pool *p, void (*entry)(void *), void *data) return c; } + +/* Semaphores */ +struct bsem { + resource r; + sem_t sem; +}; + +static void bsem_free(resource *r) +{ + struct bsem *b = (void *) r; + if (sem_destroy(&b->sem) < 0) + bug("sem_destroy() failed: %m"); +} + +static struct resclass bsem_class = { + .name = "Semaphore", + .size = sizeof(struct bsem), + .free = bsem_free, +}; + +struct bsem *bsem_new(pool *p) { + struct bsem *b = ralloc(p, &bsem_class); + if (sem_init(&b->sem, 0, 0) < 0) + bug("sem_init() failed: %m"); + + return b; +} + +void bsem_post(struct bsem *b) { + if (sem_post(&b->sem) < 0) + bug("sem_post() failed: %m"); +} + +void bsem_wait(struct bsem *b) { + if (sem_wait(&b->sem) < 0) + if (errno == EINTR) + return bsem_wait(b); + else + bug("sem_wait() failed: %m"); +}