diff --git a/src/c/stacks.d b/src/c/stacks.d index 3b7ac0ac9..f7887a0ef 100644 --- a/src/c/stacks.d +++ b/src/c/stacks.d @@ -322,14 +322,19 @@ ecl_bds_bind(cl_env_ptr env, cl_object s, cl_object v) location = env->thread_local_bindings + index; slot = ++env->bds_top; if (slot >= env->bds_limit) slot = ecl_bds_overflow(); + ecl_disable_interrupts_env(env); slot->symbol = s; slot->value = *location; *location = v; + ecl_enable_interrupts_env(env); #else ecl_bds_check(env); - (++(env->bds_top))->symbol = s; - env->bds_top->value = s->symbol.value; \ + ecl_bds_ptr slot = ++(env->bds_top); + ecl_disable_interrupts_env(env); + slot->symbol = s; + slot->value = s->symbol.value; s->symbol.value = v; + ecl_enable_interrupts_env(env); #endif } @@ -346,13 +351,18 @@ ecl_bds_push(cl_env_ptr env, cl_object s) location = env->thread_local_bindings + index; slot = ++env->bds_top; if (slot >= env->bds_limit) slot = ecl_bds_overflow(); + ecl_disable_interrupts_env(env); slot->symbol = s; slot->value = *location; if (*location == ECL_NO_TL_BINDING) *location = s->symbol.value; + ecl_enable_interrupts_env(env); #else ecl_bds_check(env); - (++(env->bds_top))->symbol = s; - env->bds_top->value = s->symbol.value; + ecl_bds_ptr slot = ++(env->bds_top); + ecl_disable_interrupts_env(env); + slot->symbol = s; + slot->value = s->symbol.value; + ecl_enable_interrupts_env(env); #endif } diff --git a/src/h/ecl-atomic-ops.h b/src/h/ecl-atomic-ops.h new file mode 100644 index 000000000..24097ce10 --- /dev/null +++ b/src/h/ecl-atomic-ops.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*- */ +/* vim: set filetype=c tabstop=8 shiftwidth=4 expandtab: */ + +/* + ecl-atomic-ops.h -- Wrapper around libatomic_ops functions +*/ +/* + Copyright (c) 2001, Juan Jose Garcia Ripoll. + + ECL is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + See file '../Copyright' for full details. +*/ + +#ifndef ECL_ATOMIC_OPS_H +#define ECL_ATOMIC_OPS_H + +#ifdef ECL_THREADS +# define AO_REQUIRE_CAS +# ifdef ECL_LIBATOMIC_OPS_H +# include +# else +# include +# endif +#else +# define AO_load(x) (x) +# define AO_store(x,y) ((x)=(y)) +# define AO_store_full(x,y) ((x)=(y)) +#endif + +#endif /* ECL_ATOMIC_OPS_H */ diff --git a/src/h/internal.h b/src/h/internal.h index 5e702394b..55b5f5d96 100755 --- a/src/h/internal.h +++ b/src/h/internal.h @@ -420,17 +420,7 @@ extern void cl_write_object(cl_object x, cl_object stream); # define ECL_WITH_GLOBAL_ENV_WRLOCK_END #endif /* ECL_RWLOCK */ -#ifdef ECL_THREADS -# define AO_REQUIRE_CAS -# ifdef ECL_LIBATOMIC_OPS_H -# include -# else -# include -# endif -#else -# define AO_load(x) (x) -# define AO_store(x,y) ((x)=(y)) -#endif +#include /* read.d */ #ifdef ECL_UNICODE diff --git a/src/h/stacks.h b/src/h/stacks.h index bbef83376..72af71cb8 100755 --- a/src/h/stacks.h +++ b/src/h/stacks.h @@ -17,6 +17,11 @@ See file '../Copyright' for full details. */ +#ifndef ECL_STACKS_H +#define ECL_STACKS_H + +#include + #ifdef __cplusplus extern "C" { #endif @@ -76,18 +81,29 @@ static inline void ecl_bds_bind_inl(cl_env_ptr env, cl_object s, cl_object v) ecl_bds_bind(env,s,v); } else { location = env->thread_local_bindings + index; + /* First, we push a dummy symbol in the stack to + * prevent segfaults when we are interrupted with a + * call to ecl_bds_unwind. */ + AO_store_full((AO_t*)&(env->bds_top+1)->symbol,(AO_t)ECL_DUMMY_TAG); slot = ++env->bds_top; if (slot >= env->bds_limit) slot = ecl_bds_overflow(); + /* Then we disable interrupts to ensure that + * ecl_bds_unwind doesn't overwrite the symbol with + * some random value. */ + ecl_disable_interrupts_env(env); slot->symbol = s; slot->value = *location; *location = v; + ecl_enable_interrupts_env(env); } # else slot = ++env->bds_top; if (slot >= env->bds_limit) slot = ecl_bds_overflow(); + ecl_disable_interrupts_env(env); slot->symbol = s; slot->value = s->symbol.value; s->symbol.value = v; + ecl_enable_interrupts_env(env); # endif /* !ECL_THREADS */ } @@ -101,17 +117,22 @@ static inline void ecl_bds_push_inl(cl_env_ptr env, cl_object s) ecl_bds_push(env, s); } else { location = env->thread_local_bindings + index; + AO_store_full((AO_t*)&(env->bds_top+1)->symbol,(AO_t)ECL_DUMMY_TAG); slot = ++env->bds_top; if (slot >= env->bds_limit) slot = ecl_bds_overflow(); + ecl_disable_interrupts_env(env); slot->symbol = s; slot->value = *location; if (*location == ECL_NO_TL_BINDING) *location = s->symbol.value; + ecl_enable_interrupts_env(env); } # else slot = ++env->bds_top; if (slot >= env->bds_limit) slot = ecl_bds_overflow(); + ecl_disable_interrupts_env(env); slot->symbol = s; slot->value = s->symbol.value; + ecl_enable_interrupts_env(env); # endif /* !ECL_THREADS */ } @@ -154,21 +175,27 @@ static inline cl_object *ecl_bds_ref_inl(cl_env_ptr env, cl_object s) # define ecl_bds_unwind1 ecl_bds_unwind1_inl #else /* !__GNUC__ */ # ifndef ECL_THREADS -# define ecl_bds_bind(env,sym,val) do { \ - const cl_env_ptr env_copy = (env); \ - const cl_object s = (sym); \ - const cl_object v = (val); \ - ecl_bds_check(env_copy); \ - (++(env_copy->bds_top))->symbol = s, \ - env_copy->bds_top->value = s->symbol.value; \ - s->symbol.value = v; } while (0) +# define ecl_bds_bind(env,sym,val) do { \ + const cl_env_ptr env_copy = (env); \ + const cl_object s = (sym); \ + const cl_object v = (val); \ + ecl_bds_check(env_copy); \ + ecl_bds_ptr slot = ++(env_copy->bds_top); \ + ecl_disable_interrupts_env(env_copy); \ + slot->symbol = s; \ + slot->value = s->symbol.value; \ + s->symbol.value = v; \ + ecl_enable_interrupts_env(env_copy); } while (0) # define ecl_bds_push(env,sym) do { \ - const cl_env_ptr env_copy = (env); \ - const cl_object s = (sym); \ - const cl_object v = s->symbol.value; \ - ecl_bds_check(env_copy); \ - (++(env_copy->bds_top))->symbol = s, \ - env_copy->bds_top->value = s->symbol.value; } while (0); + const cl_env_ptr env_copy = (env); \ + const cl_object s = (sym); \ + const cl_object v = s->symbol.value; \ + ecl_bds_check(env_copy); \ + ecl_bds_ptr slot = ++(env_copy->bds_top); \ + ecl_disable_interrupts_env(env_copy); \ + slot->symbol = s; \ + slot->value = s->symbol.value; \ + ecl_enable_interrupts_env(env_copy); } while (0); # define ecl_bds_unwind1(env) do { \ const cl_env_ptr env_copy = (env); \ const cl_object s = env_copy->bds_top->symbol; \ @@ -484,3 +511,5 @@ extern ECL_API ecl_frame_ptr _ecl_frs_push(register cl_env_ptr, register cl_obje #ifdef __cplusplus } #endif + +#endif /* ECL_STACKS_H */