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