* libguile/scm.h (scm_tc7_thread): Give threads their own tc7.
* libguile/threads.h (struct scm_thread): Add a tag, so that struct
thread can be a SCM directly. Add a struct gc_mutator* member.
(scm_thread_handle): New inline function.
(SCM_I_IS_THREAD, SCM_I_THREAD_DATA, SCM_VALIDATE_THREAD): Update to use
tc7 instead of SMOB tags.
* libguile/continuations.c (scm_i_with_continuation_barrier)
* libguile/finalizers.c (queue_finalizer_async)
* libguile/jit.c (compile_current_thread)
* libguile/threads.c (block_self, guilify_self_2)
(lock_mutex, unlock_mutex, timed_wait scm_current_thread)
(scm_all_threads)
* libguile/vm-engine.c (current-thread): Use scm_thread_handle instead
of thread->handle.
* libguile/evalext.c (scm_self_evaluating_p):
* libguile/goops.c (class_thread, scm_class_of, scm_sys_goops_early_init)
* libguile/print.c (iprin1)
* module/language/cps/compile-bytecode.scm (compile-function)
* module/oop/goops.scm (<thread>)
* module/system/base/types.scm (cell->object)
* module/system/base/types/internal.scm (heap-tags)
* module/system/vm/assembler.scm: (emit-thread?): Adapt to
scm_tc7_thread.
* libguile/gc-internal.h: Move init functions that take "struct
gc_stack_addr" here, so that internal Whippet uses don't cause Whippet
to be added to public headers.
* libguile/gc.c (scm_storage_prehistory): Take struct gc_stack_addr as
arg, and pass to gc_init. Return a mutator pointer.
* libguile/init.c (scm_i_init_guile): Pass mutator and stack base to GC
and thread init routines.
* libguile/threads.c (scm_trace_dynstack, scm_trace_thread)
(scm_trace_thread_mutator_roots): New infra for marking threads in terms
of Whippet API.
* libguile/threads.c (guilify_self_1): Since we don't use a separate GC
kind for threads any more, and thread marking is keyed off
gc_mutator_set_roots, we can avoid some of the gnarly synchronization.
(on_thread_exit): Arrange to gc_finish_for_thread.
(scm_i_init_thread_for_guile): Use gc_init_for_thread.
(init_main_thread, with_guile, scm_i_with_guile): Use Whippet API.
(scm_threads_prehistory): Take main-thread mutator and the stack base as
arguments.
* libguile/vm.c (scm_trace_vm): Rework in terms of Whippet API.
* libguile/whippet-embedder.h (gc_trace_mutator_roots): Arrange to trace
the current mutator's SCM thread object.
* libguile/trace.h: New file, to declare implementations of trace
routines.
* libguile/Makefile.am (noinst_HEADERS): Add trace.h.
Fixes <https://bugs.gnu.org/76343>.
Fixes a bug whereby “echo '(environ)' | guile” would wrongfully trigger
the multiple-thread warning.
* libguile/finalizers.c (finalizer_thread): New variable.
(finalization_thread_proc): Set it.
(scm_i_is_finalizer_thread): New function.
(run_finalization_thread): Clear FINALIZER_THREAD.
* libguile/finalizers.h (scm_i_is_finalizer_thread): New declaration.
* libguile/threads.c (scm_all_threads): Use it.
* NEWS: Update.
Reported-by: Simon Josefsson <simon@josefsson.org>
* libguile/scmsigs.c: Use raw pthread_create / pthread_join instead of
Guile's scm_spawn_thread, to ensure that the thread is entirely stopped
before a fork.
* libguile/scmsigs.h (scm_i_is_signal_delivery_thread): New internal
procedure, replacing a manual check against scm_i_signal_delivery_thread.
* libguile/threads.c: Use the new procedure.
Based on a patch by Rob Browning. Thanks!
Fixes <https://bugs.gnu.org/68087>.
* libguile/scmsigs.h (scm_i_signals_pre_fork, scm_i_signals_post_fork):
New declarations.
(scm_i_signal_delivery_thread): Change type to SCM..
* libguile/threads.c (scm_all_threads): Adjust accordingly and exclude
threads that have ‘t->exited’. Access ‘thread_count’ after grabbing
‘thread_admin_mutex’.
* libguile/posix.c (scm_fork): Add calls to ‘scm_i_signals_pre_fork’ and
‘scm_i_signals_post_fork’.
* libguile/scmsigs.c (signal_delivery_thread): Close signal_pipe[0] upon
exit and set it to -1.
(once): New file-global variable, moved from…
(scm_i_ensure_signal_delivery_thread): … here.
(stop_signal_delivery_thread, scm_i_signals_pre_fork)
(scm_i_signals_post_fork): New functions.
* test-suite/standalone/test-sigaction-fork: New file.
* test-suite/standalone/Makefile.am (check_SCRIPTS, TESTS): Add it.
This is a followup to f859e0f58b, which
led to warnings on GNU/Linux:
threads.c:358:43: warning: 'scm_i_current_thread' initialized and declared 'extern'
* libguile/threads.c (scm_i_current_thread): Make 'SCM_INTERNAL'
conditional.
If we got interrupted while waiting on our condition variable, we unlock
the kernel mutex momentarily while executing asynchronous operations
before putting us back into the waiting queue.
However, we have to retry acquiring the mutex before getting back into
the queue, otherwise it's possible that we wait indefinitely since
nobody could be the owner for a while.
* libguile/threads.c (lock_mutex): Try acquring the mutex after signal
interruption.
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
* libguile/exceptions.c:
* libguile/exceptions.h: New files.
* libguile.h: Add exceptions.h.
* libguile/Makefile.am (libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES):
(DOT_X_FILES, DOT_DOC_FILES, modinclude_HEADERS): Add exceptions.c and
exceptions.h.
* libguile/init.c (scm_i_init_guile): Initialize exceptions.
* libguile/threads.c (scm_spawn_thread): Use new names for
scm_i_make_catch_handler and scm_c_make_thunk.
* libguile/throw.c: Rewrite to be implemented in terms of
with-exception-handler / raise-exception.
* libguile/throw.h: Use data types from exceptions.h. Move
scm_report_stack_overflow and scm_report_out_of_memory to
exceptions.[ch].
* module/ice-9/boot-9.scm (&error, &programming-error)
(&non-continuable, make-exception-from-throw, raise-exception)
(with-exception-handler): New top-level definitions.
(throw, catch, with-throw-handler): Rewrite in terms of
with-exception-handler and raise-exception.
: New top-level definitions.
* module/ice-9/exceptions.scm: Adapt to re-export &error,
&programming-error, &non-continuable, raise-exception, and
with-exception-handler from boot-9.
(make-quit-exception, guile-quit-exception-converter): New exception
converters.
(make-exception-from-throw): Override core binding.
* test-suite/tests/eval.test ("inner trim with prompt tag"): Adapt to
"with-exception-handler" being the procedure on the stack.
("outer trim with prompt tag"): Likewise.
* test-suite/tests/exceptions.test (throw-test): Use pass-if-equal.
* module/srfi/srfi-34.scm: Reimplement in terms of core exceptions, and
make "guard" actually re-raise continuations with the original "raise"
continuation.
* libguile/gc-inline.h:
* libguile/threads.h (SCM_INLINE_GC_GRANULE_WORDS)
(SCM_INLINE_GC_GRANULE_BYTES, SCM_INLINE_GC_FREELIST_COUNT): Move
definitions here, from gc-inline.h.
(struct scm_thread): Inline freelist vectors.
* libguile/threads.c (thread_mark): Update marker for pointerless
freelists.
(on_thread_exit): Clear individual freelist entries, instead of the
vector as a whole.
(guilify_self_2): No need to alloc freelist vectors.
* libguile/jit.c: Wrap the whole thing in ENABLE_JIT.
* libguile/threads.c (on_thread_exit):
* libguile/vm.c (scm_call_n):
* libguile/init.c (scm_i_init_guile):
* libguile/vm-engine.c (VM_NAME): Wrap calls into jit.c with ENABLE_JIT.
* configure.ac: Move up AC_CANONICAL_TARGET, as autoconf was complaining
about it coming after AC_ARG_PROGRAM.
* acinclude.m4 (GUILE_ENABLE_JIT): Fix to honor --enable-jit arg.
* libguile/init.c (scm_i_init_guile): Call scm_init_jit ().
* libguile/jit.c (enter_mcode, exit_mcode): New static members; code
pointers for the JIT trampoline.
(emit_exit): New helper. The Lightning tramp/frame mechanism that we
use needs to exit via a jmp instead of a return. Adapt callers of
jit_ret.
(emit_entry_trampoline): Use the "frame" mechanism to enter the JIT.
(compile1): Add missing "break" after case statements. Oops!
(compile): Add prolog and "tramp" to compiled functions.
(initialize_jit): New local routine to init the JIT on demand.
(compute_mcode): New helper, to compile a function.
(scm_sys_jit_compile): New function, exported to Scheme as
%jit-compile.
(scm_jit_compute_mcode): Return the existing mcode if the function is
at the start.
(scm_jit_enter_mcode): Call the enter_mcode trampoline.
* libguile/jit.h (struct scm_jit_state): Declare, so we can make
pointers to it.
* libguile/threads.h (struct scm_thread): Add jit_state member.
* libguile/threads.c (on_thread_exit): Free the jit state.
* libguile/threads.c (thread_mark): Unconditionally call
scm_i_vm_mark_stack.
(guilify_self_1): Eagerly prepare the thread stack, before entering
Guile mode. It's only a page of mmap, after all.
* libguile/vm.c (scm_i_vm_prepare_stack): Rename from init_vm.
(thread_vm, scm_the_vm): Remove.
(VM_DEFINE_HOOK, scm_vm_trace_level, scm_set_vm_trace_level_x)
(scm_vm_engine, scm_c_set_vm_engine_x, scm_i_capture_current_stack)
(scm_call_n, scm_call_with_stack_overflow_handler): Adapt to get VM
from thread.
(scm_i_vm_free_stack): Memset the whole thing to 0 when we're done.
* libguile/control.c (scm_abort_to_prompt_star)
* libguile/eval.c (eval):
* libguile/throw.c (catch, abort_to_prompt): Get VM from thread.
As the FSF advises, 'There is no legal significance to using the
three-character sequence “(C)”, but it does no harm.' It does take up
space though! For that reason, we remove it here from our C files.
* libguile/__scm.h (scm_i_jmp_buf): Remove definition, which was a shim
for ia64. Instead, always use setjmp/longjmp and jmp_buf.
* libguile/_scm.h (SCM_I_SETJMP, SCM_I_LONGJMP): Remove; instead use
setjmp and longjmp.
* libguile/continuations.c (capture_auxiliary_stack):
(restore_auxiliary_stack): New helpers.
(scm_i_make_continuation): Use capture_auxiliary_stack.
(copy_stack_and_call): Use restore_auxiliary_stack. No need to stash
the aux stack on the thread, either.
* libguile/continuations.h (scm_t_contregs): Use
SCM_HAVE_AUXILIARY_STACK to flag when to have an auxiliary_stack
member.
* libguile/control.h:
* libguile/control.c (reify_partial_continuation, scm_c_abort):
(scm_suspendable_continuation_p): Adapt to use setjmp/longjmp
directly.
* libguile/deprecated.h: Add deprecated scm_i_jmp_buf define.
* libguile/dynstack.h:
* libguile/dynstack.c (PROMPT_JMPBUF):
(scm_dynstack_push_prompt, scm_dynstack_find_prompt):
(scm_dynstack_wind_prompt): Adapt to jmp_buf type.
* libguile/eval.c (eval): Use jmp_buf and setjmp directly.
* libguile/gc-malloc.c: No need for ia64-specific things.
* libguile/gc.c: No need for ia64-specific things.
* libguile/gc.h: No need to declare scm_ia64_ar_bsp.
* libguile/init.c: Remove typedef of setjmp_type for Cray, unused.
* libguile/threads.c (guilify_self_1): No more pending_rbs_continuation
in scm_i_thread, and register_backing_store_base is handled by libgc.
(scm_ia64_ar_bsp): Remove definitions; inlined into continuations.c's
capture_auxiliary_stack.
* libguile/threads.h (scm_i_thread): jmpbuf member is plain jmp_buf.
* libguile/throw.c (catch): Just use jmp_buf and setjmp.
* libguile/vm-engine.c (VM_NAME): Adapt prototype to take jmp_buf
pointer.
* libguile/vm.c (vm_abort): Adapt jmp_buf types.
(scm_call_n): Use setjmp.
* libguile/bytevectors.h: Include uniform.h, for use in the macros.
* libguile/extensions.h: Include libpath.h, for the
SCM_EFFECTIVE_VERSION, which is almost always used with these
routines.
* libguile/frames.h:
* libguile/instructions.h:
* libguile/intrinsics.h:
* libguile/loader.h:
* libguile/programs.h:
* libguile/vm.h: Include <libguile/__scm.h> instead of <libguile.h>.
Cuts a circular include, but also precipitates a lot of maintenance in
the .c files.
* libguile/*.c: Update C files to add needed all needed includes that
before were getting automatically pulled in by the indirect inclusion
of libguile.h.
Fixes <https://bugs.gnu.org/29151> and <https://bugs.gentoo.org/613986>.
Backtrace looks like that:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x200000000014a5c0 in scm_ia64_longjmp (JB=0x6000000000817020, VAL=1) at continuations.c:372
372 t->pending_rbs_continuation->backing_store,
[Current thread is 1 (Thread 0x2000000000049340 (LWP 8190))]
(gdb) bt
#0 0x200000000014a5c0 in scm_ia64_longjmp (JB=0x6000000000817020, VAL=1) at continuations.c:372
#1 0x2000000000148e00 in scm_c_abort (vm=0x60000000000edea0, tag=0x6000000000795ba0, n=0, argv=0x60000fffff7f0ce0, cookie=-1) at control.c:239
#2 0x2000000000149070 in scm_at_abort (tag=0x6000000000795ba0, args=0x304) at control.c:258
(gdb) print t
$2 = (scm_i_thread *) 0x6000000000068000
(gdb) print t->pending_rbs_continuation
$3 = (scm_t_contregs *) 0xffeb
The problem here is the value of 't->pending_rbs_continuation' pointer.
It's supposed to poin to a register stack pointer or be NULL if not yet
backed up.
The problem is it is never initialized to NULL at creation time and
contained garbage on stack. Sometimes people are lucky and have zeros
on stack and guile works. But sometimes there is something and guile
crashes.
The fix is trivial: initialize 'pending_rbs_continuation = NULL'
at thread registration time (the same way other threads are registered).
Reported-by: Matt Turner
* libguile/threads.c (guilify_self_1): Initialize pending_rbs_continuation
to avoid crash on ia64.
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
* libguile/fluids.h (struct scm_dynamic_state): Add thread_local_values
table. Thread locals are flushed to a separate thread-local table.
The references are strong references since the table never escapes the
thread.
(scm_make_thread_local_fluid, scm_fluid_thread_local_p): New
functions.
* libguile/fluids.c (FLUID_F_THREAD_LOCAL):
(SCM_I_FLUID_THREAD_LOCAL_P): New macros.
(restore_dynamic_state): Add comment about precondition.
(save_dynamic_state): Flush thread locals.
(scm_i_fluid_print): Print thread locals nicely.
(new_fluid): Add flags arg.
(scm_make_fluid, scm_make_fluid_with_default, scm_make_unbound_fluid):
Adapt.
(scm_make_thread_local_fluid, scm_fluid_thread_local_p): New
functions.
(fluid_set_x): Special flushing logic for thread-locals.
(fluid_ref): Special cache miss logic for thread locals.
* libguile/stacks.c (scm_init_stacks):
* libguile/throw.c (scm_init_throw): %stacks and %exception-handler are
thread-locals.
* libguile/threads.c (guilify_self_2): Init thread locals table.
* test-suite/tests/fluids.test ("dynamic states"): Add test.
* doc/ref/api-control.texi (Fluids and Dynamic States): Add link to
Thread-Local Variables.
* doc/ref/api-scheduling.texi (Thread Local Variables): Update with real
thread-locals.
* NEWS: Update.
* libguile/threads.h (scm_i_thread): Add bool tracking whether the
thread needs to be unregistered from libgc.
* libguile/threads.c (guilify_self_1): Add needs_unregister arg.
(on_thread_exit): Only unregister thread if the thread needs it.
(scm_i_init_thread_for_guile): A thread needs unregistering if
GC_register_my_thread succeeded.
(scm_threads_prehistory): Don't unregister initial thread.
Fixes#19523. Thanks to Anthonin Bonnefoy for the report.
* libguile/threads.c (struct launch_data): Add prev/next pointers.
(protected_launch_data, protected_launch_data_lock): New static vars.
(protect_launch_data, unprotect_launch_data): New functions.
(really_launch, scm_sys_call_with_new_thread): Preserve launch data
from GC. Thanks to Linas Vepstas for the report!
* libguile/threads.c (really_launch): Start threads with asyncs
blocked.
* module/ice-9/threads.scm (call-with-new-thread): Unblock asyncs once
we have the bookkeeping sorted out. Don't use
with-continuation-barrier; it's not needed. Print nice thread
backtraces.