]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Added a simple layer for semaphores
authorMaria Matejka <mq@ucw.cz>
Sun, 21 Mar 2021 22:57:01 +0000 (23:57 +0100)
committerMaria Matejka <mq@ucw.cz>
Wed, 2 Jun 2021 12:28:14 +0000 (14:28 +0200)
lib/coro.h
sysdep/unix/coroutine.c

index 51712b3627c8003776584a64a9ad15345d461b2f..c1f4ce478c55d4218aeb75e5b01ad22b68d49da8 100644 (file)
@@ -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
index bf5b09db6314052cb279f9a88aa0437b2b71eec1..febf0511286c2f5ffa40b8ba9090f3401bc18c71 100644 (file)
@@ -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");
+}