1SEMOP(3P)                  POSIX Programmer's Manual                 SEMOP(3P)
2
3
4

PROLOG

6       This  manual  page is part of the POSIX Programmer's Manual.  The Linux
7       implementation of this interface may differ (consult the  corresponding
8       Linux  manual page for details of Linux behavior), or the interface may
9       not be implemented on Linux.
10

NAME

12       semop — XSI semaphore operations
13

SYNOPSIS

15       #include <sys/sem.h>
16
17       int semop(int semid, struct sembuf *sops, size_t nsops);
18

DESCRIPTION

20       The semop() function operates on XSI semaphores (see the  Base  Defini‐
21       tions volume of POSIX.1‐2017, Section 4.17, Semaphore).  It is unspeci‐
22       fied whether this function interoperates with the realtime interprocess
23       communication facilities defined in Section 2.8, Realtime.
24
25       The  semop()  function shall perform atomically a user-defined array of
26       semaphore operations in array order on the set of semaphores associated
27       with the semaphore identifier specified by the argument semid.
28
29       The  argument  sops  is  a pointer to a user-defined array of semaphore
30       operation structures. The implementation shall not modify  elements  of
31       this  array  unless  the application uses implementation-defined exten‐
32       sions.
33
34       The argument nsops is the number of such structures in the array.
35
36       Each structure, sembuf, includes the following members:
37
38             ┌───────────────┬───────────────┬──────────────────────────┐
39Member Type   Member Name   Description        
40             ├───────────────┼───────────────┼──────────────────────────┤
41unsigned short sem_num       │Semaphore number.         │
42short          sem_op        │Semaphore operation.      │
43short          sem_flg       │Operation flags.          │
44             └───────────────┴───────────────┴──────────────────────────┘
45       Each semaphore operation specified by sem_op is performed on the corre‐
46       sponding semaphore specified by semid and sem_num.
47
48       The variable sem_op specifies one of three semaphore operations:
49
50        1. If  sem_op  is a negative integer and the calling process has alter
51           permission, one of the following shall occur:
52
53            *  If semval(see <sys/sem.h>) is greater  than  or  equal  to  the
54               absolute  value of sem_op, the absolute value of sem_op is sub‐
55               tracted from semval.  Also, if (sem_flg &SEM_UNDO) is non-zero,
56               the absolute value of sem_op shall be added to the semadj value
57               of the calling process for the specified semaphore.
58
59            *  If semval is  less  than  the  absolute  value  of  sem_op  and
60               (sem_flg &IPC_NOWAIT) is non-zero, semop() shall return immedi‐
61               ately.
62
63            *  If semval is  less  than  the  absolute  value  of  sem_op  and
64               (sem_flg &IPC_NOWAIT) is 0, semop() shall increment the semncnt
65               associated with the specified semaphore and  suspend  execution
66               of  the  calling  thread  until one of the following conditions
67               occurs:
68
69               --  The value of semval becomes greater than or  equal  to  the
70                   absolute  value  of sem_op.  When this occurs, the value of
71                   semncnt associated with the specified  semaphore  shall  be
72                   decremented,  the  absolute  value  of sem_op shall be sub‐
73                   tracted from semval and, if  (sem_flg  &SEM_UNDO)  is  non-
74                   zero,  the  absolute  value of sem_op shall be added to the
75                   semadj value of the calling process for the specified sema‐
76                   phore.
77
78               --  The  semid  for which the calling thread is awaiting action
79                   is removed from the system. When this occurs,  errno  shall
80                   be set to [EIDRM] and -1 shall be returned.
81
82               --  The  calling thread receives a signal that is to be caught.
83                   When this occurs, the value of semncnt associated with  the
84                   specified  semaphore  shall be decremented, and the calling
85                   thread shall resume execution in the manner  prescribed  in
86                   sigaction().
87
88        2. If  sem_op  is a positive integer and the calling process has alter
89           permission, the value of sem_op shall be added to  semval  and,  if
90           (sem_flg  &SEM_UNDO) is non-zero, the value of sem_op shall be sub‐
91           tracted from the semadj value of the calling process for the speci‐
92           fied semaphore.
93
94        3. If  sem_op is 0 and the calling process has read permission, one of
95           the following shall occur:
96
97            *  If semval is 0, semop() shall return immediately.
98
99            *  If semval is non-zero and (sem_flg  &IPC_NOWAIT)  is  non-zero,
100               semop() shall return immediately.
101
102            *  If  semval  is non-zero and (sem_flg &IPC_NOWAIT) is 0, semop()
103               shall increment the semzcnt associated with the specified sema‐
104               phore  and suspend execution of the calling thread until one of
105               the following occurs:
106
107               --  The value of semval becomes 0, at which time the  value  of
108                   semzcnt  associated  with  the specified semaphore shall be
109                   decremented.
110
111               --  The semid for which the calling thread is  awaiting  action
112                   is  removed  from the system. When this occurs, errno shall
113                   be set to [EIDRM] and -1 shall be returned.
114
115               --  The calling thread receives a signal that is to be  caught.
116                   When  this occurs, the value of semzcnt associated with the
117                   specified semaphore shall be decremented, and  the  calling
118                   thread  shall  resume execution in the manner prescribed in
119                   sigaction().
120
121       Upon successful completion, the value  of  sempid  for  each  semaphore
122       specified  in  the array pointed to by sops shall be set to the process
123       ID of the calling process. Also, the sem_otime timestamp shall  be  set
124       to  the  current  time,  as  described  in  Section  2.7.1, IPC General
125       Description.
126

