much pain.
\begin{code}
-
#include "platform.h"
#if defined(sunos4_TARGET_OS)
# define NON_POSIX_SOURCE
#endif
+#if defined(freebsd_TARGET_OS)
+# define NON_POSIX_SOURCE
+#endif
+
#if defined(osf1_TARGET_OS)
/* The include files for OSF1 do not normally define SA_SIGINFO */
# define _OSF_SOURCE 1
#endif
-#if defined(linuxaout_TARGET_OS) || defined(linux_TARGET_OS)
- /* I have no idea why this works (WDP 95/03) */
-# define _BSD_SOURCE 1
+#if irix_TARGET_OS
+/* SIGVTALRM not avail w/ POSIX_SOURCE, but worse things happen without */
+/* SIGH: triple SIGH (WDP 95/07) */
+# define SIGVTALRM 28
#endif
#include "rtsdefs.h"
#if defined(HAVE_SIGNAL_H)
# include <signal.h>
#endif
-#if irix_TARGET_OS
-/* SIGVTALRM not avail w/ POSIX_SOURCE, but worse things happen without */
-/* SIGH: triple SIGH (WDP 95/07) */
-# define SIGVTALRM 28
+
+#if defined(linux_TARGET_OS) || defined(linuxaout_TARGET_OS)
+ /* to look *inside* sigcontext... */
+# include <asm/signal.h>
#endif
#if defined(HAVE_SIGINFO_H)
fault.
\begin{code}
-
#if STACK_CHECK_BY_PAGE_FAULT
extern P_ stks_space; /* Where the stacks live, from SMstacks.lc */
-extern I_ SM_word_stk_size; /* How big they are (ditto) */
-
\end{code}
SunOS 4.x is too old to have @SA_SIGINFO@ as a flag to @sigaction@, so
Fun, eh?
\begin{code}
-
-# if defined(sunos4_TARGET_OS) || defined(linuxaout_TARGET_OS) || defined(linux_TARGET_OS)
+# if defined(sunos4_TARGET_OS) || defined(freebsd_TARGET_OS) \
+ || defined(linux_TARGET_OS) || defined(linuxaout_TARGET_OS)
static void
-segv_handler(sig, code, scp, addr)
- int sig;
- int code;
- struct sigcontext *scp;
- caddr_t addr;
+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 */
+ struct sigcontext_struct scp)
+# endif /* linux */
{
extern void StackOverflow(STG_NO_ARGS) STG_NORETURN;
+# if defined(linux_TARGET_OS) || defined(linuxaout_TARGET_OS)
+ caddr_t addr = scp.cr2;
+ /* Magic info from Tommy Thorn! */
+# endif
+
if (addr >= (caddr_t) stks_space
- && addr < (caddr_t) (stks_space + SM_word_stk_size))
+ && addr < (caddr_t) (stks_space + RTSflags.GcFlags.stksSize))
StackOverflow();
fflush(stdout);
}
int
-install_segv_handler()
+install_segv_handler(void)
{
- return (int) signal(SIGSEGV, segv_handler) == -1;
+#if freebsd_TARGET_OS
+ /* FreeBSD seems to generate SIGBUS for stack overflows */
+ if (signal(SIGBUS, segv_handler) == SIG_ERR)
+ return -1;
+ return ((int) signal(SIGSEGV, segv_handler));
+#else
+ return ((int) signal(SIGSEGV, segv_handler) == SIG_ERR);
+ /* I think the "== SIG_ERR" is saying "there was no
+ handler for SIGSEGV before this one". WDP 95/12
+ */
+#endif
}
-# else /* Not SunOS 4 */
+# else /* Not SunOS 4, FreeBSD, or Linux(a.out) */
# if defined(irix_TARGET_OS)
/* certainly BOGUS (WDP 94/05) -- copied from /usr/include/sys/siginfo.h */
# endif
static void
-segv_handler(sig, sip)
- int sig;
- siginfo_t *sip;
+segv_handler(int sig, siginfo_t *sip)
+ /* NB: the second "siginfo_t" argument is not really standard */
{
fflush(stdout);
if (sip == NULL) {
fprintf(stderr, "Segmentation fault caught, address unknown\n");
} else {
if (sip->si_addr >= (caddr_t) stks_space
- && sip->si_addr < (caddr_t) (stks_space + SM_word_stk_size))
+ && sip->si_addr < (caddr_t) (stks_space + RTSflags.GcFlags.stksSize))
StackOverflow();
fprintf(stderr, "Segmentation fault caught, address = %08lx\n", (W_) sip->si_addr);
}
int
-install_segv_handler()
+install_segv_handler(STG_NO_ARGS)
{
struct sigaction action;
action.sa_handler = segv_handler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_SIGINFO;
+
return sigaction(SIGSEGV, &action, NULL);
}
here.
\begin{code}
-#if (defined(USE_COST_CENTRES) || defined(CONCURRENT)) && !defined(GRAN)
-
-# if defined(USE_COST_CENTRES)
-extern I_ heap_profiling_req;
-# endif
+#if defined(PROFILING) || defined(CONCURRENT) /* && !defined(GRAN) */
# ifdef CONCURRENT
-# if defined(USE_COST_CENTRES) || defined(GUM)
-I_ contextSwitchTicks;
-I_ profilerTicks;
-# endif
-
+extern I_ delayTicks;
+
# ifdef PAR
extern P_ CurrentTSO;
# endif
-extern I_ contextSwitchTime;
static void
-vtalrm_handler(sig)
- int sig;
+vtalrm_handler(int sig)
{
/*
For the parallel world, currentTSO is set if there is any work
in case other PEs have sent us messages which must be processed.
*/
-# if defined(USE_COST_CENTRES) || defined(GUM)
+# if defined(PROFILING) || defined(PAR)
static I_ csTicks = 0, pTicks = 0;
if (time_profiling) {
- if (++pTicks % profilerTicks == 0) {
-# if ! defined(USE_COST_CENTRES)
+ if (++pTicks % RTSflags.CcFlags.profilerTicks == 0) {
+# if ! defined(PROFILING)
handle_tick_serial();
# else
- if (cc_profiling > 1 || heap_profiling_req != HEAP_NO_PROFILING)
+ if (RTSflags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE
+ || RTSflags.ProfFlags.doHeapProfile)
handle_tick_serial();
else
handle_tick_noserial();
# endif
}
- if (++csTicks % contextSwitchTicks != 0)
+ if (++csTicks % RTSflags.CcFlags.ctxtSwitchTicks != 0)
return;
}
# endif
- if (WaitingThreadsHd != Nil_closure)
- AwaitEvent(contextSwitchTime);
+ /*
+ Handling a tick for threads blocked waiting for file
+ descriptor I/O or time.
+
+ This requires some care since virtual time alarm ticks
+ can occur when we are in the GC. If that is the case,
+ we just increment a delayed timer tick counter, but do
+ not check to see if any TSOs have been made runnable
+ as a result. (Do a bulk update of their status once
+ the GC has completed).
+
+ If the vtalrm does not occur within GC, we try to promote
+ any of the waiting threads to the runnable list (see awaitEvent)
+
+ 4/96 SOF
+ */
+
+ if (delayTicks != 0) /* delayTicks>0 => don't handle timer expiry (in GC) */
+ delayTicks++;
+ else if (WaitingThreadsHd != Prelude_Z91Z93_closure)
+ AwaitEvent(RTSflags.ConcFlags.ctxtSwitchTime);
# ifdef PAR
if (PendingSparksTl[REQUIRED_POOL] == PendingSparksLim[REQUIRED_POOL] ||
PendingSparksTl[ADVISORY_POOL] == PendingSparksLim[ADVISORY_POOL]) {
PruneSparks();
- if (PendingSparksTl[REQUIRED_POOL] == PendingSparksLim[REQUIRED_POOL])
+ if (PendingSparksTl[REQUIRED_POOL] == PendingSparksLim[REQUIRED_POOL])
PendingSparksTl[REQUIRED_POOL] = PendingSparksBase[REQUIRED_POOL] +
SparkLimit[REQUIRED_POOL] / 2;
- if (PendingSparksTl[ADVISORY_POOL] == PendingSparksLim[ADVISORY_POOL])
+ if (PendingSparksTl[ADVISORY_POOL] == PendingSparksLim[ADVISORY_POOL]) {
PendingSparksTl[ADVISORY_POOL] = PendingSparksBase[ADVISORY_POOL] +
SparkLimit[ADVISORY_POOL] / 2;
+ sparksIgnored += SparkLimit[REQUIRED_POOL] / 2;
+ }
}
if (CurrentTSO != NULL ||
# else
- if (RunnableThreadsHd != Nil_closure ||
+ if (RunnableThreadsHd != Prelude_Z91Z93_closure ||
# endif
PendingSparksHd[REQUIRED_POOL] < PendingSparksTl[REQUIRED_POOL] ||
PendingSparksHd[ADVISORY_POOL] < PendingSparksTl[ADVISORY_POOL]) {
# endif
-# if defined(sunos4_TARGET_OS) || defined(linuxaout_TARGET_OS) || defined(linux_TARGET_OS)
+# if defined(sunos4_TARGET_OS)
int
-install_vtalrm_handler()
+install_vtalrm_handler(void)
{
void (*old)();
# ifdef CONCURRENT
old = signal(SIGVTALRM, vtalrm_handler);
# else
- if (cc_profiling > 1 || heap_profiling_req != HEAP_NO_PROFILING)
+ if (RTSflags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE
+ || RTSflags.ProfFlags.doHeapProfile)
old = signal(SIGVTALRM, handle_tick_serial);
else
old = signal(SIGVTALRM, handle_tick_noserial);
# endif
- return (int) old == -1;
+ return ((int) old == SIG_ERR);
}
static int vtalrm_mask;
# ifdef CONCURRENT
action.sa_handler = vtalrm_handler;
# else
- if (cc_profiling > 1 || heap_profiling_req != HEAP_NO_PROFILING)
+ if (RTSflags.CcFlags.doCostCentres >= COST_CENTRES_VERBOSE
+ || RTSflags.ProfFlags.doHeapProfile)
action.sa_handler = handle_tick_serial;
else
action.sa_handler = handle_tick_noserial;
(void) sigprocmask(SIG_UNBLOCK, &signals, NULL);
}
-# endif /* SunOS 4 */
+# endif /* ! SunOS 4 */
-#endif /* USE_COST_CENTRES || CONCURRENT (but not GRAN) */
+#endif /* PROFILING || CONCURRENT (but not GRAN) */
\end{code}
\begin{code}
-#ifdef PAR
+#if defined(PAR) /* || defined(GRAN) */
void
-blockUserSignals()
+blockUserSignals(void)
{
return;
}
void
-unblockUserSignals()
+unblockUserSignals(void)
{
return;
}
# include <setjmp.h>
-extern StgPtr deRefStablePointer PROTO((StgStablePtr));
-extern void freeStablePointer PROTO((I_));
+StgPtr deRefStablePointer PROTO((StgStablePtr));
+void freeStablePointer PROTO((I_));
extern jmp_buf restart_main;
static I_ *handlers = NULL; /* Dynamically grown array of signal handlers */
static I_ nHandlers = 0; /* Size of handlers array */
static void
-more_handlers(sig)
- I_ sig;
+more_handlers(I_ sig)
{
I_ i;
if (handlers == NULL) {
fflush(stdout);
- fprintf(stderr, "VM exhausted\n");
+ fprintf(stderr, "VM exhausted (in more_handlers)\n");
EXIT(EXIT_FAILURE);
}
for(i = nHandlers; i <= sig; i++)
nHandlers = sig + 1;
}
+I_ nocldstop = 0;
+
# ifdef _POSIX_SOURCE
static void
-generic_handler(sig)
+generic_handler(int sig)
{
sigset_t signals;
SAVE_Hp = SAVE_HpLim; /* Just to be safe */
- if (initStacks(&StorageMgrInfo) != 0) {
+ if (! initStacks(&StorageMgrInfo)) {
fflush(stdout);
fprintf(stderr, "initStacks failed!\n");
EXIT(EXIT_FAILURE);
static sigset_t savedSignals;
void
-initUserSignals()
+initUserSignals(void)
{
sigemptyset(&userSignals);
}
void
-blockUserSignals()
+blockUserSignals(void)
{
sigprocmask(SIG_SETMASK, &userSignals, &savedSignals);
}
void
-unblockUserSignals()
+unblockUserSignals(void)
{
sigprocmask(SIG_SETMASK, &savedSignals, NULL);
}
-I_ nocldstop = 0;
-
I_
sig_install(sig, spi, mask)
I_ sig;
sigemptyset(&action.sa_mask);
action.sa_flags = sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
+
if (sigaction(sig, &action, NULL) || sigprocmask(SIG_UNBLOCK, &signals, NULL)) {
if (previous_spi)
freeStablePointer(handlers[sig]);
generic_handler(sig)
{
SAVE_Hp = SAVE_HpLim; /* Just to be safe */
- if (initStacks(&StorageMgrInfo) != 0) {
+ if (! initStacks(&StorageMgrInfo)) {
fflush(stdout);
fprintf(stderr, "initStacks failed!\n");
EXIT(EXIT_FAILURE);
static int savedSignals;
void
-initUserSignals()
+initUserSignals(void)
{
userSignals = 0;
}
void
-blockUserSignals()
+blockUserSignals(void)
{
savedSignals = sigsetmask(userSignals);
}
void
-unblockUserSignals()
+unblockUserSignals(void)
{
sigsetmask(savedSignals);
}
{
I_ previous_spi;
int mask;
- void (*handler)();
+ void (*handler)(int);
/* Block the signal until we figure out what to do */
/* Count on this to fail if the signal number is invalid */
return previous_spi;
}
-# endif /* POSIX */
+# endif /* !POSIX */
#endif /* PAR */