nginx-0.0.1-2003-05-19-20:39:14 import
diff --git a/src/event/modules/ngx_aio_module.c b/src/event/modules/ngx_aio_module.c
index f2d0e83..20cb1a6 100644
--- a/src/event/modules/ngx_aio_module.c
+++ b/src/event/modules/ngx_aio_module.c
@@ -21,7 +21,7 @@
 
     rc = ngx_kqueue_init(max_connections, log);
 
-    ngx_event_flags = NGX_HAVE_AIO_EVENT;
+    ngx_event_flags = NGX_HAVE_AIO_EVENT|NGX_USE_AIO_EVENT;
     ngx_write_chain_proc = ngx_aio_write_chain;
 
     return rc;
diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c
index 8cc7190..bf03f5c 100644
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (C) 2002-2003 Igor Sysoev, http://sysoev.ru
  */
@@ -5,39 +6,30 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-#include <ngx_types.h>
-#include <ngx_log.h>
 #include <ngx_connection.h>
 #include <ngx_event.h>
-#include <ngx_event_timer.h>
-#include <ngx_conf_file.h>
 #include <ngx_kqueue_module.h>
 
 
-/* STUB */
-#define KQUEUE_NCHANGES  512
-#define KQUEUE_NEVENTS   512
+static int ngx_kqueue_init(ngx_log_t *log);
+static void ngx_kqueue_done(ngx_log_t *log);
+static int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags);
+static int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags);
+static int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags);
+static int ngx_kqueue_process_events(ngx_log_t *log);
+
+static void *ngx_kqueue_create_conf(ngx_pool_t *pool);
+static char *ngx_kqueue_init_conf(ngx_pool_t *pool, void *conf);
 
 
-static int  ngx_kqueue_changes;
-static int  ngx_kqueue_events;
+int                    ngx_kqueue;
+
+static struct kevent  *change_list, *event_list;
+static u_int           max_changes, nchanges;
+static int             nevents;
 
 
-/* should be per-thread if threads are used without thread pool */
-#if 1
-int                     kq;
-#else
-static int              kq;
-#endif
-static struct kevent   *change_list, *event_list;
-static unsigned int     nchanges;
-static int              nevents;
-
-static ngx_event_t     *timer_queue;
-/* */
-
-
-static ngx_str_t  kqueue_name = ngx_string("kqueue");
+static ngx_str_t      kqueue_name = ngx_string("kqueue");
 
 static ngx_command_t  ngx_kqueue_commands[] = {
 
@@ -45,21 +37,42 @@
      NGX_EVENT_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_num_slot,
      0,
-     addressof(ngx_kqueue_changes),
+     offsetof(ngx_kqueue_conf_t, changes),
      NULL},
 
     {ngx_string("kqueue_events"),
      NGX_EVENT_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_num_slot,
      0,
-     addressof(ngx_kqueue_events),
+     offsetof(ngx_kqueue_conf_t, events),
      NULL},
 
     {ngx_string(""), 0, NULL, 0, 0, NULL}
 };
 
+
+ngx_event_module_t  ngx_kqueue_module_ctx = {
+    NGX_EVENT_MODULE,
+    &kqueue_name,
+    ngx_kqueue_create_conf,                /* create configuration */
+    ngx_kqueue_init_conf,                  /* init configuration */
+
+    { 
+        ngx_kqueue_add_event,              /* add an event */
+        ngx_kqueue_del_event,              /* delete an event */
+        ngx_kqueue_add_event,              /* enable an event */
+        ngx_kqueue_del_event,              /* disable an event */
+        NULL,                              /* add an connection */
+        NULL,                              /* delete an connection */
+        ngx_kqueue_process_events,         /* process the events */
+        ngx_kqueue_init,                   /* init the events */
+        ngx_kqueue_done,                   /* done the events */
+    }
+
+};
+
 ngx_module_t  ngx_kqueue_module = {
-    &kqueue_name,                          /* module context */
+    &ngx_kqueue_module_ctx,                /* module context */
     0,                                     /* module index */
     ngx_kqueue_commands,                   /* module directives */
     NGX_EVENT_MODULE_TYPE,                 /* module type */
@@ -67,109 +80,91 @@
 };
 
 