RETURN VALUE

128       Upon successful completion, semop() shall return 0; otherwise, it shall
129       return -1 and set errno to indicate the error.
130

ERRORS

132       The semop() function shall fail if:
133
134       E2BIG  The value of nsops is greater than the system-imposed maximum.
135
136       EACCES Operation  permission is denied to the calling process; see Sec‐
137              tion 2.7, XSI Interprocess Communication.
138
139       EAGAIN The operation would result in suspension of the calling  process
140              but (sem_flg &IPC_NOWAIT) is non-zero.
141
142       EFBIG  The  value  of sem_num is greater than or equal to the number of
143              semaphores in the set associated with semid.
144
145       EIDRM  The semaphore identifier semid is removed from the system.
146
147       EINTR  The semop() function was interrupted by a signal.
148
149       EINVAL The value of semid is not a valid semaphore identifier,  or  the
150              number  of  individual  semaphores for which the calling process
151              requests a SEM_UNDO would exceed the system-imposed limit.
152
153       ENOSPC The limit on the number of  individual  processes  requesting  a
154              SEM_UNDO would be exceeded.
155
156       ERANGE An operation would cause a semval to overflow the system-imposed
157              limit, or an operation would cause a semadj  value  to  overflow
158              the system-imposed limit.
159
160       The following sections are informative.
161

EXAMPLES

