Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
4.  Programming with Synchronization Objects Semaphores Initialize a Semaphore sem_init(3RT)  Previous   Contents   Next 
   
 

Initializing Semaphores With Interprocess Scope

When pshared is nonzero, the semaphore can be shared by other processes.

#include <semaphore.h>

sem_t sem;
int ret;
int count = 4;

/* to be shared among processes */
ret = sem_init(&sem, 1, count);

Named Semaphores

The functions sem_open(3RT), sem_getvalue(3RT), sem_close(3RT), and sem_unlink(3RT) are available to open, retrieve, close, and remove named semaphores. Using sem_open(), you can create a semaphore that has a name defined in the file system name space.

Named semaphores are like process shared semaphores, except that they are referenced with a pathname rather than a pshared value.

For more information about named semaphores, see sem_open(3RT), sem_getvalue(3RT), sem_close(3RT), and sem_unlink(3RT).

Increment a Semaphore

sem_post(3RT)

Prototype:
int	sem_post(sem_t *sem);
#include <semaphore.h>

sem_t sem;
int ret;

ret = sem_post(&sem); /* semaphore is posted */

Use sema_post(3THR) to atomically increment the semaphore pointed to by sem. When any threads are blocked on the semaphore, one of them is unblocked. (For Solaris threads, see "sema_post(3THR)".)

Return Values

sem_post() returns zero after completing successfully. Any other return value indicates that an error occurred. When the following condition occurs, the function fails and returns the corresponding value.

 

EINVAL

sem points to an illegal address.

Block on a Semaphore Count

sem_wait(3RT)

Prototype:
int	sem_wait(sem_t *sem);
#include <semaphore.h>

sem_t sem;
int ret;

ret = sem_wait(&sem); /* wait for semaphore */

Use sema_wait(3THR) to block the calling thread until the count in the semaphore pointed to by sem becomes greater than zero, then atomically decrement it.

Return Values

sem_wait() returns zero after completing successfully. Any other return value indicates that an error occurred. When any of the following conditions occurs, the function fails and returns the corresponding value.

 

EINVAL

sem points to an illegal address.

 

EINTR

A signal interrupted this function.

Decrement a Semaphore Count

sem_trywait(3RT)

Prototype:
int	sem_trywait(sem_t *sem);
#include <semaphore.h>

sem_t sem;
int ret;

ret = sem_trywait(&sem); /* try to wait for semaphore*/

Use sem_trywait(3RT) to try to atomically decrement the count in the semaphore pointed to by sem when the count is greater than zero. This function is a nonblocking version of sem_wait(); that is it returns immediately if unsuccessful.

Return Values

sem_trywait() returns zero after completing successfully. Any other return value indicates that an error occurred. When any of the following conditions occurs, the function fails and returns the corresponding value.

 

EINVAL

sem points to an illegal address.

 

EINTR

A signal interrupted this function.

 

EAGAIN

The semaphore was already locked, so it cannot be immediately locked by the sem_trywait() operation.

Destroy the Semaphore State

sem_destroy(3RT)

Prototype:
int	sem_destroy(sem_t *sem);
#include <semaphore.h>

sem_t sem;
int ret;

ret = sem_destroy(&sem); /* the semaphore is destroyed */

Use sem_destroy(3RT) to destroy any state associated with the semaphore pointed to by sem. The space for storing the semaphore is not freed. (For Solaris threads, see "sem_destroy(3THR)".)

Return Values

sem_destroy() returns zero after completing successfully. Any other return value indicates that an error occurred. When the following condition occurs, the function fails and returns the corresponding value.

 

EINVAL

sem points to an illegal address.

The Producer/Consumer Problem, Using Semaphores

The data structure in Example 4-14 is similar to that used for the condition variables example (see Example 4-11). Two semaphores represent the number of full and empty buffers and ensure that producers wait until there are empty buffers and that consumers wait until there are full buffers.


Example 4-14 The Producer/Consumer Problem With Semaphores

typedef struct {
    char buf[BSIZE];
    sem_t occupied;
    sem_t empty;
    int nextin;
    int nextout;
    sem_t pmut;
    sem_t cmut;
} buffer_t;

buffer_t buffer;

sem_init(&buffer.occupied, 0, 0);
sem_init(&buffer.empty,0, BSIZE);
sem_init(&buffer.pmut, 0, 1);
sem_init(&buffer.cmut, 0, 1);
buffer.nextin = buffer.nextout = 0;

Another pair of (binary) semaphores plays the same role as mutexes, controlling access to the buffer when there are multiple producers and multiple empty buffer slots, and when there are multiple consumers and multiple full buffer slots. Mutexes would work better here, but would not provide as good an example of semaphore use.


Example 4-15 The Producer/Consumer Problem--the Producer

void producer(buffer_t *b, char item) {
    sem_wait(&b->empty);
    sem_wait(&b->pmut);

    b->buf[b->nextin] = item;
    b->nextin++;
    b->nextin %= BSIZE;

    sem_post(&b->pmut);
    sem_post(&b->occupied);
}


Example 4-16 The Producer/Consumer Problem--the Consumer

char consumer(buffer_t *b) {
    char item;

    sem_wait(&b->occupied);
   
    sem_wait(&b->cmut);

    item = b->buf[b->nextout];
    b->nextout++;
    b->nextout %= BSIZE;

    sem_post(&b->cmut);

    sem_post(&b->empty);

    return(item);
}

 
 
 
  Previous   Contents   Next