[svn:mod_parrot] r501 - in mod_parrot/trunk: include src
[email protected] Sun, 23 Nov 2008 09:52:06 -0800 (PST)
| Newsgroups | perl.cvs.mod_parrot |
|---|---|
| Message-ID | <[email protected]> |
Author: jhorwitz
Date: Sun Nov 23 09:52:05 2008
New Revision: 501
Modified:
mod_parrot/trunk/include/mod_parrot.h
mod_parrot/trunk/src/context.c
mod_parrot/trunk/src/mod_parrot.c
Log:
use connection ID to bind contexts to connections. this guarantees all phases
of a request will use the same context/interpreter in a threaded MPM.
Modified: mod_parrot/trunk/include/mod_parrot.h
==============================================================================
--- mod_parrot/trunk/include/mod_parrot.h (original)
+++ mod_parrot/trunk/include/mod_parrot.h Sun Nov 23 09:52:05 2008
@@ -37,6 +37,7 @@
#define MODPARROT_CTX_ISLOCKED(x) (x->locked == 1)
#define MODPARROT_CTX_LOCK(x) (x->locked = 1)
#define MODPARROT_CTX_UNLOCK(x) (x->locked = 0)
+#define MP_CTX_ANY (-1)
/* we need to move things around to avoid this */
#include "modparrot_config.h"
@@ -57,6 +58,7 @@
conn_rec *c;
void *csd;
int module_index;
+ int pool_index;
};
typedef struct modparrot_context modparrot_context;
@@ -75,7 +77,7 @@
Parrot_PMC get_sub_pmc(Parrot_Interp , char *, char *);
apr_array_header_t *mp_ctx_pool_init(apr_pool_t *, Parrot_Interp, int);
void mp_ctx_pool_destroy(apr_array_header_t *);
-modparrot_context *reserve_ctx(apr_array_header_t *);
+modparrot_context *reserve_ctx(apr_array_header_t *, int index);
void release_ctx(modparrot_context *);
modparrot_context *get_interp_ctx(Parrot_Interp);
void set_interp_ctx(Parrot_Interp, modparrot_context *);
Modified: mod_parrot/trunk/src/context.c
==============================================================================
--- mod_parrot/trunk/src/context.c (original)
+++ mod_parrot/trunk/src/context.c Sun Nov 23 09:52:05 2008
@@ -53,6 +53,7 @@
ctx = (*(modparrot_context **)apr_array_push(ctx_pool) =
(modparrot_context *)apr_pcalloc(p, sizeof(modparrot_context)));
ctx->parent_interp = parent_interp;
+ ctx->pool_index = -1;
}
#ifdef MPM_IS_THREADED
@@ -91,38 +92,52 @@
}
/* finds and reserves a context for use by a handler */
-modparrot_context *reserve_ctx(apr_array_header_t *ctx_pool)
+modparrot_context *reserve_ctx(apr_array_header_t *ctx_pool, int index)
{
#ifdef MPM_IS_THREADED
int i;
#endif /* MPM_IS_THREADED */
- modparrot_context *ctx;
+ modparrot_context *ctxp = (modparrot_context *)NULL;
if (!ctx_pool) return NULL;
#ifdef MPM_IS_THREADED
apr_thread_mutex_lock(ctx_pool_mutex);
- for (i = 0; i < ctx_pool->nelts; i++) {
- ctx = ((modparrot_context **)ctx_pool->elts)[i];
- if (MODPARROT_CTX_ISLOCKED(ctx)) continue;
- MODPARROT_CTX_LOCK(ctx);
- apr_thread_mutex_unlock(ctx_pool_mutex);
- return(ctx);
+ if (index == MP_CTX_ANY) {
+ for (i = 0; i < ctx_pool->nelts; i++) {
+ modparrot_context *c;
+ c = ((modparrot_context **)ctx_pool->elts)[i];
+ if (MODPARROT_CTX_ISLOCKED(c)) continue;
+ MODPARROT_CTX_LOCK(c);
+ ctxp = c;
+ ctxp->pool_index = i;
+ break;
+ }
+ }
+ else {
+ if (ctxp = ((modparrot_context **)ctx_pool->elts)[index]) {
+ if (MODPARROT_CTX_ISLOCKED(ctxp)) {
+ ctxp = NULL;
+ }
+ else {
+ MODPARROT_CTX_LOCK(ctxp);
+ ctxp->pool_index = index;
+ }
+ }
}
apr_thread_mutex_unlock(ctx_pool_mutex);
-
- /* XXX should wait for free context here instead of bailing */
- return (modparrot_context *)NULL;
#else /* MPM_IS_THREADED */
- ctx = ((modparrot_context **)ctx_pool->elts)[0];
- MODPARROT_CTX_LOCK(ctx); /* no threads here, just for consistency */
- return ctx;
+ ctxp = ((modparrot_context **)ctx_pool->elts)[0];
+ ctxp->pool_index = 0;
+ MODPARROT_CTX_LOCK(ctxp); /* no threads here, just for consistency */
#endif /* MPM_IS_THREADED */
+ return(ctxp);
}
/* releases a context back into the pool of available contexts */
-void release_ctx(modparrot_context *ctx)
+void release_ctx(modparrot_context *ctxp)
{
- MODPARROT_CTX_UNLOCK(ctx);
+ ctxp->pool_index = -1;
+ MODPARROT_CTX_UNLOCK(ctxp);
}
void set_interp_ctx(Parrot_Interp interp, modparrot_context *ctx)
Modified: mod_parrot/trunk/src/mod_parrot.c
==============================================================================
--- mod_parrot/trunk/src/mod_parrot.c (original)
+++ mod_parrot/trunk/src/mod_parrot.c Sun Nov 23 09:52:05 2008
@@ -27,6 +27,7 @@
#include "http_core.h"
#include "http_connection.h"
#include "http_main.h"
+#include "ap_mpm.h"
#include "parrot/parrot.h"
#include "parrot/embed.h"
@@ -40,6 +41,12 @@
#define NEXT_HANDLER_MODULE(x) (mpcfg->handler_modules[x] ? ((module **)mpcfg->module_array->elts)[((int *)mpcfg->handler_modules[x]->elts)[++(ctxp->module_index)]] : NULL);
+#ifdef MPM_IS_THREADED
+#define CONN_INDEX(c) (c->id % max_threads)
+#else
+#define CONN_INDEX(c) MP_CTX_ANY
+#endif
+
/* declare our module */
extern module AP_MODULE_DECLARE_DATA parrot_module;
@@ -52,6 +59,17 @@
/* have we started? this can be global since it's written to at startup */
int mp_is_started = 0;
+/* thread info */
+int hard_thread_limit, max_threads;
+
+/* maps connection ID to a context so we can maintain state between phases */
+int *conn_ctx;
+
+#ifdef MPM_IS_THREADED
+apr_thread_mutex_t *ctx_pool_mutex;
+apr_thread_mutex_t *conn_ctx_mutex;
+#endif /* MPM_IS_THREADED */
+
void modparrot_load_file(Parrot_Interp interp, server_rec *s, const char *file)
{
int ret;
@@ -118,15 +136,29 @@
return(interp);
}
-static modparrot_context *init_ctx(server_rec *s)
+static modparrot_context *init_ctx(server_rec *s, conn_rec *c)
{
Parrot_Interp interp;
modparrot_context *ctxp;
modparrot_srv_config *cfg;
+ int conn_idx, ctx_idx;
cfg = ap_get_module_config(s->module_config, &parrot_module);
- if ((ctxp = reserve_ctx(cfg->ctx_pool))) {
+#ifdef MPM_IS_THREADED
+ if (c) {
+ conn_idx = c->id % max_threads;
+ ctx_idx = conn_ctx[conn_idx];
+ }
+ else {
+ conn_idx = -1; /* unused */
+ ctx_idx = MP_CTX_ANY;
+ }
+#else /* MPM_IS_THREADED */
+ ctx_idx = MP_CTX_ANY;
+#endif /* MPM_IS_THREADED */
+
+ if ((ctxp = reserve_ctx(cfg->ctx_pool, ctx_idx))) {
if (!ctxp->interp) {
if (!(interp = modparrot_init(ctxp, s))) {
MPLOG_ERROR(s,
@@ -139,6 +171,13 @@
interp = ctxp->interp;
}
+#ifdef MPM_IS_THREADED
+ /* if we're in a connection, remember this context for future phases */
+ if (c) {
+ conn_ctx[conn_idx] = ctxp->pool_index;
+ }
+#endif /* MPM_IS_THREADED */
+
/* usually set s in a hook, but need it here for the config phase */
ctxp->s = s;
}
@@ -166,7 +205,7 @@
}
}
- if ((ctxp = init_ctx(s))) {
+ if ((ctxp = init_ctx(s, NULL))) {
mp_is_started = 1;
}
else {
@@ -242,7 +281,7 @@
modparrot_context *ctxp;
/* initialize context */
- if (!(ctxp = init_ctx(r->server))) {
+ if (!(ctxp = init_ctx(r->server, r->connection))) {
MPLOG_ERROR(r->server, "context initialization failed");
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -261,7 +300,7 @@
modparrot_context *ctxp;
/* initialize context */
- if (!(ctxp = init_ctx(c->base_server))) {
+ if (!(ctxp = init_ctx(c->base_server, c))) {
MPLOG_ERROR(c->base_server, "context initialization failed");
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -287,7 +326,7 @@
int status, m;
/* initialize context */
- if (!(ctxp = init_ctx(r->server))) {
+ if (!(ctxp = init_ctx(r->server, r->connection))) {
MPLOG_ERROR(r->server, "context initialization failed");
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -304,7 +343,7 @@
/* get HLL config */
/* can't use NEXT_HANDLER_MODULE here since cleanup handlers are LIFO */
- modp = ((module **)mpcfg->module_array->elts)[mpcfg->handler_modules[MP_HOOK_CLEANUP]->elts[ctxp->module_index]];
+ modp = ((module **)mpcfg->module_array->elts)[mpcfg->handler_modules[MP_HOOK_CLEANUP]->elts[m]];
minfo = (modparrot_module_info *)modp->dynamic_load_handle;
/* check for an actual cleanup metahandler sub */
/* XXX we shouldn't really be using get_sub_pmc here... */
@@ -346,7 +385,7 @@
Parrot_PMC sub; \
int status; \
/* initialize context */ \
- if (!(ctxp = init_ctx(r->server))) { \
+ if (!(ctxp = init_ctx(r->server, r->connection))) { \
MPLOG_ERROR(r->server, "context initialization failed"); \
return HTTP_INTERNAL_SERVER_ERROR; \
} \
@@ -410,7 +449,7 @@
int status;
/* initialize context */
- if (!(ctxp = init_ctx(c->base_server))) {
+ if (!(ctxp = init_ctx(c->base_server, c))) {
MPLOG_ERROR(c->base_server, "context initialization failed");
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -447,7 +486,7 @@
modparrot_context *ctxp;
/* initialize context */
- if (!(ctxp = init_ctx(c->base_server))) {
+ if (!(ctxp = init_ctx(c->base_server, c))) {
MPLOG_ERROR(c->base_server, "context initialization failed");
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -472,7 +511,7 @@
int status;
/* initialize context */
- if (!(ctxp = init_ctx(c->base_server))) {
+ if (!(ctxp = init_ctx(c->base_server, c))) {
MPLOG_ERROR(c->base_server, "context initialization failed");
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -509,7 +548,7 @@
modparrot_context *ctxp;
/* initialize context */
- if (!(ctxp = init_ctx(s))) {
+ if (!(ctxp = init_ctx(s, NULL))) {
MPLOG_ERROR(s, "context initialization failed");
return;
}
@@ -517,6 +556,17 @@
/* we're FIRST, so reset the module index */
ctxp->module_index = -1;
+ /* query apache mpm for thread limits */
+#ifdef MPM_IS_THREADED
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &hard_thread_limit);
+ ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads);
+ /* an APR array is overkill for a static array, so alloc it ourselves */
+ conn_ctx = (int *)apr_pcalloc(p, sizeof(int) * max_threads);
+#else /* MPM_IS_THREADED */
+ hard_thread_limit = 1;
+ max_threads = 1;
+#endif /* MPM_IS_THREADED */
+
/* clean up */
release_ctx(ctxp);
}
@@ -532,7 +582,7 @@
int status;
/* initialize context */
- if (!(ctxp = init_ctx(s))) {
+ if (!(ctxp = init_ctx(s, NULL))) {
MPLOG_ERROR(s, "context initialization failed");
return;
}
@@ -567,7 +617,7 @@
modparrot_context *ctxp;
/* initialize context */
- if (!(ctxp = init_ctx(s))) {
+ if (!(ctxp = init_ctx(s, NULL))) {
MPLOG_ERROR(s, "context initialization failed");
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -593,7 +643,7 @@
int status;
/* initialize context */
- if (!(ctxp = init_ctx(s))) {
+ if (!(ctxp = init_ctx(s, NULL))) {
MPLOG_ERROR(s, "context initialization failed");
return HTTP_INTERNAL_SERVER_ERROR;
}
@@ -707,7 +757,7 @@
int status;
/* initialize context */
- if (!(ctxp = init_ctx(s))) {
+ if (!(ctxp = init_ctx(s, NULL))) {
MPLOG_ERROR(s, "context initialization failed");
return HTTP_INTERNAL_SERVER_ERROR;
}