Home | History | Annotate | Line # | Download | only in util
      1 /*	$NetBSD: events.c,v 1.2 2017/02/14 01:16:49 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	events 3
      6 /* SUMMARY
      7 /*	event manager
      8 /* SYNOPSIS
      9 /*	#include <events.h>
     10 /*
     11 /*	time_t	event_time()
     12 /*
     13 /*	void	event_loop(delay)
     14 /*	int	delay;
     15 /*
     16 /*	time_t	event_request_timer(callback, context, delay)
     17 /*	void	(*callback)(int event, void *context);
     18 /*	void	*context;
     19 /*	int	delay;
     20 /*
     21 /*	int	event_cancel_timer(callback, context)
     22 /*	void	(*callback)(int event, void *context);
     23 /*	void	*context;
     24 /*
     25 /*	void	event_enable_read(fd, callback, context)
     26 /*	int	fd;
     27 /*	void	(*callback)(int event, void *context);
     28 /*	void	*context;
     29 /*
     30 /*	void	event_enable_write(fd, callback, context)
     31 /*	int	fd;
     32 /*	void	(*callback)(int event, void *context);
     33 /*	void	*context;
     34 /*
     35 /*	void	event_disable_readwrite(fd)
     36 /*	int	fd;
     37 /*
     38 /*	void	event_drain(time_limit)
     39 /*	int	time_limit;
     40 /*
     41 /*	void	event_fork(void)
     42 /* DESCRIPTION
     43 /*	This module delivers I/O and timer events.
     44 /*	Multiple I/O streams and timers can be monitored simultaneously.
     45 /*	Events are delivered via callback routines provided by the
     46 /*	application. When requesting an event, the application can provide
     47 /*	private context that is passed back when the callback routine is
     48 /*	executed.
     49 /*
     50 /*	event_time() returns a cached value of the current time.
     51 /*
     52 /*	event_loop() monitors all I/O channels for which the application has
     53 /*	expressed interest, and monitors the timer request queue.
     54 /*	It notifies the application whenever events of interest happen.
     55 /*	A negative delay value causes the function to pause until something
     56 /*	happens; a positive delay value causes event_loop() to return when
     57 /*	the next event happens or when the delay time in seconds is over,
     58 /*	whatever happens first. A zero delay effectuates a poll.
     59 /*
     60 /*	Note: in order to avoid race conditions, event_loop() cannot
     61 /*	not be called recursively.
     62 /*
     63 /*	event_request_timer() causes the specified callback function to
     64 /*	be called with the specified context argument after \fIdelay\fR
     65 /*	seconds, or as soon as possible thereafter. The delay should
     66 /*	not be negative (the manifest EVENT_NULL_DELAY provides for
     67 /*	convenient zero-delay notification).
     68 /*	The event argument is equal to EVENT_TIME.
     69 /*	Only one timer request can be active per (callback, context) pair.
     70 /*	Calling event_request_timer() with an existing (callback, context)
     71 /*	pair does not schedule a new event, but updates the time of event
     72 /*	delivery. The result is the absolute time at which the timer is
     73 /*	scheduled to go off.
     74 /*
     75 /*	event_cancel_timer() cancels the specified (callback, context) request.
     76 /*	The application is allowed to cancel non-existing requests. The result
     77 /*	value is the amount of time left before the timer would have gone off,
     78 /*	or -1 in case of no pending timer.
     79 /*
     80 /*	event_enable_read() (event_enable_write()) enables read (write) events
     81 /*	on the named I/O channel. It is up to the application to assemble
     82 /*	partial reads or writes.
     83 /*	An I/O channel cannot handle more than one request at the
     84 /*	same time. The application is allowed to enable an event that
     85 /*	is already enabled (same channel, same read or write operation,
     86 /*	but perhaps a different callback or context). On systems with
     87 /*	kernel-based event filters this is preferred usage, because
     88 /*	each disable and enable request would cost a system call.
     89 /*
     90 /*	The manifest constants EVENT_NULL_CONTEXT and EVENT_NULL_TYPE
     91 /*	provide convenient null values.
     92 /*
     93 /*	The callback routine has the following arguments:
     94 /* .IP fd
     95 /*	The stream on which the event happened.
     96 /* .IP event
     97 /*	An indication of the event type:
     98 /* .RS
     99 /* .IP EVENT_READ
    100 /*	read event,
    101 /* .IP EVENT_WRITE
    102 /*	write event,
    103 /* .IP EVENT_XCPT
    104 /*	exception (actually, any event other than read or write).
    105 /* .RE
    106 /* .IP context
    107 /*	Application context given to event_enable_read() (event_enable_write()).
    108 /* .PP
    109 /*	event_disable_readwrite() disables further I/O events on the specified
    110 /*	I/O channel. The application is allowed to cancel non-existing
    111 /*	I/O event requests.
    112 /*
    113 /*	event_drain() repeatedly calls event_loop() until no more timer
    114 /*	events or I/O events are pending or until the time limit is reached.
    115 /*	This routine must not be called from an event_whatever() callback
    116 /*	routine. Note: this function assumes that no new I/O events
    117 /*	will be registered.
    118 /*
    119 /*	event_fork() must be called by a child process after it is
    120 /*	created with fork(), to re-initialize event processing.
    121 /* DIAGNOSTICS
    122 /*	Panics: interface violations. Fatal errors: out of memory,
    123 /*	system call failure. Warnings: the number of available
    124 /*	file descriptors is much less than FD_SETSIZE.
    125 /* BUGS
    126 /*	This module is based on event selection. It assumes that the
    127 /*	event_loop() routine is called frequently. This approach is
    128 /*	not suitable for applications with compute-bound loops that
    129 /*	take a significant amount of time.
    130 /* LICENSE
    131 /* .ad
    132 /* .fi
    133 /*	The Secure Mailer license must be distributed with this software.
    134 /* AUTHOR(S)
    135 /*	Wietse Venema
    136 /*	IBM T.J. Watson Research
    137 /*	P.O. Box 704
    138 /*	Yorktown Heights, NY 10598, USA
    139 /*--*/
    140 
    141 /* System libraries. */
    142 
    143 #include "sys_defs.h"
    144 #include <sys/time.h>			/* XXX: 44BSD uses bzero() */
    145 #include <time.h>
    146 #include <errno.h>
    147 #include <unistd.h>
    148 #include <stddef.h>			/* offsetof() */
    149 #include <string.h>			/* bzero() prototype for 44BSD */
    150 #include <limits.h>			/* INT_MAX */
    151 
    152 #ifdef USE_SYS_SELECT_H
    153 #include <sys/select.h>
    154 #endif
    155 
    156 /* Application-specific. */
    157 
    158 #include "mymalloc.h"
    159 #include "msg.h"
    160 #include "iostuff.h"
    161 #include "ring.h"
    162 #include "events.h"
    163 
    164 #if !defined(EVENTS_STYLE)
    165 #error "must define EVENTS_STYLE"
    166 #endif
    167 
    168  /*
    169   * Traditional BSD-style select(2). Works everywhere, but has a built-in
    170   * upper bound on the number of file descriptors, and that limit is hard to
    171   * change on Linux. Is sometimes emulated with SYSV-style poll(2) which
    172   * doesn't have the file descriptor limit, but unfortunately does not help
    173   * to improve the performance of servers with lots of connections.
    174   */
    175 #define EVENT_ALLOC_INCR		10
    176 
    177 #if (EVENTS_STYLE == EVENTS_STYLE_SELECT)
    178 typedef fd_set EVENT_MASK;
    179 
    180 #define EVENT_MASK_BYTE_COUNT(mask)	sizeof(*(mask))
    181 #define EVENT_MASK_ZERO(mask)		FD_ZERO(mask)
    182 #define EVENT_MASK_SET(fd, mask)	FD_SET((fd), (mask))
    183 #define EVENT_MASK_ISSET(fd, mask)	FD_ISSET((fd), (mask))
    184 #define EVENT_MASK_CLR(fd, mask)	FD_CLR((fd), (mask))
    185 #define EVENT_MASK_CMP(m1, m2) memcmp((m1), (m2), EVENT_MASK_BYTE_COUNT(m1))
    186 #else
    187 
    188  /*
    189   * Kernel-based event filters (kqueue, /dev/poll, epoll). We use the
    190   * following file descriptor mask structure which is expanded on the fly.
    191   */
    192 typedef struct {
    193     char   *data;			/* bit mask */
    194     size_t  data_len;			/* data byte count */
    195 } EVENT_MASK;
    196 
    197  /* Bits per byte, byte in vector, bit offset in byte, bytes per set. */
    198 #define EVENT_MASK_NBBY		(8)
    199 #define EVENT_MASK_FD_BYTE(fd, mask) \
    200 	(((unsigned char *) (mask)->data)[(fd) / EVENT_MASK_NBBY])
    201 #define EVENT_MASK_FD_BIT(fd)	(1 << ((fd) % EVENT_MASK_NBBY))
    202 #define EVENT_MASK_BYTES_NEEDED(len) \
    203 	(((len) + (EVENT_MASK_NBBY -1)) / EVENT_MASK_NBBY)
    204 #define EVENT_MASK_BYTE_COUNT(mask)	((mask)->data_len)
    205 
    206  /* Memory management. */
    207 #define EVENT_MASK_ALLOC(mask, bit_len) do { \
    208 	size_t _byte_len = EVENT_MASK_BYTES_NEEDED(bit_len); \
    209 	(mask)->data = mymalloc(_byte_len); \
    210 	memset((mask)->data, 0, _byte_len); \
    211 	(mask)->data_len = _byte_len; \
    212     } while (0)
    213 #define EVENT_MASK_REALLOC(mask, bit_len) do { \
    214 	size_t _byte_len = EVENT_MASK_BYTES_NEEDED(bit_len); \
    215 	size_t _old_len = (mask)->data_len; \
    216 	(mask)->data = myrealloc((mask)->data, _byte_len); \
    217 	if (_byte_len > _old_len) \
    218 	    memset((mask)->data + _old_len, 0, _byte_len - _old_len); \
    219 	(mask)->data_len = _byte_len; \
    220     } while (0)
    221 #define EVENT_MASK_FREE(mask)	myfree((mask)->data)
    222 
    223  /* Set operations, modeled after FD_ZERO/SET/ISSET/CLR. */
    224 #define EVENT_MASK_ZERO(mask) \
    225 	memset((mask)->data, 0, (mask)->data_len)
    226 #define EVENT_MASK_SET(fd, mask) \
    227 	(EVENT_MASK_FD_BYTE((fd), (mask)) |= EVENT_MASK_FD_BIT(fd))
    228 #define EVENT_MASK_ISSET(fd, mask) \
    229 	(EVENT_MASK_FD_BYTE((fd), (mask)) & EVENT_MASK_FD_BIT(fd))
    230 #define EVENT_MASK_CLR(fd, mask) \
    231 	(EVENT_MASK_FD_BYTE((fd), (mask)) &= ~EVENT_MASK_FD_BIT(fd))
    232 #define EVENT_MASK_CMP(m1, m2) \
    233 	memcmp((m1)->data, (m2)->data, EVENT_MASK_BYTE_COUNT(m1))
    234 #endif
    235 
    236  /*
    237   * I/O events.
    238   */
    239 typedef struct EVENT_FDTABLE EVENT_FDTABLE;
    240 
    241 struct EVENT_FDTABLE {
    242     EVENT_NOTIFY_RDWR_FN callback;
    243     char   *context;
    244 };
    245 static EVENT_MASK event_rmask;		/* enabled read events */
    246 static EVENT_MASK event_wmask;		/* enabled write events */
    247 static EVENT_MASK event_xmask;		/* for bad news mostly */
    248 static int event_fdlimit;		/* per-process open file limit */
    249 static EVENT_FDTABLE *event_fdtable;	/* one slot per file descriptor */
    250 static int event_fdslots;		/* number of file descriptor slots */
    251 static int event_max_fd = -1;		/* highest fd number seen */
    252 
    253  /*
    254   * FreeBSD kqueue supports no system call to find out what descriptors are
    255   * registered in the kernel-based filter. To implement our own sanity checks
    256   * we maintain our own descriptor bitmask.
    257   *
    258   * FreeBSD kqueue does support application context pointers. Unfortunately,
    259   * changing that information would cost a system call, and some of the
    260   * competitors don't support application context. To keep the implementation
    261   * simple we maintain our own table with call-back information.
    262   *
    263   * FreeBSD kqueue silently unregisters a descriptor from its filter when the
    264   * descriptor is closed, so our information could get out of sync with the
    265   * kernel. But that will never happen, because we have to meticulously
    266   * unregister a file descriptor before it is closed, to avoid errors on
    267   * systems that are built with EVENTS_STYLE == EVENTS_STYLE_SELECT.
    268   */
    269 #if (EVENTS_STYLE == EVENTS_STYLE_KQUEUE)
    270 #include <sys/event.h>
    271 
    272  /*
    273   * Some early FreeBSD implementations don't have the EV_SET macro.
    274   */
    275 #ifndef EV_SET
    276 #define EV_SET(kp, id, fi, fl, ffl, da, ud) do { \
    277         (kp)->ident = (id); \
    278         (kp)->filter = (fi); \
    279         (kp)->flags = (fl); \
    280         (kp)->fflags = (ffl); \
    281         (kp)->data = (da); \
    282         (kp)->udata = (ud); \
    283     } while(0)
    284 #endif
    285 
    286  /*
    287   * Macros to initialize the kernel-based filter; see event_init().
    288   */
    289 static int event_kq;			/* handle to event filter */
    290 
    291 #define EVENT_REG_INIT_HANDLE(er, n) do { \
    292 	er = event_kq = kqueue(); \
    293     } while (0)
    294 #define EVENT_REG_INIT_TEXT	"kqueue"
    295 
    296 #define EVENT_REG_FORK_HANDLE(er, n) do { \
    297 	(void) close(event_kq); \
    298 	EVENT_REG_INIT_HANDLE(er, (n)); \
    299     } while (0)
    300 
    301  /*
    302   * Macros to update the kernel-based filter; see event_enable_read(),
    303   * event_enable_write() and event_disable_readwrite().
    304   */
    305 #define EVENT_REG_FD_OP(er, fh, ev, op) do { \
    306 	struct kevent dummy; \
    307 	EV_SET(&dummy, (fh), (ev), (op), 0, 0, 0); \
    308 	(er) = kevent(event_kq, &dummy, 1, 0, 0, 0); \
    309     } while (0)
    310 
    311 #define EVENT_REG_ADD_OP(e, f, ev) EVENT_REG_FD_OP((e), (f), (ev), EV_ADD)
    312 #define EVENT_REG_ADD_READ(e, f)   EVENT_REG_ADD_OP((e), (f), EVFILT_READ)
    313 #define EVENT_REG_ADD_WRITE(e, f)  EVENT_REG_ADD_OP((e), (f), EVFILT_WRITE)
    314 #define EVENT_REG_ADD_TEXT         "kevent EV_ADD"
    315 
    316 #define EVENT_REG_DEL_OP(e, f, ev) EVENT_REG_FD_OP((e), (f), (ev), EV_DELETE)
    317 #define EVENT_REG_DEL_READ(e, f)   EVENT_REG_DEL_OP((e), (f), EVFILT_READ)
    318 #define EVENT_REG_DEL_WRITE(e, f)  EVENT_REG_DEL_OP((e), (f), EVFILT_WRITE)
    319 #define EVENT_REG_DEL_TEXT         "kevent EV_DELETE"
    320 
    321  /*
    322   * Macros to retrieve event buffers from the kernel; see event_loop().
    323   */
    324 typedef struct kevent EVENT_BUFFER;
    325 
    326 #define EVENT_BUFFER_READ(event_count, event_buf, buflen, delay) do { \
    327 	struct timespec ts; \
    328 	struct timespec *tsp; \
    329 	if ((delay) < 0) { \
    330 	    tsp = 0; \
    331 	} else { \
    332 	    tsp = &ts; \
    333 	    ts.tv_nsec = 0; \
    334 	    ts.tv_sec = (delay); \
    335 	} \
    336 	(event_count) = kevent(event_kq, (struct kevent *) 0, 0, (event_buf), \
    337 			  (buflen), (tsp)); \
    338     } while (0)
    339 #define EVENT_BUFFER_READ_TEXT	"kevent"
    340 
    341  /*
    342   * Macros to process event buffers from the kernel; see event_loop().
    343   */
    344 #define EVENT_GET_FD(bp)	((bp)->ident)
    345 #define EVENT_GET_TYPE(bp)	((bp)->filter)
    346 #define EVENT_TEST_READ(bp)	(EVENT_GET_TYPE(bp) == EVFILT_READ)
    347 #define EVENT_TEST_WRITE(bp)	(EVENT_GET_TYPE(bp) == EVFILT_WRITE)
    348 
    349 #endif
    350 
    351  /*
    352   * Solaris /dev/poll does not support application context, so we have to
    353   * maintain our own. This has the benefit of avoiding an expensive system
    354   * call just to change a call-back function or argument.
    355   *
    356   * Solaris /dev/poll does have a way to query if a specific descriptor is
    357   * registered. However, we maintain a descriptor mask anyway because a) it
    358   * avoids having to make an expensive system call to find out if something
    359   * is registered, b) some EVENTS_STYLE_MUMBLE implementations need a
    360   * descriptor bitmask anyway and c) we use the bitmask already to implement
    361   * sanity checks.
    362   */
    363 #if (EVENTS_STYLE == EVENTS_STYLE_DEVPOLL)
    364 #include <sys/devpoll.h>
    365 #include <fcntl.h>
    366 
    367  /*
    368   * Macros to initialize the kernel-based filter; see event_init().
    369   */
    370 static int event_pollfd;		/* handle to file descriptor set */
    371 
    372 #define EVENT_REG_INIT_HANDLE(er, n) do { \
    373 	er = event_pollfd = open("/dev/poll", O_RDWR); \
    374 	if (event_pollfd >= 0) close_on_exec(event_pollfd, CLOSE_ON_EXEC); \
    375     } while (0)
    376 #define EVENT_REG_INIT_TEXT	"open /dev/poll"
    377 
    378 #define EVENT_REG_FORK_HANDLE(er, n) do { \
    379 	(void) close(event_pollfd); \
    380 	EVENT_REG_INIT_HANDLE(er, (n)); \
    381     } while (0)
    382 
    383  /*
    384   * Macros to update the kernel-based filter; see event_enable_read(),
    385   * event_enable_write() and event_disable_readwrite().
    386   */
    387 #define EVENT_REG_FD_OP(er, fh, ev) do { \
    388 	struct pollfd dummy; \
    389 	dummy.fd = (fh); \
    390 	dummy.events = (ev); \
    391 	(er) = write(event_pollfd, (void *) &dummy, \
    392 	    sizeof(dummy)) != sizeof(dummy) ? -1 : 0; \
    393     } while (0)
    394 
    395 #define EVENT_REG_ADD_READ(e, f)  EVENT_REG_FD_OP((e), (f), POLLIN)
    396 #define EVENT_REG_ADD_WRITE(e, f) EVENT_REG_FD_OP((e), (f), POLLOUT)
    397 #define EVENT_REG_ADD_TEXT        "write /dev/poll"
    398 
    399 #define EVENT_REG_DEL_BOTH(e, f)  EVENT_REG_FD_OP((e), (f), POLLREMOVE)
    400 #define EVENT_REG_DEL_TEXT        "write /dev/poll"
    401 
    402  /*
    403   * Macros to retrieve event buffers from the kernel; see event_loop().
    404   */
    405 typedef struct pollfd EVENT_BUFFER;
    406 
    407 #define EVENT_BUFFER_READ(event_count, event_buf, buflen, delay) do { \
    408 	struct dvpoll dvpoll; \
    409 	dvpoll.dp_fds = (event_buf); \
    410 	dvpoll.dp_nfds = (buflen); \
    411 	dvpoll.dp_timeout = (delay) < 0 ? -1 : (delay) * 1000; \
    412 	(event_count) = ioctl(event_pollfd, DP_POLL, &dvpoll); \
    413     } while (0)
    414 #define EVENT_BUFFER_READ_TEXT	"ioctl DP_POLL"
    415 
    416  /*
    417   * Macros to process event buffers from the kernel; see event_loop().
    418   */
    419 #define EVENT_GET_FD(bp)	((bp)->fd)
    420 #define EVENT_GET_TYPE(bp)	((bp)->revents)
    421 #define EVENT_TEST_READ(bp)	(EVENT_GET_TYPE(bp) & POLLIN)
    422 #define EVENT_TEST_WRITE(bp)	(EVENT_GET_TYPE(bp) & POLLOUT)
    423 
    424 #endif
    425 
    426  /*
    427   * Linux epoll supports no system call to find out what descriptors are
    428   * registered in the kernel-based filter. To implement our own sanity checks
    429   * we maintain our own descriptor bitmask.
    430   *
    431   * Linux epoll does support application context pointers. Unfortunately,
    432   * changing that information would cost a system call, and some of the
    433   * competitors don't support application context. To keep the implementation
    434   * simple we maintain our own table with call-back information.
    435   *
    436   * Linux epoll silently unregisters a descriptor from its filter when the
    437   * descriptor is closed, so our information could get out of sync with the
    438   * kernel. But that will never happen, because we have to meticulously
    439   * unregister a file descriptor before it is closed, to avoid errors on
    440   * systems that are built with EVENTS_STYLE == EVENTS_STYLE_SELECT.
    441   */
    442 #if (EVENTS_STYLE == EVENTS_STYLE_EPOLL)
    443 #include <sys/epoll.h>
    444 
    445  /*
    446   * Macros to initialize the kernel-based filter; see event_init().
    447   */
    448 static int event_epollfd;		/* epoll handle */
    449 
    450 #define EVENT_REG_INIT_HANDLE(er, n) do { \
    451 	er = event_epollfd = epoll_create(n); \
    452 	if (event_epollfd >= 0) close_on_exec(event_epollfd, CLOSE_ON_EXEC); \
    453     } while (0)
    454 #define EVENT_REG_INIT_TEXT	"epoll_create"
    455 
    456 #define EVENT_REG_FORK_HANDLE(er, n) do { \
    457 	(void) close(event_epollfd); \
    458 	EVENT_REG_INIT_HANDLE(er, (n)); \
    459     } while (0)
    460 
    461  /*
    462   * Macros to update the kernel-based filter; see event_enable_read(),
    463   * event_enable_write() and event_disable_readwrite().
    464   */
    465 #define EVENT_REG_FD_OP(er, fh, ev, op) do { \
    466 	struct epoll_event dummy; \
    467 	dummy.events = (ev); \
    468 	dummy.data.fd = (fh); \
    469 	(er) = epoll_ctl(event_epollfd, (op), (fh), &dummy); \
    470     } while (0)
    471 
    472 #define EVENT_REG_ADD_OP(e, f, ev) EVENT_REG_FD_OP((e), (f), (ev), EPOLL_CTL_ADD)
    473 #define EVENT_REG_ADD_READ(e, f)   EVENT_REG_ADD_OP((e), (f), EPOLLIN)
    474 #define EVENT_REG_ADD_WRITE(e, f)  EVENT_REG_ADD_OP((e), (f), EPOLLOUT)
    475 #define EVENT_REG_ADD_TEXT         "epoll_ctl EPOLL_CTL_ADD"
    476 
    477 #define EVENT_REG_DEL_OP(e, f, ev) EVENT_REG_FD_OP((e), (f), (ev), EPOLL_CTL_DEL)
    478 #define EVENT_REG_DEL_READ(e, f)   EVENT_REG_DEL_OP((e), (f), EPOLLIN)
    479 #define EVENT_REG_DEL_WRITE(e, f)  EVENT_REG_DEL_OP((e), (f), EPOLLOUT)
    480 #define EVENT_REG_DEL_TEXT         "epoll_ctl EPOLL_CTL_DEL"
    481 
    482  /*
    483   * Macros to retrieve event buffers from the kernel; see event_loop().
    484   */
    485 typedef struct epoll_event EVENT_BUFFER;
    486 
    487 #define EVENT_BUFFER_READ(event_count, event_buf, buflen, delay) do { \
    488 	(event_count) = epoll_wait(event_epollfd, (event_buf), (buflen), \
    489 				  (delay) < 0 ? -1 : (delay) * 1000); \
    490     } while (0)
    491 #define EVENT_BUFFER_READ_TEXT	"epoll_wait"
    492 
    493  /*
    494   * Macros to process event buffers from the kernel; see event_loop().
    495   */
    496 #define EVENT_GET_FD(bp)	((bp)->data.fd)
    497 #define EVENT_GET_TYPE(bp)	((bp)->events)
    498 #define EVENT_TEST_READ(bp)	(EVENT_GET_TYPE(bp) & EPOLLIN)
    499 #define EVENT_TEST_WRITE(bp)	(EVENT_GET_TYPE(bp) & EPOLLOUT)
    500 
    501 #endif
    502 
    503  /*
    504   * Timer events. Timer requests are kept sorted, in a circular list. We use
    505   * the RING abstraction, so we get to use a couple ugly macros.
    506   *
    507   * When a call-back function adds a timer request, we label the request with
    508   * the event_loop() call instance that invoked the call-back. We use this to
    509   * prevent zero-delay timer requests from running in a tight loop and
    510   * starving I/O events.
    511   */
    512 typedef struct EVENT_TIMER EVENT_TIMER;
    513 
    514 struct EVENT_TIMER {
    515     time_t  when;			/* when event is wanted */
    516     EVENT_NOTIFY_TIME_FN callback;	/* callback function */
    517     char   *context;			/* callback context */
    518     long    loop_instance;		/* event_loop() call instance */
    519     RING    ring;			/* linkage */
    520 };
    521 
    522 static RING event_timer_head;		/* timer queue head */
    523 static long event_loop_instance;	/* event_loop() call instance */
    524 
    525 #define RING_TO_TIMER(r) \
    526 	((EVENT_TIMER *) ((void *) (r) - offsetof(EVENT_TIMER, ring)))
    527 
    528 #define FOREACH_QUEUE_ENTRY(entry, head) \
    529 	for (entry = ring_succ(head); entry != (head); entry = ring_succ(entry))
    530 
    531 #define FIRST_TIMER(head) \
    532 	(ring_succ(head) != (head) ? RING_TO_TIMER(ring_succ(head)) : 0)
    533 
    534  /*
    535   * Other private data structures.
    536   */
    537 static time_t event_present;		/* cached time of day */
    538 
    539 #define EVENT_INIT_NEEDED()	(event_present == 0)
    540 
    541 /* event_init - set up tables and such */
    542 
    543 static void event_init(void)
    544 {
    545     EVENT_FDTABLE *fdp;
    546     int     err;
    547 
    548     if (!EVENT_INIT_NEEDED())
    549 	msg_panic("event_init: repeated call");
    550 
    551     /*
    552      * Initialize the file descriptor masks and the call-back table. Where
    553      * possible we extend these data structures on the fly. With select(2)
    554      * based implementations we can only handle FD_SETSIZE open files.
    555      */
    556 #if (EVENTS_STYLE == EVENTS_STYLE_SELECT)
    557     if ((event_fdlimit = open_limit(FD_SETSIZE)) < 0)
    558 	msg_fatal("unable to determine open file limit");
    559 #else
    560     if ((event_fdlimit = open_limit(INT_MAX)) < 0)
    561 	msg_fatal("unable to determine open file limit");
    562 #endif
    563     if (event_fdlimit < FD_SETSIZE / 2 && event_fdlimit < 256)
    564 	msg_warn("could allocate space for only %d open files", event_fdlimit);
    565     event_fdslots = EVENT_ALLOC_INCR;
    566     event_fdtable = (EVENT_FDTABLE *)
    567 	mymalloc(sizeof(EVENT_FDTABLE) * event_fdslots);
    568     for (fdp = event_fdtable; fdp < event_fdtable + event_fdslots; fdp++) {
    569 	fdp->callback = 0;
    570 	fdp->context = 0;
    571     }
    572 
    573     /*
    574      * Initialize the I/O event request masks.
    575      */
    576 #if (EVENTS_STYLE == EVENTS_STYLE_SELECT)
    577     EVENT_MASK_ZERO(&event_rmask);
    578     EVENT_MASK_ZERO(&event_wmask);
    579     EVENT_MASK_ZERO(&event_xmask);
    580 #else
    581     EVENT_MASK_ALLOC(&event_rmask, event_fdslots);
    582     EVENT_MASK_ALLOC(&event_wmask, event_fdslots);
    583     EVENT_MASK_ALLOC(&event_xmask, event_fdslots);
    584 
    585     /*
    586      * Initialize the kernel-based filter.
    587      */
    588     EVENT_REG_INIT_HANDLE(err, event_fdslots);
    589     if (err < 0)
    590 	msg_fatal("%s: %m", EVENT_REG_INIT_TEXT);
    591 #endif
    592 
    593     /*
    594      * Initialize timer stuff.
    595      */
    596     ring_init(&event_timer_head);
    597     (void) time(&event_present);
    598 
    599     /*
    600      * Avoid an infinite initialization loop.
    601      */
    602     if (EVENT_INIT_NEEDED())
    603 	msg_panic("event_init: unable to initialize");
    604 }
    605 
    606 /* event_extend - make room for more descriptor slots */
    607 
    608 static void event_extend(int fd)
    609 {
    610     const char *myname = "event_extend";
    611     int     old_slots = event_fdslots;
    612     int     new_slots = (event_fdslots > fd / 2 ?
    613 			 2 * old_slots : fd + EVENT_ALLOC_INCR);
    614     EVENT_FDTABLE *fdp;
    615 
    616 #ifdef EVENT_REG_UPD_HANDLE
    617     int     err;
    618 
    619 #endif
    620 
    621     if (msg_verbose > 2)
    622 	msg_info("%s: fd %d", myname, fd);
    623     event_fdtable = (EVENT_FDTABLE *)
    624 	myrealloc((void *) event_fdtable, sizeof(EVENT_FDTABLE) * new_slots);
    625     event_fdslots = new_slots;
    626     for (fdp = event_fdtable + old_slots;
    627 	 fdp < event_fdtable + new_slots; fdp++) {
    628 	fdp->callback = 0;
    629 	fdp->context = 0;
    630     }
    631 
    632     /*
    633      * Initialize the I/O event request masks.
    634      */
    635 #if (EVENTS_STYLE != EVENTS_STYLE_SELECT)
    636     EVENT_MASK_REALLOC(&event_rmask, new_slots);
    637     EVENT_MASK_REALLOC(&event_wmask, new_slots);
    638     EVENT_MASK_REALLOC(&event_xmask, new_slots);
    639 #endif
    640 #ifdef EVENT_REG_UPD_HANDLE
    641     EVENT_REG_UPD_HANDLE(err, new_slots);
    642     if (err < 0)
    643 	msg_fatal("%s: %s: %m", myname, EVENT_REG_UPD_TEXT);
    644 #endif
    645 }
    646 
    647 /* event_time - look up cached time of day */
    648 
    649 time_t  event_time(void)
    650 {
    651     if (EVENT_INIT_NEEDED())
    652 	event_init();
    653 
    654     return (event_present);
    655 }
    656 
    657 /* event_drain - loop until all pending events are done */
    658 
    659 void    event_drain(int time_limit)
    660 {
    661     EVENT_MASK zero_mask;
    662     time_t  max_time;
    663 
    664     if (EVENT_INIT_NEEDED())
    665 	return;
    666 
    667 #if (EVENTS_STYLE == EVENTS_STYLE_SELECT)
    668     EVENT_MASK_ZERO(&zero_mask);
    669 #else
    670     EVENT_MASK_ALLOC(&zero_mask, event_fdslots);
    671 #endif
    672     (void) time(&event_present);
    673     max_time = event_present + time_limit;
    674     while (event_present < max_time
    675 	   && (event_timer_head.pred != &event_timer_head
    676 	       || EVENT_MASK_CMP(&zero_mask, &event_xmask) != 0)) {
    677 	event_loop(1);
    678 #if (EVENTS_STYLE != EVENTS_STYLE_SELECT)
    679 	if (EVENT_MASK_BYTE_COUNT(&zero_mask)
    680 	    != EVENT_MASK_BYTES_NEEDED(event_fdslots))
    681 	    EVENT_MASK_REALLOC(&zero_mask, event_fdslots);
    682 #endif
    683     }
    684 #if (EVENTS_STYLE != EVENTS_STYLE_SELECT)
    685     EVENT_MASK_FREE(&zero_mask);
    686 #endif
    687 }
    688 
    689 /* event_fork - resume event processing after fork() */
    690 
    691 void    event_fork(void)
    692 {
    693 #if (EVENTS_STYLE != EVENTS_STYLE_SELECT)
    694     EVENT_FDTABLE *fdp;
    695     int     err;
    696     int     fd;
    697 
    698     /*
    699      * No event was ever registered, so there's nothing to be done.
    700      */
    701     if (EVENT_INIT_NEEDED())
    702 	return;
    703 
    704     /*
    705      * Close the existing filter handle and open a new kernel-based filter.
    706      */
    707     EVENT_REG_FORK_HANDLE(err, event_fdslots);
    708     if (err < 0)
    709 	msg_fatal("%s: %m", EVENT_REG_INIT_TEXT);
    710 
    711     /*
    712      * Populate the new kernel-based filter with events that were registered
    713      * in the parent process.
    714      */
    715     for (fd = 0; fd <= event_max_fd; fd++) {
    716 	if (EVENT_MASK_ISSET(fd, &event_wmask)) {
    717 	    EVENT_MASK_CLR(fd, &event_wmask);
    718 	    fdp = event_fdtable + fd;
    719 	    event_enable_write(fd, fdp->callback, fdp->context);
    720 	} else if (EVENT_MASK_ISSET(fd, &event_rmask)) {
    721 	    EVENT_MASK_CLR(fd, &event_rmask);
    722 	    fdp = event_fdtable + fd;
    723 	    event_enable_read(fd, fdp->callback, fdp->context);
    724 	}
    725     }
    726 #endif
    727 }
    728 
    729 /* event_enable_read - enable read events */
    730 
    731 void    event_enable_read(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
    732 {
    733     const char *myname = "event_enable_read";
    734     EVENT_FDTABLE *fdp;
    735     int     err;
    736 
    737     if (EVENT_INIT_NEEDED())
    738 	event_init();
    739 
    740     /*
    741      * Sanity checks.
    742      */
    743     if (fd < 0 || fd >= event_fdlimit)
    744 	msg_panic("%s: bad file descriptor: %d", myname, fd);
    745 
    746     if (msg_verbose > 2)
    747 	msg_info("%s: fd %d", myname, fd);
    748 
    749     if (fd >= event_fdslots)
    750 	event_extend(fd);
    751 
    752     /*
    753      * Disallow mixed (i.e. read and write) requests on the same descriptor.
    754      */
    755     if (EVENT_MASK_ISSET(fd, &event_wmask))
    756 	msg_panic("%s: fd %d: read/write I/O request", myname, fd);
    757 
    758     /*
    759      * Postfix 2.4 allows multiple event_enable_read() calls on the same
    760      * descriptor without requiring event_disable_readwrite() calls between
    761      * them. With kernel-based filters (kqueue, /dev/poll, epoll) it's
    762      * wasteful to make system calls when we change only application
    763      * call-back information. It has a noticeable effect on smtp-source
    764      * performance.
    765      */
    766     if (EVENT_MASK_ISSET(fd, &event_rmask) == 0) {
    767 	EVENT_MASK_SET(fd, &event_xmask);
    768 	EVENT_MASK_SET(fd, &event_rmask);
    769 	if (event_max_fd < fd)
    770 	    event_max_fd = fd;
    771 #if (EVENTS_STYLE != EVENTS_STYLE_SELECT)
    772 	EVENT_REG_ADD_READ(err, fd);
    773 	if (err < 0)
    774 	    msg_fatal("%s: %s: %m", myname, EVENT_REG_ADD_TEXT);
    775 #endif
    776     }
    777     fdp = event_fdtable + fd;
    778     if (fdp->callback != callback || fdp->context != context) {
    779 	fdp->callback = callback;
    780 	fdp->context = context;
    781     }
    782 }
    783 
    784 /* event_enable_write - enable write events */
    785 
    786 void    event_enable_write(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
    787 {
    788     const char *myname = "event_enable_write";
    789     EVENT_FDTABLE *fdp;
    790     int     err;
    791 
    792     if (EVENT_INIT_NEEDED())
    793 	event_init();
    794 
    795     /*
    796      * Sanity checks.
    797      */
    798     if (fd < 0 || fd >= event_fdlimit)
    799 	msg_panic("%s: bad file descriptor: %d", myname, fd);
    800 
    801     if (msg_verbose > 2)
    802 	msg_info("%s: fd %d", myname, fd);
    803 
    804     if (fd >= event_fdslots)
    805 	event_extend(fd);
    806 
    807     /*
    808      * Disallow mixed (i.e. read and write) requests on the same descriptor.
    809      */
    810     if (EVENT_MASK_ISSET(fd, &event_rmask))
    811 	msg_panic("%s: fd %d: read/write I/O request", myname, fd);
    812 
    813     /*
    814      * Postfix 2.4 allows multiple event_enable_write() calls on the same
    815      * descriptor without requiring event_disable_readwrite() calls between
    816      * them. With kernel-based filters (kqueue, /dev/poll, epoll) it's
    817      * incredibly wasteful to make unregister and register system calls when
    818      * we change only application call-back information. It has a noticeable
    819      * effect on smtp-source performance.
    820      */
    821     if (EVENT_MASK_ISSET(fd, &event_wmask) == 0) {
    822 	EVENT_MASK_SET(fd, &event_xmask);
    823 	EVENT_MASK_SET(fd, &event_wmask);
    824 	if (event_max_fd < fd)
    825 	    event_max_fd = fd;
    826 #if (EVENTS_STYLE != EVENTS_STYLE_SELECT)
    827 	EVENT_REG_ADD_WRITE(err, fd);
    828 	if (err < 0)
    829 	    msg_fatal("%s: %s: %m", myname, EVENT_REG_ADD_TEXT);
    830 #endif
    831     }
    832     fdp = event_fdtable + fd;
    833     if (fdp->callback != callback || fdp->context != context) {
    834 	fdp->callback = callback;
    835 	fdp->context = context;
    836     }
    837 }
    838 
    839 /* event_disable_readwrite - disable request for read or write events */
    840 
    841 void    event_disable_readwrite(int fd)
    842 {
    843     const char *myname = "event_disable_readwrite";
    844     EVENT_FDTABLE *fdp;
    845     int     err;
    846 
    847     if (EVENT_INIT_NEEDED())
    848 	event_init();
    849 
    850     /*
    851      * Sanity checks.
    852      */
    853     if (fd < 0 || fd >= event_fdlimit)
    854 	msg_panic("%s: bad file descriptor: %d", myname, fd);
    855 
    856     if (msg_verbose > 2)
    857 	msg_info("%s: fd %d", myname, fd);
    858 
    859     /*
    860      * Don't complain when there is nothing to cancel. The request may have
    861      * been canceled from another thread.
    862      */
    863     if (fd >= event_fdslots)
    864 	return;
    865 #if (EVENTS_STYLE != EVENTS_STYLE_SELECT)
    866 #ifdef EVENT_REG_DEL_BOTH
    867     /* XXX Can't seem to disable READ and WRITE events selectively. */
    868     if (EVENT_MASK_ISSET(fd, &event_rmask)
    869 	|| EVENT_MASK_ISSET(fd, &event_wmask)) {
    870 	EVENT_REG_DEL_BOTH(err, fd);
    871 	if (err < 0)
    872 	    msg_fatal("%s: %s: %m", myname, EVENT_REG_DEL_TEXT);
    873     }
    874 #else
    875     if (EVENT_MASK_ISSET(fd, &event_rmask)) {
    876 	EVENT_REG_DEL_READ(err, fd);
    877 	if (err < 0)
    878 	    msg_fatal("%s: %s: %m", myname, EVENT_REG_DEL_TEXT);
    879     } else if (EVENT_MASK_ISSET(fd, &event_wmask)) {
    880 	EVENT_REG_DEL_WRITE(err, fd);
    881 	if (err < 0)
    882 	    msg_fatal("%s: %s: %m", myname, EVENT_REG_DEL_TEXT);
    883     }
    884 #endif						/* EVENT_REG_DEL_BOTH */
    885 #endif						/* != EVENTS_STYLE_SELECT */
    886     EVENT_MASK_CLR(fd, &event_xmask);
    887     EVENT_MASK_CLR(fd, &event_rmask);
    888     EVENT_MASK_CLR(fd, &event_wmask);
    889     fdp = event_fdtable + fd;
    890     fdp->callback = 0;
    891     fdp->context = 0;
    892 }
    893 
    894 /* event_request_timer - (re)set timer */
    895 
    896 time_t  event_request_timer(EVENT_NOTIFY_TIME_FN callback, void *context, int delay)
    897 {
    898     const char *myname = "event_request_timer";
    899     RING   *ring;
    900     EVENT_TIMER *timer;
    901 
    902     if (EVENT_INIT_NEEDED())
    903 	event_init();
    904 
    905     /*
    906      * Sanity checks.
    907      */
    908     if (delay < 0)
    909 	msg_panic("%s: invalid delay: %d", myname, delay);
    910 
    911     /*
    912      * Make sure we schedule this event at the right time.
    913      */
    914     time(&event_present);
    915 
    916     /*
    917      * See if they are resetting an existing timer request. If so, take the
    918      * request away from the timer queue so that it can be inserted at the
    919      * right place.
    920      */
    921     FOREACH_QUEUE_ENTRY(ring, &event_timer_head) {
    922 	timer = RING_TO_TIMER(ring);
    923 	if (timer->callback == callback && timer->context == context) {
    924 	    timer->when = event_present + delay;
    925 	    timer->loop_instance = event_loop_instance;
    926 	    ring_detach(ring);
    927 	    if (msg_verbose > 2)
    928 		msg_info("%s: reset 0x%lx 0x%lx %d", myname,
    929 			 (long) callback, (long) context, delay);
    930 	    break;
    931 	}
    932     }
    933 
    934     /*
    935      * If not found, schedule a new timer request.
    936      */
    937     if (ring == &event_timer_head) {
    938 	timer = (EVENT_TIMER *) mymalloc(sizeof(EVENT_TIMER));
    939 	timer->when = event_present + delay;
    940 	timer->callback = callback;
    941 	timer->context = context;
    942 	timer->loop_instance = event_loop_instance;
    943 	if (msg_verbose > 2)
    944 	    msg_info("%s: set 0x%lx 0x%lx %d", myname,
    945 		     (long) callback, (long) context, delay);
    946     }
    947 
    948     /*
    949      * Timer requests are kept sorted to reduce lookup overhead in the event
    950      * loop.
    951      *
    952      * XXX Append the new request after existing requests for the same time
    953      * slot. The event_loop() routine depends on this to avoid starving I/O
    954      * events when a call-back function schedules a zero-delay timer request.
    955      */
    956     FOREACH_QUEUE_ENTRY(ring, &event_timer_head) {
    957 	if (timer->when < RING_TO_TIMER(ring)->when)
    958 	    break;
    959     }
    960     ring_prepend(ring, &timer->ring);
    961 
    962     return (timer->when);
    963 }
    964 
    965 /* event_cancel_timer - cancel timer */
    966 
    967 int     event_cancel_timer(EVENT_NOTIFY_TIME_FN callback, void *context)
    968 {
    969     const char *myname = "event_cancel_timer";
    970     RING   *ring;
    971     EVENT_TIMER *timer;
    972     int     time_left = -1;
    973 
    974     if (EVENT_INIT_NEEDED())
    975 	event_init();
    976 
    977     /*
    978      * See if they are canceling an existing timer request. Do not complain
    979      * when the request is not found. It might have been canceled from some
    980      * other thread.
    981      */
    982     FOREACH_QUEUE_ENTRY(ring, &event_timer_head) {
    983 	timer = RING_TO_TIMER(ring);
    984 	if (timer->callback == callback && timer->context == context) {
    985 	    if ((time_left = timer->when - event_present) < 0)
    986 		time_left = 0;
    987 	    ring_detach(ring);
    988 	    myfree((void *) timer);
    989 	    break;
    990 	}
    991     }
    992     if (msg_verbose > 2)
    993 	msg_info("%s: 0x%lx 0x%lx %d", myname,
    994 		 (long) callback, (long) context, time_left);
    995     return (time_left);
    996 }
    997 
    998 /* event_loop - wait for the next event */
    999 
   1000 void    event_loop(int delay)
   1001 {
   1002     const char *myname = "event_loop";
   1003     static int nested;
   1004 
   1005 #if (EVENTS_STYLE == EVENTS_STYLE_SELECT)
   1006     fd_set  rmask;
   1007     fd_set  wmask;
   1008     fd_set  xmask;
   1009     struct timeval tv;
   1010     struct timeval *tvp;
   1011     int     new_max_fd;
   1012 
   1013 #else
   1014     EVENT_BUFFER event_buf[100];
   1015     EVENT_BUFFER *bp;
   1016 
   1017 #endif
   1018     int     event_count;
   1019     EVENT_TIMER *timer;
   1020     int     fd;
   1021     EVENT_FDTABLE *fdp;
   1022     int     select_delay;
   1023 
   1024     if (EVENT_INIT_NEEDED())
   1025 	event_init();
   1026 
   1027     /*
   1028      * XXX Also print the select() masks?
   1029      */
   1030     if (msg_verbose > 2) {
   1031 	RING   *ring;
   1032 
   1033 	FOREACH_QUEUE_ENTRY(ring, &event_timer_head) {
   1034 	    timer = RING_TO_TIMER(ring);
   1035 	    msg_info("%s: time left %3d for 0x%lx 0x%lx", myname,
   1036 		     (int) (timer->when - event_present),
   1037 		     (long) timer->callback, (long) timer->context);
   1038 	}
   1039     }
   1040 
   1041     /*
   1042      * Find out when the next timer would go off. Timer requests are sorted.
   1043      * If any timer is scheduled, adjust the delay appropriately.
   1044      */
   1045     if ((timer = FIRST_TIMER(&event_timer_head)) != 0) {
   1046 	event_present = time((time_t *) 0);
   1047 	if ((select_delay = timer->when - event_present) < 0) {
   1048 	    select_delay = 0;
   1049 	} else if (delay >= 0 && select_delay > delay) {
   1050 	    select_delay = delay;
   1051 	}
   1052     } else {
   1053 	select_delay = delay;
   1054     }
   1055     if (msg_verbose > 2)
   1056 	msg_info("event_loop: select_delay %d", select_delay);
   1057 
   1058     /*
   1059      * Negative delay means: wait until something happens. Zero delay means:
   1060      * poll. Positive delay means: wait at most this long.
   1061      */
   1062 #if (EVENTS_STYLE == EVENTS_STYLE_SELECT)
   1063     if (select_delay < 0) {
   1064 	tvp = 0;
   1065     } else {
   1066 	tvp = &tv;
   1067 	tv.tv_usec = 0;
   1068 	tv.tv_sec = select_delay;
   1069     }
   1070 
   1071     /*
   1072      * Pause until the next event happens. When select() has a problem, don't
   1073      * go into a tight loop. Allow select() to be interrupted due to the
   1074      * arrival of a signal.
   1075      */
   1076     rmask = event_rmask;
   1077     wmask = event_wmask;
   1078     xmask = event_xmask;
   1079 
   1080     event_count = select(event_max_fd + 1, &rmask, &wmask, &xmask, tvp);
   1081     if (event_count < 0) {
   1082 	if (errno != EINTR)
   1083 	    msg_fatal("event_loop: select: %m");
   1084 	return;
   1085     }
   1086 #else
   1087     EVENT_BUFFER_READ(event_count, event_buf,
   1088 		      sizeof(event_buf) / sizeof(event_buf[0]),
   1089 		      select_delay);
   1090     if (event_count < 0) {
   1091 	if (errno != EINTR)
   1092 	    msg_fatal("event_loop: " EVENT_BUFFER_READ_TEXT ": %m");
   1093 	return;
   1094     }
   1095 #endif
   1096 
   1097     /*
   1098      * Before entering the application call-back routines, make sure we
   1099      * aren't being called from a call-back routine. Doing so would make us
   1100      * vulnerable to all kinds of race conditions.
   1101      */
   1102     if (nested++ > 0)
   1103 	msg_panic("event_loop: recursive call");
   1104 
   1105     /*
   1106      * Deliver timer events. Allow the application to add/delete timer queue
   1107      * requests while it is being called back. Requests are sorted: we keep
   1108      * running over the timer request queue from the start, and stop when we
   1109      * reach the future or the list end. We also stop when we reach a timer
   1110      * request that was added by a call-back that was invoked from this
   1111      * event_loop() call instance, for reasons that are explained below.
   1112      *
   1113      * To avoid dangling pointer problems 1) we must remove a request from the
   1114      * timer queue before delivering its event to the application and 2) we
   1115      * must look up the next timer request *after* calling the application.
   1116      * The latter complicates the handling of zero-delay timer requests that
   1117      * are added by event_loop() call-back functions.
   1118      *
   1119      * XXX When a timer event call-back function adds a new timer request,
   1120      * event_request_timer() labels the request with the event_loop() call
   1121      * instance that invoked the timer event call-back. We use this instance
   1122      * label here to prevent zero-delay timer requests from running in a
   1123      * tight loop and starving I/O events. To make this solution work,
   1124      * event_request_timer() appends a new request after existing requests
   1125      * for the same time slot.
   1126      */
   1127     event_present = time((time_t *) 0);
   1128     event_loop_instance += 1;
   1129 
   1130     while ((timer = FIRST_TIMER(&event_timer_head)) != 0) {
   1131 	if (timer->when > event_present)
   1132 	    break;
   1133 	if (timer->loop_instance == event_loop_instance)
   1134 	    break;
   1135 	ring_detach(&timer->ring);		/* first this */
   1136 	if (msg_verbose > 2)
   1137 	    msg_info("%s: timer 0x%lx 0x%lx", myname,
   1138 		     (long) timer->callback, (long) timer->context);
   1139 	timer->callback(EVENT_TIME, timer->context);	/* then this */
   1140 	myfree((void *) timer);
   1141     }
   1142 
   1143     /*
   1144      * Deliver I/O events. Allow the application to cancel event requests
   1145      * while it is being called back. To this end, we keep an eye on the
   1146      * contents of event_xmask, so that we deliver only events that are still
   1147      * wanted. We do not change the event request masks. It is up to the
   1148      * application to determine when a read or write is complete.
   1149      */
   1150 #if (EVENTS_STYLE == EVENTS_STYLE_SELECT)
   1151     if (event_count > 0) {
   1152 	for (new_max_fd = 0, fd = 0; fd <= event_max_fd; fd++) {
   1153 	    if (FD_ISSET(fd, &event_xmask)) {
   1154 		new_max_fd = fd;
   1155 		/* In case event_fdtable is updated. */
   1156 		fdp = event_fdtable + fd;
   1157 		if (FD_ISSET(fd, &xmask)) {
   1158 		    if (msg_verbose > 2)
   1159 			msg_info("%s: exception fd=%d act=0x%lx 0x%lx", myname,
   1160 			     fd, (long) fdp->callback, (long) fdp->context);
   1161 		    fdp->callback(EVENT_XCPT, fdp->context);
   1162 		} else if (FD_ISSET(fd, &wmask)) {
   1163 		    if (msg_verbose > 2)
   1164 			msg_info("%s: write fd=%d act=0x%lx 0x%lx", myname,
   1165 			     fd, (long) fdp->callback, (long) fdp->context);
   1166 		    fdp->callback(EVENT_WRITE, fdp->context);
   1167 		} else if (FD_ISSET(fd, &rmask)) {
   1168 		    if (msg_verbose > 2)
   1169 			msg_info("%s: read fd=%d act=0x%lx 0x%lx", myname,
   1170 			     fd, (long) fdp->callback, (long) fdp->context);
   1171 		    fdp->callback(EVENT_READ, fdp->context);
   1172 		}
   1173 	    }
   1174 	}
   1175 	event_max_fd = new_max_fd;
   1176     }
   1177 #else
   1178     for (bp = event_buf; bp < event_buf + event_count; bp++) {
   1179 	fd = EVENT_GET_FD(bp);
   1180 	if (fd < 0 || fd > event_max_fd)
   1181 	    msg_panic("%s: bad file descriptor: %d", myname, fd);
   1182 	if (EVENT_MASK_ISSET(fd, &event_xmask)) {
   1183 	    fdp = event_fdtable + fd;
   1184 	    if (EVENT_TEST_READ(bp)) {
   1185 		if (msg_verbose > 2)
   1186 		    msg_info("%s: read fd=%d act=0x%lx 0x%lx", myname,
   1187 			     fd, (long) fdp->callback, (long) fdp->context);
   1188 		fdp->callback(EVENT_READ, fdp->context);
   1189 	    } else if (EVENT_TEST_WRITE(bp)) {
   1190 		if (msg_verbose > 2)
   1191 		    msg_info("%s: write fd=%d act=0x%lx 0x%lx", myname,
   1192 			     fd, (long) fdp->callback,
   1193 			     (long) fdp->context);
   1194 		fdp->callback(EVENT_WRITE, fdp->context);
   1195 	    } else {
   1196 		if (msg_verbose > 2)
   1197 		    msg_info("%s: other fd=%d act=0x%lx 0x%lx", myname,
   1198 			     fd, (long) fdp->callback, (long) fdp->context);
   1199 		fdp->callback(EVENT_XCPT, fdp->context);
   1200 	    }
   1201 	}
   1202     }
   1203 #endif
   1204     nested--;
   1205 }
   1206 
   1207 #ifdef TEST
   1208 
   1209  /*
   1210   * Proof-of-concept test program for the event manager. Schedule a series of
   1211   * events at one-second intervals and let them happen, while echoing any
   1212   * lines read from stdin.
   1213   */
   1214 #include <stdio.h>
   1215 #include <ctype.h>
   1216 #include <stdlib.h>
   1217 
   1218 /* timer_event - display event */
   1219 
   1220 static void timer_event(int unused_event, void *context)
   1221 {
   1222     printf("%ld: %s\n", (long) event_present, context);
   1223     fflush(stdout);
   1224 }
   1225 
   1226 /* echo - echo text received on stdin */
   1227 
   1228 static void echo(int unused_event, void *unused_context)
   1229 {
   1230     char    buf[BUFSIZ];
   1231 
   1232     if (fgets(buf, sizeof(buf), stdin) == 0)
   1233 	exit(0);
   1234     printf("Result: %s", buf);
   1235 }
   1236 
   1237 /* request - request a bunch of timer events */
   1238 
   1239 static void request(int unused_event, void *unused_context)
   1240 {
   1241     event_request_timer(timer_event, "3 first", 3);
   1242     event_request_timer(timer_event, "3 second", 3);
   1243     event_request_timer(timer_event, "4 first", 4);
   1244     event_request_timer(timer_event, "4 second", 4);
   1245     event_request_timer(timer_event, "2 first", 2);
   1246     event_request_timer(timer_event, "2 second", 2);
   1247     event_request_timer(timer_event, "1 first", 1);
   1248     event_request_timer(timer_event, "1 second", 1);
   1249     event_request_timer(timer_event, "0 first", 0);
   1250     event_request_timer(timer_event, "0 second", 0);
   1251 }
   1252 
   1253 int     main(int argc, void **argv)
   1254 {
   1255     if (argv[1])
   1256 	msg_verbose = atoi(argv[1]);
   1257     event_request_timer(request, (void *) 0, 0);
   1258     event_enable_read(fileno(stdin), echo, (void *) 0);
   1259     event_drain(10);
   1260     exit(0);
   1261 }
   1262 
   1263 #endif
   1264