changeset 245:e6c005b66b3a

nginx-0.0.1-2004-01-30-00:45:01 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 29 Jan 2004 21:45:01 +0000
parents 187dc0a3197d
children 6753e8cdaa2c
files auto/options auto/os/conf auto/os/linux auto/sources src/core/ngx_times.c src/core/ngx_times.h src/event/modules/ngx_devpoll_module.c src/event/modules/ngx_devpoll_module.h src/event/modules/ngx_epoll_module.c src/event/modules/ngx_kqueue_module.c src/event/modules/ngx_poll_module.c src/event/modules/ngx_poll_module.h src/event/modules/ngx_select_module.c src/event/modules/ngx_select_module.h src/event/ngx_event.c src/event/ngx_event_accept.c
diffstat 16 files changed, 495 insertions(+), 265 deletions(-) [+]
line wrap: on
line diff
--- a/auto/options
+++ b/auto/options
@@ -5,6 +5,7 @@ CC=gcc
 OBJS=objs
 
 TEST_BUILD_DEVPOLL=NO
+TEST_BUILD_EPOLL=NO
 
 SELECT=YES
 POLL=YES
@@ -54,6 +55,7 @@ do
         --with-zlib=*)                   ZLIB="$value"              ;;
 
         --test-build-devpoll)            TEST_BUILD_DEVPOLL=YES     ;;
+        --test-build-epoll)              TEST_BUILD_EPOLL=YES       ;;
 
         *)
             echo "$0: error: invalid option \"$option\""
--- a/auto/os/conf
+++ b/auto/os/conf
@@ -44,6 +44,13 @@ esac
 
 
 if [ $TEST_BUILD_DEVPOLL = YES ]; then
+    CFLAGS="$CFLAGS -D HAVE_DEVPOLL=1 -D TEST_BUILD_DEVPOLL=1"
     EVENT_MODULES="$EVENT_MODULES $DEVPOLL_MODULE"
-    EVENT_SRCS="$EVENT_SRCS $DEVPOLL_SRCS"
+    CORE_SRCS="$CORE_SRCS $DEVPOLL_SRCS"
 fi
+
+if [ $TEST_BUILD_EPOLL = YES ]; then
+    CFLAGS="$CFLAGS -D HAVE_EPOLL=1 -D TEST_BUILD_EPOLL=1"
+    EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE"
+    CORE_SRCS="$CORE_SRCS $EPOLL_SRCS"
+fi
--- a/auto/os/linux
+++ b/auto/os/linux
@@ -7,6 +7,15 @@ EVENT_MODULES="$EVENT_MODULES $SELECT_MO
 ZLIB_LIB="-lz"
 
 
+NGX_INC="sys/epoll.h"; . auto/inc
+
+if [ $NGX_FOUND=YES ]; then
+    CFLAGS="$CFLAGS -D HAVE_EPOLL=1"
+    EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE"
+    CORE_SRCS="$CORE_SRCS $EPOLL_SRCS"
+fi
+
+
 # TODO check sendfile64()
 
 CC_TEST_FLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE"
--- a/auto/sources
+++ b/auto/sources
@@ -74,6 +74,9 @@ KQUEUE_SRCS=src/event/modules/ngx_kqueue
 DEVPOLL_MODULE="ngx_devpoll_module"
 DEVPOLL_SRCS=src/event/modules/ngx_devpoll_module.c
 
+EPOLL_MODULE="ngx_epoll_module"
+EPOLL_SRCS=src/event/modules/ngx_epoll_module.c
+
 IOCP_MODULE="ngx_iocp_module"
 IOCP_SRCS=src/event/modules/ngx_iocp_module.c
 
--- a/src/core/ngx_times.c
+++ b/src/core/ngx_times.c
@@ -37,9 +37,10 @@ void ngx_time_init()
     ngx_cached_err_log_time.data = cached_err_log_time;
     ngx_cached_http_time.data = cached_http_time;
     ngx_cached_http_log_time.data = cached_http_log_time;
+    ngx_cached_time = 0;
 
     ngx_gettimeofday(&tv);
-    ngx_cached_time = 0;
+
     ngx_start_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000;
     ngx_old_elapsed_msec = 0;
     ngx_elapsed_msec = 0;
--- a/src/core/ngx_times.h
+++ b/src/core/ngx_times.h
@@ -15,13 +15,24 @@ void ngx_gmtime(time_t t, ngx_tm_t *tp);
 
 
 extern time_t            ngx_cached_time;
-extern ngx_epoch_msec_t  ngx_elapsed_msec;
-extern ngx_epoch_msec_t  ngx_old_elapsed_msec;
-extern ngx_epoch_msec_t  ngx_start_msec;
-
 extern ngx_str_t         ngx_cached_err_log_time;
 extern ngx_str_t         ngx_cached_http_time;
 extern ngx_str_t         ngx_cached_http_log_time;
 
