1SEM_WAIT(3) Linux Programmer's Manual SEM_WAIT(3)
2
3
4
6 sem_wait, sem_timedwait, sem_trywait - lock a semaphore
7
9 #include <semaphore.h>
10
11 int sem_wait(sem_t *sem);
12
13 int sem_trywait(sem_t *sem);
14
15 int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
16
17 Link with -pthread.
18
19 Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
20
21 sem_timedwait(): _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
22
24 sem_wait() decrements (locks) the semaphore pointed to by sem. If the
25 semaphore's value is greater than zero, then the decrement proceeds,
26 and the function returns, immediately. If the semaphore currently has
27 the value zero, then the call blocks until either it becomes possible
28 to perform the decrement (i.e., the semaphore value rises above zero),
29 or a signal handler interrupts the call.
30
31 sem_trywait() is the same as sem_wait(), except that if the decrement
32 cannot be immediately performed, then call returns an error (errno set
33 to EAGAIN) instead of blocking.
34
35 sem_timedwait() is the same as sem_wait(), except that abs_timeout
36 specifies a limit on the amount of time that the call should block if
37 the decrement cannot be immediately performed. The abs_timeout argu‐
38 ment points to a structure that specifies an absolute timeout in sec‐
39 onds and nanoseconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).
40 This structure is defined as follows:
41
42 struct timespec {
43 time_t tv_sec; /* Seconds */
44 long tv_nsec; /* Nanoseconds [0 .. 999999999] */
45 };
46
47 If the timeout has already expired by the time of the call, and the
48 semaphore could not be locked immediately, then sem_timedwait() fails
49 with a timeout error (errno set to ETIMEDOUT).
50
51 If the operation can be performed immediately, then sem_timedwait()
52 never fails with a timeout error, regardless of the value of abs_time‐
53 out. Furthermore, the validity of abs_timeout is not checked in this
54 case.
55
57 All of these functions return 0 on success; on error, the value of the
58 semaphore is left unchanged, -1 is returned, and errno is set to indi‐
59 cate the error.
60
62 EINTR The call was interrupted by a signal handler; see signal(7).
63
64 EINVAL sem is not a valid semaphore.
65
66 The following additional error can occur for sem_trywait():
67
68 EAGAIN The operation could not be performed without blocking (i.e., the
69 semaphore currently has the value zero).
70
71 The following additional errors can occur for sem_timedwait():
72
73 EINVAL The value of abs_timeout.tv_nsecs is less than 0, or greater
74 than or equal to 1000 million.
75
76 ETIMEDOUT
77 The call timed out before the semaphore could be locked.
78
80 POSIX.1-2001.
81
83 A signal handler always interrupts a blocked call to one of these func‐
84 tions, regardless of the use of the sigaction(2) SA_RESTART flag.
85
87 The (somewhat trivial) program shown below operates on an unnamed sema‐
88 phore. The program expects two command-line arguments. The first
89 argument specifies a seconds value that is used to set an alarm timer
90 to generate a SIGALRM signal. This handler performs a sem_post(3) to
91 increment the semaphore that is being waited on in main() using
92 sem_timedwait(). The second command-line argument specifies the length
93 of the timeout, in seconds, for sem_timedwait(). The following shows
94 what happens on two different runs of the program:
95
96 $ ./a.out 2 3
97 About to call sem_timedwait()
98 sem_post() from handler
99 sem_timedwait() succeeded
100 $ ./a.out 2 1
101 About to call sem_timedwait()
102 sem_timedwait() timed out
103
104 Program source
105
106 #include <unistd.h>
107 #include <stdio.h>
108 #include <stdlib.h>
109 #include <semaphore.h>
110 #include <time.h>
111 #include <assert.h>
112 #include <errno.h>
113 #include <signal.h>
114
115 sem_t sem;
116
117 #define handle_error(msg) \
118 do { perror(msg); exit(EXIT_FAILURE); } while (0)
119
120 static void
121 handler(int sig)
122 {
123 write(STDOUT_FILENO, "sem_post() from handler\n", 24);
124 if (sem_post(&sem) == -1) {
125 write(STDERR_FILENO, "sem_post() failed\n", 18);
126 _exit(EXIT_FAILURE);
127 }
128 }
129
130 int
131 main(int argc, char *argv[])
132 {
133 struct sigaction sa;
134 struct timespec ts;
135 int s;
136
137 if (argc != 3) {
138 fprintf(stderr, "Usage: %s <alarm-secs> <wait-secs>\n",
139 argv[0]);
140 exit(EXIT_FAILURE);
141 }
142
143 if (sem_init(&sem, 0, 0) == -1)
144 handle_error("sem_init");
145
146 /* Establish SIGALRM handler; set alarm timer using argv[1] */
147
148 sa.sa_handler = handler;
149 sigemptyset(&sa.sa_mask);
150 sa.sa_flags = 0;
151 if (sigaction(SIGALRM, &sa, NULL) == -1)
152 handle_error("sigaction");
153
154 alarm(atoi(argv[1]));
155
156 /* Calculate relative interval as current time plus
157 number of seconds given argv[2] */
158
159 if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
160 handle_error("clock_gettime");
161
162 ts.tv_sec += atoi(argv[2]);
163
164 printf("main() about to call sem_timedwait()\n");
165 while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
166 continue; /* Restart if interrupted by handler */
167
168 /* Check what happened */
169
170 if (s == -1) {
171 if (errno == ETIMEDOUT)
172 printf("sem_timedwait() timed out\n");
173 else
174 perror("sem_timedwait");
175 } else
176 printf("sem_timedwait() succeeded\n");
177
178 exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
179 }
180
182 clock_gettime(2), sem_getvalue(3), sem_post(3), sem_overview(7),
183 time(7)
184
186 This page is part of release 3.53 of the Linux man-pages project. A
187 description of the project, and information about reporting bugs, can
188 be found at http://www.kernel.org/doc/man-pages/.
189
190
191
192Linux 2012-05-13 SEM_WAIT(3)