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

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

unix.superglobalmegacorp.com

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