+extern ngx_epoch_msec_t  ngx_start_msec;
+
+/*
+ * msecs elapsed since ngx_start_msec in the current event cycle,
+ * used in ngx_event_add_timer() and ngx_event_find_timer()
+ */
+extern ngx_epoch_msec_t  ngx_elapsed_msec;
+
+/*
+ * msecs elapsed since ngx_start_msec in the previous event cycle,
+ * used in ngx_event_expire_timers()
+ */
+extern ngx_epoch_msec_t  ngx_old_elapsed_msec;
+
+
 
 #endif /* _NGX_TIMES_H_INCLUDED_ */
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -106,9 +106,6 @@ static int ngx_devpoll_init(ngx_cycle_t 
 
     dpcf = ngx_event_get_conf(cycle->conf_ctx, ngx_devpoll_module);
 
-ngx_log_debug(cycle->log, "CH: %d" _ dpcf->changes);
-ngx_log_debug(cycle->log, "EV: %d" _ dpcf->events);
-
     if (dp == -1) {
         dp = open("/dev/poll", O_RDWR);
 
@@ -122,7 +119,7 @@ ngx_log_debug(cycle->log, "EV: %d" _ dpc
     if (max_changes < dpcf->changes) {
         if (nchanges) {
             n = nchanges * sizeof(struct pollfd);
-            if ((size_t) write(dp, change_list, n) != n) {
+            if (write(dp, change_list, n) != (ssize_t) n) {
                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                               "write(/dev/poll) failed");
                 return NGX_ERROR;
@@ -199,8 +196,8 @@ static void ngx_devpoll_done(ngx_cycle_t
 
 static int ngx_devpoll_add_event(ngx_event_t *ev, int event, u_int flags)
 {
-#if (NGX_DEBUG_EVENT)
-    ngx_connection_t *c = (ngx_connection_t *) ev->data;
+#if (NGX_DEBUG)
+    ngx_connection_t *c;
 #endif
 
 #if (NGX_READ_EVENT != POLLIN)
@@ -213,9 +210,10 @@ static int ngx_devpoll_add_event(ngx_eve
     }
 #endif
 
-#if (NGX_DEBUG_EVENT)
-    c = (ngx_connection_t *) ev->data;
-    ngx_log_debug(ev->log, "add event: %d:%d" _ c->fd _ event);
+#if (NGX_DEBUG)
+    c = ev->data;
+    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+                   "devpoll add event: fd:%d ev:%04X", c->fd, event);
 #endif
 
     ev->active = 1;
@@ -230,9 +228,8 @@ static int ngx_devpoll_del_event(ngx_eve
 
     c = ev->data;
 
-#if (NGX_DEBUG_EVENT)
-    ngx_log_debug(c->log, "del event: %d, %d" _ c->fd _ event);
-#endif
+    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+                   "devpoll del event: fd:%d ev:%04X", c->fd, event);
 
     if (ngx_devpoll_set_event(ev, POLLREMOVE, flags) == NGX_ERROR) {
         return NGX_ERROR;
@@ -270,17 +267,15 @@ static int ngx_devpoll_set_event(ngx_eve
 
     c = ev->data;
 
-#if (NGX_DEBUG_EVENT)
-    ngx_log_debug(ev->log, "devpoll fd:%d event:%d flush:%d" _
-                           c->fd _ event _ flags);
-#endif
+    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+                   "devpoll fd:%d ev:%d fl:%d", c->fd, event, flags);
 
     if (nchanges >= max_changes) {
         ngx_log_error(NGX_LOG_WARN, ev->log, 0,
                       "/dev/pool change list is filled up");
 
         n = nchanges * sizeof(struct pollfd);
-        if ((size_t) write(dp, change_list, n) != n) {
+        if (write(dp, change_list, n) != (ssize_t) n) {
             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
                           "write(/dev/poll) failed");
             return NGX_ERROR;
@@ -300,7 +295,7 @@ static int ngx_devpoll_set_event(ngx_eve
 
     if (flags & NGX_CLOSE_EVENT) {
         n = nchanges * sizeof(struct pollfd);
-        if ((size_t) write(dp, change_list, n) != n) {
+        if (write(dp, change_list, n) != (ssize_t) n) {
             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
                           "write(/dev/poll) failed");
             return NGX_ERROR;
@@ -320,29 +315,23 @@ int ngx_devpoll_process_events(ngx_log_t
     ngx_msec_t          timer;
     ngx_err_t           err;
     ngx_cycle_t       **cycle;
-    ngx_epoch_msec_t   delta;
     ngx_connection_t   *c;
+    ngx_epoch_msec_t    delta;
     struct dvpoll       dvp;
     struct timeval      tv;
 
     timer = ngx_event_find_timer();
+    ngx_old_elapsed_msec = ngx_elapsed_msec;
 
-    if (timer) {
-        ngx_gettimeofday(&tv);
-        delta = tv.tv_sec * 1000 + tv.tv_usec / 1000;
-
-    } else {
+    if (timer == 0) {
         timer = (ngx_msec_t) INFTIM;
-        delta = 0;
     }
 
-#if (NGX_DEBUG_EVENT)
-    ngx_log_debug(log, "devpoll timer: %d" _ timer);
-#endif
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "devpoll timer: %d", timer);
 
     if (nchanges) {
         n = nchanges * sizeof(struct pollfd);
-        if ((size_t) write(dp, change_list, n) != n) {
+        if (write(dp, change_list, n) != (ssize_t) n) {
             ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                           "write(/dev/poll) failed");
             return NGX_ERROR;
@@ -363,34 +352,27 @@ int ngx_devpoll_process_events(ngx_log_t
     nchanges = 0;
 
     ngx_gettimeofday(&tv);
+    ngx_time_update(tv.tv_sec);
 
-    if (ngx_cached_time != tv.tv_sec) {
-        ngx_cached_time = tv.tv_sec;
-        ngx_time_update();
-    }
+    delta = ngx_elapsed_msec;
+    ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
 
     if ((int) timer != INFTIM) {
-        delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
+        delta = ngx_elapsed_msec - delta;
 
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "devpoll timer: %d, delta: %d" _ timer _ (int)delta);
-#endif
-        ngx_event_expire_timers((ngx_msec_t) delta);
-
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "devpoll timer: %d, delta: %d", timer, (int) delta);
     } else {
         if (events == 0) {
             ngx_log_error(NGX_LOG_ALERT, log, 0,
                           "ioctl(DP_POLL) returned no events without timeout");
             return NGX_ERROR;
         }
-
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "devpoll timer: %d, delta: %d" _ timer _ (int)delta);
-#endif
     }
 
     if (err) {
-        ngx_log_error(NGX_LOG_ALERT, log, err, "ioctl(DP_POLL) failed");
+        ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
+                      log, err, "ioctl(DP_POLL) failed");
         return NGX_ERROR;
     }
 
@@ -411,15 +393,14 @@ int ngx_devpoll_process_events(ngx_log_t
         }
 
         if (c->fd == -1) {
-            ngx_log_error(NGX_LOG_ALERT, log, 0, "unkonwn cycle");
+            ngx_log_error(NGX_LOG_EMERG, log, 0, "unknown cycle");
             exit(1);
         }
 
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "devpoll: %d: ev:%d rev:%d" _
-                      event_list[i].fd _
-                      event_list[i].events _ event_list[i].revents);
-#endif
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "devpoll: fd:%d, ev:%04X, rev:%04X",
+                       event_list[i].fd,
+                       event_list[i].events, event_list[i].revents);
 
         if (event_list[i].revents & POLLIN) {
             if (!c->read->active) {
@@ -451,6 +432,10 @@ int ngx_devpoll_process_events(ngx_log_t
         }
     }
 
+    if (timer != (ngx_msec_t) INFTIM && delta) {
+        ngx_event_expire_timers((ngx_msec_t) delta);
+    }
+
     return NGX_OK;
 }
 
deleted file mode 100644
--- a/src/event/modules/ngx_devpoll_module.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _NGX_DEVPOLL_MODULE_H_INCLUDED_
-#define _NGX_DEVPOLL_MODULE_H_INCLUDED_
-
-
-#include <ngx_types.h>
-#include <ngx_log.h>
-#include <ngx_event.h>
-
-int ngx_devpoll_init(int max_connections, ngx_log_t *log);
-int ngx_devpoll_add_event(ngx_event_t *ev, int event, u_int flags);
-int ngx_devpoll_del_event(ngx_event_t *ev, int event, u_int flags);
-void ngx_devpoll_add_timer(ngx_event_t *ev, ngx_msec_t timer);
-int ngx_devpoll_process_events(ngx_log_t *log);
-
-
-#if 0
-/* Solaris */
-
-#define POLLREMOVE   0x0800
-
-#define DP_POLL      0xD001
-
-struct dvpoll {
-    struct pollfd  *dp_fds;
-    int             dp_nfds;
-    int             dp_timeout;
-};
-
-#endif
-
-
-#endif /* _NGX_DEVPOLL_MODULE_H_INCLUDED_ */
new file mode 100644
--- /dev/null
+++ b/src/event/modules/ngx_epoll_module.c
@@ -0,0 +1,344 @@
+
+/*
+ * Copyright (C) 2002-2004 Igor Sysoev, http://sysoev.ru/en/
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+
+
+#if (TEST_BUILD_EPOLL)
+
+/* epoll declarations */
+
+#define EPOLLIN      0x001
+#define EPOLLPRI     0x002
+#define EPOLLOUT     0x004
+#define EPOLLRDNORM  0x040
+#define EPOLLRDBAND  0x080
+#define EPOLLWRNORM  0x100
+#define EPOLLWRBAND  0x200
+#define EPOLLMSG     0x400
+#define EPOLLERR     0x008
+#define EPOLLHUP     0x010
+
+#define EPOLL_CTL_ADD  1
+#define EPOLL_CTL_DEL  2
+#define EPOLL_CTL_MOD  3
+
+typedef union epoll_data {
+    void         *ptr;
+    int           fd;
+    uint32_t      u32;
+    uint64_t      u64;
+} epoll_data_t;
+
+struct epoll_event {
+    uint32_t      events;
+    epoll_data_t  data;
+};
+
+int epoll_create(int size);
+int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
+int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout);
+
+int epoll_create(int size)
+{
+    return -1;
+}
+
+int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
+{
+    return -1;
+}
+
+int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout)
+{
+    return -1;
+}
+
+#endif
+
+
+typedef struct {
+    u_int  events;
+} ngx_epoll_conf_t;
+
+
+static int ngx_epoll_init(ngx_cycle_t *cycle);
+static void ngx_epoll_done(ngx_cycle_t *cycle);
+static int ngx_epoll_add_connection(ngx_connection_t *c);
+static int ngx_epoll_del_connection(ngx_connection_t *c);
+static int ngx_epoll_process_events(ngx_log_t *log);
+
+static void *ngx_epoll_create_conf(ngx_cycle_t *cycle);
+static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf);
+
+static int                  ep = -1;
+static struct epoll_event  *event_list;
+static u_int                nevents;
+
+
+static ngx_str_t      epoll_name = ngx_string("epoll");
+
+static ngx_command_t  ngx_epoll_commands[] = {
+
+    {ngx_string("epoll_events"),
+     NGX_EVENT_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_num_slot,
+     0,
+     offsetof(ngx_epoll_conf_t, events),
+     NULL},
+
+    ngx_null_command
+};
+
+
+ngx_event_module_t  ngx_epoll_module_ctx = {
+    &epoll_name,
+    ngx_epoll_create_conf,               /* create configuration */
+    ngx_epoll_init_conf,                 /* init configuration */
+
+    {
+        NULL,                            /* add an event */
+        NULL,                            /* delete an event */
+        NULL,                            /* enable an event */
+        NULL,                            /* disable an event */
+        ngx_epoll_add_connection,        /* add an connection */
+        ngx_epoll_del_connection,        /* delete an connection */
+        ngx_epoll_process_events,        /* process the events */
+        ngx_epoll_init,                  /* init the events */
+        ngx_epoll_done,                  /* done the events */
+    }
+
+};
+
+ngx_module_t  ngx_epoll_module = {
+    NGX_MODULE,
+    &ngx_epoll_module_ctx,               /* module context */
+    ngx_epoll_commands,                  /* module directives */
+    NGX_EVENT_MODULE,                      /* module type */
+    NULL,                                  /* init module */
+    NULL                                   /* init child */
+};
+
+
+static int ngx_epoll_init(ngx_cycle_t *cycle)
+{
+    size_t             n;
+    ngx_epoll_conf_t  *epcf;
+
+    epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
+
+    if (ep == -1) {
+        ep = epoll_create(/* STUB: open_files / 2 */ 512);
+
+        if (ep == -1) {
+            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                          "epoll_create() failed");
+            return NGX_ERROR;
+        }
+    }
+
+    if (nevents < epcf->events) {
+        if (event_list) {
+            ngx_free(event_list);
+        }
+
+        event_list = ngx_alloc(sizeof(struct epoll_event) * epcf->events,
+                               cycle->log);
+        if (event_list == NULL) {
+            return NGX_ERROR;
+        }
+    }
+
+    nevents = epcf->events;
+
+    ngx_io = ngx_os_io;
+
+    ngx_event_actions = ngx_epoll_module_ctx.actions;
+
+    ngx_event_flags = NGX_USE_EDGE_EVENT;
+
+    return NGX_OK;
+}
+
+
+static void ngx_epoll_done(ngx_cycle_t *cycle)
+{
+    if (close(ep) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "epoll close() failed");
+    }
+
+    ep = -1;
+
+    ngx_free(event_list);
+
+    event_list = NULL;
+    nevents = 0;
+}
+
+
+static int ngx_epoll_add_connection(ngx_connection_t *c)
+{
+    struct epoll_event  ev;
+
+    ev.events = EPOLLIN|EPOLLOUT;
+    ev.data.ptr = (void *) ((uintptr_t) c | c->read->instance);
+
+    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "epoll add connection: fd:%d ev:%04X", c->fd, ev.events);
+
+    if (epoll_ctl(ep, EPOLL_CTL_ADD, c->fd, &ev) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
+                      "epoll_ctl(#%d) failed", c->fd);
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
+
+
+static int ngx_epoll_del_connection(ngx_connection_t *c)
+{
+    c->read->active = 0;
+    c->write->active = 0;
+
+    return NGX_OK;
+}
+
+
+int ngx_epoll_process_events(ngx_log_t *log)
+{
+    int                 events;
+    ngx_int_t           instance, i;
+    size_t              n;
+    ngx_msec_t          timer;
+    ngx_err_t           err;
+    ngx_cycle_t       **cycle;
+    struct timeval      tv;
+    ngx_connection_t   *c;
+    ngx_epoch_msec_t    delta;
+
+
+    timer = ngx_event_find_timer();
+    ngx_old_elapsed_msec = ngx_elapsed_msec;
+
+    if (timer == 0) {
+        timer = (ngx_msec_t) -1;
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "epoll timer: %d", timer);
+
+    events = epoll_wait(ep, event_list, nevents, timer);
+
+    if (events == -1) {
+        err = ngx_errno;
+    } else {
+        err = 0;
+    }
+
+    ngx_gettimeofday(&tv);
+    ngx_time_update(tv.tv_sec);
+
+    delta = ngx_elapsed_msec;
+    ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
+
+    if ((int) timer != INFTIM) {
+        delta = ngx_elapsed_msec - delta;
+
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "epoll timer: %d, delta: %d", timer, (int) delta);
+    } else {
+        if (events == 0) {
+            ngx_log_error(NGX_LOG_ALERT, log, 0,
+                          "epoll_wait() returned no events without timeout");
+            return NGX_ERROR;
+        }
+    }
+
+    if (err) {
+        ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
+                      log, err, "epoll_wait() failed");
+        return NGX_ERROR;
+    }
+
+    for (i = 0; i < events; i++) {
+        c = event_list[i].data.ptr;
+
+        instance = (uintptr_t) c & 1;
+        c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
+
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "epoll: fd:%d ev:%04X d:" PTR_FMT,
+                       c->fd, event_list[i].events, event_list[i].data);
+
+        if (c->read->instance != instance) {
+
+            /*
+             * it's a stale event from a file descriptor
+             * that was just closed in this iteration
+             */
+
+            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
+                           "epoll: stale event " PTR_FMT, c);
+            continue;
+        }
+
+        if (event_list[i].events & EPOLLIN) {
+            if (!c->read->active) {
+                continue;
+            }
+
+            c->read->ready = 1;
+            c->read->event_handler(c->read);
+        }
+
+        if (event_list[i].events & EPOLLOUT) {
+            if (!c->write->active) {
+                continue;
+            }
+
+            c->write->ready = 1;
+            c->write->event_handler(c->write);
+        }
+
+        if (event_list[i].events & (EPOLLERR|EPOLLHUP|EPOLLMSG)) {
+            ngx_log_error(NGX_LOG_ERR, log, 0,
+                          "epoll_wait() error on fd:%d ev:%d",
+                          c->fd, event_list[i].events);
+        }
+    }
+
+    if (timer != (ngx_msec_t) -1 && delta) {
+        ngx_event_expire_timers((ngx_msec_t) delta);
+    }
+
+    return NGX_OK;
+}
+
+
+static void *ngx_epoll_create_conf(ngx_cycle_t *cycle)
+{
+    ngx_epoll_conf_t  *epcf;
+
+    ngx_test_null(epcf, ngx_palloc(cycle->pool, sizeof(ngx_epoll_conf_t)),
+                  NGX_CONF_ERROR);
+
+    epcf->events = NGX_CONF_UNSET;
+
+    return epcf;
+}
+
+
+static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf)
+{
+    ngx_epoll_conf_t *epcf = conf;
+
+    ngx_conf_init_unsigned_value(epcf->events, 512);
+
+    return NGX_CONF_OK;
+}
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -339,7 +339,8 @@ static int ngx_kqueue_set_event(ngx_even
 
 static int ngx_kqueue_process_events(ngx_log_t *log)
 {
-    ngx_int_t          events, instance, i;
+    int                events;
+    ngx_int_t          instance, i;
     ngx_err_t          err;
     ngx_msec_t         timer;
     ngx_event_t       *ev;
@@ -355,13 +356,7 @@ static int ngx_kqueue_process_events(ngx
         ts.tv_nsec = (timer % 1000) * 1000000;
         tp = &ts;
 
-#if 0
-        ngx_gettimeofday(&tv);
-        delta = tv.tv_sec * 1000 + tv.tv_usec / 1000;
-#endif
-
     } else {
-        delta = 0;
         tp = NULL;
     }
 
@@ -378,17 +373,17 @@ static int ngx_kqueue_process_events(ngx
     nchanges = 0;
 
     ngx_gettimeofday(&tv);
+    ngx_time_update(tv.tv_sec);
 
-#if 1
     delta = ngx_elapsed_msec;
-#endif
     ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
 
-    ngx_time_update(tv.tv_sec);
-
     if (timer) {
         delta = ngx_elapsed_msec - delta;
 
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "kevent timer: %d, delta: %d", timer, (int) delta);
+
     } else {
         if (events == 0) {
             ngx_log_error(NGX_LOG_ALERT, log, 0,
@@ -397,9 +392,6 @@ static int ngx_kqueue_process_events(ngx
         }
     }
 
-    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
-                   "kevent timer: %d, delta: %d", timer, (int) delta);
-
     if (err) {
         ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
                       log, err, "kevent() failed");
@@ -496,33 +488,6 @@ static int ngx_kqueue_process_events(ngx
 }
 
 
-#if 0
-
-static void ngx_kqueue_thread_handler(ngx_event_t *ev, ngx_log_t *log)
-{
-    ngx_int_t  instance;
-
-    instance = (uintptr_t) ev & 1;
-    ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1);
-
-    if (ev->active && ev->instance == instance) {
-        ev->event_handler(ev);
-        return;
-    }
-
-    /*
-     * it's a stale event from a file descriptor
-     * that was just closed in this iteration
-     */
-
-    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
-                   "kevent: stale event " PTR_FMT, ev);
-
-}
-
-#endif
-
-
 static void *ngx_kqueue_create_conf(ngx_cycle_t *cycle)
 {
     ngx_kqueue_conf_t  *kcf;
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (C) 2002-2003 Igor Sysoev, http://sysoev.ru
+ * Copyright (C) 2002-2004 Igor Sysoev, http://sysoev.ru/en/
  */
 
 
@@ -146,9 +146,8 @@ static int ngx_poll_add_event(ngx_event_
 #endif
     }
 
-#if (NGX_DEBUG_EVENT)
-    ngx_log_debug(ev->log, "add event: %d:%d" _ c->fd _ event);
-#endif
+    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+                   "poll add event: fd:%d ev:%d", c->fd, event);
 
     if (e == NULL || e->index == NGX_INVALID_INDEX) {
         event_list[nevents].fd = c->fd;
@@ -192,9 +191,8 @@ static int ngx_poll_del_event(ngx_event_
 #endif
     }
 
-#if (NGX_DEBUG_EVENT)
-    ngx_log_debug(c->log, "del event: %d, %d" _ c->fd _ event);
-#endif
+    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+                   "poll del event: fd:%d ev:%d", c->fd, event);
 
     if (e == NULL || e->index == NGX_INVALID_INDEX) {
         if (ev->index < (u_int) --nevents) {
@@ -221,28 +219,24 @@ static int ngx_poll_process_events(ngx_l
     ngx_err_t           err;
     ngx_cycle_t       **cycle;
     ngx_event_t        *ev;
-    ngx_epoch_msec_t   delta;
+    ngx_epoch_msec_t    delta;
     ngx_connection_t   *c;
-    struct timeval     tv;
+    struct timeval      tv;
 
     timer = ngx_event_find_timer();
+    ngx_old_elapsed_msec = ngx_elapsed_msec; 
 
-    if (timer) {
-        ngx_gettimeofday(&tv);
-        delta = tv.tv_sec * 1000 + tv.tv_usec / 1000;
-
-    } else {
+    if (timer == 0) {
         timer = (ngx_msec_t) INFTIM;
-        delta = 0;
     }
 
-#if (NGX_DEBUG_EVENT)
+#if (NGX_DEBUG)
     for (i = 0; i < nevents; i++) {
-        ngx_log_debug(log, "poll: %d, %d" _
-                      event_list[i].fd _ event_list[i].events);
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0, "poll: fd:%d ev:%04X",
+                       event_list[i].fd, event_list[i].events);
     }
 
-    ngx_log_debug(log, "poll timer: %d" _ timer);
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "poll timer: %d", timer);
 #endif
 
     ready = poll(event_list, (u_int) nevents, (int) timer);
@@ -253,33 +247,30 @@ static int ngx_poll_process_events(ngx_l
         err = 0;
     }
 
-    ngx_log_debug(log, "poll ready %d" _ ready);
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "poll ready %d", ready);
 
     ngx_gettimeofday(&tv);
     ngx_time_update(tv.tv_sec);
 
-    if ((int) timer != INFTIM) {
-        delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
+    delta = ngx_elapsed_msec;
+    ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
 
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "poll timer: %d, delta: %d" _ timer _ (int) delta);
-#endif
-        ngx_event_expire_timers((ngx_msec_t) delta);
+    if ((int) timer != INFTIM) {
+        delta = ngx_elapsed_msec - delta;
 
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "poll timer: %d, delta: %d", timer, (int) delta);
     } else {
         if (ready == 0) {
             ngx_log_error(NGX_LOG_ALERT, log, 0,
                           "poll() returned no events without timeout");
             return NGX_ERROR;
         }
-
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "poll timer: %d, delta: %d" _ timer _ (int) delta);
-#endif
     }
 
     if (err) {
-        ngx_log_error(NGX_LOG_ALERT, log, err, "poll() failed");
+        ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
+                      log, err, "poll() failed");
         return NGX_ERROR;
     }
 
