diff src/event/modules/ngx_epoll_module.c @ 306:6b91bfbc4123

nginx-0.0.3-2004-04-05-00:32:09 import
author Igor Sysoev <igor@sysoev.ru>
date Sun, 04 Apr 2004 20:32:09 +0000
parents 4b1a3a4acc60
children 2e899477243a
line wrap: on
line diff
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -168,10 +168,11 @@ static int ngx_epoll_init(ngx_cycle_t *c
     ngx_event_actions = ngx_epoll_module_ctx.actions;
 
 #if (HAVE_CLEAR_EVENT)
-    ngx_event_flags = NGX_USE_CLEAR_EVENT;
+    ngx_event_flags = NGX_USE_CLEAR_EVENT
 #else
-    ngx_event_flags = NGX_USE_LEVEL_EVENT;
+    ngx_event_flags = NGX_USE_LEVEL_EVENT
 #endif
+                      |NGX_HAVE_INSTANCE_EVENT;
 
     return NGX_OK;
 }
@@ -257,7 +258,7 @@ static int ngx_epoll_del_event(ngx_event
     /*
      * 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.
+     * before the closing the file descriptor
      */
 
     if (flags & NGX_CLOSE_EVENT) {
@@ -339,21 +340,36 @@ static int ngx_epoll_del_connection(ngx_
 
 int ngx_epoll_process_events(ngx_cycle_t *cycle)
 {
-    int                 events;
-    ngx_int_t           instance, i;
-    size_t              n;
-    ngx_msec_t          timer;
-    ngx_err_t           err;
-    struct timeval      tv;
-    ngx_connection_t   *c;
-    ngx_epoch_msec_t    delta;
-
+    int                events;
+    ngx_int_t          instance, i;
+    ngx_uint_t         lock, expire;
+    size_t             n;
+    ngx_msec_t         timer;
+    ngx_err_t          err;
+    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;
+        expire = 0;
+
+    } else {
+        expire = 1;
+    }
+
+    if (ngx_accept_mutex) {
+        if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
+            return NGX_ERROR;
+        }
+
+        if (ngx_accept_mutex_held == 0 && timer > ngx_accept_mutex_delay) {
+            timer = ngx_accept_mutex_delay;
+            expire = 0;
+        }
     }
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
@@ -382,6 +398,7 @@ int ngx_epoll_process_events(ngx_cycle_t
         if (events == 0) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                           "epoll_wait() returned no events without timeout");
+            ngx_accept_mutex_unlock();
             return NGX_ERROR;
         }
     }
@@ -389,9 +406,17 @@ int ngx_epoll_process_events(ngx_cycle_t
     if (err) {
         ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
                       cycle->log, err, "epoll_wait() failed");
+        ngx_accept_mutex_unlock();
         return NGX_ERROR;
     }
 
+    if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
+        ngx_accept_mutex_unlock();
+        return NGX_ERROR;
+    }
+
+    lock = 1;
+
     for (i = 0; i < events; i++) {
         c = event_list[i].data.ptr;
 
@@ -434,25 +459,68 @@ int ngx_epoll_process_events(ngx_cycle_t
                           c->fd, event_list[i].events);
         }
 
+        if ((event_list[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP))
+            && c->write->active)
+        {
+            c->write->ready = 1;
+
+            if (!ngx_threaded && !ngx_accept_mutex_held) {
+                c->write->event_handler(c->write);
+
+            } else {
+                ngx_post_event(c->write);
+            }
+        }
+
+        /*
+         * EPOLLIN must be handled after EPOLLOUT because we use
+         * the optimization to avoid the unnecessary mutex locking/unlocking
+         * if the accept event is the last one.
+         */
+
         if ((event_list[i].events & (EPOLLIN|EPOLLERR|EPOLLHUP))
             && c->read->active)
         {
             c->read->ready = 1;
-            c->read->event_handler(c->read);
-        }
+
+            if (!ngx_threaded && !ngx_accept_mutex_held) {
+                c->read->event_handler(c->read);
+
+            } else if (!c->read->accept) {
+                ngx_post_event(c->read);
+
+            } else {
+                ngx_mutex_unlock(ngx_posted_events_mutex);
 
-        if ((event_list[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP))
-            && c->write->active)
-        {
-            c->write->ready = 1;
-            c->write->event_handler(c->write);
+                c->read->event_handler(c->read);
+
+                if (i + 1 == events) {
+                    lock = 0;
+                    break;
+                }
+
+                if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
+                    ngx_accept_mutex_unlock();
+                    return NGX_ERROR;
+                }
+            }
         }
     }
 
-    if (timer != (ngx_msec_t) -1 && delta) {
+    if (lock) {
+        ngx_mutex_unlock(ngx_posted_events_mutex);
+    }
+
+    ngx_accept_mutex_unlock();
+
+    if (expire && delta) {
         ngx_event_expire_timers((ngx_msec_t) delta);
     }
 
+    if (!ngx_threaded) {
+        ngx_event_process_posted(cycle);
+    }
+
     return NGX_OK;
 }