-
-int ngx_kqueue_init(int max_connections, ngx_log_t *log)
+static int ngx_kqueue_init(ngx_log_t *log)
 {
-    int  change_size, event_size;
+    ngx_kqueue_conf_t  *kcf;
 
-    nevents = KQUEUE_NEVENTS;
+    kcf = ngx_event_get_conf(ngx_kqueue_module_ctx);
+
+ngx_log_debug(log, "CH: %d" _ kcf->changes);
+ngx_log_debug(log, "EV: %d" _ kcf->events);
+
+    max_changes = kcf->changes;
+    nevents = kcf->events;
     nchanges = 0;
-    change_size = sizeof(struct kevent) * KQUEUE_NCHANGES;
-    event_size = sizeof(struct kevent) * KQUEUE_NEVENTS;
 
-    kq = kqueue();
+    ngx_kqueue = kqueue();
 
-    if (kq == -1) {
+    if (ngx_kqueue == -1) {
         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "kqueue() failed");
         return NGX_ERROR;
     }
 
-    ngx_test_null(change_list, ngx_alloc(change_size, log), NGX_ERROR);
-    ngx_test_null(event_list, ngx_alloc(event_size, log), NGX_ERROR);
+    ngx_test_null(change_list,
+                  ngx_alloc(kcf->changes * sizeof(struct kevent), log),
+                  NGX_ERROR);
+    ngx_test_null(event_list,
+                  ngx_alloc(kcf->events * sizeof(struct kevent), log),
+                  NGX_ERROR);
 
-    timer_queue = ngx_event_init_timer(log);
-    if (timer_queue == NULL) {
+    if (ngx_event_timer_init(log) == NGX_ERROR) {
         return NGX_ERROR;
     }
 
-    ngx_event_actions.add = ngx_kqueue_add_event;
-    ngx_event_actions.del = ngx_kqueue_del_event;
-    ngx_event_actions.timer = ngx_event_add_timer;
-    ngx_event_actions.process = ngx_kqueue_process_events;
-
-#if (HAVE_AIO_EVENT)
-
-    ngx_event_flags = NGX_HAVE_AIO_EVENT;
-
-#else
+    ngx_event_actions = ngx_kqueue_module_ctx.actions;
 
     ngx_event_flags = NGX_HAVE_LEVEL_EVENT
                      |NGX_HAVE_ONESHOT_EVENT
-
 #if (HAVE_CLEAR_EVENT)
                      |NGX_HAVE_CLEAR_EVENT
 #else
                      |NGX_USE_LEVEL_EVENT
 #endif
-
 #if (HAVE_LOWAT_EVENT)
                      |NGX_HAVE_LOWAT_EVENT
 #endif
-
                      |NGX_HAVE_KQUEUE_EVENT;
 
-    ngx_write_chain_proc = ngx_freebsd_write_chain;
-
-#endif
-
     return NGX_OK;
 }
 
 
-void ngx_kqueue_done(ngx_log_t *log)
+static void ngx_kqueue_done(ngx_log_t *log)
 {
-    if (close(kq) == -1) {
+    if (close(ngx_kqueue) == -1) {
         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "kqueue close() failed");
     }
+
+    ngx_event_timer_done(log);
+
+    ngx_free(change_list);
+    ngx_free(event_list);
 }
 
 
-int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags)
+static int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags)
 {
+    ngx_connection_t  *c;
+
     ev->active = 1;
     ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0;
 
-    /* The event addition or change should be always passed to a kernel
-       because there can be case when event was passed to a kernel then
-       added again to the change_list and then deleted from the change_list
-       by ngx_kqueue_del_event() so the first event still remains in a kernel */
-
-#if 0
-
     if (nchanges > 0
         && ev->index < nchanges
-        && change_list[ev->index].udata == ev)
+        && (void *) ((uintptr_t) change_list[ev->index].udata & ~1) == ev)
     {
-#if (NGX_DEBUG_EVENT)
-        ngx_connection_t *c = (ngx_connection_t *) ev->data;
-        ngx_log_debug(ev->log, "kqueue add event: %d: ft:%d" _ c->fd _ event);
-#endif
+        c = ev->data;
+        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
+                      "previous event were not passed in kernel", c->fd);
 
-        /* if the event is still not passed to a kernel we change it */
-
-        change_list[ev->index].filter = event;
-        change_list[ev->index].flags = flags;
-
-        return NGX_OK;
+        return NGX_ERROR;
     }
 
-#endif
-
     return ngx_kqueue_set_event(ev, event, EV_ADD | flags);
 }
 
 
-int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
+static int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
 {
     ngx_event_t  *e;
 
@@ -181,7 +176,8 @@
     {
 #if (NGX_DEBUG_EVENT)
         ngx_connection_t *c = (ngx_connection_t *) ev->data;
-        ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ c->fd _ event);
+        ngx_log_debug(ev->log, "kqueue event deleted: %d: ft:%d" _
+                      c->fd _ event);
 #endif
 
         /* if the event is still not passed to a kernel we will not pass it */
@@ -207,26 +203,26 @@
 }
 
 
