much pain.
\begin{code}
-#include "platform.h"
+#include "config.h"
+/* Treat nexttep3 and sunos4 alike. CaS */
+#if defined(nextstep3_TARGET_OS)
+# define NON_POSIX_SOURCE
+#endif
+
#if defined(sunos4_TARGET_OS)
/* The sigaction in SunOS 4.1.X does not grok SA_SIGINFO */
# define NON_POSIX_SOURCE
#endif
-#if defined(freebsd_TARGET_OS)
+#if defined(freebsd_TARGET_OS)
# define NON_POSIX_SOURCE
#endif
-#if defined(osf1_TARGET_OS)
+#if defined(osf3_TARGET_OS) || defined(osf1_TARGET_OS)
/* The include files for OSF1 do not normally define SA_SIGINFO */
# define _OSF_SOURCE 1
#endif
# include <sys/types.h>
#endif
+ /* This is useful with the particular set of header files on my NeXT.
+ * CaS
+ */
+#if defined(HAVE_SYS_SIGNAL_H)
+# include <sys/signal.h>
+#endif
+
#if defined(HAVE_SIGNAL_H)
# include <signal.h>
#endif
#if defined(linux_TARGET_OS) || defined(linuxaout_TARGET_OS)
- /* to look *inside* sigcontext... */
-# include <asm/signal.h>
+/* to look *inside* sigcontext...
+
+ sigcontext has moved and been protected from the General Public,
+ in later versions (>2), the sigcontext decl is protected by
+ a __KERNEL__ #ifdef. As ever, we workaround by trying to
+ be version savvy - the version numbers are currently just a guess!
+ (ToDo: determine at what version no. the sigcontext move
+ was made).
+*/
+# ifndef LINUX_VERSION_CODE
+# include <linux/version.h>
+# endif
+/* Snaffled from drivers/scsi/eata.c in 2.0.30 sources */
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+# if ( LINUX_VERSION_CODE < LinuxVersionCode(2,0,0) )
+# include <asm/signal.h>
+# else
+# include <asm/sigcontext.h>
+# endif
+
#endif
#if defined(HAVE_SIGINFO_H)
#endif
#if defined(cygwin32_TARGET_OS)
-#include <windows.h>
+# include <windows.h>
#endif
\end{code}
\begin{code}
#if STACK_CHECK_BY_PAGE_FAULT
+ /* NB: At the moment, this is always false on nextstep3. CaS. */
extern P_ stks_space; /* Where the stacks live, from SMstacks.lc */
\end{code}
\begin{code}
# if defined(sunos4_TARGET_OS) || defined(freebsd_TARGET_OS) \
- || defined(linux_TARGET_OS) || defined(linuxaout_TARGET_OS)
+ || defined(linux_TARGET_OS) || defined(linuxaout_TARGET_OS) \
+ || defined(aix_TARGET_OS)
static void
segv_handler(int sig,
/* NB: all except first argument are "implementation defined" */
# if defined(sunos4_TARGET_OS) || defined(freebsd_TARGET_OS)
int code, struct sigcontext *scp, caddr_t addr)
-# else /* linux */
+# else /* linux || aix */
+# if defined(aix_TARGET_OS)
+ int code, struct sigcontext *scp)
+# else /* linux */
+ /* sigcontext_struct has been renamed to sigcontext. If
+ compiling this code elicits a bunch of warnings about
+ "struct sigcontext_struct" being undeclared, check to
+ see whether you've got "struct sigcontext" in <asm/sigcontext.h>.
+ or not.
+
+ If you do, lower the version number below to fit the version
+ you're running (and pass us a note saying that you had to - thx!)
+ */
+# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,51)
+ /* sigcontext_struct has been renamed to sigcontext */
+ struct sigcontext scp)
+# else
struct sigcontext_struct scp)
-# endif /* linux */
+# endif
+# endif
+# endif
{
extern void StackOverflow(STG_NO_ARGS) STG_NORETURN;
# if defined(linux_TARGET_OS) || defined(linuxaout_TARGET_OS)
- caddr_t addr = scp.cr2;
+ unsigned long addr = scp.cr2;
/* Magic info from Tommy Thorn! */
# endif
-
- if (addr >= (caddr_t) stks_space
- && addr < (caddr_t) (stks_space + RTSflags.GcFlags.stksSize))
+# if defined(aix_TARGET_OS)
+ caddr_t addr = scp->sc_jmpbuf.jmp_context.o_vaddr;
+ /* Magic guess by andre */
+# endif
+ if ( (char *)addr >= (char *)stks_space
+ && (char *)addr < (char *)(stks_space + RTSflags.GcFlags.stksSize))
StackOverflow();
fflush(stdout);
/* FreeBSD seems to generate SIGBUS for stack overflows */
if (signal(SIGBUS, segv_handler) == SIG_ERR)
return -1;
- return ((int) signal(SIGSEGV, segv_handler));
+ if (signal(SIGSEGV, segv_handler) == SIG_ERR)
+ return -1;
+ return 0;
#else
return ((int) signal(SIGSEGV, segv_handler) == SIG_ERR);
/* I think the "== SIG_ERR" is saying "there was no
#endif
}
-# else /* Not SunOS 4, FreeBSD, or Linux(a.out) */
+# elif defined(irix6_TARGET_OS)
-# if defined(irix_TARGET_OS)
- /* certainly BOGUS (WDP 94/05) -- copied from /usr/include/sys/siginfo.h */
-# define si_addr _data._fault._addr
-# endif
+static void
+segv_handler(int sig, siginfo_t *sip, void *dummy)
+{
+ fflush(stdout);
+ if (sip == NULL) {
+ fprintf(stderr, "Segmentation fault caught, address unknown\n");
+ } else {
+ if (sip->si_addr >= (void *) stks_space
+ && sip->si_addr < (void *) (stks_space + RTSflags.GcFlags.stksSize))
+ StackOverflow();
+ fprintf(stderr, "Segmentation fault caught, address = %08lx\n", (W_) sip->si_addr);
+ }
+ abort();
+}
+
+int
+install_segv_handler(STG_NO_ARGS)
+{
+ struct sigaction action;
+
+ action.sa_sigaction = segv_handler;
+ sigemptyset(&action.sa_mask);
+ action.sa_flags = SA_SIGINFO;
+
+ return sigaction(SIGSEGV, &action, NULL);
+}
+
+# elif defined(cygwin32_TARGET_OS)
-#if defined(cygwin32_TARGET_OS)
/*
- The signal handlers in cygwin32 (beta14) are only passed the signal
+ The signal handlers in cygwin32 are only passed the signal
number, no sigcontext/siginfo is passed as event data..sigh. For
SIGSEGV, to get at the violating address, we need to use the Win32's
- WaitForDebugEvent() to get out any status information.
+ GetThreadContext() to get at the faulting address.
*/
static void
segv_handler(sig)
int sig;
{
- /* From gdb/win32-nat.c */
- DEBUG_EVENT event;
- BOOL t = TRUE; /* WaitForDebugEvent (&event, INFINITE); */
+ CONTEXT context;
+ HANDLE hThread;
+ BOOL t;
+
+ context.ContextFlags = CONTEXT_CONTROL;
+ hThread = GetCurrentThread(); /* cannot fail */
+ t = GetThreadContext(hThread,&context);
fflush(stdout);
if (t == FALSE) {
fprintf(stderr, "Segmentation fault caught, address unknown\n");
} else {
- void *si_addr = event.u.Exception.ExceptionRecord.ExceptionAddress;
+ void *si_addr = context.Eip; /* magic */
if (si_addr >= (void *) stks_space
&& si_addr < (void *) (stks_space + RTSflags.GcFlags.stksSize))
StackOverflow();
return (int) signal(SIGSEGV, segv_handler) == -1;
}
+# else /* ! (cygwin32|irix6|sunos4|linux*|*bsd|aix) */
-#else /* !defined(cygwin32_TARGET_OS) */
+# if defined(irix_TARGET_OS)
+ /* certainly BOGUS (WDP 94/05) -- copied from /usr/include/sys/siginfo.h */
+# define si_addr _data._fault._addr
+# endif
static void
segv_handler(int sig, siginfo_t *sip)
return sigaction(SIGSEGV, &action, NULL);
}
-#endif /* not cygwin32_TARGET_OS */
-
-# endif /* not SunOS 4 */
+# endif /* ! (cygwin32|irix6|sunos4|linux*|*bsd|aix) */
#endif /* STACK_CHECK_BY_PAGE_FAULT */
if (delayTicks != 0) /* delayTicks>0 => don't handle timer expiry (in GC) */
delayTicks++;
- else if (WaitingThreadsHd != Prelude_Z91Z93_closure)
+ else if (WaitingThreadsHd != PrelBase_Z91Z93_closure)
AwaitEvent(RTSflags.ConcFlags.ctxtSwitchTime);
# ifdef PAR
if (CurrentTSO != NULL ||
# else
- if (RunnableThreadsHd != Prelude_Z91Z93_closure ||
+ if (RunnableThreadsHd != PrelBase_Z91Z93_closure ||
# endif
PendingSparksHd[REQUIRED_POOL] < PendingSparksTl[REQUIRED_POOL] ||
PendingSparksHd[ADVISORY_POOL] < PendingSparksTl[ADVISORY_POOL]) {