X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=Magic.xs;h=207fcb383a75a3162632239b0cc74c7ff5335504;hb=64d80b88646a16ec430354d4139798d152f0e3ca;hp=cf5bc21472701075610c731a660948e45cbc9404;hpb=ea4de64c75c0516d7cc92a586c9f8b76465ca130;p=perl%2Fmodules%2FVariable-Magic.git diff --git a/Magic.xs b/Magic.xs index cf5bc21..207fcb3 100644 --- a/Magic.xs +++ b/Magic.xs @@ -1745,24 +1745,37 @@ static I32 vmg_svt_val(pTHX_ IV action, SV *sv) { #endif /* VMG_UVAR */ -/* --- Global setup/teardown ----------------------------------------------- */ +/* --- Module setup/teardown ----------------------------------------------- */ -static VOL U32 vmg_initialized = 0; - -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; } @@ -1821,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; @@ -1875,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; @@ -1922,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; } @@ -1978,8 +1992,7 @@ PROTOTYPES: ENABLE BOOT: { - vmg_global_setup(); - vmg_local_setup(); + vmg_setup(); } #if VMG_THREADSAFE @@ -2008,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);