-int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags)
+static int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags)
 {
-    struct timespec    ts;
-    ngx_connection_t  *c;
+    struct timespec     ts;
+    ngx_connection_t   *c;
 
-    c = (ngx_connection_t *) ev->data;
+    c = ev->data;
 
 #if (NGX_DEBUG_EVENT)
     ngx_log_debug(ev->log, "kqueue set event: %d: ft:%d f:%08x" _
                   c->fd _ filter _ flags);
 #endif
 
-    if (nchanges >= KQUEUE_NCHANGES) {
+    if (nchanges >= max_changes) {
         ngx_log_error(NGX_LOG_WARN, ev->log, 0,
                       "kqueue change list is filled up");
 
         ts.tv_sec = 0;
         ts.tv_nsec = 0;
 
-        if (kevent(kq, change_list, nchanges, NULL, 0, &ts) == -1) {
+        if (kevent(ngx_kqueue, change_list, nchanges, NULL, 0, &ts) == -1) {
             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent failed");
             return NGX_ERROR;
         }
@@ -265,7 +261,7 @@
 }
 
 
-int ngx_kqueue_process_events(ngx_log_t *log)
+static int ngx_kqueue_process_events(ngx_log_t *log)
 {
     int              events, instance, i;
     ngx_msec_t       timer, delta;
@@ -292,7 +288,7 @@
     ngx_log_debug(log, "kevent timer: %d" _ timer);
 #endif
 
-    events = kevent(kq, change_list, nchanges, event_list, nevents, tp);
+    events = kevent(ngx_kqueue, change_list, nchanges, event_list, nevents, tp);
 
     if (events == -1) {
         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "kevent failed");
@@ -305,8 +301,8 @@
         gettimeofday(&tv, NULL);
         delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
 
-        /* Expired timers must be deleted before the events processing
-           because the new timers can be added during the processing */
+        /* The expired timers must be handled before a processing of the events
+           because the new timers can be added during a processing */
 
         ngx_event_expire_timers(delta);
 
@@ -370,8 +366,9 @@
                 ev->error = event_list[i].fflags;
             }
 
-            if (ev->oneshot) {
+            if (ev->oneshot && ev->timer_set) {
                 ngx_del_timer(ev);
+                ev->timer_set = 0;
             }
 
             /* fall through */
@@ -392,3 +389,28 @@
 
     return NGX_OK;
 }
+
+
+static void *ngx_kqueue_create_conf(ngx_pool_t *pool)
+{
+    ngx_kqueue_conf_t  *kcf;
+
+    ngx_test_null(kcf, ngx_palloc(pool, sizeof(ngx_kqueue_conf_t)),
+                  NGX_CONF_ERROR);
+
+    kcf->changes = NGX_CONF_UNSET;
+    kcf->events = NGX_CONF_UNSET;
+
+    return kcf;
+}
+
+
+static char *ngx_kqueue_init_conf(ngx_pool_t *pool, void *conf)
+{
+    ngx_kqueue_conf_t *kcf = conf;
+
+    ngx_conf_init_value(kcf->changes, 512);
+    ngx_conf_init_value(kcf->events, 512);
+
+    return NGX_CONF_OK;
+}
diff --git a/src/event/modules/ngx_kqueue_module.h b/src/event/modules/ngx_kqueue_module.h
index 568476e..4f41ae7 100644
--- a/src/event/modules/ngx_kqueue_module.h
+++ b/src/event/modules/ngx_kqueue_module.h
@@ -2,22 +2,13 @@
 #define _NGX_KQUEUE_MODULE_H_INCLUDED_
 
 
-#include <ngx_types.h>
-#include <ngx_log.h>
-#include <ngx_event.h>
-
-int ngx_kqueue_init(int max_connections, ngx_log_t *log);
-int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags);
-int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags);
-int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags);
-void ngx_kqueue_add_timer(ngx_event_t *ev, ngx_msec_t timer);
-int ngx_kqueue_process_events(ngx_log_t *log);
+typedef struct {
+    int   changes;
+    int   events;
+} ngx_kqueue_conf_t;
 
 
-#if 1
-extern int              kq;
-#endif
-
+extern int  ngx_kqueue;
 
 
 #endif /* _NGX_KQUEUE_MODULE_H_INCLUDED_ */
diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c
index f0f39dd..c58c898 100644
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -242,7 +242,10 @@
         ev->ready = 1;
 
         if (ev->oneshot) {
-            ngx_del_timer(ev);
+            if (ev->timer_set) {
+                ngx_del_timer(ev);
+                ev->timer_set = 0;
+            }
 
             if (ev->write) {
                 ngx_poll_del_event(ev, NGX_WRITE_EVENT, 0);
diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c
index 74c790e..bb3c89d 100644
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -1,16 +1,24 @@
 
+/*
+ * Copyright (C) 2002-2003 Igor Sysoev, http://sysoev.ru
+ */
+
+
 #include <ngx_config.h>
 #include <ngx_core.h>
-#include <ngx_types.h>
-#include <ngx_log.h>
-#include <ngx_time.h>
 #include <ngx_connection.h>
 #include <ngx_event.h>
-#include <ngx_event_timer.h>
-#include <ngx_select_module.h>
 
 
-/* should be per-thread */
+static int ngx_select_init(ngx_log_t *log);
+static void ngx_select_done(ngx_log_t *log);
+static int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags);
+static int ngx_select_del_event(ngx_event_t *ev, int event, u_int flags);
+static int ngx_select_process_events(ngx_log_t *log);
+
+static char *ngx_select_init_conf(ngx_pool_t *pool, void *conf);
+
+
 static fd_set         master_read_fd_set;
 static fd_set         master_write_fd_set;
 static fd_set         work_read_fd_set;
@@ -27,45 +35,67 @@
 
 static ngx_event_t  **event_index;
 static ngx_event_t  **ready_index;
-static ngx_event_t   *timer_queue;
-/* */
 
-int ngx_select_init(int max_connections, ngx_log_t *log)
-{
-    if (max_connections > FD_SETSIZE) {
-        ngx_log_error(NGX_LOG_EMERG, log, 0,
-#if (WIN32)
-                      "maximum number of descriptors "
-                      "supported by select() is %d", FD_SETSIZE);
-#else
-                      "maximum descriptor number"
-                      "supported by select() is %d", FD_SETSIZE - 1);
-#endif
-        exit(1);
+
+static ngx_str_t    select_name = ngx_string("select");
+
+ngx_event_module_t  ngx_select_module_ctx = {
+    NGX_EVENT_MODULE,
+    &select_name,
+    NULL,                                  /* create configuration */
+    ngx_select_init_conf,                  /* init configuration */
+
+    {
+        ngx_select_add_event,              /* add an event */
+        ngx_select_del_event,              /* delete an event */
+        ngx_select_add_event,              /* enable an event */
+        ngx_select_del_event,              /* disable an event */
+        NULL,                              /* add an connection */
+        NULL,                              /* delete an connection */
+        ngx_select_process_events,         /* process the events */
+        ngx_select_init,                   /* init the events */
+        ngx_select_done                    /* done the events */
     }
 
+};
+
+ngx_module_t  ngx_select_module = {
+    &ngx_select_module_ctx,                /* module context */
+    0,                                     /* module index */
+    NULL,                                  /* module directives */
+    NGX_EVENT_MODULE_TYPE,                 /* module type */
+    NULL                                   /* init module */
+};
+
+
+static int ngx_select_init(ngx_log_t *log)
+{
+    ngx_event_conf_t  *ecf;
+
+    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+
     FD_ZERO(&master_read_fd_set);
     FD_ZERO(&master_write_fd_set);
 
     ngx_test_null(event_index,
-                  ngx_alloc(sizeof(ngx_event_t *) * 2 * max_connections, log),
+                  ngx_alloc(sizeof(ngx_event_t *) * 2 * ecf->connections, log),
                   NGX_ERROR);
 
     ngx_test_null(ready_index,
-                  ngx_alloc(sizeof(ngx_event_t *) * 2 * max_connections, log),
+                  ngx_alloc(sizeof(ngx_event_t *) * 2 * ecf->connections, log),
                   NGX_ERROR);
 
     nevents = 0;
 
-    timer_queue = ngx_event_init_timer(log);
-    if (timer_queue == NULL) {
+    if (ngx_event_timer_init(log) == NGX_ERROR) {
         return NGX_ERROR;
     }
 
-    ngx_event_actions.add = ngx_select_add_event;
-    ngx_event_actions.del = ngx_select_del_event;
-    ngx_event_actions.timer = ngx_event_add_timer;
-    ngx_event_actions.process = ngx_select_process_events;
+    ngx_event_actions = ngx_select_module_ctx.actions;
+
+    ngx_event_flags = NGX_HAVE_LEVEL_EVENT
+                      |NGX_HAVE_ONESHOT_EVENT
+                      |NGX_USE_LEVEL_EVENT;
 
 #if (WIN32)
     max_read = max_write = 0;
@@ -76,11 +106,19 @@
     return NGX_OK;
 }
 
-int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags)
+
+static void ngx_select_done(ngx_log_t *log)
+{
+    ngx_free(event_index);
+    ngx_free(ready_index);
+}
+
+
+static int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags)
 {
     ngx_connection_t  *c;
 
-    c = (ngx_connection_t *) ev->data;
+    c = ev->data;
 
 #if (NGX_DEBUG_EVENT)
     ngx_log_debug(ev->log, "select fd:%d event:%d" _ c->fd _ event);
@@ -132,10 +170,12 @@
     return NGX_OK;
 }
 
-int ngx_select_del_event(ngx_event_t *ev, int event, u_int flags)
+
+static int ngx_select_del_event(ngx_event_t *ev, int event, u_int flags)
 {
-    ngx_connection_t *c;
-    c = (ngx_connection_t *) ev->data;
+    ngx_connection_t  *c;
+
+    c = ev->data;
 
     if (ev->index == NGX_INVALID_INDEX)
         return NGX_OK;
@@ -175,7 +215,8 @@
     return NGX_OK;
 }
 
-int ngx_select_process_events(ngx_log_t *log)
+
+static int ngx_select_process_events(ngx_log_t *log)
 {
     int                ready, found;
     u_int              i, nready;
@@ -298,7 +339,10 @@
         ev->ready = 1;
 
         if (ev->oneshot) {
-            ngx_del_timer(ev);
+            if (ev->timer_set) {
+                ngx_del_timer(ev);
+                ev->timer_set = 0;
+            }
 
             if (ev->write)
                 ngx_select_del_event(ev, NGX_WRITE_EVENT, 0);
@@ -315,3 +359,18 @@
 
     return NGX_OK;
 }
+
+
+static char *ngx_select_init_conf(ngx_pool_t *pool, void *conf)
+{
+    ngx_event_conf_t  *ecf;
+
+    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+
+    if (ecf->connections > FD_SETSIZE) {
+        return "maximum number of connections "
+               "supported by select() is " ngx_value(FD_SETSIZE);
+    }
+
+    return NGX_CONF_OK;
+}
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index a3b12d0..ed22db5 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -11,7 +11,7 @@
 #include <ngx_event.h>
 #include <ngx_conf_file.h>
 
-#include <ngx_select_module.h>
+extern ngx_event_module_t ngx_select_module_ctx;
 
 #if (HAVE_POLL)
 #include <ngx_poll_module.h>
@@ -22,6 +22,7 @@
 #endif
 
 #if (HAVE_KQUEUE)
+extern ngx_event_module_t ngx_kqueue_module_ctx;
 #include <ngx_kqueue_module.h>
 #endif
 
@@ -36,46 +37,26 @@
 
 
 static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
+static char *ngx_event_set_type(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
+static void *ngx_event_create_conf(ngx_pool_t *pool);
+static char *ngx_event_init_conf(ngx_pool_t *pool, void *conf);
 
 
+int                  ngx_event_flags;
+ngx_event_actions_t  ngx_event_actions;
+
 ngx_connection_t    *ngx_connections;
 ngx_event_t         *ngx_read_events, *ngx_write_events;
 
-#if !(USE_KQUEUE)
 
-ngx_event_type_e     ngx_event_type;
-
-int                  ngx_event_flags;
-
-ngx_event_actions_t  ngx_event_actions;
-
-/* ngx_event_type_e order */
-static int (*ngx_event_init[]) (int max_connections, ngx_log_t *log) = {
-    ngx_select_init,
-#if (HAVE_POLL)
-    ngx_poll_init,
-#endif
-#if (HAVE_DEVPOLL)
-    ngx_devpoll_init,
-#endif
-#if (HAVE_KQUEUE)
-    ngx_kqueue_init,
-#endif
-#if (HAVE_AIO)
-    ngx_aio_init,
-#endif
-#if (HAVE_IOCP)
-    ngx_iocp_init
-#endif
-};
-
-#endif /* USE_KQUEUE */
+static int  ngx_event_max_module;
 
 
 static int  ngx_event_connections;
 
 
 static ngx_str_t  events_name = ngx_string("events");
+static ngx_str_t  event_name = ngx_string("event");
 
 static ngx_command_t  ngx_events_commands[] = {
 
@@ -106,67 +87,87 @@
      NGX_EVENT_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_num_slot,
      0,
-     addressof(ngx_event_connections),
+     offsetof(ngx_event_conf_t, connections),
      NULL},
 
-#if 0
     {ngx_string("type"),
      NGX_EVENT_CONF|NGX_CONF_TAKE1,
      ngx_event_set_type,
      0,
      0,
      NULL},
-#endif
+
+    {ngx_string("timer_queues"),
+     NGX_EVENT_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_num_slot,
+     0,
+     offsetof(ngx_event_conf_t, timer_queues),
+     NULL},
 
     {ngx_string(""), 0, NULL, 0, 0, NULL}
 };
 
 
+ngx_event_module_t  ngx_event_module_ctx = {
+    NGX_EVENT_MODULE,
+    &event_name,
+    ngx_event_create_conf,                 /* create configuration */
+    ngx_event_init_conf,                   /* init configuration */
+
+    { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+
 ngx_module_t  ngx_event_module = {
-    NULL,                                  /* module context */
+    &ngx_event_module_ctx,                 /* module context */
     0,                                     /* module index */
-    ngx_events_commands,                   /* module directives */
+    ngx_event_commands,                    /* module directives */
     NGX_EVENT_MODULE_TYPE,                 /* module type */
     NULL                                   /* init module */
 };
 
 
 
-void ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log)
+int ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log)
 {
-    int  i, fd;
+    int  m, i, fd;
 
     ngx_listen_t      *s;
     ngx_event_t       *ev;
     ngx_connection_t  *c;
+    ngx_event_conf_t  *ecf;
+    ngx_event_module_t  *module;
 
-    /* STUB */
-    int max_connections = 512;
+    ecf = ngx_event_get_conf(ngx_event_module_ctx);
 
-#if 0
-    ngx_event_type = NGX_POLL_EVENT_N;
-#endif
-#if 1
-    ngx_event_type = NGX_KQUEUE_EVENT_N;
-#endif
-#if 0
-    ngx_event_type = NGX_DEVPOLL_EVENT_N;
-#endif
-#if 0
-    ngx_event_type = NGX_AIO_EVENT_N;
-#endif
-#if 0
-    ngx_event_type = NGX_IOCP_EVENT_N;
-#endif
+ngx_log_debug(log, "CONN: %d" _ ecf->connections);
+ngx_log_debug(log, "TYPE: %d" _ ecf->type);
 
-    if (ngx_init_events(max_connections, log) == NGX_ERROR) {
-        exit(1);
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+            continue;
+        }
+
+        module = ngx_modules[m]->ctx;
+        if (module->index == ecf->type) {
+            if (module->actions.init(log) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+            break;
+        }
     }
 
-    ngx_connections = ngx_alloc(sizeof(ngx_connection_t)
-                                                       * max_connections, log);
-    ngx_read_events = ngx_alloc(sizeof(ngx_event_t) * max_connections, log);
-    ngx_write_events = ngx_alloc(sizeof(ngx_event_t) * max_connections, log);
+    ngx_test_null(ngx_connections,
+                  ngx_alloc(sizeof(ngx_connection_t) * ecf->connections, log),
+                  NGX_ERROR);
+
+    ngx_test_null(ngx_read_events,
+                  ngx_alloc(sizeof(ngx_event_t) * ecf->connections, log),
+                  NGX_ERROR);
+
+    ngx_test_null(ngx_write_events,
+                  ngx_alloc(sizeof(ngx_event_t) * ecf->connections, log),
+                  NGX_ERROR);
 
     /* for each listening socket */
     s = (ngx_listen_t *) ls->elts;
@@ -196,7 +197,9 @@
         c->pool_size = s[i].pool_size;
 
         ngx_test_null(ev->log,
-                      ngx_palloc(pool, sizeof(ngx_log_t)), /* void */ ; );
+                      ngx_palloc(pool, sizeof(ngx_log_t)),
+                      NGX_ERROR);
+
         ngx_memcpy(ev->log, c->log, sizeof(ngx_log_t));
         c->read = ev;
         ev->data = c;
@@ -235,6 +238,8 @@
 
 #endif
     }
+
+    return NGX_OK;
 }
 
 
