|
|
1.1 root 1: /*
2:
1.1.1.3 ! root 3: Copyright 1990,1991,1992 Eric R. Smith.
! 4:
! 5: Copyright 1992 Atari Corporation.
! 6:
! 7: All rights reserved.
1.1 root 8:
9: */
10:
11:
12:
13: /* signal.c:: signal handling routines */
14:
15:
16:
17: #include "mint.h"
18:
19:
20:
21: void (*sig_routine)(); /* used in intr.s */
22:
1.1.1.2 root 23: short sig_exc; /* used in intr.s */
24:
1.1 root 25:
26:
27: /*
28:
29: * killgroup(pgrp, sig): send a signal to all members of a process group
30:
31: * returns 0 on success, or an error code on failure
32:
33: */
34:
35:
36:
37: long
38:
39: killgroup(pgrp, sig)
40:
41: int pgrp, sig;
42:
43: {
44:
45: PROC *p;
46:
47: int found = 0;
48:
49:
50:
1.1.1.2 root 51: TRACE(("killgroup %d %d", pgrp, sig));
1.1 root 52:
53:
54:
55: if (pgrp < 0)
56:
57: return EINTRN;
58:
59:
60:
61: for (p = proclist; p; p = p->gl_next) {
62:
63: if (p->pgrp == pgrp) {
64:
65: post_sig(p, sig);
66:
67: found++;
68:
69: }
70:
71: }
72:
73: if (found) {
74:
75: check_sigs(); /* see if the current process is affected */
76:
77: return 0;
78:
79: }
80:
81: else {
82:
1.1.1.2 root 83: DEBUG(("killgroup: no processes found"));
1.1 root 84:
85: return EFILNF;
86:
87: }
88:
89: }
90:
91:
92:
93: /* post_sig: post a signal as being pending. It is assumed that the
94:
95: caller has already verified that "sig" is a valid signal, and
96:
97: moreover it is the caller's responsibility to call check_sigs()
98:
99: if it's possible that p == curproc
100:
101: */
102:
103:
104:
105: void
106:
107: post_sig(p, sig)
108:
109: PROC *p;
110:
111: int sig;
112:
113: {
114:
115: ulong sigm;
116:
117:
118:
119: /* if process is ignoring this signal, do nothing
120:
121: * also: signal 0 is SIGNULL, and should never be delivered through
122:
123: * the normal channels (indeed, it's filtered out in dossig.c,
124:
125: * but the extra sanity check here is harmless). The kernel uses
126:
127: * signal 0 internally for some purposes, but it is handled
128:
129: * specially (see supexec() in xbios.c, for example).
130:
131: */
132:
133: if (p->sighandle[sig] == SIG_IGN || sig == 0)
134:
135: return;
136:
137:
138:
139: /* if the process is already dead, do nothing */
140:
141: if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q)
142:
143: return;
144:
145:
146:
147: /* mark the signal as pending */
148:
149: sigm = (1L << (unsigned long)sig);
150:
151: p->sigpending |= sigm;
152:
153:
154:
155: /* if the signal is masked, do nothing further */
156:
157: if ( (p->sigmask & sigm) != 0 )
158:
159: return;
160:
161:
162:
163: /* otherwise, make sure the process is awake */
164:
165: if (p->wait_q && p->wait_q != READY_Q) {
166:
1.1.1.3 ! root 167: short sr = spl7();
! 168:
1.1 root 169: rm_q(p->wait_q, p);
170:
171: add_q(READY_Q, p);
172:
1.1.1.3 ! root 173: spl(sr);
! 174:
1.1 root 175: }
176:
177: }
178:
179:
180:
181: /*
182:
183: * check_sigs: see if we have any signals pending. if so,
184:
185: * handle them.
186:
187: */
188:
189:
190:
191: void
192:
193: check_sigs()
194:
195: {
196:
197: ulong sigs, sigm;
198:
1.1.1.2 root 199: int i;
200:
201: short deliversig;
1.1 root 202:
203:
204:
205: if (curproc->pid == 0) return;
206:
1.1.1.2 root 207: top:
208:
1.1 root 209: sigs = curproc->sigpending & ~(curproc->sigmask);
210:
211: if (sigs) {
212:
213: sigm = 2;
214:
1.1.1.2 root 215: /* with tracing we need a mechanism to allow a signal to be delivered
216:
217: * to the child (curproc); Fcntl(...TRACEGO...) passes a SIGNULL to indicate that we
218:
219: * should really deliver the signal, hence its always safe to remove it
220:
221: * from pending.
222:
223: */
224:
225: deliversig = (curproc->sigpending & 1L);
226:
227: curproc->sigpending &= ~1L;
228:
229:
230:
1.1 root 231: for (i = 1; i < NSIG; i++) {
232:
233: if (sigs & sigm) {
234:
1.1.1.2 root 235: curproc->sigpending &= ~sigm;
236:
237: if (curproc->ptracer && !deliversig) {
1.1 root 238:
1.1.1.2 root 239: TRACE(("tracer being notified of signal %d", i));
1.1 root 240:
1.1.1.2 root 241: stop(i);
1.1 root 242:
1.1.1.2 root 243: /* the parent may reset our pending signals, so check again */
244:
245: goto top;
246:
247: } else {
248:
249: ulong omask;
1.1 root 250:
251:
252:
1.1.1.2 root 253: curproc->sigpending &= ~sigm;
1.1 root 254:
1.1.1.2 root 255: omask = curproc->sigmask;
256:
257:
258:
259: /* sigextra gives which extra signals should also be masked */
260:
261: curproc->sigmask |= curproc->sigextra[i] | sigm;
262:
263: handle_sig(i);
1.1 root 264:
265:
266:
267:
268:
269: /*
270:
271: * POSIX.1-3.3.4.2(723) "If and when the user's signal handler returns
272:
273: * normally, the original signal mask is restored."
274:
275: *
276:
277: * BUG?: This unmasking could unmask a pending signal which we will not
278:
279: * see this time around (if the signal number is less than i) and which
280:
281: * was not pending when we started; should we detect this condition and
282:
283: * loop around for a second try? POSIX only guarantees delivery of
284:
285: * one signal per kernel entry, so this shouldn't really be a problem.
286:
287: */
288:
1.1.1.2 root 289: curproc->sigmask = omask; /* unmask signals */
290:
291: }
1.1 root 292:
293: }
294:
295: sigm = sigm << 1;
296:
297: }
298:
299: }
300:
301: }
302:
303:
304:
305: /*
306:
307: * raise: cause a signal to be raised in the current process
308:
309: */
310:
311:
312:
313: void
314:
315: raise(sig)
316:
317: int sig;
318:
319: {
320:
321: post_sig(curproc, sig);
322:
323: check_sigs();
324:
325: }
326:
327:
328:
329: #ifdef EXCEPTION_SIGS
330:
331: /* exception numbers corresponding to signals */
332:
333: char excep_num[NSIG] =
334:
335: { 0, 0, 0, 0,
336:
337: 4, /* SIGILL == illegal instruction */
338:
339: 9, /* SIGTRAP == trace trap */
340:
341: 4, /* pretend SIGABRT is also illegal instruction */
342:
343: 8, /* SIGPRIV == privileged instruction exception */
344:
345: 5, /* SIGFPE == divide by zero */
346:
347: 0, 2, /* SIGBUS == bus error */
348:
349: 3 /* SIGSEGV == address error */
350:
351: /* everything else gets zeros */
352:
353: };
354:
355:
356:
357: /* a "0" means we don't print a message when it happens -- typically the
358:
359: user is expecting a synchronous signal, so we don't need to report it
360:
361: */
362:
363:
364:
365: const char *signames[NSIG] = { 0,
366:
367: 0, 0, 0, "ILLEGAL INSTRUCTION", "TRACE TRAP",
368:
369: 0, "PRIVILEGE VIOLATION", "DIVISION BY ZERO", 0, "BUS ERROR",
370:
371: "ADDRESS ERROR", "BAD SYSTEM CALL", 0, 0, 0,
372:
373: 0, 0, 0, 0, 0,
374:
375: 0, 0, 0, "CPU TIME EXHAUSTED", "FILE TOO BIG",
376:
377: 0, 0, 0, 0, 0
378:
379: };
380:
381:
382:
383: /*
384:
385: * replaces the TOS "show bombs" routine: for now, print the name of the
386:
387: * interrupt on the console, and save info on the crash in the appropriate
388:
389: * system area
390:
391: */
392:
393:
394:
395: void
396:
397: bombs(sig)
398:
399: int sig;
400:
401: {
402:
403: long *procinfo = (long *)0x380L;
404:
405: int i;
406:
407: CONTEXT *crash;
408:
1.1.1.3 ! root 409: extern int no_mem_prot;
! 410:
! 411:
! 412:
! 413: if (sig < 0 || sig > 31) {
! 414:
! 415: ALERT("bombs(%d): sig out of range", sig);
! 416:
! 417: }
! 418:
! 419: else if (signames[sig]) {
1.1 root 420:
1.1.1.3 ! root 421: if (!no_mem_prot && sig == SIGBUS) {
1.1 root 422:
1.1.1.3 ! root 423: /* already reported by report_buserr */
1.1 root 424:
1.1.1.3 ! root 425: } else {
1.1 root 426:
1.1.1.3 ! root 427: ALERT("%s: User PC=%lx (basepage=%lx)",
1.1 root 428:
1.1.1.3 ! root 429: signames[sig],
1.1 root 430:
1.1.1.3 ! root 431: curproc->exception_pc, curproc->base);
1.1 root 432:
1.1.1.3 ! root 433: }
1.1 root 434:
435: /* save the processor state at crash time */
436:
437: /* assumes that "crash time" is the context curproc->ctxt[SYSCALL] */
438:
439: /* BUG: this is not true if the crash happened in the kernel; in the
440:
441: * latter case, the crash context wasn't saved anywhere.
442:
443: */
444:
445: crash = &curproc->ctxt[SYSCALL];
446:
1.1.1.2 root 447: *procinfo++ = 0x12345678L; /* magic flag for valid info */
1.1 root 448:
449: for (i = 0; i < 15; i++)
450:
451: *procinfo++ = crash->regs[i];
452:
1.1.1.3 ! root 453: *procinfo++ = curproc->exception_ssp;
1.1 root 454:
455: *procinfo++ = ((long)excep_num[sig]) << 24L;
456:
1.1.1.2 root 457: *procinfo = crash->usp;
1.1 root 458:
459:
460:
461: /* we're also supposed to save some info from the supervisor stack. it's not
462:
463: * clear what we should do for MiNT, since most of the stuff that used to be
464:
465: * on the stack has been put in the CONTXT struct. Moreover, we don't want
466:
467: * to crash because of an attempt to access illegal memory. Hence, we do
468:
469: * nothing here...
470:
471: */
472:
1.1.1.3 ! root 473: } else {
! 474:
! 475: TRACE(("bombs(%d)", sig));
! 476:
1.1 root 477: }
478:
479: }
480:
481: #endif
482:
483:
484:
485: /*
486:
487: * handle_sig: do whatever is appropriate to handle a signal
488:
489: */
490:
491:
492:
493: static long unwound_stack = 0;
494:
495:
496:
497: void
498:
499: handle_sig(sig)
500:
501: int sig;
502:
503: {
504:
505: long oldstack, newstack;
506:
507: long *stack;
508:
509: CONTEXT *call, oldsysctxt, newcurrent;
510:
511: extern void sig_return();
512:
513:
514:
515: if (curproc->sighandle[sig] == SIG_IGN)
516:
517: return;
518:
519: else if (curproc->sighandle[sig] == SIG_DFL) {
520:
521: _default:
522:
523: switch(sig) {
524:
525: #if 0
526:
527: /* Note: SIGNULL is filtered out in dossig.c and is never actually
528:
529: * delivered (its only purpose for the user is to test for the existence of
530:
531: * a process, it isn't a real signal). The kernel uses SIGNULL
532:
533: * internally, but all such code does the signal handling "by hand"
534:
535: * and so no default handling is necessary.
536:
537: */
538:
1.1.1.2 root 539: case SIGNULL:
1.1 root 540:
541: #endif
542:
1.1.1.2 root 543: case SIGWINCH:
1.1 root 544:
1.1.1.2 root 545: case SIGCHLD:
1.1 root 546:
1.1.1.3 ! root 547: /* SIGFPE is divide by 0; TOS ignores this, so we will too */
! 548:
! 549: case SIGFPE:
! 550:
1.1.1.2 root 551: return; /* do nothing */
1.1 root 552:
1.1.1.2 root 553: case SIGSTOP:
1.1 root 554:
1.1.1.2 root 555: case SIGTSTP:
1.1 root 556:
1.1.1.2 root 557: case SIGTTIN:
1.1 root 558:
1.1.1.2 root 559: case SIGTTOU:
1.1 root 560:
1.1.1.2 root 561: stop(sig);
1.1 root 562:
1.1.1.2 root 563: return;
1.1 root 564:
1.1.1.2 root 565: case SIGCONT:
1.1 root 566:
1.1.1.2 root 567: curproc->sigpending &= ~STOPSIGS;
1.1 root 568:
1.1.1.2 root 569: return;
1.1 root 570:
571:
572:
1.1.1.2 root 573: /* here are the fatal signals. for SIGINT, we use p_term(-32) so that
1.1 root 574:
1.1.1.2 root 575: * TOS programs that catch ^C via the vector at 0x400 and which expect
1.1 root 576:
1.1.1.2 root 577: * TOS's error code (-32) to be sent will work. For most other signals,
1.1 root 578:
1.1.1.2 root 579: * we p_term with an error code; for SIGKILL, we don't want to allow
1.1 root 580:
1.1.1.2 root 581: * the program any chance to recover, so we call terminate() directly
1.1 root 582:
1.1.1.2 root 583: * to avoid calling through to the user's terminate vector.
1.1 root 584:
1.1.1.2 root 585: */
1.1 root 586:
1.1.1.2 root 587: case SIGINT: /* ^C */
1.1 root 588:
1.1.1.2 root 589: if (curproc->domain == DOM_TOS) {
1.1 root 590:
1.1.1.2 root 591: p_term(-32);
1.1 root 592:
1.1.1.2 root 593: return;
1.1 root 594:
1.1.1.2 root 595: }
596:
597: /* otherwise, fall through */
1.1 root 598:
1.1.1.2 root 599: default:
1.1 root 600:
601: #ifdef EXCEPTION_SIGS
602:
1.1.1.2 root 603: bombs(sig); /* tell the user what happened */
1.1 root 604:
605: #endif
606:
1.1.1.2 root 607: /* the "sigmask" check is in case a bus error happens in the user's
608:
609: * term_vec code; we don't want to get stuck in an infinite loop!
610:
611: */
612:
613: if ((curproc->sigmask & 1L) || sig == SIGKILL)
614:
1.1 root 615: terminate(sig << 8, ZOMBIE_Q);
616:
1.1.1.2 root 617: else
618:
619: p_term(sig << 8);
620:
1.1 root 621: }
622:
623: }
624:
625: else { /* user wants to handle it himself */
626:
627:
628:
629: /* another kludge: there is one case in which the p_sigreturn mechanism
630:
631: * is invoked by the kernel, namely when the user calls Supexec()
632:
633: * or when s/he installs a handler for the GEMDOS terminate vector (#0x102)
634:
635: * and the program terminates. MiNT fakes the call to user code with
636:
637: * signal 0 (SIGNULL); programs that longjmp out of the user function
638:
639: * and are later sent back to it again (e.g. if ^C keeps getting pressed
640:
641: * and a terminate vector has been installed) will grow the stack without
642:
643: * bound unless we watch for this case.
644:
645: *
646:
647: * Solution (sort of): whenever Pterm() is called, we unwind the
648:
649: * stack; otherwise, we let it grow, so that nested Supexec()
650:
651: * calls work.
652:
653: *
654:
655: * Note that SIGNULL is thrown away when sent by user processes,
656:
657: * and the user can't mask it (it's UNMASKABLE), so there is
658:
659: * is no possibility of confusion with anything the user does.
660:
661: */
662:
663: if (sig == 0) {
664:
665: /* p_term() sets sigmask to let us know to do Psigreturn */
666:
667: if (curproc->sigmask & 1L) {
668:
669: p_sigreturn();
670:
671: curproc->sigmask &= ~1L;
672:
673: } else {
674:
675: unwound_stack = 0;
676:
677: }
678:
679: }
680:
681:
682:
683: call = &curproc->ctxt[SYSCALL];
684:
685: /*
686:
687: * what we do is build two fake stack frames; the bottom one is
688:
689: * for a call to the user function, with (long)parameter being the
690:
691: * signal number; the top one is for sig_return.
692:
693: * When the user function returns, it returns to sig_return, which
694:
695: * calls into the kernel to restore the context in prev_ctxt
696:
697: * (thus putting us back here). We can then continue on our way.
698:
699: */
700:
701:
702:
703: /* set a new system stack, with a bit of buffer space */
704:
705: oldstack = curproc->sysstack;
706:
707: newstack = ((long) ( (&newcurrent) - 3 )) - 12;
708:
709:
710:
711: if (newstack < (long)curproc->stack + ISTKSIZE + 256) {
712:
713: ALERT("stack overflow");
714:
715: goto _default;
716:
717: }
718:
719: else if ((long) curproc->stack + STKSIZE < newstack) {
720:
721: FATAL("system stack not in proc structure");
722:
723: }
724:
725:
726:
727: /* unwound_stack is set by p_sigreturn() */
728:
729: if (sig == 0 && unwound_stack)
730:
731: curproc->sysstack = unwound_stack;
732:
733: else
734:
735: curproc->sysstack = newstack;
736:
737: oldsysctxt = *call;
738:
739: stack = (long *)(call->sr & 0x2000 ? call->ssp :
740:
741: call->usp);
742:
743: /*
744:
745: Hmmm... here's another potential problem for the signal 0 terminate
746:
747: vector: if the program keeps returning back to user mode without
748:
749: worrying about the supervisor stack, we'll eventually overflow it.
750:
751: However, if the program is in supervisor mode itself, then we don't
752:
753: want to stomp on its stack. Temporary solution: ignore the problem,
754:
1.1.1.2 root 755: the stack's only growing 12 bytes at a time.
1.1 root 756:
757: */
758:
1.1.1.2 root 759: /*
760:
761: * in addition to the signal number we stuff the vector offset on the
762:
763: * stack; if the user is interested they can sniff it, if not ignoring
764:
765: * it needs no action on their part. Why do we need this? So that a
766:
767: * single SIGFPE handler (for example) can discriminate amongst the
768:
769: * multiple things which may get thrown its way
770:
771: */
772:
773: *(--stack) = (long)call->sfmt & 0xfff;
774:
1.1 root 775: *(--stack) = (long)sig;
776:
777: *(--stack) = (long)sig_return;
778:
779: if (call->sr & 0x2000)
780:
781: call->ssp = ((long) stack);
782:
783: else
784:
785: call->usp = ((long) stack);
786:
787: call->pc = (long) curproc->sighandle[sig];
788:
1.1.1.2 root 789: call->sfmt = call->fstate[0] = 0; /* don't restart FPU communication */
790:
1.1 root 791:
792:
793: ((long *)curproc->sysstack)[1] = FRAME_MAGIC;
794:
795: ((long *)curproc->sysstack)[2] = oldstack;
796:
797: ((long *)curproc->sysstack)[3] = sig;
798:
799:
800:
1.1.1.2 root 801: if (curproc->sigflags[sig] & SA_RESET) {
802:
803: curproc->sighandle[sig] = SIG_DFL;
804:
805: curproc->sigflags[sig] &= ~SA_RESET;
806:
807: }
808:
809:
810:
1.1 root 811: if (save_context(&newcurrent) == 0 ) {
812:
813: /*
814:
815: * go do the signal; eventually, we'll restore this context (unless the
816:
817: * user longjmp'd out of his signal handler). while the user is handling
818:
819: * the signal, it's masked out to prevent race conditions. p_sigreturn()
820:
821: * will unmask it for us when the user is finished.
822:
823: */
824:
825: newcurrent.regs[0] = CTXT_MAGIC;
826:
827: /* set D0 so next return is different */
828:
829: assert(curproc->magic == CTXT_MAGIC);
830:
831: leave_kernel();
832:
833: restore_context(call);
834:
835: }
836:
837: /*
838:
839: * OK, we get here from p_sigreturn, via the user returning from
840:
841: * the handler to sig_return. Restoring the stack and unmasking the
842:
843: * signal have been done already for us by p_sigreturn.
844:
845: * We should just restore the old system call context
846:
847: * and continue with whatever it was we were doing.
848:
849: */
850:
1.1.1.2 root 851: TRACE(("done handling signal"));
1.1 root 852:
853: curproc->ctxt[SYSCALL] = oldsysctxt;
854:
855: assert(curproc->magic == CTXT_MAGIC);
856:
857: }
858:
859: }
860:
861:
862:
863: /*
864:
865: * the p_sigreturn system call
866:
867: * When called by the user from inside a signal handler, it indicates a
868:
869: * desire to restore the old stack frame prior to a longjmp() out of
870:
871: * the handler.
872:
873: * When called from the sig_return module, it indicates that the user
874:
875: * is finished a handler, and we should not only restore the stack
876:
877: * frame but also the old context we were working in (which is on the
878:
879: * system call stack -- see handle_sig).
880:
881: * The "valid_return" variable is 0 in the first case, 1 in the second.
882:
883: */
884:
885:
886:
887: short valid_return;
888:
889:
890:
1.1.1.2 root 891: long ARGS_ON_STACK
1.1 root 892:
893: p_sigreturn()
894:
895: {
896:
897: CONTEXT *oldctxt;
898:
899: long *frame;
900:
901: long sig;
902:
903:
904:
905: unwound_stack = 0;
906:
907: top:
908:
909: frame = (long *)curproc->sysstack;
910:
911: frame++; /* frame should point at FRAME_MAGIC, now */
912:
913: sig = frame[2];
914:
915: if (*frame != FRAME_MAGIC || (sig < 0) || (sig >= NSIG)) {
916:
917: FATAL("Psigreturn: system stack corrupted");
918:
919: }
920:
921: if (frame[1] == 0) {
922:
1.1.1.2 root 923: DEBUG(("Psigreturn: frame at %lx points to 0", frame-1));
1.1 root 924:
925: return 0;
926:
927: }
928:
929: unwound_stack = curproc->sysstack;
930:
1.1.1.2 root 931: TRACE(("Psigreturn(%d)", (int)sig));
1.1 root 932:
933:
934:
935: curproc->sysstack = frame[1]; /* restore frame */
936:
937: curproc->sigmask &= ~(1L<<sig); /* unblock signal */
938:
939:
940:
941: if (!valid_return) {
942:
943: /* here, the user is telling us that a longjmp out of a signal handler is
944:
945: * about to occur; so we should unwind *all* the signal frames
946:
947: */
948:
949: goto top;
950:
951: }
952:
953: else {
954:
955: valid_return = 0;
956:
957: oldctxt = ((CONTEXT *)(&frame[2])) + 3;
958:
959: if (oldctxt->regs[0] != CTXT_MAGIC) {
960:
961: FATAL("p_sigreturn: corrupted context");
962:
963: }
964:
965: assert(curproc->magic == CTXT_MAGIC);
966:
967: restore_context(oldctxt);
968:
969: return 0; /* dummy -- this isn't reached */
970:
971: }
972:
973: }
974:
975:
976:
977: /*
978:
979: * stop a process because of signal "sig"
980:
981: */
982:
983:
984:
985: void
986:
987: stop(sig)
988:
989: int sig;
990:
991: {
992:
993: unsigned int code;
994:
995: unsigned long oldmask;
996:
997: PROC *p;
998:
999:
1000:
1001: code = sig << 8;
1002:
1003:
1004:
1005: if (curproc->pid == 0) {
1006:
1.1.1.3 ! root 1007: FORCE("attempt to stop MiNT");
1.1 root 1008:
1009: return;
1010:
1011: }
1012:
1013:
1014:
1015: /* notify parent */
1016:
1.1.1.2 root 1017: if (curproc->ptracer) {
1.1 root 1018:
1.1.1.2 root 1019: p = curproc->ptracer;
1.1 root 1020:
1021: post_sig(p, SIGCHLD);
1022:
1.1.1.2 root 1023: } else {
1024:
1025: p = pid2proc(curproc->ppid);
1026:
1027: if (p && !(p->sigflags[SIGCHLD] & SA_NOCLDSTOP))
1028:
1029: post_sig(p, SIGCHLD);
1030:
1.1 root 1031: }
1032:
1033:
1034:
1035: oldmask = curproc->sigmask;
1036:
1037:
1038:
1.1.1.2 root 1039: if ((1L << sig) & STOPSIGS) {
1040:
1041: /* mask out most signals */
1042:
1043: curproc->sigmask |= ~(UNMASKABLE | SIGTERM);
1044:
1045: }
1.1 root 1046:
1.1.1.2 root 1047: else
1048:
1049: assert(curproc->ptracer);
1.1 root 1050:
1051:
1052:
1053: /* sleep until someone signals us awake */
1054:
1055: sleep(STOP_Q, (long) code | 0177);
1056:
1057:
1058:
1059: /* when we wake up, restore the signal mask */
1060:
1061: curproc->sigmask = oldmask;
1062:
1063:
1064:
1065: /* and discard any signals that would cause us to stop again */
1066:
1067: curproc->sigpending &= ~STOPSIGS;
1068:
1069: }
1070:
1071:
1072:
1073: /*
1074:
1075: * interrupt handlers to raise SIGBUS, SIGSEGV, etc. Note that for
1076:
1077: * really fatal errors we reset the handler to SIG_DFL, so that
1078:
1079: * a second such error kills us
1080:
1081: */
1082:
1083:
1084:
1085: void
1086:
1087: exception(sig)
1088:
1089: int sig;
1090:
1091: {
1092:
1.1.1.2 root 1093: curproc->sigflags[sig] |= SA_RESET;
1094:
1.1.1.3 ! root 1095: DEBUG(("exception #%d raised", sig));
1.1 root 1096:
1097: raise(sig);
1098:
1099: }
1100:
1101:
1102:
1103: void
1104:
1105: sigbus()
1106:
1107: {
1108:
1.1.1.3 ! root 1109: report_buserr();
! 1110:
1.1 root 1111: exception(SIGBUS);
1112:
1113: }
1114:
1115:
1116:
1117: void
1118:
1119: sigaddr()
1120:
1121: {
1122:
1123: exception(SIGSEGV);
1124:
1125: }
1126:
1127:
1128:
1129: void
1130:
1131: sigill()
1132:
1133: {
1134:
1135: exception(SIGILL);
1136:
1137: }
1138:
1139:
1140:
1141: void
1142:
1143: sigpriv()
1144:
1145: {
1146:
1147: raise(SIGPRIV);
1148:
1149: }
1150:
1151:
1152:
1153: void
1154:
1155: sigfpe()
1156:
1157: {
1158:
1.1.1.2 root 1159: extern short fpu; /* in main.c */
1160:
1161:
1162:
1163: if (fpu) {
1164:
1165: CONTEXT *ctxt;
1166:
1167:
1168:
1169: ctxt = &curproc->ctxt[SYSCALL];
1170:
1171:
1172:
1173: /* 0x1f38 is a Motorola magic cookie to detect a 68882 idle state frame */
1174:
1175: if (*(ushort *)ctxt->fstate == 0x1f38 &&
1176:
1177: (ctxt->sfmt & 0xfff) >= 0xc0L && (ctxt->sfmt & 0xfff) <= 0xd8L) {
1178:
1179: /* fix a bug in the 68882 - Motorola call it a feature :-) */
1180:
1181: ctxt->fstate[ctxt->fstate[1]] |= 1 << 3;
1182:
1183: }
1184:
1185: }
1186:
1.1 root 1187: raise(SIGFPE);
1188:
1189: }
1190:
1191:
1192:
1193: void
1194:
1195: sigtrap()
1196:
1197: {
1198:
1199: raise(SIGTRAP);
1200:
1201: }
1202:
1.1.1.2 root 1203:
1204:
1205: void
1206:
1207: haltformat()
1208:
1209: {
1210:
1211: FATAL("halt: invalid stack frame format");
1212:
1213: }
1214:
1215:
1216:
1217: void
1218:
1219: haltcpv()
1220:
1221: {
1222:
1223: FATAL("halt: coprocessor protocol violation");
1224:
1225: }
1226:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.