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
11
13 semop — XSI semaphore operations
14
16 #include <sys/sem.h>
17
18 int semop(int semid, struct sembuf *sops, size_t nsops);
19
21 The semop() function operates on XSI semaphores (see the Base Defini‐
22 tions volume of POSIX.1‐2008, Section 4.16, Semaphore). It is unspeci‐
23 fied whether this function interoperates with the realtime interprocess
24 communication facilities defined in Section 2.8, Realtime.
25
26 The semop() function shall perform atomically a user-defined array of
27 semaphore operations in array order on the set of semaphores associated
28 with the semaphore identifier specified by the argument semid.
29
30 The argument sops is a pointer to a user-defined array of semaphore
31 operation structures. The implementation shall not modify elements of
32 this array unless the application uses implementation-defined exten‐
33 sions.
34
35 The argument nsops is the number of such structures in the array.
36
37 Each structure, sembuf, includes the following members:
38
39 ┌───────────────┬───────────────┬──────────────────────────┐
40 │ Member Type │ Member Name │ Description │
41 ├───────────────┼───────────────┼──────────────────────────┤
42 │unsigned short │ sem_num │Semaphore number. │
43 │short │ sem_op │Semaphore operation. │
44 │short │ sem_flg │Operation flags. │
45 └───────────────┴───────────────┴──────────────────────────┘
46 Each semaphore operation specified by sem_op is performed on the corre‐
47 sponding semaphore specified by semid and sem_num.
48
49 The variable sem_op specifies one of three semaphore operations:
50
51 1. If sem_op is a negative integer and the calling process has alter
52 permission, one of the following shall occur:
53
54 * If semval(see <sys/sem.h>) is greater than or equal to the
55 absolute value of sem_op, the absolute value of sem_op is sub‐
56 tracted from semval. Also, if (sem_flg &SEM_UNDO) is non-zero,
57 the absolute value of sem_op shall be added to the semadj value
58 of the calling process for the specified semaphore.
59
60 * If semval is less than the absolute value of sem_op and
61 (sem_flg &IPC_NOWAIT) is non-zero, semop() shall return immedi‐
62 ately.
63
64 * If semval is less than the absolute value of sem_op and
65 (sem_flg &IPC_NOWAIT) is 0, semop() shall increment the semncnt
66 associated with the specified semaphore and suspend execution
67 of the calling thread until one of the following conditions
68 occurs:
69
70 -- The value of semval becomes greater than or equal to the
71 absolute value of sem_op. When this occurs, the value of
72 semncnt associated with the specified semaphore shall be
73 decremented, the absolute value of sem_op shall be sub‐
74 tracted from semval and, if (sem_flg &SEM_UNDO) is non-
75 zero, the absolute value of sem_op shall be added to the
76 semadj value of the calling process for the specified sema‐
77 phore.
78
79 -- The semid for which the calling thread is awaiting action
80 is removed from the system. When this occurs, errno shall
81 be set to [EIDRM] and −1 shall be returned.
82
83 -- The calling thread receives a signal that is to be caught.
84 When this occurs, the value of semncnt associated with the
85 specified semaphore shall be decremented, and the calling
86 thread shall resume execution in the manner prescribed in
87 sigaction().
88
89 2. If sem_op is a positive integer and the calling process has alter
90 permission, the value of sem_op shall be added to semval and, if
91 (sem_flg &SEM_UNDO) is non-zero, the value of sem_op shall be sub‐
92 tracted from the semadj value of the calling process for the speci‐
93 fied semaphore.
94
95 3. If sem_op is 0 and the calling process has read permission, one of
96 the following shall occur:
97
98 * If semval is 0, semop() shall return immediately.
99
100 * If semval is non-zero and (sem_flg &IPC_NOWAIT) is non-zero,
101 semop() shall return immediately.
102
103 * If semval is non-zero and (sem_flg &IPC_NOWAIT) is 0, semop()
104 shall increment the semzcnt associated with the specified sema‐
105 phore and suspend execution of the calling thread until one of
106 the following occurs:
107
108 -- The value of semval becomes 0, at which time the value of
109 semzcnt associated with the specified semaphore shall be
110 decremented.
111
112 -- The semid for which the calling thread is awaiting action
113 is removed from the system. When this occurs, errno shall
114 be set to [EIDRM] and −1 shall be returned.
115
116 -- The calling thread receives a signal that is to be caught.
117 When this occurs, the value of semzcnt associated with the
118 specified semaphore shall be decremented, and the calling
119 thread shall resume execution in the manner prescribed in
120 sigaction().
121
122 Upon successful completion, the value of sempid for each semaphore
123 specified in the array pointed to by sops shall be set to the process
124 ID of the calling process. Also, the sem_otime timestamp shall be set
125 to the current time, as described in Section 2.7.1, IPC General
126 Description.
127
129 Upon successful completion, semop() shall return 0; otherwise, it shall
130 return −1 and set errno to indicate the error.
131
133 The semop() function shall fail if:
134
135 E2BIG The value of nsops is greater than the system-imposed maximum.
136
137 EACCES Operation permission is denied to the calling process; see Sec‐
138 tion 2.7, XSI Interprocess Communication.
139
140 EAGAIN The operation would result in suspension of the calling process
141 but (sem_flg &IPC_NOWAIT) is non-zero.
142
143 EFBIG The value of sem_num is greater than or equal to the number of
144 semaphores in the set associated with semid.
145
146 EIDRM The semaphore identifier semid is removed from the system.
147
148 EINTR The semop() function was interrupted by a signal.
149
150 EINVAL The value of semid is not a valid semaphore identifier, or the
151 number of individual semaphores for which the calling process
152 requests a SEM_UNDO would exceed the system-imposed limit.
153
154 ENOSPC The limit on the number of individual processes requesting a
155 SEM_UNDO would be exceeded.
156
157 ERANGE An operation would cause a semval to overflow the system-imposed
158 limit, or an operation would cause a semadj value to overflow
159 the system-imposed limit.
160
161 The following sections are informative.
162
164 Setting Values in Semaphores
165 The following example sets the values of the two semaphores associated
166 with the semid identifier to the values contained in the sb array.
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 #include <stdio.h>
214 #include <sys/sem.h>
215 #include <sys/stat.h>
216 #include <errno.h>
217 #include <stdlib.h>
218 ...
219 key_t semkey;
220 int semid;
221 struct sembuf sbuf;
222 union semun {
223 int val;
224 struct semid_ds *buf;
225 unsigned short *array;
226 } arg;
227 struct semid_ds ds;
228 ...
229 /* Get unique key for semaphore. */
230 if ((semkey = ftok("/tmp", 'a')) == (key_t) -1) {
231 perror("IPC error: ftok"); exit(1);
232 }
233
234 /* Get semaphore ID associated with this key. */
235 if ((semid = semget(semkey, 0, 0)) == -1) {
236
237 /* Semaphore does not exist - Create. */
238 if ((semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | S_IRUSR |
239 S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != -1)
240 {
241 /* Initialize the semaphore. */
242 arg.val = 0;
243 sbuf.sem_num = 0;
244 sbuf.sem_op = 2; /* This is the number of runs without queuing. */
245 sbuf.sem_flg = 0;
246 if (semctl(semid, 0, SETVAL, arg) == -1
247 || semop(semid, &sbuf, 1) == -1) {
248 perror("IPC error: semop"); exit(1);
249 }
250 }
251 else if (errno == EEXIST) {
252 if ((semid = semget(semkey, 0, 0)) == -1) {
253 perror("IPC error 1: semget"); exit(1);
254 }
255 goto check_init;
256 }
257 else {
258 perror("IPC error 2: semget"); exit(1);
259 }
260 }
261 else
262 {
263 /* Check that semid has completed initialization. */
264 /* An application can use a retry loop at this point rather than
265 exiting. */
266 check_init:
267 arg.buf = &ds;
268 if (semctl(semid, 0, IPC_STAT, arg) < 0) {
269 perror("IPC error 3: semctl"); exit(1);
270 }
271 if (ds.sem_otime == 0) {
272 perror("IPC error 4: semctl"); exit(1);
273 }
274 }
275 ...
276 sbuf.sem_num = 0;
277 sbuf.sem_op = -1;
278 sbuf.sem_flg = SEM_UNDO;
279 if (semop(semid, &sbuf, 1) == -1) {
280 perror("IPC Error: semop"); exit(1);
281 }
282
284 The POSIX Realtime Extension defines alternative interfaces for inter‐
285 process communication. Application developers who need to use IPC
286 should design their applications so that modules using the IPC routines
287 described in Section 2.7, XSI Interprocess Communication can be easily
288 modified to use the alternative interfaces.
289
291 None.
292
294 None.
295
297 Section 2.7, XSI Interprocess Communication, Section 2.8, Realtime,
298 exec, exit(), fork(), semctl(), semget(), sem_close(), sem_destroy(),
299 sem_getvalue(), sem_init(), sem_open(), sem_post(), sem_trywait(),
300 sem_unlink()
301
302 The Base Definitions volume of POSIX.1‐2008, Section 4.16, Semaphore,
303 <sys_ipc.h>, <sys_sem.h>, <sys_types.h>
304
306 Portions of this text are reprinted and reproduced in electronic form
307 from IEEE Std 1003.1, 2013 Edition, Standard for Information Technology
308 -- Portable Operating System Interface (POSIX), The Open Group Base
309 Specifications Issue 7, Copyright (C) 2013 by the Institute of Electri‐
310 cal and Electronics Engineers, Inc and The Open Group. (This is
311 POSIX.1-2008 with the 2013 Technical Corrigendum 1 applied.) 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.unix.org/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 2013 SEMOP(3P)