163   Setting Values in Semaphores
164       The  following example sets the values of the two semaphores associated
165       with the semid identifier to the values contained in the sb array.
166
167
168           #include <sys/sem.h>
169           ...
170           int semid;
171           struct sembuf sb[2];
172           int nsops = 2;
173           int result;
174
175           /* Code to initialize semid. */
176           ...
177
178           /* Adjust value of semaphore in the semaphore array semid. */
179           sb[0].sem_num = 0;
180           sb[0].sem_op = -1;
181           sb[0].sem_flg = SEM_UNDO | IPC_NOWAIT;
182           sb[1].sem_num = 1;
183           sb[1].sem_op = 1;
184           sb[1].sem_flg = 0;
185
186           result = semop(semid, sb, nsops);
187
188   Creating a Semaphore Identifier
189       The following example gets a unique  semaphore  key  using  the  ftok()
190       function,  then  gets a semaphore ID associated with that key using the
191       semget() function (the first call also tests to make sure the semaphore
192       exists).   If  the semaphore does not exist, the program creates it, as
193       shown by the second call to semget().  In creating  the  semaphore  for
194       the  queuing process, the program attempts to create one semaphore with
195       read/write permission for all. It also uses the  IPC_EXCL  flag,  which
196       forces semget() to fail if the semaphore already exists.
197
198       After  creating  the  semaphore, the program uses calls to semctl() and
199       semop() to initialize it to the values in the sbuf array. The number of
200       processes  that  can  execute concurrently without queuing is initially
201       set to 2. The final call to semget()  creates  a  semaphore  identifier
202       that can be used later in the program.
203
204       Processes that obtain semid without creating it check that sem_otime is
205       non-zero, to ensure that the creating process has completed the semop()
206       initialization.
207
208       The  final call to semop() acquires the semaphore and waits until it is
209       free; the SEM_UNDO option  releases  the  semaphore  when  the  process
210       exits,  waiting until there are less than two processes running concur‐
211       rently.
212
213
214           #include <stdio.h>
215           #include <sys/sem.h>
216           #include <sys/stat.h>
217           #include <errno.h>
218           #include <stdlib.h>
219           ...
220           key_t semkey;
221           int semid;
222           struct sembuf sbuf;
223           union semun {
224               int val;
225               struct semid_ds *buf;
226               unsigned short *array;
227           } arg;
228           struct semid_ds ds;
229           ...
230           /* Get unique key for semaphore. */
231           if ((semkey = ftok("/tmp", 'a')) == (key_t) -1) {
232               perror("IPC error: ftok"); exit(1);
233           }
234
235           /* Get semaphore ID associated with this key. */
236           if ((semid = semget(semkey, 0, 0)) == -1) {
237
238               /* Semaphore does not exist - Create. */
239               if ((semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | S_IRUSR |
240                   S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != -1)
241               {
242                   /* Initialize the semaphore. */
243                   arg.val = 0;
244                   sbuf.sem_num = 0;
245                   sbuf.sem_op = 2;  /* This is the number of runs without queuing. */
246                   sbuf.sem_flg = 0;
247                   if (semctl(semid, 0, SETVAL, arg) == -1
248                       || semop(semid, &sbuf, 1) == -1) {
249                       perror("IPC error: semop"); exit(1);
250                   }
251               }
252               else if (errno == EEXIST) {
253                   if ((semid = semget(semkey, 0, 0)) == -1) {
254                       perror("IPC error 1: semget"); exit(1);
255                   }
256                   goto check_init;
257               }
258               else {
259                   perror("IPC error 2: semget"); exit(1);
260               }
261           }
262           else
263           {
264               /* Check that semid has completed initialization. */
265               /* An application can use a retry loop at this point rather than
266                  exiting. */
267               check_init:
268               arg.buf = &ds;
269               if (semctl(semid, 0, IPC_STAT, arg) < 0) {
270                   perror("IPC error 3: semctl"); exit(1);
271               }
272               if (ds.sem_otime == 0) {
273                   perror("IPC error 4: semctl"); exit(1);
274               }
275           }
276           ...
277           sbuf.sem_num = 0;
278           sbuf.sem_op = -1;
279           sbuf.sem_flg = SEM_UNDO;
280           if (semop(semid, &sbuf, 1) == -1) {
281               perror("IPC Error: semop"); exit(1);
282           }
283

APPLICATION USAGE

285       The POSIX Realtime Extension defines alternative interfaces for  inter‐
286       process  communication.  Application  developers  who  need  to use IPC
287       should design their applications so that modules using the IPC routines
288       described  in Section 2.7, XSI Interprocess Communication can be easily
289       modified to use the alternative interfaces.
290

RATIONALE

292       None.
293

FUTURE DIRECTIONS

295       None.
296

SEE ALSO

298       Section 2.7, XSI Interprocess  Communication,  Section  2.8,  Realtime,
299       exec,  exit(),  fork(), semctl(), semget(), sem_close(), sem_destroy(),
300       sem_getvalue(),  sem_init(),  sem_open(),  sem_post(),   sem_trywait(),
301       sem_unlink()
302
303       The  Base  Definitions volume of POSIX.1‐2017, Section 4.17, Semaphore,
304       <sys_ipc.h>, <sys_sem.h>, <sys_types.h>
305
307       Portions of this text are reprinted and reproduced in  electronic  form
308       from  IEEE Std 1003.1-2017, Standard for Information Technology -- Por‐
309       table Operating System Interface (POSIX), The Open Group Base  Specifi‐
310       cations  Issue  7, 2018 Edition, Copyright (C) 2018 by the Institute of
311       Electrical and Electronics Engineers, Inc and The Open Group.   In  the
312       event of any discrepancy between this version and the original IEEE and
313       The Open Group Standard, the original IEEE and The Open Group  Standard
314       is  the  referee document. The original Standard can be obtained online
315       at http://www.opengroup.org/unix/online.html .
316
317       Any typographical or formatting errors that appear  in  this  page  are
318       most likely to have been introduced during the conversion of the source
319       files to man page format. To report such errors,  see  https://www.ker
320       nel.org/doc/man-pages/reporting_bugs.html .
321
322
323
324IEEE/The Open Group                  2017                            SEMOP(3P)
Impressum