Commit 8d7fbf91 authored by Maria Matejka's avatar Maria Matejka
Browse files

Added a simple layer for semaphores

parent bc353f1b
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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
+40 −0
Original line number Diff line number Diff line
@@ -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");
}