]>
Commit | Line | Data |
---|---|---|
064af421 | 1 | /* |
cf1b8a92 | 2 | * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. |
064af421 | 3 | * |
a14bc59f BP |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
064af421 | 7 | * |
a14bc59f BP |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
064af421 BP |
15 | */ |
16 | ||
17 | #include <config.h> | |
18 | #include "poll-loop.h" | |
064af421 | 19 | #include <errno.h> |
2886875a | 20 | #include <inttypes.h> |
064af421 BP |
21 | #include <poll.h> |
22 | #include <stdlib.h> | |
23 | #include <string.h> | |
064af421 BP |
24 | #include "coverage.h" |
25 | #include "dynamic-string.h" | |
d8b30702 | 26 | #include "fatal-signal.h" |
064af421 | 27 | #include "list.h" |
f89ffb0e | 28 | #include "socket-util.h" |
064af421 | 29 | #include "timeval.h" |
064af421 BP |
30 | #include "vlog.h" |
31 | ||
f89ffb0e BP |
32 | #undef poll_fd_wait |
33 | #undef poll_timer_wait | |
34 | #undef poll_timer_wait_until | |
35 | #undef poll_immediate_wake | |
36 | ||
d98e6007 | 37 | VLOG_DEFINE_THIS_MODULE(poll_loop); |
5136ce49 | 38 | |
d76f09ea BP |
39 | COVERAGE_DEFINE(poll_fd_wait); |
40 | COVERAGE_DEFINE(poll_zero_timeout); | |
41 | ||
064af421 BP |
42 | /* An event that will wake the following call to poll_block(). */ |
43 | struct poll_waiter { | |
44 | /* Set when the waiter is created. */ | |
45 | struct list node; /* Element in global waiters list. */ | |
46 | int fd; /* File descriptor. */ | |
47 | short int events; /* Events to wait for (POLLIN, POLLOUT). */ | |
f89ffb0e | 48 | const char *where; /* Where the waiter was created. */ |
064af421 BP |
49 | |
50 | /* Set only when poll_block() is called. */ | |
d474bd01 | 51 | struct pollfd *pollfd; /* Pointer to element of the pollfds array. */ |
064af421 BP |
52 | }; |
53 | ||
54 | /* All active poll waiters. */ | |
55 | static struct list waiters = LIST_INITIALIZER(&waiters); | |
56 | ||
cee03df4 BP |
57 | /* Time at which to wake up the next call to poll_block(), in milliseconds as |
58 | * returned by time_msec(), LLONG_MIN to wake up immediately, or LLONG_MAX to | |
064af421 | 59 | * wait forever. */ |
cee03df4 | 60 | static long long int timeout_when = LLONG_MAX; |
064af421 | 61 | |
f89ffb0e BP |
62 | /* Location where waiter created. */ |
63 | static const char *timeout_where; | |
064af421 | 64 | |
f89ffb0e BP |
65 | static struct poll_waiter *new_waiter(int fd, short int events, |
66 | const char *where); | |
064af421 BP |
67 | |
68 | /* Registers 'fd' as waiting for the specified 'events' (which should be POLLIN | |
69 | * or POLLOUT or POLLIN | POLLOUT). The following call to poll_block() will | |
70 | * wake up when 'fd' becomes ready for one or more of the requested events. | |
71 | * | |
72 | * The event registration is one-shot: only the following call to poll_block() | |
73 | * is affected. The event will need to be re-registered after poll_block() is | |
f89ffb0e BP |
74 | * called if it is to persist. |
75 | * | |
76 | * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h | |
77 | * for more information. */ | |
064af421 | 78 | struct poll_waiter * |
f89ffb0e | 79 | poll_fd_wait(int fd, short int events, const char *where) |
064af421 BP |
80 | { |
81 | COVERAGE_INC(poll_fd_wait); | |
f89ffb0e | 82 | return new_waiter(fd, events, where); |
064af421 BP |
83 | } |
84 | ||
85 | /* Causes the following call to poll_block() to block for no more than 'msec' | |
86 | * milliseconds. If 'msec' is nonpositive, the following call to poll_block() | |
87 | * will not block at all. | |
88 | * | |
89 | * The timer registration is one-shot: only the following call to poll_block() | |
90 | * is affected. The timer will need to be re-registered after poll_block() is | |
f89ffb0e BP |
91 | * called if it is to persist. |
92 | * | |
93 | * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h | |
94 | * for more information. */ | |
064af421 | 95 | void |
f89ffb0e | 96 | poll_timer_wait(long long int msec, const char *where) |
064af421 | 97 | { |
cee03df4 BP |
98 | long long int now = time_msec(); |
99 | long long int when; | |
100 | ||
101 | if (msec <= 0) { | |
102 | /* Wake up immediately. */ | |
103 | when = LLONG_MIN; | |
104 | } else if ((unsigned long long int) now + msec <= LLONG_MAX) { | |
105 | /* Normal case. */ | |
106 | when = now + msec; | |
107 | } else { | |
108 | /* now + msec would overflow. */ | |
109 | when = LLONG_MAX; | |
110 | } | |
111 | ||
112 | poll_timer_wait_until(when, where); | |
064af421 BP |
113 | } |
114 | ||
7cf8b266 | 115 | /* Causes the following call to poll_block() to wake up when the current time, |
cee03df4 | 116 | * as returned by time_msec(), reaches 'when' or later. If 'when' is earlier |
7cf8b266 BP |
117 | * than the current time, the following call to poll_block() will not block at |
118 | * all. | |
119 | * | |
120 | * The timer registration is one-shot: only the following call to poll_block() | |
121 | * is affected. The timer will need to be re-registered after poll_block() is | |
f89ffb0e BP |
122 | * called if it is to persist. |
123 | * | |
124 | * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h | |
125 | * for more information. */ | |
7cf8b266 | 126 | void |
cee03df4 | 127 | poll_timer_wait_until(long long int when, const char *where) |
7cf8b266 | 128 | { |
cee03df4 BP |
129 | if (when < timeout_when) { |
130 | timeout_when = when; | |
131 | timeout_where = where; | |
132 | } | |
7cf8b266 BP |
133 | } |
134 | ||
064af421 | 135 | /* Causes the following call to poll_block() to wake up immediately, without |
f89ffb0e BP |
136 | * blocking. |
137 | * | |
138 | * Ordinarily the 'where' argument is supplied automatically; see poll-loop.h | |
139 | * for more information. */ | |
064af421 | 140 | void |
f89ffb0e | 141 | poll_immediate_wake(const char *where) |
064af421 | 142 | { |
f89ffb0e | 143 | poll_timer_wait(0, where); |
064af421 BP |
144 | } |
145 | ||
959ec62e BP |
146 | /* Logs, if appropriate, that the poll loop was awakened by an event |
147 | * registered at 'where' (typically a source file and line number). The other | |
148 | * arguments have two possible interpretations: | |
149 | * | |
150 | * - If 'pollfd' is nonnull then it should be the "struct pollfd" that caused | |
d19cedb2 | 151 | * the wakeup. 'timeout' is ignored. |
959ec62e | 152 | * |
d19cedb2 BP |
153 | * - If 'pollfd' is NULL then 'timeout' is the number of milliseconds after |
154 | * which the poll loop woke up. | |
959ec62e BP |
155 | */ |
156 | static void | |
157 | log_wakeup(const char *where, const struct pollfd *pollfd, int timeout) | |
064af421 | 158 | { |
f43e80e0 | 159 | static struct vlog_rate_limit trace_rl = VLOG_RATE_LIMIT_INIT(1, 1); |
cf1b8a92 | 160 | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 10); |
959ec62e BP |
161 | enum vlog_level level; |
162 | int cpu_usage; | |
163 | struct ds s; | |
064af421 | 164 | |
959ec62e BP |
165 | cpu_usage = get_cpu_usage(); |
166 | if (VLOG_IS_DBG_ENABLED()) { | |
167 | level = VLL_DBG; | |
168 | } else if (cpu_usage > 50 && !VLOG_DROP_WARN(&rl)) { | |
169 | level = VLL_WARN; | |
170 | } else { | |
171 | return; | |
172 | } | |
064af421 | 173 | |
959ec62e BP |
174 | ds_init(&s); |
175 | ds_put_cstr(&s, "wakeup due to "); | |
176 | if (pollfd) { | |
177 | char *description = describe_fd(pollfd->fd); | |
178 | if (pollfd->revents & POLLIN) { | |
179 | ds_put_cstr(&s, "[POLLIN]"); | |
180 | } | |
181 | if (pollfd->revents & POLLOUT) { | |
182 | ds_put_cstr(&s, "[POLLOUT]"); | |
183 | } | |
184 | if (pollfd->revents & POLLERR) { | |
185 | ds_put_cstr(&s, "[POLLERR]"); | |
186 | } | |
187 | if (pollfd->revents & POLLHUP) { | |
188 | ds_put_cstr(&s, "[POLLHUP]"); | |
189 | } | |
190 | if (pollfd->revents & POLLNVAL) { | |
191 | ds_put_cstr(&s, "[POLLNVAL]"); | |
192 | } | |
193 | ds_put_format(&s, " on fd %d (%s)", pollfd->fd, description); | |
194 | free(description); | |
195 | } else { | |
196 | ds_put_format(&s, "%d-ms timeout", timeout); | |
197 | } | |
f89ffb0e | 198 | if (where) { |
959ec62e | 199 | ds_put_format(&s, " at %s", where); |
064af421 | 200 | } |
959ec62e BP |
201 | if (cpu_usage >= 0) { |
202 | ds_put_format(&s, " (%d%% CPU usage)", cpu_usage); | |
f43e80e0 EJ |
203 | |
204 | if (!vlog_should_drop(THIS_MODULE, level, &trace_rl)) { | |
205 | ds_put_char(&s, '\n'); | |
206 | format_backtraces(&s, 2); | |
207 | } | |
959ec62e BP |
208 | } |
209 | VLOG(level, "%s", ds_cstr(&s)); | |
210 | ds_destroy(&s); | |
064af421 BP |
211 | } |
212 | ||
213 | /* Blocks until one or more of the events registered with poll_fd_wait() | |
214 | * occurs, or until the minimum duration registered with poll_timer_wait() | |
d474bd01 | 215 | * elapses, or not at all if poll_immediate_wake() has been called. */ |
064af421 BP |
216 | void |
217 | poll_block(void) | |
218 | { | |
3907401c BP |
219 | static struct pollfd *pollfds; |
220 | static size_t max_pollfds; | |
221 | ||
d474bd01 | 222 | struct poll_waiter *pw, *next; |
3907401c | 223 | int n_waiters, n_pollfds; |
cee03df4 | 224 | int elapsed; |
064af421 BP |
225 | int retval; |
226 | ||
d8b30702 JG |
227 | /* Register fatal signal events before actually doing any real work for |
228 | * poll_block. */ | |
229 | fatal_signal_wait(); | |
230 | ||
934264ec | 231 | n_waiters = list_size(&waiters); |
064af421 BP |
232 | if (max_pollfds < n_waiters) { |
233 | max_pollfds = n_waiters; | |
234 | pollfds = xrealloc(pollfds, max_pollfds * sizeof *pollfds); | |
235 | } | |
236 | ||
237 | n_pollfds = 0; | |
4e8e4213 | 238 | LIST_FOR_EACH (pw, node, &waiters) { |
064af421 BP |
239 | pw->pollfd = &pollfds[n_pollfds]; |
240 | pollfds[n_pollfds].fd = pw->fd; | |
241 | pollfds[n_pollfds].events = pw->events; | |
242 | pollfds[n_pollfds].revents = 0; | |
243 | n_pollfds++; | |
244 | } | |
245 | ||
cee03df4 | 246 | if (timeout_when == LLONG_MIN) { |
064af421 BP |
247 | COVERAGE_INC(poll_zero_timeout); |
248 | } | |
cee03df4 | 249 | retval = time_poll(pollfds, n_pollfds, timeout_when, &elapsed); |
064af421 BP |
250 | if (retval < 0) { |
251 | static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); | |
252 | VLOG_ERR_RL(&rl, "poll: %s", strerror(-retval)); | |
959ec62e | 253 | } else if (!retval) { |
cee03df4 | 254 | log_wakeup(timeout_where, NULL, elapsed); |
064af421 BP |
255 | } |
256 | ||
4e8e4213 | 257 | LIST_FOR_EACH_SAFE (pw, next, node, &waiters) { |
959ec62e BP |
258 | if (pw->pollfd->revents) { |
259 | log_wakeup(pw->where, pw->pollfd, 0); | |
064af421 | 260 | } |
064af421 BP |
261 | poll_cancel(pw); |
262 | } | |
263 | ||
cee03df4 | 264 | timeout_when = LLONG_MAX; |
f89ffb0e | 265 | timeout_where = NULL; |
d8b30702 JG |
266 | |
267 | /* Handle any pending signals before doing anything else. */ | |
268 | fatal_signal_run(); | |
064af421 BP |
269 | } |
270 | ||
d474bd01 BP |
271 | /* Cancels the file descriptor event registered with poll_fd_wait() using 'pw', |
272 | * the struct poll_waiter returned by that function. | |
064af421 BP |
273 | * |
274 | * An event registered with poll_fd_wait() may be canceled from its time of | |
275 | * registration until the next call to poll_block(). At that point, the event | |
d474bd01 | 276 | * is automatically canceled by the system and its poll_waiter is freed. */ |
064af421 BP |
277 | void |
278 | poll_cancel(struct poll_waiter *pw) | |
279 | { | |
280 | if (pw) { | |
064af421 | 281 | list_remove(&pw->node); |
064af421 | 282 | free(pw); |
064af421 BP |
283 | } |
284 | } | |
285 | \f | |
286 | /* Creates and returns a new poll_waiter for 'fd' and 'events'. */ | |
287 | static struct poll_waiter * | |
f89ffb0e | 288 | new_waiter(int fd, short int events, const char *where) |
064af421 | 289 | { |
ec6fde61 | 290 | struct poll_waiter *waiter = xzalloc(sizeof *waiter); |
cb22974d | 291 | ovs_assert(fd >= 0); |
064af421 BP |
292 | waiter->fd = fd; |
293 | waiter->events = events; | |
f89ffb0e | 294 | waiter->where = where; |
064af421 | 295 | list_push_back(&waiters, &waiter->node); |
064af421 BP |
296 | return waiter; |
297 | } |