@@ -248,35 +253,50 @@
 }
 
 
-static char *ngx_events_init(ngx_pool_t *pool)
-{
-    ngx_event_connections = -1;
-    ngx_event_type = -1;
-
-    return NGX_CONF_OK;
-}
-
-
-static char *ngx_events_postconf(ngx_pool_t *pool)
-{
-    if (ngx_event_connections == -1) {
-        ngx_event_connections = 512;
-    }
-
-    return NGX_CONF_OK;
-}
-
-
 static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
 {
-    char        *rv;
-    ngx_conf_t   pcf;
+    int                    m;
+    char                  *rv;
+    void               ***ctx;
+    ngx_conf_t            pcf;
+    ngx_event_conf_t     *ecf;
+    ngx_event_module_t   *module;
 
-#if 0
-    *(ngx_events_conf_ctx_t **) conf = ctx;
-#endif
+    /* count the number of the event modules and set up their indices */
+
+    ngx_event_max_module = 0;
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+            continue;
+        }
+
+        module = ngx_modules[m]->ctx;
+        module->index = ngx_event_max_module++;
+    }
+
+    ngx_test_null(ctx, ngx_pcalloc(cf->pool, sizeof(void *)), NGX_CONF_ERROR);
+
+    ngx_test_null(*ctx,
+                  ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *)),
+                  NGX_CONF_ERROR);
+
+    *(void **) conf = ctx;
+
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+            continue;
+        }
+
+        module = ngx_modules[m]->ctx;
+
+        if (module->create_conf) {
+            ngx_test_null((*ctx)[module->index], module->create_conf(cf->pool),
+                          NGX_CONF_ERROR);
+        }
+    }
 
     pcf = *cf;
