|
|
1.1 root 1: /* (lgl-
2: * The information contained herein is a trade secret of Mark Williams
3: * Company, and is confidential information. It is provided under a
4: * license agreement, and may be copied or disclosed only under the
5: * terms of that agreement. Any reproduction or disclosure of this
6: * material without the express written authorization of Mark Williams
7: * Company or persuant to the license agreement is unlawful.
8: *
9: * COHERENT Version 5.0
10: * Copyright (c) 1982, 1993.
11: * An unpublished work by Mark Williams Company, Chicago.
12: * All rights reserved.
13: -lgl) */
14: /*
15: * File: coh.386/sig.c
16: *
17: * Purpose: signal handling
18: *
19: * Revised: Tue May 4 11:59:15 1993 CDT
20: */
21:
22: /*
23: * ----------------------------------------------------------------------
24: * Includes.
25: */
26: #include <sys/coherent.h>
27: #include <errno.h>
28: #include <sys/ino.h>
29: #include <sys/inode.h>
30: #include <sys/io.h>
31: #include <sys/proc.h>
32: #include <sys/ptrace.h>
33: #include <sys/sched.h>
34: #include <sys/seg.h>
35: #include <signal.h>
36: #include <sys/core.h>
37:
38: /*
39: * ----------------------------------------------------------------------
40: * Definitions.
41: * Constants.
42: * Macros with argument lists.
43: * Typedefs.
44: * Enums.
45: */
46: typedef void (*VFPTR)(); /* pointer to void function */
47:
48: /*
49: * ----------------------------------------------------------------------
50: * Functions.
51: * Import Functions.
52: * Export Functions.
53: * Local Functions.
54: */
55: int actvsig();
56: int nondsig();
57: int ptret();
58: int ptset();
59: void sendsig();
60: void sigDefault();
61: void sigHold();
62: void sigIgnore();
63: void sigPause();
64: void sigRelease();
65: int sigSet();
66: int sigdump();
67: int usigsys();
68:
69: static struct _fpstate * empack();
70:
71: /*
72: * ----------------------------------------------------------------------
73: * Global Data.
74: * Import Variables.
75: * Export Variables.
76: * Local Variables.
77: */
78: /*
79: * Patchable variables.
80: *
81: * Patch DUMP_TEXT nonzero to make text segment show up in core files.
82: * Patch DUMP_LIM set the upper limit in bytes of how much of a
83: * segment is written to a core file.
84: *
85: * Patch CATCH_SEGV nonzero if you are trying to run software that was
86: * written in blatant defiance of the SVID 2 caution that handling SIGSEGV
87: * is nonportable and should not be assumed valid on all systems.
88: */
89: int DUMP_TEXT = 0;
90: int DUMP_LIM=512*1024;
91: int CATCH_SEGV = 0;
92:
93: /*
94: * ----------------------------------------------------------------------
95: * Code.
96: */
97:
98: /*
99: * Given 1-based signal number, ask whether a signal handler was
100: * attached to the current process using sigset(). This allows
101: * the kernel to process sigset() differently from signal(), as
102: * required.
103: *
104: * return 1 if sigset(), 0 if not.
105: */
106: int
107: sigSet(signal)
108: int signal;
109: {
110: return (SELF->p_dsig & SIG_BIT(signal)) ? 1 : 0;
111: }
112:
113: /*
114: * Given 1-based signal number, ignore that signal in the current process.
115: */
116: void
117: sigIgnore(signal)
118: int signal;
119: {
120: int sigbit = SIG_BIT(signal);
121:
122: SELF->p_dfsig &= ~sigbit; /* No longer defaulted. */
123: SELF->p_isig |= sigbit; /* Mark signal as ignored. */
124: u.u_sfunc[signal - 1] = SIG_IGN;
125: }
126:
127: /*
128: * Given 1-based signal number, restore default handling for the current
129: * process.
130: *
131: * There is some duplication of work done in sigAttach(), but sigDefault()
132: * is also called from msig.c
133: */
134: void
135: sigDefault(signal)
136: int signal;
137: {
138: int sigbit = SIG_BIT(signal);
139:
140: SELF->p_dfsig |= sigbit;
141: SELF->p_isig &= ~sigbit;
142: u.u_sfunc[signal - 1] = SIG_DFL;
143: }
144:
145: /*
146: * Given 1-based signal number, hold that signal for the current process.
147: */
148: void
149: sigHold(signal)
150: int signal;
151: {
152: SELF->p_hsig |= SIG_BIT(signal);
153: }
154:
155: /*
156: * Given 1-based signal number, pause for that signal for the current process.
157: */
158: void
159: sigPause(signal)
160: int signal;
161: {
162: SELF->p_hsig &= ~SIG_BIT(signal);
163:
164: /*
165: * Like upause(), do a sleep on an event which never gets a wakeup.
166: * The sleep returns immediately if a signal was already holding.
167: */
168: x_sleep((char *)&u, prilo, slpriSigCatch, "sigpause");
169: actvsig();
170: }
171:
172: /*
173: * Given 1-based signal number, release that signal for the current process.
174: */
175: void
176: sigRelease(signal)
177: int signal;
178: {
179: SELF->p_hsig &= ~SIG_BIT(signal);
180: if (nondsig()) {
181: actvsig();
182: }
183: }
184:
185: /*
186: * Given 1-based signal number, a pointer to a signal-handling function,
187: * and a flag, attach the signal handler to the current process.
188: *
189: * Function pointer "func" may take on special values SIG_DFL, SIG_IGN,
190: * and, if "how" is SIGSET, SIG_HOLD.
191: *
192: * The flag "how" is 0 if attachment is via signal(), SIGSET if attachment
193: * is via sigset().
194: *
195: * Return the previously attached signal handler, or SIG_HOLD if signals
196: * were previously held.
197: */
198: VFPTR
199: sigAttach(signal, func, how)
200: int signal;
201: VFPTR func;
202: int how;
203: {
204: VFPTR retval;
205: int sigbit = SIG_BIT(signal);
206:
207: /*
208: * Set up the return value, which says what was previously
209: * done with the given signal.
210: */
211: if (SELF->p_isig & sigbit)
212: retval = (VFPTR)SIG_IGN;
213: else if (SELF->p_hsig & sigbit)
214: retval = (VFPTR)SIG_HOLD;
215: else
216: retval = u.u_sfunc[signal - 1];
217:
218: u.u_sigreturn = (VFPTR)(u.u_regl[EDX]);
219: u.u_sfunc[signal - 1] = func;
220:
221: /*
222: * Remove previous default, ignore, or hold status.
223: */
224: SELF->p_dfsig &= ~sigbit;
225: SELF->p_isig &= ~sigbit;
226: SELF->p_hsig &= ~sigbit;
227:
228: /*
229: * Any pending signal is lost.
230: */
231: SELF->p_ssig &= ~sigbit;
232:
233: /*
234: * Special cases for handler.
235: */
236: switch ((int)func) {
237: case (int)SIG_DFL:
238: sigDefault(signal);
239: break;
240: case (int)SIG_IGN:
241: sigIgnore(signal);
242: break;
243: case (int)SIG_HOLD:
244: sigHold(signal);
245: break;
246: }
247:
248: /*
249: * Remember whether handler was attached with sigset() vs signal().
250: */
251: if (how == SIGSET)
252: SELF->p_dsig |= sigbit;
253: else
254: SELF->p_dsig &= ~sigbit;
255:
256: return retval;
257: }
258:
259: /*
260: * Set up the action to be taken on a signal.
261: */
262: int
263: usigsys(signal, func)
264: int signal;
265: VFPTR func;
266: {
267: int sigtype;
268: int retval = 0;
269:
270: sigtype = signal & ~0xFF;
271: signal &= 0xFF;
272:
273: T_HAL(8, if (signal == SIGINT)
274: printf("[%d]sigint(%x, %x) ", SELF->p_pid, sigtype, func));
275:
276: /* Range check on 1-based signal number. */
277: if (signal <= 0 || signal > NSIG) {
278: u.u_error = EINVAL;
279: return;
280: }
281:
282: /*
283: * Don't allow setting/holding/releasing some signals.
284: *
285: * NOTICE: Ignoring SIGSEGV causes runaway user faults.
286: * SVID Issue 2 says *don't* do signal(SIGSEGV,...)!!!
287: */
288: if (signal == SIGKILL) {
289: u.u_error = EINVAL;
290: return;
291: }
292:
293: if (signal == SIGSEGV && CATCH_SEGV == 0) {
294: u.u_error = EINVAL;
295: return;
296: }
297:
298: switch (sigtype) {
299: case SIGHOLD:
300: sigHold(signal);
301: break;
302: case SIGRELSE:
303: sigRelease(signal);
304: break;
305: case SIGIGNORE:
306: sigIgnore(signal);
307: break;
308: case 0: /* old system entry */
309: retval = (int)sigAttach(signal, func, 0);
310: break;
311: case SIGSET: /* new system entry */
312: retval = (int)sigAttach(signal, func, SIGSET);
313: break;
314: case SIGPAUSE:
315: sigPause(signal);
316: break;
317: default:
318: u.u_error = SIGSYS;
319: break;
320: }
321: return retval;
322: }
323:
324: /*
325: * Send a signal to the process `pp'.
326: * Return 1 if signal was sent.
327: * Return 0 if signal was ignored.
328: * The return value is of use to the trap handler.
329: */
330: void
331: sendsig(sig, pp)
332: register unsigned sig;
333: register PROC *pp;
334: {
335: register sig_t f;
336: register int s;
337:
338: T_HAL(8, if (sig == SIGINT) printf("[%d]gets int ", pp->p_pid));
339:
340: /*
341: * Convert the signal to a bit position.
342: */
343: f = SIG_BIT(sig);
344:
345: /*
346: * If the signal is ignored, and is not SIGCLD, do nothing.
347: */
348: if ((pp->p_isig & f) && sig != SIGCLD) {
349: goto sendSigDone;
350: }
351:
352: /*
353: * No further processing for delayed or held signals.
354: */
355: if ((pp->p_ssig & f) && (pp->p_hsig|pp->p_dsig) & f)
356: goto sendSigDone;
357:
358: /*
359: * Actually send the signal by flagging the needed bit.
360: */
361: pp->p_ssig |= f;
362:
363: /*
364: * If the process is sleeping, wake it up so that
365: * it can process this signal.
366: */
367: if (pp->p_state == PSSLSIG) {
368: s = sphi();
369: pp->p_lback->p_lforw = pp->p_lforw;
370: pp->p_lforw->p_lback = pp->p_lback;
371: #ifndef _I386
372: addu(pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK);
373: #endif
374: setrun(pp);
375: spl(s);
376: }
377: sendSigDone:
378: return;
379: }
380:
381: /*
382: * Return signal number if we have a non ignored or delayed signal, else zero.
383: */
384: int
385: nondsig()
386: {
387: register PROC *pp;
388: register sig_t mask;
389: register int signo;
390:
391: pp = SELF;
392: signo = 0;
393:
394: /*
395: * Turn off all ignored signals except SIGCLD.
396: */
397: pp->p_ssig &= ~(pp->p_isig & ~SIG_BIT(SIGCLD));
398:
399: /*
400: * If any signals have arrived, but which are not held,
401: * figure out what they are.
402: */
403: if (pp->p_ssig&~pp->p_hsig) {
404: /*
405: * There is at least one signal. Extract its number
406: * from the signal bits.
407: */
408: mask = (sig_t) 1;
409: signo += 1;
410: while (((pp->p_ssig&~pp->p_hsig) & mask) == 0) {
411: mask <<= 1;
412: signo += 1;
413: }
414: }
415: return signo;
416: }
417:
418: /*
419: * If we have a signal that isn't ignored, activate it.
420: */
421: int
422: actvsig()
423: {
424: register int signum;
425: register PROC *pp;
426: register int (*func)();
427: int ptval;
428:
429: /*
430: * Fetch an unprocessed signal.
431: * Return if there are none.
432: * The while() structure is only for traced processes.
433: */
434: while (signum = nondsig()) {
435:
436: pp = SELF;
437:
438: /*
439: * Reset the signal to indicate that it has been processed.
440: * Bit table p_ssig uses 0-based signals, while signal.h
441: * lists 1-based signals.
442: */
443: pp->p_ssig &= ~SIG_BIT(signum);
444:
445: /*
446: * Fetch the user function that goes with this signal.
447: * Function table u_sfunc uses 0-based signals, while signal.h
448: * lists 1-based signals.
449: */
450: func = u.u_sfunc[signum-1];
451:
452: /*
453: * SIGCLD causes no work here if defaulted or ignored.
454: */
455: if (signum == SIGCLD && (func == SIG_DFL || func == SIG_IGN))
456: return;
457:
458: /*
459: * Store the (1-based) signal number in the u area.
460: * This is how a core dump records the death signal.
461: */
462: u.u_signo = signum;
463:
464: /*
465: * If the signal is not defaulted, go run the requested
466: * function.
467: */
468: if (func != SIG_DFL) {
469: if (XMODE_286)
470: oldsigstart(signum, func);
471: else {
472: msigstart(signum, func);
473: }
474: return;
475: }
476:
477: /*
478: * ASSERTION: the signal being processed is SIG_DFL'd.
479: */
480:
481: /*
482: * msysgen() is a nop for COHERENT 4.0. The comment in the
483: * assembly code is "Nothing useful to save".
484: */
485: msysgen(u.u_sysgen);
486:
487: /*
488: * When a traced process is signaled, it may need to exchange
489: * data with its parent (via ptret).
490: */
491: if (pp->p_flags&PFTRAC) {
492: pp->p_flags |= PFWAIT;
493: ptval = ptret();
494: T_HAL(0x10000, printf("ptret()=%x ", ptval));
495: pp->p_flags &= ~(PFWAIT|PFSTOP);
496: if (ptval == 0)
497: /* see if another signal came in */
498: continue;
499: else
500: signum = ptval;
501: }
502:
503: /*
504: * Some signals cause a core file to be written.
505: */
506: switch(signum) {
507: case SIGQUIT:
508: case SIGILL:
509: case SIGTRAP:
510: case SIGABRT:
511: case SIGFPE:
512: case SIGSEGV:
513: case SIGSYS:
514: if (sigdump())
515: signum |= 0x80;
516: break;
517: }
518: pexit(signum);
519: }
520: }
521:
522: /*
523: * Create a dump of ourselves onto the file `core'.
524: */
525: int
526: sigdump()
527: {
528: register INODE *ip;
529: register SR *srp;
530: register SEG * sp;
531: register int n;
532: register paddr_t ssize;
533: extern int DUMP_LIM;
534: struct ch_info chInfo;
535:
536: if (SELF->p_flags&PFNDMP)
537: return (0);
538: u.u_io.io_seg = IOSYS;
539: u.u_io.io_flag = 0;
540: /* Make the core with the real owners */
541: schizo();
542: if (ftoi("core", 'c')) {
543: schizo();
544: return (0);
545: }
546: if ((ip=u.u_cdiri) == NULL) {
547: if ((ip=imake(IFREG|0644, 0)) == NULL) {
548: schizo();
549: return (0);
550: }
551: } else {
552: if ((ip->i_mode&IFMT)!=IFREG
553: || iaccess(ip, IPW)==0
554: || getment(ip->i_dev, 1)==NULL) {
555: idetach(ip);
556: schizo();
557: return (0);
558: }
559: iclear(ip);
560: }
561: schizo();
562: u.u_error = 0;
563: u.u_io.io_seek = 0;
564:
565: /* Write core file header */
566: chInfo.ch_magic = CORE_MAGIC;
567: chInfo.ch_info_len = sizeof(chInfo);
568: chInfo.ch_uproc_offset = U_OFFSET;
569:
570: u.u_io.io_seg = IOSYS;
571: u.u_io.io.vbase = &chInfo;
572: u.u_io.io_ioc = sizeof(chInfo);
573: u.u_io.io_flag = 0;
574:
575: sp->s_lrefc++;
576: iwrite(ip, &u.u_io);
577: sp->s_lrefc--;
578:
579: /*
580: * Added to aid in kernel debugging - if DUMP_TEXT is nonzero,
581: * dump the text segment (to see if it was corrupted) and set
582: * the dump flag so that postmortem utilities will know that
583: * text is present in the core file.
584: */
585: if (DUMP_TEXT)
586: u.u_segl[SISTEXT].sr_flag |= SRFDUMP;
587:
588: for (srp=u.u_segl; u.u_error==0 && srp<&u.u_segl[NUSEG]; srp++) {
589:
590: if ((srp->sr_flag & SRFDUMP)==0)
591: continue;
592:
593: /* Don't try to dump empty segments. */
594: if ((sp = srp->sr_segp)==NULL) {
595: srp->sr_flag &= ~SRFDUMP;
596: continue;
597: }
598:
599: /* Don't dump segments too big to dump. */
600: if (sp->s_size > DUMP_LIM)
601: srp->sr_flag &= ~SRFDUMP;
602: }
603:
604: for (srp=u.u_segl; u.u_error==0 && srp<&u.u_segl[NUSEG]; srp++) {
605:
606: /* Only dump segments flagged for dumping. */
607: if ((srp->sr_flag & SRFDUMP)==0)
608: continue;
609:
610: ssize = sp->s_size;
611: u.u_io.io_seg = IOPHY;
612: u.u_io.io.pbase = MAPIO(sp->s_vmem, 0);
613: u.u_io.io_flag = 0;
614: sp->s_lrefc++;
615: while (u.u_error == 0 && ssize != 0) {
616: n = ssize > SCHUNK ? SCHUNK : ssize;
617: u.u_io.io_ioc = n;
618: iwrite(ip, &u.u_io);
619: u.u_io.io.pbase += n;
620: ssize -= (paddr_t)n;
621: }
622: sp->s_lrefc--;
623: }
624: idetach(ip);
625: return (u.u_error==0);
626: }
627:
628: /*
629: * Send a ptrace command to the child.
630: *
631: * "pid" is child pid.
632: */
633: int
634: ptset(req, pid, addr, data)
635: unsigned req;
636: int *addr;
637: {
638: register PROC *pp;
639:
640: lock(pnxgate);
641: for (pp=procq.p_nforw; pp!=&procq; pp=pp->p_nforw)
642: if (pp->p_pid == pid)
643: break;
644: unlock(pnxgate);
645: if (pp==&procq || (pp->p_flags&PFSTOP)==0 || pp->p_ppid!=SELF->p_pid){
646: u.u_error = ESRCH;
647: return;
648: }
649: lock(pts.pt_gate);
650: pts.pt_req = req;
651: pts.pt_pid = pid;
652: pts.pt_addr = addr;
653: pts.pt_data = data;
654: pts.pt_errs = 0;
655: pts.pt_rval = 0;
656: pts.pt_busy = 1;
657: wakeup((char *)&pts.pt_req);
658: while (pts.pt_busy) {
659: x_sleep((char *)&pts.pt_busy, primed, slpriSigCatch, "ptrace");
660: /* Send a ptrace command to the child. */
661: }
662: u.u_error = pts.pt_errs;
663: unlock(pts.pt_gate);
664: return (pts.pt_rval);
665: }
666:
667: /*
668: * This routine is called when a child that is being traced receives a signal
669: * that is not caught or ignored. It follows up on any requests by the parent
670: * and returns when done.
671: *
672: * After ptrace handling done in this routine, a real or simulated signal
673: * may need to be sent to the traced process.
674: * Return a signal number to be sent to the child process, or 0 if none.
675: */
676: int
677: ptret()
678: {
679: extern void (*ndpKfrstor)();
680: register PROC *pp;
681: register PROC *pp1;
682: register int sign;
683: unsigned off;
684: int doEmUnpack = 0;
685:
686: struct _fpstate * fstp = empack();
687:
688: pp = SELF;
689: next:
690: u.u_error = 0;
691: if (pp->p_ppid == 1)
692: return (SIGKILL);
693: sign = -1;
694:
695: /* wake up parent if it is sleeping */
696: lock(pnxgate);
697: pp1 = &procq;
698: for (;;) {
699: if ((pp1=pp1->p_nforw) == &procq) {
700: sign = SIGKILL;
701: break;
702: }
703: if (pp1->p_pid != pp->p_ppid)
704: continue;
705: if (ASLEEP(pp1))
706: wakeup((char *)pp1);
707: break;
708: }
709: unlock(pnxgate);
710:
711: while (sign < 0) {
712: /* If no pending ptrace transaction for this process, sleep. */
713: if (pts.pt_busy==0 || pp->p_pid!=pts.pt_pid) {
714: /* If a signal bit is set now, just exit - let
715: * actvsig() handle it next time through.
716: * Doing sleep and goto next will stick us in a loop */
717: if (nondsig())
718: return 0;
719: x_sleep((char *)&pts.pt_req,
720: primed, slpriSigCatch, "ptret");
721: goto next;
722: }
723: switch (pts.pt_req) {
724: case PTRACE_RD_TXT:
725: if (XMODE_286) {
726: pts.pt_rval = getuwd(NBPS+pts.pt_addr);
727: break;
728: }
729: /* Fall through for 386 mode processes. */
730: case PTRACE_RD_DAT:
731: pts.pt_rval = getuwd(pts.pt_addr);
732: break;
733: case PTRACE_RD_USR:
734: /* See ptrace.h for valid offsets. */
735: off = (unsigned)pts.pt_addr;
736: if (off & 3)
737: u.u_error = EINVAL;
738: else if (off < PTRACE_FP_CW) {
739: /* Reading CPU general register state */
740: if (off == PTRACE_SIG)
741: pts.pt_rval = u.u_signo;
742: else
743: pts.pt_rval = u.u_regl[off>>2];
744: } else if (off < PTRACE_DR0) {
745: /*
746: * Reading NDP state.
747: * If NDP state not already saved, save it.
748: * Fetch desired info.
749: * Restore NDP state in case we will resume.
750: */
751: if (rdNdpUser()) {
752: /* if using coprocessor */
753: if (!rdNdpSaved()) {
754: ndpSave(&u.u_ndpCon);
755: wrNdpSaved(1);
756: }
757: pts.pt_rval = ((int *)&u.u_ndpCon)[(off - PTRACE_FP_CW)>>2];
758: ndpRestore(&u.u_ndpCon);
759: wrNdpSaved(0);
760: } else if (fstp) {
761: pts.pt_rval = getuwd(((int *)fstp) + ((off - PTRACE_FP_CW)>>2));
762: /* if emulating */
763: } else /* no ndp state to display */
764: pts.pt_rval = 0;
765: } else
766: u.u_error = EINVAL;
767: break;
768: case PTRACE_WR_TXT:
769: if (XMODE_286) {
770: putuwd(NBPS+pts.pt_addr, pts.pt_data);
771: break;
772: }
773: /* Fall through for 386 mode processes. */
774: case PTRACE_WR_DAT:
775: putuwd(pts.pt_addr, pts.pt_data);
776: break;
777: case PTRACE_WR_USR:
778: /* See ptrace.h for valid offsets. */
779: off = (unsigned)pts.pt_addr;
780:
781: if (off & 3)
782: u.u_error = EINVAL;
783: else if (off < PTRACE_FP_CW) {
784: /* Writing CPU general register state */
785: if (off == PTRACE_SIG)
786: u.u_error = EINVAL;
787: else
788: u.u_regl[off>>2] = pts.pt_data;
789: } else if (off < PTRACE_DR0) {
790: if (rdNdpUser()) {
791: /*
792: * Writing NDP state.
793: * If NDP state not already saved, save it.
794: * Store desired info.
795: * Restore NDP state in case we will resume.
796: */
797: if (!rdNdpSaved()) {
798: ndpSave(&u.u_ndpCon);
799: wrNdpSaved(1);
800: }
801: ((int *)&u.u_ndpCon)[(off - PTRACE_FP_CW)>>2] = pts.pt_data;
802: ndpRestore(&u.u_ndpCon);
803: wrNdpSaved(0);
804: } else if (fstp && ndpKfrstor) {
805: putuwd(((int *)fstp) + ((off - PTRACE_FP_CW)>>2), pts.pt_data);
806: doEmUnpack = 1;
807: }
808: } else
809: u.u_error = EINVAL;
810: break;
811: case PTRACE_RESUME:
812: u.u_regl[EFL] &= ~MFTTB;
813: goto sig;
814: case PTRACE_TERM:
815: sign = SIGKILL;
816: break;
817: case PTRACE_SSTEP:
818: u.u_regl[EFL] |= MFTTB;
819: sig:
820: if (pts.pt_data<0 || pts.pt_data>NSIG) {
821: u.u_error = EINVAL;
822: break;
823: }
824: sign = pts.pt_data;
825: if (pts.pt_addr != SIG_IGN) {
826: u.u_regl[EIP] = (int)pts.pt_addr;
827: }
828: break;
829: default:
830: u.u_error = EINVAL;
831: }
832: if ((pts.pt_errs=u.u_error) == EFAULT)
833: pts.pt_errs = EINVAL;
834: pts.pt_busy = 0;
835: wakeup((char *)&pts.pt_busy);
836: }
837: if (doEmUnpack)
838: (*ndpKfrstor)(fstp, &u.u_ndpCon);
839: return (sign);
840: }
841:
842: /*
843: * If using floating point emulator, make room on user stack and save
844: * floating point context there. Code elsewhere takes care of floating
845: * point context if there is a coprocessor.
846: *
847: * Return the virtual address in user space of the context area, or
848: * return NULL if not using FP emulation.
849: */
850: static struct _fpstate *
851: empack()
852: {
853: int uesp;
854: int sphi, splo;
855: SEG * segp;
856: cseg_t * pp;
857: struct _fpstate * ret = NULL;
858: extern void (*ndpKfsave)();
859: unsigned long sw_old;
860:
861: /* If not emulating, do nothing */
862: if (rdNdpUser() || !rdEmTrapped() || !ndpKfsave)
863: return NULL;
864:
865: /*
866: * Will copy at least u_sigreturn, _fpstackframe, and ndpFlags.
867: * If using ndp, need room for an _fpstate.
868: * If emulating, need room for an _fpemstate.
869: */
870: uesp = u.u_regl[UESP] - sizeof(struct _fpstate);
871:
872: /* Add to user stack if necessary. */
873: segp = u.u_segl[SISTACK].sr_segp;
874: sphi = (XMODE_286) ? ISP_286 : ISP_386;
875: splo = sphi - segp->s_size;
876:
877: if (splo > uesp) {
878: pp = c_extend(segp->s_vmem, btoc(segp->s_size));
879: if (pp==0) {
880: printf("Empack failed. cmd=%s c_extend(%x,%x)=0 ",
881: u.u_comm, segp->s_vmem, btoc(segp->s_size));
882: return NULL;
883: }
884:
885: segp->s_vmem = pp;
886: segp->s_size += NBPC;
887: if (sproto(0)==0) {
888: printf("Empack failed. cmd=%s sproto(0)=0 ",
889: u.u_comm);
890: return NULL;
891: }
892:
893: segload();
894: }
895:
896: ret = (struct _fpstate *)uesp;
897: (*ndpKfsave)(&u.u_ndpCon, uesp);
898: sw_old = getuwd(&ret->sw);
899: putuwd(&ret->status, sw_old);
900: putuwd(&ret->sw, sw_old & 0x7f00);
901:
902: return ret;
903: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.