... when alloc() is called and when calling into Lisp.
that matter) never wait for another thread that's not in
@code{WITHOUT-GCING}.
+Somewhat of a special case, it is enforced by the runtime that
+@code{SIG_STOP_FOR_GC} and @code{SIG_RESUME_FROM_GC} always unblocked
+when we might trigger a gc (i.e. on alloc or calling into Lisp).
+
@subsection Calling user code
For the reasons above, calling user code, i.e. functions passed in, or
lispobj *result;
struct thread *th = arch_os_get_current_thread();
+ /* SIG_STOP_FOR_GC needs to be enabled before we can call lisp:
+ * otherwise two threads racing here may deadlock: the other will
+ * wait on the GC lock, and the other cannot stop the first
+ * one... */
+ check_gc_signals_unblocked_or_lose();
+
/* FIXME: OOAO violation: see arch_pseudo_* */
set_pseudo_atomic_atomic(th);
result = general_alloc(bytes, page_type_flag);
fake_foreign_function_call(context);
+ unblock_gc_signals();
context_sap = alloc_sap(context);
code = find_code(context);
fake_foreign_function_call(context);
+ unblock_gc_signals();
context_sap = alloc_sap(context);
code = find_code(context);
codeptr = (struct code *)native_pointer(code);
#include "sbcl.h"
#include "runtime.h"
#include "globals.h"
+#include "os.h"
+#include "interrupt.h"
/* This is implemented in assembly language and called from C: */
extern lispobj call_into_lisp(lispobj fun, lispobj *args, int nargs);
+static inline lispobj
+safe_call_into_lisp(lispobj fun, lispobj *args, int nargs)
+{
+ /* SIG_STOP_FOR_GC needs to be enabled before we can call lisp:
+ * otherwise two threads racing here may deadlock: the other will
+ * wait on the GC lock, and the other cannot stop the first
+ * one... */
+ check_gc_signals_unblocked_or_lose();
+ return call_into_lisp(fun, args, nargs);
+}
+
#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
/* These functions are an interface to the Lisp call-in facility.
* Since this is C we can know nothing about the calling environment.
lispobj *args = NULL;
FSHOW((stderr, "/entering funcall0(0x%lx)\n", (long)function));
- return call_into_lisp(function, args, 0);
+ return safe_call_into_lisp(function, args, 0);
}
lispobj
funcall1(lispobj function, lispobj arg0)
{
lispobj args[1];
args[0] = arg0;
- return call_into_lisp(function, args, 1);
+ return safe_call_into_lisp(function, args, 1);
}
lispobj
lispobj args[2];
args[0] = arg0;
args[1] = arg1;
- return call_into_lisp(function, args, 2);
+ return safe_call_into_lisp(function, args, 2);
}
lispobj
args[0] = arg0;
args[1] = arg1;
args[2] = arg2;
- return call_into_lisp(function, args, 3);
+ return safe_call_into_lisp(function, args, 3);
}
#else
{
lispobj *args = current_control_stack_pointer;
- return call_into_lisp(function, args, 0);
+ return safe_call_into_lisp(function, args, 0);
}
lispobj
current_control_stack_pointer += 1;
args[0] = arg0;
- return call_into_lisp(function, args, 1);
+ return safe_call_into_lisp(function, args, 1);
}
lispobj
args[0] = arg0;
args[1] = arg1;
- return call_into_lisp(function, args, 2);
+ return safe_call_into_lisp(function, args, 2);
}
lispobj
args[1] = arg1;
args[2] = arg2;
- return call_into_lisp(function, args, 3);
+ return safe_call_into_lisp(function, args, 3);
}
#endif
/* Allocate the SAP object while the interrupts are still
* disabled. */
+ unblock_gc_signals();
context_sap = alloc_sap(context);
#ifndef LISP_FEATURE_WIN32
* Yeah, but non-gencgc platforms don't really wrap allocation
* in PA. MG - 2005-08-29 */
- lispobj info_sap,context_sap = alloc_sap(context);
- info_sap = alloc_sap(info);
+ lispobj info_sap, context_sap;
/* Leave deferrable signals blocked, the handler itself will
* allow signals again when it sees fit. */
-#ifdef LISP_FEATURE_SB_THREAD
- {
- sigset_t unblock;
- sigemptyset(&unblock);
- sigaddset(&unblock, SIG_STOP_FOR_GC);
-#ifdef SIG_RESUME_FROM_GC
- sigaddset(&unblock, SIG_RESUME_FROM_GC);
-#endif
- thread_sigmask(SIG_UNBLOCK, &unblock, 0);
- }
-#endif
+ unblock_gc_signals();
+ context_sap = alloc_sap(context);
+ info_sap = alloc_sap(info);
FSHOW_SIGNAL((stderr,"/calling Lisp-level handler\n"));
void
arrange_return_to_lisp_function(os_context_t *context, lispobj function)
{
+ check_gc_signals_unblocked_in_sigset_or_lose
+ (os_context_sigmask_addr(context));
#if !(defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64))
void * fun=native_pointer(function);
void *code = &(((struct simple_fun *) fun)->code);
{
lispobj context_sap;
fake_foreign_function_call(context);
+ unblock_gc_signals();
context_sap = alloc_sap(context);
#ifndef LISP_FEATURE_WIN32
thread_sigmask(SIG_SETMASK, os_context_sigmask_addr(context), 0);
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.25.34"
+"1.0.25.35"