7#include <sys/ucontext.h>
12#pragma STDC FENV_ACCESS ON
16#include <fpu_control.h>
19#define SIG_PROLOG_OFFSET 32
21#define SIG_EXCEPTION (SIG_PROLOG_OFFSET + 0)
23#define SIG_ATOM_GC (SIG_PROLOG_OFFSET + 1)
25#define SIG_GC (SIG_PROLOG_OFFSET + 2)
27#define SIG_THREAD_SIGNAL (SIG_PROLOG_OFFSET + 3)
29#define SIG_FREECLAUSES (SIG_PROLOG_OFFSET + 4)
30#define SIG_PLABORT (SIG_PROLOG_OFFSET + 5)
32static struct signame {
89 {SIGSTKFLT,
"stkflt", 0},
101 {SIGXCPU,
"xcpu", 0},
104 {SIGXFSZ,
"xfsz", 0},
107 {SIGVTALRM,
"vtalrm", 0},
110 {SIGPROF,
"prof", 0},
115 {SIG_EXCEPTION,
"prolog:exception", 0},
117 {SIG_ATOM_GC,
"prolog:atom_gc", 0},
119 {SIG_GC,
"prolog:gc", 0},
120#ifdef SIG_THREAD_SIGNAL
121 {SIG_THREAD_SIGNAL,
"prolog:thread_signal", 0},
127static void my_signal_info(
int sig,
void *handler) {
128 struct sigaction sigact;
130 sigact.sa_handler = handler;
131 sigemptyset(&sigact.sa_mask);
132 sigact.sa_flags = SA_SIGINFO;
134 sigaction(sig, &sigact, NULL);
137static void my_signal(
int sig,
void *handler) {
138 struct sigaction sigact;
140 sigact.sa_handler = (
void *)handler;
141 sigemptyset(&sigact.sa_mask);
143 sigaction(sig, &sigact, NULL);
146 int Yap_set_sigaction(
int sig,
void *handler) {
147 struct sigaction sigact;
149 sigact.sa_handler = (
void *)handler;
150 sigemptyset(&sigact.sa_mask);
152 sigaction(sig, &sigact,NULL);
156static void my_signal(
int sig,
void *handler) {
158 signal(sig, handler);
162static void my_signal_info(
int sig,
void *handler) {
164 if (signal(sig, (
void *)handler) == SIG_ERR)
171static void HandleMatherr(
int sig,
void *sipv,
void *uapv) {
173 LOCAL_Error_TYPE = Yap_MathException();
175 Yap_external_signal(worker_id, YAP_FPE_SIGNAL);
179int Yap_signal_index(
const char *name) {
180 struct signame *sn = signames;
183 if (strncmp(name,
"SIG", 3) == 0 && strlen(name) < 12) {
184 char *p = (
char *)name + 3, *q = tmp;
185 while ((*q++ = tolower(*p++))) {
190 for (; sn->name; sn++) {
191 if (!strcmp(sn->name, name))
199static void SearchForTrailFault(
void *ptr,
int sure) {
206#if OS_HANDLES_TR_OVERFLOW && !USE_SYSTEM_MALLOC
207 if ((ptr > (
void *)LOCAL_TrailTop - 1024 &&
208 TR < (tr_fr_ptr)LOCAL_TrailTop + (64 * 1024))) {
209 if (!Yap_growtrail(64 * 1024, TRUE)) {
210 Yap_Error(RESOURCE_ERROR_TRAIL, TermNil,
211 "YAP failed to reserve %ld bytes in growtrail", K64);
218 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
219 "tried to access illegal address %p!!!!", ptr);
221 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
222 "likely bug in YAP, segmentation violation");
228HandleSIGSEGV(
int sig,
void *sipv,
void *uap) {
233 if (LOCAL_PrologMode & ExtendStackMode) {
234 Yap_Error(SYSTEM_ERROR_FATAL, TermNil,
235 "OS memory allocation crashed at address %p, bailing out\n",
238#if (defined(__svr4__) || defined(__SVR4))
239 siginfo_t *sip = sipv;
240 if (sip->si_code != SI_NOINFO && sip->si_code == SEGV_MAPERR) {
245 siginfo_t *sip = sipv;
249 SearchForTrailFault(ptr, sure);
255bool Yap_set_fpu_exceptions(Term flag) {
256 if (flag == TermTrue) {
258 fexcept_t excepts = 0;
259 return fesetexceptflag(&excepts,
260 FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW) == 0;
261#elif HAVE_FEENABLEEXCEPTFLAG
263 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
266 _controlfp_s(0, ~(_EM_ZERODIVIDE | _EM_UNDERFLOW | _EM_OVERFLOW),
269#if HAVE_FESETTRAPENABLE
271 fesettrapenable(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW);
282 fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_UFL);
284#elif HAVE_FPU_CONTROL_H && i386 && defined(__GNUC__)
287 ~(_FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM);
290 feclearexcept(FE_ALL_EXCEPT);
293 my_signal(SIGFPE, HandleMatherr);
297#if HAVE_FESETEXCEPTFLAG
299 return fesetexceptflag(&excepts, 0) == 0;
300#elif HAVE_FEENABLEEXCEPT
305 _controlfp_s(0, (_EM_ZERODIVIDE | _EM_UNDERFLOW | _EM_OVERFLOW),
308#if HAVE_FESETTRAPENABLE
309 fesettrapenable(FE_ALL_EXCEPT);
311 fpsetmask(FP_X_CLEAR);
314#if HAVE_FPU_CONTROL_H && i386 && defined(__GNUC__)
320 my_signal(SIGFPE, SIG_IGN);
326static void ReceiveSignal(
int s,
void *x,
void *y) {
328 LOCAL_PrologMode |= InterruptMode;
329#if !defined(LIGHT) && !_MSC_VER && !defined(__MINGW32__)
331 if (s == SIGINT && (LOCAL_PrologMode & ConsoleGetcMode)) {
335 my_signal(s, ReceiveSignal);
340 Yap_external_signal(worker_id, YAP_INT_SIGNAL);
343 Yap_external_signal(worker_id, YAP_ALARM_SIGNAL);
346 Yap_external_signal(worker_id, YAP_VTALARM_SIGNAL);
351 Yap_external_signal(worker_id, YAP_FPE_SIGNAL);
355#if !defined(LIGHT) && !defined(_WIN32)
359 LOCAL_PrologMode &= ~InterruptMode;
360 Yap_Error(INTERRUPT_EVENT, MkIntTerm(s), NULL);
366 Yap_external_signal(worker_id, YAP_USR1_SIGNAL);
372 Yap_external_signal(worker_id, YAP_USR2_SIGNAL);
378 Yap_external_signal(worker_id, YAP_PIPE_SIGNAL);
388 fprintf(stderr,
"\n[ Unexpected signal ]\n");
392 LOCAL_PrologMode &= ~InterruptMode;
395#if (_MSC_VER || defined(__MINGW32__))
396static BOOL WINAPI MSCHandleSignal(DWORD dwCtrlType) {
399 REMOTE_InterruptsDisabled(0)
401 LOCAL_InterruptsDisabled
406 switch (dwCtrlType) {
408 case CTRL_BREAK_EVENT:
410 Yap_external_signal(0, YAP_WINTIMER_SIGNAL);
411 REMOTE_PrologMode(0) |= InterruptMode;
413 Yap_signal(YAP_WINTIMER_SIGNAL);
414 LOCAL_PrologMode |= InterruptMode;
424#if _MSC_VER || defined(__MINGW32__)
426static DWORD WINAPI DoTimerThread(LPVOID targ) {
427 Int *time = (Int *)targ;
429 LARGE_INTEGER liDueTime;
431 htimer = CreateWaitableTimer(NULL, FALSE, NULL);
432 liDueTime.QuadPart = -10000000;
433 liDueTime.QuadPart *= time[0];
435 liDueTime.QuadPart -= time[1] * 10;
437 if (SetWaitableTimer(htimer, &liDueTime, 0, NULL, NULL, 0) == 0) {
440 if (WaitForSingleObject(htimer, INFINITE) != WAIT_OBJECT_0)
441 fprintf(stderr,
"WaitForSingleObject failed (%ld)\n", GetLastError());
442 Yap_signal(YAP_WINTIMER_SIGNAL);
444 Yap_PutValue(AtomAlarm, MkAtomTerm(AtomTrue));
453static Int enable_interrupts(USES_REGS1) {
454 LOCAL_InterruptsDisabled--;
455 if (LOCAL_Signals && !LOCAL_InterruptsDisabled) {
456 CreepFlag = Unsigned(LCL0);
457 if (!Yap_only_has_signal(YAP_CREEP_SIGNAL))
458 EventFlag = Unsigned(LCL0);
463static Int disable_interrupts(USES_REGS1) {
464 LOCAL_InterruptsDisabled++;
465 CalculateStackGap(PASS_REGS1);
471static Int alarm4(USES_REGS1) {
472 Term t = Deref(ARG1);
473 Term t2 = Deref(ARG2);
476 Yap_Error(INSTANTIATION_ERROR, t,
"alarm/2");
479 if (!IsIntegerTerm(t)) {
480 Yap_Error(TYPE_ERROR_INTEGER, t,
"alarm/2");
484 Yap_Error(INSTANTIATION_ERROR, t2,
"alarm/2");
487 if (!IsIntegerTerm(t2)) {
488 Yap_Error(TYPE_ERROR_INTEGER, t2,
"alarm/2");
491 i1 = IntegerOfTerm(t);
492 i2 = IntegerOfTerm(t2);
493 if (i1 == 0 && i2 == 0) {
495 Yap_get_signal(YAP_WINTIMER_SIGNAL);
497 Yap_get_signal(YAP_ALARM_SIGNAL);
500#if _MSC_VER || defined(__MINGW32__)
508 if (time[0] != 0 && time[1] != 0) {
512 hThread = CreateThread(NULL,
520 if (hThread == NULL) {
521 Yap_WinError(
"trying to use alarm");
525 return Yap_unify(ARG3, tout) && Yap_unify(ARG4, MkIntTerm(0));
527#elif HAVE_SETITIMER && !SUPPORT_CONDOR
529 struct itimerval new, old;
531 new.it_interval.tv_sec = 0;
532 new.it_interval.tv_usec = 0;
533 new.it_value.tv_sec = i1;
534 new.it_value.tv_usec = i2;
537 if (setitimer(ITIMER_REAL, &
new, &old) < 0) {
539 Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1,
"setitimer: %s",
542 Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1,
"setitimer %d", errno);
546 return Yap_unify(ARG3, MkIntegerTerm(old.it_value.tv_sec)) &&
547 Yap_unify(ARG4, MkIntegerTerm(old.it_value.tv_usec));
549#elif HAVE_ALARM && !SUPPORT_CONDOR
555 tout = MkIntegerTerm(left);
556 return Yap_unify(ARG3, tout) && Yap_unify(ARG4, MkIntTerm(0));
560 if (IntegerOfTerm(t) == 0)
562 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
563 "alarm not available in this configuration");
568static Int virtual_alarm(USES_REGS1) {
569 Term t = Deref(ARG1);
570 Term t2 = Deref(ARG2);
572 Yap_Error(INSTANTIATION_ERROR, t,
"alarm/2");
575 if (!IsIntegerTerm(t)) {
576 Yap_Error(TYPE_ERROR_INTEGER, t,
"alarm/2");
580 Yap_Error(INSTANTIATION_ERROR, t2,
"alarm/2");
583 if (!IsIntegerTerm(t2)) {
584 Yap_Error(TYPE_ERROR_INTEGER, t2,
"alarm/2");
587#if _MSC_VER || defined(__MINGW32__)
592 time[0] = IntegerOfTerm(t);
593 time[1] = IntegerOfTerm(t2);
595 if (time[0] != 0 && time[1] != 0) {
599 hThread = CreateThread(NULL,
607 if (hThread == NULL) {
608 Yap_WinError(
"trying to use alarm");
612 return Yap_unify(ARG3, tout) && Yap_unify(ARG4, MkIntTerm(0));
614#elif HAVE_SETITIMER && !SUPPORT_CONDOR
616 struct itimerval new, old;
618 new.it_interval.tv_sec = 0;
619 new.it_interval.tv_usec = 0;
620 new.it_value.tv_sec = IntegerOfTerm(t);
621 new.it_value.tv_usec = IntegerOfTerm(t2);
622 if (setitimer(ITIMER_VIRTUAL, &
new, &old) < 0) {
624 Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1,
"setitimer: %s",
627 Yap_Error(SYSTEM_ERROR_OPERATING_SYSTEM, ARG1,
"setitimer %d", errno);
631 return Yap_unify(ARG3, MkIntegerTerm(old.it_value.tv_sec)) &&
632 Yap_unify(ARG4, MkIntegerTerm(old.it_value.tv_usec));
636 if (IntegerOfTerm(t) == 0)
638 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
639 "alarm not available in this configuration");
670 VaxFramePtr fp = (VaxFramePtr)(((
int *)&dummy) - 6);
671 while (--maxframes) {
672 fp = (VaxFramePtr)fp->fp;
674 if (fp->oldfp >= ®S[6] && fp->oldfp < ®S[REG_SIZE])
675 fp->oldfp = vax_absmi_fp;
685int WINAPI win_yap(HANDLE, DWORD, LPVOID);
687int WINAPI win_yap(HANDLE hinst, DWORD reason, LPVOID reserved) {
689 case DLL_PROCESS_ATTACH:
691 case DLL_PROCESS_DETACH:
693 case DLL_THREAD_ATTACH:
695 case DLL_THREAD_DETACH:
702#if (defined(YAPOR) || defined(THREADS)) && !defined(USE_PTHREAD_LOCKING)
704void rw_lock_voodoo(
void);
706void rw_lock_voodoo(
void) {
711 __asm__ __volatile__(
"___rw_read_enter_spin_on_wlock:\n"
712 " orcc %g2, 0x0, %g0\n"
713 " be,a ___rw_read_enter\n"
714 " ldstub [%g1 + 3], %g2\n"
715 " b ___rw_read_enter_spin_on_wlock\n"
716 " ldub [%g1 + 3], %g2\n"
717 "___rw_read_exit_spin_on_wlock:\n"
718 " orcc %g2, 0x0, %g0\n"
719 " be,a ___rw_read_exit\n"
720 " ldstub [%g1 + 3], %g2\n"
721 " b ___rw_read_exit_spin_on_wlock\n"
722 " ldub [%g1 + 3], %g2\n"
723 "___rw_write_enter_spin_on_wlock:\n"
724 " orcc %g2, 0x0, %g0\n"
725 " be,a ___rw_write_enter\n"
726 " ldstub [%g1 + 3], %g2\n"
727 " b ___rw_write_enter_spin_on_wlock\n"
730 " .globl ___rw_read_enter\n"
731 "___rw_read_enter:\n"
732 " orcc %g2, 0x0, %g0\n"
733 " bne,a ___rw_read_enter_spin_on_wlock\n"
734 " ldub [%g1 + 3], %g2\n"
740 " .globl ___rw_read_exit\n"
742 " orcc %g2, 0x0, %g0\n"
743 " bne,a ___rw_read_exit_spin_on_wlock\n"
744 " ldub [%g1 + 3], %g2\n"
746 " sub %g2, 0x1ff, %g2\n"
750 " .globl ___rw_write_enter\n"
751 "___rw_write_enter:\n"
752 " orcc %g2, 0x0, %g0\n"
753 " bne ___rw_write_enter_spin_on_wlock\n"
755 " andncc %g2, 0xff, %g0\n"
756 " bne,a ___rw_write_enter_spin_on_wlock\n"
757 " stb %g0, [%g1 + 3]\n"
765yap_error_number Yap_MathException__(USES_REGS1) {
770 if ((raised = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW))) {
772 feclearexcept(FE_ALL_EXCEPT);
773 if (raised & FE_OVERFLOW) {
774 return EVALUATION_ERROR_FLOAT_OVERFLOW;
775 }
else if (raised & FE_DIVBYZERO) {
776 return EVALUATION_ERROR_ZERO_DIVISOR;
777 }
else if (raised & FE_UNDERFLOW) {
778 return EVALUATION_ERROR_FLOAT_UNDERFLOW;
782 return EVALUATION_ERROR_UNDEFINED;
790 err = _controlfp_s(&raised, 0, 0);
792 return EVALUATION_ERROR_UNDEFINED;
795 feclearexcept(FE_ALL_EXCEPT);
796 if (raised & FE_OVERFLOW) {
797 return EVALUATION_ERROR_FLOAT_OVERFLOW;
798 }
else if (raised & FE_DIVBYZERO) {
799 return EVALUATION_ERROR_ZERO_DIVISOR;
800 }
else if (raised & FE_UNDERFLOW) {
801 return EVALUATION_ERROR_FLOAT_UNDERFLOW;
805 return EVALUATION_ERROR_UNDEFINED;
808#elif (defined(__svr4__) || defined(__SVR4))
809 switch (sip->si_code) {
811 return EVALUATION_ERROR_ZERO_DIVISOR;
814 return EVALUATION_ERROR_INT_OVERFLOW;
817 return EVALUATION_ERROR_ZERO_DIVISOR;
820 return EVALUATION_ERROR_FLOAT_OVERFLOW;
823 return EVALUATION_ERROR_FLOAT_UNDERFLOW;
829 return EVALUATION_ERROR_UNDEFINED;
831 Yap_set_fpu_exceptions(0);
834 return LOCAL_Error_TYPE;
847 if (GLOBAL_PrologShouldHandleInterrupts || enable == TermFalse || enable == TermOff) {
848 my_signal(SIGSEGV, SIG_DFL);
850 my_signal_info(SIGSEGV, HandleSIGSEGV);
868void Yap_InitOSSignals(
int wid) {
870 if (GLOBAL_PrologShouldHandleInterrupts) {
873#if !defined(LIGHT) && !_MSC_VER && !defined(__MINGW32__) && !defined(LIGHT)
874 my_signal(SIGQUIT, hdl);
875 my_signal(SIGKILL, hdl);
876 my_signal(SIGUSR1, hdl);
877 my_signal(SIGUSR2, hdl);
878 my_signal(SIGHUP, hdl);
879 my_signal(SIGALRM, hdl);
880 my_signal(SIGVTALRM, hdl);
883 my_signal(SIGPIPE, hdl);
885#if _MSC_VER || defined(__MINGW32__)
886 signal(SIGINT, SIG_IGN);
887 SetConsoleCtrlHandler(MSCHandleSignal, TRUE);
889 my_signal(SIGINT, hdl);
893 if (GLOBAL_PrologShouldHandleInterrupts) {
894 my_signal(SIGFPE, HandleMatherr);
896 my_signal(SIGFPE, hdl);
900 if (GLOBAL_PrologShouldHandleInterrupts) {
901 my_signal_info(SIGSEGV, HandleSIGSEGV);
903 my_signal(SIGFPE, hdl);
907 signal(SIGCHLD, SIG_IGN);
915void Yap_InitSignalPreds(
void) {
917 Term cm = CurrentModule;
918 Yap_InitCPred(
"alarm", 4, alarm4, SyncPredFlag);
919 Yap_InitCPred(
"virtual_alarm", 4, virtual_alarm, SyncPredFlag);
920 CurrentModule = HACKS_MODULE;
921 Yap_InitCPred(
"enable_interrupts", 0, enable_interrupts, SafePredFlag);
922 Yap_InitCPred(
"disable_interrupts", 0, disable_interrupts, SafePredFlag);
923 my_signal_info(SIGSEGV, HandleSIGSEGV);
925 Yap_set_fpu_exceptions(TermFalse);
bool Yap_InitSIGSEGV(Term enable)
This function implements the sigsegv prolog flag.