mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-01-21 03:51:47 -08:00
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:
parent
87a529c883
commit
42f0b2eaa5
4 changed files with 41 additions and 16 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,10 @@ struct cl_env_struct {
|
|||
|
||||
/* Segmentation fault address */
|
||||
void *fault_address;
|
||||
|
||||
#ifdef ECL_THREADS
|
||||
int cleanup;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue