Chapter Contents

Previous

Next
semop

semop



Update Semaphores Atomically

Portability: UNIX compatible


SYNOPSIS
DESCRIPTION
RETURN VALUE
USAGE NOTES
PORTABILITY
EXAMPLE
RELATED FUNCTIONS


SYNOPSIS

#include <sys/sem.h>
int semop(int id, struct sembuf *ops, 
          size_t num);


DESCRIPTION

The semop function is used to update one or more semaphores from a set atomically. For each update, the caller can request either blocking until the operation can be performed, or immediate failure of semop .

Note:   See the semget function description in section semget for general information about UNIX System Services semaphores.  [cautionend]

The id argument to semop specifies the id of the semaphore set to be updated. This argument is an id, such as the id returned by semget , not a semaphore set key, which might be passed as an argument to semget .

The ops argument should be a pointer to an array of one or more sembuf structures, each of which defines a single semaphore operation to be performed. All the operations are performed simultaneously and atomically; that is, no changes are made to any semaphore until they can be made to all specified semaphores. The struct sembuf mapping is defined by sys/sem.h as follows:

struct sembuf {
   /* semaphore number */
   unsigned short sem_num;

   /* semaphore operation code */
   short sem_op;

   /* option flags */
   short sem_flg;
};

The sem_num field of a struct sembuf specifies the specific semaphore to be updated. The sem_op field is interpreted in the following manner:

The sem_flg field of the sembuf structure is used to specify option flags. It may contain 0 if no options are required, or one or more of the following symbolic constants, combined by the or operator (|).

The num argument to semop indicates the number of operations specified by the ops argument.


RETURN VALUE

semop returns 0 if successful, or -1 if unsuccessful.


USAGE NOTES

The semop function can only be used with MVS 5.2.2 or a later release.


PORTABILITY

Complex semop calls may be handled differently by different systems, especially if some operations specify IPC_NOWAIT and some do not. For best results, it is recommended that IPC_NOWAIT should be either specified by all elements of the ops array, or by none of them.


EXAMPLE

This example uses a single semaphore to synchronize access to a resource. The semaphore is created the first time the application runs, and is deleted only if the first argument to the program is the string -d .

#include <sys/sem.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

int main(int argc, char *argv[])
{
  /* semaphore set id */
  int id;

  /* inital value for semaphore set */
  unsigned short available[1] = { 1 };

  /* return code var */
  int rc;

  /* to reserve the semaphore */
  struct sembuf reserve[1];

  /* to release the semaphore */
  struct sembuf release[1];

   /* If this application's semaphore 
      does not exist, create it */

  /* arg1-arbitrary unique semaphore key */
  /* arg2-only 1 semaphore in set */
  /* arg3-don't create it */
  id = semget(0x5A5C, 1, 0);

  if (id < 0)

    /* if failed, but not because
       semaphore doesn't exist */
    if (errno != ENOENT) 
    {

      badget:
      perror("semget");
      abort();
    } 

    /* no semaphore, create it */
    else 
    {
      /* unless its to be deleted */
      if (argc>1 && 
          strcmp(argv[1],"-d")==0)
          exit(0);
      id=semget(0x5A5C, 1,
           IPC_CREAT | S_IRUSR | S_IWUSR);
      /* if that fails, give up */
      if (id < 0) goto badget;

      /* Init semaphore to 1 (available) */
      rc=semctl(id, 0, SETALL, available);
      if (rc < 0) 
      {
        perror("semctl SETALL");
        abort();
      }
    }

  /* set up to reserve semaphore */
  reserve[0].sem_num = 0;

  /* try to decrement semaphore by 1 */
  reserve[0].sem_op = -1;

  /* if process dies, unreserve it */
  reserve[0].sem_flg = SEM_UNDO;
                          
  /* wait for semaphore to become
     non-zero, then zero it */
  rc = semop(id, reserve, 1);

  if (rc < 0) 
  {
    perror("semop reserve");
    abort();
  }

  /* We now have exclusive control of the 
     guarded resource. Place code here to 
     update the resource. */

  if (argc>1 && strcmp(argv[1],"-d") == 0)
  {
    /* Check for a request to delete 
       the semaphore */
    rc = semctl(id, 0, IPC_RMID);
    if (rc < 0) 
    {
      perror("semctl IPC_RMID");
      abort();
    }
    exit(0);
  }

  /* Release semaphore for next request */

  /* set up to release semaphore */
  release[0].sem_num = 0;

  /* try to increment semaphore by 1 */
  release[0].sem_op = 1;

  /* if process dies, undo it */
  release[0].sem_flg = SEM_UNDO;

  rc = semop(id, release, 1);
  if (rc < 0) 
  {
    perror("semop release");
      abort();
  }
  exit(0);
}


RELATED FUNCTIONS

semctl , semget


Chapter Contents

Previous

Next

Top of Page

Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.