changeset 381:02a511569afb

nginx-0.0.7-2004-07-07-19:01:00 import
author Igor Sysoev <igor@sysoev.ru>
date Wed, 07 Jul 2004 15:01:00 +0000
parents 5ce6561246a5
children 449c4885dcd1
files src/core/ngx_cycle.c src/core/ngx_cycle.h src/core/ngx_regex.c src/event/modules/ngx_devpoll_module.c src/event/modules/ngx_epoll_module.c src/event/modules/ngx_iocp_module.c src/event/modules/ngx_kqueue_module.c src/event/modules/ngx_poll_module.c src/event/modules/ngx_rtsig_module.c src/event/modules/ngx_select_module.c src/event/ngx_event.h src/event/ngx_event_accept.c src/event/ngx_event_connect.c src/event/ngx_event_posted.c src/event/ngx_event_timer.c src/http/ngx_http_core_module.c src/os/unix/ngx_channel.c src/os/unix/ngx_errno.h src/os/unix/ngx_freebsd_rfork_thread.c src/os/unix/ngx_freebsd_rfork_thread.h src/os/unix/ngx_process_cycle.c src/os/unix/ngx_thread.h
diffstat 22 files changed, 429 insertions(+), 224 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -15,6 +15,10 @@ static ngx_event_t     ngx_cleaner_event
 
 ngx_uint_t             ngx_test_config;
 
+#if (NGX_THREADS)
+ngx_tls_key_t          ngx_core_tls_key;
+#endif
+
 
 /* STUB NAME */
 static ngx_connection_t  dumb;
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -49,6 +49,11 @@ typedef struct {
 } ngx_core_conf_t;
 
 
+typedef struct {
+     ngx_pool_t  *pool;   /* pcre's malloc() pool */
+} ngx_core_tls_t;
+
+
 ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle);
 ngx_int_t ngx_create_pidfile(ngx_cycle_t *cycle, ngx_cycle_t *old_cycle);
 void ngx_delete_pidfile(ngx_cycle_t *cycle);
@@ -60,6 +65,9 @@ extern volatile ngx_cycle_t  *ngx_cycle;
 extern ngx_array_t            ngx_old_cycles;
 extern ngx_module_t           ngx_core_module;
 extern ngx_uint_t             ngx_test_config;
