Fixed problems in ecl_register_current_thread(). First, allocation of environment and process structures could not proceed when ecl_process_env() did not return a valid environment. Second, we can only call GC_unregister_my_thread() when the thread was not created by the garbage collector itself, for which we must inspect the output of GC_register_my_thread()

This commit is contained in:
Juan Jose Garcia Ripoll 2012-09-27 23:06:56 +02:00
parent 87a529c883
commit 42f0b2eaa5
4 changed files with 41 additions and 16 deletions

View file

@ -134,6 +134,7 @@ ecl_init_env(cl_env_ptr env)
env->c_env = NULL;
#if !defined(ECL_THREADS)
env->own_process = ECL_NIL;
env->cleanup = 0;
#endif
env->string_pool = ECL_NIL;
@ -207,7 +208,7 @@ _ecl_dealloc_env(cl_env_ptr env)
}
cl_env_ptr
_ecl_alloc_env()
_ecl_alloc_env(cl_env_ptr parent)
{
/*
* Allocates the lisp environment for a thread. Depending on which
@ -242,10 +243,10 @@ _ecl_alloc_env()
size_t bytes = cl_core.default_sigmask_bytes;
if (bytes == 0) {
output->default_sigmask = 0;
} else if (ecl_option_values[ECL_OPT_BOOTED]) {
} else if (parent) {
output->default_sigmask = ecl_alloc_atomic(bytes);
memcpy(output->default_sigmask,
ecl_process_env()->default_sigmask,
parent->default_sigmask,
bytes);
} else {
output->default_sigmask = cl_core.default_sigmask;
@ -518,7 +519,7 @@ cl_boot(int argc, char **argv)
init_unixint(0);
init_alloc();
GC_disable();
env = _ecl_alloc_env();
env = _ecl_alloc_env(0);
#ifdef ECL_THREADS
init_threads(env);
#else

View file

@ -333,9 +333,11 @@ alloc_process(cl_object name, cl_object initial_bindings)
bool
ecl_import_current_thread(cl_object name, cl_object bindings)
{
struct cl_env_struct env_aux[1];
cl_object process;
pthread_t current;
cl_env_ptr env;
int registered;
#ifdef ECL_WINDOWS_THREADS
{
HANDLE aux = GetCurrentThread();
@ -352,7 +354,18 @@ ecl_import_current_thread(cl_object name, cl_object bindings)
current = pthread_self();
#endif
#ifdef GBC_BOEHM
GC_register_my_thread((void*)&name);
switch (GC_register_my_thread((void*)&name)) {
case GC_SUCCESS:
registered = 1;
break;
case GC_DUPLICATE:
/* Thread was probably created using the GC hooks
* for thread creation */
registered = 0;
break;
default:
return 0;
}
#endif
{
cl_object processes = cl_core.processes;
@ -363,17 +376,20 @@ ecl_import_current_thread(cl_object name, cl_object bindings)
return 0;
}
}
process = alloc_process(name, bindings);
/* We need a fake env to allow for interrupts blocking. */
env_aux->disable_interrupts = 1;
ecl_set_process_env(env_aux);
env = _ecl_alloc_env(0);
ecl_set_process_env(env);
env->cleanup = registered;
/* Link environment and process together */
env->own_process = process = alloc_process(name, bindings);
process->process.env = env;
process->process.phase = ECL_PROCESS_BOOTING;
process->process.thread = current;
ecl_list_process(process);
/* Link environment and process together */
env = _ecl_alloc_env();
env->own_process = process;
process->process.env = env;
ecl_set_process_env(env);
ecl_init_env(env);
env->bindings_array = process->process.initial_bindings;
env->thread_local_bindings_size = env->bindings_array->vector.dim;
@ -389,9 +405,13 @@ ecl_import_current_thread(cl_object name, cl_object bindings)
void
ecl_release_current_thread(void)
{
thread_cleanup(ecl_process_env()->own_process);
cl_env_ptr env = ecl_process_env();
int cleanup = env->cleanup;
thread_cleanup(env->own_process);
#ifdef GBC_BOEHM
GC_unregister_my_thread();
if (cleanup) {
GC_unregister_my_thread();
}
#endif
}
@ -491,7 +511,7 @@ mp_process_enable(cl_object process)
ecl_list_process(process);
/* Link environment and process together */
process_env = _ecl_alloc_env();
process_env = _ecl_alloc_env(ecl_process_env());
process_env->own_process = process;
process->process.env = process_env;

View file

@ -137,6 +137,10 @@ struct cl_env_struct {
/* Segmentation fault address */
void *fault_address;
#ifdef ECL_THREADS
int cleanup;
#endif
};
#ifndef __GNUC__

View file

@ -52,7 +52,7 @@ extern void init_threads(cl_env_ptr);
extern void ecl_init_env(cl_env_ptr);
extern void init_lib_LSP(cl_object);
extern cl_env_ptr _ecl_alloc_env(void);
extern cl_env_ptr _ecl_alloc_env(cl_env_ptr parent);
extern void _ecl_dealloc_env(cl_env_ptr);
/* alloc.d/alloc_2.d */