1

I am trying to use POSIX counting semaphore as a binary semaphore?

For the purpose, I have written the following code

sem = sem_open(argv[optind], flags, perms, 1); // Initialising semaphore to 1

    while(sem_getvalue(sem) > 0)
    {
    continue;

    }
    sem_post(sem);

Are there any other methods to use a counting semaphore as a binary semaphore? Here if the comtext switching occurs immediately after the while lopp is evalauted to false, and yet sem_post hasn't been called, in such a situation wouldn't that leads to race condition? Is there any other better soultions, for what I am trying to achieve.

I have multiple processes being synchronized with the sempahore. I am aware this code does not let gurantee a scenario, when during sem_getvalue even if the sem value becomes zero, even before sem_post in a particular process is called, anotehr process may also call sem_post, leading the value to be 2. How such a scenario can be resolved.

My problem won't be solved by a mutex, as in my problem, there are processes that is used only for the signal i.e. sem_post operation, unlike in mutex, where all the processes will have wait and signal continually

Amrith Krishna
  • 2,768
  • 3
  • 31
  • 65
  • Possible [duplicate](https://stackoverflow.com/questions/32156321/making-binary-semaphore-shared-between-multiple-processesnot-threads-process/32158121#32158121). – Jason Aug 23 '15 at 05:10

1 Answers1

0

There are some issues with the code you posted.

while(sem_getvalue(sem) > 0)

This is referred to as busy waiting, which means the process spins on the semaphore and doesn't relinquish the CPU to the scheduler. Typically, busy waiting is only done in the scenario where the wait should be less than the time for context switching (e.g. low latency).

The next issue is that your semantics are inverted. You decrement and proceed when the semaphore is greater than 0. Additionally, your calls are not atomic which introduces a number of race conditions.

Effectively, you need mutex semantics since there are only two states (0/locked and 1/unlocked). For this, you can either guarantee that a sem_post never proceeds a sem_wait, or you can use a file lock.

const char* lock_file = ".lock";

const int fd_lock = open(lock_file, O_CREAT);

flock(fd_lock, LOCK_EX);

// do stuff

flock(fd_lock, LOCK_UN);

// do more stuff

close(fd_lock);    
unlink(lock_file);

The POSIX variant would involve fcntl instead of flock.

Jason
  • 3,777
  • 14
  • 27
  • Wouldn't using a file lock slow down the processes, as file operations are create unnecessary lag. Also here there can be multiple processes, that can do a semaphore signal operation. In fact there some processes, that will do only signal operation. So this is not a typical mutex operation. – Amrith Krishna Aug 23 '15 at 05:20
  • Thanks for your inputs, but I am precisely looking for a semaphore based solution, not a file lock operation. – Amrith Krishna Aug 23 '15 at 05:38
  • No, mutexes, semaphores, and file locks are all implemented in the kernel as processes need to block on them. Lock files are typically empty, and locking/unlocking does not imply any I/O. How are the semantics you're describing different than a mutex? – Jason Aug 23 '15 at 05:52
  • You are assuming that all processes will do the lcok and then will do unlock. But in my case, there are processes, that will only do unlock – Amrith Krishna Aug 23 '15 at 05:54
  • I'm not sure what you're trying to accomplish, normally a semaphore/mutex represents a shared resource. How can something post/unlock if it doesn't know whether something has completed? What you're doing sounds more like a POSIX queue. – Jason Aug 23 '15 at 06:06