XINU provides semaphores for the synchronization of applications. Wait() is XINU's version of P(), and Signal() is XINU's version of V(). XINU also provides some lower-level primitives, suspend() and resume(), which were discussed in the previous chapter.
You already know a fair bit about semaphore implementation from 315. XINU's implementation will not surprise you.
Semaphores are statically allocated in XINU. There is an array of semaphore structures called semaph[]. This is an array of sentry structures. Each sentry contains a count (the semaphore value), the state of that semaphore (whether it is allocated or free), and pointers to the head and tail of the list that processes blocked on this semaphore are kept on. Remember when we did XINU lists that each semaphore (of which there are NSEM) has its own list on which to keep blocked processes.
Initially, all sentries are marked as free. When an application needs a semaphore, it calls screate(int count). Screate() (using newsem) scans through the s-entries looking for a semaphore marked free. Assuming one is found, the state is changed to SUSED, the count field is set to the given count, and the index of the sentry in the semaph table is returned.
Freeing a semaphore after the application is done with it is accomplished by a call to sdelete(sem). Sdelete() (after some error checking) marks the sentry as free, and then if there are any processes waiting on that semaphore, it readies them.
Wait() and Signal() are as expected. Wait() tests and decrements the value of the semaphore. If the value before the call was 0 or less, it places the calling process on that semaphores wait list, changes the processes state to PRWAIT, and then calls resched() (these last two things effectively block the process).
Signal() increments the value of the semaphore. If the value was negative when signal() was called, this means that there is at least one process waiting on the semaphore. Therefore it removes a process from that semaphores list and readies it.
Wait() and Signal() cooperate to ensure FIFO semaphore waiting. To ensure this, wait() adds processes to the tail of the semaphore list, and signal() removes processes from the head of the list.