Chapter Contents |
Previous |
Next |
semop |
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.
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:
sem_op
is
a positive integer, the value of the indicated semaphore is increased by the
specified amount.
sem_op
is
a negative integer and the semaphore value is greater than or equal to
-sem_op
, the semaphore value
is decremented by
-sem_op
.
sem_op
is
a negative integer and the semaphore value is less than
-sem_op
,
semop
will either wait for the semaphore value to be raised, or return
failure, depending on whether
IPC_NOWAIT
is set in
sem_flg
. If
semop
waits,
once the semaphore value is greater than or equal to
-sem_op
, the value is decremented by
-sem_op
.
sem_op
is
zero and the semaphore value is zero, no action is taken.
sem_op
is
zero and the semaphore value is non-zero,
semop
will either wait for the semaphore value to become zero, or return
failure, depending on whether
IPC_NOWAIT
is set in
sem_flg
.
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 (|).
IPC_NOWAIT
-
Specifies that if the operation specified by
sem_op
cannot be immediately performed,
semop
should return failure with
errno
set to
EAGAIN
rather than waiting to perform the operation. If
IPC_NOWAIT
is not specified,
semop
will block until the operation can be performed, or until the
semaphore set is destroyed or a signal is received.
SEM_UNDO
-
Specifies that each successful semaphore operation be reflected in a semaphore
adjustment value maintained for the process for each semaphore changed. When
the process is terminated, each semaphore updated by the process using the
SEM_UNDO
flag is adjusted by
the semaphore adjustment value. If
SEM_UNDO
is used consistently by the process, this will have the effect
of undoing the semaphore updates performed by the process when it terminates.
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 |
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.