semop, semtimedop — semaphore operations
#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h>
| int
            semop( | int | semid, | 
| struct sembuf * | sops, | |
| unsigned | nsops ); | 
| int
            semtimedop( | int | semid, | 
| struct sembuf * | sops, | |
| unsigned | nsops, | |
| struct timespec * | timeout ); | 
| ![[Note]](../stylesheet/note.png) | Note | ||
|---|---|---|---|
| 
 | 
Each semaphore in a semaphore set has the following associated values:
unsigned short semval; /* semaphore value */ unsigned short semzcnt; /* # waiting for zero */ unsigned short semncnt; /* # waiting for increase */ pid_t sempid; /* process that did last op */
semop() performs operations
      on selected semaphores in the set indicated by semid. Each of the nsops elements in the array
      pointed to by sops
      specifies an operation to be performed on a single semaphore.
      The elements of this structure are of type struct sembuf, containing the
      following members:
unsigned short sem_num; /* semaphore number */ short sem_op; /* semaphore operation */ short sem_flg; /* operation flags */
Flags recognized in sem_flg are IPC_NOWAIT and SEM_UNDO. If an operation specifies
      SEM_UNDO, it will be
      automatically undone when the process terminates.
The set of operations contained in sops is performed in
      array order, and
      atomically, that
      is, the operations are performed either as a complete unit,
      or not at all. The behavior of the system call if not all
      operations can be performed immediately depends on the
      presence of the IPC_NOWAIT flag
      in the individual sem_flg fields, as noted
      below.
Each operation is performed on the sem_num−th semaphore of
      the semaphore set, where the first semaphore of the set is
      numbered 0. There are three types of operation, distinguished
      by the value of sem_op.
If sem_op is a
      positive integer, the operation adds this value to the
      semaphore value (semval). Furthermore, if
      SEM_UNDO is specified for this
      operation, the system updates the process undo count
      (semadj) for this
      semaphore. This operation can always proceed — it never
      forces a process to wait. The calling process must have alter
      permission on the semaphore set.
If sem_op is
      zero, the process must have read permission on the semaphore
      set. This is a "wait-for-zero" operation: if semval is zero, the operation
      can immediately proceed. Otherwise, if IPC_NOWAIT is specified in sem_flg, semop() fails with errno set to EAGAIN (and none of the operations in
      sops is performed).
      Otherwise semzcnt
      (the count of processes waiting until this semaphore's value
      becomes zero) is incremented by one and the process sleeps
      until one of the following occurs:
semval
            becomes 0, at which time the value of semzcnt is
            decremented.
The semaphore set is removed: semop() fails, with errno set to EIDRM.
The calling process catches a signal: the value of
            semzcnt is
            decremented and semop()
            fails, with errno set to
            EINTR.
The time limit specified by timeout in a semtimedop() call expires:
            semop() fails, with
            errno set to EAGAIN.
If sem_op is
      less than zero, the process must have alter permission on the
      semaphore set. If semval is greater than or
      equal to the absolute value of sem_op, the operation can
      proceed immediately: the absolute value of sem_op is subtracted from
      semval, and, if
      SEM_UNDO is specified for this
      operation, the system updates the process undo count
      (semadj) for this
      semaphore. If the absolute value of sem_op is greater than
      semval, and
      IPC_NOWAIT is specified in
      sem_flg,
      semop() fails, with
      errno set to EAGAIN (and none of the operations in
      sops is performed).
      Otherwise semncnt
      (the counter of processes waiting for this semaphore's value
      to increase) is incremented by one and the process sleeps
      until one of the following occurs:
semval
            becomes greater than or equal to the absolute value of
            sem_op, at
            which time the value of semncnt is decremented,
            the absolute value of sem_op is subtracted
            from semval
            and, if SEM_UNDO is
            specified for this operation, the system updates the
            process undo count (semadj) for this
            semaphore.
The semaphore set is removed from the system:
            semop() fails, with
            errno set to EIDRM.
The calling process catches a signal: the value of
            semncnt is
            decremented and semop()
            fails, with errno set to
            EINTR.
The time limit specified by timeout in a semtimedop() call expires: the system
            call fails, with errno set
            to EAGAIN.
On successful completion, the sempid value for each
      semaphore specified in the array pointed to by sops is set to the process ID
      of the calling process. In addition, the sem_otime is set to the
      current time.
semtimedop() behaves
      identically to semop() except
      that in those cases were the calling process would sleep, the
      duration of that sleep is limited by the amount of elapsed
      time specified by the timespec structure whose address is
      passed in the timeout
      parameter. If the specified time limit has been reached,
      semtimedop() fails with
      errno set to EAGAIN (and none of the operations in
      sops is performed).
      If the timeout
      parameter is NULL, then semtimedop() behaves exactly like
      semop().
If successful semop() and
      semtimedop() return 0;
      otherwise they return −1 with errno indicating the error.
On failure, errno is set to
      one of the following:
The argument nsops is greater than
            SEMOPM, the maximum
            number of operations allowed per system call.
