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

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

unix.superglobalmegacorp.com

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