@@ -306,11 +297,10 @@ static int ngx_poll_process_events(ngx_l
             exit(1);
         }
 
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "poll: fd:%d, ev:%d, rev:%d" _
-                      event_list[i].fd _
-                      event_list[i].events _ event_list[i].revents);
-#endif
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "poll: fd:%d ev:%04X rev:%04X",
+                       event_list[i].fd,
+                       event_list[i].events, event_list[i].revents);
 
         found = 0;
 
@@ -343,7 +333,7 @@ static int ngx_poll_process_events(ngx_l
 
         if (event_list[i].revents & (POLLERR|POLLHUP)) {
             ngx_log_error(NGX_LOG_ALERT, log, 0,
-                          "strange poll() error on %d:%d:%d",
+                          "strange poll() error on fd:%d ev:%04X rev:%04X",
                           event_list[i].fd,
                           event_list[i].events, event_list[i].revents);
         }
@@ -377,5 +367,9 @@ static int ngx_poll_process_events(ngx_l
         ngx_log_error(NGX_LOG_ALERT, log, 0, "poll ready != events");
     }
 
+    if (timer != (ngx_msec_t) INFTIM && delta) {
+        ngx_event_expire_timers((ngx_msec_t) delta);
+    }
+
     return NGX_OK;
 }
deleted file mode 100644
--- a/src/event/modules/ngx_poll_module.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _NGX_POLL_MODULE_H_INCLUDED_
-#define _NGX_POLL_MODULE_H_INCLUDED_
-
-
-#include <ngx_types.h>
-#include <ngx_log.h>
-#include <ngx_event.h>
-
-int ngx_poll_init(int max_connections, ngx_log_t *log);
-int ngx_poll_add_event(ngx_event_t *ev, int event, u_int flags);
-int ngx_poll_del_event(ngx_event_t *ev, int event, u_int flags);
-void ngx_poll_add_timer(ngx_event_t *ev, ngx_msec_t timer);
-int ngx_poll_process_events(ngx_log_t *log);
-
-
-#endif /* _NGX_POLL_MODULE_H_INCLUDED_ */
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -131,9 +131,8 @@ static int ngx_select_add_event(ngx_even
 
     c = ev->data;
 
-#if (NGX_DEBUG_EVENT)
-    ngx_log_debug(ev->log, "select fd:%d event:%d" _ c->fd _ event);
-#endif
+    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+                   "select add event fd:%d ev:%d", c->fd, event);
 
     if (ev->index != NGX_INVALID_INDEX) {
         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
@@ -197,9 +196,8 @@ static int ngx_select_del_event(ngx_even
         return NGX_OK;
     }
 
-#if (NGX_DEBUG_EVENT)
-    ngx_log_debug(c->log, "del event: %d, %d" _ c->fd _ event);
-#endif
+    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
+                   "select del event fd:%d ev:%d", c->fd, event);
 
 #if (WIN32)
 
@@ -259,19 +257,11 @@ static int ngx_select_process_events(ngx
     ngx_old_elapsed_msec = ngx_elapsed_msec;
 
     if (timer) {
-#if (HAVE_SELECT_CHANGE_TIMEOUT)
-        delta = 0;
-#else
-        ngx_gettimeofday(&tv);
-        delta = tv.tv_sec * 1000 + tv.tv_usec / 1000;
-#endif
-
         tv.tv_sec = timer / 1000;
         tv.tv_usec = (timer % 1000) * 1000;
         tp = &tv;
 
     } else {
-        delta = 0;
         tp = NULL;
     }
 
@@ -284,21 +274,21 @@ static int ngx_select_process_events(ngx
             }
         }
 
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "change max_fd: %d" _ max_fd);
-#endif
+        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "change max_fd: %d", max_fd);
     }
 #endif
 
-#if (NGX_DEBUG_EVENT)
+#if (NGX_DEBUG)
     for (i = 0; i < nevents; i++) {
         ev = event_index[i];
         c = (ngx_connection_t *) ev->data;
-        ngx_log_debug(log, "select: %d:%d" _ c->fd _ ev->write);
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "select event: fd:%d wr:%d", c->fd,ev->write);
     }
+#endif
 
-    ngx_log_debug(log, "select timer: %d" _ timer);
-#endif
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "select timer: %d", timer);
 
 #if (WIN32)
     ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp);
@@ -312,10 +302,6 @@ static int ngx_select_process_events(ngx
         err = 0;
     }
 
-#if (NGX_DEBUG_EVENT)
-    ngx_log_debug(log, "select ready %d" _ ready);
-#endif
-
 #if (HAVE_SELECT_CHANGE_TIMEOUT)
 
     if (timer) {
@@ -330,51 +316,36 @@ static int ngx_select_process_events(ngx
         if (deltas > 1000) {
             ngx_gettimeofday(&tv);
             deltas = tv.tv_usec / 1000;
-
-            if (ngx_cached_time != tv.tv_sec) {
-                ngx_cached_time = tv.tv_sec;
-                ngx_time_update();
-            }
+            ngx_time_update(tv.tv_sec);
         }
 
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "select timer: %d, delta: %d" _ timer _ (int) delta);
-#endif
-
-        ngx_event_expire_timers((ngx_msec_t) delta);
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "select timer: %d, delta: %d", timer, (int) delta);
 
     } else {
         ngx_gettimeofday(&tv);
-
-        if (ngx_cached_time != tv.tv_sec) {
-            ngx_cached_time = tv.tv_sec;
-            ngx_time_update();
-        }
+        ngx_time_update(tv.tv_sec);
 
         if (ready == 0) {
             ngx_log_error(NGX_LOG_ALERT, log, 0,
                           "select() returned no events without timeout");
             return NGX_ERROR;
         }
-
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "select timer: %d, delta: %d" _ timer _ (int) delta);
-#endif
     }
 
