|
@@ -51,6 +51,10 @@ |
|
|
#ifdef HAVE_SYS_SELECT_H |
|
|
#ifdef HAVE_SYS_SELECT_H |
|
|
#include <sys/select.h> |
|
|
#include <sys/select.h> |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
#ifdef HAVE_EPOLL |
|
|
|
|
|
#include <sys/epoll.h> |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
#ifdef HAVE_KEVENT |
|
|
#ifdef HAVE_KEVENT |
|
|
#include <sys/event.h> |
|
|
#include <sys/event.h> |
|
|
|
|
|
|
|
@@ -107,10 +111,17 @@ static u_long max_burst_len; |
|
|
#ifdef HAVE_KEVENT |
|
|
#ifdef HAVE_KEVENT |
|
|
static int kq, max_sd = 0; |
|
|
static int kq, max_sd = 0; |
|
|
#else |
|
|
#else |
|
|
|
|
|
#ifdef HAVE_EPOLL |
|
|
|
|
|
#define EPOLL_N_MAX 8192 |
|
|
|
|
|
static int epoll_fd, max_sd = 0; |
|
|
|
|
|
static struct epoll_event *epoll_events; |
|
|
|
|
|
static int epoll_timeout; |
|
|
|
|
|
#else |
|
|
static fd_set rdfds, wrfds; |
|
|
static fd_set rdfds, wrfds; |
|
|
static int min_sd = 0x7fffffff, max_sd = 0, alloced_sd_to_conn = 0; |
|
|
static int min_sd = 0x7fffffff, max_sd = 0, alloced_sd_to_conn = 0; |
|
|
static struct timeval select_timeout; |
|
|
static struct timeval select_timeout; |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
#endif |
|
|
static struct sockaddr_in myaddr; |
|
|
static struct sockaddr_in myaddr; |
|
|
static struct address_pool myaddrs; |
|
|
static struct address_pool myaddrs; |
|
|
#ifndef HAVE_KEVENT |
|
|
#ifndef HAVE_KEVENT |
|
@@ -151,12 +162,14 @@ static char http11req_nohost[] = |
|
|
enum Syscalls { |
|
|
enum Syscalls { |
|
|
SC_BIND, SC_CONNECT, SC_READ, SC_SELECT, SC_SOCKET, SC_WRITEV, |
|
|
SC_BIND, SC_CONNECT, SC_READ, SC_SELECT, SC_SOCKET, SC_WRITEV, |
|
|
SC_SSL_READ, SC_SSL_WRITEV, SC_KEVENT, |
|
|
SC_SSL_READ, SC_SSL_WRITEV, SC_KEVENT, |
|
|
|
|
|
SC_EPOLL_CREATE, SC_EPOLL_CTL, SC_EPOLL_WAIT, |
|
|
SC_NUM_SYSCALLS |
|
|
SC_NUM_SYSCALLS |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
static const char *const syscall_name[SC_NUM_SYSCALLS] = { |
|
|
static const char *const syscall_name[SC_NUM_SYSCALLS] = { |
|
|
"bind", "connct", "read", "select", "socket", "writev", |
|
|
"bind", "connct", "read", "select", "socket", "writev", |
|
|
"ssl_read", "ssl_writev", "kevent" |
|
|
|
|
|
|
|
|
"ssl_read", "ssl_writev", "kevent", |
|
|
|
|
|
"epoll_create", "epoll_ctl", "epoll_wait" |
|
|
}; |
|
|
}; |
|
|
static Time syscall_time[SC_NUM_SYSCALLS]; |
|
|
static Time syscall_time[SC_NUM_SYSCALLS]; |
|
|
static u_int syscall_count[SC_NUM_SYSCALLS]; |
|
|
static u_int syscall_count[SC_NUM_SYSCALLS]; |
|
@@ -373,6 +386,23 @@ clear_active(Conn * s, enum IO_DIR dir) |
|
|
"write" : "read"); |
|
|
"write" : "read"); |
|
|
exit(1); |
|
|
exit(1); |
|
|
} |
|
|
} |
|
|
|
|
|
#else |
|
|
|
|
|
#ifdef HAVE_EPOLL |
|
|
|
|
|
struct epoll_event ev; |
|
|
|
|
|
int error; |
|
|
|
|
|
|
|
|
|
|
|
if (dir == WRITE) |
|
|
|
|
|
ev.events = EPOLLIN; |
|
|
|
|
|
else |
|
|
|
|
|
ev.events = EPOLLOUT; |
|
|
|
|
|
ev.data.ptr = s; |
|
|
|
|
|
|
|
|
|
|
|
error = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, sd, &ev); |
|
|
|
|
|
if (error < 0) { |
|
|
|
|
|
error = errno; |
|
|
|
|
|
fprintf(stderr, "failed to EPOLL_CTL_DEL\n"); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
#else |
|
|
#else |
|
|
fd_set * fdset; |
|
|
fd_set * fdset; |
|
|
|
|
|
|
|
@@ -381,6 +411,7 @@ clear_active(Conn * s, enum IO_DIR dir) |
|
|
else |
|
|
else |
|
|
fdset = &rdfds; |
|
|
fdset = &rdfds; |
|
|
FD_CLR(sd, fdset); |
|
|
FD_CLR(sd, fdset); |
|
|
|
|
|
#endif |
|
|
#endif |
|
|
#endif |
|
|
if (dir == WRITE) |
|
|
if (dir == WRITE) |
|
|
s->writing = 0; |
|
|
s->writing = 0; |
|
@@ -404,6 +435,28 @@ set_active(Conn * s, enum IO_DIR dir) |
|
|
"write" : "read"); |
|
|
"write" : "read"); |
|
|
exit(1); |
|
|
exit(1); |
|
|
} |
|
|
} |
|
|
|
|
|
#else |
|
|
|
|
|
#ifdef HAVE_EPOLL |
|
|
|
|
|
struct epoll_event ev; |
|
|
|
|
|
int error; |
|
|
|
|
|
|
|
|
|
|
|
if (dir == WRITE) |
|
|
|
|
|
ev.events = EPOLLOUT; |
|
|
|
|
|
else |
|
|
|
|
|
ev.events = EPOLLIN; |
|
|
|
|
|
ev.data.ptr = s; |
|
|
|
|
|
|
|
|
|
|
|
if (s->epoll_added) |
|
|
|
|
|
error = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, sd, &ev); |
|
|
|
|
|
else { |
|
|
|
|
|
error = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sd, &ev); |
|
|
|
|
|
s->epoll_added = 1; |
|
|
|
|
|
} |
|
|
|
|
|
if (error < 0) { |
|
|
|
|
|
error = errno; |
|
|
|
|
|
fprintf(stderr, "failed to EPOLL_CTL_MOD\n"); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
#else |
|
|
#else |
|
|
fd_set * fdset; |
|
|
fd_set * fdset; |
|
|
|
|
|
|
|
@@ -414,6 +467,7 @@ set_active(Conn * s, enum IO_DIR dir) |
|
|
FD_SET(sd, fdset); |
|
|
FD_SET(sd, fdset); |
|
|
if (sd < min_sd) |
|
|
if (sd < min_sd) |
|
|
min_sd = sd; |
|
|
min_sd = sd; |
|
|
|
|
|
#endif |
|
|
#endif |
|
|
#endif |
|
|
if (sd >= max_sd) |
|
|
if (sd >= max_sd) |
|
|
max_sd = sd; |
|
|
max_sd = sd; |
|
@@ -882,7 +936,7 @@ core_init(void) |
|
|
Any_Type arg; |
|
|
Any_Type arg; |
|
|
|
|
|
|
|
|
memset(&hash_table, 0, sizeof(hash_table)); |
|
|
memset(&hash_table, 0, sizeof(hash_table)); |
|
|
#ifndef HAVE_KEVENT |
|
|
|
|
|
|
|
|
#if !defined(HAVE_KEVENT) && !defined(HAVE_EPOLL) |
|
|
memset(&rdfds, 0, sizeof(rdfds)); |
|
|
memset(&rdfds, 0, sizeof(rdfds)); |
|
|
memset(&wrfds, 0, sizeof(wrfds)); |
|
|
memset(&wrfds, 0, sizeof(wrfds)); |
|
|
#endif |
|
|
#endif |
|
@@ -922,6 +976,23 @@ core_init(void) |
|
|
strerror(errno)); |
|
|
strerror(errno)); |
|
|
} |
|
|
} |
|
|
#else |
|
|
#else |
|
|
|
|
|
#ifdef HAVE_EPOLL |
|
|
|
|
|
epoll_fd = epoll_create(EPOLL_N_MAX); |
|
|
|
|
|
if (epoll_fd < 0) { |
|
|
|
|
|
fprintf(stderr, |
|
|
|
|
|
"%s: failed to create epoll: %s", prog_name, |
|
|
|
|
|
strerror(errno)); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
epoll_events = calloc(EPOLL_N_MAX, sizeof(struct epoll_event)); |
|
|
|
|
|
if (epoll_events == NULL) { |
|
|
|
|
|
fprintf(stderr, |
|
|
|
|
|
"%s: failed to create epoll_events: %s", prog_name, |
|
|
|
|
|
strerror(errno)); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
epoll_timeout = 0; |
|
|
|
|
|
#else |
|
|
#ifdef DONT_POLL |
|
|
#ifdef DONT_POLL |
|
|
/* |
|
|
/* |
|
|
* This causes select() to take several milliseconds on both Linux/x86 |
|
|
* This causes select() to take several milliseconds on both Linux/x86 |
|
@@ -939,6 +1010,7 @@ core_init(void) |
|
|
select_timeout.tv_sec = 0; |
|
|
select_timeout.tv_sec = 0; |
|
|
select_timeout.tv_usec = 0; |
|
|
select_timeout.tv_usec = 0; |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
#endif |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
/* |
|
|
/* |
|
@@ -1120,7 +1192,7 @@ core_connect(Conn * s) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
s->sd = sd; |
|
|
s->sd = sd; |
|
|
#ifndef HAVE_KEVENT |
|
|
|
|
|
|
|
|
#if !defined(HAVE_KEVENT) && !defined(HAVE_EPOLL) |
|
|
if (sd >= alloced_sd_to_conn) { |
|
|
if (sd >= alloced_sd_to_conn) { |
|
|
size_t size, old_size; |
|
|
size_t size, old_size; |
|
|
|
|
|
|
|
@@ -1368,8 +1440,19 @@ core_close(Conn * conn) |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
if (sd >= 0) { |
|
|
if (sd >= 0) { |
|
|
|
|
|
#ifdef HAVE_EPOLL |
|
|
|
|
|
struct epoll_event ev = { 0, { 0 } }; |
|
|
|
|
|
int error; |
|
|
|
|
|
|
|
|
|
|
|
error = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, sd, &ev); |
|
|
|
|
|
if (error < 0) { |
|
|
|
|
|
error = errno; |
|
|
|
|
|
printf("EPOLL_CTL_DEL: %d %d %d\n", epoll_fd, sd, error); |
|
|
|
|
|
assert(error == 0); |
|
|
|
|
|
} |
|
|
|
|
|
#endif |
|
|
close(sd); |
|
|
close(sd); |
|
|
#ifndef HAVE_KEVENT |
|
|
|
|
|
|
|
|
#if !defined(HAVE_KEVENT) && !defined(HAVE_EPOLL) |
|
|
sd_to_conn[sd] = 0; |
|
|
sd_to_conn[sd] = 0; |
|
|
FD_CLR(sd, &wrfds); |
|
|
FD_CLR(sd, &wrfds); |
|
|
FD_CLR(sd, &rdfds); |
|
|
FD_CLR(sd, &rdfds); |
|
@@ -1445,6 +1528,58 @@ core_loop(void) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
#else |
|
|
#else |
|
|
|
|
|
#ifdef HAVE_EPOLL |
|
|
|
|
|
void |
|
|
|
|
|
core_loop(void) |
|
|
|
|
|
{ |
|
|
|
|
|
struct epoll_event *ep; |
|
|
|
|
|
int i, n; |
|
|
|
|
|
Any_Type arg; |
|
|
|
|
|
Conn *conn; |
|
|
|
|
|
|
|
|
|
|
|
while (running) { |
|
|
|
|
|
++iteration; |
|
|
|
|
|
|
|
|
|
|
|
timer_tick(); |
|
|
|
|
|
n = epoll_wait(epoll_fd, epoll_events, EPOLL_N_MAX, epoll_timeout); |
|
|
|
|
|
if (n < 0 && errno == EINTR) { |
|
|
|
|
|
fprintf(stderr, "failed to fetch event: %s", |
|
|
|
|
|
strerror(errno)); |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
ep = epoll_events; |
|
|
|
|
|
for (i = 0; i < n; i++, ep++) { |
|
|
|
|
|
conn = ep->data.ptr; |
|
|
|
|
|
conn_inc_ref(conn); |
|
|
|
|
|
|
|
|
|
|
|
if (conn->watchdog) { |
|
|
|
|
|
timer_cancel(conn->watchdog); |
|
|
|
|
|
conn->watchdog = 0; |
|
|
|
|
|
} |
|
|
|
|
|
if (conn->state == S_CONNECTING) { |
|
|
|
|
|
#ifdef HAVE_SSL |
|
|
|
|
|
if (param.use_ssl) |
|
|
|
|
|
core_ssl_connect(conn); |
|
|
|
|
|
else |
|
|
|
|
|
#endif |
|
|
|
|
|
if (ep->events & EPOLLOUT) { |
|
|
|
|
|
clear_active(conn, WRITE); |
|
|
|
|
|
conn->state = S_CONNECTED; |
|
|
|
|
|
arg.l = 0; |
|
|
|
|
|
event_signal(EV_CONN_CONNECTED, (Object*)conn, arg); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
if (ep->events & (EPOLLIN | EPOLLHUP) && conn->recvq) |
|
|
|
|
|
do_recv(conn); |
|
|
|
|
|
if (ep->events & EPOLLOUT && conn->sendq) |
|
|
|
|
|
do_send(conn); |
|
|
|
|
|
} |
|
|
|
|
|
conn_dec_ref(conn); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
close(epoll_fd); |
|
|
|
|
|
} |
|
|
|
|
|
#else |
|
|
void |
|
|
void |
|
|
core_loop(void) |
|
|
core_loop(void) |
|
|
{ |
|
|
{ |
|
@@ -1541,6 +1676,7 @@ core_loop(void) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
void |
|
|
void |
|
|
core_exit(void) |
|
|
core_exit(void) |
|
|