2 Unix SMB/CIFS implementation.
3 main select loop and event handling
4 Copyright (C) Andrew Tridgell 2003-2005
5 Copyright (C) Stefan Metzmacher 2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This is SAMBA's default event loop code
25 - we try to use epoll if configure detected support for it
26 otherwise we use select()
27 - if epoll is broken on the system or the kernel doesn't support it
28 at runtime we fallback to select()
32 #include "system/filesys.h"
33 #include "dlinklist.h"
34 #include "lib/events/events.h"
35 #include "lib/events/events_internal.h"
37 /* use epoll if it is available */
38 #if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H)
43 #include <sys/epoll.h>
46 struct std_event_context {
47 /* list of filedescriptor events */
48 struct fd_event *fd_events;
50 /* list of timed events */
51 struct timed_event *timed_events;
53 /* the maximum file descriptor number in fd_events */
56 /* information for exiting from the event loop */
59 /* this is changed by the destructors for the fd event
60 type. It is used to detect event destruction by event
61 handlers, which means the code that is calling the event
62 handler needs to assume that the linked list is no longer
65 uint32_t destruction_count;
68 /* when using epoll this is the handle from epoll_create */
74 destroy an event context
76 static int std_event_context_destructor(void *ptr)
79 struct event_context *ev = talloc_get_type(ptr, struct event_context);
80 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
81 struct std_event_context);
82 if (std_ev->epoll_fd != -1) {
83 close(std_ev->epoll_fd);
84 std_ev->epoll_fd = -1;
91 create a std_event_context structure.
93 static int std_event_context_init(struct event_context *ev, void *privata_data)
95 struct std_event_context *std_ev;
97 std_ev = talloc_zero(ev, struct std_event_context);
98 if (!std_ev) return -1;
101 std_ev->epoll_fd = epoll_create(64);
104 ev->additional_data = std_ev;
106 talloc_set_destructor(ev, std_event_context_destructor);
112 recalculate the maxfd
114 static void calc_maxfd(struct event_context *ev)
116 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
117 struct std_event_context);
118 struct fd_event *fde;
121 for (fde = std_ev->fd_events; fde; fde = fde->next) {
122 if (fde->fd > std_ev->maxfd) {
123 std_ev->maxfd = fde->fd;
129 /* to mark the ev->maxfd invalid
130 * this means we need to recalculate it
132 #define EVENT_INVALID_MAXFD (-1)
137 called when a epoll call fails, and we should fallback
140 static void epoll_fallback_to_select(struct event_context *ev, const char *reason)
142 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
143 struct std_event_context);
144 DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno)));
145 close(std_ev->epoll_fd);
146 std_ev->epoll_fd = -1;
153 map from EVENT_FD_* to EPOLLIN/EPOLLOUT
155 static uint32_t epoll_map_flags(uint16_t flags)
158 if (flags & EVENT_FD_READ) ret |= EPOLLIN;
159 if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT;
167 static int std_event_fd_destructor(void *ptr)
169 struct fd_event *fde = talloc_get_type(ptr, struct fd_event);
170 struct event_context *ev = fde->event_ctx;
171 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
172 struct std_event_context);
174 if (std_ev->maxfd == fde->fd) {
175 std_ev->maxfd = EVENT_INVALID_MAXFD;
177 DLIST_REMOVE(std_ev->fd_events, fde);
178 std_ev->destruction_count++;
180 if (std_ev->epoll_fd != -1) {
181 struct epoll_event event;
183 event.events = epoll_map_flags(fde->flags);
184 event.data.ptr = fde;
185 epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
193 return NULL on failure (memory allocation error)
195 static struct fd_event *std_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
196 int fd, uint16_t flags,
197 event_fd_handler_t handler,
200 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
201 struct std_event_context);
202 struct fd_event *fde;
204 fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
205 if (!fde) return NULL;
210 fde->handler = handler;
211 fde->private_data = private_data;
212 fde->additional_data = NULL;
214 DLIST_ADD(std_ev->fd_events, fde);
216 if (fde->fd > std_ev->maxfd) {
217 std_ev->maxfd = fde->fd;
220 talloc_set_destructor(fde, std_event_fd_destructor);
223 if (std_ev->epoll_fd != -1) {
224 struct epoll_event event;
226 event.events = epoll_map_flags(flags);
227 event.data.ptr = fde;
228 if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
229 epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed");
239 return the fd event flags
241 static uint16_t std_event_get_fd_flags(struct fd_event *fde)
243 return fde?fde->flags:0;
247 set the fd event flags
249 static void std_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
252 struct event_context *ev;
253 struct std_event_context *std_ev;
255 fde->flags == flags) {
259 std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
260 if (std_ev->epoll_fd != -1) {
261 struct epoll_event event;
263 event.events = epoll_map_flags(flags);
264 event.data.ptr = fde;
265 if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
266 epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed");
276 destroy a timed event
278 static int std_event_timed_destructor(void *ptr)
280 struct timed_event *te = talloc_get_type(ptr, struct timed_event);
281 struct std_event_context *std_ev = talloc_get_type(te->event_ctx->additional_data,
282 struct std_event_context);
283 DLIST_REMOVE(std_ev->timed_events, te);
289 return NULL on failure (memory allocation error)
291 static struct timed_event *std_event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
292 struct timeval next_event,
293 event_timed_handler_t handler,
296 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
297 struct std_event_context);
298 struct timed_event *te, *last_te, *cur_te;
300 te = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
301 if (te == NULL) return NULL;
304 te->next_event = next_event;
305 te->handler = handler;
306 te->private_data = private_data;
307 te->additional_data = NULL;
309 /* keep the list ordered */
311 for (cur_te = std_ev->timed_events; cur_te; cur_te = cur_te->next) {
312 /* if the new event comes before the current one break */
313 if (!timeval_is_zero(&cur_te->next_event) &&
314 timeval_compare(&cur_te->next_event, &te->next_event) < 0) {
321 DLIST_ADD_AFTER(std_ev->timed_events, te, last_te);
323 talloc_set_destructor(te, std_event_timed_destructor);
329 a timer has gone off - call it
331 static void std_event_loop_timer(struct event_context *ev)
333 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
334 struct std_event_context);
335 struct timeval t = timeval_current();
336 struct timed_event *te = std_ev->timed_events;
342 te->next_event = timeval_zero();
344 te->handler(ev, te, t, te->private_data);
346 /* note the care taken to prevent referencing a event
347 that could have been freed by the handler */
348 if (std_ev->timed_events) {
349 if (timeval_is_zero(&std_ev->timed_events->next_event)) {
357 event loop handling using epoll
359 static int std_event_loop_epoll(struct event_context *ev, struct timeval *tvalp)
361 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
362 struct std_event_context);
365 struct epoll_event events[MAXEVENTS];
366 uint32_t destruction_count = std_ev->destruction_count;
370 /* it's better to trigger timed events a bit later than to early */
371 timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
374 ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
376 if (ret == -1 && errno != EINTR) {
377 epoll_fallback_to_select(ev, "epoll_wait() failed");
381 if (ret == 0 && tvalp) {
382 std_event_loop_timer(ev);
386 for (i=0;i<ret;i++) {
387 struct fd_event *fde = talloc_get_type(events[i].data.ptr,
392 epoll_fallback_to_select(ev, "epoll_wait() gave bad data");
395 if (events[i].events & (EPOLLIN|EPOLLHUP|EPOLLERR))
396 flags |= EVENT_FD_READ;
397 if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
399 fde->handler(ev, fde, flags, fde->private_data);
400 if (destruction_count != std_ev->destruction_count) {
411 event loop handling using select()
413 static int std_event_loop_select(struct event_context *ev, struct timeval *tvalp)
415 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
416 struct std_event_context);
418 struct fd_event *fde;
420 uint32_t destruction_count = std_ev->destruction_count;
422 /* we maybe need to recalculate the maxfd */
423 if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
430 /* setup any fd events */
431 for (fde = std_ev->fd_events; fde; fde = fde->next) {
432 if (fde->flags & EVENT_FD_READ) {
433 FD_SET(fde->fd, &r_fds);
435 if (fde->flags & EVENT_FD_WRITE) {
436 FD_SET(fde->fd, &w_fds);
440 selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
442 if (selrtn == -1 && errno == EBADF) {
443 /* the socket is dead! this should never
444 happen as the socket should have first been
445 made readable and that should have removed
446 the event, so this must be a bug. This is a
448 DEBUG(0,("ERROR: EBADF on std_event_loop_once\n"));
449 std_ev->exit_code = EBADF;
453 if (selrtn == 0 && tvalp) {
454 std_event_loop_timer(ev);
459 /* at least one file descriptor is ready - check
460 which ones and call the handler, being careful to allow
461 the handler to remove itself when called */
462 for (fde = std_ev->fd_events; fde; fde = fde->next) {
465 if (FD_ISSET(fde->fd, &r_fds)) flags |= EVENT_FD_READ;
466 if (FD_ISSET(fde->fd, &w_fds)) flags |= EVENT_FD_WRITE;
468 fde->handler(ev, fde, flags, fde->private_data);
469 if (destruction_count != std_ev->destruction_count) {
480 do a single event loop using the events defined in ev
482 static int std_event_loop_once(struct event_context *ev)
484 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
485 struct std_event_context);
488 /* work out the right timeout for all timed events */
489 if (std_ev->timed_events) {
490 struct timeval t = timeval_current();
491 tval = timeval_diff(&std_ev->timed_events->next_event, &t);
492 if (timeval_is_zero(&tval)) {
493 std_event_loop_timer(ev);
497 /* have a default tick time of 30 seconds. This guarantees
498 that code that uses its own timeout checking will be
499 able to proceeed eventually */
500 tval = timeval_set(30, 0);
504 if (std_ev->epoll_fd != -1) {
505 if (std_event_loop_epoll(ev, &tval) == 0) {
511 return std_event_loop_select(ev, &tval);
515 return on failure or (with 0) if all fd events are removed
517 static int std_event_loop_wait(struct event_context *ev)
519 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
520 struct std_event_context);
521 std_ev->exit_code = 0;
523 while (std_ev->fd_events && std_ev->exit_code == 0) {
524 if (std_event_loop_once(ev) != 0) {
529 return std_ev->exit_code;
532 static const struct event_ops std_event_ops = {
533 .context_init = std_event_context_init,
534 .add_fd = std_event_add_fd,
535 .get_fd_flags = std_event_get_fd_flags,
536 .set_fd_flags = std_event_set_fd_flags,
537 .add_timed = std_event_add_timed,
538 .loop_once = std_event_loop_once,
539 .loop_wait = std_event_loop_wait,
542 const struct event_ops *event_standard_get_ops(void)
544 return &std_event_ops;