|
|
1.1 root 1: /*
2:
3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved.
4:
5: */
6:
7:
8:
9: /*
10:
11: * GEMDOS emulation routines: these are for the GEMDOS system calls
12:
13: * concerning allocating/freeing memory, including Pexec() (since
14:
15: * this allocates memory) and Pterm() (since this, implicitly, frees
16:
17: * it).
18:
19: */
20:
21:
22:
23: #include "mint.h"
24:
25:
26:
27: int procdate, proctime; /* set when any processes are created/destroyed */
28:
29:
30:
31: static long do_vfork P_((int));
32:
33:
34:
35: /*
36:
37: * new call for TT TOS, for the user to inform DOS of alternate memory
38:
39: * FIXME: we really shouldn't trust the user so completely
40:
41: */
42:
43:
44:
1.1.1.2 ! root 45: long ARGS_ON_STACK
1.1 root 46:
47: m_addalt(start, size)
48:
49: long start, size;
50:
51: {
52:
53: if (!add_region(alt, start, size, M_ALT))
54:
55: return EINTRN;
56:
57: else
58:
59: return 0;
60:
61: }
62:
63:
64:
65: /*
66:
67: * internal routine for doing Malloc on a particular memory map
68:
69: */
70:
71:
72:
73: long
74:
75: _do_malloc(map, size, mode)
76:
77: MMAP map;
78:
79: long size;
80:
81: int mode;
82:
83: {
84:
85: virtaddr v;
86:
87: MEMREGION *m;
88:
89: long maxsize, mleft;
90:
91:
92:
93: if (size == -1L) {
94:
95: maxsize = max_rsize(map);
96:
97: if (curproc->maxmem) {
98:
99: mleft = curproc->maxmem - memused(curproc);
100:
101: if (maxsize > mleft)
102:
103: maxsize = mleft;
104:
105: if (maxsize < 0)
106:
107: maxsize = 0;
108:
109: }
110:
111: /* make sure to round down */
112:
113: return maxsize & ~MASKBITS;
114:
115: }
116:
117:
118:
119: /* special case: Malloc(0) should always return 0 */
120:
121: if (size == 0)
122:
123: return 0;
124:
125:
126:
127: if (curproc->maxmem) { /* memory limit? */
128:
129: if (size > curproc->maxmem - memused(curproc)) {
130:
1.1.1.2 ! root 131: DEBUG(("malloc: memory request would exceed limit"));
1.1 root 132:
133: return 0;
134:
135: }
136:
137: }
138:
139:
140:
141: m = get_region(map, size);
142:
143: if (!m) {
144:
1.1.1.2 ! root 145: DEBUG(("malloc: out of memory"));
1.1 root 146:
147: return 0;
148:
149: }
150:
151: v = attach_region(curproc, m);
152:
153: if (!v) {
154:
155: m->links = 0;
156:
157: free_region(m);
158:
159: return 0;
160:
161: }
162:
163: /* NOTE: get_region returns a region with link count 1; since attach_region
164:
165: * increments the link count, we have to remember to decrement the count
166:
167: * to correct for this.
168:
169: */
170:
171: m->links--;
172:
173: if ((mode & F_KEEP)) { /* request for permanent memory */
174:
175: m->mflags |= M_KEEP;
176:
177: }
178:
179: return (long)v;
180:
181: }
182:
183:
184:
1.1.1.2 ! root 185: long ARGS_ON_STACK
1.1 root 186:
187: m_xalloc(size, mode)
188:
189: long size;
190:
191: int mode;
192:
193: {
194:
195: long r, r1;
196:
197:
198:
1.1.1.2 ! root 199: TRACE(("Mxalloc(%ld,%x)",size,mode));
1.1 root 200:
201: if ( (mode & 8) ) {
202:
1.1.1.2 ! root 203: DEBUG(("Unsupported Mxalloc mode: %x", mode));
1.1 root 204:
205: return 0; /* future expansion */
206:
207: }
208:
209: if ( (mode&3) == 0)
210:
211: return _do_malloc(core, size, mode);
212:
213: else if ( (mode&3) == 1)
214:
215: return _do_malloc(alt, size, mode);
216:
217: else if (size == -1) {
218:
219: /* modes 2 and 3 are the same for for size -1 */
220:
221: r = _do_malloc(core, -1L, mode);
222:
223: r1 = _do_malloc(alt, -1L, mode);
224:
225: if (r > r1) return r;
226:
227: else return r1;
228:
229: }
230:
231: else if ( (mode&3) == 2) {
232:
233: r = _do_malloc(core, size, mode);
234:
235: if (r == 0) return _do_malloc(alt, size, mode);
236:
237: else return r;
238:
239: }
240:
241: else /* if ( (mode&3) == 3) */ {
242:
243: r = _do_malloc(alt, size, mode);
244:
245: if (r == 0) return _do_malloc(core, size, mode);
246:
247: else return r;
248:
249: }
250:
251: }
252:
253:
254:
1.1.1.2 ! root 255: long ARGS_ON_STACK
1.1 root 256:
257: m_alloc(size)
258:
259: long size;
260:
261: {
262:
263: long r;
264:
265:
266:
1.1.1.2 ! root 267: TRACE(("Malloc(%lx)", size));
1.1 root 268:
269: if (curproc->memflags & F_ALTALLOC)
270:
271: r = m_xalloc(size, 3);
272:
273: else
274:
275: r = m_xalloc(size, 0);
276:
1.1.1.2 ! root 277: TRACE(("Malloc: returning %lx", r));
1.1 root 278:
279: return r;
280:
281: }
282:
283:
284:
1.1.1.2 ! root 285: long ARGS_ON_STACK
1.1 root 286:
287: m_free(block)
288:
289: virtaddr block;
290:
291: {
292:
293: MEMREGION *m;
294:
295: int i;
296:
297:
298:
1.1.1.2 ! root 299: TRACE(("Mfree(%lx)", block));
1.1 root 300:
301: if (!block) {
302:
1.1.1.2 ! root 303: DEBUG(("Mfree: null pointer"));
1.1 root 304:
305: return EIMBA;
306:
307: }
308:
309:
310:
311: /* search backwards so that most recently allocated incarnations of
312:
313: shared memory blocks are freed first (this doesn't matter very often)
314:
315: */
316:
317:
318:
319: for (i = curproc->num_reg - 1; i >= 0; i--) {
320:
321: if (curproc->addr[i] == block) {
322:
323: m = curproc->mem[i];
324:
325: assert(m != NULL);
326:
327: assert(m->loc == (long)block);
328:
329: curproc->mem[i] = 0;
330:
331: curproc->addr[i] = 0;
332:
333: m->links--;
334:
335: if (m->links == 0) {
336:
337: free_region(m);
338:
339: }
340:
341: return 0;
342:
343: }
344:
345: }
346:
347:
348:
349: /* hmmm... if we didn't find the region, perhaps it's a global
350:
351: * one (with the M_KEEP flag set) belonging to a process that
352:
353: * terminated
354:
355: */
356:
357: for (i = rootproc->num_reg - 1; i >= 0; i--) {
358:
359: if (rootproc->addr[i] == block) {
360:
361: m = rootproc->mem[i];
362:
363: assert(m != NULL);
364:
365: assert(m->loc == (long)block);
366:
367: if (!(m->mflags & M_KEEP))
368:
369: continue;
370:
371: rootproc->mem[i] = 0;
372:
373: rootproc->addr[i] = 0;
374:
375: m->links--;
376:
377: if (m->links == 0) {
378:
379: free_region(m);
380:
381: }
382:
383: return 0;
384:
385: }
386:
387: }
388:
389:
390:
391:
392:
1.1.1.2 ! root 393: DEBUG(("Mfree: bad address %lx", block));
1.1 root 394:
395: return EIMBA;
396:
397: }
398:
399:
400:
1.1.1.2 ! root 401: long ARGS_ON_STACK
1.1 root 402:
403: m_shrink(dummy, block, size)
404:
405: int dummy;
406:
407: virtaddr block;
408:
409: long size;
410:
411: {
412:
413: MEMREGION *m;
414:
415: int i;
416:
417:
418:
1.1.1.2 ! root 419: UNUSED(dummy);
! 420:
! 421: TRACE(("Mshrink: %lx to %ld", block, size));
1.1 root 422:
423: if (!block) {
424:
1.1.1.2 ! root 425: DEBUG(("Mshrink: null pointer"));
1.1 root 426:
427: return EIMBA;
428:
429: }
430:
431:
432:
433: for (i = 0; i < curproc->num_reg; i++) {
434:
435: if (curproc->addr[i] == block) {
436:
437: m = curproc->mem[i];
438:
439: assert(m != NULL);
440:
441: assert(m->loc == (long)block);
442:
443: return shrink_region(m, size);
444:
445: }
446:
447: }
448:
1.1.1.2 ! root 449: DEBUG(("Mshrink: bad address (%lx)", block));
1.1 root 450:
451: return EIMBA;
452:
453: }
454:
455:
456:
1.1.1.2 ! root 457: long ARGS_ON_STACK
1.1 root 458:
459: p_exec(mode, ptr1, ptr2, ptr3)
460:
461: int mode;
462:
463: void *ptr1, *ptr2, *ptr3;
464:
465: {
466:
1.1.1.2 ! root 467: MEMREGION *base,
! 468:
! 469: *env = 0; /* assignment suppresses spurious warning */
1.1 root 470:
1.1.1.2 ! root 471: MEMREGION *text = 0; /* for shared text regions */
! 472:
! 473: PROC *p;
1.1 root 474:
475: long r, flags = 0;
476:
477: int i;
478:
479: char mkbase = 0, mkload = 0, mkgo = 0, mkwait = 0, mkfree = 0;
480:
481: char overlay = 0;
482:
483: char thread = 0;
484:
1.1.1.2 ! root 485: char ptrace;
! 486:
1.1 root 487: char mkname = 0, *newname, *lastslash;
488:
489: char localname[PNAMSIZ+1];
490:
491: XATTR xattr;
492:
493:
494:
1.1.1.2 ! root 495: /* the high bit of mode controls process tracing */
! 496:
! 497: switch(mode & 0x7fff) {
1.1 root 498:
499: case 0:
500:
501: mkwait = 1; /* fall through */
502:
503: case 100:
504:
505: mkload = mkgo = mkfree = 1;
506:
507: mkname = 1;
508:
1.1.1.2 ! root 509: TRACE(("Pexec(%d,%s,\"%s\")", mode, ptr1, ptr2));
1.1 root 510:
511: break;
512:
513: case 200: /* overlay current process */
514:
515: mkload = mkgo = 1;
516:
517: overlay = mkname = 1;
518:
1.1.1.2 ! root 519: TRACE(("Pexec(%d,%s,\"%s\")", mode, ptr1, ptr2));
1.1 root 520:
521: break;
522:
523: case 3:
524:
525: mkload = 1;
526:
1.1.1.2 ! root 527: TRACE(("Pexec(%d,%s,\"%s\")", mode, ptr1, ptr2));
1.1 root 528:
529: break;
530:
531: case 6:
532:
533: mkfree = 1;
534:
535: /* fall through */
536:
537: case 4:
538:
539: mkwait = mkgo = 1;
540:
1.1.1.2 ! root 541: TRACE(("Pexec(%d,%lx)", mode, ptr2));
1.1 root 542:
543: break;
544:
545: case 106:
546:
547: mkfree = 1; /* fall through */
548:
549: case 104:
550:
551: thread = (mode == 104);
552:
553: mkgo = 1;
554:
555: mkname = (ptr1 != 0);
556:
1.1.1.2 ! root 557: TRACE(("Pexec(%d,%s,%lx)", mode, ptr1, ptr2));
! 558:
! 559: break;
! 560:
! 561: case 206:
! 562:
! 563: #if 0
! 564:
! 565: /* mkfree has no effect when overlay is set, since
! 566:
! 567: * in this case the "parent" and "child" are the same
! 568:
! 569: * process; since the "child" will run in memory that the
! 570:
! 571: * "parent" allocated, we don't want that memory freed!
! 572:
! 573: */
! 574:
! 575: mkfree = 1;
! 576:
! 577: #endif
! 578:
! 579: /* fall through */
! 580:
! 581: case 204:
! 582:
! 583: mkgo = overlay = 1;
! 584:
! 585: mkname = (ptr1 != 0);
! 586:
! 587: TRACE(("Pexec(%d,%s,%lx)", mode, ptr1, ptr2));
1.1 root 588:
589: break;
590:
591: case 7:
592:
593: flags = (long)ptr1; /* set program flags */
594:
595: /* and fall through */
596:
597: case 5:
598:
599: mkbase = 1;
600:
1.1.1.2 ! root 601: TRACE(("Pexec(%d,%lx,\"%s\")", mode, ptr1, ptr2));
1.1 root 602:
603: break;
604:
605: default:
606:
1.1.1.2 ! root 607: DEBUG(("Pexec: bad mode %d", mode));
1.1 root 608:
609: return EINVFN;
610:
611: }
612:
613:
614:
1.1.1.2 ! root 615: ptrace = (!mkwait && (mode & 0x8000));
! 616:
! 617:
! 618:
1.1 root 619: /* in most cases, we'll want a process struct to exist,
620:
621: * so make sure one is around. Note that we must be
622:
623: * careful to free it later!
624:
625: */
626:
627:
628:
629: p = 0;
630:
631: if (!overlay) {
632:
633: p = new_proc();
634:
635: if (!p) {
636:
1.1.1.2 ! root 637: DEBUG(("Pexec: couldn't get a PROC struct"));
1.1 root 638:
639: return ENSMEM;
640:
641: }
642:
643: }
644:
645:
646:
647:
648:
649: if (mkload || mkbase) {
650:
651: env = create_env((char *)ptr3);
652:
653: if (!env) {
654:
1.1.1.2 ! root 655: DEBUG(("Pexec: unable to create environment"));
1.1 root 656:
657: if (p) dispose_proc(p);
658:
659: return ENSMEM;
660:
661: }
662:
663: }
664:
665:
666:
667: if (mkbase) {
668:
669: base = create_base((char *)ptr2, env, flags, 0L);
670:
671: if (!base) {
672:
1.1.1.2 ! root 673: DEBUG(("Pexec: unable to create basepage"));
1.1 root 674:
675: detach_region(curproc, env);
676:
677: if (p) dispose_proc(p);
678:
679: return ENSMEM;
680:
681: }
682:
1.1.1.2 ! root 683: TRACE(("Pexec: basepage region(%lx) is %ld bytes at %lx", base, base->len, base->loc));
! 684:
1.1 root 685: }
686:
687: else if (mkload) {
688:
1.1.1.2 ! root 689: base = load_region((char *)ptr1, env, (char *)ptr2,
! 690:
! 691: &xattr, &text);
1.1 root 692:
693: if (!base) {
694:
1.1.1.2 ! root 695: DEBUG(("Pexec: load_region failed"));
1.1 root 696:
697: detach_region(curproc, env);
698:
699: if (p) dispose_proc(p);
700:
701: return mint_errno;
702:
703: }
704:
1.1.1.2 ! root 705: TRACE(("Pexec: basepage region(%lx) is %ld bytes at %lx", base, base->len, base->loc));
! 706:
1.1 root 707: }
708:
1.1.1.2 ! root 709: else { /* mode == 4,6,104,106,204, or 206 -- just go */
1.1 root 710:
711: base = addr2mem((virtaddr)ptr2);
712:
713: if (base)
714:
715: env = addr2mem(*(void **)(base->loc + 0x2c));
716:
717: else
718:
719: env = 0;
720:
721: if (!env) {
722:
723: if (p) dispose_proc(p);
724:
725: return EIMBA;
726:
727: }
728:
729: }
730:
731:
732:
733: /* make a local copy of the name, in case we are overlaying the current
734:
735: * process
736:
737: */
738:
739: if (mkname) {
740:
741: lastslash = 0;
742:
743: newname = ptr1;
744:
745: while (*newname) {
746:
747: if (*newname == '\\' || *newname == '/')
748:
749: lastslash = newname;
750:
751: ++newname;
752:
753: }
754:
755: if (!lastslash)
756:
757: lastslash = ptr1;
758:
759: else
760:
761: lastslash++;
762:
763:
764:
765: i = 0; newname = localname;
766:
767: while (i++ < PNAMSIZ) {
768:
769: if (*lastslash == '.' || *lastslash == 0) {
770:
771: *newname = 0; break;
772:
773: }
774:
775: else
776:
777: *newname++ = *lastslash++;
778:
779: }
780:
781: *newname = 0;
782:
783: }
784:
785:
786:
787: if (p) {
788:
789: /* free the PROC struct so fork_proc will succeed */
790:
791: dispose_proc(p);
792:
793: p = 0;
794:
795: }
796:
797:
798:
799: if (mkgo) {
800:
801: BASEPAGE *b;
802:
803:
804:
805: if (overlay) {
806:
807: p = curproc;
808:
809: /* make sure that exec_region doesn't free the base and env */
810:
811: base->links++;
812:
813: env->links++;
814:
1.1.1.2 ! root 815: if (text) text->links++;
! 816:
1.1 root 817: }
818:
819: else {
820:
821: p = fork_proc();
822:
823: }
824:
825: if (!p) {
826:
827: if (mkbase) {
828:
829: detach_region(curproc, base);
830:
831: detach_region(curproc, env);
832:
1.1.1.2 ! root 833: if (text) detach_region(curproc, text);
! 834:
1.1 root 835: }
836:
837: return mint_errno;
838:
839: }
840:
1.1.1.2 ! root 841: if (ptrace)
! 842:
! 843: p->ptracer = pid2proc(p->ppid);
! 844:
! 845:
! 846:
! 847: /* Even though the file system won't allow unauthorized access
1.1 root 848:
1.1.1.2 ! root 849: * to setuid/setgid programs, it's better to err on the side of
1.1 root 850:
1.1.1.2 ! root 851: * caution and forbid them to be traced (since the parent can arrange
! 852:
! 853: * to share the child's address space, not all accesses need to
! 854:
! 855: * go through the file system!)
! 856:
! 857: */
! 858:
! 859: if (mkload && mkgo && !p->ptracer) { /* setuid/setgid is OK */
1.1 root 860:
861: if (xattr.mode & S_ISUID)
862:
863: p->euid = xattr.uid;
864:
865: if (xattr.mode & S_ISGID)
866:
867: p->egid = xattr.gid;
868:
869: }
870:
871: (void)exec_region(p, base, thread);
872:
873: attach_region(p, env);
874:
875: attach_region(p, base);
876:
1.1.1.2 ! root 877: if (text) attach_region(p, text);
! 878:
1.1 root 879:
880:
881: /* tell the child who the parent was */
882:
883: b = (BASEPAGE *)base->loc;
884:
885: if (!overlay)
886:
887: b->p_parent = (BASEPAGE *)curproc->base;
888:
889:
890:
891: if (mkname) {
892:
893: /* interesting coincidence -- if a process needs a name, it usually
894:
895: * needs to have its domain reset to DOM_TOS. Doing it this way
896:
897: * (instead of doing it in exec_region) means that Pexec(4,...)
898:
899: * can be used to create new threads of execution which retain
900:
901: * the same domain.
902:
903: */
904:
905: if (!thread)
906:
907: p->domain = DOM_TOS;
908:
909:
910:
911: /* put in the new process name we saved above */
912:
913: strcpy(p->name, localname);
914:
915: }
916:
917:
918:
1.1.1.2 ! root 919: /* turn on tracing for the new process */
! 920:
! 921: if (p->ptracer)
! 922:
! 923: p->ctxt[CURRENT].ptrace = 1;
! 924:
! 925:
! 926:
1.1 root 927: /* set the time/date stamp of u:\proc */
928:
929: proctime = timestamp;
930:
931: procdate = datestamp;
932:
933:
934:
935: if (overlay) {
936:
937: /* correct for temporary increase in links (see above) */
938:
939: base->links--;
940:
941: env->links--;
942:
1.1.1.2 ! root 943: if (text) text->links--;
! 944:
1.1 root 945: /* let our parent run, if it Vfork'd() */
946:
947: if ( (p = pid2proc(curproc->ppid)) != 0 ) {
948:
949: if (p->wait_q == WAIT_Q &&
950:
951: p->wait_cond == (long)curproc) {
952:
953: rm_q(WAIT_Q, p);
954:
955: add_q(READY_Q, p);
956:
957: }
958:
959: }
960:
961:
962:
963: /* OK, let's run our new code */
964:
965: /* we guarantee ourselves at least 2 timeslices to do an Mshrink */
966:
967: assert(curproc->magic == CTXT_MAGIC);
968:
969: fresh_slices(2);
970:
971: leave_kernel();
972:
973: restore_context(&(curproc->ctxt[CURRENT]));
974:
975: }
976:
977: else {
978:
979: /* we want this process to run ASAP */
980:
981: /* so we temporarily give it high priority and put it first on the
982:
983: * run queue
984:
985: */
986:
987: run_next(p, 2);
988:
989: }
990:
991: }
992:
993:
994:
995: if (mkfree) {
996:
997: detach_region(curproc, base);
998:
999: detach_region(curproc, env);
1000:
1.1.1.2 ! root 1001: if (text) detach_region(curproc, text);
! 1002:
1.1 root 1003: }
1004:
1005:
1006:
1007: if (mkwait) {
1008:
1009: long oldsigint, oldsigquit;
1010:
1011:
1012:
1013: oldsigint = curproc->sighandle[SIGINT];
1014:
1015: oldsigquit = curproc->sighandle[SIGQUIT];
1016:
1017: curproc->sighandle[SIGINT] =
1018:
1019: curproc->sighandle[SIGQUIT] = SIG_IGN;
1020:
1021:
1022:
1023: i = p->pid;
1024:
1025: for(;;) {
1026:
1027: r = p_wait3(0, (long *)0);
1028:
1029: if (r < 0) {
1030:
1031: ALERT("p_exec: wait error");
1032:
1033: return EINTRN;
1034:
1035: }
1036:
1.1.1.2 ! root 1037: if ( i == ((r&0xffff0000L) >> 16) ) {
1.1 root 1038:
1.1.1.2 ! root 1039: TRACE(("leaving Pexec with child return code"));
1.1 root 1040:
1.1.1.2 ! root 1041: r = r & 0x0000ffffL;
1.1 root 1042:
1043: break;
1044:
1045: }
1046:
1047: if (curproc->pid)
1048:
1.1.1.2 ! root 1049: DEBUG(("Pexec: wrong child found"));
1.1 root 1050:
1051: }
1052:
1053: curproc->sighandle[SIGINT] = oldsigint;
1054:
1055: curproc->sighandle[SIGQUIT] = oldsigquit;
1056:
1057: return r;
1058:
1059: }
1060:
1061: else if (mkgo) {
1062:
1063: yield(); /* let the new process run */
1064:
1065: return p->pid;
1066:
1067: } else {
1068:
1.1.1.2 ! root 1069: TRACE(("leaving Pexec with basepage address %lx", base->loc));
1.1 root 1070:
1071: return base->loc;
1072:
1073: }
1074:
1075: }
1076:
1077:
1078:
1079: /*
1080:
1081: * terminate a process, with return code "code". If que == ZOMBIE_Q, free
1082:
1083: * all resources attached to the child; if que == TSR_Q, free everything
1084:
1.1.1.2 ! root 1085: * but memory.
! 1086:
! 1087: * NOTE: terminate() should be called only when the process is to be
! 1088:
! 1089: * "terminated with extreme prejuidice". Most times, p_term or p_termres
! 1090:
! 1091: * are the functions to use, since they allow the user to do some cleaning
! 1092:
! 1093: * up, etc.
1.1 root 1094:
1095: */
1096:
1097:
1098:
1099: long
1100:
1101: terminate(code, que)
1102:
1103: int code, que;
1104:
1105: {
1106:
1107: extern PROC *dlockproc[]; /* in dosdir.c */
1108:
1109: PROC *p;
1110:
1111: FILEPTR *fp;
1112:
1113: MEMREGION *m;
1114:
1115: int i, wakemint = 0;
1116:
1117: extern short bconbsiz; /* in bios.c */
1118:
1119:
1120:
1121: if (bconbsiz)
1122:
1123: (void) bflush();
1124:
1125:
1126:
1127: assert(que == ZOMBIE_Q || que == TSR_Q);
1128:
1129:
1130:
1131: if (curproc->pid == 0) {
1132:
1133: FATAL("attempt to terminate MiNT");
1134:
1135: }
1136:
1137:
1138:
1139: /* cancel all pending timeouts for this process */
1140:
1141: cancelalltimeouts();
1142:
1143: /* cancel alarm clock */
1144:
1145: curproc->alarmtim = 0;
1146:
1147:
1148:
1149: /* release any drives locked by Dlock */
1150:
1151: for(i = 0; i < NUM_DRIVES; i++) {
1152:
1153: if (dlockproc[i] == curproc) {
1154:
1155: dlockproc[i] = 0;
1156:
1157: changedrv(i);
1158:
1159: }
1160:
1161: }
1162:
1163:
1164:
1165: /* release the controlling terminal, if we're a process group leader */
1166:
1167: fp = curproc->handle[-1];
1168:
1169: if (fp && is_terminal(fp) && curproc->pgrp == curproc->pid) {
1170:
1171: struct tty *tty = (struct tty *)fp->devinfo;
1172:
1173: if (curproc->pgrp == tty->pgrp)
1174:
1175: tty->pgrp = 0;
1176:
1177: }
1178:
1179:
1180:
1181: /* close all files */
1182:
1183: for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
1184:
1.1.1.2 ! root 1185: if ((fp = curproc->handle[i]) != 0)
1.1 root 1186:
1187: do_close(fp);
1188:
1189: curproc->handle[i] = 0;
1190:
1191: }
1192:
1193:
1194:
1195: /* close any unresolved Fsfirst/Fsnext directory searches */
1196:
1197: for (i = 0; i < NUM_SEARCH; i++) {
1198:
1199: if (curproc->srchdta[i]) {
1200:
1201: DIR *dirh = &curproc->srchdir[i];
1202:
1203: (*dirh->fc.fs->closedir)(dirh);
1204:
1205: }
1206:
1207: }
1208:
1209:
1210:
1211: /* release all semaphores owned by this process */
1212:
1213: free_semaphores(curproc->pid);
1214:
1215:
1216:
1217: /* free all memory */
1218:
1219: if (que == ZOMBIE_Q) {
1220:
1221: for (i = curproc->num_reg - 1; i >=0; i--) {
1222:
1223: m = curproc->mem[i];
1224:
1225: curproc->mem[i] = 0; curproc->addr[i] = 0;
1226:
1227: if (m) {
1228:
1229: /* don't free specially allocated memory */
1230:
1231: if (m->mflags & M_KEEP) {
1232:
1233: if (curproc != rootproc)
1234:
1235: attach_region(rootproc, m);
1236:
1237: }
1238:
1239: m->links--;
1240:
1241: if (m->links == 0) {
1242:
1243: free_region(m);
1244:
1245: }
1246:
1247: }
1248:
1249: }
1250:
1251: kfree(curproc->mem); kfree(curproc->addr);
1252:
1253: curproc->mem = 0;
1254:
1255: curproc->addr = 0;
1256:
1257: curproc->num_reg = 0;
1258:
1259: }
1260:
1261: /* else
1262:
1263: make TSR process non-swappable */
1264:
1265:
1266:
1267: /*
1268:
1269: * make sure that any open files that refer to this process are
1270:
1271: * closed
1272:
1273: */
1274:
1275: changedrv(PROC_BASE_DEV | curproc->pid);
1276:
1277:
1278:
1279: /* find our parent (if parent not found, then use process 0 as parent
1280:
1281: * since that process is constantly in a wait loop)
1282:
1283: */
1284:
1285:
1286:
1287: p = pid2proc(curproc->ppid);
1288:
1289: if (!p) {
1290:
1.1.1.2 ! root 1291: TRACE(("terminate: parent not found"));
1.1 root 1292:
1293: p = pid2proc(0);
1294:
1295: }
1296:
1297:
1298:
1299: /* NOTE: normally just post_sig is sufficient for sending a signal; but
1300:
1301: * in this particular case, we have to worry about processes that are
1302:
1303: * blocking all signals because they Vfork'd and are waiting for us to
1304:
1305: * finish (which is indicated by a wait_cond matching our PROC
1306:
1307: * structure), and also processes that are ignoring SIGCHLD but are
1308:
1309: * waiting for us.
1310:
1311: */
1312:
1313: if (p->wait_q == WAIT_Q &&
1314:
1.1.1.2 ! root 1315: (p->wait_cond == (long)curproc || p->wait_cond == (long)p_waitpid) ) {
1.1 root 1316:
1.1.1.2 ! root 1317: TRACE(("terminate: waking up parent"));
1.1 root 1318:
1319: rm_q(WAIT_Q, p);
1320:
1321: add_q(READY_Q, p);
1322:
1323: }
1324:
1.1.1.2 ! root 1325: if (curproc->ptracer && curproc->ptracer != p) {
! 1326:
! 1327: /* BUG: should we ensure curproc->ptracer is awake ? */
! 1328:
! 1329: post_sig(curproc->ptracer, SIGCHLD); /* tell tracing process */
! 1330:
! 1331: }
! 1332:
1.1 root 1333: post_sig(p, SIGCHLD); /* inform of process termination */
1334:
1335:
1336:
1.1.1.2 ! root 1337: /* find our children, and orphan them
! 1338:
! 1339: * also, check for processes we were tracing, and
! 1340:
! 1341: * cancel the trace
! 1342:
! 1343: */
1.1 root 1344:
1345: i = curproc->pid;
1346:
1347: for (p = proclist; p; p = p->gl_next) {
1348:
1349: if (p->ppid == i) {
1350:
1351: p->ppid = 0; /* have the system adopt it */
1352:
1353: if (p->wait_q == ZOMBIE_Q)
1354:
1355: wakemint = 1; /* we need to wake proc. 0 */
1356:
1357: }
1358:
1.1.1.2 ! root 1359: if (p->ptracer == curproc) {
! 1360:
! 1361: p->ptracer = 0;
! 1362:
! 1363: /*
! 1364:
! 1365: * `FEATURE': we terminate traced processes when the tracer terminates.
! 1366:
! 1367: * It might plausibly be argued that it would be better to let them
! 1368:
! 1369: * continue, to let some (new) tracer take them over. On the other hand,
! 1370:
! 1371: * if the tracer terminated normally, it should have used Fcntl(PTRACESFLAGS)
! 1372:
! 1373: * to reset the trace nicely, so something must be wrong for us to have
! 1374:
! 1375: * reached here.
! 1376:
! 1377: */
! 1378:
! 1379: post_sig(p, SIGTERM); /* arrange for termination */
! 1380:
! 1381: }
! 1382:
1.1 root 1383: }
1384:
1385:
1386:
1387: if (wakemint) {
1388:
1389: p = rootproc; /* pid 0 */
1390:
1391: if (p->wait_q == WAIT_Q) {
1392:
1393: rm_q(WAIT_Q, p);
1394:
1395: add_q(READY_Q, p);
1396:
1397: }
1398:
1399: }
1400:
1401:
1402:
1403: /* this makes sure that our children are inherited by the system;
1404:
1405: * plus, it may help avoid problems if somehow a signal gets
1406:
1407: * through to us
1408:
1409: */
1410:
1411: for(i = 0; i < NSIG; i++)
1412:
1413: curproc->sighandle[i] = SIG_IGN;
1414:
1415:
1416:
1417: /* finally, reset the time/date stamp for u:\proc */
1418:
1419: proctime = timestamp;
1420:
1421: procdate = datestamp;
1422:
1423:
1424:
1.1.1.2 ! root 1425: sleep(que, (long)(unsigned)code);
1.1 root 1426:
1427:
1428:
1.1.1.2 ! root 1429: /* we shouldn't ever get here */
1.1 root 1430:
1.1.1.2 ! root 1431: FATAL("terminate: sleep woke up when it shouldn't have");
1.1 root 1432:
1.1.1.2 ! root 1433: return 0;
1.1 root 1434:
1435: }
1436:
1437:
1438:
1439: /*
1440:
1441: * TOS process termination entry points:
1442:
1.1.1.2 ! root 1443: * p_term terminates the process, freeing its memory
1.1 root 1444:
1445: * p_termres lets the process hang around resident in memory, after
1446:
1447: * shrinking its transient program area to "save" bytes
1448:
1449: */
1450:
1451:
1452:
1.1.1.2 ! root 1453: long ARGS_ON_STACK
1.1 root 1454:
1455: p_term(code)
1456:
1457: int code;
1458:
1459: {
1460:
1461: CONTEXT *syscall;
1462:
1463:
1464:
1.1.1.2 ! root 1465: TRACE(("Pterm(%d)", code));
1.1 root 1466:
1467: /* call the process termination vector */
1468:
1469: syscall = &curproc->ctxt[SYSCALL];
1470:
1471:
1472:
1473: if (syscall->term_vec != (long)rts) {
1474:
1.1.1.2 ! root 1475: TRACE(("term_vec: user has something to do"));
1.1 root 1476:
1477: /*
1478:
1479: * we handle the termination vector just like Supexec(), by
1480:
1481: * sending signal 0 to the process. See supexec() in xbios.c for details.
1482:
1.1.1.2 ! root 1483: * Note that we _always_ want to unwind the signal stack, and setting
1.1 root 1484:
1.1.1.2 ! root 1485: * bit 1 of curproc->sigmask tells handle_sig to do that -- see signal.c.
1.1 root 1486:
1487: */
1488:
1489: curproc->sigmask |= 1L;
1490:
1491: (void)supexec((Func)syscall->term_vec, 0L, 0L, 0L, 0L,
1492:
1493: (long)code);
1494:
1495: /*
1496:
1497: * if we arrive here, continue with the termination...
1498:
1499: */
1500:
1501: }
1502:
1503: return terminate(code, ZOMBIE_Q);
1504:
1505: }
1506:
1507:
1508:
1.1.1.2 ! root 1509: long ARGS_ON_STACK
1.1 root 1510:
1511: p_term0()
1512:
1513: {
1514:
1515: return p_term(0);
1516:
1517: }
1518:
1519:
1520:
1.1.1.2 ! root 1521: long ARGS_ON_STACK
1.1 root 1522:
1523: p_termres(save, code)
1524:
1525: long save;
1526:
1527: int code;
1528:
1529: {
1530:
1531: MEMREGION *m;
1532:
1533:
1534:
1.1.1.2 ! root 1535: TRACE(("Ptermres(%ld, %d)", save, code));
1.1 root 1536:
1537: m = curproc->mem[1]; /* should be the basepage (0 is env.) */
1538:
1539: if (m) {
1540:
1541: (void)shrink_region(m, save);
1542:
1543: }
1544:
1545: return terminate(code, TSR_Q);
1546:
1547: }
1548:
1549:
1550:
1551: /*
1552:
1553: * routine for waiting for children to die. Return has the pid of the
1554:
1555: * found child in the high word, and the child's exit code in
1556:
1557: * the low word. If no children exist, return "File Not Found".
1558:
1559: * If (nohang & 1) is nonzero, then return a 0 immediately if we have
1560:
1561: * no dead children but some living ones that we still have to wait
1562:
1563: * for. If (nohang & 2) is nonzero, then we return any stopped
1564:
1565: * children; otherwise, only children that have exited or are stopped
1566:
1567: * due to a trace trap are returned.
1568:
1569: * If "rusage" is non-zero and a child is found, put the child's
1570:
1571: * resource usage into it (currently only the user and system time are
1572:
1.1.1.2 ! root 1573: * sent back).
! 1574:
! 1575: * The pid argument specifies a set of child processes for which status
! 1576:
! 1577: * is requested:
! 1578:
! 1579: * If pid is equal to -1, status is requested for any child process.
! 1580:
! 1581: *
! 1582:
! 1583: * If pid is greater than zero, it specifies the process ID of a
! 1584:
! 1585: * single child process for which status is requested.
! 1586:
! 1587: *
! 1588:
! 1589: * If pid is equal to zero, status is requested for any child
! 1590:
! 1591: * process whose process group ID is equal to that of the calling
! 1592:
! 1593: * process.
! 1594:
! 1595: *
! 1596:
! 1597: * If pid is less than -1, status is requested for any child process
! 1598:
! 1599: * whose process group ID is equal to the absolute value of pid.
! 1600:
! 1601: *
! 1602:
! 1603: * Note this call is a real standard crosser... POSIX.1 doesn't have the
! 1604:
! 1605: * rusage stuff, BSD doesn't have the pid stuff; both are useful, so why
! 1606:
! 1607: * not have it all!
1.1 root 1608:
1609: */
1610:
1611:
1612:
1.1.1.2 ! root 1613: long ARGS_ON_STACK
1.1 root 1614:
1.1.1.2 ! root 1615: p_waitpid(pid, nohang, rusage)
! 1616:
! 1617: int pid;
1.1 root 1618:
1619: int nohang;
1620:
1621: long *rusage;
1622:
1623: {
1624:
1625: long r;
1626:
1627: PROC *p, *q;
1628:
1629: int ourpid;
1630:
1631: int found;
1632:
1633:
1634:
1.1.1.2 ! root 1635: TRACE(("Pwaitpid(%d, %d, %lx)", pid, nohang, rusage));
1.1 root 1636:
1637: ourpid = curproc->pid;
1638:
1639:
1640:
1641: /* if there are terminated children, clean up and return their info;
1642:
1643: * if there are children, but still running, wait for them;
1644:
1645: * if there are no children, return an error
1646:
1647: */
1648:
1649:
1650:
1651: do {
1652:
1653: /* look for any children */
1654:
1655: found = 0;
1656:
1657: for (p = proclist; p; p = p->gl_next) {
1658:
1.1.1.2 ! root 1659: if ((p->ppid == ourpid || p->ptracer == curproc) &&
! 1660:
! 1661: (pid == -1 ||
! 1662:
! 1663: (pid > 0 && pid == p->pid) ||
! 1664:
! 1665: (pid == 0 && p->pgrp == ourpid) ||
! 1666:
! 1667: (pid < -1 && p->pgrp == -pid))) {
1.1 root 1668:
1669: found++;
1670:
1671: if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q)
1672:
1673: break;
1674:
1675:
1676:
1677: /* p->wait_cond == 0 if a stopped process has already been waited for */
1678:
1679: if (p->wait_q == STOP_Q && p->wait_cond) {
1680:
1681: if ((nohang & 2) ||
1682:
1.1.1.2 ! root 1683: ((p->wait_cond&0x1f00) == (SIGTRAP<<8)))
1.1 root 1684:
1685: break;
1686:
1687: }
1688:
1689: }
1690:
1691: }
1692:
1693: if (!p) {
1694:
1695: if (found) {
1696:
1697: if (nohang & 1)
1698:
1699: return 0;
1700:
1701: if (curproc->pid)
1702:
1.1.1.2 ! root 1703: TRACE(("Pwaitpid: going to sleep"));
1.1 root 1704:
1.1.1.2 ! root 1705: sleep(WAIT_Q, (long)p_waitpid);
1.1 root 1706:
1707: }
1708:
1709: else {
1710:
1.1.1.2 ! root 1711: DEBUG(("Pwaitpid: no children found"));
1.1 root 1712:
1713: return EFILNF;
1714:
1715: }
1716:
1717: }
1718:
1719: } while (!p);
1720:
1721:
1722:
1723: /* OK, we've found our child */
1724:
1725: /* calculate the return code from the child's exit code and pid */
1726:
1727: r = (((unsigned long)p->pid) << 16) | (p->wait_cond & 0x0000ffff);
1728:
1729:
1730:
1731: /* check resource usage */
1732:
1733: if (rusage) {
1734:
1735: *rusage++ = p->usrtime;
1736:
1.1.1.2 ! root 1737: *rusage = p->systime;
1.1 root 1738:
1739: }
1740:
1741:
1742:
1.1.1.2 ! root 1743: /* avoid adding adopted trace processes usage to the foster parent */
! 1744:
! 1745: if (curproc->pid == p->ppid) {
1.1 root 1746:
1.1.1.2 ! root 1747: /* add child's resource usage to parent's */
1.1 root 1748:
1.1.1.2 ! root 1749: if (p->wait_q == TSR_Q || p->wait_q == ZOMBIE_Q) {
1.1 root 1750:
1.1.1.2 ! root 1751: curproc->chldstime += p->systime;
! 1752:
! 1753: curproc->chldutime += p->usrtime;
! 1754:
! 1755: }
1.1 root 1756:
1757: }
1758:
1759:
1760:
1.1.1.2 ! root 1761: /* if it was stopped, mark it as having been found and again return */
1.1 root 1762:
1.1.1.2 ! root 1763: if (p->wait_q == STOP_Q) {
1.1 root 1764:
1.1.1.2 ! root 1765: p->wait_cond = 0;
1.1 root 1766:
1767: return r;
1768:
1769: }
1770:
1771:
1772:
1.1.1.2 ! root 1773: /* We have to worry about processes which attach themselves to running
1.1 root 1774:
1.1.1.2 ! root 1775: * processes which they want to trace. We fix things up so that the
1.1 root 1776:
1.1.1.2 ! root 1777: * second time the signal gets delivered we will go all the way to the
! 1778:
! 1779: * end of this function.
! 1780:
! 1781: */
! 1782:
! 1783: if (p->ptracer && p->ptracer->pid != p->ppid) {
! 1784:
! 1785: if (curproc == p->ptracer) {
! 1786:
! 1787: /* deliver the signal to the tracing process first */
! 1788:
! 1789: TRACE(("Pwaitpid(ptracer): returning status to tracing process"));
! 1790:
! 1791: p->ptracer = NULL;
! 1792:
! 1793: return r;
! 1794:
! 1795: }
! 1796:
! 1797: else {
! 1798:
! 1799: /* Hmmm, the real parent got here first */
! 1800:
! 1801: TRACE(("Pwaitpid(ptracer): returning status to parent process"));
! 1802:
! 1803: p->ppid = -1;
! 1804:
! 1805: return r;
! 1806:
! 1807: }
! 1808:
! 1809: }
! 1810:
! 1811:
! 1812:
! 1813: /* if it was a TSR, mark it as having been found and return */
! 1814:
! 1815: if (p->wait_q == TSR_Q) {
! 1816:
! 1817: p->ppid = -1;
1.1 root 1818:
1819: return r;
1820:
1821: }
1822:
1823:
1824:
1825: /* it better have been on the ZOMBIE queue from here on in... */
1826:
1827: assert(p->wait_q == ZOMBIE_Q);
1828:
1829: assert(p != curproc);
1830:
1831:
1832:
1833: /* take the child off both the global and ZOMBIE lists */
1834:
1835: rm_q(ZOMBIE_Q, p);
1836:
1837:
1838:
1839: if (proclist == p) {
1840:
1841: proclist = p->gl_next;
1842:
1843: p->gl_next = 0;
1844:
1845: }
1846:
1847: else {
1848:
1849: q = proclist;
1850:
1851: while(q && q->gl_next != p)
1852:
1853: q = q->gl_next;
1854:
1855: assert(q);
1856:
1857: q->gl_next = p->gl_next;
1858:
1859: p->gl_next = 0;
1860:
1861: }
1862:
1863:
1864:
1865: dispose_proc(p); /* free the PROC structure */
1866:
1867:
1868:
1869: return r;
1870:
1871: }
1872:
1873:
1874:
1.1.1.2 ! root 1875: /* p_wait3: BSD process termination primitive, here to maintain
! 1876:
! 1877: * compatibility with existing binaries.
! 1878:
! 1879: */
! 1880:
! 1881: long ARGS_ON_STACK
! 1882:
! 1883: p_wait3(nohang, rusage)
! 1884:
! 1885: int nohang;
! 1886:
! 1887: long *rusage;
! 1888:
! 1889: {
! 1890:
! 1891: return p_waitpid(-1, nohang, rusage);
! 1892:
! 1893: }
! 1894:
! 1895:
! 1896:
1.1 root 1897: /* p_wait: block until a child has exited, and don't worry about
1898:
1899: resource stats. this is provided as a convenience, and to maintain
1900:
1901: compatibility with existing binaries (yes, I'm lazy...). we could
1902:
1.1.1.2 ! root 1903: make do with Pwaitpid().
1.1 root 1904:
1905: */
1906:
1907:
1908:
1.1.1.2 ! root 1909: long ARGS_ON_STACK
1.1 root 1910:
1911: p_wait()
1912:
1913: {
1914:
1.1.1.2 ! root 1915: /*
! 1916:
! 1917: * BEWARE:
! 1918:
! 1919: * POSIX says that wait() should be implemented as
! 1920:
! 1921: * Pwaitpid(-1, 0, (long *)0). Pwait is really not
! 1922:
! 1923: * useful for much at all, but we'll keep it around
! 1924:
! 1925: * for a while (with it's old, crufty semantics)
! 1926:
! 1927: * for backwards compatibility. People implementing
! 1928:
! 1929: * POSIX style libraries should use Pwaitpid even
! 1930:
! 1931: * to implement wait().
! 1932:
! 1933: */
! 1934:
1.1 root 1935: return p_wait3(2, (long *)0);
1936:
1937: }
1938:
1939:
1940:
1941: /*
1942:
1943: * do_vfork(save): create a duplicate of the current process. This is
1944:
1945: * essentially a vfork() algorithm, except that if (save == 1) the
1946:
1947: * parent's address space is saved, and then restored when the process
1948:
1949: * is made runnable again. The parent is suspended until either the child
1950:
1951: * process (the duplicate) exits or does a Pexec which overlays its
1952:
1953: * memory space.
1954:
1955: *
1956:
1957: * "txtsize" is the size of the process' TEXT area, if it has a valid one;
1958:
1959: * this is part of the second memory region attached (the basepage one)
1960:
1961: * and need not be saved (we assume processes don't write on their own
1962:
1963: * code segment)
1964:
1965: */
1966:
1967:
1968:
1969: static long
1970:
1971: do_vfork(save)
1972:
1973: int save;
1974:
1975: {
1976:
1977: PROC *p;
1978:
1979: long sigmask;
1980:
1981: MEMREGION *m, *savemem = 0;
1982:
1983: long savesize, txtsize;
1984:
1985: int i;
1986:
1987: char *saveplace;
1988:
1989:
1990:
1991: p = fork_proc();
1992:
1993: if (!p) {
1994:
1.1.1.2 ! root 1995: DEBUG(("do_vfork: couldn't get new PROC struct"));
1.1 root 1996:
1997: return mint_errno;
1998:
1999: }
2000:
2001: /* set u:\proc time+date */
2002:
2003: proctime = timestamp;
2004:
2005: procdate = datestamp;
2006:
2007:
2008:
2009: /*
2010:
2011: * maybe save the parent's address space
2012:
2013: */
2014:
2015: txtsize = p->txtsize;
2016:
2017:
2018:
2019: if (save) {
2020:
1.1.1.2 ! root 2021: TRACE(("do_vfork: saving parent"));
1.1 root 2022:
2023: savesize = memused(curproc) - txtsize;
2024:
2025: assert(savesize >= 0);
2026:
2027:
2028:
2029: saveplace = (char *)alloc_region(alt, savesize);
2030:
2031: if (!saveplace)
2032:
2033: saveplace = (char *)alloc_region(core, savesize);
2034:
2035:
2036:
2037: if (!saveplace) {
2038:
1.1.1.2 ! root 2039: DEBUG(("do_vfork: can't save parent's memory"));
1.1 root 2040:
2041: p->ppid = 0; /* abandon the child */
2042:
2043: post_sig(p, SIGKILL); /* then kill it */
2044:
2045: p->ctxt[CURRENT].pc = (long)check_sigs;
2046:
2047: /* just to make sure it dies */
2048:
2049: p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
2050:
2051: p->pri = MAX_NICE+1;
2052:
2053: run_next(p, 1);
2054:
2055: yield();
2056:
2057: return ENSMEM;
2058:
2059: }
2060:
2061: savemem = addr2mem((virtaddr)saveplace);
2062:
2063: assert(savemem);
2064:
2065: for (i = 0; i < curproc->num_reg; i++) {
2066:
2067: m = curproc->mem[i];
2068:
1.1.1.2 ! root 2069: if (m && m != savemem && !(m->mflags & M_SHTEXT)) {
1.1 root 2070:
2071: if (i != 1 || txtsize == 0) {
2072:
2073: quickmove(saveplace, (char *)m->loc, m->len);
2074:
2075: saveplace += m->len;
2076:
2077: }
2078:
2079: else {
2080:
2081: quickmove(saveplace, (char *)m->loc+txtsize,
2082:
2083: m->len - txtsize);
2084:
2085: saveplace += m->len - txtsize;
2086:
2087: }
2088:
2089: }
2090:
2091: }
2092:
2093: }
2094:
2095:
2096:
2097: p->ctxt[CURRENT] = p->ctxt[SYSCALL];
2098:
2099: p->ctxt[CURRENT].regs[0] = 0; /* child returns a 0 from call */
2100:
2101: p->ctxt[CURRENT].sr &= ~(0x2000); /* child must be in user mode */
2102:
2103: #if 0 /* set up in fork_proc() */
2104:
2105: p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
2106:
2107: #endif
2108:
2109:
2110:
2111: /* watch out for job control signals, since our parent can never wake
2112:
2113: * up to respond to them. solution: block them; exec_region (in mem.c)
2114:
2115: * clears the signal mask, so an exec() will unblock them.
2116:
2117: */
2118:
2119: p->sigmask |= (1L << SIGTSTP) | (1L << SIGTTIN) | (1L << SIGTTOU);
2120:
2121:
2122:
1.1.1.2 ! root 2123: TRACE(("do_vfork: parent going to sleep, wait_cond == %lx",
1.1 root 2124:
1.1.1.2 ! root 2125: (long)p));
1.1 root 2126:
2127:
2128:
2129: /* WARNING: This sleep() must absolutely not wake up until the child
2130:
2131: * has released the memory space correctly. That's why we mask off
2132:
2133: * all signals.
2134:
2135: */
2136:
2137: sigmask = curproc->sigmask;
2138:
1.1.1.2 ! root 2139: curproc->sigmask = ~((unsigned long)1 << SIGKILL);
1.1 root 2140:
2141:
2142:
2143: add_q(READY_Q, p); /* put it on the ready queue */
2144:
2145: sleep(WAIT_Q, (long)p); /* while we wait for it */
2146:
1.1.1.2 ! root 2147: TRACE(("do_vfork: parent waking up"));
1.1 root 2148:
2149:
2150:
2151: if (save) {
2152:
1.1.1.2 ! root 2153: TRACE(("do_vfork: parent restoring memory"));
1.1 root 2154:
2155: saveplace = (char *)savemem->loc;
2156:
2157: for (i = 0; i < curproc->num_reg; i++) {
2158:
2159: m = curproc->mem[i];
2160:
1.1.1.2 ! root 2161: if (m && (m != savemem) && !(m->mflags & M_SHTEXT)) {
1.1 root 2162:
2163: if (i != 1 || txtsize == 0) {
2164:
2165: quickmove((char *)m->loc, saveplace, m->len);
2166:
2167: saveplace += m->len;
2168:
2169: }
2170:
2171: else {
2172:
2173: quickmove((char *)m->loc+txtsize, saveplace,
2174:
2175: m->len - txtsize);
2176:
2177: saveplace += m->len - txtsize;
2178:
2179: }
2180:
2181: }
2182:
2183: }
2184:
2185: detach_region(curproc, savemem);
2186:
2187: }
2188:
2189: curproc->sigmask = sigmask;
2190:
2191: check_sigs(); /* did we get any signals while sleeping? */
2192:
2193: return p->pid;
2194:
2195: }
2196:
2197:
2198:
2199: /*
2200:
2201: * here are the interfaces that the user sees. Pvfork() doesn't save
2202:
2203: * the child's address space; Pfork() does. Someday Pfork() should
2204:
2205: * allow asynchronous execution of both child and parent, but this
2206:
2207: * will do for now.
2208:
2209: */
2210:
2211:
2212:
1.1.1.2 ! root 2213: long ARGS_ON_STACK
1.1 root 2214:
2215: p_vfork()
2216:
2217: {
2218:
2219: return do_vfork(0);
2220:
2221: }
2222:
2223:
2224:
1.1.1.2 ! root 2225: long ARGS_ON_STACK
1.1 root 2226:
2227: p_fork()
2228:
2229: {
2230:
2231: return do_vfork(1);
2232:
2233: }
2234:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.