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
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 For an explanation of the terms used in this section, see
81 attributes(7).
82
83 ┌───────────────────────────┬───────────────┬─────────┐
84 │Interface │ Attribute │ Value │
85 ├───────────────────────────┼───────────────┼─────────┤
86 │sem_wait(), sem_trywait(), │ Thread safety │ MT-Safe │
87 │sem_timedwait() │ │ │
88 └───────────────────────────┴───────────────┴─────────┘
90 POSIX.1-2001, POSIX.1-2008.
91
93 The (somewhat trivial) program shown below operates on an unnamed sema‐
94 phore. The program expects two command-line arguments. The first
95 argument specifies a seconds value that is used to set an alarm timer
96 to generate a SIGALRM signal. This handler performs a sem_post(3) to
97 increment the semaphore that is being waited on in main() using
98 sem_timedwait(). The second command-line argument specifies the length
99 of the timeout, in seconds, for sem_timedwait(). The following shows
100 what happens on two different runs of the program:
101
102 $ ./a.out 2 3
103 About to call sem_timedwait()
104 sem_post() from handler
105 sem_timedwait() succeeded
106 $ ./a.out 2 1
107 About to call sem_timedwait()
108 sem_timedwait() timed out
109
110 Program source
111
112 #include <unistd.h>
113 #include <stdio.h>
114 #include <stdlib.h>
115 #include <semaphore.h>
116 #include <time.h>
117 #include <assert.h>
118 #include <errno.h>
119 #include <signal.h>
120
121 sem_t sem;
122
123 #define handle_error(msg) \
124 do { perror(msg); exit(EXIT_FAILURE); } while (0)
125
126 static void
127 handler(int sig)
128 {
129 write(STDOUT_FILENO, "sem_post() from handler\n", 24);
130 if (sem_post(&sem) == -1) {
131 write(STDERR_FILENO, "sem_post() failed\n", 18);
132 _exit(EXIT_FAILURE);
133 }
134 }
135
136 int
137 main(int argc, char *argv[])
138 {
139 struct sigaction sa;
140 struct timespec ts;
141 int s;
142
143 if (argc != 3) {
144 fprintf(stderr, "Usage: %s <alarm-secs> <wait-secs>\n",
145 argv[0]);
146 exit(EXIT_FAILURE);
147 }
148
149 if (sem_init(&sem, 0, 0) == -1)
150 handle_error("sem_init");
151
152 /* Establish SIGALRM handler; set alarm timer using argv[1] */
153
154 sa.sa_handler = handler;
155 sigemptyset(&sa.sa_mask);
156 sa.sa_flags = 0;
157 if (sigaction(SIGALRM, &sa, NULL) == -1)
158 handle_error("sigaction");
159
160 alarm(atoi(argv[1]));
161
162 /* Calculate relative interval as current time plus
163 number of seconds given argv[2] */
164
165 if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
166 handle_error("clock_gettime");
167
168 ts.tv_sec += atoi(argv[2]);
169
170 printf("main() about to call sem_timedwait()\n");
171 while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
172 continue; /* Restart if interrupted by handler */
173
174 /* Check what happened */
175
176 if (s == -1) {
177 if (errno == ETIMEDOUT)
178 printf("sem_timedwait() timed out\n");
179 else
180 perror("sem_timedwait");
181 } else
182 printf("sem_timedwait() succeeded\n");
183
184 exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
185 }
186
188 clock_gettime(2), sem_getvalue(3), sem_post(3), sem_overview(7),
189 time(7)
190
192 This page is part of release 5.07 of the Linux man-pages project. A
193 description of the project, information about reporting bugs, and the
194 latest version of this page, can be found at
195 https://www.kernel.org/doc/man-pages/.
196
197
198
199Linux 2020-06-09 SEM_WAIT(3)