dougm 00/04/14 16:51:59 Added: src/modules/perl modperl_interp.c modperl_interp.h Log: first stab at interpreter pool Revision Changes Path 1.1 modperl-2.0/src/modules/perl/modperl_interp.c Index: modperl_interp.c =================================================================== #include "mod_perl.h" /* * XXX: this is not the most efficent interpreter pool implementation * but it will do for proof-of-concept */ modperl_interp_t *modperl_interp_new(ap_pool_t *p, modperl_interp_t *parent) { modperl_interp_t *interp = (modperl_interp_t *)ap_pcalloc(p, sizeof(*interp)); if (parent) { interp->mip_lock = parent->mip_lock; } fprintf(stderr, "modperl_interp_new: 0x%lx\n", (unsigned long)interp); return interp; } modperl_interp_t *modperl_interp_get(server_rec *s) { MP_dSCFG(s); modperl_interp_t *head, *interp = NULL; modperl_interp_pool_t *mip = scfg->mip; if (!mip->head) { /* * XXX: no interp pool * need to lock the interpreter during callbacks * unless mpm is prefork */ fprintf(stderr, "modperl_interp_get: no pool, returning parent\n"); return mip->parent; } ap_lock(mip->mip_lock); head = mip->head; fprintf(stderr, "modperl_interp_get: head == 0x%lx, parent == 0x%lx\n", (unsigned long)head, (unsigned long)mip->parent); while (head) { if (!MpInterpIN_USE(head)) { interp = head; fprintf(stderr, "modperl_interp_get: selected 0x%lx\n", (unsigned long)interp); #ifdef _PTHREAD_H fprintf(stderr, "pthread_self == 0x%lx\n", (unsigned long)pthread_self()); #endif MpInterpIN_USE_On(interp); MpInterpPUTBACK_On(interp); break; } else { fprintf(stderr, "modperl_interp_get: 0x%lx in use\n", (unsigned long)head); head = head->next; } } ap_unlock(mip->mip_lock); if (!interp) { /* * XXX: options * -block until one is available * -clone a new Perl * - ... */ } return interp; } ap_status_t modperl_interp_pool_destroy(void *data) { modperl_interp_pool_t *mip = (modperl_interp_pool_t *)data; while (mip->head) { dTHXa(mip->head->perl); fprintf(stderr, "modperl_interp_pool_destroy: head == 0x%lx", (unsigned long)mip->head); if (MpInterpIN_USE(mip->head)) { fprintf(stderr, " *error - still in use!*"); } fprintf(stderr, "\n"); PL_perl_destruct_level = 2; perl_destruct(mip->head->perl); perl_free(mip->head->perl); mip->head->perl = NULL; mip->head = mip->head->next; } fprintf(stderr, "modperl_interp_pool_destroy: parent == 0x%lx\n", (unsigned long)mip->parent); perl_destruct(mip->parent->perl); perl_free(mip->parent->perl); mip->parent->perl = NULL; ap_destroy_lock(mip->mip_lock); return APR_SUCCESS; } void modperl_interp_pool_init(server_rec *s, ap_pool_t *p, PerlInterpreter *perl) { MP_dSCFG(s); modperl_interp_pool_t *mip = (modperl_interp_pool_t *)ap_pcalloc(p, sizeof(*mip)); modperl_interp_t *cur_interp = NULL; ap_status_t rc; int i; rc = ap_create_lock(&mip->mip_lock, APR_MUTEX, APR_LOCKALL, "mip", p); if (rc != APR_SUCCESS) { exit(1); /*XXX*/ } mip->parent = modperl_interp_new(p, NULL); mip->parent->perl = perl; mip->parent->mip_lock = mip->mip_lock; #ifdef USE_ITHREADS mip->start = 3; /*XXX*/ for (i=0; i<mip->start; i++) { modperl_interp_t *interp = modperl_interp_new(p, mip->parent); interp->perl = perl_clone(perl, TRUE); if (cur_interp) { cur_interp->next = interp; cur_interp = cur_interp->next; } else { mip->head = cur_interp = interp; } } #endif fprintf(stderr, "modperl_interp_pool_init: parent == 0x%lx " "start=%d, min_spare=%d, max_spare=%d\n", (unsigned long)mip->parent, mip->start, mip->min_spare, mip->max_spare); ap_register_cleanup(p, (void*)mip, modperl_interp_pool_destroy, ap_null_cleanup); scfg->mip = mip; } ap_status_t modperl_interp_unselect(void *data) { modperl_interp_t *interp = (modperl_interp_t *)data; ap_lock(interp->mip_lock); MpInterpIN_USE_Off(interp); fprintf(stderr, "modperl_interp_unselect: 0x%lx\n", (unsigned long)interp); ap_unlock(interp->mip_lock); return APR_SUCCESS; } int modperl_interp_select(request_rec *r) { modperl_interp_t *interp = modperl_interp_get(r->server); /* XXX: stash interp pointer in r->per_request */ if (MpInterpPUTBACK(interp)) { ap_register_cleanup(r->pool, (void*)interp, modperl_interp_unselect, ap_null_cleanup); } if (1) { /* testing concurrent callbacks into the Perl runtime(s) */ dTHXa(interp->perl); SV *sv = get_sv("Apache::Server::Perl", TRUE); sv_setref_pv(sv, Nullch, (void*)interp->perl); eval_pv("printf STDERR qq(Perl == 0x%lx\n), " "$$Apache::Server::Perl", TRUE); } return OK; } 1.1 modperl-2.0/src/modules/perl/modperl_interp.h Index: modperl_interp.h =================================================================== #ifndef MODPERL_INTERP_H #define MODPERL_INTERP_H modperl_interp_t *modperl_interp_new(ap_pool_t *p, modperl_interp_t *parent); modperl_interp_t *modperl_interp_get(server_rec *s); void modperl_interp_pool_init(server_rec *s, ap_pool_t *p, PerlInterpreter *perl); ap_status_t modperl_interp_unselect(void *data); int modperl_interp_select(request_rec *r); #endif /* MODPERL_INTERP_H */