+    cf->ctx = ctx;
     cf->module_type = NGX_EVENT_MODULE_TYPE;
     cf->cmd_type = NGX_EVENT_CONF;
     rv = ngx_conf_parse(cf, NULL);
@@ -285,5 +305,90 @@
     if (rv != NGX_CONF_OK)
         return rv;
 
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+            continue;
+        }
+
+        module = ngx_modules[m]->ctx;
+
+        if (module->init_conf) {
+            rv = module->init_conf(cf->pool, (*ctx)[module->index]);
+            if (rv != NGX_CONF_OK) {
+                return rv;
+            }
+        }
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *ngx_event_set_type(ngx_conf_t *cf, ngx_command_t *cmd, char *conf)
+{
+    ngx_event_conf_t *ecf = (ngx_event_conf_t *) conf;
+
+    int                   m;
+    ngx_str_t            *args;
+    ngx_event_module_t   *module;
+
+    if (ecf->type != NGX_CONF_UNSET) {
+        return "duplicate event type" ;
+    }
+
+    args = cf->args->elts;
+
+    for (m = 0; ngx_modules[m]; m++) {
+        if (ngx_modules[m]->type != NGX_EVENT_MODULE_TYPE) {
+            continue;
+        }
+
+        module = ngx_modules[m]->ctx;
+        if (module->name->len == args[1].len) {
+            if (ngx_strcmp(module->name->data, args[1].data) == 0) {
+                ecf->type = module->index;
+                return NGX_CONF_OK;
+            }
+        }
+    }
+
+    return "invalid event type";
+}
+
+
+static void *ngx_event_create_conf(ngx_pool_t *pool)
+{
+    ngx_event_conf_t  *ecf;
+
+    ngx_test_null(ecf, ngx_palloc(pool, sizeof(ngx_event_conf_t)),
+                  NGX_CONF_ERROR);
+
+    ecf->connections = NGX_CONF_UNSET;
+    ecf->type = NGX_CONF_UNSET;
+
+    return ecf;
+}
+
+
+static char *ngx_event_init_conf(ngx_pool_t *pool, void *conf)
+{
+    ngx_event_conf_t *ecf = conf;
+
+#if (HAVE_KQUEUE)
+
+    ngx_conf_init_value(ecf->connections, 1024);
+    ngx_conf_init_value(ecf->type, ngx_kqueue_module_ctx.index);
+
+#else /* HAVE_SELECT */
+
+    ngx_conf_init_value(ecf->connections,
+                        FD_SETSIZE < 1024 ? FD_SETSIZE : 1024);
+
+    ngx_conf_init_value(ecf->type, ngx_select_module_ctx.index);
+
+#endif
+
+    ngx_conf_init_value(ecf->timer_queues, 10);
+
     return NGX_CONF_OK;
 }
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index c976e17..3b189d6 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -9,12 +9,16 @@
 #include <ngx_log.h>
 #include <ngx_alloc.h>
 #include <ngx_array.h>
