I want to use semaphores to make threads block until the semaphores become positive; but when my threads block on a semaphore, they unblock immediately on the first sem_post
called on it, regardless of the value of that semaphore afterwards.
The situation is as follows:
- Semaphore is set to
-1
. - A thread is started to wait
5
seconds before posting to the semaphore. - Once
5
seconds pass, the thread posts to the semaphore. - The semaphore's value is
0
, but the main process unblocks anyway.
Here is the code demonstrating the situation:
/**
* testing whether sem_post on semaphore unblocks threads
* despite still being negative.
**/
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
sem_t sem;
void *proc(void *arg)
{
sleep(5);
puts("posting");
sem_post(&sem);
}
void setup()
{
pthread_t pt;
pthread_create(&pt, 0, proc, 0);
}
int main(int argc, char **argv)
{
sem_init(&sem, 0, -1);
setup();
sem_wait(&sem);
return 0;
}
I have found a crude way to overcome this issue by wrapping sem_wait
in a busy loop that checks if the semaphore's value is 0
, but this seems like a wrong way to approach this.
Is there a more elegant way to block on a semaphore until its value is positive (not 0
, nor negative)?
sem_init
:int sem_init(sem_t *sem, int pshared, unsigned int value);
Note theunsigned
. Also,man sem_overview:
A semaphore is an integer whose value is never allowed to fall below zero.[...]. – EOFsem_t
. In fact, using a second semaphore to count the waiting processes would probably involve a race condition. – EOFfutex
), so the OS can schedule out a process that is blocked, and schedule it back in when the semaphore is posted. The OS will keep a list of processes blocked on the semaphore, but userspace doesn't usually see it. – EOF