-#else /* HAVE_SELECT_CHANGE_TIMEOUT */
+#else /* !(HAVE_SELECT_CHANGE_TIMEOUT) */
 
     ngx_gettimeofday(&tv);
     ngx_time_update(tv.tv_sec);
 
-    if (timer) {
-        delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
+    delta = ngx_elapsed_msec;
+    ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
 
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "select timer: %d, delta: %d" _ timer _ (int) delta);
-#endif
+    if (timer) {
+        delta = ngx_elapsed_msec - delta;
 
-        ngx_event_expire_timers((ngx_msec_t) delta);
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
+                       "select timer: %d, delta: %d", timer, (int) delta);
 
     } else {
         if (ready == 0) {
@@ -382,16 +353,15 @@ static int ngx_select_process_events(ngx
                           "select() returned no events without timeout");
             return NGX_ERROR;
         }
-
-#if (NGX_DEBUG_EVENT)
-        ngx_log_debug(log, "select timer: %d, delta: %d" _ timer _ (int) delta);
-#endif
     }
 
 #endif /* HAVE_SELECT_CHANGE_TIMEOUT */
 
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "select ready %d", ready);
+
     if (err) {
-        ngx_log_error(NGX_LOG_ALERT, log, err, "select() failed");
+        ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
+                      log, err, "select() failed");
         return NGX_ERROR;
     }
 
