Annotation of MiNT/src/dosmem.c, revision 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.