These functions are the practical implementation of the theoretical “P operation” (test and decrement) we discussed earlier.
1. The sem_wait Function
This is the standard blocking function used when a process needs to acquire a resource.
#include <semaphore.h>
int sem_wait(sem_t *sem);
// Returns: 0 if OK, -1 on errorHow it works:
- Test: It checks the current value of the semaphore
sem. - Decrement (Lock):
- If value > 0: It decrements the counter by 1 and returns immediately. The process has successfully “acquired” one unit of the resource.
- If value == 0: The call blocks (sleeps). The process pauses execution and waits in a queue until some other process increments the semaphore (using
sem_post). Once woken up, it decrements the value and returns.
Key Concept: Atomicity
Crucially, the “test and decrement” happens as a single, atomic step. The kernel guarantees that no two processes can see a value of 1 and both decrement it to 0 simultaneously.
2. The sem_trywait Function
This is the non-blocking version of the function.
#include <semaphore.h>
int sem_trywait(sem_t *sem);
// Returns: 0 if OK, -1 on errorHow it works:
- Test: It checks the current value of the semaphore.
- Decrement or Fail:
- If value > 0: It decrements the counter by 1 and returns
0(Success). - If value == 0: It does not block. Instead, it returns
-1immediately and sets the error variableerrnotoEAGAIN.
- If value > 0: It decrements the counter by 1 and returns
3. When to use which?
- Use
sem_waitwhen your program absolutely cannot proceed without the resource (e.g., waiting for data to arrive in a buffer). - Use
sem_trywaitwhen your program has other work it can do if the resource isn’t ready (e.g., “Check if the printer is free; if not, I’ll update the display and try again later”).
Summary Table
| Function | Semaphore Value is > 0 | Semaphore Value is 0 |
|---|---|---|
sem_wait | Decrements value, Returns 0. | Blocks (sleeps) until value > 0. |
sem_trywait | Decrements value, Returns 0. | Returns -1 immediately (errno = EAGAIN). |