X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Magic.xs;h=207fcb383a75a3162632239b0cc74c7ff5335504;hb=64d80b88646a16ec430354d4139798d152f0e3ca;hp=9a5a04f152334809b09ece05e18b4830fec68fd4;hpb=4bd785b430cf478b6cbf5b2cfe5cc1a9a9f72203;p=perl%2Fmodules%2FVariable-Magic.git diff --git a/Magic.xs b/Magic.xs index 9a5a04f..207fcb3 100644 --- a/Magic.xs +++ b/Magic.xs @@ -49,12 +49,17 @@ #endif #ifndef VMG_MULTIPLICITY -# if defined(MULTIPLICITY) || defined(PERL_IMPLICIT_CONTEXT) +# if defined(MULTIPLICITY) # define VMG_MULTIPLICITY 1 # else # define VMG_MULTIPLICITY 0 # endif #endif +#if VMG_MULTIPLICITY +# ifndef PERL_IMPLICIT_CONTEXT +# error MULTIPLICITY builds must set PERL_IMPLICIT_CONTEXT +# endif +#endif #if VMG_MULTIPLICITY && defined(USE_ITHREADS) && defined(dMY_CXT) && defined(MY_CXT) && defined(START_MY_CXT) && defined(MY_CXT_INIT) && (defined(MY_CXT_CLONE) || defined(dMY_CXT_SV)) # define VMG_THREADSAFE 1 @@ -1740,24 +1745,37 @@ static I32 vmg_svt_val(pTHX_ IV action, SV *sv) { #endif /* VMG_UVAR */ -/* --- Global setup/teardown ----------------------------------------------- */ - -static VOL U32 vmg_initialized = 0; +/* --- Module setup/teardown ----------------------------------------------- */ -static void vmg_global_teardown_late(pTHX) { -#define vmg_global_teardown_late() vmg_global_teardown_late(aTHX) #if VMG_THREADSAFE + +static I32 vmg_loaded = 0; + +/* We must use preexistent global mutexes or we will never be able to destroy + * them. */ +# if VMG_HAS_PERL(5, 9, 3) +# define VMG_LOADED_LOCK MUTEX_LOCK(&PL_my_ctx_mutex) +# define VMG_LOADED_UNLOCK MUTEX_UNLOCK(&PL_my_ctx_mutex) +# else +# define VMG_LOADED_LOCK OP_REFCNT_LOCK +# define VMG_LOADED_UNLOCK OP_REFCNT_UNLOCK +# endif + +static void vmg_global_teardown_late_locked(pTHX) { +#define vmg_global_teardown_late_locked() vmg_global_teardown_late_locked(aTHX) MUTEX_DESTROY(&vmg_op_name_init_mutex); MUTEX_DESTROY(&vmg_vtable_refcount_mutex); -#endif - - vmg_initialized = 0; return; } static int vmg_global_teardown_free(pTHX_ SV *sv, MAGIC *mg) { - vmg_global_teardown_late(); + VMG_LOADED_LOCK; + + if (vmg_loaded == 0) + vmg_global_teardown_late_locked(); + + VMG_LOADED_UNLOCK; return 0; } @@ -1816,52 +1834,36 @@ static signed char vmg_destruct_level(pTHX) { return lvl; } -static void vmg_global_teardown(pTHX_ void *root) { - if (!vmg_initialized) - return; +#endif /* VMG_THREADSAFE */ + +static void vmg_teardown(pTHX_ void *interp) { + dMY_CXT; #if VMG_MULTIPLICITY - if (aTHX != root) + if (aTHX != interp) return; #endif - if (vmg_destruct_level() == 0) { - vmg_global_teardown_late(); +#if VMG_THREADSAFE + VMG_LOADED_LOCK; + + if (vmg_loaded == 1) { + vmg_loaded = 0; + if (vmg_destruct_level() == 0) { + vmg_global_teardown_late_locked(); + } else { + if (!PL_strtab) + PL_strtab = newHV(); + vmg_sv_magicext((SV *) PL_strtab, NULL, &vmg_global_teardown_vtbl, NULL, 0); + } } else { - if (!PL_strtab) - PL_strtab = newHV(); - vmg_sv_magicext((SV *) PL_strtab, NULL, &vmg_global_teardown_vtbl, NULL, 0); + assert(vmg_loaded > 1); + --vmg_loaded; } - return; -} - -static void vmg_global_setup(pTHX) { -#define vmg_global_setup() vmg_global_setup(aTHX) - if (vmg_initialized) - return; - -#if VMG_THREADSAFE - MUTEX_INIT(&vmg_vtable_refcount_mutex); - MUTEX_INIT(&vmg_op_name_init_mutex); -#endif - -#if VMG_MULTIPLICITY - call_atexit(vmg_global_teardown, aTHX); -#else - call_atexit(vmg_global_teardown, NULL); + VMG_LOADED_UNLOCK; #endif - vmg_initialized = 1; - - return; -} - -/* --- Interpreter setup/teardown ------------------------------------------ */ - -static void vmg_local_teardown(pTHX_ void *param) { - dMY_CXT; - if (MY_CXT.depth == 0 && MY_CXT.freed_tokens) { vmg_magic_chain_free(MY_CXT.freed_tokens, NULL); MY_CXT.freed_tokens = NULL; @@ -1870,12 +1872,25 @@ static void vmg_local_teardown(pTHX_ void *param) { return; } -static void vmg_local_setup(pTHX) { -#define vmg_local_setup() vmg_local_setup(aTHX) +static void vmg_setup(pTHX) { +#define vmg_setup() vmg_setup(aTHX) HV *stash; int c; - MY_CXT_INIT; + +#if VMG_THREADSAFE + VMG_LOADED_LOCK; + + if (vmg_loaded <= 0) { + assert(vmg_loaded == 0); + MUTEX_INIT(&vmg_vtable_refcount_mutex); + MUTEX_INIT(&vmg_op_name_init_mutex); + } + ++vmg_loaded; + + VMG_LOADED_UNLOCK; +#endif + for (c = OPc_NULL; c < OPc_MAX; ++c) MY_CXT.b__op_stashes[c] = NULL; @@ -1917,7 +1932,11 @@ static void vmg_local_setup(pTHX) { newCONSTSUB(stash, "VMG_OP_INFO_NAME", newSVuv(VMG_OP_INFO_NAME)); newCONSTSUB(stash, "VMG_OP_INFO_OBJECT", newSVuv(VMG_OP_INFO_OBJECT)); - call_atexit(vmg_local_teardown, NULL); +#if VMG_MULTIPLICITY + call_atexit(vmg_teardown, aTHX); +#else + call_atexit(vmg_teardown, NULL); +#endif return; } @@ -1973,8 +1992,7 @@ PROTOTYPES: ENABLE BOOT: { - vmg_global_setup(); - vmg_local_setup(); + vmg_setup(); } #if VMG_THREADSAFE @@ -2003,6 +2021,10 @@ PPCODE: } MY_CXT.depth = old_depth; MY_CXT.freed_tokens = NULL; + VMG_LOADED_LOCK; + assert(vmg_loaded > 0); + ++vmg_loaded; + VMG_LOADED_UNLOCK; } XSRETURN(0);