You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ic...@apache.org on 2017/07/06 08:15:27 UTC
svn commit: r1800978 - in /httpd/httpd/trunk: CHANGES
modules/http2/h2_mplx.c modules/http2/h2_mplx.h modules/http2/h2_util.c
modules/http2/h2_util.h modules/http2/h2_version.h
Author: icing
Date: Thu Jul 6 08:15:27 2017
New Revision: 1800978
URL: http://svn.apache.org/viewvc?rev=1800978&view=rev
Log:
On the trunk:
mod_http2: Simplify ready queue, less memory and better performance. Update
mod_http2 version to 1.10.7.
Modified:
httpd/httpd/trunk/CHANGES
httpd/httpd/trunk/modules/http2/h2_mplx.c
httpd/httpd/trunk/modules/http2/h2_mplx.h
httpd/httpd/trunk/modules/http2/h2_util.c
httpd/httpd/trunk/modules/http2/h2_util.h
httpd/httpd/trunk/modules/http2/h2_version.h
Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1800978&r1=1800977&r2=1800978&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Thu Jul 6 08:15:27 2017
@@ -1,8 +1,8 @@
-*- coding: utf-8 -*-
Changes with Apache 2.5.0
- *) mod_http2: disable and give warning when mpm_prefork is encountered. The server will
- continue to work, but HTTP/2 will no longer be negotiated. [Stefan Eissing]
+ *) mod_http2: Simplify ready queue, less memory and better performance. Update
+ mod_http2 version to 1.10.7. [Stefan Eissing]
*) htpasswd / htdigest: Do not apply the strict permissions of the temporary
passwd file to a possibly existing passwd file. PR 61240. [Ruediger Pluem]
Modified: httpd/httpd/trunk/modules/http2/h2_mplx.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_mplx.c?rev=1800978&r1=1800977&r2=1800978&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_mplx.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_mplx.c Thu Jul 6 08:15:27 2017
@@ -125,9 +125,9 @@ static void stream_cleanup(h2_mplx *m, h
h2_stream_cleanup(stream);
- h2_iq_remove(m->q, stream->id);
- h2_fifo_remove(m->readyq, stream);
h2_ihash_remove(m->streams, stream->id);
+ h2_iq_remove(m->q, stream->id);
+ h2_ififo_remove(m->readyq, stream->id);
h2_ihash_add(m->shold, stream);
if (!stream->task || stream->task->worker_done) {
@@ -218,7 +218,7 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr
m->spurge = h2_ihash_create(m->pool, offsetof(h2_stream,id));
m->q = h2_iq_create(m->pool, m->max_streams);
- status = h2_fifo_set_create(&m->readyq, m->pool, m->max_streams);
+ status = h2_ififo_set_create(&m->readyq, m->pool, m->max_streams);
if (status != APR_SUCCESS) {
apr_pool_destroy(m->pool);
return NULL;
@@ -626,7 +626,7 @@ apr_status_t h2_mplx_out_trywait(h2_mplx
static void check_data_for(h2_mplx *m, h2_stream *stream, int lock)
{
- if (h2_fifo_push(m->readyq, stream) == APR_SUCCESS) {
+ if (h2_ififo_push(m->readyq, stream->id) == APR_SUCCESS) {
apr_atomic_set32(&m->event_pending, 1);
H2_MPLX_ENTER_MAYBE(m, lock);
if (m->added_output) {
@@ -1232,7 +1232,7 @@ apr_status_t h2_mplx_dispatch_master_eve
void *on_ctx)
{
h2_stream *stream;
- int n;
+ int n, id;
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c,
"h2_mplx(%ld): dispatch events", m->id);
@@ -1242,11 +1242,14 @@ apr_status_t h2_mplx_dispatch_master_eve
h2_ihash_iter(m->streams, report_consumption_iter, m);
purge_streams(m, 1);
- n = h2_fifo_count(m->readyq);
+ n = h2_ififo_count(m->readyq);
while (n > 0
- && (h2_fifo_try_pull(m->readyq, (void**)&stream) == APR_SUCCESS)) {
+ && (h2_ififo_try_pull(m->readyq, &id) == APR_SUCCESS)) {
--n;
- on_resume(on_ctx, stream);
+ stream = h2_ihash_get(m->streams, id);
+ if (stream) {
+ on_resume(on_ctx, stream);
+ }
}
return APR_SUCCESS;
@@ -1267,7 +1270,7 @@ int h2_mplx_awaits_data(h2_mplx *m)
if (h2_ihash_empty(m->streams)) {
waiting = 0;
}
- else if (!m->tasks_active && !h2_fifo_count(m->readyq)
+ else if (!m->tasks_active && !h2_ififo_count(m->readyq)
&& h2_iq_empty(m->q)) {
waiting = 0;
}
Modified: httpd/httpd/trunk/modules/http2/h2_mplx.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_mplx.h?rev=1800978&r1=1800977&r2=1800978&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_mplx.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_mplx.h Thu Jul 6 08:15:27 2017
@@ -69,7 +69,7 @@ struct h2_mplx {
struct h2_ihash_t *spurge; /* all streams done, ready for destroy */
struct h2_iqueue *q; /* all stream ids that need to be started */
- struct h2_fifo *readyq; /* all streams ready for output */
+ struct h2_ififo *readyq; /* all stream ids ready for output */
struct h2_ihash_t *redo_tasks; /* all tasks that need to be redone */
Modified: httpd/httpd/trunk/modules/http2/h2_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_util.c?rev=1800978&r1=1800977&r2=1800978&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_util.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_util.c Thu Jul 6 08:15:27 2017
@@ -881,6 +881,313 @@ apr_status_t h2_fifo_remove(h2_fifo *fif
return rv;
}
+/*******************************************************************************
+ * FIFO int queue
+ ******************************************************************************/
+
+struct h2_ififo {
+ int *elems;
+ int nelems;
+ int set;
+ int head;
+ int count;
+ int aborted;
+ apr_thread_mutex_t *lock;
+ apr_thread_cond_t *not_empty;
+ apr_thread_cond_t *not_full;
+};
+
+static int inth_index(h2_ififo *fifo, int n)
+{
+ return (fifo->head + n) % fifo->nelems;
+}
+
+static apr_status_t ififo_destroy(void *data)
+{
+ h2_ififo *fifo = data;
+
+ apr_thread_cond_destroy(fifo->not_empty);
+ apr_thread_cond_destroy(fifo->not_full);
+ apr_thread_mutex_destroy(fifo->lock);
+
+ return APR_SUCCESS;
+}
+
+static int iindex_of(h2_ififo *fifo, int id)
+{
+ int i;
+
+ for (i = 0; i < fifo->count; ++i) {
+ if (id == fifo->elems[inth_index(fifo, i)]) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static apr_status_t icreate_int(h2_ififo **pfifo, apr_pool_t *pool,
+ int capacity, int as_set)
+{
+ apr_status_t rv;
+ h2_ififo *fifo;
+
+ fifo = apr_pcalloc(pool, sizeof(*fifo));
+ if (fifo == NULL) {
+ return APR_ENOMEM;
+ }
+
+ rv = apr_thread_mutex_create(&fifo->lock,
+ APR_THREAD_MUTEX_UNNESTED, pool);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_thread_cond_create(&fifo->not_empty, pool);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_thread_cond_create(&fifo->not_full, pool);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ fifo->elems = apr_pcalloc(pool, capacity * sizeof(int));
+ if (fifo->elems == NULL) {
+ return APR_ENOMEM;
+ }
+ fifo->nelems = capacity;
+ fifo->set = as_set;
+
+ *pfifo = fifo;
+ apr_pool_cleanup_register(pool, fifo, ififo_destroy, apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+}
+
+apr_status_t h2_ififo_create(h2_ififo **pfifo, apr_pool_t *pool, int capacity)
+{
+ return icreate_int(pfifo, pool, capacity, 0);
+}
+
+apr_status_t h2_ififo_set_create(h2_ififo **pfifo, apr_pool_t *pool, int capacity)
+{
+ return icreate_int(pfifo, pool, capacity, 1);
+}
+
+apr_status_t h2_ififo_term(h2_ififo *fifo)
+{
+ apr_status_t rv;
+ if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
+ fifo->aborted = 1;
+ apr_thread_mutex_unlock(fifo->lock);
+ }
+ return rv;
+}
+
+apr_status_t h2_ififo_interrupt(h2_ififo *fifo)
+{
+ apr_status_t rv;
+ if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
+ apr_thread_cond_broadcast(fifo->not_empty);
+ apr_thread_cond_broadcast(fifo->not_full);
+ apr_thread_mutex_unlock(fifo->lock);
+ }
+ return rv;
+}
+
+int h2_ififo_count(h2_ififo *fifo)
+{
+ return fifo->count;
+}
+
+static apr_status_t icheck_not_empty(h2_ififo *fifo, int block)
+{
+ while (fifo->count == 0) {
+ if (!block) {
+ return APR_EAGAIN;
+ }
+ if (fifo->aborted) {
+ return APR_EOF;
+ }
+ apr_thread_cond_wait(fifo->not_empty, fifo->lock);
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t ififo_push_int(h2_ififo *fifo, int id, int block)
+{
+ if (fifo->aborted) {
+ return APR_EOF;
+ }
+
+ if (fifo->set && iindex_of(fifo, id) >= 0) {
+ /* set mode, elem already member */
+ return APR_EEXIST;
+ }
+ else if (fifo->count == fifo->nelems) {
+ if (block) {
+ while (fifo->count == fifo->nelems) {
+ if (fifo->aborted) {
+ return APR_EOF;
+ }
+ apr_thread_cond_wait(fifo->not_full, fifo->lock);
+ }
+ }
+ else {
+ return APR_EAGAIN;
+ }
+ }
+
+ ap_assert(fifo->count < fifo->nelems);
+ fifo->elems[inth_index(fifo, fifo->count)] = id;
+ ++fifo->count;
+ if (fifo->count == 1) {
+ apr_thread_cond_broadcast(fifo->not_empty);
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t ififo_push(h2_ififo *fifo, int id, int block)
+{
+ apr_status_t rv;
+
+ if (fifo->aborted) {
+ return APR_EOF;
+ }
+
+ if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
+ rv = ififo_push_int(fifo, id, block);
+ apr_thread_mutex_unlock(fifo->lock);
+ }
+ return rv;
+}
+
+apr_status_t h2_ififo_push(h2_ififo *fifo, int id)
+{
+ return ififo_push(fifo, id, 1);
+}
+
+apr_status_t h2_ififo_try_push(h2_ififo *fifo, int id)
+{
+ return ififo_push(fifo, id, 0);
+}
+
+static apr_status_t ipull_head(h2_ififo *fifo, int *pi, int block)
+{
+ apr_status_t rv;
+
+ if ((rv = icheck_not_empty(fifo, block)) != APR_SUCCESS) {
+ *pi = 0;
+ return rv;
+ }
+ *pi = fifo->elems[fifo->head];
+ --fifo->count;
+ if (fifo->count > 0) {
+ fifo->head = inth_index(fifo, 1);
+ if (fifo->count+1 == fifo->nelems) {
+ apr_thread_cond_broadcast(fifo->not_full);
+ }
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t ififo_pull(h2_ififo *fifo, int *pi, int block)
+{
+ apr_status_t rv;
+
+ if (fifo->aborted) {
+ return APR_EOF;
+ }
+
+ if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
+ rv = ipull_head(fifo, pi, block);
+ apr_thread_mutex_unlock(fifo->lock);
+ }
+ return rv;
+}
+
+apr_status_t h2_ififo_pull(h2_ififo *fifo, int *pi)
+{
+ return ififo_pull(fifo, pi, 1);
+}
+
+apr_status_t h2_ififo_try_pull(h2_ififo *fifo, int *pi)
+{
+ return ififo_pull(fifo, pi, 0);
+}
+
+static apr_status_t ififo_peek(h2_ififo *fifo, h2_ififo_peek_fn *fn, void *ctx, int block)
+{
+ apr_status_t rv;
+ int id;
+
+ if (fifo->aborted) {
+ return APR_EOF;
+ }
+
+ if (APR_SUCCESS == (rv = apr_thread_mutex_lock(fifo->lock))) {
+ if (APR_SUCCESS == (rv = ipull_head(fifo, &id, block))) {
+ switch (fn(id, ctx)) {
+ case H2_FIFO_OP_PULL:
+ break;
+ case H2_FIFO_OP_REPUSH:
+ rv = ififo_push_int(fifo, id, block);
+ break;
+ }
+ }
+ apr_thread_mutex_unlock(fifo->lock);
+ }
+ return rv;
+}
+
+apr_status_t h2_ififo_peek(h2_ififo *fifo, h2_ififo_peek_fn *fn, void *ctx)
+{
+ return ififo_peek(fifo, fn, ctx, 1);
+}
+
+apr_status_t h2_ififo_try_peek(h2_ififo *fifo, h2_ififo_peek_fn *fn, void *ctx)
+{
+ return ififo_peek(fifo, fn, ctx, 0);
+}
+
+apr_status_t h2_ififo_remove(h2_ififo *fifo, int id)
+{
+ apr_status_t rv;
+
+ if (fifo->aborted) {
+ return APR_EOF;
+ }
+
+ if ((rv = apr_thread_mutex_lock(fifo->lock)) == APR_SUCCESS) {
+ int i, rc;
+ int e;
+
+ rc = 0;
+ for (i = 0; i < fifo->count; ++i) {
+ e = fifo->elems[inth_index(fifo, i)];
+ if (e == id) {
+ ++rc;
+ }
+ else if (rc) {
+ fifo->elems[inth_index(fifo, i-rc)] = e;
+ }
+ }
+ if (rc) {
+ fifo->count -= rc;
+ if (fifo->count + rc == fifo->nelems) {
+ apr_thread_cond_broadcast(fifo->not_full);
+ }
+ rv = APR_SUCCESS;
+ }
+ else {
+ rv = APR_EAGAIN;
+ }
+
+ apr_thread_mutex_unlock(fifo->lock);
+ }
+ return rv;
+}
/*******************************************************************************
* h2_util for apt_table_t
Modified: httpd/httpd/trunk/modules/http2/h2_util.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_util.h?rev=1800978&r1=1800977&r2=1800978&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_util.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_util.h Thu Jul 6 08:15:27 2017
@@ -185,7 +185,7 @@ size_t h2_iq_mshift(h2_iqueue *q, int *p
int h2_iq_contains(h2_iqueue *q, int sid);
/*******************************************************************************
- * FIFO queue
+ * FIFO queue (void* elements)
******************************************************************************/
/**
@@ -256,6 +256,72 @@ apr_status_t h2_fifo_try_peek(h2_fifo *f
apr_status_t h2_fifo_remove(h2_fifo *fifo, void *elem);
/*******************************************************************************
+ * iFIFO queue (int elements)
+ ******************************************************************************/
+
+/**
+ * A thread-safe FIFO queue with some extra bells and whistles, if you
+ * do not need anything special, better use 'apr_queue'.
+ */
+typedef struct h2_ififo h2_ififo;
+
+/**
+ * Create a FIFO queue that can hold up to capacity int. ints can
+ * appear several times.
+ */
+apr_status_t h2_ififo_create(h2_ififo **pfifo, apr_pool_t *pool, int capacity);
+
+/**
+ * Create a FIFO set that can hold up to capacity integers. Ints only
+ * appear once. Pushing an int already present does not change the
+ * queue and is successful.
+ */
+apr_status_t h2_ififo_set_create(h2_ififo **pfifo, apr_pool_t *pool, int capacity);
+
+apr_status_t h2_ififo_term(h2_ififo *fifo);
+apr_status_t h2_ififo_interrupt(h2_ififo *fifo);
+
+int h2_ififo_count(h2_ififo *fifo);
+
+/**
+ * Push an int into the queue. Blocks if there is no capacity left.
+ *
+ * @param fifo the FIFO queue
+ * @param id the int to push
+ * @return APR_SUCCESS on push, APR_EAGAIN on try_push on a full queue,
+ * APR_EEXIST when in set mode and elem already there.
+ */
+apr_status_t h2_ififo_push(h2_ififo *fifo, int id);
+apr_status_t h2_ififo_try_push(h2_ififo *fifo, int id);
+
+apr_status_t h2_ififo_pull(h2_ififo *fifo, int *pi);
+apr_status_t h2_ififo_try_pull(h2_ififo *fifo, int *pi);
+
+typedef h2_fifo_op_t h2_ififo_peek_fn(int head, void *ctx);
+
+/**
+ * Call given function on the head of the queue, once it exists, and
+ * perform the returned operation on it. The queue will hold its lock during
+ * this time, so no other operations on the queue are possible.
+ * @param fifo the queue to peek at
+ * @param fn the function to call on the head, once available
+ * @param ctx context to pass in call to function
+ */
+apr_status_t h2_ififo_peek(h2_ififo *fifo, h2_ififo_peek_fn *fn, void *ctx);
+
+/**
+ * Non-blocking version of h2_fifo_peek.
+ */
+apr_status_t h2_ififo_try_peek(h2_ififo *fifo, h2_ififo_peek_fn *fn, void *ctx);
+
+/**
+ * Remove the integer from the queue, will remove multiple appearances.
+ * @param id the integer to remove
+ * @return APR_SUCCESS iff > 0 ints were removed, APR_EAGAIN otherwise.
+ */
+apr_status_t h2_ififo_remove(h2_ififo *fifo, int id);
+
+/*******************************************************************************
* common helpers
******************************************************************************/
/* h2_log2(n) iff n is a power of 2 */
Modified: httpd/httpd/trunk/modules/http2/h2_version.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_version.h?rev=1800978&r1=1800977&r2=1800978&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_version.h (original)
+++ httpd/httpd/trunk/modules/http2/h2_version.h Thu Jul 6 08:15:27 2017
@@ -26,7 +26,7 @@
* @macro
* Version number of the http2 module as c string
*/
-#define MOD_HTTP2_VERSION "1.10.7-DEV"
+#define MOD_HTTP2_VERSION "1.10.7"
/**
* @macro