mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-01-23 13:01:42 -08:00
threading: fix race conditions in ECL_WITH_GLOBAL_ENV_RD/WRLOCK
We can't use ecl_disable_interrupts, because often writes in the
thread local environment happen while we hold the locks (e.g.
env->packages_to_be_created is written in find_pending_package
while the lock is held in ecl_make_package). Therefore we use the
lisp interrupt blocking mechanism. For this, the order of
operations in cl_boot has to be modified a bit.
This commit is contained in:
parent
e5281a4685
commit
3f0fc4f855
5 changed files with 27 additions and 19 deletions
31
src/c/main.d
31
src/c/main.d
|
|
@ -557,6 +557,24 @@ cl_boot(int argc, char **argv)
|
|||
#endif
|
||||
|
||||
env->packages_to_be_created = ECL_NIL;
|
||||
|
||||
#ifdef ECL_THREADS
|
||||
env->bindings_array = si_make_vector(ECL_T, ecl_make_fixnum(1024),
|
||||
ECL_NIL, ECL_NIL, ECL_NIL, ECL_NIL);
|
||||
si_fill_array_with_elt(env->bindings_array, ECL_NO_TL_BINDING, ecl_make_fixnum(0), ECL_NIL);
|
||||
env->thread_local_bindings_size = env->bindings_array->vector.dim;
|
||||
env->thread_local_bindings = env->bindings_array->vector.self.t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize the per-thread data.
|
||||
* This cannot come later, because we need to be able to bind
|
||||
* ext::*interrupts-enabled while creating packages.
|
||||
*/
|
||||
init_big();
|
||||
ecl_init_env(env);
|
||||
ecl_cs_set_org(env);
|
||||
|
||||
cl_core.lisp_package =
|
||||
ecl_make_package(str_common_lisp,
|
||||
cl_list(2, str_cl, str_LISP),
|
||||
|
|
@ -623,14 +641,6 @@ cl_boot(int argc, char **argv)
|
|||
/* These must come _after_ the packages and NIL/T have been created */
|
||||
init_all_symbols();
|
||||
|
||||
/*
|
||||
* Initialize the per-thread data.
|
||||
* This cannot come later, because some routines need the
|
||||
* frame stack immediately (for instance SI:PATHNAME-TRANSLATIONS).
|
||||
*/
|
||||
init_big();
|
||||
ecl_init_env(env);
|
||||
ecl_cs_set_org(env);
|
||||
#if !defined(GBC_BOEHM)
|
||||
/* We need this because a lot of stuff is to be created */
|
||||
init_GC();
|
||||
|
|
@ -648,11 +658,6 @@ cl_boot(int argc, char **argv)
|
|||
#endif
|
||||
|
||||
#ifdef ECL_THREADS
|
||||
env->bindings_array = si_make_vector(ECL_T, ecl_make_fixnum(1024),
|
||||
ECL_NIL, ECL_NIL, ECL_NIL, ECL_NIL);
|
||||
si_fill_array_with_elt(env->bindings_array, ECL_NO_TL_BINDING, ecl_make_fixnum(0), ECL_NIL);
|
||||
env->thread_local_bindings_size = env->bindings_array->vector.dim;
|
||||
env->thread_local_bindings = env->bindings_array->vector.self.t;
|
||||
ECL_SET(@'mp::*current-process*', env->own_process);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ cl_symbols[] = {
|
|||
{SYS_ "DUMMY-TAG", SI_ORDINARY, NULL, -1, OBJNULL},
|
||||
{SYS_ "*RESTART-CLUSTERS*", SI_SPECIAL, NULL, -1, Cnil},
|
||||
{SYS_ "*HANDLER-CLUSTERS*", SI_SPECIAL, NULL, -1, Cnil},
|
||||
{EXT_ "*INTERRUPTS-ENABLED*", EXT_SPECIAL, NULL, 1, ECL_T},
|
||||
|
||||
/* LISP PACKAGE */
|
||||
{"&ALLOW-OTHER-KEYS", CL_ORDINARY, NULL, -1, OBJNULL},
|
||||
|
|
@ -1102,7 +1103,6 @@ cl_symbols[] = {
|
|||
{SYS_ "*IGNORE-EOF-ON-TERMINAL-IO*", SI_SPECIAL, NULL, -1, ECL_NIL},
|
||||
{SYS_ "*INDENT-FORMATTED-OUTPUT*", SI_SPECIAL, NULL, -1, ECL_NIL},
|
||||
{SYS_ "*INIT-FUNCTION-PREFIX*", SI_SPECIAL, NULL, -1, ECL_NIL},
|
||||
{EXT_ "*INTERRUPTS-ENABLED*", EXT_SPECIAL, NULL, 1, ECL_T},
|
||||
{SYS_ "*KEEP-DEFINITIONS*", SI_SPECIAL, NULL, -1, ECL_T},
|
||||
{EXT_ "*LOAD-HOOKS*", EXT_SPECIAL, NULL, -1, OBJNULL},
|
||||
{SYS_ "*LOAD-SEARCH-LIST*", SI_SPECIAL, NULL, -1, ECL_NIL},
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ cl_symbols[] = {
|
|||
{SYS_ "DUMMY-TAG",NULL},
|
||||
{SYS_ "*RESTART-CLUSTERS*",NULL},
|
||||
{SYS_ "*HANDLER-CLUSTERS*",NULL},
|
||||
{EXT_ "*INTERRUPTS-ENABLED*",NULL},
|
||||
|
||||
/* LISP PACKAGE */
|
||||
{"&ALLOW-OTHER-KEYS",NULL},
|
||||
|
|
@ -1102,7 +1103,6 @@ cl_symbols[] = {
|
|||
{SYS_ "*IGNORE-EOF-ON-TERMINAL-IO*",NULL},
|
||||
{SYS_ "*INDENT-FORMATTED-OUTPUT*",NULL},
|
||||
{SYS_ "*INIT-FUNCTION-PREFIX*",NULL},
|
||||
{EXT_ "*INTERRUPTS-ENABLED*",NULL},
|
||||
{SYS_ "*KEEP-DEFINITIONS*",NULL},
|
||||
{EXT_ "*LOAD-HOOKS*",NULL},
|
||||
{SYS_ "*LOAD-SEARCH-LIST*",NULL},
|
||||
|
|
|
|||
|
|
@ -401,18 +401,20 @@ extern void cl_write_object(cl_object x, cl_object stream);
|
|||
#ifdef ECL_RWLOCK
|
||||
# define ECL_WITH_GLOBAL_ENV_RDLOCK_BEGIN(the_env) { \
|
||||
const cl_env_ptr __ecl_pack_env = the_env; \
|
||||
ecl_disable_interrupts_env(__ecl_pack_env); \
|
||||
ecl_bds_bind(__ecl_pack_env, ECL_INTERRUPTS_ENABLED, ECL_NIL); \
|
||||
mp_get_rwlock_read_wait(cl_core.global_env_lock);
|
||||
# define ECL_WITH_GLOBAL_ENV_RDLOCK_END \
|
||||
mp_giveup_rwlock_read(cl_core.global_env_lock); \
|
||||
ecl_enable_interrupts_env(__ecl_pack_env); }
|
||||
ecl_bds_unwind1(__ecl_pack_env); \
|
||||
ecl_check_pending_interrupts(__ecl_pack_env); }
|
||||
# define ECL_WITH_GLOBAL_ENV_WRLOCK_BEGIN(the_env) { \
|
||||
const cl_env_ptr __ecl_pack_env = the_env; \
|
||||
ecl_disable_interrupts_env(__ecl_pack_env); \
|
||||
ecl_bds_bind(__ecl_pack_env, ECL_INTERRUPTS_ENABLED, ECL_NIL); \
|
||||
mp_get_rwlock_write_wait(cl_core.global_env_lock);
|
||||
# define ECL_WITH_GLOBAL_ENV_WRLOCK_END \
|
||||
mp_giveup_rwlock_write(cl_core.global_env_lock); \
|
||||
ecl_enable_interrupts_env(__ecl_pack_env); }
|
||||
ecl_bds_unwind1(__ecl_pack_env); \
|
||||
ecl_check_pending_interrupts(__ecl_pack_env); }
|
||||
#else
|
||||
# define ECL_WITH_GLOBAL_ENV_RDLOCK_BEGIN(the_env)
|
||||
# define ECL_WITH_GLOBAL_ENV_RDLOCK_END
|
||||
|
|
|
|||
|
|
@ -249,6 +249,7 @@ enum ecl_stype { /* symbol type */
|
|||
#define ECL_DUMMY_TAG ((cl_object)(cl_symbols+4))
|
||||
#define ECL_RESTART_CLUSTERS ((cl_object)(cl_symbols+5))
|
||||
#define ECL_HANDLER_CLUSTERS ((cl_object)(cl_symbols+6))
|
||||
#define ECL_INTERRUPTS_ENABLED ((cl_object)(cl_symbols+7))
|
||||
#define ECL_NO_TL_BINDING ((cl_object)(1 << ECL_TAG_BITS))
|
||||
|
||||
struct ecl_symbol {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue