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