*/
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
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");
+}