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
5seconds before posting semaphore. - once
5seconds 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: either0returned; 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