+#include <ngx_conf_file.h>
+
+
 
 /* STUB */
 #define NGX_LOWAT   10000
 
 #define NGX_INVALID_INDEX  0x80000000
 
+
 typedef struct ngx_event_s       ngx_event_t;
 
 #if (HAVE_IOCP)
@@ -141,15 +145,21 @@
     NGX_DUMMY_EVENT_N    /* avoid comma at end of enumerator list */
 } ngx_event_type_e ;
 
+
+
 typedef struct {
-    int  (*add)(ngx_event_t *ev, int event, u_int flags);
-    int  (*del)(ngx_event_t *ev, int event, u_int flags);
-    void (*timer)(ngx_event_t *ev, ngx_msec_t timer);
-    int  (*process)(ngx_log_t *log);
-    int  (*read)(ngx_event_t *ev, char *buf, size_t size);
-/*
-    int  (*write)(ngx_event_t *ev, char *buf, size_t size);
-*/
+    int   (*add)(ngx_event_t *ev, int event, u_int flags);
+    int   (*del)(ngx_event_t *ev, int event, u_int flags);
+
+    int   (*enable)(ngx_event_t *ev, int event, u_int flags);
+    int   (*disable)(ngx_event_t *ev, int event, u_int flags);
+
+    int   (*add_conn)(ngx_connection_t *c);
+    int   (*del_conn)(ngx_connection_t *c);
+
+    int   (*process)(ngx_log_t *log);
+    int   (*init)(ngx_log_t *log);
+    void  (*done)(ngx_log_t *log);
 } ngx_event_actions_t;
 
 
