no_cpuid_instr:
leave
ret
+\f
+# Call a function (esp[1]) with an argument (esp[2]) and a stack
+# pointer and frame pointer from inside C. When it returns, restore
+# the original stack pointer. This kludge is necessary for operating
+# system libraries (notably NetBSD's libpthread) that store important
+# information in the stack pointer, and get confused when they are
+# called in a signal handler for a signal delivered while Scheme has
+# set esp to something funny.
+
+define_c_label(within_c_stack)
+ OP(mov,l) TW(EVR(C_Stack_Pointer),REG(eax))
+ # Are we currently in C, signalled by having no saved C stack pointer?
+ OP(cmp,l) TW(IMM(0),REG(eax))
+ # Yes: just call the function without messing with esp.
+ je within_c_stack_from_c
+ # No: we have to switch esp to point into the C stack.
+ OP(push,l) REG(ebp) # Save frame pointer
+ OP(mov,l) TW(REG(esp),REG(ebp))
+ OP(mov,l) TW(REG(eax),REG(esp)) # Switch to C stack
+ OP(push,l) REG(ebp) # Save stack pointer
+ OP(push,l) LOF(HEX(c),REG(ebp)) # Push argument
+ call IJMP(LOF(8,REG(ebp))) # Call function
+
+define_debugging_label(within_c_stack_restore)
+ OP(pop,l) REG(eax) # Pop argument
+ OP(pop,l) REG(esp) # Restore stack pointer
+ # and switch back to
+ # Scheme stack
+ OP(pop,l) REG(ebp) # Restore frame pointer
+ ret
+
+define_debugging_label(within_c_stack_from_c)
+ OP(push,l) REG(ebp) # Save a frame pointer,
+ OP(mov,l) TW(REG(esp),REG(ebp)) # for debuggers.
+ OP(push,l) LOF(HEX(c),REG(ebp)) # Push argument
+ call IJMP(LOF(8,REG(ebp)))
+ leave
+ ret
+
define_c_label(C_to_interface)
OP(push,l) REG(ebp) # Link according
OP(mov,l) TW(EVR(C_Stack_Pointer),REG(esp))
OP(mov,l) TW(EVR(C_Frame_Pointer),REG(ebp))
+ # Signal to within_c_stack that we are now in C land.
+ OP(mov,l) TW(IMM(0),EVR(C_Stack_Pointer))
+
OP(sub,l) TW(IMM(8),REG(esp)) # alloc struct return
OP(push,l) LOF(REGBLOCK_UTILITY_ARG4(),regs) # push utility args
OP(mov,l) TW(LOF(REGBLOCK_VAL(),regs),REG(eax)) # Value/dynamic link
OP(mov,l) TW(IMM(ADDRESS_MASK),rmask) # = %ebp
+ # Restore the C stack pointer, which we zeroed back in
+ # scheme_to_interface, for within_c_stack.
+ OP(mov,l) TW(REG(esp),EVR(C_Stack_Pointer))
OP(mov,l) TW(EVR(stack_pointer),REG(esp))
OP(mov,l) TW(REG(eax),REG(ecx)) # Preserve if used
OP(and,l) TW(rmask,REG(ecx)) # Restore potential dynamic link
leave
ret
+# Call a function (rdi) with an argument (rsi) and a stack pointer and
+# frame pointer from inside C. When it returns, restore the original
+# stack pointer. This kludge is necessary for operating system
+# libraries (notably NetBSD's libpthread) that store important
+# information in the stack pointer, and get confused when they are
+# called in a signal handler for a signal delivered while Scheme has
+# set esp to something they consider funny.
+
+define_c_label(within_c_stack)
+ OP(mov,q) TW(ABS(EVR(C_Stack_Pointer)),REG(rax))
+ # Are we currently in C, signalled by having no saved C stack pointer?
+ OP(cmp,q) TW(IMM(0),REG(rax))
+ # Yes: just call the function without messing with rsp.
+ je within_c_stack_from_c
+ # No: we have to switch rsp to point into the C stack.
+ OP(push,q) REG(rbp) # Save frame pointer
+ OP(mov,q) TW(REG(rsp),REG(rbp))
+ OP(mov,q) TW(REG(rax),REG(rsp)) # Switch to C stack
+ OP(push,q) REG(rbp) # Save stack pointer
+ OP(mov,q) TW(REG(rdi),REG(rax)) # arg1 (fn) -> rax
+ OP(mov,q) TW(REG(rsi),REG(rdi)) # arg2 (arg) -> arg1
+ call IJMP(REG(rax)) # call fn(arg)
+
+define_debugging_label(within_c_stack_restore)
+ OP(pop,q) REG(rsp) # Restore stack pointer
+ # and switch back to
+ # Scheme stack
+ OP(pop,q) REG(rbp) # Restore frame pointer
+ ret
+
+define_debugging_label(within_c_stack_from_c)
+ OP(mov,q) TW(REG(rdi),REG(rax)) # arg1 (fn) -> rax
+ OP(mov,q) TW(REG(rsi),REG(rdi)) # arg2 (arg) -> arg1
+ jmp IJMP(REG(rax)) # tail-call fn(arg)
+\f
# C_to_interface passes control from C into Scheme. To C it is a
# unary procedure; its one argument is passed in rdi. It saves the
# state of the C world (the C frame pointer and stack pointer) and
OP(mov,q) TW(ABS(EVR(C_Stack_Pointer)),REG(rsp))
OP(mov,q) TW(ABS(EVR(C_Frame_Pointer)),REG(rbp))
+ # Signal to within_c_stack that we are now in C land.
+ OP(mov,q) TW(IMM(0),ABS(EVR(C_Stack_Pointer)))
+
OP(sub,q) TW(IMM(16),REG(rsp)) # alloc struct return
OP(mov,q) TW(REG(rsp),REG(rdi)) # Structure is first argument.
OP(mov,q) TW(REG(rbx),REG(rsi)) # rbx -> second argument.
OP(mov,q) TW(ABS(EVR(Free)),rfree) # Free pointer = %rdi
OP(mov,q) TW(QOF(REGBLOCK_VAL(),regs),REG(rax)) # Value/dynamic link
OP(mov,q) TW(IMM(ADDRESS_MASK),rmask) # = %rbp
+ # Restore the C stack pointer, which we zeroed back in
+ # scheme_to_interface, for within_c_stack.
+ OP(mov,q) TW(REG(rsp),ABS(EVR(C_Stack_Pointer)))
OP(mov,q) TW(ABS(EVR(stack_pointer)),REG(rsp))
OP(mov,q) TW(REG(rax),REG(rcx)) # Preserve if used
OP(and,q) TW(rmask,REG(rcx)) # Restore potential dynamic link
#endif
extern int ASM_ENTRY_POINT (i386_interface_initialize) (void);
+extern void ASM_ENTRY_POINT (within_c_stack) (void (*) (void *), void *);
extern void asm_assignment_trap (void);
extern void asm_dont_serialize_cache (void);
#endif
extern void ASM_ENTRY_POINT (x86_64_fpe_reset_traps) (void);
+extern void ASM_ENTRY_POINT (within_c_stack) (void (*) (void *), void *);
extern void asm_assignment_trap (void);
extern void asm_dont_serialize_cache (void);
# endif
#endif
\f
+#if defined(CC_IS_NATIVE) && !defined(SIGNAL_HANDLERS_CAN_USE_SCHEME_STACK)
+
+struct signal_instance
+{
+ int signo;
+ SIGINFO_T info;
+ SIGCONTEXT_ARG_T * pscp;
+};
+
+# define DEFUN_STD_HANDLER(name, statement) \
+ \
+DEFUN_STD_HANDLER_ (name##_body, statement) \
+ \
+void \
+name##_wrapper (void *context) \
+{ \
+ struct signal_instance *i = context; \
+ (void) name##_body ((i->signo), (i->info), (i->pscp)); \
+} \
+ \
+Tsignal_handler_result \
+name (int signo, SIGINFO_T info, SIGCONTEXT_ARG_T * pscp) \
+{ \
+ struct signal_instance i; \
+ (i.signo) = signo; \
+ (i.info) = info; \
+ (i.pscp) = pscp; \
+ within_c_stack ((&name##_wrapper), (&i)); \
+ SIGNAL_HANDLER_RETURN (); \
+}
+
+#else
+
+# define DEFUN_STD_HANDLER DEFUN_STD_HANDLER_
+
+#endif /* CC_SUPPORT_P && !SIGNAL_HANDLERS_CAN_USE_SCHEME_STACK */
+
#ifndef NEED_HANDLER_TRANSACTION
-#define DEFUN_STD_HANDLER(name, statement) \
+#define DEFUN_STD_HANDLER_(name, statement) \
Tsignal_handler_result \
name (int signo, \
SIGINFO_T info, \
Tsignal_handler handler;
};
-#define DEFUN_STD_HANDLER(name, statement) \
+#define DEFUN_STD_HANDLER_(name, statement) \
Tsignal_handler_result \
name (int signo, \
SIGINFO_T info, \