Annotation of MiNT/src/mem.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:  * mem.c:: routines for managing memory regions
        !            12: 
        !            13:  */
        !            14: 
        !            15: 
        !            16: 
        !            17: #include "mint.h"
        !            18: 
        !            19: 
        !            20: 
        !            21: static long core_malloc P_((long, int));
        !            22: 
        !            23: 
        !            24: 
        !            25: /* macro for testing whether a memory region is free */
        !            26: 
        !            27: #define ISFREE(m) ((m)->links == 0)
        !            28: 
        !            29: 
        !            30: 
        !            31: /*
        !            32: 
        !            33:  * initialize memory routines
        !            34: 
        !            35:  */
        !            36: 
        !            37: 
        !            38: 
        !            39: /* initial number of memory regions */
        !            40: 
        !            41: #define NREGIONS 512
        !            42: 
        !            43: 
        !            44: 
        !            45: /* number of new regions to allocate when the initial ones are used up */
        !            46: 
        !            47: #define NEWREGIONS 256
        !            48: 
        !            49: 
        !            50: 
        !            51: static MEMREGION use_regions[NREGIONS+1];
        !            52: 
        !            53: MEMREGION *rfreelist;
        !            54: 
        !            55: 
        !            56: 
        !            57: void
        !            58: 
        !            59: init_mem()
        !            60: 
        !            61: {
        !            62: 
        !            63:        int i;
        !            64: 
        !            65: 
        !            66: 
        !            67:        use_regions[NREGIONS].next = 0;
        !            68: 
        !            69:        for (i = 0; i < NREGIONS; i++) {
        !            70: 
        !            71:                use_regions[i].next = &use_regions[i+1];
        !            72: 
        !            73:        }
        !            74: 
        !            75:        rfreelist = use_regions;
        !            76: 
        !            77: 
        !            78: 
        !            79:        init_core();
        !            80: 
        !            81:        init_swap();
        !            82: 
        !            83: }
        !            84: 
        !            85: 
        !            86: 
        !            87: /*
        !            88: 
        !            89:  * init_core(): initialize the core memory map (normal ST ram) and also
        !            90: 
        !            91:  * the alternate memory map (fast ram on the TT)
        !            92: 
        !            93:  */
        !            94: 
        !            95: 
        !            96: 
        !            97: static MEMREGION *_core_regions = 0, *_alt_regions = 0,
        !            98: 
        !            99:        *_ker_regions = 0;
        !           100: 
        !           101: 
        !           102: 
        !           103: MMAP core = &_core_regions;
        !           104: 
        !           105: MMAP alt = &_alt_regions;
        !           106: 
        !           107: MMAP ker = &_ker_regions;
        !           108: 
        !           109: 
        !           110: 
        !           111: /* note: add_region must adjust both the size and starting
        !           112: 
        !           113:  * address of the region being added so that memory is
        !           114: 
        !           115:  * always properly aligned
        !           116: 
        !           117:  */
        !           118: 
        !           119: 
        !           120: 
        !           121: int
        !           122: 
        !           123: add_region(map, place, size, mflags)
        !           124: 
        !           125:        MMAP map;
        !           126: 
        !           127:        ulong place, size;
        !           128: 
        !           129:        unsigned mflags;        /* initial flags for region */
        !           130: 
        !           131: {
        !           132: 
        !           133:        MEMREGION *m;
        !           134: 
        !           135:        ulong newplace;
        !           136: 
        !           137: 
        !           138: 
        !           139:        newplace = ROUND(place);
        !           140: 
        !           141:        size = (place + size) - newplace;
        !           142: 
        !           143:        size &= ~MASKBITS;
        !           144: 
        !           145:        if (size <= 0)          /* region too small to use */
        !           146: 
        !           147:                return 1;
        !           148: 
        !           149: 
        !           150: 
        !           151:        m = new_region();
        !           152: 
        !           153:        if (m == 0)
        !           154: 
        !           155:                return 0;       /* failure */
        !           156: 
        !           157:        m->links = 0;
        !           158: 
        !           159:        m->len = size;
        !           160: 
        !           161:        m->loc = newplace;
        !           162: 
        !           163:        m->next = *map;
        !           164: 
        !           165:        m->mflags = mflags;
        !           166: 
        !           167:        *map = m;
        !           168: 
        !           169:        return 1;       /* success */
        !           170: 
        !           171: }
        !           172: 
        !           173: 
        !           174: 
        !           175: static long
        !           176: 
        !           177: core_malloc(amt, mode)
        !           178: 
        !           179:        long amt;
        !           180: 
        !           181:        int mode;
        !           182: 
        !           183: {
        !           184: 
        !           185:        static int mxalloc = -1;        /* does GEMDOS know about Mxalloc? */
        !           186: 
        !           187:        long ret;
        !           188: 
        !           189: 
        !           190: 
        !           191:        if (mxalloc < 0) {
        !           192: 
        !           193:                ret = (long)Mxalloc(-1L, 0);
        !           194: 
        !           195:                if (ret == -32) mxalloc = 0;    /* unknown function */
        !           196: 
        !           197:                else if (ret >= 0) mxalloc = 1;
        !           198: 
        !           199:                else {
        !           200: 
        !           201:                        ALERT("GEMDOS returned %ld from Mxalloc", ret);
        !           202: 
        !           203:                        mxalloc = 0;
        !           204: 
        !           205:                }
        !           206: 
        !           207:        }
        !           208: 
        !           209:        if (mxalloc)
        !           210: 
        !           211:                return Mxalloc(amt, mode);
        !           212: 
        !           213:        else if (mode == 1)
        !           214: 
        !           215:                return 0L;
        !           216: 
        !           217:        else
        !           218: 
        !           219:                return Malloc(amt);
        !           220: 
        !           221: }
        !           222: 
        !           223: 
        !           224: 
        !           225: void
        !           226: 
        !           227: init_core()
        !           228: 
        !           229: {
        !           230: 
        !           231: #ifdef JUNK_MEM
        !           232: 
        !           233:        extern void fillwjunk();
        !           234: 
        !           235: #endif
        !           236: 
        !           237:        ulong size;
        !           238: 
        !           239:        ulong place;
        !           240: 
        !           241:        void *tossave;
        !           242: 
        !           243: 
        !           244: 
        !           245:        tossave = (void *)core_malloc((long)TOS_MEM, 0);
        !           246: 
        !           247:        if (!tossave) {
        !           248: 
        !           249:                FATAL("Not enough memory to run MiNT");
        !           250: 
        !           251:        }
        !           252: 
        !           253: 
        !           254: 
        !           255: /* initialize kernel memory */
        !           256: 
        !           257:        place = (ulong)core_malloc(KERNEL_MEM, 3);
        !           258: 
        !           259:        if (place != 0) {
        !           260: 
        !           261:                (void)add_region(ker, place, KERNEL_MEM, M_KER);
        !           262: 
        !           263: #ifdef JUNK_MEM
        !           264: 
        !           265:        fillwjunk(place, (long)KERNEL_MEM);
        !           266: 
        !           267: #endif
        !           268: 
        !           269:        }
        !           270: 
        !           271: 
        !           272: 
        !           273: /* initialize ST RAM */
        !           274: 
        !           275:        size = (ulong)core_malloc(-1L, 0);
        !           276: 
        !           277:        while (size > 0) {
        !           278: 
        !           279:                place = (ulong)core_malloc(size, 0);
        !           280: 
        !           281:                if (!add_region(core, place, size, M_CORE))
        !           282: 
        !           283:                        FATAL("init_mem: unable to add a region");
        !           284: 
        !           285: #ifdef JUNK_MEM
        !           286: 
        !           287:                fillwjunk(place, size);
        !           288: 
        !           289: #endif
        !           290: 
        !           291:                size = (ulong)core_malloc(-1L, 0);
        !           292: 
        !           293:        }
        !           294: 
        !           295: 
        !           296: 
        !           297: /* initialize alternate RAM */
        !           298: 
        !           299:        size = (ulong)core_malloc(-1L, 1);
        !           300: 
        !           301:        while (size > 0) {
        !           302: 
        !           303:                place = (ulong)core_malloc(size, 1);
        !           304: 
        !           305:                if (!add_region(alt, place, size, M_ALT))
        !           306: 
        !           307:                        FATAL("init_mem: unable to add a region");
        !           308: 
        !           309:                size = (ulong)core_malloc(-1L, 1);
        !           310: 
        !           311:        }
        !           312: 
        !           313: 
        !           314: 
        !           315:        (void)Mfree(tossave);           /* leave some memory for TOS to use */
        !           316: 
        !           317: }
        !           318: 
        !           319: 
        !           320: 
        !           321: /*
        !           322: 
        !           323:  * init_swap(): initialize the swap area; for now, this does nothing
        !           324: 
        !           325:  */
        !           326: 
        !           327: 
        !           328: 
        !           329: MEMREGION *_swap_regions = 0;
        !           330: 
        !           331: MMAP swap = &_swap_regions;
        !           332: 
        !           333: 
        !           334: 
        !           335: void
        !           336: 
        !           337: init_swap()
        !           338: 
        !           339: {
        !           340: 
        !           341: }
        !           342: 
        !           343: 
        !           344: 
        !           345: /*
        !           346: 
        !           347:  * routines for allocating/deallocating memory regions
        !           348: 
        !           349:  */
        !           350: 
        !           351: 
        !           352: 
        !           353: /*
        !           354: 
        !           355:  * new_region returns a new memory region descriptor, or NULL
        !           356: 
        !           357:  */
        !           358: 
        !           359: 
        !           360: 
        !           361: MEMREGION *
        !           362: 
        !           363: new_region()
        !           364: 
        !           365: {
        !           366: 
        !           367:        MEMREGION *m, *newfrees;
        !           368: 
        !           369:        int i;
        !           370: 
        !           371: 
        !           372: 
        !           373:        m = rfreelist;
        !           374: 
        !           375:        if (!m) {
        !           376: 
        !           377:                ALERT("new_region: ran out of free regions");
        !           378: 
        !           379:                return 0;
        !           380: 
        !           381:        }
        !           382: 
        !           383:        assert(ISFREE(m));
        !           384: 
        !           385:        rfreelist = m->next;
        !           386: 
        !           387:        m->next = 0;
        !           388: 
        !           389: 
        !           390: 
        !           391: /* if we're running low on free regions, allocate some more
        !           392: 
        !           393:  * we have to do this with at least 1 free region left so that get_region
        !           394: 
        !           395:  * has a chance of working
        !           396: 
        !           397:  */
        !           398: 
        !           399:        if (rfreelist && !rfreelist->next) {
        !           400: 
        !           401:                MEMREGION *newstuff;
        !           402: 
        !           403: 
        !           404: 
        !           405:                TRACE("get_region: getting new region descriptors");
        !           406: 
        !           407:                newstuff = get_region(ker, NEWREGIONS*SIZEOF(MEMREGION));
        !           408: 
        !           409:                if (!newstuff)
        !           410: 
        !           411:                    newstuff = get_region(alt,NEWREGIONS*SIZEOF(MEMREGION));
        !           412: 
        !           413:                if (!newstuff)
        !           414: 
        !           415:                    newstuff = get_region(core, NEWREGIONS*SIZEOF(MEMREGION));
        !           416: 
        !           417:                newfrees = newstuff ? (MEMREGION *)newstuff->loc : 0;
        !           418: 
        !           419:                if (newfrees) {
        !           420: 
        !           421:                        newfrees[NEWREGIONS-1].next = 0;
        !           422: 
        !           423:                        newfrees[NEWREGIONS-1].links = 0;
        !           424: 
        !           425:                        for (i = 0; i < NEWREGIONS-1; i++) {
        !           426: 
        !           427:                                newfrees[i].next = &newfrees[i+1];
        !           428: 
        !           429:                                newfrees[i].links = 0;
        !           430: 
        !           431:                        }
        !           432: 
        !           433:                        rfreelist = newfrees;
        !           434: 
        !           435:                } else {
        !           436: 
        !           437:                        DEBUG("couldn't get new region descriptors!");
        !           438: 
        !           439:                }
        !           440: 
        !           441:        }
        !           442: 
        !           443: 
        !           444: 
        !           445:        return m;
        !           446: 
        !           447: }
        !           448: 
        !           449: 
        !           450: 
        !           451: /*
        !           452: 
        !           453:  * dispose_region destroys a memory region descriptor
        !           454: 
        !           455:  */
        !           456: 
        !           457: 
        !           458: 
        !           459: void
        !           460: 
        !           461: dispose_region(m)
        !           462: 
        !           463:        MEMREGION *m;
        !           464: 
        !           465: {
        !           466: 
        !           467:        assert(ISFREE(m));
        !           468: 
        !           469:        m->next = rfreelist;
        !           470: 
        !           471:        rfreelist = m;
        !           472: 
        !           473: }
        !           474: 
        !           475: 
        !           476: 
        !           477: /*
        !           478: 
        !           479:  * virtaddr
        !           480: 
        !           481:  * attach_region(proc, reg): attach the region to the given process:
        !           482: 
        !           483:  * returns the address at which it was attached, or NULL if the process
        !           484: 
        !           485:  * cannot attach more regions. The region link count is incremented if
        !           486: 
        !           487:  * the attachment is successful.
        !           488: 
        !           489:  */
        !           490: 
        !           491: 
        !           492: 
        !           493: virtaddr
        !           494: 
        !           495: attach_region(proc, reg)
        !           496: 
        !           497:        PROC *proc;
        !           498: 
        !           499:        MEMREGION *reg;
        !           500: 
        !           501: {
        !           502: 
        !           503:        int i;
        !           504: 
        !           505:        MEMREGION **newmem;
        !           506: 
        !           507:        virtaddr *newaddr;
        !           508: 
        !           509: 
        !           510: 
        !           511:        if (!reg || !reg->loc) {
        !           512: 
        !           513:                ALERT("attach_region: attaching a null region??");
        !           514: 
        !           515:                return 0;
        !           516: 
        !           517:        }
        !           518: 
        !           519:        for (i = 0; i < proc->num_reg; i++) {
        !           520: 
        !           521:                if (!proc->mem[i]) {
        !           522: 
        !           523:                        assert(proc->addr[i] == 0);
        !           524: 
        !           525:                        reg->links++;
        !           526: 
        !           527:                        proc->mem[i] = reg;
        !           528: 
        !           529:                        proc->addr[i] = (virtaddr) reg->loc;
        !           530: 
        !           531:                        return proc->addr[i];
        !           532: 
        !           533:                }
        !           534: 
        !           535:        }
        !           536: 
        !           537: 
        !           538: 
        !           539: /* Hmmm, OK, we have to expand the process' memory table */
        !           540: 
        !           541:        TRACE("Expanding process memory table");
        !           542: 
        !           543:        i = proc->num_reg + NUM_REGIONS;
        !           544: 
        !           545: 
        !           546: 
        !           547:        newmem = kmalloc(i * SIZEOF(MEMREGION *));
        !           548: 
        !           549:        newaddr = kmalloc(i * SIZEOF(virtaddr));
        !           550: 
        !           551: 
        !           552: 
        !           553:        if (newmem && newaddr) {
        !           554: 
        !           555:        /* copy over the old address mapping */
        !           556: 
        !           557:                for (i = 0; i < proc->num_reg; i++) {
        !           558: 
        !           559:                        newmem[i] = proc->mem[i];
        !           560: 
        !           561:                        newaddr[i] = proc->addr[i];
        !           562: 
        !           563:                        if (newmem[i] == 0)
        !           564: 
        !           565:                                assert(newaddr[i] == 0);
        !           566: 
        !           567:                }
        !           568: 
        !           569:        /* initialize the rest of the tables */
        !           570: 
        !           571:                for(; i < proc->num_reg + NUM_REGIONS; i++) {
        !           572: 
        !           573:                        newmem[i] = 0;
        !           574: 
        !           575:                        newaddr[i] = 0;
        !           576: 
        !           577:                }
        !           578: 
        !           579:        /* free the old tables */
        !           580: 
        !           581:                kfree(proc->mem); kfree(proc->addr);
        !           582: 
        !           583:                proc->mem = newmem;
        !           584: 
        !           585:                proc->addr = newaddr;
        !           586: 
        !           587:                proc->num_reg += NUM_REGIONS;
        !           588: 
        !           589:        /* this call will succeed */
        !           590: 
        !           591:                TRACE("recursively calling attach_region");
        !           592: 
        !           593:                return attach_region(proc, reg);
        !           594: 
        !           595:        }
        !           596: 
        !           597: 
        !           598: 
        !           599:        DEBUG("attach_region: failed");
        !           600: 
        !           601:        return 0;
        !           602: 
        !           603: }
        !           604: 
        !           605: 
        !           606: 
        !           607: /*
        !           608: 
        !           609:  * detach_region(proc, reg): remove region from the procedure's address
        !           610: 
        !           611:  * space. If no more processes reference the region, return it to the
        !           612: 
        !           613:  * system. Note that we search backwards, so that the most recent
        !           614: 
        !           615:  * attachment of memory gets detached!
        !           616: 
        !           617:  */
        !           618: 
        !           619: 
        !           620: 
        !           621: void
        !           622: 
        !           623: detach_region(proc, reg)
        !           624: 
        !           625:        PROC *proc;
        !           626: 
        !           627:        MEMREGION *reg;
        !           628: 
        !           629: {
        !           630: 
        !           631:        int i;
        !           632: 
        !           633: 
        !           634: 
        !           635:        if (!reg) return;
        !           636: 
        !           637:        for (i = proc->num_reg - 1; i >= 0; i--) {
        !           638: 
        !           639:                if (proc->mem[i] == reg) {
        !           640: 
        !           641:                        reg->links--;
        !           642: 
        !           643:                        proc->mem[i] = 0; proc->addr[i] = 0;
        !           644: 
        !           645:                        if (reg->links == 0) {
        !           646: 
        !           647:                                free_region(reg);
        !           648: 
        !           649:                        }
        !           650: 
        !           651:                        return;
        !           652: 
        !           653:                }
        !           654: 
        !           655:        }
        !           656: 
        !           657:        DEBUG("detach_region: region not attached");
        !           658: 
        !           659: }
        !           660: 
        !           661: 
        !           662: 
        !           663: /*
        !           664: 
        !           665:  * get_region(MMAP map, ulong size) -- allocate a new region of the
        !           666: 
        !           667:  * given size in the given memory map. if no region big enough is available,
        !           668: 
        !           669:  * return NULL, otherwise return a pointer to the region.
        !           670: 
        !           671:  * the "links" field in the region is set to 1
        !           672: 
        !           673:  *
        !           674: 
        !           675:  * BEWARE: new_region may call get_region (indirectly), so we have to be
        !           676: 
        !           677:  * _very_ careful with re-entrancy in this function
        !           678: 
        !           679:  */
        !           680: 
        !           681: 
        !           682: 
        !           683: MEMREGION *
        !           684: 
        !           685: get_region(map, size)
        !           686: 
        !           687:        MMAP map;
        !           688: 
        !           689:        ulong size;
        !           690: 
        !           691: {
        !           692: 
        !           693:        MEMREGION *m, *n;
        !           694: 
        !           695: 
        !           696: 
        !           697: /* precautionary measures */
        !           698: 
        !           699:        if (size == 0) {
        !           700: 
        !           701:                DEBUG("request for 0 bytes??");
        !           702: 
        !           703:                size = 1;
        !           704: 
        !           705:        }
        !           706: 
        !           707: 
        !           708: 
        !           709:        size = ROUND(size);
        !           710: 
        !           711: 
        !           712: 
        !           713:        n = *map;
        !           714: 
        !           715: 
        !           716: 
        !           717:        sanity_check(map);
        !           718: 
        !           719: /* exact matches are likely to be rare, so we pre-allocate a new
        !           720: 
        !           721:  * region here; this helps us to avoid re-entrancy problems
        !           722: 
        !           723:  * when new_region calls get_region
        !           724: 
        !           725:  */
        !           726: 
        !           727:        m = new_region();
        !           728: 
        !           729: 
        !           730: 
        !           731:        while (n) {
        !           732: 
        !           733:                if (ISFREE(n)) {
        !           734: 
        !           735:                        if (n->len == size) {
        !           736: 
        !           737:                                if (m) dispose_region(m);
        !           738: 
        !           739:                                n->links++;
        !           740: 
        !           741:                                return n;
        !           742: 
        !           743:                        }
        !           744: 
        !           745:                        else if (n->len > size) {
        !           746: 
        !           747: /* split a new region, 'm', which will contain the free bytes after n */
        !           748: 
        !           749:                                if (m) {
        !           750: 
        !           751:                                        m->next = n->next;
        !           752: 
        !           753:                                        n->next = m;
        !           754: 
        !           755:                                        m->mflags = n->mflags & M_MAP;
        !           756: 
        !           757:                                        m->loc = n->loc + size;
        !           758: 
        !           759:                                        m->len = n->len - size;
        !           760: 
        !           761:                                        n->len = size;
        !           762: 
        !           763:                                        n->links++;
        !           764: 
        !           765:                                        return n;
        !           766: 
        !           767:                                } else {
        !           768: 
        !           769:                                    DEBUG("get_region: no regions left");
        !           770: 
        !           771:                                    return 0;
        !           772: 
        !           773:                                }
        !           774: 
        !           775:                        }
        !           776: 
        !           777:                }
        !           778: 
        !           779:                n = n->next;
        !           780: 
        !           781:        }
        !           782: 
        !           783: 
        !           784: 
        !           785:        if (m)
        !           786: 
        !           787:                dispose_region(m);
        !           788: 
        !           789:        return NULL;
        !           790: 
        !           791: }
        !           792: 
        !           793: 
        !           794: 
        !           795: /*
        !           796: 
        !           797:  * free_region(MEMREGION *reg): free the indicated region. The map
        !           798: 
        !           799:  * in which the region is contained is given by reg->mflags.
        !           800: 
        !           801:  * the caller is responsible for making sure that the region
        !           802: 
        !           803:  * really should be freed, i.e. that reg->links == 0.
        !           804: 
        !           805:  */
        !           806: 
        !           807: 
        !           808: 
        !           809: void
        !           810: 
        !           811: free_region(reg)
        !           812: 
        !           813:        MEMREGION *reg;
        !           814: 
        !           815: {
        !           816: 
        !           817:        MMAP map;
        !           818: 
        !           819:        MEMREGION *m;
        !           820: 
        !           821: 
        !           822: 
        !           823:        if (!reg) return;
        !           824: 
        !           825: 
        !           826: 
        !           827:        assert(ISFREE(reg));
        !           828: 
        !           829: 
        !           830: 
        !           831:        if (reg->mflags & M_CORE)
        !           832: 
        !           833:                map = core;
        !           834: 
        !           835:        else if (reg->mflags & M_ALT)
        !           836: 
        !           837:                map = alt;
        !           838: 
        !           839:        else if (reg->mflags & M_KER)
        !           840: 
        !           841:                map = ker;
        !           842: 
        !           843:        else {
        !           844: 
        !           845:                FATAL("free_region: region flags not valid (%x)", reg->mflags);
        !           846: 
        !           847:        }
        !           848: 
        !           849:        reg->mflags &= M_MAP;
        !           850: 
        !           851:        m = *map;
        !           852: 
        !           853:        assert(m);
        !           854: 
        !           855: 
        !           856: 
        !           857:        if (m == reg) goto merge_after;
        !           858: 
        !           859: 
        !           860: 
        !           861: /* merge previous region if it's free and contiguous with 'reg' */
        !           862: 
        !           863: 
        !           864: 
        !           865: /* first, we find the region */
        !           866: 
        !           867:        while (m && m->next != reg)
        !           868: 
        !           869:                m = m->next;
        !           870: 
        !           871: 
        !           872: 
        !           873:        assert(m != NULL);
        !           874: 
        !           875: 
        !           876: 
        !           877:        if (ISFREE(m) && (m->loc + m->len == reg->loc)) {
        !           878: 
        !           879:                m->len += reg->len;
        !           880: 
        !           881:                assert(m->next == reg);
        !           882: 
        !           883:                m->next = reg->next;
        !           884: 
        !           885:                reg->next = 0;
        !           886: 
        !           887:                dispose_region(reg);
        !           888: 
        !           889:                reg = m;
        !           890: 
        !           891:        }
        !           892: 
        !           893: 
        !           894: 
        !           895: /* merge next region if it's free and contiguous with 'reg' */
        !           896: 
        !           897: merge_after:
        !           898: 
        !           899:        m = reg->next;
        !           900: 
        !           901:        if (m && ISFREE(m) && reg->loc + reg->len == m->loc) {
        !           902: 
        !           903:                reg->len += m->len;
        !           904: 
        !           905:                reg->next = m->next;
        !           906: 
        !           907:                m->next = 0;
        !           908: 
        !           909:                dispose_region(m);
        !           910: 
        !           911:        }
        !           912: 
        !           913: 
        !           914: 
        !           915:        sanity_check(map);
        !           916: 
        !           917: }
        !           918: 
        !           919: 
        !           920: 
        !           921: /*
        !           922: 
        !           923:  * shrink_region(MEMREGION *reg, ulong newsize):
        !           924: 
        !           925:  *   shrink region 'reg', so that it is now 'newsize' bytes long.
        !           926: 
        !           927:  *   if 'newsize' is bigger than the region's current size, return EGSBF;
        !           928: 
        !           929:  *   otherwise return 0.
        !           930: 
        !           931:  */
        !           932: 
        !           933: 
        !           934: 
        !           935: long
        !           936: 
        !           937: shrink_region(reg, newsize)
        !           938: 
        !           939:        MEMREGION *reg;
        !           940: 
        !           941:        ulong newsize;
        !           942: 
        !           943: {
        !           944: 
        !           945:        MMAP map;
        !           946: 
        !           947:        MEMREGION *n;
        !           948: 
        !           949:        ulong diff;
        !           950: 
        !           951: 
        !           952: 
        !           953: 
        !           954: 
        !           955:        newsize = ROUND(newsize);
        !           956: 
        !           957: 
        !           958: 
        !           959:        assert(reg->links > 0);
        !           960: 
        !           961: 
        !           962: 
        !           963:        if (reg->mflags & M_CORE)
        !           964: 
        !           965:                map = core;
        !           966: 
        !           967:        else if (reg->mflags & M_ALT)
        !           968: 
        !           969:                map = alt;
        !           970: 
        !           971:        else if (reg->mflags & M_KER)
        !           972: 
        !           973:                map = ker;
        !           974: 
        !           975:        else {
        !           976: 
        !           977:                FATAL("shrink_region: bad region flags (%x)", reg->mflags);
        !           978: 
        !           979:        }
        !           980: 
        !           981: 
        !           982: 
        !           983: /* shrinking to 0 is the same as freeing */
        !           984: 
        !           985:        if (newsize == 0) {
        !           986: 
        !           987:                detach_region(curproc, reg);
        !           988: 
        !           989:                return 0;
        !           990: 
        !           991:        }
        !           992: 
        !           993: 
        !           994: 
        !           995: /* if new size is the same as old size, don't do anything */
        !           996: 
        !           997:        if (newsize == reg->len) {
        !           998: 
        !           999:                return 0;       /* nothing to do */
        !          1000: 
        !          1001:        }
        !          1002: 
        !          1003: 
        !          1004: 
        !          1005:        if (newsize > reg->len) {
        !          1006: 
        !          1007:                DEBUG("shrink_region: request to make region bigger");
        !          1008: 
        !          1009:                return EGSBF;   /* growth failure */
        !          1010: 
        !          1011:        }
        !          1012: 
        !          1013: 
        !          1014: 
        !          1015: /* OK, we're going to free (reg->len - newsize) bytes at the end of
        !          1016: 
        !          1017:    this block. If the block after us is already free, simply add the
        !          1018: 
        !          1019:    space to that block.
        !          1020: 
        !          1021:  */
        !          1022: 
        !          1023:        n = reg->next;
        !          1024: 
        !          1025:        diff = reg->len - newsize;
        !          1026: 
        !          1027: 
        !          1028: 
        !          1029:        if (n && ISFREE(n) && reg->loc + reg->len == n->loc) {
        !          1030: 
        !          1031:                reg->len = newsize;
        !          1032: 
        !          1033:                n->loc -= diff;
        !          1034: 
        !          1035:                n->len += diff;
        !          1036: 
        !          1037:                return 0;
        !          1038: 
        !          1039:        }
        !          1040: 
        !          1041:        else {
        !          1042: 
        !          1043:                n = new_region();
        !          1044: 
        !          1045:                if (!n) {
        !          1046: 
        !          1047:                        DEBUG("shrink_region: new_region failed");
        !          1048: 
        !          1049:                        return EINTRN;
        !          1050: 
        !          1051:                }
        !          1052: 
        !          1053:                reg->len = newsize;
        !          1054: 
        !          1055:                n->loc = reg->loc + newsize;
        !          1056: 
        !          1057:                n->len = diff;
        !          1058: 
        !          1059:                n->mflags = reg->mflags & M_MAP;
        !          1060: 
        !          1061:                n->next = reg->next;
        !          1062: 
        !          1063:                reg->next = n;
        !          1064: 
        !          1065:        }
        !          1066: 
        !          1067:        return 0;
        !          1068: 
        !          1069: }
        !          1070: 
        !          1071: 
        !          1072: 
        !          1073: /*
        !          1074: 
        !          1075:  * max_rsize(map): return the length of the biggest free region
        !          1076: 
        !          1077:  * in the given memory map, or 0 if no regions remain.
        !          1078: 
        !          1079:  */
        !          1080: 
        !          1081: 
        !          1082: 
        !          1083: long
        !          1084: 
        !          1085: max_rsize(map)
        !          1086: 
        !          1087:        MMAP map;
        !          1088: 
        !          1089: {
        !          1090: 
        !          1091:        MEMREGION *m, *max = 0;
        !          1092: 
        !          1093:        long size = 0;
        !          1094: 
        !          1095: 
        !          1096: 
        !          1097:        for (m = *map; m; m = m->next) {
        !          1098: 
        !          1099:                if (ISFREE(m)) {
        !          1100: 
        !          1101:                        if (m->len > size) {
        !          1102: 
        !          1103:                                max = m;
        !          1104: 
        !          1105:                                size = m->len;
        !          1106: 
        !          1107:                        }
        !          1108: 
        !          1109:                }
        !          1110: 
        !          1111:        }
        !          1112: 
        !          1113:        return size;
        !          1114: 
        !          1115: }
        !          1116: 
        !          1117: 
        !          1118: 
        !          1119: /*
        !          1120: 
        !          1121:  * tot_rsize(map, flag): if flag == 1, return the total number of bytes in
        !          1122: 
        !          1123:  * the given memory map; if flag == 0, return only the number of free
        !          1124: 
        !          1125:  * bytes
        !          1126: 
        !          1127:  */
        !          1128: 
        !          1129: 
        !          1130: 
        !          1131: long
        !          1132: 
        !          1133: tot_rsize(map, flag)
        !          1134: 
        !          1135:        MMAP map;
        !          1136: 
        !          1137:        int flag;
        !          1138: 
        !          1139: {
        !          1140: 
        !          1141:        MEMREGION *m;
        !          1142: 
        !          1143:        long size = 0;
        !          1144: 
        !          1145: 
        !          1146: 
        !          1147:        for (m = *map; m; m = m->next) {
        !          1148: 
        !          1149:                if (flag || ISFREE(m)) {
        !          1150: 
        !          1151:                        size += m->len;
        !          1152: 
        !          1153:                }
        !          1154: 
        !          1155:        }
        !          1156: 
        !          1157:        return size;
        !          1158: 
        !          1159: }
        !          1160: 
        !          1161: 
        !          1162: 
        !          1163: /*
        !          1164: 
        !          1165:  * alloc_region(MMAP map, ulong size): allocate a new region and attach
        !          1166: 
        !          1167:  * it to the current process; returns the address at which the region
        !          1168: 
        !          1169:  * was attached, or NULL. If not enough memory is found, wait a bit
        !          1170: 
        !          1171:  * and try again before giving up (maybe someone else will free some
        !          1172: 
        !          1173:  * memory)
        !          1174: 
        !          1175:  */
        !          1176: 
        !          1177: 
        !          1178: 
        !          1179: virtaddr
        !          1180: 
        !          1181: alloc_region(map, size)
        !          1182: 
        !          1183:        MMAP map;
        !          1184: 
        !          1185:        ulong size;
        !          1186: 
        !          1187: {
        !          1188: 
        !          1189:        MEMREGION *m;
        !          1190: 
        !          1191:        PROC *proc = curproc;
        !          1192: 
        !          1193:        virtaddr v;
        !          1194: 
        !          1195: 
        !          1196: 
        !          1197:        m = get_region(map, size);
        !          1198: 
        !          1199:        if (!m) {
        !          1200: 
        !          1201:                return 0;
        !          1202: 
        !          1203:        }
        !          1204: 
        !          1205: 
        !          1206: 
        !          1207:        v = attach_region(proc, m);
        !          1208: 
        !          1209: /* NOTE: get_region returns a region with link count 1; since attach_region
        !          1210: 
        !          1211:  * increments the link count, we restore it after calling attach_region
        !          1212: 
        !          1213:  */
        !          1214: 
        !          1215:        m->links = 1;
        !          1216: 
        !          1217:        if (!v) {
        !          1218: 
        !          1219:                m->links = 0;
        !          1220: 
        !          1221:                free_region(m);
        !          1222: 
        !          1223:                return 0;
        !          1224: 
        !          1225:        }
        !          1226: 
        !          1227:        return v;
        !          1228: 
        !          1229: }
        !          1230: 
        !          1231: 
        !          1232: 
        !          1233: /*
        !          1234: 
        !          1235:  * routines for creating a copy of an environment, and a new basepage.
        !          1236: 
        !          1237:  * note that the memory regions created should immediately be attached to
        !          1238: 
        !          1239:  * a process! Also note that create_env always operates in ST RAM, but
        !          1240: 
        !          1241:  * create_base might not.
        !          1242: 
        !          1243:  */
        !          1244: 
        !          1245: 
        !          1246: 
        !          1247: MEMREGION *
        !          1248: 
        !          1249: create_env(env)
        !          1250: 
        !          1251:        const char *env;
        !          1252: 
        !          1253: {
        !          1254: 
        !          1255:        long size;
        !          1256: 
        !          1257:        MEMREGION *m;
        !          1258: 
        !          1259:        virtaddr v;
        !          1260: 
        !          1261:        const char *old;
        !          1262: 
        !          1263:        char *new;
        !          1264: 
        !          1265:        
        !          1266: 
        !          1267:        if (!env) {
        !          1268: 
        !          1269:                env = ((BASEPAGE *)curproc->base)->p_env;
        !          1270: 
        !          1271:                        /* duplicate parent's environment */
        !          1272: 
        !          1273:        }
        !          1274: 
        !          1275:        size = 2;
        !          1276: 
        !          1277:        old = env;
        !          1278: 
        !          1279:        while (*env || *(env+1))
        !          1280: 
        !          1281:                env++,size++;
        !          1282: 
        !          1283:        v = alloc_region(core, size);
        !          1284: 
        !          1285:        if (!v) {
        !          1286: 
        !          1287:                DEBUG("create_env: alloc_region failed");
        !          1288: 
        !          1289:                return (MEMREGION *)0;
        !          1290: 
        !          1291:        }
        !          1292: 
        !          1293:        m = addr2mem(v);
        !          1294: 
        !          1295: 
        !          1296: 
        !          1297: /* copy the old environment into the new */
        !          1298: 
        !          1299:        new = (char *) m->loc;
        !          1300: 
        !          1301:        while (size > 0) {
        !          1302: 
        !          1303:                *new++ = *old++;
        !          1304: 
        !          1305:                --size;
        !          1306: 
        !          1307:        }
        !          1308: 
        !          1309:        return m;
        !          1310: 
        !          1311: }
        !          1312: 
        !          1313: 
        !          1314: 
        !          1315: MEMREGION *
        !          1316: 
        !          1317: create_base(cmd, env, flags, prgsize)
        !          1318: 
        !          1319:        const char *cmd;
        !          1320: 
        !          1321:        MEMREGION *env;
        !          1322: 
        !          1323:        ulong flags, prgsize;
        !          1324: 
        !          1325: {
        !          1326: 
        !          1327:        long len, coresize, altsize;
        !          1328: 
        !          1329:        MMAP map;
        !          1330: 
        !          1331:        MEMREGION *m;
        !          1332: 
        !          1333:        BASEPAGE *b;
        !          1334: 
        !          1335: 
        !          1336: 
        !          1337: /* if flags & F_ALTLOAD == 1, then we might decide to load in alternate
        !          1338: 
        !          1339:    RAM if enough is available. "enough" is: if more alt ram than ST ram,
        !          1340: 
        !          1341:    load there; otherwise, if more than (minalt+1)*128K alt ram available
        !          1342: 
        !          1343:    for heap space, load in alt ram ("minalt" is the high byte of flags)
        !          1344: 
        !          1345:  */
        !          1346: 
        !          1347:        if (flags & F_ALTLOAD) {
        !          1348: 
        !          1349:                coresize = max_rsize(core);
        !          1350: 
        !          1351:                altsize = max_rsize(alt);
        !          1352: 
        !          1353:                if (altsize >= coresize)
        !          1354: 
        !          1355:                        map = alt;
        !          1356: 
        !          1357:                else {
        !          1358: 
        !          1359:                        len = (flags & 0xf0000000) >> 28L;
        !          1360: 
        !          1361:                        len = (len+1)*128*1024L + prgsize + 256;
        !          1362: 
        !          1363:                        if (altsize >= len)
        !          1364: 
        !          1365:                                map = alt;
        !          1366: 
        !          1367:                        else
        !          1368: 
        !          1369:                                map = core;
        !          1370: 
        !          1371:                }
        !          1372: 
        !          1373:        }
        !          1374: 
        !          1375:        else
        !          1376: 
        !          1377:                map = core;
        !          1378: 
        !          1379: 
        !          1380: 
        !          1381:        len = max_rsize(map);
        !          1382: 
        !          1383: 
        !          1384: 
        !          1385: /* make sure that a little bit of memory is left over */
        !          1386: 
        !          1387:        if (len > 2*KEEP_MEM) {
        !          1388: 
        !          1389:                len -= KEEP_MEM;
        !          1390: 
        !          1391:        }
        !          1392: 
        !          1393:        m = addr2mem(alloc_region(map, len));
        !          1394: 
        !          1395:        if (!m) {
        !          1396: 
        !          1397:                DEBUG("create_base: alloc_region failed");
        !          1398: 
        !          1399:                return 0;
        !          1400: 
        !          1401:        }
        !          1402: 
        !          1403:        b = (BASEPAGE *)(m->loc);
        !          1404: 
        !          1405: 
        !          1406: 
        !          1407:        zero((char *)b, (long)sizeof(BASEPAGE));
        !          1408: 
        !          1409:        b->p_lowtpa = (long)b;
        !          1410: 
        !          1411:        b->p_hitpa = m->loc + m->len;
        !          1412: 
        !          1413:        b->p_env = (char *)env->loc;
        !          1414: 
        !          1415:        b->p_flags = flags;
        !          1416: 
        !          1417: 
        !          1418: 
        !          1419:        if (cmd)
        !          1420: 
        !          1421:                strncpy(b->p_cmdlin, cmd, 126);
        !          1422: 
        !          1423:        return m;
        !          1424: 
        !          1425: }
        !          1426: 
        !          1427: 
        !          1428: 
        !          1429: /*
        !          1430: 
        !          1431:  * load_region(filename): loads the program with the given file name
        !          1432: 
        !          1433:  * into a new region, and returns a pointer to that region. On an error,
        !          1434: 
        !          1435:  * returns 0 and leaves the error number in mint_errno.
        !          1436: 
        !          1437:  */
        !          1438: 
        !          1439: 
        !          1440: 
        !          1441: static struct fileheader {
        !          1442: 
        !          1443:        short   fmagic;
        !          1444: 
        !          1445:        long    ftext;
        !          1446: 
        !          1447:        long    fdata;
        !          1448: 
        !          1449:        long    fbss;
        !          1450: 
        !          1451:        long    fsym;
        !          1452: 
        !          1453:        long    reserved;
        !          1454: 
        !          1455:        long    flag;
        !          1456: 
        !          1457:        short   reloc;
        !          1458: 
        !          1459: } fh;
        !          1460: 
        !          1461: 
        !          1462: 
        !          1463: MEMREGION *
        !          1464: 
        !          1465: load_region(filename, env, cmdlin, xp)
        !          1466: 
        !          1467:        const char *filename;
        !          1468: 
        !          1469:        MEMREGION *env;
        !          1470: 
        !          1471:        const char *cmdlin;
        !          1472: 
        !          1473:        XATTR *xp;              /* attributes for the file just loaded */
        !          1474: 
        !          1475: {
        !          1476: 
        !          1477:        FILEPTR *f;
        !          1478: 
        !          1479:        DEVDRV *dev;
        !          1480: 
        !          1481:        MEMREGION *reg;
        !          1482: 
        !          1483:        BASEPAGE *b;
        !          1484: 
        !          1485:        long size, fixup, base, bytes_read;
        !          1486: 
        !          1487:        unsigned char c, *next;
        !          1488: 
        !          1489: #define LRBUFSIZ 8196
        !          1490: 
        !          1491:        static unsigned char buffer[LRBUFSIZ];
        !          1492: 
        !          1493:        int trycount = 0;
        !          1494: 
        !          1495: 
        !          1496: 
        !          1497:        next = buffer;
        !          1498: 
        !          1499: 
        !          1500: 
        !          1501:        f = do_open(filename, O_DENYNONE | O_EXEC, 0, xp);
        !          1502: 
        !          1503:        if (!f) {
        !          1504: 
        !          1505:                return 0;               /* mint_errno set by do_open */
        !          1506: 
        !          1507:        }
        !          1508: 
        !          1509: 
        !          1510: 
        !          1511:        dev = f->dev;                   /* could be different from fs */
        !          1512: 
        !          1513:        if ( (*dev->read)(f, (void *)&fh, (long)sizeof(fh)) != sizeof(fh) ||
        !          1514: 
        !          1515:              fh.fmagic != 0x601a ) {
        !          1516: 
        !          1517:                DEBUG("load_region: file not executable");
        !          1518: 
        !          1519:                mint_errno = ENOEXEC;
        !          1520: 
        !          1521: failed:
        !          1522: 
        !          1523:                do_close(f);
        !          1524: 
        !          1525:                return 0;
        !          1526: 
        !          1527:        }
        !          1528: 
        !          1529: 
        !          1530: 
        !          1531:        size = fh.ftext + fh.fdata + fh.fbss;
        !          1532: 
        !          1533:        reg = 0;
        !          1534: 
        !          1535:        for (trycount = 0; (trycount < 1) && (reg == 0); trycount++) {
        !          1536: 
        !          1537:                reg = create_base(cmdlin, env, fh.flag, size);
        !          1538: 
        !          1539:                if (size+1024L > reg->len) {
        !          1540: 
        !          1541:                        DEBUG("load_region: insufficient memory to load");
        !          1542: 
        !          1543:                        detach_region(curproc, reg);
        !          1544: 
        !          1545:                        reg = 0;
        !          1546: 
        !          1547:                }
        !          1548: 
        !          1549:                if (!reg) {
        !          1550: 
        !          1551:        /* maybe the memory shortage is short-term; sleep a bit to see */
        !          1552: 
        !          1553:                        nap(10);
        !          1554: 
        !          1555:                }
        !          1556: 
        !          1557:        }
        !          1558: 
        !          1559: 
        !          1560: 
        !          1561:        if (reg == 0) {
        !          1562: 
        !          1563:                mint_errno = ENSMEM;
        !          1564: 
        !          1565:                goto failed;
        !          1566: 
        !          1567:        }
        !          1568: 
        !          1569: 
        !          1570: 
        !          1571:        b = (BASEPAGE *)reg->loc;
        !          1572: 
        !          1573:        b->p_flags = fh.flag;
        !          1574: 
        !          1575:        b->p_tbase = b->p_lowtpa + 256;
        !          1576: 
        !          1577:        b->p_tlen = fh.ftext;
        !          1578: 
        !          1579:        b->p_dbase = b->p_tbase + b->p_tlen;
        !          1580: 
        !          1581:        b->p_dlen = fh.fdata;
        !          1582: 
        !          1583:        b->p_bbase = b->p_dbase + b->p_dlen;
        !          1584: 
        !          1585:        size = (*dev->read)(f, (void *)b->p_tbase, fh.ftext+fh.fdata);
        !          1586: 
        !          1587:        if (size != fh.ftext + fh.fdata) {
        !          1588: 
        !          1589:                DEBUG("load_region: unexpected EOF");
        !          1590: 
        !          1591: failed_reloc:          /* come here when loading/relocation fails */
        !          1592: 
        !          1593:                mint_errno = ENOEXEC;
        !          1594: 
        !          1595:                detach_region(curproc, reg);
        !          1596: 
        !          1597:                goto failed;
        !          1598: 
        !          1599:        }
        !          1600: 
        !          1601: 
        !          1602: 
        !          1603:        b->p_blen = fh.fbss;
        !          1604: 
        !          1605:        if (fh.flag & F_FASTLOAD)                       /* fastload bit */
        !          1606: 
        !          1607:                size = b->p_blen;
        !          1608: 
        !          1609:        else
        !          1610: 
        !          1611:                size = b->p_hitpa - b->p_bbase;
        !          1612: 
        !          1613:        zero((char *)b->p_bbase, size);
        !          1614: 
        !          1615:        (*dev->lseek)(f, fh.fsym, SEEK_CUR);    /* skip over symbol table */
        !          1616: 
        !          1617:        base = b->p_tbase;
        !          1618: 
        !          1619: 
        !          1620: 
        !          1621: /* now read the relocation info; we use the temporary buffer provided
        !          1622: 
        !          1623:  * above to speed things up
        !          1624: 
        !          1625:  */
        !          1626: 
        !          1627: 
        !          1628: 
        !          1629:        if (fh.reloc == 0 && (*dev->read)(f, (char *)&fixup, 4L) && fixup) {
        !          1630: 
        !          1631:                fixup += base;
        !          1632: 
        !          1633:                size = LRBUFSIZ;
        !          1634: 
        !          1635:                bytes_read = 0;
        !          1636: 
        !          1637:                do {
        !          1638: 
        !          1639:                        if (fixup >= b->p_hitpa) {
        !          1640: 
        !          1641:                                DEBUG("load_region: bad relocation");
        !          1642: 
        !          1643:                                goto failed_reloc;
        !          1644: 
        !          1645:                        }
        !          1646: 
        !          1647:                        else
        !          1648: 
        !          1649:                                *((long *)fixup) += base;
        !          1650: 
        !          1651:                        do {
        !          1652: 
        !          1653:                                if (!bytes_read) {
        !          1654: 
        !          1655:                                        bytes_read =
        !          1656: 
        !          1657:                                            (*dev->read)(f,(char *)buffer,size);
        !          1658: 
        !          1659:                                        next = buffer;
        !          1660: 
        !          1661:                                }
        !          1662: 
        !          1663:                                if (bytes_read < 0) {
        !          1664: 
        !          1665:                                        DEBUG("load_region: EOF in relocation");
        !          1666: 
        !          1667:                                        goto failed_reloc;
        !          1668: 
        !          1669:                                }
        !          1670: 
        !          1671:                                else if (bytes_read == 0)
        !          1672: 
        !          1673:                                        c = 0;
        !          1674: 
        !          1675:                                else {
        !          1676: 
        !          1677:                                        c = *next++; bytes_read--;
        !          1678: 
        !          1679:                                }
        !          1680: 
        !          1681:                                if (c == 1) fixup += 254;
        !          1682: 
        !          1683:                        } while (c == 1);
        !          1684: 
        !          1685:                        fixup += ( (unsigned) c) & 0xff;
        !          1686: 
        !          1687:                } while (c);
        !          1688: 
        !          1689:        }
        !          1690: 
        !          1691: 
        !          1692: 
        !          1693:        do_close(f);
        !          1694: 
        !          1695:        return reg;
        !          1696: 
        !          1697: }
        !          1698: 
        !          1699: 
        !          1700: 
        !          1701: /*
        !          1702: 
        !          1703:  * exec_region(p, mem, thread): create a child process out of a mem region
        !          1704: 
        !          1705:  * "p" is the process structure set up by the parent; it may be "curproc",
        !          1706: 
        !          1707:  * if we're overlaying. "mem" is the loaded memory region returned by
        !          1708: 
        !          1709:  * "load region". Any open files (other than the standard handles) owned
        !          1710: 
        !          1711:  * by "p" are closed, and if thread !=0 all memory is released; the caller
        !          1712: 
        !          1713:  * must explicitly attach the environment and base region. The caller must
        !          1714: 
        !          1715:  * also put "p" on the appropriate queue (most likely READY_Q).
        !          1716: 
        !          1717:  */
        !          1718: 
        !          1719: 
        !          1720: 
        !          1721: extern long mint_dos(), mint_bios();
        !          1722: 
        !          1723: 
        !          1724: 
        !          1725: void rts() {}          /* dummy termination routine */
        !          1726: 
        !          1727: 
        !          1728: 
        !          1729: PROC *
        !          1730: 
        !          1731: exec_region(p, mem, thread)
        !          1732: 
        !          1733:        PROC      *p;
        !          1734: 
        !          1735:        MEMREGION *mem;
        !          1736: 
        !          1737:        int thread;
        !          1738: 
        !          1739: {
        !          1740: 
        !          1741:        BASEPAGE *b;
        !          1742: 
        !          1743:        FILEPTR *f;
        !          1744: 
        !          1745:        int i;
        !          1746: 
        !          1747:        MEMREGION *m;
        !          1748: 
        !          1749: 
        !          1750: 
        !          1751:        TRACE("exec_region");
        !          1752: 
        !          1753: 
        !          1754: 
        !          1755:        b = (BASEPAGE *) mem->loc;
        !          1756: 
        !          1757: 
        !          1758: 
        !          1759: /* set some (undocumented) variables in the basepage */
        !          1760: 
        !          1761:        b->p_defdrv = p->curdrv;
        !          1762: 
        !          1763:        for (i = 0; i < 6; i++)
        !          1764: 
        !          1765:                b->p_devx[i] = i;
        !          1766: 
        !          1767: 
        !          1768: 
        !          1769:        p->dta = (DTABUF *)(b->p_dta = &b->p_cmdlin[0]);
        !          1770: 
        !          1771:        p->base = b;
        !          1772: 
        !          1773: 
        !          1774: 
        !          1775: /* close extra open files */
        !          1776: 
        !          1777:        for (i = MIN_OPEN; i < MAX_OPEN; i++) {
        !          1778: 
        !          1779:                if ( (f = p->handle[i]) && (p->fdflags[i] & FD_CLOEXEC) ) {
        !          1780: 
        !          1781:                        do_pclose(p, f);
        !          1782: 
        !          1783:                        p->handle[i] = 0;
        !          1784: 
        !          1785:                }
        !          1786: 
        !          1787:        }
        !          1788: 
        !          1789: 
        !          1790: 
        !          1791: /* initialize memory */
        !          1792: 
        !          1793:        recalc_maxmem(p);
        !          1794: 
        !          1795:        if (p->maxmem) {
        !          1796: 
        !          1797:                shrink_region(mem, p->maxmem);
        !          1798: 
        !          1799:                b->p_hitpa = b->p_lowtpa + mem->len;
        !          1800: 
        !          1801:        }
        !          1802: 
        !          1803: 
        !          1804: 
        !          1805:        p->memflags = b->p_flags;
        !          1806: 
        !          1807: 
        !          1808: 
        !          1809:        if (!thread) {
        !          1810: 
        !          1811:                for (i = 0; i < p->num_reg; i++) {
        !          1812: 
        !          1813:                        m = p->mem[i];
        !          1814: 
        !          1815:                        if (m) {
        !          1816: 
        !          1817:                                m->links--;
        !          1818: 
        !          1819:                                if (m->links <= 0)
        !          1820: 
        !          1821:                                        free_region(m);
        !          1822: 
        !          1823:                        }
        !          1824: 
        !          1825:                }
        !          1826: 
        !          1827:                if (p->num_reg > NUM_REGIONS) {
        !          1828: 
        !          1829:                        kfree(p->mem); kfree(p->addr);
        !          1830: 
        !          1831:                        p->mem = kmalloc(NUM_REGIONS * SIZEOF(MEMREGION *));
        !          1832: 
        !          1833:                        p->addr = kmalloc(NUM_REGIONS * SIZEOF(virtaddr));
        !          1834: 
        !          1835:        /* note: the mallocs have succeeded, since we just freed bigger areas */
        !          1836: 
        !          1837:                        assert(p->mem && p->addr);
        !          1838: 
        !          1839:                        p->num_reg = NUM_REGIONS;
        !          1840: 
        !          1841:                }
        !          1842: 
        !          1843:                zero((char *)p->mem, (p->num_reg)*SIZEOF(MEMREGION *));
        !          1844: 
        !          1845:                zero((char *)p->addr, (p->num_reg)*SIZEOF(virtaddr));
        !          1846: 
        !          1847:        }
        !          1848: 
        !          1849: 
        !          1850: 
        !          1851: /* initialize signals */
        !          1852: 
        !          1853:        p->sigmask = 0;
        !          1854: 
        !          1855:        for (i = 0; i < NSIG; i++) {
        !          1856: 
        !          1857:                if (p->sighandle[i] != SIG_IGN) {
        !          1858: 
        !          1859:                        p->sighandle[i] = SIG_DFL;
        !          1860: 
        !          1861:                        p->sigflags[i] = 0;
        !          1862: 
        !          1863:                        p->sigextra[i] = 0;
        !          1864: 
        !          1865:                }
        !          1866: 
        !          1867:        }
        !          1868: 
        !          1869: 
        !          1870: 
        !          1871: /* zero the user registers, and set the FPU in a "clear" state */
        !          1872: 
        !          1873:        for (i = 0; i < 15; i++)
        !          1874: 
        !          1875:                p->ctxt[CURRENT].regs[i] = 0;
        !          1876: 
        !          1877:        p->ctxt[CURRENT].sr = 0;
        !          1878: 
        !          1879:        p->ctxt[CURRENT].fstate[0] = 0;
        !          1880: 
        !          1881: 
        !          1882: 
        !          1883: /* set PC, stack registers, etc. appropriately */
        !          1884: 
        !          1885:        p->ctxt[CURRENT].pc = b->p_tbase;
        !          1886: 
        !          1887: 
        !          1888: 
        !          1889: /* The "-0x20" is to make sure that syscall.s won't run past the end of
        !          1890: 
        !          1891:  * memory when the user makes a system call and doesn't push very many
        !          1892: 
        !          1893:  * parameters -- syscall always tries to copy the maximum possible number
        !          1894: 
        !          1895:  * of parms.
        !          1896: 
        !          1897:  *
        !          1898: 
        !          1899:  * NOTE: there's a sanity check here in case programs Mshrink a basepage
        !          1900: 
        !          1901:  * without fixing the p_hitpa field in the basepage; this is to ensure
        !          1902: 
        !          1903:  * compatibility with older versions of MiNT, which ignore p_hitpa.
        !          1904: 
        !          1905:  */
        !          1906: 
        !          1907:        if (valid_address(b->p_hitpa - 0x20))
        !          1908: 
        !          1909:                p->ctxt[CURRENT].usp = b->p_hitpa - 0x20;
        !          1910: 
        !          1911:        else
        !          1912: 
        !          1913:                p->ctxt[CURRENT].usp = mem->loc + mem->len - 0x20;
        !          1914: 
        !          1915: 
        !          1916: 
        !          1917:        p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
        !          1918: 
        !          1919:        p->ctxt[CURRENT].term_vec = (long)rts;
        !          1920: 
        !          1921: 
        !          1922: 
        !          1923: /* set up stack for process */
        !          1924: 
        !          1925:        *((long *)(p->ctxt[CURRENT].usp + 4)) = (long) b;
        !          1926: 
        !          1927: 
        !          1928: 
        !          1929: /* check for a valid text region. some compilers (e.g. Lattice 3) just throw
        !          1930: 
        !          1931:    everything into the text region, including data; fork() must be careful
        !          1932: 
        !          1933:    to save the whole region, then. We assume that if the compiler (or
        !          1934: 
        !          1935:    assembler, or whatever) goes to the trouble of making separate text, data,
        !          1936: 
        !          1937:    and bss regions, then the text region is code and isn't modified and
        !          1938: 
        !          1939:    fork doesn't have to save it.
        !          1940: 
        !          1941:  */
        !          1942: 
        !          1943:        if (b->p_tlen != 0 && b->p_blen != 0 && b->p_dlen != 0)
        !          1944: 
        !          1945:                p->txtsize = b->p_tlen;
        !          1946: 
        !          1947:        else
        !          1948: 
        !          1949:                p->txtsize = 0;
        !          1950: 
        !          1951: 
        !          1952: 
        !          1953: /*
        !          1954: 
        !          1955:  * An ugly hack: dLibs tries to poke around in the parent's address space
        !          1956: 
        !          1957:  * to find stuff. For now, we'll allow this by faking a pointer into
        !          1958: 
        !          1959:  * the parent's address space in the place in the basepage where dLibs is
        !          1960: 
        !          1961:  * expecting it. This ugly hack only works correctly if the Pexec'ing
        !          1962: 
        !          1963:  * program (i.e. curproc) is in user mode.
        !          1964: 
        !          1965:  */
        !          1966: 
        !          1967:        curproc->base->p_usp = curproc->ctxt[SYSCALL].usp - 0x32;
        !          1968: 
        !          1969: 
        !          1970: 
        !          1971:        return p;
        !          1972: 
        !          1973: }
        !          1974: 
        !          1975: 
        !          1976: 
        !          1977: /*
        !          1978: 
        !          1979:  * misc. utility routines
        !          1980: 
        !          1981:  */
        !          1982: 
        !          1983: 
        !          1984: 
        !          1985: /*
        !          1986: 
        !          1987:  * long memused(p): return total memory allocated to process p
        !          1988: 
        !          1989:  */
        !          1990: 
        !          1991: 
        !          1992: 
        !          1993: long
        !          1994: 
        !          1995: memused(p)
        !          1996: 
        !          1997:        PROC *p;
        !          1998: 
        !          1999: {
        !          2000: 
        !          2001:        int i;
        !          2002: 
        !          2003:        long size;
        !          2004: 
        !          2005: 
        !          2006: 
        !          2007:        size = 0;
        !          2008: 
        !          2009:        for (i = 0; i < p->num_reg; i++) {
        !          2010: 
        !          2011:                if (p->mem[i])
        !          2012: 
        !          2013:                        size += p->mem[i]->len;
        !          2014: 
        !          2015:        }
        !          2016: 
        !          2017:        return size;
        !          2018: 
        !          2019: }
        !          2020: 
        !          2021: 
        !          2022: 
        !          2023: /* 
        !          2024: 
        !          2025:  * recalculate the maximum memory limit on a process; this limit depends
        !          2026: 
        !          2027:  * on the max. allocated memory and max. total memory limits set by
        !          2028: 
        !          2029:  * p_setlimit (see dos.c), and (perhaps) on the size of the program
        !          2030: 
        !          2031:  * that the process is executing. whenever any of these things
        !          2032: 
        !          2033:  * change (through p_exec or p_setlimit) this routine must be called
        !          2034: 
        !          2035:  */
        !          2036: 
        !          2037: 
        !          2038: 
        !          2039: void
        !          2040: 
        !          2041: recalc_maxmem(p)
        !          2042: 
        !          2043:        PROC *p;
        !          2044: 
        !          2045: {
        !          2046: 
        !          2047:        BASEPAGE *b;
        !          2048: 
        !          2049:        long siz;
        !          2050: 
        !          2051: 
        !          2052: 
        !          2053:        b = (BASEPAGE *)p->base;
        !          2054: 
        !          2055:        if (b)
        !          2056: 
        !          2057:                siz = b->p_tlen + b->p_dlen + b->p_blen;
        !          2058: 
        !          2059:        else
        !          2060: 
        !          2061:                siz = 0;
        !          2062: 
        !          2063:        p->maxmem = 0;
        !          2064: 
        !          2065:        if (p->maxdata) {
        !          2066: 
        !          2067:                p->maxmem = p->maxdata + siz;
        !          2068: 
        !          2069:        }
        !          2070: 
        !          2071: 
        !          2072: 
        !          2073:        if (p->maxcore) {
        !          2074: 
        !          2075:                if (p->maxmem == 0 || p->maxmem > p->maxcore)
        !          2076: 
        !          2077:                        p->maxmem = p->maxcore;
        !          2078: 
        !          2079:        }
        !          2080: 
        !          2081:        if (p->maxmem && p->maxmem < siz)
        !          2082: 
        !          2083:                p->maxmem = siz;
        !          2084: 
        !          2085: }
        !          2086: 
        !          2087: 
        !          2088: 
        !          2089: /*
        !          2090: 
        !          2091:  * valid_address: checks to see if the indicated address falls within
        !          2092: 
        !          2093:  * memory attached to the current process
        !          2094: 
        !          2095:  */
        !          2096: 
        !          2097: 
        !          2098: 
        !          2099: int
        !          2100: 
        !          2101: valid_address(addr)
        !          2102: 
        !          2103:        long addr;
        !          2104: 
        !          2105: {
        !          2106: 
        !          2107:        int i;
        !          2108: 
        !          2109:        MEMREGION *m;
        !          2110: 
        !          2111: 
        !          2112: 
        !          2113:        for (i = 0; i < curproc->num_reg; i++) {
        !          2114: 
        !          2115:                if ((m = curproc->mem[i]) != 0) {
        !          2116: 
        !          2117:                        if (addr >= m->loc && addr <= m->loc + m->len)
        !          2118: 
        !          2119:                                return 1;
        !          2120: 
        !          2121:                }
        !          2122: 
        !          2123:        }
        !          2124: 
        !          2125:        return 0;
        !          2126: 
        !          2127: }
        !          2128: 
        !          2129: 
        !          2130: 
        !          2131: /*
        !          2132: 
        !          2133:  * some debugging stuff
        !          2134: 
        !          2135:  */
        !          2136: 
        !          2137: 
        !          2138: 
        !          2139: void
        !          2140: 
        !          2141: DUMPMEM(map)
        !          2142: 
        !          2143:        MMAP map;
        !          2144: 
        !          2145: {
        !          2146: 
        !          2147:        MEMREGION *m;
        !          2148: 
        !          2149: 
        !          2150: 
        !          2151:        m = *map;
        !          2152: 
        !          2153:        ALERT("memory dump: starting at region %lx", m);
        !          2154: 
        !          2155:        while (m) {
        !          2156: 
        !          2157: ALERT("%ld bytes at %lx (%d links); next region %lx", m->len, m->loc,
        !          2158: 
        !          2159:       m->links, m->next);
        !          2160: 
        !          2161:        m = m->next;
        !          2162: 
        !          2163:        }
        !          2164: 
        !          2165: }
        !          2166: 
        !          2167: 
        !          2168: 
        !          2169: void
        !          2170: 
        !          2171: sanity_check(map)
        !          2172: 
        !          2173:        MMAP map;
        !          2174: 
        !          2175: {
        !          2176: 
        !          2177: #ifdef SANITY_CHECK
        !          2178: 
        !          2179:        MEMREGION *m, *nxt;
        !          2180: 
        !          2181:        long end;
        !          2182: 
        !          2183: 
        !          2184: 
        !          2185:        m = *map;
        !          2186: 
        !          2187:        while (m) {
        !          2188: 
        !          2189:                nxt = m->next;
        !          2190: 
        !          2191:                if (nxt) {
        !          2192: 
        !          2193:                        end = m->loc + m->len;
        !          2194: 
        !          2195:                        if (m->loc < nxt->loc && end > nxt->loc) {
        !          2196: 
        !          2197:                                FATAL("MEMORY CHAIN CORRUPTED");
        !          2198: 
        !          2199:                        }
        !          2200: 
        !          2201:                        else if (end == nxt->loc && ISFREE(m) && ISFREE(nxt)) {
        !          2202: 
        !          2203:                                ALERT("Continguous memory regions not merged!");
        !          2204: 
        !          2205:                        }
        !          2206: 
        !          2207:                }
        !          2208: 
        !          2209:                m = nxt;
        !          2210: 
        !          2211:        }
        !          2212: 
        !          2213: #endif
        !          2214: 
        !          2215: }
        !          2216: 

unix.superglobalmegacorp.com

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