@@ -405,17 +375,15 @@ static int ngx_select_process_events(ngx
         if (ev->write) {
             if (FD_ISSET(c->fd, &work_write_fd_set)) {
                 found = 1;
-#if (NGX_DEBUG_EVENT)
-                ngx_log_debug(log, "select write %d" _ c->fd);
-#endif
+                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
+                               "select write %d", c->fd);
             }
 
         } else {
             if (FD_ISSET(c->fd, &work_read_fd_set)) {
                 found = 1;
-#if (NGX_DEBUG_EVENT)
-                ngx_log_debug(log, "select read %d" _ c->fd);
-#endif
+                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
+                               "select read %d", c->fd);
             }
         }
 
@@ -453,6 +421,10 @@ static int ngx_select_process_events(ngx
         ngx_log_error(NGX_LOG_ALERT, log, 0, "select ready != events");
     }
 
+    if (timer && delta) {
+        ngx_event_expire_timers((ngx_msec_t) delta);
+    }
+
     return NGX_OK;
 }
 
deleted file mode 100644
--- a/src/event/modules/ngx_select_module.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _NGX_SELECT_MODULE_H_INCLUDED_
-#define _NGX_SELECT_MODULE_H_INCLUDED_
-
-
-#include <ngx_types.h>
-#include <ngx_log.h>
-#include <ngx_event.h>
-
-int ngx_select_init(int max_connections, ngx_log_t *log);
-int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags);
-int ngx_select_del_event(ngx_event_t *ev, int event, u_int flags);
-void ngx_select_add_timer(ngx_event_t *ev, ngx_msec_t timer);
-int ngx_select_process_events(ngx_log_t *log);
-
-
-#endif /* _NGX_SELECT_MODULE_H_INCLUDED_ */
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -134,7 +134,8 @@ static int ngx_event_init(ngx_cycle_t *c
         if (ngx_modules[m]->ctx_index == ecf->use) {
             module = ngx_modules[m]->ctx;
             if (module->actions.init(cycle) == NGX_ERROR) {
-                return NGX_ERROR;
+                /* fatal */
+                exit(2);
             }
             break;
         }
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -192,6 +192,10 @@ void ngx_event_accept(ngx_event_t *ev)
             rev->ready = 1;
         }
 
+        if (ev->deferred_accept) {
+            rev->ready = 1;
+        }
+
         c->ctx = ls->ctx;
         c->servers = ls->servers;
 
@@ -215,10 +219,6 @@ void ngx_event_accept(ngx_event_t *ev)
         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                        "accept: %d, %d", s, c->number);
 
-        if (ev->deferred_accept) {
-            rev->ready = 1;
-        }
-
         if (ngx_add_conn) {
             if (ngx_add_conn(c) == NGX_ERROR) {
                 if (ngx_close_socket(s) == -1) {