fix problem with per-registry locking of available-module visit & instantiation

svn: r18744
This commit is contained in:
Matthew Flatt 2010-04-07 12:34:50 +00:00
parent da7d9485f1
commit abebb1c1f4
2 changed files with 14 additions and 6 deletions

View File

@ -682,7 +682,9 @@ are visited. More generally, initiating expansion at @tech{phase}
@math{n} @tech{visit}s modules at @tech{phase} @math{n}, which in turn @math{n} @tech{visit}s modules at @tech{phase} @math{n}, which in turn
@tech{instantiates} modules at @tech{phase} @math{n+1}. These @tech{instantiates} modules at @tech{phase} @math{n+1}. These
@tech{visits} and @tech{instantiations} apply to @tech{available} @tech{visits} and @tech{instantiations} apply to @tech{available}
modules in the enclosing @tech{namespace}. modules in the enclosing @tech{namespace}'s @tech{module registry};
a per-registry lock prevents multiple threads from concurrently
instantiating and visiting available modules.
When the expander encounters @scheme[require] and @scheme[(require When the expander encounters @scheme[require] and @scheme[(require
(for-syntax ....))] within a @tech{module context}, the resulting (for-syntax ....))] within a @tech{module context}, the resulting

View File

@ -3749,14 +3749,17 @@ void scheme_module_force_lazy(Scheme_Env *env, int previous)
/* not anymore */ /* not anymore */
} }
static void wait_registry(Scheme_Env *env) static int wait_registry(Scheme_Env *env)
{ {
Scheme_Object *lock, *a[1]; Scheme_Object *lock, *a[1];
while (1) { while (1) {
lock = scheme_hash_get(env->module_registry, scheme_false); lock = scheme_hash_get(env->module_registry, scheme_false);
if (!lock) if (!lock)
return; return 1;
if (SAME_OBJ(SCHEME_CDR(lock), (Scheme_Object *)scheme_current_thread))
return 0;
a[0] = SCHEME_CAR(lock); a[0] = SCHEME_CAR(lock);
a[1] = SCHEME_CDR(lock); a[1] = SCHEME_CDR(lock);
@ -4395,8 +4398,9 @@ static void do_prepare_compile_env(Scheme_Env *env, int base_phase, int pos)
{ {
Scheme_Object *v, *prev; Scheme_Object *v, *prev;
Scheme_Env *menv; Scheme_Env *menv;
int need_lock;
wait_registry(env); need_lock = wait_registry(env);
v = MODCHAIN_AVAIL(env->modchain, pos); v = MODCHAIN_AVAIL(env->modchain, pos);
if (!SCHEME_FALSEP(v)) { if (!SCHEME_FALSEP(v)) {
@ -4414,6 +4418,7 @@ static void do_prepare_compile_env(Scheme_Env *env, int base_phase, int pos)
} }
v = prev; v = prev;
if (need_lock)
lock_registry(env); lock_registry(env);
while (SCHEME_NAMESPACEP(v)) { while (SCHEME_NAMESPACEP(v)) {
@ -4425,6 +4430,7 @@ static void do_prepare_compile_env(Scheme_Env *env, int base_phase, int pos)
scheme_null); scheme_null);
} }
if (need_lock)
unlock_registry(env); unlock_registry(env);
} }
} }