- /* FIXME: This code is exactly the same as the code in the
- * other leg of the if(..), and should be factored out into
- * a shared function. */
- pending_signal = signal;
- memcpy(&pending_info, info, sizeof(siginfo_t));
- memcpy(&pending_mask,
+boolean
+maybe_defer_handler(void *handler, struct interrupt_data *data,
+ int signal, siginfo_t *info, os_context_t *context)
+{
+ struct thread *thread=arch_os_get_current_thread();
+ if (SymbolValue(INTERRUPTS_ENABLED,thread) == NIL) {
+ store_signal_data_for_later(data,handler,signal,info,context);
+ SetSymbolValue(INTERRUPT_PENDING, T,thread);
+ return 1;
+ }
+ /* a slightly confusing test. arch_pseudo_atomic_atomic() doesn't
+ * actually use its argument for anything on x86, so this branch
+ * may succeed even when context is null (gencgc alloc()) */
+ if (
+#ifndef LISP_FEATURE_X86
+ (!foreign_function_call_active) &&
+#endif
+ arch_pseudo_atomic_atomic(context)) {
+ store_signal_data_for_later(data,handler,signal,info,context);
+ arch_set_pseudo_atomic_interrupted(context);
+ return 1;
+ }
+ return 0;
+}
+static void
+store_signal_data_for_later (struct interrupt_data *data, void *handler,
+ int signal,
+ siginfo_t *info, os_context_t *context)
+{
+ data->pending_handler = handler;
+ data->pending_signal = signal;
+ if(info)
+ memcpy(&(data->pending_info), info, sizeof(siginfo_t));
+ if(context) {
+ /* the signal mask in the context (from before we were
+ * interrupted) is copied to be restored when
+ * run_deferred_handler happens. Then the usually-blocked
+ * signals are added to the mask in the context so that we are
+ * running with blocked signals when the handler returns */
+ sigemptyset(&(data->pending_mask));
+ memcpy(&(data->pending_mask),