+#if (NGX_THREADS)
+extern ngx_tls_key_t          ngx_core_tls_key;
+#endif
 
 
 #endif /* _NGX_CYCLE_H_INCLUDED_ */
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -7,7 +7,6 @@ static void *ngx_regex_malloc(size_t siz
 static void ngx_regex_free(void *p);
 
 
-/* THREADS: this pool should be private for each thread */
 static ngx_pool_t  *ngx_pcre_pool;
 
 
@@ -21,12 +20,29 @@ void ngx_regex_init()
 ngx_regex_t *ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options,
                                ngx_pool_t *pool, ngx_str_t *err)
 {
-    int           erroff;
-    const char   *errstr;
-    ngx_regex_t  *re;
+    int              erroff;
+    const char      *errstr;
+    ngx_regex_t     *re;
+#if (NGX_THREADS)
+    ngx_core_tls_t  *tls;
+
+#if (NGX_SUPPRESS_WARN)
+    tls = NULL;
+#endif
+
+    if (ngx_threaded) {
+        tls = ngx_thread_get_tls(ngx_core_tls_key);
+        tls->pool = pool;
+    } else {
+        ngx_pcre_pool = pool;
+    }
+
+#else
 
     ngx_pcre_pool = pool;
 
+#endif
+
     re = pcre_compile((const char *) pattern->data, (int) options,
                       &errstr, &erroff, NULL);
 
@@ -44,7 +60,15 @@ ngx_regex_t *ngx_regex_compile(ngx_str_t
 
     /* ensure that there is no current pool */
 
+#if (NGX_THREADS)
+    if (ngx_threaded) {
+        tls->pool = NULL;
+    } else {
+        ngx_pcre_pool = NULL;
+    }
+#else
     ngx_pcre_pool = NULL;
+#endif
 
     return re;
 }
@@ -68,8 +92,22 @@ ngx_int_t ngx_regex_exec(ngx_regex_t *re
 
 static void *ngx_regex_malloc(size_t size)
 {
-    if (ngx_pcre_pool) {
-        return ngx_palloc(ngx_pcre_pool, size);
+    ngx_pool_t      *pool;
+#if (NGX_THREADS)
+    ngx_core_tls_t  *tls;
+
+    if (ngx_threaded) {
+        tls = ngx_thread_get_tls(ngx_core_tls_key);
+        pool = tls->pool;
+    } else {
+        pool = ngx_pcre_pool;
+    }
+#else
+    pool = ngx_pcre_pool;
+#endif
+
+    if (pool) {
+        return ngx_palloc(pool, size);
     }
 
     return NULL;
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -322,6 +322,7 @@ int ngx_devpoll_process_events(ngx_cycle
     ngx_msec_t          timer;
     ngx_err_t           err;
     ngx_cycle_t       **old_cycle;
+    ngx_event_t        *rev, *wev;
     ngx_connection_t   *c;
     ngx_epoch_msec_t    delta;
     struct dvpoll       dvp;
@@ -476,16 +477,16 @@ int ngx_devpoll_process_events(ngx_cycle
                           event_list[i].events, event_list[i].revents);
         }
 
-        if ((event_list[i].events & (POLLOUT|POLLERR|POLLHUP))
-            && c->write->active)
-        {
-            c->write->ready = 1;
+        wev = c->write;
+
+        if ((event_list[i].events & (POLLOUT|POLLERR|POLLHUP)) && wev->active) {
+            wev->ready = 1;
 
             if (!ngx_threaded && !ngx_accept_mutex_held) {
-                c->write->event_handler(c->write);
+                wev->event_handler(wev);
 
             } else {
-                ngx_post_event(c->write);
+                ngx_post_event(wev);
             }
         }
 
@@ -495,21 +496,21 @@ int ngx_devpoll_process_events(ngx_cycle
          * if the accept event is the last one.
          */
 
-        if ((event_list[i].events & (POLLIN|POLLERR|POLLHUP))
-            && c->read->active)
-        {
-            c->read->ready = 1;
+        rev = c->read;
+
+        if ((event_list[i].events & (POLLIN|POLLERR|POLLHUP)) && rev->active) {
+            rev->ready = 1;
 
             if (!ngx_threaded && !ngx_accept_mutex_held) {
-                c->read->event_handler(c->read);
+                rev->event_handler(rev);
 
-            } else if (!c->read->accept) {
-                ngx_post_event(c->read);
+            } else if (!rev->accept) {
+                ngx_post_event(rev);
 
             } else if (ngx_accept_disabled <= 0) {
                 ngx_mutex_unlock(ngx_posted_events_mutex);
 
-                c->read->event_handler(c->read);
+                c->read->event_handler(rev);
 
                 if (ngx_accept_disabled > 0) { 
                     ngx_accept_mutex_unlock();
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -75,7 +75,7 @@ static void ngx_epoll_done(ngx_cycle_t *
 static int ngx_epoll_add_event(ngx_event_t *ev, int event, u_int flags);
 static int ngx_epoll_del_event(ngx_event_t *ev, int event, u_int flags);
 static int ngx_epoll_add_connection(ngx_connection_t *c);
-static int ngx_epoll_del_connection(ngx_connection_t *c);
+static int ngx_epoll_del_connection(ngx_connection_t *c, u_int flags);
 static int ngx_epoll_process_events(ngx_cycle_t *cycle);
 
 static void *ngx_epoll_create_conf(ngx_cycle_t *cycle);
@@ -111,8 +111,8 @@ ngx_event_module_t  ngx_epoll_module_ctx
         ngx_epoll_del_event,             /* delete an event */
         ngx_epoll_add_event,             /* enable an event */
         ngx_epoll_del_event,             /* disable an event */
-        NULL,                            /* add an connection */
-        NULL,                            /* delete an connection */
+        ngx_epoll_add_connection,        /* add an connection */
+        ngx_epoll_del_connection,        /* delete an connection */
         NULL,                            /* process the changes */
         ngx_epoll_process_events,        /* process the events */
         ngx_epoll_init,                  /* init the events */
@@ -124,9 +124,9 @@ 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 process */
+    NGX_EVENT_MODULE,                    /* module type */
+    NULL,                                /* init module */
+    NULL                                 /* init process */
 };
 
 
@@ -174,7 +174,7 @@ static int ngx_epoll_init(ngx_cycle_t *c
     ngx_event_flags = NGX_USE_LEVEL_EVENT
 #endif
                       |NGX_HAVE_GREEDY_EVENT
-                      |NGX_HAVE_INSTANCE_EVENT;
+                      |NGX_USE_EPOLL_EVENT;
 
     return NGX_OK;
 }
@@ -306,7 +306,6 @@ static int ngx_epoll_del_event(ngx_event
 }
 
 
-#if 0
 static int ngx_epoll_add_connection(ngx_connection_t *c)
 {
     struct epoll_event  ee;
@@ -330,14 +329,41 @@ static int ngx_epoll_add_connection(ngx_
 }
 
 
-static int ngx_epoll_del_connection(ngx_connection_t *c)
+static int ngx_epoll_del_connection(ngx_connection_t *c, u_int flags)
 {
+    int                  op;
+    struct epoll_event   ee;
+
+    /*
+     * when the file descriptor is closed the epoll automatically deletes
+     * it from its queue so we do not need to delete explicity the event
+     * before the closing the file descriptor
+     */
+
+    if (flags & NGX_CLOSE_EVENT) {
+        c->read->active = 0;
+        c->write->active = 0;
+        return NGX_OK;
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                   "epoll del connection: fd:%d", c->fd);
+
+    op = EPOLL_CTL_DEL;
+    ee.events = 0;
+    ee.data.ptr = NULL;
+
+    if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
+                      "epoll_ctl(%d, %d) failed", op, c->fd);
+        return NGX_ERROR;
+    }
+
     c->read->active = 0;
     c->write->active = 0;
 
     return NGX_OK;
 }
-#endif
 
 
 int ngx_epoll_process_events(ngx_cycle_t *cycle)
@@ -349,6 +375,7 @@ int ngx_epoll_process_events(ngx_cycle_t
     ngx_err_t          err;
     ngx_log_t         *log;
     ngx_msec_t         timer;
+    ngx_event_t       *rev, *wev;
     struct timeval     tv;
     ngx_connection_t  *c;
     ngx_epoch_msec_t   delta;
@@ -356,6 +383,19 @@ int ngx_epoll_process_events(ngx_cycle_t
     for ( ;; ) { 
         timer = ngx_event_find_timer();
 
+#if (NGX_THREADS)
+
+        if (timer == NGX_TIMER_ERROR) {
+            return NGX_ERROR;
+        }
+
+        if (timer == NGX_TIMER_INFINITE || timer > 500) {
+            timer = 500;
+            break;
+        }
+
+#endif
+
         if (timer != 0) {
             break;
         }
@@ -365,6 +405,10 @@ int ngx_epoll_process_events(ngx_cycle_t
 
         ngx_event_expire_timers((ngx_msec_t)
                                     (ngx_elapsed_msec - ngx_old_elapsed_msec));
+
+        if (ngx_posted_events && ngx_threaded) {
+            ngx_wakeup_worker_thread(cycle);
+        }
     }
 
     /* NGX_TIMER_INFINITE == INFTIM */
@@ -438,12 +482,18 @@ int ngx_epoll_process_events(ngx_cycle_t
         return NGX_ERROR;
     }
 
-    if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
-        ngx_accept_mutex_unlock();
-        return NGX_ERROR;
+    if (events > 0) {
+        if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
+            ngx_accept_mutex_unlock();
+            return NGX_ERROR;
+        } 
+
+        lock = 1;
+
+    } else {
+        lock =0;
     }
 
-    lock = 1;
     log = cycle->log;
 
     for (i = 0; i < events; i++) {
@@ -452,15 +502,9 @@ int ngx_epoll_process_events(ngx_cycle_t
         instance = (uintptr_t) c & 1;
         c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
 
-        if (event_list[i].events & EPOLLIN) {
-            c->read->returned_instance = instance;
-        }
+        rev = c->read;
 
-        if (event_list[i].events & EPOLLOUT) {
-            c->write->returned_instance = instance;
-        }
-
-        if (c->read->instance != instance) {
+        if (c->fd == -1 || rev->instance != instance) {
 
             /*
              * the stale event from a file descriptor
@@ -492,16 +536,24 @@ int ngx_epoll_process_events(ngx_cycle_t
                           c->fd, event_list[i].events);
         }
 
+        wev = c->write;
+
         if ((event_list[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP))
-            && c->write->active)
+            && wev->active)
         {
-            c->write->ready = 1;
-
-            if (!ngx_threaded && !ngx_accept_mutex_held) {
-                c->write->event_handler(c->write);
+            if (ngx_threaded) {
+                wev->posted_ready = 1;
+                ngx_post_event(wev);
 
             } else {
-                ngx_post_event(c->write);
+                wev->ready = 1;
+
+                if (!ngx_accept_mutex_held) {
+                    wev->event_handler(wev);
+
+                } else {
+                    ngx_post_event(wev);
+                }
             }
         }
 
@@ -512,21 +564,29 @@ int ngx_epoll_process_events(ngx_cycle_t
          */
 
         if ((event_list[i].events & (EPOLLIN|EPOLLERR|EPOLLHUP))
-            && c->read->active)
+            && rev->active)
         {
-            c->read->ready = 1;
+            if (ngx_threaded && !rev->accept) {
+                rev->posted_ready = 1;
+
+                ngx_post_event(rev);
+
+                continue;
+            }
+
+            rev->ready = 1;
 
             if (!ngx_threaded && !ngx_accept_mutex_held) {
-                c->read->event_handler(c->read);
+                rev->event_handler(rev);
 
-            } else if (!c->read->accept) {
-                ngx_post_event(c->read);
+            } else if (!rev->accept) {
+                ngx_post_event(rev);
 
             } else if (ngx_accept_disabled <= 0) {
 
                 ngx_mutex_unlock(ngx_posted_events_mutex);
 
-                c->read->event_handler(c->read);
+                rev->event_handler(rev);
 
                 if (ngx_accept_disabled > 0) {
                     ngx_accept_mutex_unlock();
@@ -560,8 +620,13 @@ int ngx_epoll_process_events(ngx_cycle_t
         ngx_event_expire_timers((ngx_msec_t) delta);
     }
 
-    if (!ngx_threaded) {
-        ngx_event_process_posted(cycle);
+    if (ngx_posted_events) {
+        if (ngx_threaded) {
+            ngx_wakeup_worker_thread(cycle);
+
+        } else {
+            ngx_event_process_posted(cycle);
+        }
     }
 
     return NGX_OK;
--- a/src/event/modules/ngx_iocp_module.c
+++ b/src/event/modules/ngx_iocp_module.c
@@ -60,6 +60,7 @@ ngx_event_module_t  ngx_iocp_module_ctx 
         NULL,                              /* disable an event */
         NULL,                              /* add an connection */
         ngx_iocp_del_connection,           /* delete an connection */
+        NULL,                              /* process the changes */
         ngx_iocp_process_events,           /* process the events */
         ngx_iocp_init,                     /* init the events */
         ngx_iocp_done                      /* done the events */
@@ -73,7 +74,7 @@ ngx_module_t  ngx_iocp_module = {
     ngx_iocp_commands,                     /* module directives */
     NGX_EVENT_MODULE,                      /* module type */
     NULL,                                  /* init module */
-    NULL                                   /* init child */
+    NULL                                   /* init process */
 };
 
 
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -421,6 +421,7 @@ static ngx_int_t ngx_kqueue_process_even
         timer = ngx_event_find_timer();
 
 #if (NGX_THREADS)
+
         if (timer == NGX_TIMER_ERROR) {
             return NGX_ERROR;
         }
@@ -442,7 +443,9 @@ static ngx_int_t ngx_kqueue_process_even
         ngx_event_expire_timers((ngx_msec_t)
                                     (ngx_elapsed_msec - ngx_old_elapsed_msec));
 
-        /* TODO: if ngx_threaded then wake up the worker thread */
+        if (ngx_posted_events && ngx_threaded) {
+            ngx_wakeup_worker_thread(cycle);
+        }
     }
 
     ngx_old_elapsed_msec = ngx_elapsed_msec;
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -14,6 +14,7 @@ static void ngx_poll_done(ngx_cycle_t *c
 static ngx_int_t ngx_poll_add_event(ngx_event_t *ev, int event, u_int flags);
 static ngx_int_t ngx_poll_del_event(ngx_event_t *ev, int event, u_int flags);
 static ngx_int_t ngx_poll_process_events(ngx_cycle_t *cycle);
+static char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf);
 
 
 static struct pollfd  *event_list;
@@ -31,7 +32,7 @@ static ngx_str_t    poll_name = ngx_stri
 ngx_event_module_t  ngx_poll_module_ctx = {
     &poll_name,
     NULL,                                  /* create configuration */
-    NULL,                                  /* init configuration */
+    ngx_poll_init_conf,                    /* init configuration */
 
     {
         ngx_poll_add_event,                /* add an event */
@@ -577,3 +578,27 @@ static ngx_int_t ngx_poll_process_events
 
     return nready;
 }
+
+
+static char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf)
+{
+    ngx_event_conf_t  *ecf;
+
+    ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
+
+    if (ecf->use != ngx_poll_module.ctx_index) {
+        return NGX_CONF_OK;
+    }
+
+#if (NGX_THREADS)
+
+    ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+                  "poll() is not supported in the threaded mode");
+    return NGX_CONF_ERROR;
+
+#else
+
+    return NGX_CONF_OK;
+
+#endif
+}
--- a/src/event/modules/ngx_rtsig_module.c
+++ b/src/event/modules/ngx_rtsig_module.c
@@ -158,9 +158,7 @@ static ngx_int_t ngx_rtsig_init(ngx_cycl
 
     ngx_event_actions = ngx_rtsig_module_ctx.actions;
 
-    ngx_event_flags = NGX_USE_RTSIG_EVENT
-                      |NGX_HAVE_GREEDY_EVENT
-                      |NGX_HAVE_INSTANCE_EVENT;
+    ngx_event_flags = NGX_USE_RTSIG_EVENT|NGX_HAVE_GREEDY_EVENT;
 
     return NGX_OK;
 }
@@ -275,6 +273,7 @@ ngx_int_t ngx_rtsig_process_events(ngx_c
     ngx_msec_t          timer;
     ngx_err_t           err;
     siginfo_t           si;
+    ngx_event_t        *rev, *wev;
     struct timeval      tv;
     struct timespec     ts, *tp;
     struct sigaction    sa;
@@ -290,6 +289,19 @@ ngx_int_t ngx_rtsig_process_events(ngx_c
         for ( ;; ) {
             timer = ngx_event_find_timer();
 
+#if (NGX_THREADS)
+
+            if (timer == NGX_TIMER_ERROR) {
+                return NGX_ERROR;
+            }
+
+            if (timer == NGX_TIMER_INFINITE || timer > 500) {
+                timer = 500;
+                break;
+            }
+
+#endif
+
             if (timer != 0) {
                 break;
             }
@@ -299,6 +311,10 @@ ngx_int_t ngx_rtsig_process_events(ngx_c
 
             ngx_event_expire_timers((ngx_msec_t)
                                     (ngx_elapsed_msec - ngx_old_elapsed_msec));
+
+            if (ngx_posted_events && ngx_threaded) {
+                ngx_wakeup_worker_thread(cycle);
+            }
         }
 
         expire = 1;
@@ -340,7 +356,7 @@ ngx_int_t ngx_rtsig_process_events(ngx_c
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    "rtsig timer: %d", timer);
 
-    /* Linux sigwaitinfo() is sigtimedwait() with the NULL timeout pointer */
+    /* Linux's sigwaitinfo() is sigtimedwait() with the NULL timeout pointer */
 
     signo = sigtimedwait(&set, &si, tp);
 
@@ -400,14 +416,8 @@ ngx_int_t ngx_rtsig_process_events(ngx_c
 
         instance = signo - rtscf->signo;
 
-        if (si.si_band & POLLIN) {
-            c->read->returned_instance = instance;
-        }
+        rev = c->read;
 
-        if (si.si_band & POLLOUT) {
-            c->write->returned_instance = instance;
-        }
-    
         if (c->read->instance != instance) {
 
             /*
@@ -424,47 +434,62 @@ ngx_int_t ngx_rtsig_process_events(ngx_c
         }
 
         if (si.si_band & (POLLIN|POLLHUP|POLLERR)) {
-            if (c->read->active) {
-                c->read->ready = 1;
-
-                if (!ngx_threaded && !ngx_accept_mutex_held) {
-                    c->read->event_handler(c->read);
+            if (rev->active) {
 
-                } else if (c->read->accept) {
-                    if (ngx_accept_disabled <= 0) {
-                        c->read->event_handler(c->read);
-                    }
-
-                } else {
+                if (ngx_threaded && !rev->accept) {
                     if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
                         ngx_accept_mutex_unlock();
                         return NGX_ERROR;
                     }
 
-                    ngx_post_event(c->read); 
+                    rev->posted_ready = 1;
+                    ngx_post_event(rev);
 
                     ngx_mutex_unlock(ngx_posted_events_mutex);
+
+                } else {
+                    rev->ready = 1;
+
+                    if (!ngx_threaded && !ngx_accept_mutex_held) {
+                        rev->event_handler(rev);
+
+                    } else if (rev->accept) {
+                        if (ngx_accept_disabled <= 0) {
+                            rev->event_handler(rev);
+                        }
+
+                    } else {
+                        ngx_post_event(rev); 
+                    }
                 }
             }
         }
 
-        if (si.si_band & (POLLOUT|POLLHUP|POLLERR)) {
-            if (c->write->active) {
-                c->write->ready = 1;
+        wev = c->write;
 
-                if (!ngx_threaded && !ngx_accept_mutex_held) {
-                    c->write->event_handler(c->write);
+        if (si.si_band & (POLLOUT|POLLHUP|POLLERR)) {
+            if (wev->active) {
 
-                } else {
-
+                if (ngx_threaded) {
                     if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
                         ngx_accept_mutex_unlock();
                         return NGX_ERROR;
                     }
 
-                    ngx_post_event(c->write);
+                    wev->posted_ready = 1;
+                    ngx_post_event(wev);
 
                     ngx_mutex_unlock(ngx_posted_events_mutex);
+
+                } else {
+                    wev->ready = 1;
+
+                    if (!ngx_threaded && !ngx_accept_mutex_held) {
+                        wev->event_handler(wev);
+
+                    } else {
+                        ngx_post_event(wev);
+                    }
                 }
             }
         }
@@ -512,8 +537,13 @@ ngx_int_t ngx_rtsig_process_events(ngx_c
         ngx_event_expire_timers((ngx_msec_t) delta);
     }
 
-    if (!ngx_threaded) {
-        ngx_event_process_posted(cycle);
+    if (ngx_posted_events) {
+        if (ngx_threaded) {
+            ngx_wakeup_worker_thread(cycle);
+
+        } else {
+            ngx_event_process_posted(cycle);
+        }
     }
 
     if (signo == -1) {
@@ -532,6 +562,7 @@ static ngx_int_t ngx_rtsig_process_overf
     size_t             len;
     ngx_int_t          tested, n, i;
     ngx_err_t          err;
+    ngx_event_t       *rev, *wev;
     ngx_connection_t  *c;
     ngx_rtsig_conf_t  *rtscf;
 
@@ -587,60 +618,60 @@ static ngx_int_t ngx_rtsig_process_overf
                               cycle->log, 0,
                               "poll() failed while the overflow recover");
 
-                if (err == NGX_EINTR) {
-                    continue;
+                if (err != NGX_EINTR) {
+                    break;
                 }
             }
-
-            break;
         }
 
         if (ready <= 0) {
             continue;
         }
 
+        if (n) {
+            if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+        }
+
         for (i = 0; i < n; i++) {
             c = &cycle->connections[overflow_list[i].fd];
 
+            rev = c->read;
+
             if (overflow_list[i].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL)) {
                 tested++;
-                c->read->ready = 1;
 
-                if (!ngx_threaded) {
-                    c->read->event_handler(c->read); 
+                if (ngx_threaded) {
+                    rev->posted_ready = 1;
+                    ngx_post_event(rev);
 
                 } else {
-                    if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
-                        return NGX_ERROR;
-                    }
-
-                    ngx_post_event(c->read);
-                    c->read->returned_instance = c->read->instance;
-
-                    ngx_mutex_unlock(ngx_posted_events_mutex);
+                    rev->ready = 1;
+                    rev->event_handler(rev); 
                 }
             }
 
+            wev = c->write;
+
             if (overflow_list[i].revents & (POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
                 tested++;
-                c->write->ready = 1;
-    
-                if (!ngx_threaded) {
-                    c->write->event_handler(c->write);
+
+                if (ngx_threaded) {
+                    wev->posted_ready = 1;
+                    ngx_post_event(wev);
 
                 } else {
-                    if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
-                        return NGX_ERROR;
-                    } 
-
-                    ngx_post_event(c->write);
-                    c->write->returned_instance = c->write->instance;
-
-                    ngx_mutex_unlock(ngx_posted_events_mutex);
+                    wev->ready = 1;
+                    wev->event_handler(wev); 
                 }
             }
         }
 
+        if (n) {
+            ngx_mutex_unlock(ngx_posted_events_mutex);
+        }
+
         if (tested >= rtscf->overflow_test) {
 
             /*
@@ -683,8 +714,13 @@ static ngx_int_t ngx_rtsig_process_overf
         }
     }
 
-    if (!ngx_threaded) {
-        ngx_event_process_posted(cycle);
+    if (ngx_posted_events) {
+        if (ngx_threaded) {
+            ngx_wakeup_worker_thread(cycle);
+
+        } else {
+            ngx_event_process_posted(cycle);
+        }
     }
 
     ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -15,7 +15,6 @@ static void ngx_select_done(ngx_cycle_t 
 static ngx_int_t ngx_select_add_event(ngx_event_t *ev, int event, u_int flags);
 static ngx_int_t ngx_select_del_event(ngx_event_t *ev, int event, u_int flags);
 static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle);
-
 static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf);
 
 
@@ -605,5 +604,11 @@ static char *ngx_select_init_conf(ngx_cy
     }
 #endif
 
+#if (NGX_THREADS)
+    ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+                  "select() is not supported in the threaded mode");
+    return NGX_CONF_ERROR;
+#else
     return NGX_CONF_OK;
+#endif
 }
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -41,9 +41,7 @@ struct ngx_event_s {
     unsigned         oneshot:1;
 
     /* used to detect the stale events in kqueue, rt signals and epoll */
-    unsigned         use_instance:1;
     unsigned         instance:1;
-    unsigned         returned_instance:1;
 
     /*
      * the event was passed or would be passed to a kernel;
@@ -76,6 +74,10 @@ struct ngx_event_s {
     /* the pending eof reported by kqueue or in aio chain operation */
     unsigned         pending_eof:1;
 
+#if !(NGX_THREADS)
+    unsigned         posted_ready:1;
+#endif
+
 #if (WIN32)
     /* setsockopt(SO_UPDATE_ACCEPT_CONTEXT) was succesfull */
     unsigned         accept_context_updated:1;
@@ -244,39 +246,32 @@ extern ngx_event_actions_t   ngx_event_a
 #define NGX_HAVE_LOWAT_EVENT     0x00000010
 
 /*
- * The event filter allows to pass instance information to check stale events -
- * kqueue, epoll, rt signals.
- */
-#define NGX_HAVE_INSTANCE_EVENT  0x00000020
-
-/*
  * The event filter requires to do i/o operation until EAGAIN -
  * epoll, rt signals.
  */
-#define NGX_HAVE_GREEDY_EVENT    0x00000040
+#define NGX_HAVE_GREEDY_EVENT    0x00000020
 
 /*
- * The event filter notifies only the changes (the edges)
- * but not an initial level - early epoll patches.
+ * The event filter is epoll,
  */
-#define NGX_USE_EDGE_EVENT       0x00000080
+#define NGX_USE_EPOLL_EVENT      0x00000040
 
 /*
  * No need to add or delete the event filters - rt signals.
  */
-#define NGX_USE_RTSIG_EVENT      0x00000100
+#define NGX_USE_RTSIG_EVENT      0x00000080
 
 /*
  * No need to add or delete the event filters - overlapped, aio_read,
  * aioread, io_submit.
  */
-#define NGX_USE_AIO_EVENT        0x00000200
+#define NGX_USE_AIO_EVENT        0x00000100
 
 /*
  * Need to add socket or handle only once - i/o completion port.
  * It also requires HAVE_AIO and NGX_USE_AIO_EVENT to be set.
  */
-#define NGX_USE_IOCP_EVENT       0x00000400
+#define NGX_USE_IOCP_EVENT       0x00000200
 
 
 
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -16,7 +16,7 @@ static size_t ngx_accept_log_error(void 
 
 void ngx_event_accept(ngx_event_t *ev)
 {
-    ngx_uint_t             instance, rinstance, winstance, accepted;
+    ngx_uint_t             instance, accepted;
     socklen_t              len;
     struct sockaddr       *sa;
     ngx_err_t              err;
@@ -30,7 +30,7 @@ void ngx_event_accept(ngx_event_t *ev)
 
     ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
 
-    if (ngx_event_flags & (NGX_USE_EDGE_EVENT|NGX_USE_RTSIG_EVENT)) {
+    if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
         ev->available = 1;
 
     } else if (!(ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)) {
@@ -94,8 +94,7 @@ void ngx_event_accept(ngx_event_t *ev)
             err = ngx_socket_errno;
 
             if (err == NGX_EAGAIN) {
-                if (!(ngx_event_flags
-                      & (NGX_USE_EDGE_EVENT|NGX_USE_RTSIG_EVENT)))
+                if (!(ngx_event_flags & NGX_USE_RTSIG_EVENT))
                 {
                     ngx_log_error(NGX_LOG_NOTICE, log, err,
                                   "EAGAIN after %d accepted connection(s)",
@@ -207,8 +206,6 @@ void ngx_event_accept(ngx_event_t *ev)
 #endif
 
         instance = rev->instance;
-        rinstance = rev->returned_instance;
-        winstance = wev->returned_instance;
 
 #if (NGX_THREADS)
 
@@ -231,15 +228,8 @@ void ngx_event_accept(ngx_event_t *ev)
         c->sockaddr = sa;
         c->socklen = len;
 
-        if (ngx_event_flags & NGX_HAVE_INSTANCE_EVENT) {
-            rev->use_instance = 1;
-            rev->instance = (u_char) !instance;
-            rev->returned_instance = (u_char) rinstance;
-
-            wev->use_instance = 1;
-            wev->instance = (u_char) !instance;
-            wev->returned_instance = (u_char) winstance;
-        }
+        rev->instance = !instance;
+        wev->instance = !instance;
 
         rev->index = NGX_INVALID_INDEX;
         wev->index = NGX_INVALID_INDEX;
@@ -256,9 +246,7 @@ void ngx_event_accept(ngx_event_t *ev)
         wev->write = 1;
         wev->ready = 1;
 
-        if (ngx_event_flags
-            & (NGX_USE_AIO_EVENT|NGX_USE_EDGE_EVENT|NGX_USE_RTSIG_EVENT))
-        {
+        if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {
             /* epoll, rtsig, aio, iocp */
             rev->ready = 1;
         }
@@ -267,10 +255,6 @@ void ngx_event_accept(ngx_event_t *ev)
             rev->ready = 1;
         }
 
-        if (rev->ready) {
-            rev->returned_instance = rev->instance;
-        }
-
         c->ctx = ls->ctx;
         c->servers = ls->servers;
 
@@ -318,7 +302,7 @@ void ngx_event_accept(ngx_event_t *ev)
         }
 #endif
 
-        if (ngx_add_conn) {
+        if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
             if (ngx_add_conn(c) == NGX_ERROR) {
                 if (ngx_close_socket(s) == -1) {
                     ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -11,7 +11,7 @@
 int ngx_event_connect_peer(ngx_peer_connection_t *pc)
 {
     int                  rc;
-    ngx_uint_t           instance, rinstance, winstance;
+    ngx_uint_t           instance;
     u_int                event;
     time_t               now;
     ngx_err_t            err;
@@ -30,11 +30,17 @@ int ngx_event_connect_peer(ngx_peer_conn
 
         /* cached connection */
 
-        pc->connection = pc->peers->cached[pc->peers->last_cached];
+        c = pc->peers->cached[pc->peers->last_cached];
         pc->peers->last_cached--;
 
         /* ngx_unlock_mutex(pc->peers->mutex); */
 
+#if (NGX_THREADS)
+        c->read->lock = c->read->own_lock;
+        c->write->lock = c->write->own_lock;
+#endif
+
+        pc->connection = c;
         pc->cached = 1;
         return NGX_OK;
     }
@@ -180,8 +186,6 @@ int ngx_event_connect_peer(ngx_peer_conn
 #endif
 
     instance = rev->instance;
-    rinstance = rev->returned_instance;
-    winstance = wev->returned_instance;
 
 #if (NGX_THREADS)
 
@@ -198,15 +202,8 @@ int ngx_event_connect_peer(ngx_peer_conn
     ngx_memzero(rev, sizeof(ngx_event_t));
     ngx_memzero(wev, sizeof(ngx_event_t));
 
-    if (ngx_event_flags & NGX_HAVE_INSTANCE_EVENT) {
-        rev->use_instance = 1;
-        rev->instance = (u_char) !instance;
-        rev->returned_instance = (u_char) rinstance;
-
-        wev->use_instance = 1;
-        wev->instance = (u_char) !instance;
-        wev->returned_instance = (u_char) winstance;
-    }
+    rev->instance = !instance;
+    wev->instance = !instance;
 
     rev->index = NGX_INVALID_INDEX;
     wev->index = NGX_INVALID_INDEX;
--- a/src/event/ngx_event_posted.c
+++ b/src/event/ngx_event_posted.c
@@ -73,11 +73,8 @@ void ngx_wakeup_worker_thread(ngx_cycle_
 
 ngx_int_t ngx_event_thread_process_posted(ngx_cycle_t *cycle)
 {
-    ngx_tls_t    *tls;
     ngx_event_t  *ev;
 
-    tls = ngx_thread_get_tls();
-
     for ( ;; ) {
 
         ev = (ngx_event_t *) ngx_posted_events;
@@ -136,8 +133,6 @@ ngx_int_t ngx_event_thread_process_poste
 
             ngx_mutex_unlock(ngx_posted_events_mutex);
 
-            tls->event = ev;
-
             ev->event_handler(ev);
 
             if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -136,7 +136,6 @@ void ngx_event_expire_timers(ngx_msec_t 
                 }
 
                 ev->posted_timedout = 1;
-                ev->returned_instance = ev->instance;
                 ngx_post_event(ev);
 
                 ngx_mutex_unlock(ngx_posted_events_mutex);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -456,7 +456,7 @@ ngx_int_t ngx_http_find_location_config(
     ngx_http_core_loc_conf_t      *clcf, **clcfp;
     ngx_http_core_srv_conf_t      *cscf;
 #if (HAVE_PCRE)
-    ngx_uint_t                    exact;
+    ngx_uint_t                     exact;
 #endif
 
     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
--- a/src/os/unix/ngx_channel.c
+++ b/src/os/unix/ngx_channel.c
@@ -194,6 +194,13 @@ ngx_int_t ngx_add_channel_event(ngx_cycl
     rev->data = c;
     wev->data = c;
 
+#if (NGX_THREADS)
+    rev->lock = &c->lock;
+    wev->lock = &c->lock;
+    rev->own_lock = &c->lock;
+    wev->own_lock = &c->lock;
+#endif
+
     ev = (event == NGX_READ_EVENT) ? rev : wev;
 
     ev->event_handler = handler;
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -12,10 +12,12 @@ typedef int               ngx_err_t;
 #define NGX_ESRCH         ESRCH
 #define NGX_EINTR         EINTR
 #define NGX_ECHILD        ECHILD
+#define NGX_ENOMEM        ENOMEM
 #define NGX_EACCES        EACCES
 #define NGX_EBUSY         EBUSY
 #define NGX_EEXIST        EEXIST
 #define NGX_ENOTDIR       ENOTDIR
+#define NGX_EINVAL        EINVAL
 #define NGX_EPIPE         EPIPE
 #define NGX_EAGAIN        EWOULDBLOCK
 #define NGX_EINPROGRESS   EINPROGRESS
--- a/src/os/unix/ngx_freebsd_rfork_thread.c
+++ b/src/os/unix/ngx_freebsd_rfork_thread.c
@@ -30,18 +30,20 @@
  */
 
 
-char                *ngx_freebsd_kern_usrstack;
-size_t               ngx_thread_stack_size;
+char                 *ngx_freebsd_kern_usrstack;
+size_t                ngx_thread_stack_size;
 
 
-static size_t        rz_size;
-static size_t        usable_stack_size;
-static char         *last_stack;
+static size_t         rz_size;
+static size_t         usable_stack_size;
+static char          *last_stack;
 
-static ngx_uint_t    nthreads;
-static ngx_uint_t    max_threads;
-static ngx_tid_t    *tids;      /* the threads tids array */
-void               **ngx_tls;   /* the threads tls's array */
+static ngx_uint_t     nthreads;
+static ngx_uint_t     max_threads;
+
+static ngx_uint_t     nkeys;
+static ngx_tid_t     *tids;      /* the threads tids array */
+void                **ngx_tls;   /* the threads tls's array */
 
 /* the thread-safe libc errno */
 
@@ -236,7 +238,9 @@ ngx_int_t ngx_init_threads(int n, size_t
 
     /* create the threads tls's array */
 
-    if (!(ngx_tls = ngx_calloc((n + 1) * sizeof(void *), cycle->log))) {
+    ngx_tls = ngx_calloc(NGX_THREAD_KEYS_MAX * (n + 1) * sizeof(void *),
+                         cycle->log);
+    if (ngx_tls == NULL) {
         return NGX_ERROR;
     }
 
@@ -270,11 +274,26 @@ ngx_tid_t ngx_thread_self()
 }
 
 
-ngx_int_t ngx_thread_set_tls(void *value)
+ngx_int_t ngx_thread_key_create(ngx_tls_key_t *key)
 {
-    ngx_tls[ngx_gettid()] = value;
+    if (nkeys >= NGX_THREAD_KEYS_MAX) {
+        return NGX_ENOMEM;
+    }
+
+    *key = nkeys++;
+
+    return 0;
+}
 
-    return NGX_OK;
+
+ngx_int_t ngx_thread_set_tls(ngx_tls_key_t key, void *value)
+{
+    if (key >= NGX_THREAD_KEYS_MAX) {
+        return NGX_EINVAL;
+    }
+
+    ngx_tls[key * NGX_THREAD_KEYS_MAX + ngx_gettid()] = value;
+    return 0;
 }
 
 
--- a/src/os/unix/ngx_freebsd_rfork_thread.h
+++ b/src/os/unix/ngx_freebsd_rfork_thread.h
@@ -13,14 +13,6 @@ typedef pid_t  ngx_tid_t;
 #define ngx_log_tid    0
 
 #define TID_T_FMT      PID_T_FMT
-    
-
-extern void          **ngx_tls;
-
-#define ngx_thread_create_tls()  0
-#define ngx_thread_create_tls_n  ""
-#define ngx_thread_get_tls()     ngx_tls[ngx_gettid()]
-ngx_int_t ngx_thread_set_tls(void *value);
 
 
 #define NGX_MUTEX_LIGHT      1
@@ -87,6 +79,29 @@ static inline int ngx_gettid()
 ngx_tid_t ngx_thread_self();
 
 
+typedef ngx_uint_t               ngx_tls_key_t;
+
+#define NGX_THREAD_KEYS_MAX      16
+
+extern void    **ngx_tls;
+
+ngx_int_t ngx_thread_key_create(ngx_tls_key_t *key);
+#define ngx_thread_key_create_n  "the tls key creation"
+
+ngx_int_t ngx_thread_set_tls(ngx_tls_key_t key, void *value);
+#define ngx_thread_set_tls_n     "the tls key setting"
+
+
+static void *ngx_thread_get_tls(ngx_tls_key_t key)
+{   
+    if (key >= NGX_THREAD_KEYS_MAX) {
+        return NULL;
+    }
+
+    return ngx_tls[key * NGX_THREAD_KEYS_MAX + ngx_gettid()];
+}
+
+
 #define ngx_mutex_trylock(m)  ngx_mutex_dolock(m, 1)
 #define ngx_mutex_lock(m)     ngx_mutex_dolock(m, 0)
 ngx_int_t ngx_mutex_dolock(ngx_mutex_t *m, ngx_int_t try);
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -526,6 +526,7 @@ static void ngx_master_exit(ngx_cycle_t 
 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
 {
     sigset_t           set;
+    ngx_err_t          err;
     ngx_int_t          n;
     ngx_uint_t         i;
     ngx_listening_t   *ls;
@@ -637,6 +638,14 @@ static void ngx_worker_process_cycle(ngx
             exit(2);
         }
 
+        err = ngx_thread_key_create(&ngx_core_tls_key);
+        if (err != 0) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
+                          ngx_thread_key_create_n " failed");
+            /* fatal */
+            exit(2);
+        }
+
         for (n = 0; n < ngx_threads_n; n++) {
 
             if (!(ngx_threads[n].cv = ngx_cond_init(cycle->log))) {
@@ -829,7 +838,7 @@ static void* ngx_worker_thread_cycle(voi
 
     sigset_t          set;
     ngx_err_t         err;
-    ngx_tls_t        *tls;
+    ngx_core_tls_t   *tls;
     ngx_cycle_t      *cycle;
     struct timeval    tv;
 
@@ -854,19 +863,17 @@ static void* ngx_worker_thread_cycle(voi
 
     ngx_setthrtitle("worker thread");
 
-    if (!(tls = ngx_calloc(sizeof(ngx_tls_t), cycle->log))) {
+    if (!(tls = ngx_calloc(sizeof(ngx_core_tls_t), cycle->log))) {
         return (void *) 1;
     }
 
-    err = ngx_thread_create_tls();
+    err = ngx_thread_set_tls(ngx_core_tls_key, tls);
     if (err != 0) {
         ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
-                      ngx_thread_create_tls_n " failed");
+                      ngx_thread_set_tls_n " failed");
         return (void *) 1;
     }
 
-    ngx_thread_set_tls(tls);
-
     if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
         return (void *) 1;
     }
@@ -883,7 +890,7 @@ static void* ngx_worker_thread_cycle(voi
 
             ngx_mutex_unlock(ngx_posted_events_mutex);
 
-            ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, ngx_errno,
+            ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
                            "thread %d is done", ngx_thread_self());
 
             return (void *) 0;
@@ -899,8 +906,10 @@ static void* ngx_worker_thread_cycle(voi
             return (void *) 1;
         }
 
-        if (ngx_process_changes(cycle, 1) == NGX_ERROR) {
-            return (void *) 1;
+        if (ngx_process_changes) {
+            if (ngx_process_changes(cycle, 1) == NGX_ERROR) {
+                return (void *) 1;
+            }
         }
     }
 }
--- a/src/os/unix/ngx_thread.h
+++ b/src/os/unix/ngx_thread.h
@@ -16,20 +16,22 @@
 #else /* use pthreads */
 
 #include <pthread.h>
-#include <pthread_np.h>
 
-typedef pthread_t  ngx_tid_t;
+typedef pthread_t                    ngx_tid_t;
 
-#define ngx_thread_self()   pthread_self()
-#define ngx_log_tid         (int) ngx_thread_self()
+#define ngx_thread_self()            pthread_self()
+#define ngx_log_tid                  (int) ngx_thread_self()
 
-#define TID_T_FMT           PTR_FMT
+#define TID_T_FMT                    PTR_FMT
 
 
-#define ngx_thread_create_tls()  pthread_key_create(0, NULL)
-#define ngx_thread_create_tls_n  "pthread_key_create(0, NULL)"
-#define ngx_thread_get_tls()     pthread_getspecific(0)
-#define ngx_thread_set_tls(v)    pthread_setspecific(0, v)
+typedef pthread_key_t                ngx_tls_key_t;
+
+#define ngx_thread_key_create(key)   pthread_key_create(key, NULL)
+#define ngx_thread_key_create_n      "pthread_key_create()"
+#define ngx_thread_set_tls           pthread_setspecific
+#define ngx_thread_set_tls_n         "pthread_setspecific()"
+#define ngx_thread_get_tls           pthread_getspecific
 
 
 #define NGX_MUTEX_LIGHT     0
@@ -111,10 +113,5 @@ ngx_int_t ngx_cond_signal(ngx_cond_t *cv
 #endif
 
 
-typedef struct {
-    ngx_event_t  *event;
-} ngx_tls_t;
-
-
 
 #endif /* _NGX_THREAD_H_INCLUDED_ */