include/sem: Re-implement semaphores without busy-waiting workaround
The current sem module has a design issue that requires the use of sleep
or inotifywait to avoid busy-waiting when the semaphore counter is zero.
This commit adds a new sem implementation that avoids the problem
altogether through the use of a separate mutex (called waitlock), which
sem_wait() will attempt to acquire, causing it to be blocked until the
waitlock is released by a call to sem_post().
Further, the new implementation keeps all filesystem objects belonging to
a semaphore in a directory, giving it a cleaner appearance.
This commit also adds several test cases for the new sem module.