The calling process does not have the permissions
            required to perform the specified semaphore operations,
            and does not have the CAP_IPC_OWNER capability.
An operation could not proceed immediately and
            either IPC_NOWAIT was
            specified in sem_flg or the time
            limit specified in timeout expired.
An address specified in either the sops or timeout parameters isn't
            accessible.
For some operation the value of sem_num is less than 0
            or greater than or equal to the number of semaphores in
            the set.
The semaphore set was removed.
While blocked in this system call, the process caught a signal.
The semaphore set doesn't exist, or semid is less than zero,
            or nsops has a
            non-positive value.
The sem_flg of some
            operation specified SEM_UNDO and the system does not have
            enough memory to allocate the undo structure.
For some operation sem_op+semval is
            greater than SEMVMX, the
            implementation dependent maximum value for semval.
semtimedop() first appeared
      in Linux 2.5.52, and was subsequently backported into kernel
      2.4.22. Glibc support for semtimedop() first appeared in version
      2.3.3.
The sem_undo
      structures of a process aren't inherited across a fork(2) system call, but
      they are inherited across an execve(2) system call.
semop() is never
      automatically restarted after being interrupted by a signal
      handler, regardless of the setting of the SA_RESTART flag when establishing a signal
      handler.
semadj is a
      per-process integer which is simply the (negative) count of
      all semaphore operations performed specifying the
      SEM_UNDO flag. When a
      semaphore's value is directly set using the SETVAL or SETALL request to semctl(2), the
      corresponding semadj values in all
      processes are cleared.
The semval,
      sempid, semzcnt, and semnct values for a semaphore
      can all be retrieved using appropriate semctl(2) calls.
The following limits on semaphore set resources affect the
      semop() call:
SEMOPMMaximum number of operations allowed for one
            semop() call (32) (on
            Linux, this limit can be read and modified via the
            third field of /proc/sys/kernel/sem).
SEMVMXMaximum allowable value for semval: implementation
            dependent (32767).
The implementation has no intrinsic limits for the adjust
      on exit maximum value (SEMAEM),
      the system wide maximum number of undo structures
      (SEMMNU) and the per-process
      maximum number of undo entries system parameters.
When a process terminates, its set of associated
      semadj structures
      is used to undo the effect of all of the semaphore operations
      it performed with the SEM_UNDO
      flag. This raises a difficulty: if one (or more) of these
      semaphore adjustments would result in an attempt to decrease
      a semaphore's value below zero, what should an implementation
      do? One possible approach would be to block until all the
      semaphore adjustments could be performed. This is however
      undesirable since it could force process termination to block
      for arbitrarily long periods. Another possibility is that
      such semaphore adjustments could be ignored altogether
      (somewhat analogously to failing when IPC_NOWAIT is specified for a semaphore
      operation). Linux adopts a third approach: decreasing the
      semaphore value as far as possible (i.e., to zero) and
      allowing process termination to proceed immediately.
In kernels 2.6.x, x <= 10, there is a bug that in some circumstances prevents a process that is waiting for a semaphore value to become zero from being woken up when the value does actually become zero. This bug is fixed in kernel 2.6.11.
The following code segment uses semop() to atomically wait for the value of
      semaphore 0 to become zero, and then increment the semaphore
      value by one.
    struct sembuf sops[2];
    int semid;
    /* Code to set semid omitted */
    sops[0].sem_num = 0;        /* Operate on semaphore 0 */
    sops[0].sem_op = 0;         /* Wait for value to equal 0 */
    sops[0].sem_flg = 0;
    sops[1].sem_num = 0;        /* Operate on semaphore 0 */
    sops[1].sem_op = 0;         /* Increment value by one */
    sops[1].sem_flg = 0;
    if (semop(semid, &sop, 2) == −1) {
        perror("semop");
        exit(EXIT_FAILURE);
    }
      This page is part of release 2.79 of the Linux man-pages project. A
      description of the project, and information about reporting
      bugs, can be found at
      http://www.kernel.org/doc/man-pages/.
| Copyright 1993 Giorgio Ciucci (giorgiocrcc.it) Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Since the Linux kernel and libraries are constantly changing, this manual page may be incorrect or out-of-date. The author(s) assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein. The author(s) may not have taken the same level of care in the production of this manual, which is licensed free of charge, as they might when working professionally. Formatted or processed versions of this manual, if unaccompanied by the source, must acknowledge the copyright and authors of this work. Modified 1996-10-22, Eric S. Raymond <esrthyrsus.com> Modified 2002-01-08, Michael Kerrisk <mtk.manpagesgmail.com> Modified 2003-04-28, Ernie Petrides <petridesredhat.com> Modified 2004-05-27, Michael Kerrisk <mtk.manpagesgmail.com> Modified, 11 Nov 2004, Michael Kerrisk <mtk.manpagesgmail.com> Language and formatting clean-ups Added notes on /proc files 2005-04-08, mtk, Noted kernel version numbers for semtimedop() 2007-07-09, mtk, Added an EXAMPLE code segment. |