2 Unix SMB/CIFS implementation.
3 main select loop and event handling
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 PLEASE READ THIS BEFORE MODIFYING!
24 This module is a general abstraction for the main select loop and
25 event handling. Do not ever put any localised hacks in here, instead
26 register one of the possible event types and implement that event
29 There are 2 types of event handling that are handled in this module:
31 1) a file descriptor becoming readable or writeable. This is mostly
32 used for network sockets, but can be used for any type of file
33 descriptor. You may only register one handler for each file
34 descriptor/io combination or you will get unpredictable results
35 (this means that you can have a handler for read events, and a
36 separate handler for write events, but not two handlers that are
37 both handling read events)
39 2) a timed event. You can register an event that happens at a
40 specific time. You can register as many of these as you
41 like. They are single shot - add a new timed event in the event
42 handler to get another event.
44 To setup a set of events you first need to create a event_context
45 structure using the function event_context_init(); This returns a
46 'struct event_context' that you use in all subsequent calls.
48 After that you can add/remove events that you are interested in
49 using event_add_*() and talloc_free()
51 Finally, you call event_loop_wait() to block waiting for one of the
52 events to occor. In normal operation event_loop_wait() will loop
58 #include "system/time.h"
59 #include "system/select.h"
60 #include "dlinklist.h"
61 #include "lib/events/events.h"
63 /* use epoll if it is available */
64 #if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H)
69 #include <sys/epoll.h>
72 struct event_context {
73 /* list of filedescriptor events */
75 struct event_context *event_ctx;
76 struct fd_event *next, *prev;
78 uint16_t flags; /* see EVENT_FD_* flags */
79 event_fd_handler_t handler;
83 /* list of timed events */
85 struct event_context *event_ctx;
86 struct timed_event *next, *prev;
87 struct timeval next_event;
88 event_timed_handler_t handler;
92 /* the maximum file descriptor number in fd_events */
95 /* information for exiting from the event loop */
98 /* this is changed by the destructors for the fd event
99 type. It is used to detect event destruction by event
100 handlers, which means the code that is calling the event
101 handler needs to assume that the linked list is no longer
104 uint32_t destruction_count;
107 /* when using epoll this is the handle from epoll_create */
114 destroy an event context
116 static int event_context_destructor(void *ptr)
119 struct event_context *ev = talloc_get_type(ptr, struct event_context);
120 if (ev->epoll_fd != -1) {
129 create a event_context structure. This must be the first events
130 call, and all subsequent calls pass this event_context as the first
131 element. Event handlers also receive this as their first argument.
133 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
135 struct event_context *ev;
137 ev = talloc_zero(mem_ctx, struct event_context);
138 if (!ev) return NULL;
141 ev->epoll_fd = epoll_create(64);
144 talloc_set_destructor(ev, event_context_destructor);
151 recalculate the maxfd
153 static void calc_maxfd(struct event_context *ev)
157 for (e=ev->fd_events; e; e=e->next) {
158 if (e->fd > ev->maxfd) {
165 /* to mark the ev->maxfd invalid
166 * this means we need to recalculate it
168 #define EVENT_INVALID_MAXFD (-1)
173 called when a epoll call fails, and we should fallback
176 static void epoll_fallback_to_select(struct event_context *ev, const char *reason)
178 DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno)));
187 map from EVENT_FD_* to EPOLLIN/EPOLLOUT
189 static uint32_t epoll_map_flags(uint16_t flags)
192 if (flags & EVENT_FD_READ) ret |= EPOLLIN;
193 if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT;
201 static int event_fd_destructor(void *ptr)
203 struct fd_event *fde = talloc_get_type(ptr, struct fd_event);
204 struct event_context *ev = fde->event_ctx;
206 if (ev->maxfd == fde->fd) {
207 ev->maxfd = EVENT_INVALID_MAXFD;
209 DLIST_REMOVE(ev->fd_events, fde);
210 ev->destruction_count++;
212 if (ev->epoll_fd != -1) {
213 struct epoll_event event;
215 event.events = epoll_map_flags(fde->flags);
216 event.data.ptr = fde;
217 epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
225 return NULL on failure (memory allocation error)
227 struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
228 int fd, uint16_t flags, event_fd_handler_t handler,
231 struct fd_event *e = talloc(ev, struct fd_event);
237 e->handler = handler;
238 e->private = private;
240 DLIST_ADD(ev->fd_events, e);
242 if (e->fd > ev->maxfd) {
246 talloc_set_destructor(e, event_fd_destructor);
248 talloc_steal(mem_ctx, e);
252 if (ev->epoll_fd != -1) {
253 struct epoll_event event;
255 event.events = epoll_map_flags(flags);
257 if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_ADD, e->fd, &event) != 0) {
258 epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed");
268 return the fd event flags
270 uint16_t event_fd_flags(struct fd_event *fde)
272 return fde?fde->flags:0;
276 set the fd event flags
278 void event_fd_setflags(struct fd_event *fde, uint16_t flags)
281 struct event_context *ev;
283 fde->flags == flags) {
287 if (ev->epoll_fd != -1) {
288 struct epoll_event event;
290 event.events = epoll_map_flags(flags);
291 event.data.ptr = fde;
292 if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
293 epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed");
303 destroy a timed event
305 static int event_timed_destructor(void *ptr)
307 struct timed_event *te = talloc_get_type(ptr, struct timed_event);
308 DLIST_REMOVE(te->event_ctx->timed_events, te);
314 return NULL on failure (memory allocation error)
316 struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
317 struct timeval next_event,
318 event_timed_handler_t handler,
321 struct timed_event *te, *e;
323 e = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
324 if (e == NULL) return NULL;
327 e->next_event = next_event;
328 e->handler = handler;
329 e->private = private;
331 /* keep the list ordered */
332 if (ev->timed_events == NULL ||
333 timeval_compare(&e->next_event, &ev->timed_events->next_event) > 0) {
334 DLIST_ADD(ev->timed_events, e);
336 for (te=ev->timed_events;te && te->next;te=te->next) {
337 if (!timeval_is_zero(&te->next->next_event) &&
338 timeval_compare(&te->next->next_event, &e->next_event) < 0) {
342 DLIST_ADD_AFTER(ev->timed_events, e, te);
345 talloc_set_destructor(e, event_timed_destructor);
351 a timer has gone off - call it
353 static void event_loop_timer(struct event_context *ev)
355 struct timeval t = timeval_current();
356 struct timed_event *te = ev->timed_events;
358 te->next_event = timeval_zero();
360 te->handler(ev, te, t, te->private);
362 /* note the care taken to prevent referencing a event
363 that could have been freed by the handler */
364 if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) {
365 talloc_free(ev->timed_events);
371 event loop handling using epoll
373 static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp)
376 const int maxevents = 8;
377 struct epoll_event events[maxevents];
378 uint32_t destruction_count = ev->destruction_count;
382 timeout = (tvalp->tv_usec / 1000) + (tvalp->tv_sec*1000);
385 ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout);
387 if (ret == -1 && errno != EINTR) {
388 epoll_fallback_to_select(ev, "epoll_wait() failed");
392 if (ret == 0 && tvalp) {
393 event_loop_timer(ev);
397 for (i=0;i<ret;i++) {
398 struct fd_event *fde = talloc_get_type(events[i].data.ptr,
403 epoll_fallback_to_select(ev, "epoll_wait() gave bad data");
406 if (events[i].events & EPOLLIN) flags |= EVENT_FD_READ;
407 if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
409 fde->handler(ev, fde, flags, fde->private);
410 if (destruction_count != ev->destruction_count) {
421 event loop handling using select()
423 static int event_loop_select(struct event_context *ev, struct timeval *tvalp)
427 uint32_t destruction_count = ev->destruction_count;
430 /* we maybe need to recalculate the maxfd */
431 if (ev->maxfd == EVENT_INVALID_MAXFD) {
438 /* setup any fd events */
439 for (fe=ev->fd_events; fe; ) {
440 struct fd_event *next = fe->next;
441 if (fe->flags & EVENT_FD_READ) {
442 FD_SET(fe->fd, &r_fds);
444 if (fe->flags & EVENT_FD_WRITE) {
445 FD_SET(fe->fd, &w_fds);
450 selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
452 if (selrtn == -1 && errno == EBADF) {
453 /* the socket is dead! this should never
454 happen as the socket should have first been
455 made readable and that should have removed
456 the event, so this must be a bug. This is a
458 DEBUG(0,("ERROR: EBADF on event_loop_once\n"));
459 ev->exit_code = EBADF;
463 if (selrtn == 0 && tvalp) {
464 event_loop_timer(ev);
469 /* at least one file descriptor is ready - check
470 which ones and call the handler, being careful to allow
471 the handler to remove itself when called */
472 for (fe=ev->fd_events; fe; fe=fe->next) {
474 if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ;
475 if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE;
477 fe->handler(ev, fe, flags, fe->private);
478 if (destruction_count != ev->destruction_count) {
489 do a single event loop using the events defined in ev
491 int event_loop_once(struct event_context *ev)
493 struct timeval tval, *tvalp;
497 /* work out the right timeout for all timed events */
498 if (ev->timed_events) {
499 struct timeval t = timeval_current();
500 tval = timeval_diff(&ev->timed_events->next_event, &t);
502 if (timeval_is_zero(tvalp)) {
503 event_loop_timer(ev);
509 if (ev->epoll_fd != -1) {
510 if (event_loop_epoll(ev, tvalp) == 0) {
516 return event_loop_select(ev, tvalp);
520 go into an event loop using the events defined in ev this function
521 will return with the specified code if one of the handlers calls
524 also return (with code 0) if all fd events are removed
526 int event_loop_wait(struct event_context *ev)
529 ev->maxfd = EVENT_INVALID_MAXFD;
531 while (ev->fd_events && ev->exit_code == 0) {
532 if (event_loop_once(ev) != 0) {
537 return ev->exit_code;