c - How to block on a semaphore until its value is positive -
i want use semaphores make threads block until semaphores become positive; when threads block on semaphore, unblock on first sem_post
called on it, regardless of value of semaphore afterwards.
the situation follows:
- semaphore set
-1
. - a thread started wait
5
seconds before posting semaphore. - once
5
seconds pass, thread posts semaphore. - the semaphore's value
0
, main process unblocks anyway.
here code demonstrating 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 crude way overcome issue wrapping sem_wait
in busy loop checks if semaphore's value 0
, seems wrong way approach this.
is there more elegant way block on semaphore until value positive (not 0
, nor negative)?
you can't initialize semaphore -1
because api initialize takes unsigned values.
int sem_init(sem_t *sem, int pshared, unsigned int value);
the open group
probably, using -1
caused value larger sem_value_max
passed sem_init()
, , initialization failed. should check return code, , if errno
got set einval
.
the
sem_init()
function fail if:
[ einval
] value argument exceedssem_value_max
....
the open group
if want threads block on semaphore on first call sem_wait
, initialize semaphore 0
instead.
if system supports it, can use sem_getvalue
find number of waiters on semaphore if count 0
.
if sem locked, value returned
sem_getvalue()
either 0 or negative number absolute value represents number of processes waiting semaphore @ unspecified time during call.
the open group
an implementation allowed choose behavior want, works if system supports it. linux, example, not support it, since chooses return 0
if semaphore count 0
.
if 1 or more processes or threads blocked waiting lock semaphore
sem_wait(3)
, posix.1 permits 2 possibilities value returned insval
: either0
returned; or negative number absolute value count of number of processes , threads blocked insem_wait(3)
. linux adopts former behavior.
man7.org
probably reliable way implement want use mutual exclusion variable, condition variable, , counter.
extern pthread_mutex_t lock; extern pthread_cond_t queue; extern atomic_uint waiters; /* assume waiters 0 */ pthread_mutex_lock(&lock); ++waiters; while (my_status() == waiting) { pthread_cond_wait(&queue, &lock); } --waiters; pthread_mutex_unlock(&lock);
Comments
Post a Comment