diff options
Diffstat (limited to 'src/os/unix')
-rw-r--r-- | src/os/unix/ngx_aio.h | 21 | ||||
-rw-r--r-- | src/os/unix/ngx_aio_read.c | 12 | ||||
-rw-r--r-- | src/os/unix/ngx_aio_read_chain.c | 1 | ||||
-rw-r--r-- | src/os/unix/ngx_aio_write.c | 12 | ||||
-rw-r--r-- | src/os/unix/ngx_aio_write_chain.c | 1 | ||||
-rw-r--r-- | src/os/unix/ngx_file_aio_read.c | 210 | ||||
-rw-r--r-- | src/os/unix/ngx_files.h | 8 | ||||
-rw-r--r-- | src/os/unix/ngx_freebsd_config.h | 9 | ||||
-rw-r--r-- | src/os/unix/ngx_linux_aio_read.c | 131 | ||||
-rw-r--r-- | src/os/unix/ngx_linux_config.h | 7 | ||||
-rw-r--r-- | src/os/unix/ngx_os.h | 8 | ||||
-rw-r--r-- | src/os/unix/ngx_posix_config.h | 6 | ||||
-rw-r--r-- | src/os/unix/ngx_process.c | 3 | ||||
-rw-r--r-- | src/os/unix/ngx_process_cycle.c | 11 | ||||
-rw-r--r-- | src/os/unix/ngx_process_cycle.h | 1 | ||||
-rw-r--r-- | src/os/unix/ngx_solaris_config.h | 15 |
16 files changed, 393 insertions, 63 deletions
diff --git a/src/os/unix/ngx_aio.h b/src/os/unix/ngx_aio.h deleted file mode 100644 index c286dbd60..000000000 --- a/src/os/unix/ngx_aio.h +++ /dev/null @@ -1,21 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - */ - - -#ifndef _NGX_AIO_H_INCLUDED_ -#define _NGX_AIO_H_INCLUDED_ - - -#include <ngx_core.h> - - -ssize_t ngx_aio_read(ngx_connection_t *c, u_char *buf, size_t size); -ssize_t ngx_aio_read_chain(ngx_connection_t *c, ngx_chain_t *cl); -ssize_t ngx_aio_write(ngx_connection_t *c, u_char *buf, size_t size); -ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in, - off_t limit); - - -#endif /* _NGX_AIO_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_aio_read.c b/src/os/unix/ngx_aio_read.c index 206f0efb2..1e41bac5f 100644 --- a/src/os/unix/ngx_aio_read.c +++ b/src/os/unix/ngx_aio_read.c @@ -7,20 +7,10 @@ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> -#include <ngx_aio.h> -#if (NGX_HAVE_KQUEUE) -#include <ngx_kqueue_module.h> -#endif +extern int ngx_kqueue; -/* - * the ready data requires 3 syscalls: - * aio_write(), aio_error(), aio_return() - * the non-ready data requires 4 (kqueue) or 5 syscalls: - * aio_write(), aio_error(), notifiction, aio_error(), aio_return() - * timeout, aio_cancel(), aio_error() - */ ssize_t ngx_aio_read(ngx_connection_t *c, u_char *buf, size_t size) diff --git a/src/os/unix/ngx_aio_read_chain.c b/src/os/unix/ngx_aio_read_chain.c index da85ed9ea..28b9c8fa9 100644 --- a/src/os/unix/ngx_aio_read_chain.c +++ b/src/os/unix/ngx_aio_read_chain.c @@ -7,7 +7,6 @@ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> -#include <ngx_aio.h> ssize_t diff --git a/src/os/unix/ngx_aio_write.c b/src/os/unix/ngx_aio_write.c index 57e751d10..9138af16a 100644 --- a/src/os/unix/ngx_aio_write.c +++ b/src/os/unix/ngx_aio_write.c @@ -7,20 +7,10 @@ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> -#include <ngx_aio.h> -#if (NGX_HAVE_KQUEUE) -#include <ngx_kqueue_module.h> -#endif +extern int ngx_kqueue; -/* - * the ready data requires 3 syscalls: - * aio_write(), aio_error(), aio_return() - * the non-ready data requires 4 (kqueue) or 5 syscalls: - * aio_write(), aio_error(), notifiction, aio_error(), aio_return() - * timeout, aio_cancel(), aio_error() - */ ssize_t ngx_aio_write(ngx_connection_t *c, u_char *buf, size_t size) diff --git a/src/os/unix/ngx_aio_write_chain.c b/src/os/unix/ngx_aio_write_chain.c index 6a156e91b..716789690 100644 --- a/src/os/unix/ngx_aio_write_chain.c +++ b/src/os/unix/ngx_aio_write_chain.c @@ -7,7 +7,6 @@ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> -#include <ngx_aio.h> ngx_chain_t * diff --git a/src/os/unix/ngx_file_aio_read.c b/src/os/unix/ngx_file_aio_read.c new file mode 100644 index 000000000..bf089ec5d --- /dev/null +++ b/src/os/unix/ngx_file_aio_read.c @@ -0,0 +1,210 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_event.h> + + +/* + * FreeBSD file AIO features and quirks: + * + * if an asked data are already in VM cache, then aio_error() returns 0, + * and the data are already copied in buffer; + * + * aio_read() preread in VM cache as minimum 32K; + * + * aio_read/aio_error() may return EINPROGRESS for just written data; + * + * kqueue EVFILT_AIO filter is level triggered only: an event repeats + * until aio_return() will be called; + * + * aio_cancel() can not cancel file AIO: it returns AIO_NOTCANCELED always. + */ + + +extern int ngx_kqueue; + + +static ssize_t ngx_file_aio_result(ngx_file_t *file, ngx_event_aio_t *aio, + ngx_event_t *ev); +static void ngx_file_aio_event_handler(ngx_event_t *ev); + + +ssize_t +ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset, + ngx_pool_t *pool) +{ + int n; + ngx_event_t *ev; + ngx_event_aio_t *aio; + static ngx_uint_t enosys = 0; + + if (enosys) { + return ngx_read_file(file, buf, size, offset); + } + + aio = file->aio; + + if (aio == NULL) { + aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t)); + if (aio == NULL) { + return NGX_ERROR; + } + + aio->file = file; + aio->fd = file->fd; + aio->event.data = aio; + aio->event.ready = 1; + aio->event.log = file->log; + file->aio = aio; + } + + ev = &aio->event; + + if (!ev->ready) { + ngx_log_error(NGX_LOG_ALERT, file->log, 0, + "second aio post for \"%V\"", &file->name); + return NGX_AGAIN; + } + + ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, + "aio complete:%d @%O:%z %V", + ev->complete, offset, size, &file->name); + + if (ev->complete) { + ev->complete = 0; + ngx_set_errno(aio->err); + + if (aio->err == 0) { + return aio->nbytes; + } + + return NGX_ERROR; + } + + ngx_memzero(&aio->aiocb, sizeof(struct aiocb)); + + aio->aiocb.aio_fildes = file->fd; + aio->aiocb.aio_offset = offset; + aio->aiocb.aio_buf = buf; + aio->aiocb.aio_nbytes = size; +#if (NGX_HAVE_KQUEUE) + aio->aiocb.aio_sigevent.sigev_notify_kqueue = ngx_kqueue; + aio->aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT; + aio->aiocb.aio_sigevent.sigev_value.sigval_ptr = ev; +#endif + ev->handler = ngx_file_aio_event_handler; + + n = aio_read(&aio->aiocb); + + if (n == -1) { + n = ngx_errno; + + if (n == NGX_EAGAIN) { + return ngx_read_file(file, buf, size, offset); + } + + ngx_log_error(NGX_LOG_CRIT, file->log, n, + "aio_read(\"%V\") failed", &file->name); + + if (n == NGX_ENOSYS) { + enosys = 1; + return ngx_read_file(file, buf, size, offset); + } + + return NGX_ERROR; + } + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, + "aio_read: fd:%d %d", file->fd, n); + + ev->active = 1; + ev->ready = 0; + ev->complete = 0; + + return ngx_file_aio_result(aio->file, aio, ev); +} + + +static ssize_t +ngx_file_aio_result(ngx_file_t *file, ngx_event_aio_t *aio, ngx_event_t *ev) +{ + int n; + ngx_err_t err; + + n = aio_error(&aio->aiocb); + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, + "aio_error: fd:%d %d", file->fd, n); + + if (n == -1) { + err = ngx_errno; + aio->err = err; + + ngx_log_error(NGX_LOG_ALERT, file->log, err, + "aio_error(\"%V\") failed", &file->name); + return NGX_ERROR; + } + + if (n != 0) { + if (n == NGX_EINPROGRESS) { + if (ev->ready) { + ev->ready = 0; + ngx_log_error(NGX_LOG_ALERT, file->log, n, + "aio_read(\"%V\") still in progress", + &file->name); + } + + return NGX_AGAIN; + } + + aio->err = n; + ev->ready = 0; + + ngx_log_error(NGX_LOG_CRIT, file->log, n, + "aio_read(\"%V\") failed", &file->name); + return NGX_ERROR; + } + + n = aio_return(&aio->aiocb); + + if (n == -1) { + err = ngx_errno; + aio->err = err; + ev->ready = 0; + + ngx_log_error(NGX_LOG_ALERT, file->log, err, + "aio_return(\"%V\") failed", &file->name); + return NGX_ERROR; + } + + aio->err = 0; + aio->nbytes = n; + ev->ready = 1; + ev->active = 0; + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, file->log, 0, + "aio_return: fd:%d %d", file->fd, n); + + return n; +} + + +static void +ngx_file_aio_event_handler(ngx_event_t *ev) +{ + ngx_event_aio_t *aio; + + aio = ev->data; + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, ev->log, 0, + "aio event handler fd:%d %V", aio->fd, &aio->file->name); + + if (ngx_file_aio_result(aio->file, aio, ev) != NGX_AGAIN) { + aio->handler(ev); + } +} diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h index 5395acd03..993ce8f93 100644 --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -287,4 +287,12 @@ size_t ngx_fs_bsize(u_char *name); #define ngx_set_stderr_n "dup2(STDERR_FILENO)" +#if (NGX_HAVE_FILE_AIO) + +ssize_t ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, + off_t offset, ngx_pool_t *pool); + +#endif + + #endif /* _NGX_FILES_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h index 997581a6b..20cb66640 100644 --- a/src/os/unix/ngx_freebsd_config.h +++ b/src/os/unix/ngx_freebsd_config.h @@ -73,13 +73,14 @@ #endif -#if (NGX_HAVE_AIO) -#include <aio.h> +#if (NGX_HAVE_KQUEUE) +#include <sys/event.h> #endif -#if (NGX_HAVE_KQUEUE) -#include <sys/event.h> +#if (NGX_HAVE_FILE_AIO || NGX_HAVE_AIO) +#include <aio.h> +typedef struct aiocb ngx_aiocb_t; #endif diff --git a/src/os/unix/ngx_linux_aio_read.c b/src/os/unix/ngx_linux_aio_read.c new file mode 100644 index 000000000..3b4185c8b --- /dev/null +++ b/src/os/unix/ngx_linux_aio_read.c @@ -0,0 +1,131 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_event.h> + + +extern int ngx_eventfd; +extern aio_context_t ngx_aio_ctx; + + +static void ngx_file_aio_event_handler(ngx_event_t *ev); + + +static long +io_submit(aio_context_t ctx, long n, struct iocb **paiocb) +{ + return syscall(SYS_io_submit, ctx, n, paiocb); +} + + +ssize_t +ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset, + ngx_pool_t *pool) +{ + long n; + struct iocb *piocb[1]; + ngx_event_t *ev; + ngx_event_aio_t *aio; + static ngx_uint_t enosys = 0; + + if (enosys) { + return ngx_read_file(file, buf, size, offset); + } + + aio = file->aio; + + if (aio == NULL) { + aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t)); + if (aio == NULL) { + return NGX_ERROR; + } + + aio->file = file; + aio->fd = file->fd; + aio->event.data = aio; + aio->event.ready = 1; + aio->event.log = file->log; + file->aio = aio; + } + + ev = &aio->event; + + if (!ev->ready) { + ngx_log_error(NGX_LOG_ALERT, file->log, 0, + "second aio post for \"%V\"", &file->name); + return NGX_AGAIN; + } + + ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0, + "aio complete:%d @%O:%z %V", + ev->complete, offset, size, &file->name); + + if (ev->complete) { + ev->active = 0; + ev->complete = 0; + + if (aio->res >= 0) { + ngx_set_errno(0); + return aio->res; + } + + ngx_set_errno(-aio->res); + return NGX_ERROR; + } + + ngx_memzero(&aio->aiocb, sizeof(struct iocb)); + + aio->aiocb.aio_data = (uint64_t) (uintptr_t) ev; + aio->aiocb.aio_lio_opcode = IOCB_CMD_PREAD; + aio->aiocb.aio_fildes = file->fd; + aio->aiocb.aio_buf = (uint64_t) (uintptr_t) buf; + aio->aiocb.aio_nbytes = size; + aio->aiocb.aio_offset = offset; + aio->aiocb.aio_flags = IOCB_FLAG_RESFD; + aio->aiocb.aio_resfd = ngx_eventfd; + + ev->handler = ngx_file_aio_event_handler; + + piocb[0] = &aio->aiocb; + + n = io_submit(ngx_aio_ctx, 1, piocb); + + if (n == 1) { + return NGX_AGAIN; + } + + n = -n; + + if (n == NGX_EAGAIN) { + return ngx_read_file(file, buf, size, offset); + } + + ngx_log_error(NGX_LOG_CRIT, file->log, n, + "io_submit(\"%V\") failed", &file->name); + + if (n == NGX_ENOSYS) { + enosys = 1; + return ngx_read_file(file, buf, size, offset); + } + + return NGX_ERROR; +} + + +static void +ngx_file_aio_event_handler(ngx_event_t *ev) +{ + ngx_event_aio_t *aio; + + aio = ev->data; + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, ev->log, 0, + "aio event handler fd:%d %V", aio->fd, &aio->file->name); + + aio->handler(ev); +} diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h index fb978c46e..cf45e54a1 100644 --- a/src/os/unix/ngx_linux_config.h +++ b/src/os/unix/ngx_linux_config.h @@ -81,6 +81,13 @@ extern ssize_t sendfile(int s, int fd, int32_t *offset, size_t size); #endif +#if (NGX_HAVE_FILE_AIO) +#include <sys/syscall.h> +#include <linux/aio_abi.h> +typedef struct iocb ngx_aiocb_t; +#endif + + #define NGX_LISTEN_BACKLOG 511 diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h index a8b6c6dc0..f1d8e6824 100644 --- a/src/os/unix/ngx_os.h +++ b/src/os/unix/ngx_os.h @@ -47,6 +47,14 @@ ssize_t ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size); ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit); +#if (NGX_HAVE_AIO) +ssize_t ngx_aio_read(ngx_connection_t *c, u_char *buf, size_t size); +ssize_t ngx_aio_read_chain(ngx_connection_t *c, ngx_chain_t *cl); +ssize_t ngx_aio_write(ngx_connection_t *c, u_char *buf, size_t size); +ngx_chain_t *ngx_aio_write_chain(ngx_connection_t *c, ngx_chain_t *in, + off_t limit); +#endif + extern ngx_os_io_t ngx_os_io; extern ngx_int_t ngx_ncpu; diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h index 3644151ee..86a80d701 100644 --- a/src/os/unix/ngx_posix_config.h +++ b/src/os/unix/ngx_posix_config.h @@ -112,6 +112,12 @@ #endif +#if (NGX_HAVE_FILE_AIO) +#include <aio.h> +typedef struct aiocb ngx_aiocb_t; +#endif + + #define NGX_LISTEN_BACKLOG 511 diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c index c92802ef9..48ba9d4db 100644 --- a/src/os/unix/ngx_process.c +++ b/src/os/unix/ngx_process.c @@ -73,6 +73,8 @@ ngx_signal_t signals[] = { { SIGCHLD, "SIGCHLD", "", ngx_signal_handler }, + { SIGSYS, "SIGSYS, SIG_IGN", "", SIG_IGN }, + { SIGPIPE, "SIGPIPE, SIG_IGN", "", SIG_IGN }, { 0, NULL, "", NULL } @@ -371,6 +373,7 @@ ngx_signal_handler(int signo) break; case SIGALRM: + ngx_sigalrm = 1; break; case SIGIO: diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index 69df544d3..21521ec26 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -37,6 +37,7 @@ ngx_uint_t ngx_threaded; sig_atomic_t ngx_reap; sig_atomic_t ngx_sigio; +sig_atomic_t ngx_sigalrm; sig_atomic_t ngx_terminate; sig_atomic_t ngx_quit; sig_atomic_t ngx_debug_quit; @@ -142,10 +143,13 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) for ( ;; ) { if (delay) { - delay *= 2; + if (ngx_sigalrm) { + delay *= 2; + ngx_sigalrm = 0; + } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, - "temination cycle: %d", delay); + "termination cycle: %d", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; @@ -514,8 +518,7 @@ ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo) if (kill(ngx_processes[i].pid, signo) == -1) { err = ngx_errno; ngx_log_error(NGX_LOG_ALERT, cycle->log, err, - "kill(%P, %d) failed", - ngx_processes[i].pid, signo); + "kill(%P, %d) failed", ngx_processes[i].pid, signo); if (err == NGX_ESRCH) { ngx_processes[i].exited = 1; diff --git a/src/os/unix/ngx_process_cycle.h b/src/os/unix/ngx_process_cycle.h index 8ef0c3154..f46ad463f 100644 --- a/src/os/unix/ngx_process_cycle.h +++ b/src/os/unix/ngx_process_cycle.h @@ -46,6 +46,7 @@ extern ngx_uint_t ngx_exiting; extern sig_atomic_t ngx_reap; extern sig_atomic_t ngx_sigio; +extern sig_atomic_t ngx_sigalrm; extern sig_atomic_t ngx_quit; extern sig_atomic_t ngx_debug_quit; extern sig_atomic_t ngx_terminate; diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h index 663f26570..ae8212d8a 100644 --- a/src/os/unix/ngx_solaris_config.h +++ b/src/os/unix/ngx_solaris_config.h @@ -62,16 +62,6 @@ #endif -#if (NGX_HAVE_SENDFILE) -#include <sys/sendfile.h> -#endif - - -#if (NGX_HAVE_AIO) -#include <aio.h> -#endif - - #if (NGX_HAVE_DEVPOLL) #include <sys/ioctl.h> #include <sys/devpoll.h> @@ -83,6 +73,11 @@ #endif +#if (NGX_HAVE_SENDFILE) +#include <sys/sendfile.h> +#endif + + #define NGX_LISTEN_BACKLOG 511 |