diff options
| author | Valentin Bartenev <vbart@nginx.com> | 2015-03-14 17:37:25 +0300 |
|---|---|---|
| committer | Valentin Bartenev <vbart@nginx.com> | 2015-03-14 17:37:25 +0300 |
| commit | a7ad493aa67c5f5204afbe50a42108d9e5b07c31 (patch) | |
| tree | 0c2277cd365146cfcbfc28ed8298620bcc7bf5cb /src/http | |
| parent | 547c8f601f80c4dbdd16562fec3cf947581b300a (diff) | |
| download | nginx-a7ad493aa67c5f5204afbe50a42108d9e5b07c31.tar.gz nginx-a7ad493aa67c5f5204afbe50a42108d9e5b07c31.tar.bz2 | |
Added support for offloading read() in thread pools.
Diffstat (limited to 'src/http')
| -rw-r--r-- | src/http/ngx_http_copy_filter_module.c | 76 | ||||
| -rw-r--r-- | src/http/ngx_http_core_module.c | 74 | ||||
| -rw-r--r-- | src/http/ngx_http_core_module.h | 10 | ||||
| -rw-r--r-- | src/http/ngx_http_file_cache.c | 2 |
4 files changed, 159 insertions, 3 deletions
diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c index 8e6a199a7..0f908add7 100644 --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -24,6 +24,11 @@ static ssize_t ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file); static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev); #endif #endif +#if (NGX_THREADS) +static ngx_int_t ngx_http_copy_thread_handler(ngx_thread_task_t *task, + ngx_file_t *file); +static void ngx_http_copy_thread_event_handler(ngx_event_t *ev); +#endif static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf); static char *ngx_http_copy_filter_merge_conf(ngx_conf_t *cf, @@ -121,7 +126,7 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in) ctx->filter_ctx = r; #if (NGX_HAVE_FILE_AIO) - if (ngx_file_aio && clcf->aio) { + if (ngx_file_aio && clcf->aio == NGX_HTTP_AIO_ON) { ctx->aio_handler = ngx_http_copy_aio_handler; #if (NGX_HAVE_AIO_SENDFILE) ctx->aio_preload = ngx_http_copy_aio_sendfile_preload; @@ -129,12 +134,18 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in) } #endif +#if (NGX_THREADS) + if (clcf->aio == NGX_HTTP_AIO_THREADS) { + ctx->thread_handler = ngx_http_copy_thread_handler; + } +#endif + if (in && in->buf && ngx_buf_size(in->buf)) { r->request_output = 1; } } -#if (NGX_HAVE_FILE_AIO) +#if (NGX_HAVE_FILE_AIO || NGX_THREADS) ctx->aio = r->aio; #endif @@ -233,6 +244,67 @@ ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev) #endif +#if (NGX_THREADS) + +static ngx_int_t +ngx_http_copy_thread_handler(ngx_thread_task_t *task, ngx_file_t *file) +{ + ngx_str_t name; + ngx_thread_pool_t *tp; + ngx_http_request_t *r; + ngx_http_core_loc_conf_t *clcf; + + r = file->thread_ctx; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + tp = clcf->thread_pool; + + if (tp == NULL) { + if (ngx_http_complex_value(r, clcf->thread_pool_value, &name) + != NGX_OK) + { + return NGX_ERROR; + } + + tp = ngx_thread_pool_get((ngx_cycle_t *) ngx_cycle, &name); + + if (tp == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "thread pool \"%V\" not found", &name); + return NGX_ERROR; + } + } + + task->event.data = r; + task->event.handler = ngx_http_copy_thread_event_handler; + + if (ngx_thread_task_post(tp, task) != NGX_OK) { + return NGX_ERROR; + } + + r->main->blocked++; + r->aio = 1; + + return NGX_OK; +} + + +static void +ngx_http_copy_thread_event_handler(ngx_event_t *ev) +{ + ngx_http_request_t *r; + + r = ev->data; + + r->main->blocked--; + r->aio = 0; + + r->connection->write->handler(r->connection->write); +} + +#endif + + static void * ngx_http_copy_filter_create_conf(ngx_conf_t *cf) { diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index be39accb8..0be601ee3 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -3624,6 +3624,10 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) clcf->sendfile = NGX_CONF_UNSET; clcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE; clcf->aio = NGX_CONF_UNSET; +#if (NGX_THREADS) + clcf->thread_pool = NGX_CONF_UNSET_PTR; + clcf->thread_pool_value = NGX_CONF_UNSET_PTR; +#endif clcf->read_ahead = NGX_CONF_UNSET_SIZE; clcf->directio = NGX_CONF_UNSET; clcf->directio_alignment = NGX_CONF_UNSET; @@ -3839,7 +3843,14 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); ngx_conf_merge_size_value(conf->sendfile_max_chunk, prev->sendfile_max_chunk, 0); +#if (NGX_HAVE_FILE_AIO || NGX_THREADS) ngx_conf_merge_value(conf->aio, prev->aio, NGX_HTTP_AIO_OFF); +#endif +#if (NGX_THREADS) + ngx_conf_merge_ptr_value(conf->thread_pool, prev->thread_pool, NULL); + ngx_conf_merge_ptr_value(conf->thread_pool_value, prev->thread_pool_value, + NULL); +#endif ngx_conf_merge_size_value(conf->read_ahead, prev->read_ahead, 0); ngx_conf_merge_off_value(conf->directio, prev->directio, NGX_OPEN_FILE_DIRECTIO_OFF); @@ -4644,6 +4655,11 @@ ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return "is duplicate"; } +#if (NGX_THREADS) + clcf->thread_pool = NULL; + clcf->thread_pool_value = NULL; +#endif + value = cf->args->elts; if (ngx_strcmp(value[1].data, "off") == 0) { @@ -4676,6 +4692,64 @@ ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #endif + if (ngx_strncmp(value[1].data, "threads", 7) == 0 + && (value[1].len == 7 || value[1].data[7] == '=')) + { +#if (NGX_THREADS) + ngx_str_t name; + ngx_thread_pool_t *tp; + ngx_http_complex_value_t cv; + ngx_http_compile_complex_value_t ccv; + + clcf->aio = NGX_HTTP_AIO_THREADS; + + if (value[1].len >= 8) { + name.len = value[1].len - 8; + name.data = value[1].data + 8; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &name; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths != NULL) { + clcf->thread_pool_value = ngx_palloc(cf->pool, + sizeof(ngx_http_complex_value_t)); + if (clcf->thread_pool_value == NULL) { + return NGX_CONF_ERROR; + } + + *clcf->thread_pool_value = cv; + + return NGX_CONF_OK; + } + + tp = ngx_thread_pool_add(cf, &name); + + } else { + tp = ngx_thread_pool_add(cf, NULL); + } + + if (tp == NULL) { + return NGX_CONF_ERROR; + } + + clcf->thread_pool = tp; + + return NGX_CONF_OK; +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"aio threads\" " + "is unsupported on this platform"); + return NGX_CONF_ERROR; +#endif + } + return "invalid value"; } diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index de7d4edcd..ac5ca4eab 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -13,6 +13,10 @@ #include <ngx_core.h> #include <ngx_http.h> +#if (NGX_THREADS) +#include <ngx_thread_pool.h> +#endif + #define NGX_HTTP_GZIP_PROXIED_OFF 0x0002 #define NGX_HTTP_GZIP_PROXIED_EXPIRED 0x0004 @@ -27,6 +31,7 @@ #define NGX_HTTP_AIO_OFF 0 #define NGX_HTTP_AIO_ON 1 +#define NGX_HTTP_AIO_THREADS 2 #define NGX_HTTP_SATISFY_ALL 0 @@ -421,6 +426,11 @@ struct ngx_http_core_loc_conf_s { #endif #endif +#if (NGX_THREADS) + ngx_thread_pool_t *thread_pool; + ngx_http_complex_value_t *thread_pool_value; +#endif + #if (NGX_HAVE_OPENAT) ngx_uint_t disable_symlinks; /* disable_symlinks */ ngx_http_complex_value_t *disable_symlinks_from; diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index 7f289ed33..52cbdda83 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -646,7 +646,7 @@ ngx_http_file_cache_aio_read(ngx_http_request_t *r, ngx_http_cache_t *c) clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (!clcf->aio) { + if (clcf->aio != NGX_HTTP_AIO_ON) { goto noaio; } |
