1
0
mirror of https://github.com/Interlisp/maiko.git synced 2026-01-17 00:22:59 +00:00
Bruce Mitchener 2dcdf14334
Migrate to POSIX signals. (#190)
This removes SYSVSIGNALS as we're always and only using POSIX
signals now.

Some platform differences have been papered over. We used to
only ignore SIGPIPE when using BSD signals, but we now ignore
it all the time.

While the SIGFPE code will now compile, it hasn't been updated
to work on modern OSes fully yet as it will need to enable
the correct FP exceptions.
2021-01-09 04:55:39 +00:00

883 lines
26 KiB
C

/* $Id: timer.c,v 1.5 2001/12/26 22:17:05 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved */
/************************************************************************/
/* */
/* t i m e r . c */
/* */
/* Timer handling routines, plus set-up for the other interrupts */
/* Medley uses on Unix. */
/* */
/************************************************************************/
/************************************************************************/
/* */
/* (C) Copyright 1989-99 Venue. All Rights Reserved. */
/* Manufactured in the United States of America. */
/* */
/************************************************************************/
#include "version.h"
#include <fcntl.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#ifdef DOS
#include <dos.h>
#include <i32.h> /* "#pragma interrupt" & '_chain_intr'*/
/******************************************************************************
* Global variables
******************************************************************************/
void (*prev_int_1c)(); /* keeps address of previous 1c handlr*/
/* used for chaining & restore at exit*/
#pragma interrupt(DOStimer)
void DOStimer();
unsigned long tick_count = 0; /* approx 18 ticks per sec */
#else /* DOS */
#include <sys/resource.h>
#include <sys/time.h>
#endif /* DOS */
#ifdef USE_DLPI
#include <stropts.h>
extern int ether_fd;
#endif
#include "lispemul.h"
#include "emlglob.h"
#include "lspglob.h"
#include "adr68k.h"
#include "lsptypes.h"
#include "arith.h"
#include "lispmap.h"
#include "stack.h"
#include "dbprint.h"
#include "timerdefs.h"
#include "commondefs.h"
#include "mkcelldefs.h"
#include "keyeventdefs.h"
#ifdef XWINDOW
#include "devif.h"
extern DspInterface currentdsp;
#endif /* XWINDOW */
#define LISP_UNIX_TIME_DIFF 29969152
#define LISP_ALTO_TIME_MASK 0x80000000
#define UNIX_ALTO_TIME_DIFF 2177452800U
/* Interlisp time is signed; MIN.FIXP = "01-JAN-01 00:00:00 GMT"
* Interlisp 0 is at "19-Jan-69 12:14:08 PST"
* Unix begins at " 1-Jan-70 0:00:00 GMT"
* (CL:- (IL:IDATE " 1-Jan-70 0:00:00 GMT")
* (IL:IDATE "19-Jan-69 12:14:08 PST"))
* => 29969152, amount to add to Lisp time to get Unix time
* Alto time is unsigned; 0 = "01-JAN-01 00:00:00 GMT"
* UNIX_ALTO_TIME_DIFF is amount to add to Unix time
* to get Alto time.
*/
int TIMEOUT_TIME; /* For file system timeout */
#ifdef XWINDOW
#define FALSE 0
#define TRUE !FALSE
int Event_Req = FALSE;
#endif /* XWINDOW */
static int gettime(int casep);
/************************************************************************/
/* */
/* u p d a t e _ m i s c s t a t s */
/* */
/* Updates counters and timers in the MISCSTATS "page". */
/* */
/* */
/* */
/************************************************************************/
void update_miscstats() {
#ifdef DOS
struct dostime_t dtm; /* holds DOS time, so we can get .01 secs */
_dos_gettime(&dtm);
MiscStats->totaltime = (time(0) * 1000) + (10 * dtm.hsecond);
MiscStats->swapwaittime = 0;
MiscStats->pagefaults = 0;
MiscStats->swapwrites = 0;
MiscStats->diskiotime = 0; /* ?? not available ?? */
MiscStats->diskops = 0;
MiscStats->secondstmp = MiscStats->secondsclock = (time(0) + UNIX_ALTO_TIME_DIFF);
#else
struct timeval timev;
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
MiscStats->totaltime = ru.ru_utime.tv_sec * 1000 + ru.ru_utime.tv_usec / 1000;
MiscStats->swapwaittime = ru.ru_stime.tv_sec * 1000 + ru.ru_stime.tv_usec / 1000;
MiscStats->pagefaults = ru.ru_minflt + ru.ru_majflt;
MiscStats->swapwrites = ru.ru_majflt;
MiscStats->diskiotime = 0; /* ?? not available ?? */
MiscStats->diskops = ru.ru_inblock
/* ?? this doesn't work ???
+ ru.ru_outblock */
;
gettimeofday(&timev, NULL);
MiscStats->secondstmp = MiscStats->secondsclock = (timev.tv_sec + UNIX_ALTO_TIME_DIFF);
#endif /* DOS */
}
/************************************************************************/
/* */
/* i n i t _ m i s c s t a t s */
/* */
/* Called at initialization time to set miscstats words. */
/* ?? and to periodically update them ?? [JDS 11/22/89] */
/* */
/* */
/************************************************************************/
void init_miscstats() {
MiscStats->starttime = gettime(0);
MiscStats->gctime = 0;
update_miscstats();
}
/************************************************************************/
/* */
/* s u b r _ g e t t i m e */
/* */
/* Handler for Lisps GETTIME subr call, dispatched thru */
/* subr.c/miscn.c sub-dispatch. */
/* */
/* Calls gettime, and returns the result to Lisp as a SMALLP */
/* or FIXP, as appropriate. */
/* */
/************************************************************************/
DLword *createcell68k();
LispPTR subr_gettime(LispPTR args[])
{
int result;
result = gettime(args[0] & 0xffff);
if (args[1]) {
*((int *)Addr68k_from_LADDR(args[1])) = result;
return (args[1]);
} else
N_ARITH_SWITCH(result);
}
/************************************************************************/
/* */
/* g e t t i m e */
/* */
/* Get the value of one of the various time counters, as */
/* specified by the argument casep. casep's values & meanings: */
/* */
/* 0 elapsed time, in milliseconds. */
/* 1 start of elapsed-time period, in milliseconds */
/* 2 this process's run time, in milliseconds */
/* 3 total GC time, in milliseconds */
/* 4 current time-of-day, in ALTO format */
/* 5 current time-of-day, in Interlisp format */
/* 6 start of daylight-savings, as day-in-year */
/* 7 end of daylight-savings, as day-in-year */
/* 8 time zone, as hours of offset from GMT (whole hours only) */
/* */
/************************************************************************/
static int gettime(int casep)
{
#ifdef DOS
struct dostime_t dtm; /* for hundredths of secs */
#else
struct timeval timev;
#endif /* DOS */
switch (casep) {
case 0: /* elapsed time in alto milliseconds */
#ifdef DOS
_dos_gettime(&dtm);
return ((time(0) + UNIX_ALTO_TIME_DIFF) * 1000) + (10 * dtm.hsecond);
#else /* DOS */
gettimeofday(&timev, NULL);
return ((timev.tv_sec + UNIX_ALTO_TIME_DIFF) * 1000 + timev.tv_usec / 1000);
#endif /* DOS */
case 1: /* starting elapsed time in milliseconds */ return (MiscStats->starttime);
case 2: /* run time, this process, in milliseconds */
update_miscstats();
return (MiscStats->totaltime);
case 3: /* total GC time in milliseconds */ return (MiscStats->gctime);
case 4: /* current time of day in Alto format */
#ifdef DOS
return (time(0) + UNIX_ALTO_TIME_DIFF);
#else
gettimeofday(&timev, NULL);
return (timev.tv_sec + UNIX_ALTO_TIME_DIFF);
#endif
case 5: /* current time of day in Interlisp format */
#ifdef DOS
return (time(0) + LISP_UNIX_TIME_DIFF);
#else
gettimeofday(&timev, NULL);
return (timev.tv_sec + LISP_UNIX_TIME_DIFF);
#endif
case 6:
return (98); /* this is wrong, only works in PST */
case 7:
return (305); /* this is wrong, only works in PST */
case 8:
/* other methods of determining timezone offset are unreliable and/or deprecated */
/* timezone is declared in <time.h>; the time mechanisms must be initialized */
/* Unfortunately, FreeBSD does not support the timezone external variable, nor */
/* does gettimeofday() seem to produce the correct timezone values. */
tzset();
#if defined(FREEBSD)
time_t tv = time(NULL);
struct tm *tm = localtime(&tv);
return (tm->tm_gmtoff / -3600);
#else
return (timezone / 3600); /* timezone, extern, is #secs diff GMT to local. */
#endif
default: return (0);
}
}
/************************************************************************/
/* */
/* s u b r _ s e t t i m e */
/* */
/* Converts its argument, a time in ALTO seconds, to the */
/* UNIX time format, and sets the UNIX clock. You must be */
/* the super-user for this to work. */
/* */
/* Implements the SETTIME subr call, sub-dispatched from subr.c */
/* */
/************************************************************************/
void subr_settime(LispPTR args[])
{
#ifdef DOS
struct dostime_t dostime;
struct dosdate_t dosday;
struct tm uxtime;
uxtime = *localtime((time_t *)(*((int *)Addr68k_from_LADDR(args[0])) - UNIX_ALTO_TIME_DIFF));
dostime.hsecond = 0;
dostime.second = uxtime.tm_sec;
dostime.minute = uxtime.tm_min;
dostime.hour = uxtime.tm_hour;
_dos_settime(&dostime);
dosday.day = uxtime.tm_mday;
dosday.month = uxtime.tm_mon;
dosday.year = uxtime.tm_year;
dosday.dayofweek = uxtime.tm_wday;
_dos_setdate(&dosday);
#else
struct timeval timev;
timev.tv_sec = *((int *)Addr68k_from_LADDR(args[0])) - UNIX_ALTO_TIME_DIFF;
timev.tv_usec = 0;
settimeofday(&timev, NULL);
#endif
} /* end subr_settime */
/************************************************************************/
/* */
/* s u b r _ c o p y t i m e s t a t s */
/* */
/* Given source and destination MISCSTATS structure pointers, */
/* copy the contents of the source structure into the dest. */
/* */
/* Also calls update_miscstats, to keep stats current. */
/* */
/************************************************************************/
void subr_copytimestats(LispPTR args[])
{
MISCSTATS *source;
MISCSTATS *dest;
source = (MISCSTATS *)Addr68k_from_LADDR(args[0]);
dest = (MISCSTATS *)Addr68k_from_LADDR(args[1]);
update_miscstats();
*dest = *source;
}
/************************************************************************/
/* */
/* N _ O P _ r c l k */
/* */
/* Get the current time in UNIX format, convert it to micro- */
/* seconds in ALTO format, and store the low 32 bits into */
/* the FIXP cell passed in to us on the top of stack. */
/* */
/************************************************************************/
LispPTR N_OP_rclk(LispPTR tos)
{
unsigned int usec;
#ifdef DOS
struct dostime_t dtm;
#endif /* DOS */
#ifdef DOS
_dos_gettime(&dtm);
usec = (time(0) * 1000000) + (10000 * dtm.hsecond);
#else
struct timeval timev;
gettimeofday(&timev, NULL);
usec = (timev.tv_sec * 1000000UL) + timev.tv_usec;
#endif /* DOS */
*((unsigned int *)(Addr68k_from_LADDR(tos))) = usec;
return (tos);
} /* end N_OP_rclk */
/**********************************************************************/
/* update_timer called periodically */
/************************************************************************/
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/************************************************************************/
void update_timer() {
#ifdef DOS
MiscStats->secondstmp = MiscStats->secondsclock = time(0) + UNIX_ALTO_TIME_DIFF;
#else
struct timeval timev;
gettimeofday(&timev, NIL);
MiscStats->secondstmp = MiscStats->secondsclock = (timev.tv_sec + UNIX_ALTO_TIME_DIFF);
#endif /* DOS */
}
/************************************************************************/
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/************************************************************************/
/**********************************************************************/
/* timer interrupt handling system
int_init() should be called before first entering dispatch loop.
int_timer_init() is called by int_init() and arms the timer interrupt.
int_io_init() is called by int_init() and arms the I/O interrupt.
int_timer_service() catches the timer signal and sets
Irq_Stk_Check & Irq_Stk_End to 0
so the rest of the system will see it and respond.
int_block() and int_unblock() block timer interrupts and release them.
int_io_open(fd) should be called whenever a file that should interrupt
us is opened; it enables the interrupt on that fd.
int_io_close(fd) should be called whenever a file that should interrupt
us is closed; it disables the interrupt on that fd.
*/
/* TIMER_INTERVAL usec ~ 20 per second. This should live in some
machine-configuration
file somewhere - it can be changed as the -t parameter to lisp*/
#ifdef sparc
int TIMER_INTERVAL = 100000;
#else
int TIMER_INTERVAL = 25000;
#endif
int FileIOFlag = 0;
int TimerFlag = 0;
extern int LispWindowFd;
/************************************************************************/
/* */
/* i n t _ t i m e r _ s e r v i c e */
/* */
/* Handle the virtual-time alarm signal VTALRM. */
/* */
/* */
/************************************************************************/
static void int_timer_service(int sig)
{
/* this may have to do more in the future, like check for nested interrupts,
etc... */
Irq_Stk_Check = 0;
Irq_Stk_End = 0;
TimerFlag = 1;
#ifdef XWINDOW
Event_Req = TRUE;
#endif
}
/************************************************************************/
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/************************************************************************/
static void int_timer_init()
{
#ifdef DOS
/******************************************************************************
* All code and data touched during the processing of an interrupt should
* locked prior to receiving any interrupts. This prevents the Timer
* function from being swapped out during an interrupt.
******************************************************************************/
_dpmi_lockregion((void *)TimerFlag, sizeof(TimerFlag));
_dpmi_lockregion((void *)Irq_Stk_End, sizeof(Irq_Stk_End));
_dpmi_lockregion((void *)Irq_Stk_Check, sizeof(Irq_Stk_Check));
_dpmi_lockregion((void *)tick_count, sizeof(tick_count));
_dpmi_lockregion((void *)&DOStimer, 4096);
_dpmi_lockregion((void *)prev_int_1c, sizeof(prev_int_1c));
/* Set up the DOS time handler. */
prev_int_1c = _dos_getvect(0x1c); /* get addr of currnt 1c hndlr, */
/* if any*/
_dos_setvect(0x1c, DOStimer); /* hook our int handler to timer int */
#else
struct itimerval timert, tmpt;
struct sigaction timer_action;
timer_action.sa_handler = int_timer_service;
sigemptyset(&timer_action.sa_mask);
timer_action.sa_flags = 0;
if (sigaction(SIGVTALRM, &timer_action, NULL) == -1) {
perror("sigaction: SIGVTALRM");
}
/* then attach a timer to it and turn it loose */
timert.it_interval.tv_sec = timert.it_value.tv_sec = 0;
timert.it_interval.tv_usec = timert.it_value.tv_usec = TIMER_INTERVAL;
timerclear(&tmpt.it_value);
timerclear(&tmpt.it_interval);
setitimer(ITIMER_VIRTUAL, &timert, &tmpt);
getitimer(ITIMER_VIRTUAL, &tmpt);
DBPRINT(("Timer interval set to %d usec\n", timert.it_value.tv_usec));
#endif /* DOS */
}
/************************************************************************/
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/************************************************************************/
void int_io_open(int fd)
{
#ifdef DOS
/* would turn on DOS kbd signal handler here */
#elif KBINT
DBPRINT(("int_io_opening %d\n", fd));
if (fcntl(fd, F_SETOWN, getpid()) == -1) {
#ifdef DEBUG
perror("fcntl F_SETOWN ERROR");
#endif
};
if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_ASYNC) == -1) perror("fcntl F_SETFL error");
#endif
}
void int_io_close(int fd)
{
#ifdef DOS
/* Turn off signaller here */
#elif KBINT
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_ASYNC);
#endif
}
/************************************************************************/
/* */
/* i n t _ i o _ i n i t */
/* */
/* Set up handling for the SIGIO signals, in */
/* support of keyboard event handling and ethernet incoming- */
/* packet handling. */
/* */
/* */
/************************************************************************/
static void int_io_init() {
#ifndef DOS
struct sigaction io_action;
io_action.sa_handler = getsignaldata;
sigemptyset(&io_action.sa_mask);
io_action.sa_flags = 0;
if (sigaction(SIGIO, &io_action, NULL) == -1) {
perror("sigaction: SIGIO");
} else {
DBPRINT(("I/O interrupts enabled\n"));
}
#if defined(XWINDOW) && defined(I_SETSIG)
if (ioctl(ConnectionNumber(currentdsp->display_id), I_SETSIG, S_INPUT) < 0)
perror("ioctl on X fd - SETSIG for input handling failed");
#endif
#ifdef USE_DLPI
DBPRINT(("INIT ETHER: Doing I_SETSIG.\n"));
if (ether_fd > 0)
if (ioctl(ether_fd, I_SETSIG, S_INPUT) != 0) {
perror("init_ether: I_SETSIG failed:\n");
close(ether_fd);
ether_fd = -1;
return;
}
#endif /* USE_DLPI */
#endif /* DOS */
}
/************************************************************************/
/* */
/* i n t _ b l o c k */
/* */
/* Temporarily turn off interrupts. */
/* */
/* NOTE that these interrupts must also be turned off in ldeboot's */
/* forking code; if you change these, go fix that one too */
/* */
/************************************************************************/
void int_block() {
/* temporarily turn off interrupts */
#ifdef DOS
_dos_setvect(0x1c, prev_int_1c);
#else /* DOS */
sigset_t signals;
sigemptyset(&signals);
sigaddset(&signals, SIGVTALRM);
sigaddset(&signals, SIGIO);
sigaddset(&signals, SIGALRM);
sigaddset(&signals, SIGXFSZ);
#ifdef FLTINT
sigaddset(&signals, SIGFPE);
#endif
sigprocmask(SIG_BLOCK, &signals, NULL);
#endif /* DOS */
}
/************************************************************************/
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/************************************************************************/
void int_unblock() {
#ifdef DOS
_dos_setvect(0x1c, DOStimer);
#else /* DOS */
sigset_t signals;
sigemptyset(&signals);
sigaddset(&signals, SIGVTALRM);
sigaddset(&signals, SIGIO);
sigaddset(&signals, SIGALRM);
sigaddset(&signals, SIGXFSZ);
#ifdef FLTINT
sigaddset(&signals, SIGFPE);
#endif
sigprocmask(SIG_UNBLOCK, &signals, NULL);
#endif /* DOS */
}
void int_timer_on() { int_unblock(); }
void int_timer_off() { int_block(); }
#ifdef FLTINT
/************************************************************************/
/* */
/* F L O A T I N G - P O I N T I N T E R R U P T H A N D L I N G */
/* */
/* This is the handler for the SIGFPE signal, to catch floating- */
/* point exceptions. Sets the global 'FP_error' to the error */
/* code passed in by the signal; FP_error is checked by the */
/* Lisp emulator FP code to make sure everything is OK. */
/* */
/************************************************************************/
/* The global used to signal floating-point errors */
volatile int FP_error = 0;
void int_fp_service(int sig, siginfo_t *info, void *context)
{
switch (info->si_code) {
case FPE_FLTDIV:
case FPE_FLTUND:
case FPE_FLTOVF:
case FPE_FLTINV:
FP_error = info->si_code;
break;
default: {
#ifdef DEBUG
char stuff[100];
snprintf(stuff, sizeof(stuff), "Unexpected FP error signal code: %d", info->si_code);
perror(stuff);
#else
FP_error = info->si_code;
#endif
}
}
}
void int_fp_init() {
struct sigaction fpe_action;
fpe_action.sa_handler = int_fp_service;
sigemptyset(&fpe_action.sa_mask);
fpe_action.sa_flags = SA_SIGINFO;
if (sigaction(SIGFPE, &fpe_action, NULL) == -1) {
perror("Sigset for FPE failed");
} else {
DBPRINT(("FP interrupts enabled\n"));
}
}
#endif /* FLTINT */
/************************************************************************/
/* */
/* t i m e o u t _ e r r o r */
/* */
/* Error handling routine for SIGALRM. Called when any */
/* TIMEOUT(...) forms spend more than TIMEOUT_TIME (normally */
/* 10 sec.) trying to do an I/O operation. */
/* */
/* */
/************************************************************************/
jmp_buf jmpbuf;
static void timeout_error(int sig) {
longjmp(jmpbuf, 1);
}
/************************************************************************/
/* */
/* i n t _ f i l e _ i n i t */
/* */
/* Set up the signal handler for SIGALRM, to catch TIMEOUTs: */
/* TIMEOUT(...) forms spend more than TIMEOUT_TIME (normally */
/* 10 sec.) trying to do an I/O operation. */
/* */
/* */
/************************************************************************/
static void int_file_init() {
char *envtime;
int timeout_time;
struct sigaction timer_action;
timer_action.sa_handler = timeout_error;
sigemptyset(&timer_action.sa_mask);
timer_action.sa_flags = 0;
if (sigaction(SIGALRM, &timer_action, NULL) == -1) {
perror("sigaction: SIGALRM");
}
/* Set Timeout period */
if ((envtime = getenv("LDEFILETIMEOUT")) == NULL) {
TIMEOUT_TIME = 10;
} else {
if ((timeout_time = atoi(envtime)) > 0)
TIMEOUT_TIME = timeout_time;
else
TIMEOUT_TIME = 10;
}
DBPRINT(("File timeout interrupts enabled\n"));
}
/************************************************************************/
/* */
/* p a n i c u r a i d */
/* */
/* Most of the unused process-killing interrupts end up here; you */
/* can't do a whole lot safely here but dump your sysout for */
/* post-mortem analysis, but you MIGHT be able to get a clue */
/* about what killed you. */
/* */
/************************************************************************/
void panicuraid(int sig, siginfo_t *info, void *context)
{
static char errormsg[200];
static char *stdmsg =
"Please record the signal and code information\n\
and do a 'v' before trying anything else.";
switch (sig) {
case SIGBUS:
case SIGILL:
case SIGSEGV:
snprintf(errormsg, sizeof(errormsg), "%s at address %p.\n%s", strsignal(sig), info->si_addr, stdmsg);
break;
case SIGPIPE:
snprintf(errormsg, sizeof(errormsg), "Broken PIPE.\n%s", stdmsg);
break;
case SIGHUP:
snprintf(errormsg, sizeof(errormsg), "HANGUP signalled.\n%s", stdmsg);
/* Assume that a user tried to exit UNIX shell */
killpg(getpgrp(), SIGKILL);
exit(0);
break;
case SIGFPE:
snprintf(errormsg, sizeof(errormsg), "%s (%d) at address %p.\n%s", strsignal(sig), info->si_code, info->si_addr, stdmsg);
break;
default: snprintf(errormsg, sizeof(errormsg), "Uncaught SIGNAL %s (%d).\n%s", strsignal(sig), sig, stdmsg);
}
error(errormsg);
}
/************************************************************************/
/* */
/* i n t _ p a n i c _ i n i t */
/* */
/* A catch for all the deadly interupts (but KILL, of course) */
/* Dumps you into uraid; you probably can't get back from it, */
/* but there is hope that you will be able to poke around with */
/* uraid and get a clue about why you're dying. */
/* */
/************************************************************************/
static void int_panic_init() {
#ifndef DOS
struct sigaction panic_action, ignore_action;
panic_action.sa_sigaction = panicuraid;
sigemptyset(&panic_action.sa_mask);
panic_action.sa_flags = SA_SIGINFO;
ignore_action.sa_handler = SIG_IGN;
sigemptyset(&panic_action.sa_mask);
panic_action.sa_flags = 0;
sigaction(SIGHUP, &panic_action, NULL);
sigaction(SIGQUIT, &panic_action, NULL);
sigaction(SIGILL, &panic_action, NULL);
#ifdef SIGEMT
sigaction(SIGEMT, &panic_action, NULL);
#endif
sigaction(SIGBUS, &panic_action, NULL);
sigaction(SIGSEGV, &panic_action, NULL);
sigaction(SIGSYS, &panic_action, NULL);
sigaction(SIGTERM, &panic_action, NULL);
/* Ignore SIGPIPE */
sigaction(SIGPIPE, &ignore_action, NULL);
#endif
DBPRINT(("Panic interrupts enabled\n"));
}
/************************************************************************/
/* */
/* i n t _ i n i t */
/* */
/* Initialize all the interrupts for Lisp & the emulator. */
/* */
/************************************************************************/
void int_init() {
int_timer_init(); /* periodic interrupt timer */
int_io_init(); /* SIGIO async I/O handlers */
int_file_init(); /* file-io TIMEOUT support */
int_panic_init(); /* catch for all other dangerous interrupts */
#ifdef FLTINT
int_fp_init(); /* Floating-point exception handler */
#endif
int_unblock(); /* Turn on interrupts */
}
#ifdef DOS
/******************************************************************************
* DOStimer()
*
* The interrupt 0x1c handler. This routine must be declared using the
* '#pragma interrupt()' statement to ensure that all registers are preserved.
* It is also needed to ensure the proper functioning of '_chain_intr()'.
*
* The timer interrupt (normally) occurs 18.2 times per second. This routine
* waits one extra tick every 91 ticks (18.2*5).
*
* Before this interrupt was installed, 'prev_int_1c' was set to the current
* 0x1c interrupt. 'DOStimer()' chains to this interrupt using '_chain_intr()',
* rather than returning back to the caller.
*
* Note that as little as possible should be done within a timer interrupt,
* since further clock ticks are disabled until the interrupt returns.
******************************************************************************/
void DOStimer() {
/* if (--tick_count == 0) { */
Irq_Stk_Check = 0;
Irq_Stk_End = 0;
TimerFlag = 1;
/* _dos_setvect(0x1c, prev_int_1c);
} else if (tick_count <= 0) { */
/* I'm dead, uninstal me */
/* _dos_setvect(0x1c, prev_int_1c);
tick_count = 0;
} */
_chain_intr(prev_int_1c); /* call previous int 1c handlr, if any*/
/* (pts to 'ret' if no prev installed)*/
}
void alarm(unsigned long sec)
{
/* tick_count = sec * 18;
_dos_setvect(0x1c, DOStimer); */
}
#endif /* DOS */