1SEMOP(3P) POSIX Programmer's Manual SEMOP(3P)
2
3
4
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
12 semop — XSI semaphore operations
13
15 #include <sys/sem.h>
16
17 int semop(int semid, struct sembuf *sops, size_t nsops);
18
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 ┌───────────────┬───────────────┬──────────────────────────┐
39 │ Member Type │ Member Name │ Description │
40 ├───────────────┼───────────────┼──────────────────────────┤
41 │unsigned short │ sem_num │Semaphore number. │
42 │short │ sem_op │Semaphore operation. │
43 │short │ 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
128 Upon successful completion, semop() shall return 0; otherwise, it shall
129 return -1 and set errno to indicate the error.
130
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
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
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
292 None.
293
295 None.
296
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)