Annotation of MiNT/src/dosmem.c, revision 1.1.1.2

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.