Reputation: 151
The behavior of the sem_post()
function is not clear for a binary semaphore based implementation.
What happens when you call sem_wait()
after calling sem_post()
?
Will it work?
Code example :
Thread 1 :
do_something_critical()
sem_post();
Thread 2 :
sem_wait()
Proceed()
Here if some how sem_post()
gets called before the call to sem_wait()
,
will it work? Or is it necessary that sem_wait()
need to be called before sem_post()
?
Upvotes: 0
Views: 4257
Reputation: 5201
sem_post() merely increments the semaphore and wakes up any waiting thread if any. Otherwise it does nothing.
sem_wait() merely decrements the semaphore. The caller will be blocked only if the current value of the semaphore is 0.
Here is an example program where the main thread initializes a semaphore to 0 and calls sem_trywait() to verify that the semaphore is busy (i.e. value is 0). Then, it calls sem_post() to release the semaphore (i.e. value is 1) before creating a thread. The thread calls sem_wait() (this decrements the semaphore to 0) and returns. The main thread waits for the end of the thread and verifies that the semaphore is 0 with a call to sem_trywait():
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
static sem_t *sem;
void *thd_entry(void *p)
{
int rc;
printf("Thread is starting...\n");
// This decrements the semaphore
rc = sem_wait(sem);
if (0 != rc) {
perror("sem_wait()");
return NULL;
}
printf("Thread is exiting...\n");
return NULL;
}
int main(int ac, char *av[])
{
int rc;
pthread_t thd;
// Create a semaphore with an initial value set to 0
sem = sem_open("/example", O_CREAT|O_RDWR, 0777, 0);
if (sem == SEM_FAILED) {
perror("sem_open()");
return 1;
}
// After creation the value of the semaphore is 0
rc = sem_trywait(sem);
if (-1 == rc) {
if (errno == EAGAIN) {
printf("Semaphore is busy (i.e. value is 0)\n");
} else {
perror("sem_trywait()");
return 1;
}
}
// Increment the semaphore
rc = sem_post(sem);
if (0 != rc) {
perror("sem_post()");
return 1;
}
// Create a thread
rc = pthread_create(&thd, NULL, thd_entry, 0);
if (0 != rc) {
errno = rc;
perror("pthread_create()");
return 1;
}
rc = pthread_join(thd, NULL);
if (0 != rc) {
errno = rc;
perror("pthread_join()");
return 1;
}
// The semaphore is 0 as the thread decremented it
rc = sem_trywait(sem);
if (-1 == rc) {
if (errno == EAGAIN) {
printf("Semaphore is busy (i.e. value is 0)\n");
} else {
perror("sem_trywait()");
return 1;
}
}
return 0;
}
Here is a try:
$ ls -l /dev/shm
total 0
$ gcc sema.c -o sema -lpthread
$ ./sema
Semaphore is busy (i.e. value is 0)
Thread is starting...
Thread is exiting...
Semaphore is busy (i.e. value is 0)
$ ls -l /dev/shm
total 4
-rwxrwxr-x 1 xxxxx xxxxx 32 janv. 5 16:24 sem.example
$ rm /dev/shm/sem.example
Upvotes: 2