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

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

unix.superglobalmegacorp.com

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