I am thinking that there must be some race condition: When the
condition variable is created the cond->sem value will be set to
zero. While waiting for cond->sem, it will be set to -1. If you see
cond->sem equal to zero, my guess would be that the signal was
received and cond->sem was incremented asychronously by the signal
delivery logic. But that is only a guess.
I know what is going on. There is no race condition. It is normal
behavior for a signal handler:
* The signal handler runs on the same thread that receives the signal
* In order for the signal handler to run, the thread must be running.
If the thread is blocked, then it must be unblocked so that the
signal handler can run (that is why EINTR is returned under POSIX...
To indicate only that the thread had to be unblocked and awakened to
process a signal).
* If the thread is blocked waiting on a semaphore, then the semaphore
count must be incremented in order to unblock the thread.
* This must happen BEFORE the signal handler runs.
So there is no race condition, instead there is a simple ordering issue
The sequence above should be modified like:
* When the condition variable is created the cond->sem value will be
set to zero.
* While waiting for cond->sem, the value will be decremented to -1
* When a signal is received, the thread will be awakened be
incremented back to zero.
* THEN the thread will run and signal handler will be invoked with the
cond->sem value ALWAYS equal to zero.
So it is perfectly normal behavior that the cond->sem count is zero in
this case. It just indicates that the thread is running. So, no, I was
wrong. It is not possible to use pthread_cond_signal() form a thread to
wake itself up BECAUSE it already had to be awakened in order for the
signal handler to run.
When the signal handler returns, pthread_cond_wait() will run inside of
nxsem_wait_interruptible() and it will correctly ignore the EINTR error
and call nxsem_wait() again.