1SEMOP(2)                   Linux Programmer's Manual                  SEMOP(2)


6       semop, semtimedop - System V semaphore operations


9       #include <sys/types.h>
10       #include <sys/ipc.h>
11       #include <sys/sem.h>
13       int semop(int semid, struct sembuf *sops, size_t nsops);
15       int semtimedop(int semid, struct sembuf *sops, size_t nsops,
16                      const struct timespec *timeout);
18   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
20       semtimedop(): _GNU_SOURCE


23       Each semaphore in a System V semaphore set has the following associated
24       values:
26           unsigned short  semval;   /* semaphore value */
27           unsigned short  semzcnt;  /* # waiting for zero */
28           unsigned short  semncnt;  /* # waiting for increase */
29           pid_t           sempid;   /* PID of process that last
31       semop() performs operations on selected semaphores in the set indicated
32       by  semid.   Each of the nsops elements in the array pointed to by sops
33       is a structure that specifies an operation to be performed on a  single
34       semaphore.   The  elements of this structure are of type struct sembuf,
35       containing the following members:
37           unsigned short sem_num;  /* semaphore number */
38           short          sem_op;   /* semaphore operation */
39           short          sem_flg;  /* operation flags */
41       Flags recognized in sem_flg are IPC_NOWAIT and SEM_UNDO.  If an  opera‐
42       tion  specifies  SEM_UNDO,  it  will  be  automatically undone when the
43       process terminates.
45       The set of operations contained in sops is performed  in  array  order,
46       and  atomically, that is, the operations are performed either as a com‐
47       plete unit, or not at all.  The behavior of the system call if not  all
48       operations  can be performed immediately depends on the presence of the
49       IPC_NOWAIT flag in the individual sem_flg fields, as noted below.
51       Each operation is performed on the sem_num-th semaphore  of  the  sema‐
52       phore  set,  where the first semaphore of the set is numbered 0.  There
53       are three types of operation, distinguished by the value of sem_op.
55       If sem_op is a positive integer, the operation adds this value  to  the
56       semaphore  value  (semval).   Furthermore, if SEM_UNDO is specified for
57       this operation, the system subtracts the value sem_op  from  the  sema‐
58       phore adjustment (semadj) value for this semaphore.  This operation can
59       always proceed—it never forces a thread to wait.  The  calling  process
60       must have alter permission on the semaphore set.
62       If  sem_op  is zero, the process must have read permission on the sema‐
63       phore set.  This is a "wait-for-zero" operation: if semval is zero, the
64       operation  can immediately proceed.  Otherwise, if IPC_NOWAIT is speci‐
65       fied in sem_flg, semop() fails with errno set to EAGAIN  (and  none  of
66       the operations in sops is performed).  Otherwise, semzcnt (the count of
67       threads waiting until this semaphore's value becomes  zero)  is  incre‐
68       mented by one and the thread sleeps until one of the following occurs:
70       ·  semval becomes 0, at which time the value of semzcnt is decremented.
72       ·  The  semaphore  set  is  removed:  semop()  fails, with errno set to
73          EIDRM.
75       ·  The calling thread catches a signal: the value of semzcnt is  decre‐
76          mented and semop() fails, with errno set to EINTR.
78       If  sem_op is less than zero, the process must have alter permission on
79       the semaphore set.  If semval is greater than or equal to the  absolute
80       value  of  sem_op,  the operation can proceed immediately: the absolute
81       value of sem_op is subtracted from semval, and, if SEM_UNDO  is  speci‐
82       fied  for  this operation, the system adds the absolute value of sem_op
83       to the semaphore adjustment (semadj) value for this semaphore.  If  the
84       absolute  value  of  sem_op  is  greater than semval, and IPC_NOWAIT is
85       specified in sem_flg, semop() fails, with errno set to EAGAIN (and none
86       of  the  operations  in  sops  is  performed).  Otherwise, semncnt (the
87       counter of threads waiting for this semaphore's value to  increase)  is
88       incremented  by  one  and  the thread sleeps until one of the following
89       occurs:
91       ·  semval becomes greater than  or  equal  to  the  absolute  value  of
92          sem_op: the operation now proceeds, as described above.
94       ·  The  semaphore  set  is removed from the system: semop() fails, with
95          errno set to EIDRM.
97       ·  The calling thread catches a signal: the value of semncnt is  decre‐
98          mented and semop() fails, with errno set to EINTR.
100       On successful completion, the sempid value for each semaphore specified
101       in the array pointed to by sops is set to the caller's process ID.   In
102       addition, the sem_otime is set to the current time.
104   semtimedop()
105       semtimedop()  behaves identically to semop() except that in those cases
106       where the calling thread would sleep, the duration  of  that  sleep  is
107       limited  by the amount of elapsed time specified by the timespec struc‐
108       ture whose address is passed in  the  timeout  argument.   (This  sleep
109       interval will be rounded up to the system clock granularity, and kernel
110       scheduling delays mean  that  the  interval  may  overrun  by  a  small
111       amount.)   If  the  specified time limit has been reached, semtimedop()
112       fails with errno set to EAGAIN (and none of the operations in  sops  is
113       performed).  If the timeout argument is NULL, then semtimedop() behaves
114       exactly like semop().
116       Note that if semtimedop() is interrupted by a signal, causing the  call
117       to  fail  with  the  error  EINTR,  the  contents  of  timeout are left
118       unchanged.


121       If successful, semop() and semtimedop() return 0; otherwise they return
122       -1 with errno indicating the error.


125       On failure, errno is set to one of the following:
127       E2BIG  The argument nsops is greater than SEMOPM, the maximum number of
128              operations allowed per system call.
130       EACCES The calling process does not have the  permissions  required  to
131              perform  the  specified  semaphore operations, and does not have
132              the CAP_IPC_OWNER capability in the user namespace that  governs
133              its IPC namespace.
135       EAGAIN An operation could not proceed immediately and either IPC_NOWAIT
136              was specified in sem_flg or the time limit specified in  timeout
137              expired.
139       EFAULT An  address specified in either the sops or the timeout argument
140              isn't accessible.
142       EFBIG  For some operation the value  of  sem_num  is  less  than  0  or
143              greater than or equal to the number of semaphores in the set.
145       EIDRM  The semaphore set was removed.
147       EINTR  While  blocked  in this system call, the thread caught a signal;
148              see signal(7).
150       EINVAL The semaphore set doesn't exist, or semid is less than zero,  or
151              nsops has a nonpositive value.
153       ENOMEM The  sem_flg of some operation specified SEM_UNDO and the system
154              does not have enough memory to allocate the undo structure.
156       ERANGE For some operation sem_op+semval is  greater  than  SEMVMX,  the
157              implementation dependent maximum value for semval.


160       semtimedop() first appeared in Linux 2.5.52, and was subsequently back‐
161       ported into  kernel  2.4.22.   Glibc  support  for  semtimedop()  first
162       appeared in version 2.3.3.


165       POSIX.1-2001, POSIX.1-2008, SVr4.


168       The  inclusion of <sys/types.h> and <sys/ipc.h> isn't required on Linux
169       or by any version of POSIX.  However, some old implementations required
170       the inclusion of these header files, and the SVID also documented their
171       inclusion.  Applications intended to be portable to  such  old  systems
172       may need to include these header files.
174       The sem_undo structures of a process aren't inherited by the child pro‐
175       duced by fork(2), but they are inherited  across  an  execve(2)  system
176       call.
178       semop()  is  never automatically restarted after being interrupted by a
179       signal handler, regardless of the setting of the SA_RESTART  flag  when
180       establishing a signal handler.
182       A  semaphore  adjustment (semadj) value is a per-process, per-semaphore
183       integer that is the negated sum of all operations performed on a  sema‐
184       phore  specifying the SEM_UNDO flag.  Each process has a list of semadj
185       values—one value for each semaphore on  which  it  has  operated  using
186       SEM_UNDO.   When a process terminates, each of its per-semaphore semadj
187       values is added to the corresponding semaphore, thus undoing the effect
188       of  that  process's  operations  on the semaphore (but see BUGS below).
189       When a semaphore's value is directly set using  the  SETVAL  or  SETALL
190       request  to semctl(2), the corresponding semadj values in all processes
191       are cleared.  The clone(2) CLONE_SYSVSEM  flag  allows  more  than  one
192       process to share a semadj list; see clone(2) for details.
194       The  semval, sempid, semzcnt, and semnct values for a semaphore can all
195       be retrieved using appropriate semctl(2) calls.
197   Semaphore limits
198       The following limits on semaphore  set  resources  affect  the  semop()
199       call:
201       SEMOPM Maximum  number  of  operations  allowed  for  one semop() call.
202              Before Linux 3.19, the default value  for  this  limit  was  32.
203              Since  Linux  3.19,  the  default  value is 500.  On Linux, this
204              limit  can  be  read  and  modified  via  the  third  field   of
205              /proc/sys/kernel/sem.   Note:  this  limit  should not be raised
206              above 1000, because of the risk of that  semop()  fails  due  to
207              kernel  memory  fragmentation when allocating memory to copy the
208              sops array.
210       SEMVMX Maximum allowable value  for  semval:  implementation  dependent
211              (32767).
213       The implementation has no intrinsic limits for the adjust on exit maxi‐
214       mum value (SEMAEM), the system wide maximum number of  undo  structures
215       (SEMMNU)  and  the  per-process  maximum  number of undo entries system
216       parameters.


219       When a process terminates, its set of associated semadj  structures  is
220       used to undo the effect of all of the semaphore operations it performed
221       with the SEM_UNDO flag.  This raises a difficulty: if one (or more)  of
222       these  semaphore  adjustments  would result in an attempt to decrease a
223       semaphore's value below zero, what should an  implementation  do?   One
224       possible approach would be to block until all the semaphore adjustments
225       could be performed.  This is however undesirable since it  could  force
226       process  termination  to  block  for arbitrarily long periods.  Another
227       possibility is that such semaphore adjustments could be  ignored  alto‐
228       gether  (somewhat  analogously  to failing when IPC_NOWAIT is specified
229       for a semaphore operation).  Linux adopts a third approach:  decreasing
230       the  semaphore  value  as  far as possible (i.e., to zero) and allowing
231       process termination to proceed immediately.
233       In kernels 2.6.x, x <= 10, there is a bug that  in  some  circumstances
234       prevents  a thread that is waiting for a semaphore value to become zero
235       from being woken up when the value does actually become zero.  This bug
236       is fixed in kernel 2.6.11.


239       The  following  code  segment  uses  semop() to atomically wait for the
240       value of semaphore 0 to become zero, and then increment  the  semaphore
241       value by one.
243           struct sembuf sops[2];
244           int semid;
246           /* Code to set semid omitted */
248           sops[0].sem_num = 0;        /* Operate on semaphore 0 */
249           sops[0].sem_op = 0;         /* Wait for value to equal 0 */
250           sops[0].sem_flg = 0;
252           sops[1].sem_num = 0;        /* Operate on semaphore 0 */
253           sops[1].sem_op = 1;         /* Increment value by one */
254           sops[1].sem_flg = 0;
256           if (semop(semid, sops, 2) == -1) {
257               perror("semop");
258               exit(EXIT_FAILURE);
259           }


262       clone(2),    semctl(2),   semget(2),   sigaction(2),   capabilities(7),
263       sem_overview(7), svipc(7), time(7)


266       This page is part of release 4.16 of the Linux  man-pages  project.   A
267       description  of  the project, information about reporting bugs, and the
268       latest    version    of    this    page,    can     be     found     at
269       https://www.kernel.org/doc/man-pages/.
273Linux                             2017-09-15                          SEMOP(2)