summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorValentin Bartenev <vbart@nginx.com>2016-07-15 15:18:57 +0300
committerValentin Bartenev <vbart@nginx.com>2016-07-15 15:18:57 +0300
commit5c2dd3913aad5c4bf7d9056e1336025c2703586b (patch)
tree8569c90681ada207b182ff4b583225c7a70f3d9e
parentb60534e0d8f943740fb6847ac0a1ff3091a373d0 (diff)
downloadnginx-5c2dd3913aad5c4bf7d9056e1336025c2703586b.tar.gz
nginx-5c2dd3913aad5c4bf7d9056e1336025c2703586b.tar.bz2
Events: support for EPOLLEXCLUSIVE.
This flag appeared in Linux 4.5 and is useful for avoiding thundering herd problem. The current Linux kernel implementation walks the list of exclusive waiters, and queues an event to each epfd, until it finds the first waiter that has threads blocked on it via epoll_wait().
-rw-r--r--auto/modules1
-rw-r--r--auto/os/linux16
-rw-r--r--src/event/modules/ngx_epoll_module.c7
-rw-r--r--src/event/ngx_event.c29
-rw-r--r--src/event/ngx_event.h8
5 files changed, 58 insertions, 3 deletions
diff --git a/auto/modules b/auto/modules
index 829079842..614037cb1 100644
--- a/auto/modules
+++ b/auto/modules
@@ -43,6 +43,7 @@ fi
if [ $NGX_TEST_BUILD_EPOLL = YES ]; then
have=NGX_HAVE_EPOLL . auto/have
have=NGX_HAVE_EPOLLRDHUP . auto/have
+ have=NGX_HAVE_EPOLLEXCLUSIVE . auto/have
have=NGX_HAVE_EVENTFD . auto/have
have=NGX_TEST_BUILD_EPOLL . auto/have
EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE"
diff --git a/auto/os/linux b/auto/os/linux
index 132ce3b42..fae8842c6 100644
--- a/auto/os/linux
+++ b/auto/os/linux
@@ -70,6 +70,22 @@ if [ $ngx_found = yes ]; then
ee.data.ptr = NULL;
epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)"
. auto/feature
+
+
+ # EPOLLEXCLUSIVE appeared in Linux 4.5, glibc 2.24
+
+ ngx_feature="EPOLLEXCLUSIVE"
+ ngx_feature_name="NGX_HAVE_EPOLLEXCLUSIVE"
+ ngx_feature_run=no
+ ngx_feature_incs="#include <sys/epoll.h>"
+ ngx_feature_path=
+ ngx_feature_libs=
+ ngx_feature_test="int efd = 0, fd = 0;
+ struct epoll_event ee;
+ ee.events = EPOLLIN|EPOLLEXCLUSIVE;
+ ee.data.ptr = NULL;
+ epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)"
+ . auto/feature
fi
diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c
index dff778831..c267fd6c7 100644
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -27,6 +27,7 @@
#define EPOLLRDHUP 0x2000
+#define EPOLLEXCLUSIVE 0x10000000
#define EPOLLONESHOT 0x40000000
#define EPOLLET 0x80000000
@@ -610,6 +611,12 @@ ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
op = EPOLL_CTL_ADD;
}
+#if (NGX_HAVE_EPOLLEXCLUSIVE && NGX_HAVE_EPOLLRDHUP)
+ if (flags & NGX_EXCLUSIVE_EVENT) {
+ events &= ~EPOLLRDHUP;
+ }
+#endif
+
ee.events = events | (uint32_t) flags;
ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index 2f3a098de..9d6c4c91b 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -822,15 +822,38 @@ ngx_event_process_init(ngx_cycle_t *cycle)
rev->handler = (c->type == SOCK_STREAM) ? ngx_event_accept
: ngx_event_recvmsg;
- if (ngx_use_accept_mutex
#if (NGX_HAVE_REUSEPORT)
- && !ls[i].reuseport
+
+ if (ls[i].reuseport) {
+ if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ continue;
+ }
+
#endif
- )
+
+ if (ngx_use_accept_mutex) {
+ continue;
+ }
+
+#if (NGX_HAVE_EPOLLEXCLUSIVE)
+
+ if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
+ && ccf->worker_processes > 1)
{
+ if (ngx_add_event(rev, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT)
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+
continue;
}
+#endif
+
if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
return NGX_ERROR;
}
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index 394a0e8e5..27139ee8c 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -367,6 +367,9 @@ extern ngx_uint_t ngx_use_epoll_rdhup;
#define NGX_ONESHOT_EVENT EPOLLONESHOT
#endif
+#if (NGX_HAVE_EPOLLEXCLUSIVE)
+#define NGX_EXCLUSIVE_EVENT EPOLLEXCLUSIVE
+#endif
#elif (NGX_HAVE_POLL)
@@ -395,6 +398,11 @@ extern ngx_uint_t ngx_use_epoll_rdhup;
#endif
+#if (NGX_TEST_BUILD_EPOLL)
+#define NGX_EXCLUSIVE_EVENT 0
+#endif
+
+
#ifndef NGX_CLEAR_EVENT
#define NGX_CLEAR_EVENT 0 /* dummy declaration */
#endif