So my problem is simple, I need to know how many threads are waiting for the semaphore(are queued). Initially I thought sem_getvalue
would return a negative number showing the number of threads blocked by the semaphore but it only goes down to 0 and stays there. I also tried to declare a global variable like int waiting
and incrementing it before calling sem_wait
with waiting++
and decrementing it after the call but it seems like this solution is not working(by which I am baffled because I thought incrementing and decrementing won't cause race condition). I have looked at the semaphore.h
but none of the functions seem to do what I want.
Writing here, I came up with an imperfect solution of declaring a second semaphore and initializing it with 0 then calling sem_post
on it before the actual sem_wait
and a wait after the actual wait. Haven't tested whether it works but even if it does it seems a little hacky a not very nice!
Asked
Active
Viewed 912 times
1

Ali Rahimi
- 394
- 4
- 12
-
https://pubs.opengroup.org/onlinepubs/7908799/xsh/sem_getvalue.html according to the doc it does exactly what you want. Maybe post your code? – littleadv Jan 24 '22 at 08:32
-
Unfortunately: POSIX.1 permits two possibilities for the value returned in sval: either 0 is returned; or a negative number whose absolute value is the count of the number of processes and threads currently blocked in sem_wait(3). Linux adopts the former behavior. – Ali Rahimi Jan 24 '22 at 08:38
-
Increment/decrement is a read-calculate-write-operation, so it is not thread-safe. If you protect the `waiting` counter with a dedicated mutex, then that should work. – nielsen Jan 24 '22 at 08:42
-
C doesn't guarantee there won't be any race conditions even with simple increment/decrement in one thread and reads in another - unless the variables involved are `_Atomic`. – Lundin Jan 24 '22 at 08:43
-
There is something wrong with your design if you attempt this for any reason other than, maybe, debugging. I have written a lot of multithreaded apps and have never found a need to monitor a semaphore count. – Martin James Jan 24 '22 at 13:03
1 Answers
1
Without getting into why you have a lot of threads waiting on a semaphore, one way to solve this is what you already have tried, having a counter.
This counter has to be *atomic*
, or do something like:
pthread_mutex_t wait_m = PTHREAD_MUTEX_INITIALIZER;
int wait_counter = 0;
void inc_wait_counter()
{
pthread_mutex_lock(&wait_m);
wait_counter ++;
pthread_mutex_unlock(&wait_m);
}
void dec_wait_counter()
{
pthread_mutex_lock(&wait_m);
wait_counter --;
pthread_mutex_unlock(&wait_m);
}
int get_wait_counter()
{
/* No need to lock here for only reading wait_counter */
return wait_counter;
}
Then just something like:
inc_wait_counter();
sem_wait(...);
dec_wait_counter();
NOTE: Using atomic integers instead, I suggest to check: How to do an atomic increment and fetch in C?

Morgan V
- 71
- 3
-
In many cases, `get_wait_counter()` will be ok without a lock, but it cannot be guaranteed that writing an integer is an atomic operation (e.g. on an 8-bit processor which nowadays is still found in some embedded systems). So unless integer write (also considering the alignment of the `wait_counter` variable) is known to be atomic on the given system, a lock should be used also for read. – nielsen Jan 24 '22 at 08:56