aboutsummaryrefslogtreecommitdiff
path: root/src/event/modules/ngx_epoll_module.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/event/modules/ngx_epoll_module.c')
-rw-r--r--src/event/modules/ngx_epoll_module.c108
1 files changed, 88 insertions, 20 deletions
diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c
index 3f534ff17..fb41fd417 100644
--- 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 *cycle)
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_t *ev, int event, u_int flags)
/*
* 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_connection_t *c)
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 *cycle)
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 *cycle)
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 *cycle)
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 ((event_list[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP))
- && c->write->active)
- {
- c->write->ready = 1;
- c->write->event_handler(c->write);
+ 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);
+
+ 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;
}