|
|
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 2.3.37 ! 10: * Copyright (c) 1982, 1983, 1984. ! 11: * An unpublished work by Mark Williams Company, Chicago. ! 12: * All rights reserved. ! 13: -lgl) */ ! 14: /* ! 15: * coh.386/sys1.c ! 16: * ! 17: * Coherent. ! 18: * General system calls. ! 19: * ! 20: * Revised: Tue May 11 11:12:03 1993 CDT ! 21: */ ! 22: ! 23: #include <common/_gregset.h> ! 24: #include <kernel/sigproc.h> ! 25: #include <sys/coherent.h> ! 26: #include <sys/acct.h> ! 27: #include <sys/con.h> ! 28: #include <sys/wait.h> ! 29: #include <sys/errno.h> ! 30: #include <sys/proc.h> ! 31: #include <sys/sched.h> ! 32: #include <sys/seg.h> ! 33: #include <sys/stat.h> ! 34: #include <signal.h> ! 35: #include <sys/times.h> ! 36: ! 37: /* ! 38: * Send alarm signal to specified process - function timed by ualarm() ! 39: */ ! 40: sigalrm(pp) ! 41: register PROC * pp; ! 42: { ! 43: sendsig (SIGALRM, pp); ! 44: } ! 45: ! 46: /* ! 47: * Send a SIGALARM signal in `n' seconds. ! 48: */ ! 49: ualarm(n) ! 50: unsigned n; ! 51: { ! 52: register PROC * pp = SELF; ! 53: register unsigned s; ! 54: ! 55: /* ! 56: * Calculate time left before current alarm timeout. ! 57: */ ! 58: s = 0; ! 59: if (pp->p_alrmtim.t_last != NULL) ! 60: s = (pp->p_alrmtim.t_lbolt - lbolt + HZ - 1) / HZ; ! 61: ! 62: /* ! 63: * Cancel previous alarm [if any], start new alarm [if n != 0]. ! 64: */ ! 65: timeout2 (& pp->p_alrmtim, (long) n * HZ, sigalrm, pp); ! 66: ! 67: /* ! 68: * Return time left before previous alarm timeout. ! 69: */ ! 70: return s; ! 71: } ! 72: ! 73: ! 74: /* ! 75: * Change the size of our data segment. ! 76: */ ! 77: char * ! 78: ubrk(cp) ! 79: caddr_t cp; ! 80: { ! 81: register SEG *sp; ! 82: register caddr_t sb; ! 83: register SR *stack_sr; ! 84: caddr_t top_of_stack; ! 85: ! 86: T_HAL (0x8000, printf ("%s:ubrk(%x) ", u.u_comm, cp)); ! 87: ! 88: /* ! 89: * Pick up the segment handle for our data segment. ! 90: */ ! 91: sp = SELF->p_segp [SIPDATA]; ! 92: ! 93: /* ! 94: * Extract the starting virtual address for our data segment, ! 95: * as it is currently mapped into the memory space. ! 96: */ ! 97: sb = u.u_segl [SIPDATA].sr_base; ! 98: ! 99: /* ! 100: * We can not move the top of the data segment below the ! 101: * start of the data segment. ! 102: */ ! 103: if (cp < sb) { ! 104: SET_U_ERROR (ENOMEM, ! 105: "Requested brk address is below start of data segment."); ! 106: return 0; ! 107: } ! 108: ! 109: /* ! 110: * Would the request cause a collision with the stack segment? ! 111: * ! 112: * Since the stack grows downward, its top is below its base :-). ! 113: */ ! 114: ! 115: stack_sr = & u.u_segl [SISTACK]; ! 116: top_of_stack = stack_sr->sr_base - stack_sr->sr_size; ! 117: ! 118: if (btoc (cp) >= btoc (top_of_stack)) { ! 119: SET_U_ERROR (ENOMEM, ! 120: "Requested brk address would collide with stack segment."); ! 121: return 0; ! 122: } ! 123: ! 124: /* ! 125: * Attempt to establish the segment with the newly requested size. ! 126: */ ! 127: segsize (sp, cp - sb); ! 128: ! 129: /* ! 130: * Be sure to return the true new top of data segment. ! 131: */ ! 132: sb += sp->s_size; ! 133: ! 134: T_HAL (0x8000, printf ("=%x ", sb)); ! 135: return sb; ! 136: } ! 137: ! 138: ! 139: /* ! 140: * Execute an l.out or COFF file. ! 141: */ ! 142: ! 143: int ! 144: uexece (np, argp, envp, regsetp) ! 145: char * np; ! 146: char * argp []; ! 147: char * envp []; ! 148: gregset_t * regsetp; ! 149: { ! 150: pexece (np, argp, envp, regsetp); ! 151: } ! 152: ! 153: ! 154: /* ! 155: * Exit. ! 156: */ ! 157: ! 158: uexit (s) ! 159: unsigned s; ! 160: { ! 161: pexit ((s & 0xFF) << 8); ! 162: } ! 163: ! 164: ! 165: /* ! 166: * Fork. ! 167: */ ! 168: ! 169: pid_t ! 170: ufork () ! 171: { ! 172: return pfork (); ! 173: } ! 174: ! 175: /* ! 176: * Get group id. ! 177: * Get effective group id. ! 178: */ ! 179: ! 180: gid_t ! 181: ugetgid () ! 182: { ! 183: u.u_rval2 = u.u_gid; ! 184: return u.u_rgid; ! 185: } ! 186: ! 187: ! 188: /* ! 189: * Get user id. ! 190: * Get effective user id. ! 191: */ ! 192: ! 193: uid_t ! 194: ugetuid () ! 195: { ! 196: u.u_rval2 = u.u_uid; ! 197: return u.u_ruid; ! 198: } ! 199: ! 200: ! 201: /* ! 202: * Get process group. ! 203: * Set the process group. ! 204: * ! 205: * This is System V type setpgrp(). ! 206: * Set process group equal to process id (make process its own group leader). ! 207: * If process was NOT already a group leader, lose its controlling terminal. ! 208: */ ! 209: ! 210: int ! 211: upgrp (fl) ! 212: { ! 213: register PROC * pp = SELF; ! 214: ! 215: if (fl) { ! 216: if (pp->p_group != pp->p_pid) ! 217: pp->p_ttdev = NODEV; ! 218: pp->p_group = pp->p_pid; ! 219: } ! 220: return pp->p_group; ! 221: } ! 222: ! 223: ! 224: /* ! 225: * Get process id. ! 226: */ ! 227: ! 228: pid_t ! 229: ugetpid() ! 230: { ! 231: u.u_rval2 = SELF->p_ppid; ! 232: return SELF->p_pid; ! 233: } ! 234: ! 235: ! 236: /* ! 237: * Send the signal `sig' to the process with id `pid'. ! 238: */ ! 239: ! 240: int ! 241: ukill(pid, sig) ! 242: int pid; ! 243: register unsigned sig; ! 244: { ! 245: register PROC *pp; ! 246: register int sigflag; ! 247: ! 248: if (sig > NSIG) { ! 249: u.u_error = EINVAL; ! 250: return; ! 251: } ! 252: ! 253: sigflag = 0; ! 254: lock (pnxgate); ! 255: ! 256: if (pid > 0) { /* send to matching process */ ! 257: for (pp = procq.p_nforw ; pp != & procq ; pp = pp->p_nforw) { ! 258: if (pp->p_state == PSDEAD) ! 259: continue; ! 260: if (pp->p_pid == pid) { ! 261: sigflag = 1; ! 262: if (sig) { ! 263: if (sigperm (sig, pp)) ! 264: sendsig (sig, pp); ! 265: else ! 266: u.u_error = EPERM; ! 267: } ! 268: break; ! 269: } ! 270: } ! 271: } else if (pid < -1) { ! 272: pid = -pid; ! 273: for (pp = procq.p_nforw ; pp != & procq ; pp = pp->p_nforw) { ! 274: if (pp->p_state == PSDEAD) ! 275: continue; ! 276: if (pp->p_group == pid) { ! 277: sigflag = 1; ! 278: if (sig) { ! 279: if (sigperm (sig, pp)) ! 280: sendsig (sig,pp); ! 281: else ! 282: u.u_error = EPERM; ! 283: } ! 284: } ! 285: } ! 286: } else if (pid == 0) { ! 287: for (pp = procq.p_nforw ; pp != & procq ; pp = pp->p_nforw) { ! 288: if (pp->p_state == PSDEAD) ! 289: continue; ! 290: if (pp->p_group == SELF->p_group) { ! 291: sigflag = 1; ! 292: if (sig && sigperm (sig, pp)) ! 293: sendsig (sig, pp); ! 294: } ! 295: } ! 296: } else if (pid == -1) { ! 297: for (pp = procq.p_nforw ; pp != & procq ; pp = pp->p_nforw) { ! 298: if (pp->p_state == PSDEAD) ! 299: continue; ! 300: if (pp->p_pid == 0) ! 301: continue; ! 302: if (pp->p_pid == 1) ! 303: continue; ! 304: if (pp->p_flags & PFKERN) ! 305: continue; ! 306: sigflag = 1; ! 307: if (sig && super ()) ! 308: sendsig (sig, pp); ! 309: } ! 310: } ! 311: ! 312: unlock (pnxgate); ! 313: if (sigflag == 0) ! 314: u.u_error = ESRCH; ! 315: ! 316: return 0; ! 317: } ! 318: ! 319: /* ! 320: * See if we have permission to send the signal, `sig' to the process, `pp'. ! 321: */ ! 322: sigperm(sig, pp) ! 323: register PROC *pp; ! 324: { ! 325: if (u.u_uid == pp->p_uid) ! 326: return 1; ! 327: ! 328: if (u.u_ruid == pp->p_ruid && (sig == SIGHUP || sig == SIGINT || ! 329: sig == SIGQUIT || sig == SIGTERM)) ! 330: return 1; ! 331: ! 332: if (u.u_uid == 0) { ! 333: u.u_flag |= ASU; ! 334: return 1; ! 335: } ! 336: return 0; ! 337: } ! 338: ! 339: /* ! 340: * Lock a process in core. ! 341: */ ! 342: ulock(f) ! 343: { ! 344: if (super () == 0) ! 345: return; ! 346: if (f) ! 347: SELF->p_flags |= PFLOCK; ! 348: else ! 349: SELF->p_flags &= ~PFLOCK; ! 350: return 0; ! 351: } ! 352: ! 353: /* ! 354: * Change priority by the given increment. ! 355: */ ! 356: unice(n) ! 357: register int n; ! 358: { ! 359: n += SELF->p_nice; ! 360: if (n < MINNICE) ! 361: n = MINNICE; ! 362: if (n > MAXNICE) ! 363: n = MAXNICE; ! 364: if (n < SELF->p_nice && super () == 0) ! 365: return; ! 366: SELF->p_nice = n; ! 367: return 0; ! 368: } ! 369: ! 370: /* ! 371: * Non existant system call. ! 372: */ ! 373: unone() ! 374: { ! 375: u.u_error = EFAULT; ! 376: } ! 377: ! 378: /* ! 379: * Null system call. ! 380: */ ! 381: unull() ! 382: { ! 383: } ! 384: ! 385: /* ! 386: * Pause. Go to sleep on a channel that nobody will wakeup so that only ! 387: * signals will wake us up. ! 388: */ ! 389: upause() ! 390: { ! 391: x_sleep ((char *) & u, prilo, slpriSigLjmp, "pause"); ! 392: } ! 393: ! 394: /* ! 395: * Start/stop profiling. ! 396: * ! 397: * buff: address in user data of an array of shorts ! 398: * bufsiz: number of bytes in the area at buff ! 399: * offset: address in user text of start of profiling area ! 400: * scale: 0 or 1 - turn off profiling ! 401: * other - treat as 16 bit scale factor ! 402: * ! 403: * For purposes of compatibility with System 5, scale values work as follows: ! 404: * 0xFFFF profile buffer is same length as text being profiled. ! 405: * 0x7FFF profile buffer is half as long as text being profiled. ! 406: * 0x4000 profile buffer is one fourth as long as text profiled. ! 407: * (each short in the buffer covers 8 bytes of text) ! 408: * ... ... ! 409: * 0x0002 each short in the buffer covers 64K bytes of text. ! 410: * ! 411: * Values 0xFFFF and 0x7FFF are used, for historical reasons, when 0x10000 ! 412: * and 0x8000, respectively, should be used. To clean up the ensuing ! 413: * arithmetic, there is an upward rounding kluge below. ! 414: * ! 415: * Each clock interrupt, take (pc - offset) * scale * (2**-16) as a byte ! 416: * offset into pbase. Add 1 to the short at or below the given address ! 417: * when profiling. ! 418: */ ! 419: uprofil(buff, bufsiz, offset, scale) ! 420: short * buff; ! 421: int bufsiz, offset, scale; ! 422: { ! 423: u.u_pbase = buff; ! 424: u.u_pbend = buff + bufsiz; ! 425: u.u_pofft = offset; ! 426: u.u_pscale = scale & 0xffff; /* scale is really unsigned short */ ! 427: ! 428: /* round up kluge - see above */ ! 429: if ((scale & 0xfff) == 0xfff) ! 430: u.u_pscale ++; ! 431: } ! 432: ! 433: /* ! 434: * Process trace. ! 435: */ ! 436: uptrace(req, pid, add, data) ! 437: int *add; ! 438: { ! 439: int ret; ! 440: ! 441: #ifdef TRACER ! 442: int readChild = 0; /* for debug, true if reading child memory */ ! 443: ! 444: if (t_hal & 0x10000) { ! 445: switch (req) { ! 446: case 0: /* init called by child */ ! 447: printf("PSetup: child=%d ", SELF->p_pid); ! 448: break; ! 449: case 1: /* parent reads child text */ ! 450: printf("PRdT: add=%x ", add); ! 451: readChild = 1; ! 452: break; ! 453: case 2: /* parent reads child data */ ! 454: printf("PRdD: add=%x ", add); ! 455: readChild = 1; ! 456: break; ! 457: case 3: /* parent reads child u area */ ! 458: printf("PRdU: add=%x ", add); ! 459: readChild = 1; ! 460: break; ! 461: case 4: /* parent writes child text */ ! 462: printf("PWrT: add=%x data=%x ", add, data); ! 463: break; ! 464: case 5: /* parent writes child data */ ! 465: printf("PWrD: add=%x data=%x ", add, data); ! 466: break; ! 467: case 6: /* parent writes child u area */ ! 468: printf("PWrU: add=%x data=%x ", add, data); ! 469: break; ! 470: case 7: /* resume child, maybe fake signal to child */ ! 471: printf("PResume: sig=%d ", data); ! 472: break; ! 473: case 8: /* terminate child */ ! 474: printf("PTerm: pid=%d ", pid); ! 475: break; ! 476: case 9: /* single-step child, maybe fake signal to child */ ! 477: printf("PSStp: sig=%d ", data); ! 478: break; ! 479: } ! 480: } ! 481: #endif ! 482: ! 483: if (req == 0) { ! 484: SELF->p_flags |= PFTRAC; ! 485: ret = 0; ! 486: } else ! 487: ret = ptset (req, pid, add, data); ! 488: ! 489: #ifdef TRACER ! 490: if (t_hal & 0x10000) { ! 491: if (readChild) ! 492: printf("data=%x ", ret); ! 493: } ! 494: #endif ! 495: ! 496: return ret; ! 497: } ! 498: ! 499: /* ! 500: * Set group id. ! 501: * ! 502: * As in SVID issue 2: ! 503: * ! 504: * if effective gid is superuser ! 505: * set real, effective, and saved effective gid to argument "gid" ! 506: * else if real gid is same as "gid" ! 507: * set effective gid to "gid" ! 508: * else if saved effective gid is same as "gid" ! 509: * set effective gid to "gid" ! 510: */ ! 511: ! 512: usetgid(gid) ! 513: register int gid; ! 514: { ! 515: if (super ()) { ! 516: u.u_gid = u.u_rgid = u.u_egid = gid; ! 517: SELF->p_rgid = gid; ! 518: } else { ! 519: u.u_error = 0; /* super() sets u_error when it fails */ ! 520: ! 521: if (u.u_rgid == gid || u.u_egid == gid) ! 522: u.u_gid = gid; ! 523: else ! 524: SET_U_ERROR (EPERM, "Illegal gid"); ! 525: } ! 526: return 0; ! 527: } ! 528: ! 529: /* ! 530: * Set user id. ! 531: * ! 532: * As in SVID issue 2: ! 533: * ! 534: * if effective uid is superuser ! 535: * set real, effective, and saved effective uid to argument "uid" ! 536: * else if real uid is same as "uid" ! 537: * set effective uid to "uid" ! 538: * else if saved effective uid is same as "uid" ! 539: * set effective uid to "uid" ! 540: */ ! 541: ! 542: usetuid(uid) ! 543: register int uid; ! 544: { ! 545: if (super ()) { ! 546: u.u_uid = u.u_ruid = u.u_euid = uid; ! 547: SELF->p_uid = SELF->p_ruid = uid; ! 548: } else { ! 549: u.u_error = 0; /* super() sets u_error when it fails */ ! 550: ! 551: if (u.u_ruid == uid || u.u_euid == uid) ! 552: SELF->p_uid = u.u_uid = uid; ! 553: else ! 554: SET_U_ERROR(EPERM, "Illegal uid"); ! 555: } ! 556: return 0; ! 557: } ! 558: ! 559: /* ! 560: * Load a device driver. ! 561: */ ! 562: usload(np) ! 563: char *np; ! 564: { ! 565: return pload (np); ! 566: } ! 567: ! 568: /* ! 569: * Set time and date. ! 570: * ! 571: * Unlike the libc interface, this routine expects a time_t value ! 572: * as an arg, not a time_t pointer. ! 573: */ ! 574: ! 575: int ! 576: ustime (newtime) ! 577: time_t newtime; ! 578: { ! 579: register int s; ! 580: ! 581: if (super () == 0) ! 582: return; ! 583: ! 584: s = sphi (); ! 585: timer.t_time = newtime; ! 586: spl (s); ! 587: return 0; ! 588: } ! 589: ! 590: /* ! 591: * Return process times. ! 592: */ ! 593: utimes(tp) ! 594: struct tms *tp; ! 595: { ! 596: register PROC *pp; ! 597: struct tms tbuffer; ! 598: ! 599: if (tp) { ! 600: pp = SELF; ! 601: tbuffer.tms_utime = pp->p_utime; ! 602: tbuffer.tms_stime = pp->p_stime; ! 603: tbuffer.tms_cutime = pp->p_cutime; ! 604: tbuffer.tms_cstime = pp->p_cstime; ! 605: kucopyS (& tbuffer, tp, sizeof (tbuffer)); ! 606: } ! 607: return lbolt; ! 608: } ! 609: ! 610: /* ! 611: * Unload a device driver. ! 612: */ ! 613: usuload(m) ! 614: register int m; ! 615: { ! 616: if (super () == 0) ! 617: return; ! 618: puload (m); ! 619: return 0; ! 620: } ! 621: ! 622: /* ! 623: * Wait for a child to terminate. If this function is called from i286 code, ! 624: * then we will have a "statp" argument, where we stash the exit status, but ! 625: * for the i386 code we put a value in u.u_rval2. ! 626: * ! 627: * NIGEL: The idiom for looping over the process table must be changed to ! 628: * work right ASAP. ! 629: */ ! 630: ! 631: int ! 632: uwait (statp) ! 633: short * statp; ! 634: { ! 635: register PROC *pp; ! 636: register PROC *ppp; ! 637: register PROC *cpp; ! 638: register int pid; ! 639: ! 640: /* Wait for a child to stop or die. */ ! 641: ! 642: T_HAL (8, printf ("[%d]waits ", SELF->p_pid)); ! 643: ppp = SELF; ! 644: ! 645: for (;;) { ! 646: /* Look at all processes. */ ! 647: again: ! 648: lock (pnxgate); ! 649: cpp = NULL; ! 650: pp = & procq; ! 651: while ((pp = pp->p_nforw) != &procq) { ! 652: ! 653: /* Ignore the current process. */ ! 654: if (pp == ppp) ! 655: continue; ! 656: /* ! 657: * Ignore processes that aren't children of the ! 658: * current one. ! 659: */ ! 660: if (pp->p_ppid != ppp->p_pid || ! 661: (pp->p_flags & PFSTOP) != 0) ! 662: continue; ! 663: ! 664: /* Here is a child that hit a breakpoint. */ ! 665: if (pp->p_flags & PFWAIT) { ! 666: int work; /* virtual click number */ ! 667: int childUseg; /* system global addr */ ! 668: UPROC * uprc; ! 669: SEG * sp; ! 670: ! 671: pp->p_flags &= ~PFWAIT; ! 672: pp->p_flags |= PFSTOP; ! 673: ! 674: /* fetch u.u_signo from the child */ ! 675: ! 676: /* Find u area for child process pp */ ! 677: sp = pp->p_segp [SIUSERP]; ! 678: childUseg = MAPIO (sp->s_vmem, U_OFFSET); ! 679: work = workAlloc (); ! 680: ptable1_v [work] = ! 681: sysmem.u.pbase [btocrd (childUseg)] | SEG_RW; ! 682: uprc = (UPROC *) (ctob (work) + U_OFFSET); ! 683: ! 684: if (statp != NULL) ! 685: putusd (statp, (uprc->u_signo << 8) | ! 686: __WSTOPFLG); ! 687: else ! 688: u.u_rval2 = (uprc->u_signo << 8) | ! 689: __WSTOPFLG; ! 690: ! 691: workFree (work); ! 692: ! 693: unlock (pnxgate); ! 694: T_HAL (8, ! 695: printf ("[%d]ends waiting, %d stopped ", ! 696: SELF->p_pid, pid)); ! 697: return pp->p_pid; ! 698: } ! 699: if (pp->p_state == PSDEAD) { ! 700: ppp->p_cutime += pp->p_utime + pp->p_cutime; ! 701: ppp->p_cstime += pp->p_stime + pp->p_cstime; ! 702: ! 703: if (statp != NULL) ! 704: putusd (statp, pp->p_exit); ! 705: else ! 706: u.u_rval2 = pp->p_exit; ! 707: pid = pp->p_pid; ! 708: unlock (pnxgate); ! 709: relproc (pp); ! 710: ! 711: if ((proc_signal_misc (ppp) & ! 712: __SF_NOCLDWAIT) != 0) ! 713: goto again; ! 714: ! 715: T_HAL (8, printf ("[%d]ends waiting, %d died ", ! 716: SELF->p_pid, pid)); ! 717: return pid; ! 718: } ! 719: cpp = pp; ! 720: } ! 721: unlock (pnxgate); ! 722: if (cpp == NULL) { ! 723: T_HAL (8, printf ("[%d]ends waiting, no children ", ! 724: SELF->p_pid)); ! 725: u.u_error = ECHILD; ! 726: return; ! 727: } ! 728: (void) x_sleep ((char *) ppp, prilo, slpriSigLjmp, "wait"); ! 729: /* Wait for a child to terminate. */ ! 730: } ! 731: } ! 732: ! 733: /* ! 734: * waitpid() and wait() share the same system call number under BCS. ! 735: * ! 736: * pid argument: ! 737: * > 0 wait for child whose process matches pid ! 738: * = 0 wait for any child in current process group ! 739: * = -1 wait for any child - same as wait() ! 740: * < -1 wait for any child in group given by -pid ! 741: * ! 742: * The only waitpid() options supported are WNOHANG and WUNTRACED. ! 743: * ! 744: */ ! 745: int ! 746: uwaitpid(opid, stat_loc, options) ! 747: register pid_t opid; ! 748: int *stat_loc, options; ! 749: { ! 750: register PROC *pp; ! 751: register PROC *ppp; ! 752: register PROC *cpp; ! 753: register int pid; ! 754: ! 755: if (options & WUNTRACED) { ! 756: printf("waitpid(%d,%d, WUNTRACED): unsupported\n", opid, ! 757: stat_loc); ! 758: u.u_error = EINVAL; ! 759: return; ! 760: } ! 761: ! 762: /* Wait for a child to stop or die. */ ! 763: ppp = SELF; ! 764: for (;;) { ! 765: /* Look at all processes. */ ! 766: again: ! 767: lock (pnxgate); ! 768: cpp = NULL; ! 769: pp = & procq; ! 770: while ((pp=pp->p_nforw) != &procq) { ! 771: ! 772: /* Ignore the current process. */ ! 773: if (pp == ppp) ! 774: continue; ! 775: /* ! 776: * Ignore processes that aren't children of the ! 777: * current one. ! 778: */ ! 779: if (pp->p_ppid != ppp->p_pid || ! 780: (pp->p_flags & PFSTOP) != 0) ! 781: continue; ! 782: ! 783: /* If opid == 0 we want to match gids */ ! 784: /* If opid>0, want to match opid to child pid */ ! 785: /* If opid<-1, want to match -opid to child gid */ ! 786: if ((opid == 0 && pp->p_group != ppp->p_group) || ! 787: (opid > 0 && opid != pp->p_pid) || ! 788: (opid < -1 && - opid != pp->p_group)) ! 789: continue; ! 790: ! 791: /* if opid == -1, then any child is acceptable */ ! 792: ! 793: /* Here is an acceptable child that hit a breakpoint. */ ! 794: if (pp->p_flags & PFWAIT) { ! 795: int work; /* virtual click number */ ! 796: int childUseg; /* system global addr */ ! 797: UPROC * uprc; ! 798: SEG * sp; ! 799: ! 800: pp->p_flags &= ~PFWAIT; ! 801: pp->p_flags |= PFSTOP; ! 802: ! 803: /* fetch u.u_signo from the child */ ! 804: ! 805: /* Find u area for child process pp */ ! 806: sp = pp->p_segp [SIUSERP]; ! 807: childUseg = MAPIO (sp->s_vmem, U_OFFSET); ! 808: work = workAlloc (); ! 809: ptable1_v [work] = ! 810: sysmem.u.pbase [btocrd (childUseg)] | SEG_RW; ! 811: mmuupd (); ! 812: uprc = (UPROC *) (ctob (work) + U_OFFSET); ! 813: u.u_rval2 = (uprc->u_signo << 8) | __WSTOPFLG; ! 814: workFree (work); ! 815: ! 816: unlock (pnxgate); ! 817: return pp->p_pid; ! 818: } ! 819: ! 820: /* Here is an acceptable child that is a zombie. */ ! 821: if (pp->p_state == PSDEAD) { ! 822: ppp->p_cutime += pp->p_utime + pp->p_cutime; ! 823: ppp->p_cstime += pp->p_stime + pp->p_cstime; ! 824: u.u_rval2 = pp->p_exit; ! 825: pid = pp->p_pid; ! 826: unlock (pnxgate); ! 827: relproc (pp); ! 828: ! 829: if ((proc_signal_misc (ppp) & ! 830: __SF_NOCLDWAIT) != 0) ! 831: goto again; ! 832: ! 833: return pid; ! 834: } ! 835: cpp = pp; ! 836: } ! 837: unlock (pnxgate); ! 838: if (cpp == NULL) { ! 839: u.u_error = ECHILD; ! 840: return; ! 841: } ! 842: ! 843: if (options & WNOHANG) { ! 844: u.u_rval2 = 0; ! 845: return 0; ! 846: } ! 847: ! 848: /* Wait for a child to terminate. */ ! 849: (void) x_sleep ((char *) ppp, prilo, slpriSigLjmp, ! 850: "waitpid"); ! 851: } ! 852: } ! 853: ! 854: /* ! 855: * Wait for a child to terminate. ! 856: * ! 857: * iBCS2 says the same system call number is wait() and waitpid(), the ! 858: * distinction being in how the psw is set on entry. ! 859: * ! 860: * iBCS2 fails to mention that when wait() or waitpid() report status ! 861: * by writing into the pointer supplied, the status is put into %edx by ! 862: * the kernel, and moved from there into user space by the function in ! 863: * libc.a. uwait() and uwaitpid() specify a value for %edx by writing ! 864: * to u.u_rval2. ! 865: * ! 866: * Do wait() unless (ZF|PF|SF|OF) (=WPMASK) are set in psw. ! 867: */ ! 868: #define WPMASK 0x8C4 ! 869: ! 870: uwait386(arg1, arg2, arg3, regsetp) ! 871: unsigned long arg1; ! 872: unsigned long arg2; ! 873: unsigned long arg3; ! 874: gregset_t * regsetp; ! 875: { ! 876: return (regsetp->_i386._eflags & WPMASK) == WPMASK ? ! 877: uwaitpid (arg1, arg2, arg3) : uwait (NULL); ! 878: } ! 879:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.