mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-03-13 08:20:31 -07:00
threading: be more interrupt safe with thread local variables in environment
Also add some comments and use the right interrupt disabling
mechanism in get_aux_stream.
This commit is contained in:
parent
9f8adbbe4e
commit
fd62dc11f8
3 changed files with 25 additions and 10 deletions
|
|
@ -98,14 +98,14 @@ get_aux_stream(void)
|
|||
cl_env_ptr env = ecl_process_env();
|
||||
cl_object stream;
|
||||
|
||||
ecl_disable_interrupts_env(env);
|
||||
if (env->fmt_aux_stream == ECL_NIL) {
|
||||
stream = ecl_make_string_output_stream(64, 1);
|
||||
} else {
|
||||
stream = env->fmt_aux_stream;
|
||||
env->fmt_aux_stream = ECL_NIL;
|
||||
}
|
||||
ecl_enable_interrupts_env(env);
|
||||
ECL_WITHOUT_INTERRUPTS_BEGIN(env) {
|
||||
if (env->fmt_aux_stream == ECL_NIL) {
|
||||
stream = ecl_make_string_output_stream(64, 1);
|
||||
} else {
|
||||
stream = env->fmt_aux_stream;
|
||||
env->fmt_aux_stream = ECL_NIL;
|
||||
}
|
||||
} ECL_WITHOUT_INTERRUPTS_END;
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -378,18 +378,31 @@ handle_all_queued_interrupt_safe(cl_env_ptr env)
|
|||
/* We have to save and later restore thread-local variables to
|
||||
* ensure that they don't get overwritten by the interrupting
|
||||
* code */
|
||||
/* INV: - Frame, Binding and IHS stack manipulations are
|
||||
* interrupt safe
|
||||
* - The rest of the thread local variables are
|
||||
* guaranteed to be used in an interrupt safe way. This
|
||||
* is not true for the compiler environment and ffi
|
||||
* data, but it is unclear whether the DFFI or compiler
|
||||
* are thread safe anyway. */
|
||||
cl_object fun = env->function;
|
||||
cl_index nvalues = env->nvalues;
|
||||
cl_object* values = ecl_alloc_atomic(ECL_MULTIPLE_VALUES_LIMIT*sizeof(cl_object));
|
||||
cl_object values[ECL_MULTIPLE_VALUES_LIMIT];
|
||||
memcpy(values, env->values, ECL_MULTIPLE_VALUES_LIMIT*sizeof(cl_object));
|
||||
cl_object big_register[3];
|
||||
memcpy(big_register, env->big_register, 3*sizeof(cl_object));
|
||||
cl_object packages_to_be_created = env->packages_to_be_created;
|
||||
cl_object packages_to_be_created_p = env->packages_to_be_created_p;
|
||||
/* We might have been interrupted while we push/pop in the
|
||||
* stack. Increasing env->stack_top ensures that we don't
|
||||
* overwrite the topmost stack value. */
|
||||
env->stack_top++;
|
||||
/* Finally we can handle the queued signals */
|
||||
handle_all_queued(env);
|
||||
/* And restore thread local variables again */
|
||||
env->stack_top--;
|
||||
env->packages_to_be_created_p = packages_to_be_created_p;
|
||||
env->packages_to_be_created = packages_to_be_created;
|
||||
memcpy(env->big_register, big_register, 3*sizeof(cl_object));
|
||||
memcpy(env->values, values, ECL_MULTIPLE_VALUES_LIMIT*sizeof(cl_object));
|
||||
env->nvalues = nvalues;
|
||||
|
|
|
|||
|
|
@ -87,14 +87,16 @@ struct cl_env_struct {
|
|||
char *cs_barrier;
|
||||
|
||||
/* Private variables used by different parts of ECL: */
|
||||
/* ... the reader ... */
|
||||
/* ... the reader and printer ... */
|
||||
cl_object string_pool;
|
||||
|
||||
/* ... the compiler ... */
|
||||
struct cl_compiler_env *c_env;
|
||||
|
||||
/* ... the formatter ... */
|
||||
#if !defined(ECL_CMU_FORMAT)
|
||||
cl_object fmt_aux_stream;
|
||||
#endif
|
||||
|
||||
/* ... arithmetics ... */
|
||||
/* Note: if you change the size of these registers, change also
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue