/* * Binary semaphore that represents a resource that can be * acquired. * * Initial state is "busy = false" which means the resource * is available. Supports wait and signal operations. */ #include "list.h" #include "semaphore.h" #include "process.h" #include #include #include struct semaphore { const char *name; // name for debugging bool busy; // is resource acquired? struct list queue; // list of waiters struct scheduler *sched; // associated scheduler }; struct semaphore * semaphore_new(struct scheduler *sched, const char *name) { struct semaphore *s = malloc(sizeof *s); s->name = name; s->busy = false; s->sched = sched; list_init(&s->queue); return s; } const char * semaphore_name(struct semaphore *self) { return self->name; } void semaphore_print(struct semaphore *self) { /* debug print function */ printf("Semaphore %s (busy=%s)", self->name, self->busy ? "true": "false"); for (struct list_elem *e = list_begin(&self->queue); e != list_end(&self->queue); e = list_next(e)) { struct process *p = list_entry(e, struct process, elem); process_print(p); } } /* request this resource; block if necessary */ void semaphore_wait(struct semaphore *self) { if (self->busy) process_waitq(self->sched->current, &self->queue); else self->busy = true; } /* release this resource */ void semaphore_signal(struct semaphore *self) { if (list_empty(&self->queue)) self->busy = false; else sched_activate_now(self->sched, list_entry(list_pop_front(&self->queue), struct process, elem)); }