Semaphores

Lock with multiple states

init

int sem_init(sem_t *s, ..., unsigned int n);

wait

sem_wait(sem_t *s);

signal

sem_signal(sem_t *s);

Implementation

wait

Semaphore_Wait(Semaphore *sem) {
  Spinlock_Lock(&sem->sem_lock);
  while (sem->sem_count == 0) {
    /* Locking the wchan prevents a race on sleep */
    WaitChannel_Lock(sem->sem_wchan);
    /* Release spinlock before sleeping */
    Spinlock_Unlock(&sem->sem_lock);
    /* Wait channel protected by it’s own lock */
    WaitChannel_Sleep(sem->sem_wchan);
    /* Recheck condition, no locks held */
    Spinlock_Lock(&sem->sem_lock);
  }
  sem->sem_count--;
  Spinlock_Unlock(&sem->sem_lock);
}

signal

Semaphore_Post(Semaphore *sem) {
  Spinlock_Lock(&sem->sem_lock);
  sem->sem_count++;
  WaitChannel_Wake(sem->sem_wchan);
  Spinlock_Unlock(&sem->sem_lock);
}