@@ -273,7 +283,8 @@
 #elif (HAVE_AIO_EVENT)
 #define ngx_event_recv       ngx_event_aio_read
 #else
-#define ngx_event_recv       ngx_event_recv_core
+#define ngx_event_recv       ngx_io.recv
+#define ngx_write_chain      ngx_io.send_chain
 #endif
 
 #endif
@@ -301,6 +312,33 @@
 #define NGX_EVENT_MODULE_TYPE 0x544E5645  /* "EVNT" */
 
 #define NGX_EVENT_CONF        0x00200000
+#define NGX_EVENT_MODULE      0
+
+
+typedef struct {
+    int   connections;
+    int   type;
+    int   timer_queues;
+} ngx_event_conf_t;
+
+
+typedef struct {
+    int                     index;
+    ngx_str_t              *name;
+
+    void                 *(*create_conf)(ngx_pool_t *p);
+    char                 *(*init_conf)(ngx_pool_t *p, void *conf);
+
+    ngx_event_actions_t     actions;
+} ngx_event_module_t;
+
+
+extern ngx_module_t        ngx_events_module;
+extern ngx_event_module_t  ngx_event_module_ctx;
+
+
+#define ngx_event_get_conf(module)                                           \
+                          (*(ngx_get_conf(ngx_events_module))) [module.index];
 
 
 
@@ -311,8 +349,11 @@
 int ngx_event_close_connection(ngx_event_t *ev);
 
 
-void ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log);
+int  ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log);
 void ngx_worker(ngx_log_t *log);
 
 
+#include <ngx_event_timer.h>
+
+
 #endif /* _NGX_EVENT_H_INCLUDED_ */
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index 26bc2e3..720b3a5 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -175,10 +175,7 @@
 
 #elif (HAVE_KQUEUE)
 
-/*
-        if (ngx_event_type == NGX_HAVE_AIO_EVENT  or NGX_HAVE_KQUEUE_EVENT) {
-*/
-        if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT) {
+        if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
             ev->available--;
         }
 
diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c
index b5dfdf9..03e29d9 100644
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -9,33 +9,38 @@
 
 #include <ngx_event_timer.h>
 
-/* STUB */
-#define NGX_TIMER_QUEUE_NUM  5
 
-/* should be per-thread */
 static ngx_event_t  *ngx_timer_queue;
 static int           ngx_timer_cur_queue;
-/* */
 static int           ngx_timer_queue_num;
 
 
-ngx_event_t *ngx_event_init_timer(ngx_log_t *log)
+int ngx_event_timer_init(ngx_log_t *log)
 {
-    int  i;
+    int                i;
+    ngx_event_conf_t  *ecf;
 
-    ngx_timer_queue_num = NGX_TIMER_QUEUE_NUM;
+    ecf = ngx_event_get_conf(ngx_event_module_ctx);
+
+    ngx_timer_queue_num = ecf->timer_queues;
     ngx_timer_cur_queue = 0;
 
     ngx_test_null(ngx_timer_queue,
                   ngx_alloc(ngx_timer_queue_num * sizeof(ngx_event_t), log),
-                  NULL);
+                  NGX_ERROR);
 
     for (i = 0; i < ngx_timer_queue_num; i++) {
         ngx_timer_queue[i].timer_prev = &ngx_timer_queue[i];
         ngx_timer_queue[i].timer_next = &ngx_timer_queue[i];
     }
 
-    return ngx_timer_queue;
+    return NGX_OK;;
+}
+
+
+void ngx_event_timer_done(ngx_log_t *log)
+{
+    ngx_free(ngx_timer_queue);
 }
 
 
@@ -126,6 +131,8 @@
             delta -= ev->timer_delta;
 
             ngx_del_timer(ev);
+            ev->timer_set = 0;
+
             if (ev->delayed) {
                 ev->delayed = 0;
                 if (ev->ready == 0) {
diff --git a/src/event/ngx_event_timer.h b/src/event/ngx_event_timer.h
index f5f78ae..cb024a3 100644
--- a/src/event/ngx_event_timer.h
+++ b/src/event/ngx_event_timer.h
@@ -9,9 +9,10 @@
 #include <ngx_event.h>
 
 
-ngx_event_t *ngx_event_init_timer(ngx_log_t *log);
+int  ngx_event_timer_init(ngx_log_t *log);
+void ngx_event_timer_done(ngx_log_t *log);
 void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer);
-int ngx_event_find_timer(void);
+int  ngx_event_find_timer(void);
 void ngx_event_expire_timers(ngx_msec_t timer);