]>
Commit | Line | Data |
---|---|---|
2c731798 | 1 | '\" t |
c11b1abf | 2 | .\" Copyright (C) 2006 Michael Kerrisk <mtk.manpages@gmail.com> |
2c731798 | 3 | .\" |
93015253 | 4 | .\" %%%LICENSE_START(VERBATIM) |
2c731798 MK |
5 | .\" Permission is granted to make and distribute verbatim copies of this |
6 | .\" manual provided the copyright notice and this permission notice are | |
7 | .\" preserved on all copies. | |
8 | .\" | |
9 | .\" Permission is granted to copy and distribute modified versions of this | |
10 | .\" manual under the conditions for verbatim copying, provided that the | |
11 | .\" entire resulting derived work is distributed under the terms of a | |
12 | .\" permission notice identical to this one. | |
c13182ef | 13 | .\" |
2c731798 MK |
14 | .\" Since the Linux kernel and libraries are constantly changing, this |
15 | .\" manual page may be incorrect or out-of-date. The author(s) assume no | |
16 | .\" responsibility for errors or omissions, or for damages resulting from | |
10d76543 MK |
17 | .\" the use of the information contained herein. The author(s) may not |
18 | .\" have taken the same level of care in the production of this manual, | |
19 | .\" which is licensed free of charge, as they might when working | |
20 | .\" professionally. | |
c13182ef | 21 | .\" |
2c731798 MK |
22 | .\" Formatted or processed versions of this manual, if unaccompanied by |
23 | .\" the source, must acknowledge the copyright and authors of this work. | |
4b72fb64 | 24 | .\" %%%LICENSE_END |
2c731798 | 25 | .\" |
4b8c67d9 | 26 | .TH SEM_WAIT 3 2017-09-15 "Linux" "Linux Programmer's Manual" |
2c731798 | 27 | .SH NAME |
6f4b6fc9 | 28 | sem_wait, sem_timedwait, sem_trywait \- lock a semaphore |
2c731798 MK |
29 | .SH SYNOPSIS |
30 | .nf | |
31 | .B #include <semaphore.h> | |
68e4db0a | 32 | .PP |
2c731798 | 33 | .BI "int sem_wait(sem_t *" sem ); |
68e4db0a | 34 | .PP |
2c731798 | 35 | .BI "int sem_trywait(sem_t *" sem ); |
68e4db0a | 36 | .PP |
2c731798 MK |
37 | .BI "int sem_timedwait(sem_t *" sem ", const struct timespec *" abs_timeout ); |
38 | .fi | |
68e4db0a | 39 | .PP |
2c5f8c8c | 40 | Link with \fI\-pthread\fP. |
68e4db0a | 41 | .PP |
cc4615cc MK |
42 | .in -4n |
43 | Feature Test Macro Requirements for glibc (see | |
44 | .BR feature_test_macros (7)): | |
45 | .in | |
68e4db0a | 46 | .PP |
cc4615cc | 47 | .BR sem_timedwait (): |
a446ac0c | 48 | _POSIX_C_SOURCE\ >=\ 200112L |
2c731798 MK |
49 | .SH DESCRIPTION |
50 | .BR sem_wait () | |
51 | decrements (locks) the semaphore pointed to by | |
52 | .IR sem . | |
53 | If the semaphore's value is greater than zero, | |
54 | then the decrement proceeds, and the function returns, immediately. | |
55 | If the semaphore currently has the value zero, | |
c13182ef | 56 | then the call blocks until either it becomes possible to perform |
2c731798 MK |
57 | the decrement (i.e., the semaphore value rises above zero), |
58 | or a signal handler interrupts the call. | |
847e0d88 | 59 | .PP |
2c731798 MK |
60 | .BR sem_trywait () |
61 | is the same as | |
62 | .BR sem_wait (), | |
63 | except that if the decrement cannot be immediately performed, | |
c13182ef MK |
64 | then call returns an error |
65 | .RI ( errno | |
2c731798 MK |
66 | set to |
67 | .BR EAGAIN ) | |
68 | instead of blocking. | |
847e0d88 | 69 | .PP |
2c731798 | 70 | .BR sem_timedwait () |
c13182ef | 71 | is the same as |
2c731798 MK |
72 | .BR sem_wait (), |
73 | except that | |
74 | .I abs_timeout | |
c13182ef | 75 | specifies a limit on the amount of time that the call |
2c731798 | 76 | should block if the decrement cannot be immediately performed. |
c13182ef | 77 | The |
2c731798 | 78 | .I abs_timeout |
c13182ef | 79 | argument points to a structure that specifies an absolute timeout |
f49c451a | 80 | in seconds and nanoseconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC). |
2c731798 | 81 | This structure is defined as follows: |
847e0d88 | 82 | .PP |
a08ea57c | 83 | .in +4n |
b8302363 | 84 | .EX |
2c731798 MK |
85 | struct timespec { |
86 | time_t tv_sec; /* Seconds */ | |
87 | long tv_nsec; /* Nanoseconds [0 .. 999999999] */ | |
88 | }; | |
b8302363 | 89 | .EE |
e646a1ba | 90 | .in |
2c731798 MK |
91 | .PP |
92 | If the timeout has already expired by the time of the call, | |
93 | and the semaphore could not be locked immediately, | |
c13182ef | 94 | then |
2c731798 MK |
95 | .BR sem_timedwait () |
96 | fails with a timeout error | |
97 | .RI ( errno | |
98 | set to | |
99 | .BR ETIMEDOUT ). | |
847e0d88 | 100 | .PP |
2c731798 MK |
101 | If the operation can be performed immediately, then |
102 | .BR sem_timedwait () | |
103 | never fails with a timeout error, regardless of the value of | |
104 | .IR abs_timeout . | |
c13182ef | 105 | Furthermore, the validity of |
2c731798 MK |
106 | .I abs_timeout |
107 | is not checked in this case. | |
108 | .SH RETURN VALUE | |
c13182ef | 109 | All of these functions return 0 on success; |
2c731798 MK |
110 | on error, the value of the semaphore is left unchanged, |
111 | \-1 is returned, and | |
c13182ef | 112 | .I errno |
2c731798 MK |
113 | is set to indicate the error. |
114 | .SH ERRORS | |
115 | .TP | |
116 | .B EINTR | |
01538d0d MK |
117 | The call was interrupted by a signal handler; see |
118 | .BR signal (7). | |
2c731798 MK |
119 | .TP |
120 | .B EINVAL | |
121 | .I sem | |
122 | is not a valid semaphore. | |
123 | .PP | |
124 | The following additional error can occur for | |
125 | .BR sem_trywait (): | |
126 | .TP | |
127 | .B EAGAIN | |
128 | The operation could not be performed without blocking (i.e., the | |
129 | semaphore currently has the value zero). | |
4509e795 | 130 | .PP |
2c731798 MK |
131 | The following additional errors can occur for |
132 | .BR sem_timedwait (): | |
133 | .TP | |
134 | .B EINVAL | |
135 | The value of | |
136 | .I abs_timeout.tv_nsecs | |
137 | is less than 0, or greater than or equal to 1000 million. | |
138 | .TP | |
139 | .B ETIMEDOUT | |
140 | The call timed out before the semaphore could be locked. | |
c13182ef | 141 | .\" POSIX.1-2001 also allows EDEADLK -- "A deadlock condition |
2c731798 | 142 | .\" was detected", but this does not occur on Linux(?). |
498b329f | 143 | .SH ATTRIBUTES |
8141aab5 PH |
144 | For an explanation of the terms used in this section, see |
145 | .BR attributes (7). | |
146 | .TS | |
147 | allbox; | |
148 | lbw26 lb lb | |
149 | l l l. | |
150 | Interface Attribute Value | |
151 | T{ | |
498b329f PH |
152 | .BR sem_wait (), |
153 | .BR sem_trywait (), | |
498b329f | 154 | .BR sem_timedwait () |
8141aab5 PH |
155 | T} Thread safety MT-Safe |
156 | .TE | |
2b2581ee | 157 | .SH CONFORMING TO |
e4dc59e7 | 158 | POSIX.1-2001, POSIX.1-2008. |
2c731798 MK |
159 | .SH EXAMPLE |
160 | .PP | |
c13182ef | 161 | The (somewhat trivial) program shown below operates on an |
2c731798 MK |
162 | unnamed semaphore. |
163 | The program expects two command-line arguments. | |
164 | The first argument specifies a seconds value that is used to | |
165 | set an alarm timer to generate a | |
166 | .B SIGALRM | |
167 | signal. | |
168 | This handler performs a | |
fb186734 | 169 | .BR sem_post (3) |
2c731798 MK |
170 | to increment the semaphore that is being waited on in |
171 | .I main() | |
c13182ef | 172 | using |
2c731798 MK |
173 | .BR sem_timedwait (). |
174 | The second command-line argument specifies the length | |
c13182ef | 175 | of the timeout, in seconds, for |
2c731798 MK |
176 | .BR sem_timedwait (). |
177 | The following shows what happens on two different runs of the program: | |
847e0d88 | 178 | .PP |
a08ea57c | 179 | .in +4n |
b8302363 | 180 | .EX |
b43a3b30 | 181 | .RB "$" " ./a.out 2 3" |
2c731798 MK |
182 | About to call sem_timedwait() |
183 | sem_post() from handler | |
2c731798 | 184 | sem_timedwait() succeeded |
b43a3b30 | 185 | .RB "$" " ./a.out 2 1" |
2c731798 MK |
186 | About to call sem_timedwait() |
187 | sem_timedwait() timed out | |
b8302363 | 188 | .EE |
a08ea57c | 189 | .in |
9c330504 | 190 | .SS Program source |
d84d0300 | 191 | \& |
e7d0bb47 | 192 | .EX |
2c731798 MK |
193 | #include <unistd.h> |
194 | #include <stdio.h> | |
195 | #include <stdlib.h> | |
196 | #include <semaphore.h> | |
197 | #include <time.h> | |
198 | #include <assert.h> | |
199 | #include <errno.h> | |
200 | #include <signal.h> | |
201 | ||
2c731798 MK |
202 | sem_t sem; |
203 | ||
4407d3d8 MK |
204 | #define handle_error(msg) \\ |
205 | do { perror(msg); exit(EXIT_FAILURE); } while (0) | |
206 | ||
2c731798 MK |
207 | static void |
208 | handler(int sig) | |
209 | { | |
6ba73a73 MK |
210 | write(STDOUT_FILENO, "sem_post() from handler\\n", 24); |
211 | if (sem_post(&sem) == \-1) { | |
212 | write(STDERR_FILENO, "sem_post() failed\\n", 18); | |
213 | _exit(EXIT_FAILURE); | |
214 | } | |
215 | } | |
2c731798 MK |
216 | |
217 | int | |
218 | main(int argc, char *argv[]) | |
219 | { | |
220 | struct sigaction sa; | |
221 | struct timespec ts; | |
222 | int s; | |
223 | ||
6ba73a73 MK |
224 | if (argc != 3) { |
225 | fprintf(stderr, "Usage: %s <alarm\-secs> <wait\-secs>\\n", | |
226 | argv[0]); | |
227 | exit(EXIT_FAILURE); | |
228 | } | |
2c731798 | 229 | |
4407d3d8 MK |
230 | if (sem_init(&sem, 0, 0) == \-1) |
231 | handle_error("sem_init"); | |
2c731798 MK |
232 | |
233 | /* Establish SIGALRM handler; set alarm timer using argv[1] */ | |
234 | ||
235 | sa.sa_handler = handler; | |
236 | sigemptyset(&sa.sa_mask); | |
237 | sa.sa_flags = 0; | |
5ce7e85e | 238 | if (sigaction(SIGALRM, &sa, NULL) == \-1) |
4407d3d8 | 239 | handle_error("sigaction"); |
2c731798 MK |
240 | |
241 | alarm(atoi(argv[1])); | |
242 | ||
243 | /* Calculate relative interval as current time plus | |
244 | number of seconds given argv[2] */ | |
245 | ||
4407d3d8 MK |
246 | if (clock_gettime(CLOCK_REALTIME, &ts) == \-1) |
247 | handle_error("clock_gettime"); | |
248 | ||
2c731798 MK |
249 | ts.tv_sec += atoi(argv[2]); |
250 | ||
251 | printf("main() about to call sem_timedwait()\\n"); | |
29059a65 | 252 | while ((s = sem_timedwait(&sem, &ts)) == \-1 && errno == EINTR) |
6ba73a73 | 253 | continue; /* Restart if interrupted by handler */ |
2c731798 MK |
254 | |
255 | /* Check what happened */ | |
256 | ||
29059a65 | 257 | if (s == \-1) { |
2c731798 MK |
258 | if (errno == ETIMEDOUT) |
259 | printf("sem_timedwait() timed out\\n"); | |
260 | else | |
6ba73a73 | 261 | perror("sem_timedwait"); |
2c731798 MK |
262 | } else |
263 | printf("sem_timedwait() succeeded\\n"); | |
264 | ||
6ba73a73 | 265 | exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE); |
2c731798 | 266 | } |
e7d0bb47 | 267 | .EE |
47297adb | 268 | .SH SEE ALSO |
8b98f282 | 269 | .BR clock_gettime (2), |
2c731798 MK |
270 | .BR sem_getvalue (3), |
271 | .BR sem_post (3), | |
1d7c4d16 MK |
272 | .BR sem_overview (7), |
273 | .BR time (7) |