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

1.1       root        1: /*
                      2: 
                      3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved.
                      4: 
                      5: */
                      6: 
                      7: 
                      8: 
                      9: /*
                     10: 
                     11:  * GEMDOS emulation routines: these are for the GEMDOS system calls
                     12: 
                     13:  * concerning allocating/freeing memory, including Pexec() (since
                     14: 
                     15:  * this allocates memory) and Pterm() (since this, implicitly, frees
                     16: 
                     17:  * it).
                     18: 
                     19:  */
                     20: 
                     21: 
                     22: 
                     23: #include "mint.h"
                     24: 
                     25: 
                     26: 
                     27: int procdate, proctime;        /* set when any processes are created/destroyed */
                     28: 
                     29: 
                     30: 
                     31: static long do_vfork P_((int));
                     32: 
                     33: 
                     34: 
                     35: /*
                     36: 
                     37:  * new call for TT TOS, for the user to inform DOS of alternate memory
                     38: 
                     39:  * FIXME: we really shouldn't trust the user so completely
                     40: 
                     41:  */
                     42: 
                     43: 
                     44: 
                     45: long
                     46: 
                     47: m_addalt(start, size)
                     48: 
                     49:        long start, size;
                     50: 
                     51: {
                     52: 
                     53:        if (!add_region(alt, start, size, M_ALT))
                     54: 
                     55:                return EINTRN;
                     56: 
                     57:        else
                     58: 
                     59:                return 0;
                     60: 
                     61: }
                     62: 
                     63: 
                     64: 
                     65: /*
                     66: 
                     67:  * internal routine for doing Malloc on a particular memory map
                     68: 
                     69:  */
                     70: 
                     71: 
                     72: 
                     73: long
                     74: 
                     75: _do_malloc(map, size, mode)
                     76: 
                     77:        MMAP map;
                     78: 
                     79:        long size;
                     80: 
                     81:        int mode;
                     82: 
                     83: {
                     84: 
                     85:        virtaddr v;
                     86: 
                     87:        MEMREGION *m;
                     88: 
                     89:        long maxsize, mleft;
                     90: 
                     91: 
                     92: 
                     93:        if (size == -1L) {
                     94: 
                     95:                maxsize = max_rsize(map);
                     96: 
                     97:                if (curproc->maxmem) {
                     98: 
                     99:                        mleft = curproc->maxmem - memused(curproc);
                    100: 
                    101:                        if (maxsize > mleft)
                    102: 
                    103:                                maxsize = mleft;
                    104: 
                    105:                        if (maxsize < 0)
                    106: 
                    107:                                maxsize = 0;
                    108: 
                    109:                }
                    110: 
                    111:        /* make sure to round down */
                    112: 
                    113:                return maxsize & ~MASKBITS;
                    114: 
                    115:        }
                    116: 
                    117: 
                    118: 
                    119: /* special case: Malloc(0) should always return 0 */
                    120: 
                    121:        if (size == 0)
                    122: 
                    123:                return 0;
                    124: 
                    125: 
                    126: 
                    127:        if (curproc->maxmem) {          /* memory limit? */
                    128: 
                    129:                if (size > curproc->maxmem - memused(curproc)) {
                    130: 
                    131:                        DEBUG("malloc: memory request would exceed limit");
                    132: 
                    133:                        return 0;
                    134: 
                    135:                }
                    136: 
                    137:        }
                    138: 
                    139: 
                    140: 
                    141:        m = get_region(map, size);
                    142: 
                    143:        if (!m) {
                    144: 
                    145:                DEBUG("malloc: out of memory");
                    146: 
                    147:                return 0;
                    148: 
                    149:        }
                    150: 
                    151:        v = attach_region(curproc, m);
                    152: 
                    153:        if (!v) {
                    154: 
                    155:                m->links = 0;
                    156: 
                    157:                free_region(m);
                    158: 
                    159:                return 0;
                    160: 
                    161:        }
                    162: 
                    163: /* NOTE: get_region returns a region with link count 1; since attach_region
                    164: 
                    165:  * increments the link count, we have to remember to decrement the count
                    166: 
                    167:  * to correct for this.
                    168: 
                    169:  */
                    170: 
                    171:        m->links--;
                    172: 
                    173:        if ((mode & F_KEEP)) {  /* request for permanent memory */
                    174: 
                    175:                m->mflags |= M_KEEP;
                    176: 
                    177:        }
                    178: 
                    179:        return (long)v;
                    180: 
                    181: }
                    182: 
                    183: 
                    184: 
                    185: long
                    186: 
                    187: m_xalloc(size, mode)
                    188: 
                    189:        long size;
                    190: 
                    191:        int mode;
                    192: 
                    193: {
                    194: 
                    195:        long r, r1;
                    196: 
                    197: 
                    198: 
                    199:        TRACE("Mxalloc(%ld,%x)",size,mode);
                    200: 
                    201:        if ( (mode & 8) ) {
                    202: 
                    203:                DEBUG("Unsupported Mxalloc mode");
                    204: 
                    205:                return 0;               /* future expansion */
                    206: 
                    207:        }
                    208: 
                    209:        if ( (mode&3) == 0)
                    210: 
                    211:                return _do_malloc(core, size, mode);
                    212: 
                    213:        else if ( (mode&3) == 1)
                    214: 
                    215:                return _do_malloc(alt, size, mode);
                    216: 
                    217:        else if (size == -1) {
                    218: 
                    219:                /* modes 2 and 3 are the same for for size -1 */
                    220: 
                    221:                r = _do_malloc(core, -1L, mode);
                    222: 
                    223:                r1 = _do_malloc(alt, -1L, mode);
                    224: 
                    225:                if (r > r1) return r;
                    226: 
                    227:                else return r1;
                    228: 
                    229:        }
                    230: 
                    231:        else if ( (mode&3) == 2) {
                    232: 
                    233:                r = _do_malloc(core, size, mode);
                    234: 
                    235:                if (r == 0) return _do_malloc(alt, size, mode);
                    236: 
                    237:                else return r;
                    238: 
                    239:        }
                    240: 
                    241:        else /* if ( (mode&3) == 3) */ {
                    242: 
                    243:                r = _do_malloc(alt, size, mode);
                    244: 
                    245:                if (r == 0) return _do_malloc(core, size, mode);
                    246: 
                    247:                else return r;
                    248: 
                    249:        }
                    250: 
                    251: 
                    252: 
                    253:        DEBUG("Mxalloc: bad request??");
                    254: 
                    255:        return 0;
                    256: 
                    257: }
                    258: 
                    259: 
                    260: 
                    261: long
                    262: 
                    263: m_alloc(size)
                    264: 
                    265:        long size;
                    266: 
                    267: {
                    268: 
                    269:        long r;
                    270: 
                    271: 
                    272: 
                    273:        TRACE("Malloc(%lx)", size);
                    274: 
                    275:        if (curproc->memflags & F_ALTALLOC)
                    276: 
                    277:                r = m_xalloc(size, 3);
                    278: 
                    279:        else
                    280: 
                    281:                r = m_xalloc(size, 0);
                    282: 
                    283:        TRACE("Malloc: returning %lx", r);
                    284: 
                    285:        return r;
                    286: 
                    287: }
                    288: 
                    289: 
                    290: 
                    291: long
                    292: 
                    293: m_free(block)
                    294: 
                    295:        virtaddr block;
                    296: 
                    297: {
                    298: 
                    299:        MEMREGION *m;
                    300: 
                    301:        int i;
                    302: 
                    303: 
                    304: 
                    305:        TRACE("Mfree(%lx)", block);
                    306: 
                    307:        if (!block) {
                    308: 
                    309:                DEBUG("Mfree: null pointer");
                    310: 
                    311:                return EIMBA;
                    312: 
                    313:        }
                    314: 
                    315: 
                    316: 
                    317: /* search backwards so that most recently allocated incarnations of
                    318: 
                    319:    shared memory blocks are freed first (this doesn't matter very often)
                    320: 
                    321:  */
                    322: 
                    323: 
                    324: 
                    325:        for (i = curproc->num_reg - 1; i >= 0; i--) {
                    326: 
                    327:                if (curproc->addr[i] == block) {
                    328: 
                    329:                        m = curproc->mem[i];
                    330: 
                    331:                        assert(m != NULL);
                    332: 
                    333:                        assert(m->loc == (long)block);
                    334: 
                    335:                        curproc->mem[i] = 0;
                    336: 
                    337:                        curproc->addr[i] = 0;
                    338: 
                    339:                        m->links--;
                    340: 
                    341:                        if (m->links == 0) {
                    342: 
                    343:                                free_region(m);
                    344: 
                    345:                        }
                    346: 
                    347:                        return 0;
                    348: 
                    349:                }
                    350: 
                    351:        }
                    352: 
                    353: 
                    354: 
                    355: /* hmmm... if we didn't find the region, perhaps it's a global
                    356: 
                    357:  * one (with the M_KEEP flag set) belonging to a process that
                    358: 
                    359:  * terminated
                    360: 
                    361:  */
                    362: 
                    363:        for (i = rootproc->num_reg - 1; i >= 0; i--) {
                    364: 
                    365:                if (rootproc->addr[i] == block) {
                    366: 
                    367:                        m = rootproc->mem[i];
                    368: 
                    369:                        assert(m != NULL);
                    370: 
                    371:                        assert(m->loc == (long)block);
                    372: 
                    373:                        if (!(m->mflags & M_KEEP))
                    374: 
                    375:                                continue;
                    376: 
                    377:                        rootproc->mem[i] = 0;
                    378: 
                    379:                        rootproc->addr[i] = 0;
                    380: 
                    381:                        m->links--;
                    382: 
                    383:                        if (m->links == 0) {
                    384: 
                    385:                                free_region(m);
                    386: 
                    387:                        }
                    388: 
                    389:                        return 0;
                    390: 
                    391:                }
                    392: 
                    393:        }
                    394: 
                    395: 
                    396: 
                    397: 
                    398: 
                    399:        DEBUG("Mfree: bad address %lx", block);
                    400: 
                    401:        return EIMBA;
                    402: 
                    403: }
                    404: 
                    405: 
                    406: 
                    407: long
                    408: 
                    409: m_shrink(dummy, block, size)
                    410: 
                    411:        int dummy;
                    412: 
                    413:        virtaddr block;
                    414: 
                    415:        long size;
                    416: 
                    417: {
                    418: 
                    419:        MEMREGION *m;
                    420: 
                    421:        int i;
                    422: 
                    423: 
                    424: 
                    425:        TRACE("Mshrink: %lx to %ld", block, size);
                    426: 
                    427:        if (!block) {
                    428: 
                    429:                DEBUG("Mshrink: null pointer");
                    430: 
                    431:                return EIMBA;
                    432: 
                    433:        }
                    434: 
                    435: 
                    436: 
                    437:        for (i = 0; i < curproc->num_reg; i++) {
                    438: 
                    439:                if (curproc->addr[i] == block) {
                    440: 
                    441:                        m = curproc->mem[i];
                    442: 
                    443:                        assert(m != NULL);
                    444: 
                    445:                        assert(m->loc == (long)block);
                    446: 
                    447:                        return shrink_region(m, size);
                    448: 
                    449:                }
                    450: 
                    451:        }
                    452: 
                    453:        DEBUG("Mshrink: bad address (%lx)", block);
                    454: 
                    455:        return EIMBA;
                    456: 
                    457: }
                    458: 
                    459: 
                    460: 
                    461: long
                    462: 
                    463: p_exec(mode, ptr1, ptr2, ptr3)
                    464: 
                    465:        int mode;
                    466: 
                    467:        void *ptr1, *ptr2, *ptr3;
                    468: 
                    469: {
                    470: 
                    471:        MEMREGION *base, *env = 0;   /* assignment suppress spurious warning */
                    472: 
                    473:        PROC *p = 0;
                    474: 
                    475:        long r, flags = 0;
                    476: 
                    477:        int i;
                    478: 
                    479:        char mkbase = 0, mkload = 0, mkgo = 0, mkwait = 0, mkfree = 0;
                    480: 
                    481:        char overlay = 0;
                    482: 
                    483:        char thread = 0;
                    484: 
                    485:        char mkname = 0, *newname, *lastslash;
                    486: 
                    487:        char localname[PNAMSIZ+1];
                    488: 
                    489:        XATTR xattr;
                    490: 
                    491: 
                    492: 
                    493:        switch(mode) {
                    494: 
                    495:        case 0:
                    496: 
                    497:                mkwait = 1;             /* fall through */
                    498: 
                    499:        case 100:
                    500: 
                    501:                mkload = mkgo = mkfree = 1;
                    502: 
                    503:                mkname = 1;
                    504: 
                    505:                TRACE("Pexec(%d,%s,\"%s\")", mode, ptr1, ptr2);
                    506: 
                    507:                break;
                    508: 
                    509:        case 200:                       /* overlay current process */
                    510: 
                    511:                mkload = mkgo = 1;
                    512: 
                    513:                overlay = mkname = 1;
                    514: 
                    515:                TRACE("Pexec(%d,%s,\"%s\")", mode, ptr1, ptr2);
                    516: 
                    517:                break;
                    518: 
                    519:        case 3:
                    520: 
                    521:                mkload = 1;
                    522: 
                    523:                TRACE("Pexec(%d,%s,\"%s\")", mode, ptr1, ptr2);
                    524: 
                    525:                break;
                    526: 
                    527:        case 6:
                    528: 
                    529:                mkfree = 1;
                    530: 
                    531:                /* fall through */
                    532: 
                    533:        case 4:
                    534: 
                    535:                mkwait = mkgo = 1;
                    536: 
                    537:                TRACE("Pexec(%d,%lx)", mode, ptr2);
                    538: 
                    539:                break;
                    540: 
                    541:        case 106:
                    542: 
                    543:                mkfree = 1;             /* fall through */
                    544: 
                    545:        case 104:
                    546: 
                    547:                thread = (mode == 104);
                    548: 
                    549:                mkgo = 1;
                    550: 
                    551:                mkname = (ptr1 != 0);
                    552: 
                    553:                TRACE("Pexec(%d,%s,%lx)", mode, ptr1, ptr2);
                    554: 
                    555:                break;
                    556: 
                    557:        case 7:
                    558: 
                    559:                flags = (long)ptr1;     /* set program flags */
                    560: 
                    561:                                        /* and fall through */
                    562: 
                    563:        case 5:
                    564: 
                    565:                mkbase = 1;
                    566: 
                    567:                TRACE("Pexec(%d,%lx,\"%s\")", mode, ptr1, ptr2);
                    568: 
                    569:                break;
                    570: 
                    571:        default:
                    572: 
                    573:                DEBUG("Pexec: bad mode %d", mode);
                    574: 
                    575:                return EINVFN;
                    576: 
                    577:        }
                    578: 
                    579: 
                    580: 
                    581: /* in most cases, we'll want a process struct to exist,
                    582: 
                    583:  * so make sure one is around. Note that we must be
                    584: 
                    585:  * careful to free it later!
                    586: 
                    587:  */
                    588: 
                    589: 
                    590: 
                    591:        p = 0;
                    592: 
                    593:        if (!overlay) {
                    594: 
                    595:                p = new_proc();
                    596: 
                    597:                if (!p) {
                    598: 
                    599:                        DEBUG("Pexec: couldn't get a PROC struct");
                    600: 
                    601:                        return ENSMEM;
                    602: 
                    603:                }
                    604: 
                    605:        }
                    606: 
                    607: 
                    608: 
                    609: 
                    610: 
                    611:        if (mkload || mkbase) {
                    612: 
                    613:                env = create_env((char *)ptr3);
                    614: 
                    615:                if (!env) {
                    616: 
                    617:                        DEBUG("Pexec: unable to create environment");
                    618: 
                    619:                        if (p) dispose_proc(p);
                    620: 
                    621:                        return ENSMEM;
                    622: 
                    623:                }
                    624: 
                    625:        }
                    626: 
                    627: 
                    628: 
                    629:        if (mkbase) {
                    630: 
                    631:                base = create_base((char *)ptr2, env, flags, 0L);
                    632: 
                    633:                if (!base) {
                    634: 
                    635:                        DEBUG("Pexec: unable to create basepage");
                    636: 
                    637:                        detach_region(curproc, env);
                    638: 
                    639:                        if (p) dispose_proc(p);
                    640: 
                    641:                        return ENSMEM;
                    642: 
                    643:                }
                    644: 
                    645:        }
                    646: 
                    647:        else if (mkload) {
                    648: 
                    649:                base = load_region((char *)ptr1, env, (char *)ptr2, &xattr);
                    650: 
                    651:                if (!base) {
                    652: 
                    653:                        DEBUG("Pexec: load_region failed");
                    654: 
                    655:                        detach_region(curproc, env);
                    656: 
                    657:                        if (p) dispose_proc(p);
                    658: 
                    659:                        return mint_errno;
                    660: 
                    661:                }
                    662: 
                    663:        }
                    664: 
                    665:        else {  /* mode == 4 or 6 or 104 or 106 -- just go */
                    666: 
                    667:                base = addr2mem((virtaddr)ptr2);
                    668: 
                    669:                if (base)
                    670: 
                    671:                        env = addr2mem(*(void **)(base->loc + 0x2c));
                    672: 
                    673:                else
                    674: 
                    675:                        env = 0;
                    676: 
                    677:                if (!env) {
                    678: 
                    679:                        if (p) dispose_proc(p);
                    680: 
                    681:                        return EIMBA;
                    682: 
                    683:                }
                    684: 
                    685:        }
                    686: 
                    687: 
                    688: 
                    689: /* make a local copy of the name, in case we are overlaying the current
                    690: 
                    691:  * process
                    692: 
                    693:  */
                    694: 
                    695:        if (mkname) {
                    696: 
                    697:                lastslash = 0;
                    698: 
                    699:                newname = ptr1;
                    700: 
                    701:                while (*newname) {
                    702: 
                    703:                        if (*newname == '\\' || *newname == '/')
                    704: 
                    705:                                lastslash = newname;
                    706: 
                    707:                        ++newname;
                    708: 
                    709:                }
                    710: 
                    711:                if (!lastslash)
                    712: 
                    713:                        lastslash = ptr1;
                    714: 
                    715:                else
                    716: 
                    717:                        lastslash++;
                    718: 
                    719: 
                    720: 
                    721:                i = 0; newname = localname;
                    722: 
                    723:                while (i++ < PNAMSIZ) {
                    724: 
                    725:                        if (*lastslash == '.' || *lastslash == 0) {
                    726: 
                    727:                                *newname = 0; break;
                    728: 
                    729:                        }
                    730: 
                    731:                        else
                    732: 
                    733:                                *newname++ = *lastslash++;
                    734: 
                    735:                }
                    736: 
                    737:                *newname = 0;
                    738: 
                    739:        }
                    740: 
                    741: 
                    742: 
                    743:        if (p) {
                    744: 
                    745:        /* free the PROC struct so fork_proc will succeed */
                    746: 
                    747:                dispose_proc(p);
                    748: 
                    749:                p = 0;
                    750: 
                    751:        }
                    752: 
                    753: 
                    754: 
                    755:        if (mkgo) {
                    756: 
                    757:                BASEPAGE *b;
                    758: 
                    759: 
                    760: 
                    761:                if (overlay) {
                    762: 
                    763:                        p = curproc;
                    764: 
                    765:                /* make sure that exec_region doesn't free the base and env */
                    766: 
                    767:                        base->links++;
                    768: 
                    769:                        env->links++;
                    770: 
                    771:                }
                    772: 
                    773:                else {
                    774: 
                    775:                        p = fork_proc();
                    776: 
                    777:                }
                    778: 
                    779:                if (!p) {
                    780: 
                    781:                        if (mkbase) {
                    782: 
                    783:                                detach_region(curproc, base);
                    784: 
                    785:                                detach_region(curproc, env);
                    786: 
                    787:                        }
                    788: 
                    789:                        return mint_errno;
                    790: 
                    791:                }
                    792: 
                    793: 
                    794: 
                    795:                if (mkload && mkgo) {           /* setuid/setgid is OK */
                    796: 
                    797:                        if (xattr.mode & S_ISUID)
                    798: 
                    799:                                p->euid = xattr.uid;
                    800: 
                    801:                        if (xattr.mode & S_ISGID)
                    802: 
                    803:                                p->egid = xattr.gid;
                    804: 
                    805:                }
                    806: 
                    807:                (void)exec_region(p, base, thread);
                    808: 
                    809:                attach_region(p, env);
                    810: 
                    811:                attach_region(p, base);
                    812: 
                    813: 
                    814: 
                    815:        /* tell the child who the parent was */
                    816: 
                    817:                b = (BASEPAGE *)base->loc;
                    818: 
                    819:                if (!overlay)
                    820: 
                    821:                        b->p_parent = (BASEPAGE *)curproc->base;
                    822: 
                    823: 
                    824: 
                    825:                if (mkname) {
                    826: 
                    827:        /* interesting coincidence -- if a process needs a name, it usually
                    828: 
                    829:         * needs to have its domain reset to DOM_TOS. Doing it this way
                    830: 
                    831:         * (instead of doing it in exec_region) means that Pexec(4,...)
                    832: 
                    833:         * can be used to create new threads of execution which retain
                    834: 
                    835:         * the same domain.
                    836: 
                    837:         */
                    838: 
                    839:                        if (!thread)
                    840: 
                    841:                                p->domain = DOM_TOS;
                    842: 
                    843: 
                    844: 
                    845:        /* put in the new process name we saved above */
                    846: 
                    847:                        strcpy(p->name, localname);
                    848: 
                    849:                }
                    850: 
                    851: 
                    852: 
                    853:        /* set the time/date stamp of u:\proc */
                    854: 
                    855:                proctime = timestamp;
                    856: 
                    857:                procdate = datestamp;
                    858: 
                    859: 
                    860: 
                    861:                if (overlay) {
                    862: 
                    863:                        /* correct for temporary increase in links (see above) */
                    864: 
                    865:                        base->links--;
                    866: 
                    867:                        env->links--;
                    868: 
                    869:                        /* let our parent run, if it Vfork'd() */
                    870: 
                    871:                        if ( (p = pid2proc(curproc->ppid)) != 0 ) {
                    872: 
                    873:                                if (p->wait_q == WAIT_Q && 
                    874: 
                    875:                                    p->wait_cond == (long)curproc) {
                    876: 
                    877:                                        rm_q(WAIT_Q, p);
                    878: 
                    879:                                        add_q(READY_Q, p);
                    880: 
                    881:                                }
                    882: 
                    883:                        }
                    884: 
                    885: 
                    886: 
                    887:                /* OK, let's run our new code */
                    888: 
                    889:                /* we guarantee ourselves at least 2 timeslices to do an Mshrink */
                    890: 
                    891:                        assert(curproc->magic == CTXT_MAGIC);
                    892: 
                    893:                        fresh_slices(2);
                    894: 
                    895:                        leave_kernel();
                    896: 
                    897:                        restore_context(&(curproc->ctxt[CURRENT]));
                    898: 
                    899:                }
                    900: 
                    901:                else {
                    902: 
                    903:        /* we want this process to run ASAP */
                    904: 
                    905:        /* so we temporarily give it high priority and put it first on the
                    906: 
                    907:         * run queue
                    908: 
                    909:         */
                    910: 
                    911:                        run_next(p, 2);
                    912: 
                    913:                }
                    914: 
                    915:        }
                    916: 
                    917: 
                    918: 
                    919:        if (mkfree) {
                    920: 
                    921:                detach_region(curproc, base);
                    922: 
                    923:                detach_region(curproc, env);
                    924: 
                    925:        }
                    926: 
                    927: 
                    928: 
                    929:        if (mkwait) {
                    930: 
                    931:                long oldsigint, oldsigquit;
                    932: 
                    933: 
                    934: 
                    935:                oldsigint = curproc->sighandle[SIGINT];
                    936: 
                    937:                oldsigquit = curproc->sighandle[SIGQUIT];
                    938: 
                    939:                curproc->sighandle[SIGINT] =
                    940: 
                    941:                         curproc->sighandle[SIGQUIT] = SIG_IGN;
                    942: 
                    943: 
                    944: 
                    945:                i = p->pid;
                    946: 
                    947:                for(;;) {
                    948: 
                    949:                        r = p_wait3(0, (long *)0);
                    950: 
                    951:                        if (r < 0) {
                    952: 
                    953:                                ALERT("p_exec: wait error");
                    954: 
                    955:                                return EINTRN;
                    956: 
                    957:                        }
                    958: 
                    959:                        if ( i == ((r&0xffff0000) >> 16) ) {
                    960: 
                    961:                                TRACE("leaving Pexec with child return code");
                    962: 
                    963:                                r = r & 0x0000ffff;
                    964: 
                    965:                                break;
                    966: 
                    967:                        }
                    968: 
                    969:                        if (curproc->pid)
                    970: 
                    971:                                DEBUG("Pexec: wrong child found");
                    972: 
                    973:                }
                    974: 
                    975:                curproc->sighandle[SIGINT] = oldsigint;
                    976: 
                    977:                curproc->sighandle[SIGQUIT] = oldsigquit;
                    978: 
                    979:                return r;
                    980: 
                    981:        }
                    982: 
                    983:        else if (mkgo) {
                    984: 
                    985:                yield();        /* let the new process run */
                    986: 
                    987:                return p->pid;
                    988: 
                    989:        } else {
                    990: 
                    991:                TRACE("leaving Pexec with basepage address %lx", base->loc);
                    992: 
                    993:                return base->loc;
                    994: 
                    995:        }
                    996: 
                    997: }
                    998: 
                    999: 
                   1000: 
                   1001: /*
                   1002: 
                   1003:  * terminate a process, with return code "code". If que == ZOMBIE_Q, free
                   1004: 
                   1005:  * all resources attached to the child; if que == TSR_Q, free everything
                   1006: 
                   1007:  * but memory
                   1008: 
                   1009:  */
                   1010: 
                   1011: 
                   1012: 
                   1013: long
                   1014: 
                   1015: terminate(code, que)
                   1016: 
                   1017:        int code, que;
                   1018: 
                   1019: {
                   1020: 
                   1021:        extern PROC *dlockproc[];       /* in dosdir.c */
                   1022: 
                   1023:        PROC *p;
                   1024: 
                   1025:        FILEPTR *fp;
                   1026: 
                   1027:        MEMREGION *m;
                   1028: 
                   1029:        int  i, wakemint = 0;
                   1030: 
                   1031:        extern short bconbsiz;  /* in bios.c */
                   1032: 
                   1033: 
                   1034: 
                   1035:        if (bconbsiz)
                   1036: 
                   1037:                (void) bflush();
                   1038: 
                   1039: 
                   1040: 
                   1041:        assert(que == ZOMBIE_Q || que == TSR_Q);
                   1042: 
                   1043: 
                   1044: 
                   1045:        if (curproc->pid == 0) {
                   1046: 
                   1047:                FATAL("attempt to terminate MiNT");
                   1048: 
                   1049:        }
                   1050: 
                   1051: 
                   1052: 
                   1053: /* cancel all pending timeouts for this process */
                   1054: 
                   1055:        cancelalltimeouts();
                   1056: 
                   1057: /* cancel alarm clock */
                   1058: 
                   1059:        curproc->alarmtim = 0;
                   1060: 
                   1061: 
                   1062: 
                   1063: /* release any drives locked by Dlock */
                   1064: 
                   1065:        for(i = 0; i < NUM_DRIVES; i++) {
                   1066: 
                   1067:                if (dlockproc[i] == curproc) {
                   1068: 
                   1069:                        dlockproc[i] = 0;
                   1070: 
                   1071:                        changedrv(i);
                   1072: 
                   1073:                }
                   1074: 
                   1075:        }
                   1076: 
                   1077: 
                   1078: 
                   1079: /* release the controlling terminal, if we're a process group leader */
                   1080: 
                   1081:        fp = curproc->handle[-1];
                   1082: 
                   1083:        if (fp && is_terminal(fp) && curproc->pgrp == curproc->pid) {
                   1084: 
                   1085:                struct tty *tty = (struct tty *)fp->devinfo;
                   1086: 
                   1087:                if (curproc->pgrp == tty->pgrp)
                   1088: 
                   1089:                        tty->pgrp = 0;
                   1090: 
                   1091:        }
                   1092: 
                   1093: 
                   1094: 
                   1095: /* close all files */
                   1096: 
                   1097:        for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
                   1098: 
                   1099:                if ((fp = curproc->handle[i]))
                   1100: 
                   1101:                        do_close(fp);
                   1102: 
                   1103:                curproc->handle[i] = 0;
                   1104: 
                   1105:        }
                   1106: 
                   1107: 
                   1108: 
                   1109: /* close any unresolved Fsfirst/Fsnext directory searches */
                   1110: 
                   1111:        for (i = 0; i < NUM_SEARCH; i++) {
                   1112: 
                   1113:                if (curproc->srchdta[i]) {
                   1114: 
                   1115:                        DIR *dirh = &curproc->srchdir[i];
                   1116: 
                   1117:                        (*dirh->fc.fs->closedir)(dirh);
                   1118: 
                   1119:                }
                   1120: 
                   1121:        }
                   1122: 
                   1123: 
                   1124: 
                   1125: /* release all semaphores owned by this process */
                   1126: 
                   1127:        free_semaphores(curproc->pid);
                   1128: 
                   1129: 
                   1130: 
                   1131: /* free all memory */
                   1132: 
                   1133:        if (que == ZOMBIE_Q) {
                   1134: 
                   1135:                for (i = curproc->num_reg - 1; i >=0; i--) {
                   1136: 
                   1137:                        m = curproc->mem[i];
                   1138: 
                   1139:                        curproc->mem[i] = 0; curproc->addr[i] = 0;
                   1140: 
                   1141:                        if (m) {
                   1142: 
                   1143:                /* don't free specially allocated memory */
                   1144: 
                   1145:                                if (m->mflags & M_KEEP) {
                   1146: 
                   1147:                                        if (curproc != rootproc)
                   1148: 
                   1149:                                            attach_region(rootproc, m);
                   1150: 
                   1151:                                }
                   1152: 
                   1153:                                m->links--;
                   1154: 
                   1155:                                if (m->links == 0) {
                   1156: 
                   1157:                                        free_region(m);
                   1158: 
                   1159:                                }
                   1160: 
                   1161:                        }
                   1162: 
                   1163:                }
                   1164: 
                   1165:                kfree(curproc->mem); kfree(curproc->addr);
                   1166: 
                   1167:                curproc->mem = 0;
                   1168: 
                   1169:                curproc->addr = 0;
                   1170: 
                   1171:                curproc->num_reg = 0;
                   1172: 
                   1173:        }
                   1174: 
                   1175: /*     else
                   1176: 
                   1177:                 make TSR process non-swappable */
                   1178: 
                   1179: 
                   1180: 
                   1181: /*
                   1182: 
                   1183:  * make sure that any open files that refer to this process are
                   1184: 
                   1185:  * closed
                   1186: 
                   1187:  */
                   1188: 
                   1189:        changedrv(PROC_BASE_DEV | curproc->pid);
                   1190: 
                   1191: 
                   1192: 
                   1193: /* find our parent (if parent not found, then use process 0 as parent
                   1194: 
                   1195:  * since that process is constantly in a wait loop)
                   1196: 
                   1197:  */
                   1198: 
                   1199: 
                   1200: 
                   1201:        p = pid2proc(curproc->ppid);
                   1202: 
                   1203:        if (!p) {
                   1204: 
                   1205:                TRACE("terminate: parent not found");
                   1206: 
                   1207:                p = pid2proc(0);
                   1208: 
                   1209:        }
                   1210: 
                   1211: 
                   1212: 
                   1213: /* NOTE: normally just post_sig is sufficient for sending a signal; but
                   1214: 
                   1215:  * in this particular case, we have to worry about processes that are
                   1216: 
                   1217:  * blocking all signals because they Vfork'd and are waiting for us to
                   1218: 
                   1219:  * finish (which is indicated by a wait_cond matching our PROC
                   1220: 
                   1221:  * structure), and also processes that are ignoring SIGCHLD but are
                   1222: 
                   1223:  * waiting for us.
                   1224: 
                   1225:  */
                   1226: 
                   1227:        if (p->wait_q == WAIT_Q && 
                   1228: 
                   1229:            (p->wait_cond == (long)curproc || p->wait_cond == (long)&p_wait3) ) {
                   1230: 
                   1231:                TRACE("terminate: waking up parent");
                   1232: 
                   1233:                rm_q(WAIT_Q, p);
                   1234: 
                   1235:                add_q(READY_Q, p);
                   1236: 
                   1237:        }
                   1238: 
                   1239:        post_sig(p, SIGCHLD);           /* inform of process termination */
                   1240: 
                   1241: 
                   1242: 
                   1243: /* find our children, and orphan them */
                   1244: 
                   1245:        i = curproc->pid;
                   1246: 
                   1247:        for (p = proclist; p; p = p->gl_next) {
                   1248: 
                   1249:                if (p->ppid == i) {
                   1250: 
                   1251:                        p->ppid = 0;    /* have the system adopt it */
                   1252: 
                   1253:                        if (p->wait_q == ZOMBIE_Q) 
                   1254: 
                   1255:                                wakemint = 1;   /* we need to wake proc. 0 */
                   1256: 
                   1257:                }
                   1258: 
                   1259:        }
                   1260: 
                   1261: 
                   1262: 
                   1263:        if (wakemint) {
                   1264: 
                   1265:                p = rootproc;           /* pid 0 */
                   1266: 
                   1267:                if (p->wait_q == WAIT_Q) {
                   1268: 
                   1269:                        rm_q(WAIT_Q, p);
                   1270: 
                   1271:                        add_q(READY_Q, p);
                   1272: 
                   1273:                }
                   1274: 
                   1275:        }
                   1276: 
                   1277: 
                   1278: 
                   1279: /* this makes sure that our children are inherited by the system;
                   1280: 
                   1281:  * plus, it may help avoid problems if somehow a signal gets
                   1282: 
                   1283:  * through to us
                   1284: 
                   1285:  */
                   1286: 
                   1287:        for(i = 0; i < NSIG; i++)
                   1288: 
                   1289:                curproc->sighandle[i] = SIG_IGN;
                   1290: 
                   1291: 
                   1292: 
                   1293: /* finally, reset the time/date stamp for u:\proc */
                   1294: 
                   1295:        proctime = timestamp;
                   1296: 
                   1297:        procdate = datestamp;
                   1298: 
                   1299: 
                   1300: 
                   1301:        for(;;) {
                   1302: 
                   1303:                sleep(que, (long)(unsigned)code);
                   1304: 
                   1305: /* we shouldn't ever get here */
                   1306: 
                   1307:                FATAL("terminate: sleep woke up when it shouldn't have");
                   1308: 
                   1309:        }
                   1310: 
                   1311:        return 0;       /* fake */
                   1312: 
                   1313: }
                   1314: 
                   1315: 
                   1316: 
                   1317: /*
                   1318: 
                   1319:  * TOS process termination entry points:
                   1320: 
                   1321:  * p_term terminates the process with extreme prejuidice
                   1322: 
                   1323:  * p_termres lets the process hang around resident in memory, after
                   1324: 
                   1325:  * shrinking its transient program area to "save" bytes
                   1326: 
                   1327:  */
                   1328: 
                   1329: 
                   1330: 
                   1331: long
                   1332: 
                   1333: p_term(code)
                   1334: 
                   1335:        int code;
                   1336: 
                   1337: {
                   1338: 
                   1339:        CONTEXT *syscall;
                   1340: 
                   1341: 
                   1342: 
                   1343:        TRACE("Pterm(%d)", code);
                   1344: 
                   1345: /* call the process termination vector */
                   1346: 
                   1347:        syscall = &curproc->ctxt[SYSCALL];
                   1348: 
                   1349: 
                   1350: 
                   1351:        if (syscall->term_vec != (long)rts) {
                   1352: 
                   1353:                TRACE("term_vec: user has something to do");
                   1354: 
                   1355: /*
                   1356: 
                   1357:  * we handle the termination vector just like Supexec(), by
                   1358: 
                   1359:  * sending signal 0 to the process. See supexec() in xbios.c for details.
                   1360: 
                   1361:  * Note that we _always_ want to unwind the signal stack, hence the
                   1362: 
                   1363:  * curproc->sigmask setting here.
                   1364: 
                   1365:  */
                   1366: 
                   1367:                curproc->sigmask |= 1L;
                   1368: 
                   1369:                (void)supexec((Func)syscall->term_vec, 0L, 0L, 0L, 0L, 
                   1370: 
                   1371:                                (long)code);
                   1372: 
                   1373: /*
                   1374: 
                   1375:  * if we arrive here, continue with the termination...
                   1376: 
                   1377:  */
                   1378: 
                   1379:        }
                   1380: 
                   1381:        return terminate(code, ZOMBIE_Q);
                   1382: 
                   1383: }
                   1384: 
                   1385: 
                   1386: 
                   1387: long
                   1388: 
                   1389: p_term0()
                   1390: 
                   1391: {
                   1392: 
                   1393:        return p_term(0);
                   1394: 
                   1395: }
                   1396: 
                   1397: 
                   1398: 
                   1399: long
                   1400: 
                   1401: p_termres(save, code)
                   1402: 
                   1403:        long save;
                   1404: 
                   1405:        int code;
                   1406: 
                   1407: {
                   1408: 
                   1409:        MEMREGION *m;
                   1410: 
                   1411: 
                   1412: 
                   1413:        TRACE("Ptermres(%ld, %d)", save, code);
                   1414: 
                   1415:        m = curproc->mem[1];    /* should be the basepage (0 is env.) */
                   1416: 
                   1417:        if (m) {
                   1418: 
                   1419:                (void)shrink_region(m, save);
                   1420: 
                   1421:        }
                   1422: 
                   1423:        return terminate(code, TSR_Q);
                   1424: 
                   1425: }
                   1426: 
                   1427: 
                   1428: 
                   1429: /*
                   1430: 
                   1431:  * routine for waiting for children to die. Return has the pid of the
                   1432: 
                   1433:  * found child in the high word, and the child's exit code in
                   1434: 
                   1435:  * the low word. If no children exist, return "File Not Found".
                   1436: 
                   1437:  * If (nohang & 1) is nonzero, then return a 0 immediately if we have
                   1438: 
                   1439:  * no dead children but some living ones that we still have to wait
                   1440: 
                   1441:  * for. If (nohang & 2) is nonzero, then we return any stopped
                   1442: 
                   1443:  * children; otherwise, only children that have exited or are stopped
                   1444: 
                   1445:  * due to a trace trap are returned.
                   1446: 
                   1447:  * If "rusage" is non-zero and a child is found, put the child's
                   1448: 
                   1449:  * resource usage into it (currently only the user and system time are
                   1450: 
                   1451:  * sent back) 
                   1452: 
                   1453:  */
                   1454: 
                   1455: 
                   1456: 
                   1457: long
                   1458: 
                   1459: p_wait3(nohang, rusage)
                   1460: 
                   1461:        int nohang;
                   1462: 
                   1463:        long *rusage;
                   1464: 
                   1465: {
                   1466: 
                   1467:        long r;
                   1468: 
                   1469:        PROC *p, *q;
                   1470: 
                   1471:        int ourpid;
                   1472: 
                   1473:        int found;
                   1474: 
                   1475: 
                   1476: 
                   1477:        TRACE("Pwait3");
                   1478: 
                   1479:        ourpid = curproc->pid;
                   1480: 
                   1481: 
                   1482: 
                   1483: /* if there are terminated children, clean up and return their info;
                   1484: 
                   1485:  * if there are children, but still running, wait for them;
                   1486: 
                   1487:  * if there are no children, return an error
                   1488: 
                   1489:  */
                   1490: 
                   1491: 
                   1492: 
                   1493:        do {
                   1494: 
                   1495: /* look for any children */
                   1496: 
                   1497:                found = 0;
                   1498: 
                   1499:                for (p = proclist; p; p = p->gl_next) {
                   1500: 
                   1501:                        if (p->ppid == ourpid) {
                   1502: 
                   1503:                                found++;
                   1504: 
                   1505:                                if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q)
                   1506: 
                   1507:                                        break;
                   1508: 
                   1509: 
                   1510: 
                   1511: /* p->wait_cond == 0 if a stopped process has already been waited for */
                   1512: 
                   1513:                                if (p->wait_q == STOP_Q && p->wait_cond) {
                   1514: 
                   1515:                                    if ((nohang & 2) ||
                   1516: 
                   1517:                                        ((p->wait_cond&0x1f00) == SIGTRAP<<8))
                   1518: 
                   1519:                                            break;
                   1520: 
                   1521:                                }
                   1522: 
                   1523:                        }
                   1524: 
                   1525:                }
                   1526: 
                   1527:                if (!p) {
                   1528: 
                   1529:                        if (found) {
                   1530: 
                   1531:                                if (nohang & 1)
                   1532: 
                   1533:                                        return 0;
                   1534: 
                   1535:                                if (curproc->pid)
                   1536: 
                   1537:                                        TRACE("Pwait3: going to sleep");
                   1538: 
                   1539:                                sleep(WAIT_Q, (long)&p_wait3);
                   1540: 
                   1541:                        }
                   1542: 
                   1543:                        else {
                   1544: 
                   1545:                                DEBUG("Pwait3: no children found");
                   1546: 
                   1547:                                return EFILNF;
                   1548: 
                   1549:                        }
                   1550: 
                   1551:                }
                   1552: 
                   1553:        } while (!p);
                   1554: 
                   1555: 
                   1556: 
                   1557: /* OK, we've found our child */
                   1558: 
                   1559: /* calculate the return code from the child's exit code and pid */
                   1560: 
                   1561:        r = (((unsigned long)p->pid) << 16) | (p->wait_cond & 0x0000ffff);
                   1562: 
                   1563: 
                   1564: 
                   1565: /* check resource usage */
                   1566: 
                   1567:        if (rusage) {
                   1568: 
                   1569:                *rusage++ = p->usrtime;
                   1570: 
                   1571:                *rusage++ = p->systime;
                   1572: 
                   1573:        }
                   1574: 
                   1575: 
                   1576: 
                   1577: /* add child's resource usage to parent's */
                   1578: 
                   1579:        if (p->wait_q == TSR_Q || p->wait_q == ZOMBIE_Q) {
                   1580: 
                   1581:                curproc->chldstime += p->systime;
                   1582: 
                   1583:                curproc->chldutime += p->usrtime;
                   1584: 
                   1585:        }
                   1586: 
                   1587: 
                   1588: 
                   1589: /* if it was a TSR, mark it as having been found and return */
                   1590: 
                   1591:        if (p->wait_q == TSR_Q) {
                   1592: 
                   1593:                p->ppid = -1;
                   1594: 
                   1595:                return r;
                   1596: 
                   1597:        }
                   1598: 
                   1599: 
                   1600: 
                   1601: /* if it was stopped, mark it as having been found and again return */
                   1602: 
                   1603:        if (p->wait_q == STOP_Q) {
                   1604: 
                   1605:                p->wait_cond = 0;
                   1606: 
                   1607:                return r;
                   1608: 
                   1609:        }
                   1610: 
                   1611: 
                   1612: 
                   1613: /* it better have been on the ZOMBIE queue from here on in... */
                   1614: 
                   1615:        assert(p->wait_q == ZOMBIE_Q);
                   1616: 
                   1617:        assert(p != curproc);
                   1618: 
                   1619: 
                   1620: 
                   1621: /* take the child off both the global and ZOMBIE lists */
                   1622: 
                   1623:        rm_q(ZOMBIE_Q, p);
                   1624: 
                   1625: 
                   1626: 
                   1627:        if (proclist == p) {
                   1628: 
                   1629:                proclist = p->gl_next;
                   1630: 
                   1631:                p->gl_next = 0;
                   1632: 
                   1633:        }
                   1634: 
                   1635:        else {
                   1636: 
                   1637:                q = proclist;
                   1638: 
                   1639:                while(q && q->gl_next != p)
                   1640: 
                   1641:                        q = q->gl_next;
                   1642: 
                   1643:                assert(q);
                   1644: 
                   1645:                q->gl_next = p->gl_next;
                   1646: 
                   1647:                p->gl_next = 0;
                   1648: 
                   1649:        }
                   1650: 
                   1651: 
                   1652: 
                   1653:        dispose_proc(p);        /* free the PROC structure */
                   1654: 
                   1655: 
                   1656: 
                   1657:        return r;
                   1658: 
                   1659: }
                   1660: 
                   1661: 
                   1662: 
                   1663: /* p_wait: block until a child has exited, and don't worry about
                   1664: 
                   1665:    resource stats. this is provided as a convenience, and to maintain
                   1666: 
                   1667:    compatibility with existing binaries (yes, I'm lazy...). we could
                   1668: 
                   1669:    make do with Pwait3().
                   1670: 
                   1671:  */
                   1672: 
                   1673: 
                   1674: 
                   1675: long
                   1676: 
                   1677: p_wait()
                   1678: 
                   1679: {
                   1680: 
                   1681:        return p_wait3(2, (long *)0);
                   1682: 
                   1683: }
                   1684: 
                   1685: 
                   1686: 
                   1687: /*
                   1688: 
                   1689:  * do_vfork(save): create a duplicate of  the current process. This is
                   1690: 
                   1691:  * essentially a vfork() algorithm, except that if (save == 1) the
                   1692: 
                   1693:  * parent's address space is saved, and then restored when the process
                   1694: 
                   1695:  * is made runnable again. The parent is suspended until either the child
                   1696: 
                   1697:  * process (the duplicate) exits or does a Pexec which overlays its
                   1698: 
                   1699:  * memory space.
                   1700: 
                   1701:  *
                   1702: 
                   1703:  * "txtsize" is the size of the process' TEXT area, if it has a valid one;
                   1704: 
                   1705:  * this is part of the second memory region attached (the basepage one)
                   1706: 
                   1707:  * and need not be saved (we assume processes don't write on their own
                   1708: 
                   1709:  * code segment)
                   1710: 
                   1711:  */
                   1712: 
                   1713: 
                   1714: 
                   1715: static long
                   1716: 
                   1717: do_vfork(save)
                   1718: 
                   1719:        int save;
                   1720: 
                   1721: {
                   1722: 
                   1723:        PROC *p;
                   1724: 
                   1725:        long sigmask;
                   1726: 
                   1727:        MEMREGION *m, *savemem = 0;
                   1728: 
                   1729:        long savesize, txtsize;
                   1730: 
                   1731:        int i;
                   1732: 
                   1733:        char *saveplace;
                   1734: 
                   1735: 
                   1736: 
                   1737:        p = fork_proc();
                   1738: 
                   1739:        if (!p) {
                   1740: 
                   1741:                DEBUG("do_vfork: couldn't get new PROC struct");
                   1742: 
                   1743:                return mint_errno;
                   1744: 
                   1745:        }
                   1746: 
                   1747: /* set u:\proc time+date */
                   1748: 
                   1749:        proctime = timestamp;
                   1750: 
                   1751:        procdate = datestamp;
                   1752: 
                   1753: 
                   1754: 
                   1755: /*
                   1756: 
                   1757:  * maybe save the parent's address space
                   1758: 
                   1759:  */
                   1760: 
                   1761:        txtsize = p->txtsize;
                   1762: 
                   1763: 
                   1764: 
                   1765:        if (save) {
                   1766: 
                   1767:                TRACE("do_vfork: saving parent");
                   1768: 
                   1769:                savesize = memused(curproc) - txtsize;
                   1770: 
                   1771:                assert(savesize >= 0);
                   1772: 
                   1773: 
                   1774: 
                   1775:                saveplace = (char *)alloc_region(alt, savesize);
                   1776: 
                   1777:                if (!saveplace)
                   1778: 
                   1779:                        saveplace = (char *)alloc_region(core, savesize);
                   1780: 
                   1781: 
                   1782: 
                   1783:                if (!saveplace) {
                   1784: 
                   1785:                        DEBUG("do_vfork: can't save parent's memory");
                   1786: 
                   1787:                        p->ppid = 0;            /* abandon the child */
                   1788: 
                   1789:                        post_sig(p, SIGKILL);   /* then kill it */
                   1790: 
                   1791:                        p->ctxt[CURRENT].pc = (long)check_sigs;
                   1792: 
                   1793:                                /* just to make sure it dies */
                   1794: 
                   1795:                        p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
                   1796: 
                   1797:                        p->pri = MAX_NICE+1;
                   1798: 
                   1799:                        run_next(p, 1);
                   1800: 
                   1801:                        yield();
                   1802: 
                   1803:                        return ENSMEM;
                   1804: 
                   1805:                }
                   1806: 
                   1807:                savemem = addr2mem((virtaddr)saveplace);
                   1808: 
                   1809:                assert(savemem);
                   1810: 
                   1811:                for (i = 0; i < curproc->num_reg; i++) {
                   1812: 
                   1813:                        m = curproc->mem[i];
                   1814: 
                   1815:                        if (m && m != savemem) {
                   1816: 
                   1817:                                if (i != 1 || txtsize == 0) {
                   1818: 
                   1819:                                    quickmove(saveplace, (char *)m->loc, m->len);
                   1820: 
                   1821:                                    saveplace += m->len;
                   1822: 
                   1823:                                }
                   1824: 
                   1825:                                else {
                   1826: 
                   1827:                                    quickmove(saveplace, (char *)m->loc+txtsize,
                   1828: 
                   1829:                                        m->len - txtsize);
                   1830: 
                   1831:                                    saveplace += m->len - txtsize;
                   1832: 
                   1833:                                }
                   1834: 
                   1835:                        }
                   1836: 
                   1837:                }
                   1838: 
                   1839:        }
                   1840: 
                   1841:                                
                   1842: 
                   1843:        p->ctxt[CURRENT] = p->ctxt[SYSCALL];
                   1844: 
                   1845:        p->ctxt[CURRENT].regs[0] = 0;   /* child returns a 0 from call */
                   1846: 
                   1847:        p->ctxt[CURRENT].sr &= ~(0x2000); /* child must be in user mode */
                   1848: 
                   1849: #if 0          /* set up in fork_proc() */
                   1850: 
                   1851:        p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
                   1852: 
                   1853: #endif
                   1854: 
                   1855: 
                   1856: 
                   1857: /* watch out for job control signals, since our parent can never wake
                   1858: 
                   1859:  * up to respond to them. solution: block them; exec_region (in mem.c)
                   1860: 
                   1861:  * clears the signal mask, so an exec() will unblock them.
                   1862: 
                   1863:  */
                   1864: 
                   1865:        p->sigmask |= (1L << SIGTSTP) | (1L << SIGTTIN) | (1L << SIGTTOU);
                   1866: 
                   1867: 
                   1868: 
                   1869:        TRACE("do_vfork: parent going to sleep, wait_cond == %lx",
                   1870: 
                   1871:                (long)p);
                   1872: 
                   1873: 
                   1874: 
                   1875: /* WARNING: This sleep() must absolutely not wake up until the child
                   1876: 
                   1877:  * has released the memory space correctly. That's why we mask off
                   1878: 
                   1879:  * all signals.
                   1880: 
                   1881:  */
                   1882: 
                   1883:        sigmask = curproc->sigmask;
                   1884: 
                   1885:        curproc->sigmask = ~(1L << SIGKILL);
                   1886: 
                   1887: 
                   1888: 
                   1889:        add_q(READY_Q, p);              /* put it on the ready queue */
                   1890: 
                   1891:        sleep(WAIT_Q, (long)p);                 /* while we wait for it */
                   1892: 
                   1893:        TRACE("do_vfork: parent waking up");
                   1894: 
                   1895: 
                   1896: 
                   1897:        if (save) {
                   1898: 
                   1899:                TRACE("do_vfork: parent restoring memory");
                   1900: 
                   1901:                saveplace = (char *)savemem->loc;
                   1902: 
                   1903:                for (i = 0; i < curproc->num_reg; i++) {
                   1904: 
                   1905:                        m = curproc->mem[i];
                   1906: 
                   1907:                        if (m && (m != savemem)) {
                   1908: 
                   1909:                                if (i != 1 || txtsize == 0) {
                   1910: 
                   1911:                                    quickmove((char *)m->loc, saveplace, m->len);
                   1912: 
                   1913:                                    saveplace += m->len;
                   1914: 
                   1915:                                }
                   1916: 
                   1917:                                else {
                   1918: 
                   1919:                                    quickmove((char *)m->loc+txtsize, saveplace,
                   1920: 
                   1921:                                        m->len - txtsize);
                   1922: 
                   1923:                                    saveplace += m->len - txtsize;
                   1924: 
                   1925:                                }
                   1926: 
                   1927:                        }
                   1928: 
                   1929:                }
                   1930: 
                   1931:                detach_region(curproc, savemem);
                   1932: 
                   1933:        }
                   1934: 
                   1935:        curproc->sigmask = sigmask;
                   1936: 
                   1937:        check_sigs();   /* did we get any signals while sleeping? */
                   1938: 
                   1939:        return p->pid;
                   1940: 
                   1941: }
                   1942: 
                   1943: 
                   1944: 
                   1945: /*
                   1946: 
                   1947:  * here are the interfaces that the user sees. Pvfork() doesn't save
                   1948: 
                   1949:  * the child's address space; Pfork() does. Someday Pfork() should
                   1950: 
                   1951:  * allow asynchronous execution of both child and parent, but this
                   1952: 
                   1953:  * will do for now.
                   1954: 
                   1955:  */
                   1956: 
                   1957: 
                   1958: 
                   1959: long
                   1960: 
                   1961: p_vfork()
                   1962: 
                   1963: {
                   1964: 
                   1965:        return do_vfork(0);
                   1966: 
                   1967: }
                   1968: 
                   1969: 
                   1970: 
                   1971: long
                   1972: 
                   1973: p_fork()
                   1974: 
                   1975: {
                   1976: 
                   1977:        return do_vfork(1);
                   1978: 
                   1979: }
                   1980: 

unix.superglobalmegacorp.com

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