Annotation of MiNT/src/mem.c, revision 1.1.1.5

1.1       root        1: /*
                      2: 
1.1.1.3   root        3: Copyright 1990,1991,1992 Eric R. Smith.
                      4: 
1.1.1.5 ! root        5: Copyright 1992,1993,1994 Atari Corporation.
1.1.1.3   root        6: 
                      7: All rights reserved.
1.1       root        8: 
                      9: */
                     10: 
                     11: 
                     12: 
                     13: /*
                     14: 
                     15:  * mem.c:: routines for managing memory regions
                     16: 
                     17:  */
                     18: 
                     19: 
                     20: 
                     21: #include "mint.h"
                     22: 
1.1.1.3   root       23: #include "fasttext.h" /* for line A stuff */
                     24: 
                     25: 
                     26: 
                     27: #ifndef VgetSize
                     28: 
                     29: extern long xbios();
                     30: 
                     31: #define VgetSize(mode) xbios(91, (short)(mode))
                     32: 
                     33: #define Vsetmode(mode) xbios(88, (short)(mode))
                     34: 
                     35: #endif
                     36: 
1.1       root       37: 
                     38: 
                     39: static long core_malloc P_((long, int));
                     40: 
1.1.1.3   root       41: static void core_free P_((long));
                     42: 
1.1       root       43: 
                     44: 
                     45: /* macro for testing whether a memory region is free */
                     46: 
                     47: #define ISFREE(m) ((m)->links == 0)
                     48: 
                     49: 
                     50: 
                     51: /*
                     52: 
1.1.1.2   root       53:  * list of shared text regions currently being executed
                     54: 
                     55:  */
                     56: 
                     57: SHTEXT *text_reg = 0;
                     58: 
                     59: 
                     60: 
                     61: /*
                     62: 
1.1       root       63:  * initialize memory routines
                     64: 
                     65:  */
                     66: 
                     67: 
                     68: 
                     69: /* initial number of memory regions */
                     70: 
1.1.1.5 ! root       71: #define NREGIONS ((8*1024)/sizeof(MEMREGION))
1.1       root       72: 
                     73: 
                     74: 
                     75: /* number of new regions to allocate when the initial ones are used up */
                     76: 
1.1.1.5 ! root       77: #define NEWREGIONS ((8*1024)/sizeof(MEMREGION))
1.1       root       78: 
                     79: 
                     80: 
                     81: static MEMREGION use_regions[NREGIONS+1];
                     82: 
                     83: MEMREGION *rfreelist;
                     84: 
                     85: 
                     86: 
1.1.1.5 ! root       87: /* variable for debugging purposes; number of times we've needed
        !            88: 
        !            89:  * to get new regions
        !            90: 
        !            91:  */
        !            92: 
        !            93: int num_reg_requests = 0;
        !            94: 
        !            95: 
        !            96: 
1.1.1.3   root       97: /* these variables are set in init_core(), and used in
                     98: 
                     99:  * init_mem()
                    100: 
                    101:  */
                    102: 
                    103: static ulong scrnsize, scrnplace;
                    104: 
                    105: static SCREEN *vscreen;
                    106: 
                    107: 
                    108: 
1.1       root      109: void
                    110: 
                    111: init_mem()
                    112: 
                    113: {
                    114: 
                    115:        int i;
                    116: 
1.1.1.3   root      117:        MEMREGION *r;
                    118: 
                    119:        long newbase;
                    120: 
1.1       root      121: 
                    122: 
                    123:        use_regions[NREGIONS].next = 0;
                    124: 
                    125:        for (i = 0; i < NREGIONS; i++) {
                    126: 
                    127:                use_regions[i].next = &use_regions[i+1];
                    128: 
                    129:        }
                    130: 
                    131:        rfreelist = use_regions;
                    132: 
                    133: 
                    134: 
                    135:        init_core();
                    136: 
                    137:        init_swap();
                    138: 
1.1.1.3   root      139: 
                    140: 
                    141:        init_tables();              /* initialize MMU constants */
                    142: 
                    143: 
                    144: 
                    145:        /* mark all the regions in the core & alt lists as "invalid" */
                    146: 
                    147:        for (r = *core; r; r = r->next) {
                    148: 
                    149:            mark_region(r,PROT_I);
                    150: 
                    151:        }
                    152: 
                    153:        for (r = *alt; r; r = r->next) {
                    154: 
                    155:            mark_region(r,PROT_I);
                    156: 
                    157:        }
                    158: 
                    159: 
                    160: 
                    161:        /* make sure the screen is set up properly */
                    162: 
                    163:        newbase = s_realloc(scrnsize);
                    164: 
                    165: 
                    166: 
                    167:        /* if we did get a new screen, point the new screen
                    168: 
                    169:         * at the right place after copying the data
                    170: 
                    171:         * if possible, save the screen to another buffer,
                    172: 
                    173:         * since if the new screen and old screen overlap
                    174: 
                    175:         * the blit will look very ugly.
                    176: 
                    177:         * Note that if the screen isn't moveable, then we set
                    178: 
                    179:         * scrnsize to a ridiculously large value, and so the
                    180: 
                    181:         * s_realloc above failed.
                    182: 
                    183:         */
                    184: 
                    185:        if (newbase) {
                    186: 
                    187:        /* find a free region for temp storage */
                    188: 
                    189:                for (r = *core; r; r = r->next) {
                    190: 
                    191:                        if (ISFREE(r) && r->len >= scrnsize)
                    192: 
                    193:                                break;
                    194: 
                    195:                }
                    196: 
                    197: 
                    198: 
                    199:                if (r) {
                    200: 
                    201:                        quickmove((char *)r->loc, (char *)scrnplace, scrnsize);
                    202: 
                    203:                        Setscreen((void *)r->loc, (void *)r->loc, -1);
                    204: 
                    205:                        Vsync();
                    206: 
                    207:                        quickmove((char *)newbase, (char *)r->loc, scrnsize);
                    208: 
                    209:                } else {
                    210: 
                    211:                        quickmove((char *)newbase, (char *)scrnplace, scrnsize);
                    212: 
                    213:                }
                    214: 
                    215:                Setscreen((void *)newbase, (void *)newbase, -1);
                    216: 
                    217:        /* fix the cursor */
                    218: 
                    219:                Cconws("\r\n"); 
                    220: 
                    221:        }
                    222: 
1.1       root      223: }
                    224: 
                    225: 
                    226: 
1.1.1.5 ! root      227: void
        !           228: 
        !           229: restr_screen()
        !           230: 
        !           231: {
        !           232: 
        !           233:   long base = (long) Physbase ();
        !           234: 
        !           235:   MEMREGION *r;
        !           236: 
        !           237: 
        !           238: 
        !           239:   if (base != scrnplace)
        !           240: 
        !           241:     {
        !           242: 
        !           243:       for (r = *core; r; r = r->next)
        !           244: 
        !           245:        {
        !           246: 
        !           247:          if (ISFREE (r) && r->len >= scrnsize)
        !           248: 
        !           249:            break;
        !           250: 
        !           251:        }
        !           252: 
        !           253:       if (r)
        !           254: 
        !           255:        {
        !           256: 
        !           257:          quickmove ((char *) r->loc, (char *) base, scrnsize);
        !           258: 
        !           259:          Setscreen ((void *) r->loc, (void *) r->loc, -1);
        !           260: 
        !           261:          Vsync ();
        !           262: 
        !           263:          quickmove ((char *) scrnplace, (char *) r->loc, scrnsize);
        !           264: 
        !           265:        }
        !           266: 
        !           267:       else
        !           268: 
        !           269:        quickmove ((char *) scrnplace, (char *) base, scrnsize);
        !           270: 
        !           271:       Setscreen ((void *) scrnplace, (void *) scrnplace, -1);
        !           272: 
        !           273:       Cconws ("\r\n"); 
        !           274: 
        !           275:     }
        !           276: 
        !           277: }
        !           278: 
        !           279: 
        !           280: 
1.1       root      281: /*
                    282: 
                    283:  * init_core(): initialize the core memory map (normal ST ram) and also
                    284: 
                    285:  * the alternate memory map (fast ram on the TT)
                    286: 
                    287:  */
                    288: 
                    289: 
                    290: 
                    291: static MEMREGION *_core_regions = 0, *_alt_regions = 0,
                    292: 
                    293:        *_ker_regions = 0;
                    294: 
                    295: 
                    296: 
                    297: MMAP core = &_core_regions;
                    298: 
                    299: MMAP alt = &_alt_regions;
                    300: 
                    301: MMAP ker = &_ker_regions;
                    302: 
                    303: 
                    304: 
                    305: /* note: add_region must adjust both the size and starting
                    306: 
                    307:  * address of the region being added so that memory is
                    308: 
                    309:  * always properly aligned
                    310: 
                    311:  */
                    312: 
                    313: 
                    314: 
                    315: int
                    316: 
                    317: add_region(map, place, size, mflags)
                    318: 
                    319:        MMAP map;
                    320: 
                    321:        ulong place, size;
                    322: 
                    323:        unsigned mflags;        /* initial flags for region */
                    324: 
                    325: {
                    326: 
1.1.1.3   root      327:        MEMREGION *m;
1.1       root      328: 
1.1.1.3   root      329:        ulong trimsize;
1.1       root      330: 
                    331: 
                    332: 
1.1.1.3   root      333:        TRACELOW(("add_region(map=%lx,place=%lx,size=%lx,flags=%x)",
1.1       root      334: 
1.1.1.3   root      335:                map,place,size,mflags));
1.1       root      336: 
                    337: 
                    338: 
                    339:        m = new_region();
                    340: 
                    341:        if (m == 0)
                    342: 
                    343:                return 0;       /* failure */
                    344: 
                    345:        m->links = 0;
                    346: 
                    347: 
                    348: 
1.1.1.3   root      349:        if (place & MASKBITS) {
                    350: 
                    351:            /* increase place & shorten size by the amount we're trimming */
                    352: 
                    353:            trimsize = (MASKBITS+1) - (place & MASKBITS);
                    354: 
                    355:            if (size <= trimsize) goto lose;
                    356: 
                    357:            size -= trimsize;
                    358: 
                    359:            place += trimsize;
                    360: 
                    361:        }
                    362: 
                    363: 
                    364: 
                    365:        /* now trim size DOWN to a multiple of pages */
                    366: 
                    367:        if (size & MASKBITS) size &= ~MASKBITS;
                    368: 
                    369: 
                    370: 
                    371:        /* only add if there's anything left */
                    372: 
                    373:        if (size) {
                    374: 
                    375:            m->len = size;
1.1       root      376: 
1.1.1.3   root      377:            m->loc = place;
                    378: 
                    379:            m->next = *map;
                    380: 
                    381:            m->mflags = mflags;
                    382: 
                    383:            *map = m;
                    384: 
                    385:        }
                    386: 
                    387:        else {
1.1       root      388: 
1.1.1.3   root      389:            /* succeed but don't do anything; dispose of region */
                    390: 
                    391: lose:      dispose_region(m);
                    392: 
                    393:        }
1.1       root      394: 
                    395:        return 1;       /* success */
                    396: 
                    397: }
                    398: 
                    399: 
                    400: 
                    401: static long
                    402: 
                    403: core_malloc(amt, mode)
                    404: 
                    405:        long amt;
                    406: 
                    407:        int mode;
                    408: 
                    409: {
                    410: 
                    411:        static int mxalloc = -1;        /* does GEMDOS know about Mxalloc? */
                    412: 
                    413:        long ret;
                    414: 
                    415: 
                    416: 
                    417:        if (mxalloc < 0) {
                    418: 
                    419:                ret = (long)Mxalloc(-1L, 0);
                    420: 
                    421:                if (ret == -32) mxalloc = 0;    /* unknown function */
                    422: 
                    423:                else if (ret >= 0) mxalloc = 1;
                    424: 
                    425:                else {
                    426: 
                    427:                        ALERT("GEMDOS returned %ld from Mxalloc", ret);
                    428: 
                    429:                        mxalloc = 0;
                    430: 
                    431:                }
                    432: 
                    433:        }
                    434: 
                    435:        if (mxalloc)
                    436: 
1.1.1.4   root      437:                return (long) Mxalloc(amt, mode);
1.1       root      438: 
                    439:        else if (mode == 1)
                    440: 
                    441:                return 0L;
                    442: 
                    443:        else
                    444: 
1.1.1.4   root      445:                return (long) Malloc(amt);
1.1       root      446: 
                    447: }
                    448: 
                    449: 
                    450: 
1.1.1.3   root      451: static void
                    452: 
                    453: core_free(where)
                    454: 
                    455:        long where;
                    456: 
                    457: {
                    458: 
                    459:        Mfree((void *)where);
                    460: 
                    461: }
                    462: 
                    463: 
                    464: 
1.1       root      465: void
                    466: 
                    467: init_core()
                    468: 
                    469: {
                    470: 
1.1.1.3   root      471:        extern int FalconVideo; /* set in main.c */
                    472: 
                    473:        int scrndone = 0;
                    474: 
1.1       root      475:        ulong size;
                    476: 
                    477:        ulong place;
                    478: 
1.1.1.3   root      479:        ulong temp;
                    480: 
1.1       root      481:        void *tossave;
                    482: 
                    483: 
                    484: 
                    485:        tossave = (void *)core_malloc((long)TOS_MEM, 0);
                    486: 
                    487:        if (!tossave) {
                    488: 
                    489:                FATAL("Not enough memory to run MiNT");
                    490: 
                    491:        }
                    492: 
                    493: 
                    494: 
                    495: /* initialize kernel memory */
                    496: 
                    497:        place = (ulong)core_malloc(KERNEL_MEM, 3);
                    498: 
                    499:        if (place != 0) {
                    500: 
1.1.1.3   root      501:                nalloc_arena_add((void *)place,KERNEL_MEM);
                    502: 
                    503:        }
                    504: 
                    505: 
                    506: 
                    507: /*
                    508: 
                    509:  * find out where the screen is. We want to manage the screen
                    510: 
                    511:  * memory along with all the other memory, so that Srealloc()
                    512: 
                    513:  * can be used by the XBIOS to allocate screens from the
                    514: 
                    515:  * end of memory -- this avoids fragmentation problems when
                    516: 
                    517:  * changing resolutions.
                    518: 
                    519:  */
                    520: 
                    521: /* Note, however, that some graphics boards (e.g. Matrix)
                    522: 
                    523:  * are unable to change the screen address. We fake out the
                    524: 
                    525:  * rest of our code by pretending to have a really huge
                    526: 
                    527:  * screen that can't be changed.
                    528: 
                    529:  */
                    530: 
                    531:        scrnplace = (long)Physbase();
                    532: 
                    533: 
                    534: 
                    535:        vscreen = (SCREEN *)((char *)lineA0() - 346);
                    536: 
                    537:        if (FalconVideo) {
                    538: 
                    539:        /* the Falcon can tell us the screen size */
                    540: 
                    541:            scrnsize = VgetSize(Vsetmode(-1));
                    542: 
                    543:        } else {
                    544: 
                    545:        /* otherwise, use the line A variables */
                    546: 
                    547:            scrnsize = (vscreen->maxy+1)*(long)vscreen->linelen;
                    548: 
                    549:        }
                    550: 
                    551: 
                    552: 
                    553: /* check for a graphics card with fixed screen location */
                    554: 
                    555: #define phys_top_st (*(ulong *)0x42eL)
                    556: 
                    557: 
                    558: 
                    559:        if (scrnplace >= phys_top_st) {
                    560: 
                    561: /* screen isn't in ST RAM */
                    562: 
                    563:                scrnsize = 0x7fffffffUL;
                    564: 
                    565:                scrndone = 1;
                    566: 
                    567:        } else {
                    568: 
                    569:                temp = (ulong)core_malloc(scrnsize+256L, 0);
                    570: 
                    571:                if (temp) {
                    572: 
                    573:                        (void)Setscreen((void *)-1L,
                    574: 
                    575:                                (void *)((temp+511)&(0xffffff00L)), -1);
                    576: 
1.1.1.4   root      577:                        if ((long)Physbase() != ((temp+511)&(0xffffff00L))) {
1.1.1.3   root      578: 
                    579:                                scrnsize = 0x7fffffffUL;
                    580: 
                    581:                                scrndone = 1;
                    582: 
                    583:                        }
                    584: 
                    585:                        (void)Setscreen((void *)-1L, (void *)scrnplace, -1);
                    586: 
                    587:                        core_free(temp);
                    588: 
                    589:                }
1.1       root      590: 
                    591:        }
                    592: 
                    593: 
                    594: 
                    595: /* initialize ST RAM */
                    596: 
                    597:        size = (ulong)core_malloc(-1L, 0);
                    598: 
                    599:        while (size > 0) {
                    600: 
                    601:                place = (ulong)core_malloc(size, 0);
                    602: 
1.1.1.5 ! root      603:                if (!scrndone && (place + size == scrnplace)) {
1.1.1.3   root      604: 
                    605:                        size += scrnsize;
                    606: 
                    607:                        scrndone = 1;
                    608: 
                    609:                }
                    610: 
1.1       root      611:                if (!add_region(core, place, size, M_CORE))
                    612: 
                    613:                        FATAL("init_mem: unable to add a region");
                    614: 
                    615:                size = (ulong)core_malloc(-1L, 0);
                    616: 
                    617:        }
                    618: 
                    619: 
                    620: 
1.1.1.3   root      621:        if (!scrndone) {
                    622: 
                    623:                (void)add_region(core, scrnplace, scrnsize, M_CORE);
                    624: 
                    625:        }
                    626: 
                    627: 
                    628: 
1.1       root      629: /* initialize alternate RAM */
                    630: 
                    631:        size = (ulong)core_malloc(-1L, 1);
                    632: 
                    633:        while (size > 0) {
                    634: 
                    635:                place = (ulong)core_malloc(size, 1);
                    636: 
                    637:                if (!add_region(alt, place, size, M_ALT))
                    638: 
                    639:                        FATAL("init_mem: unable to add a region");
                    640: 
                    641:                size = (ulong)core_malloc(-1L, 1);
                    642: 
                    643:        }
                    644: 
                    645: 
                    646: 
                    647:        (void)Mfree(tossave);           /* leave some memory for TOS to use */
                    648: 
                    649: }
                    650: 
                    651: 
                    652: 
                    653: /*
                    654: 
                    655:  * init_swap(): initialize the swap area; for now, this does nothing
                    656: 
                    657:  */
                    658: 
                    659: 
                    660: 
                    661: MEMREGION *_swap_regions = 0;
                    662: 
                    663: MMAP swap = &_swap_regions;
                    664: 
                    665: 
                    666: 
                    667: void
                    668: 
                    669: init_swap()
                    670: 
                    671: {
                    672: 
                    673: }
                    674: 
                    675: 
                    676: 
                    677: /*
                    678: 
                    679:  * routines for allocating/deallocating memory regions
                    680: 
                    681:  */
                    682: 
                    683: 
                    684: 
                    685: /*
                    686: 
                    687:  * new_region returns a new memory region descriptor, or NULL
                    688: 
                    689:  */
                    690: 
                    691: 
                    692: 
                    693: MEMREGION *
                    694: 
                    695: new_region()
                    696: 
                    697: {
                    698: 
                    699:        MEMREGION *m, *newfrees;
                    700: 
                    701:        int i;
                    702: 
                    703: 
                    704: 
                    705:        m = rfreelist;
                    706: 
                    707:        if (!m) {
                    708: 
                    709:                ALERT("new_region: ran out of free regions");
                    710: 
                    711:                return 0;
                    712: 
                    713:        }
                    714: 
                    715:        assert(ISFREE(m));
                    716: 
                    717:        rfreelist = m->next;
                    718: 
                    719:        m->next = 0;
                    720: 
                    721: 
                    722: 
                    723: /* if we're running low on free regions, allocate some more
                    724: 
                    725:  * we have to do this with at least 1 free region left so that get_region
                    726: 
                    727:  * has a chance of working
                    728: 
                    729:  */
                    730: 
                    731:        if (rfreelist && !rfreelist->next) {
                    732: 
                    733:                MEMREGION *newstuff;
                    734: 
                    735: 
                    736: 
1.1.1.3   root      737:                TRACELOW(("get_region: getting new region descriptors"));
1.1       root      738: 
1.1.1.3   root      739:                newstuff = get_region(ker, NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
1.1       root      740: 
                    741:                if (!newstuff)
                    742: 
1.1.1.3   root      743:                    newstuff = get_region(alt,NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
1.1       root      744: 
                    745:                if (!newstuff)
                    746: 
1.1.1.3   root      747:                    newstuff = get_region(core, NEWREGIONS*SIZEOF(MEMREGION), PROT_S);
1.1       root      748: 
                    749:                newfrees = newstuff ? (MEMREGION *)newstuff->loc : 0;
                    750: 
                    751:                if (newfrees) {
                    752: 
1.1.1.5 ! root      753:                        num_reg_requests++;
        !           754: 
1.1       root      755:                        newfrees[NEWREGIONS-1].next = 0;
                    756: 
                    757:                        newfrees[NEWREGIONS-1].links = 0;
                    758: 
                    759:                        for (i = 0; i < NEWREGIONS-1; i++) {
                    760: 
                    761:                                newfrees[i].next = &newfrees[i+1];
                    762: 
                    763:                                newfrees[i].links = 0;
                    764: 
                    765:                        }
                    766: 
                    767:                        rfreelist = newfrees;
                    768: 
                    769:                } else {
                    770: 
1.1.1.2   root      771:                        DEBUG(("couldn't get new region descriptors!"));
1.1       root      772: 
                    773:                }
                    774: 
                    775:        }
                    776: 
                    777: 
                    778: 
                    779:        return m;
                    780: 
                    781: }
                    782: 
                    783: 
                    784: 
                    785: /*
                    786: 
                    787:  * dispose_region destroys a memory region descriptor
                    788: 
                    789:  */
                    790: 
                    791: 
                    792: 
                    793: void
                    794: 
                    795: dispose_region(m)
                    796: 
                    797:        MEMREGION *m;
                    798: 
                    799: {
                    800: 
                    801:        m->next = rfreelist;
                    802: 
                    803:        rfreelist = m;
                    804: 
                    805: }
                    806: 
                    807: 
                    808: 
                    809: /*
                    810: 
1.1.1.3   root      811:  * change_prot_status: change the status of a region to 'newmode'.  We're
                    812: 
                    813:  * given its starting address, not its region structure pointer, so we have
                    814: 
                    815:  * to find the region pointer; since this is illegal if proc doesn't own
                    816: 
                    817:  * the region, we know we'll find the region struct pointer in proc->mem.
                    818: 
                    819:  *
                    820: 
                    821:  * If the proc doesn't own it, you get EACCDN.  There are no other errors.
                    822: 
                    823:  * God help you if newmode isn't legal!
                    824: 
                    825:  */
                    826: 
                    827: 
                    828: 
                    829: long
                    830: 
                    831: change_prot_status(proc,start,newmode)
                    832: 
                    833: PROC *proc;
                    834: 
                    835: long start;
                    836: 
                    837: int newmode;
                    838: 
                    839: {
                    840: 
                    841:     MEMREGION **mr;
                    842: 
                    843:     int i;
                    844: 
                    845: 
                    846: 
                    847:     /* return EACCDN if you don't own the region in question */
                    848: 
                    849:     if (!proc->mem) return EACCDN;
                    850: 
                    851: 
                    852: 
                    853:     for (mr = proc->mem, i = 0; i < proc->num_reg; i++, mr++) {
                    854: 
                    855:        if ((*mr)->loc == start) goto found;
                    856: 
                    857:     }
                    858: 
                    859:     return EACCDN;
                    860: 
                    861: 
                    862: 
                    863: found:
                    864: 
                    865:     mark_region(*mr,newmode);
                    866: 
                    867:     return E_OK;
                    868: 
                    869: }
                    870: 
                    871: 
                    872: 
                    873: /*
                    874: 
1.1       root      875:  * virtaddr
                    876: 
                    877:  * attach_region(proc, reg): attach the region to the given process:
                    878: 
                    879:  * returns the address at which it was attached, or NULL if the process
                    880: 
                    881:  * cannot attach more regions. The region link count is incremented if
                    882: 
                    883:  * the attachment is successful.
                    884: 
                    885:  */
                    886: 
                    887: 
                    888: 
                    889: virtaddr
                    890: 
                    891: attach_region(proc, reg)
                    892: 
                    893:        PROC *proc;
                    894: 
                    895:        MEMREGION *reg;
                    896: 
                    897: {
                    898: 
                    899:        int i;
                    900: 
                    901:        MEMREGION **newmem;
                    902: 
                    903:        virtaddr *newaddr;
                    904: 
                    905: 
                    906: 
1.1.1.3   root      907:        TRACELOW(("attach_region %lx len %lx to pid %d",
                    908: 
                    909:            reg->loc, reg->len, proc->pid));
                    910: 
                    911: 
                    912: 
1.1       root      913:        if (!reg || !reg->loc) {
                    914: 
                    915:                ALERT("attach_region: attaching a null region??");
                    916: 
                    917:                return 0;
                    918: 
                    919:        }
                    920: 
1.1.1.3   root      921: 
                    922: 
                    923: again:
                    924: 
1.1       root      925:        for (i = 0; i < proc->num_reg; i++) {
                    926: 
                    927:                if (!proc->mem[i]) {
                    928: 
                    929:                        assert(proc->addr[i] == 0);
                    930: 
                    931:                        reg->links++;
                    932: 
                    933:                        proc->mem[i] = reg;
                    934: 
                    935:                        proc->addr[i] = (virtaddr) reg->loc;
                    936: 
1.1.1.5 ! root      937:                        mark_proc_region(proc,reg,PROT_P);
1.1.1.3   root      938: 
1.1       root      939:                        return proc->addr[i];
                    940: 
                    941:                }
                    942: 
                    943:        }
                    944: 
                    945: 
                    946: 
                    947: /* Hmmm, OK, we have to expand the process' memory table */
                    948: 
1.1.1.3   root      949:        TRACELOW(("Expanding process memory table"));
1.1       root      950: 
                    951:        i = proc->num_reg + NUM_REGIONS;
                    952: 
                    953: 
                    954: 
                    955:        newmem = kmalloc(i * SIZEOF(MEMREGION *));
                    956: 
                    957:        newaddr = kmalloc(i * SIZEOF(virtaddr));
                    958: 
                    959: 
                    960: 
                    961:        if (newmem && newaddr) {
                    962: 
1.1.1.3   root      963:        /*
                    964: 
                    965:         * We have to use temps while allocating and freeing mem
                    966: 
                    967:         * and addr so the memory protection code won't walk this
                    968: 
                    969:         * process' memory list in the middle.
                    970: 
                    971:         */
                    972: 
                    973:                void *pmem, *paddr;
                    974: 
                    975: 
                    976: 
1.1       root      977:        /* copy over the old address mapping */
                    978: 
                    979:                for (i = 0; i < proc->num_reg; i++) {
                    980: 
                    981:                        newmem[i] = proc->mem[i];
                    982: 
                    983:                        newaddr[i] = proc->addr[i];
                    984: 
                    985:                        if (newmem[i] == 0)
                    986: 
                    987:                                assert(newaddr[i] == 0);
                    988: 
                    989:                }
                    990: 
                    991:        /* initialize the rest of the tables */
                    992: 
                    993:                for(; i < proc->num_reg + NUM_REGIONS; i++) {
                    994: 
                    995:                        newmem[i] = 0;
                    996: 
                    997:                        newaddr[i] = 0;
                    998: 
                    999:                }
                   1000: 
1.1.1.3   root     1001:        /* free the old tables (carefully! for memory protection) */
                   1002: 
                   1003:                pmem = proc->mem;
1.1       root     1004: 
1.1.1.3   root     1005:                paddr = proc->addr;
                   1006: 
                   1007:                proc->mem = NULL;
                   1008: 
                   1009:                proc->addr = NULL;
                   1010: 
                   1011:                kfree(pmem); kfree(paddr);
1.1       root     1012: 
                   1013:                proc->mem = newmem;
                   1014: 
                   1015:                proc->addr = newaddr;
                   1016: 
                   1017:                proc->num_reg += NUM_REGIONS;
                   1018: 
1.1.1.3   root     1019:        /* this time we will succeed */
1.1       root     1020: 
1.1.1.3   root     1021:                goto again;
1.1       root     1022: 
1.1.1.3   root     1023:        } else {
1.1       root     1024: 
1.1.1.3   root     1025:                if (newmem) kfree(newmem);
1.1       root     1026: 
1.1.1.3   root     1027:                if (newaddr) kfree(newaddr);
1.1       root     1028: 
1.1.1.3   root     1029:                DEBUG(("attach_region: failed"));
1.1       root     1030: 
1.1.1.3   root     1031:                return 0;
1.1       root     1032: 
1.1.1.3   root     1033:        }
1.1       root     1034: 
                   1035: }
                   1036: 
                   1037: 
                   1038: 
                   1039: /*
                   1040: 
                   1041:  * detach_region(proc, reg): remove region from the procedure's address
                   1042: 
                   1043:  * space. If no more processes reference the region, return it to the
                   1044: 
                   1045:  * system. Note that we search backwards, so that the most recent
                   1046: 
                   1047:  * attachment of memory gets detached!
                   1048: 
                   1049:  */
                   1050: 
                   1051: 
                   1052: 
                   1053: void
                   1054: 
                   1055: detach_region(proc, reg)
                   1056: 
                   1057:        PROC *proc;
                   1058: 
                   1059:        MEMREGION *reg;
                   1060: 
                   1061: {
                   1062: 
                   1063:        int i;
                   1064: 
                   1065: 
                   1066: 
                   1067:        if (!reg) return;
                   1068: 
1.1.1.3   root     1069: 
                   1070: 
                   1071:        TRACELOW(("detach_region %lx len %lx from pid %d",
                   1072: 
                   1073:            reg->loc, reg->len, proc->pid));
                   1074: 
                   1075: 
                   1076: 
1.1       root     1077:        for (i = proc->num_reg - 1; i >= 0; i--) {
                   1078: 
                   1079:                if (proc->mem[i] == reg) {
                   1080: 
                   1081:                        reg->links--;
                   1082: 
                   1083:                        proc->mem[i] = 0; proc->addr[i] = 0;
                   1084: 
                   1085:                        if (reg->links == 0) {
                   1086: 
                   1087:                                free_region(reg);
                   1088: 
                   1089:                        }
                   1090: 
1.1.1.3   root     1091:                        else {
                   1092: 
                   1093:                                /* cause curproc's table to be updated */
                   1094: 
1.1.1.5 ! root     1095:                                mark_proc_region(proc,reg,PROT_I);
1.1.1.3   root     1096: 
                   1097:                        }
                   1098: 
1.1       root     1099:                        return;
                   1100: 
                   1101:                }
                   1102: 
                   1103:        }
                   1104: 
1.1.1.2   root     1105:        DEBUG(("detach_region: region not attached"));
1.1       root     1106: 
                   1107: }
                   1108: 
                   1109: 
                   1110: 
                   1111: /*
                   1112: 
1.1.1.3   root     1113:  * get_region(MMAP map, ulong size, int mode) -- allocate a new region of the
1.1       root     1114: 
                   1115:  * given size in the given memory map. if no region big enough is available,
                   1116: 
                   1117:  * return NULL, otherwise return a pointer to the region.
                   1118: 
1.1.1.3   root     1119:  * "mode" tells us about memory protection modes
                   1120: 
                   1121:  *
                   1122: 
1.1       root     1123:  * the "links" field in the region is set to 1
                   1124: 
                   1125:  *
                   1126: 
                   1127:  * BEWARE: new_region may call get_region (indirectly), so we have to be
                   1128: 
                   1129:  * _very_ careful with re-entrancy in this function
                   1130: 
                   1131:  */
                   1132: 
                   1133: 
                   1134: 
                   1135: MEMREGION *
                   1136: 
1.1.1.3   root     1137: get_region(map, size, mode)
1.1       root     1138: 
                   1139:        MMAP map;
                   1140: 
                   1141:        ulong size;
                   1142: 
1.1.1.3   root     1143:        int mode;
                   1144: 
1.1       root     1145: {
                   1146: 
                   1147:        MEMREGION *m, *n;
                   1148: 
                   1149: 
                   1150: 
1.1.1.3   root     1151:        TRACELOW(("get_region(%s,%lx,%x)",
                   1152: 
                   1153:                (map == ker ? "ker" : (map == core ? "core" : "alt")),
                   1154: 
                   1155:                size, mode));
                   1156: 
                   1157: 
                   1158: 
1.1       root     1159: /* precautionary measures */
                   1160: 
                   1161:        if (size == 0) {
                   1162: 
1.1.1.2   root     1163:                DEBUG(("request for 0 bytes??"));
1.1       root     1164: 
                   1165:                size = 1;
                   1166: 
                   1167:        }
                   1168: 
                   1169: 
                   1170: 
                   1171:        size = ROUND(size);
                   1172: 
                   1173: 
                   1174: 
                   1175:        n = *map;
                   1176: 
                   1177: 
                   1178: 
                   1179:        sanity_check(map);
                   1180: 
                   1181: /* exact matches are likely to be rare, so we pre-allocate a new
                   1182: 
                   1183:  * region here; this helps us to avoid re-entrancy problems
                   1184: 
                   1185:  * when new_region calls get_region
                   1186: 
                   1187:  */
                   1188: 
                   1189:        m = new_region();
                   1190: 
                   1191: 
                   1192: 
                   1193:        while (n) {
                   1194: 
                   1195:                if (ISFREE(n)) {
                   1196: 
                   1197:                        if (n->len == size) {
                   1198: 
                   1199:                                if (m) dispose_region(m);
                   1200: 
                   1201:                                n->links++;
                   1202: 
1.1.1.3   root     1203:                                goto win;
1.1       root     1204: 
                   1205:                        }
                   1206: 
                   1207:                        else if (n->len > size) {
                   1208: 
                   1209: /* split a new region, 'm', which will contain the free bytes after n */
                   1210: 
                   1211:                                if (m) {
                   1212: 
                   1213:                                        m->next = n->next;
                   1214: 
                   1215:                                        n->next = m;
                   1216: 
                   1217:                                        m->mflags = n->mflags & M_MAP;
                   1218: 
                   1219:                                        m->loc = n->loc + size;
                   1220: 
                   1221:                                        m->len = n->len - size;
                   1222: 
                   1223:                                        n->len = size;
                   1224: 
                   1225:                                        n->links++;
                   1226: 
1.1.1.3   root     1227:                                        goto win;
1.1       root     1228: 
                   1229:                                } else {
                   1230: 
1.1.1.2   root     1231:                                    DEBUG(("get_region: no regions left"));
1.1       root     1232: 
                   1233:                                    return 0;
                   1234: 
                   1235:                                }
                   1236: 
                   1237:                        }
                   1238: 
                   1239:                }
                   1240: 
                   1241:                n = n->next;
                   1242: 
                   1243:        }
                   1244: 
                   1245: 
                   1246: 
                   1247:        if (m)
                   1248: 
                   1249:                dispose_region(m);
                   1250: 
1.1.1.3   root     1251: 
                   1252: 
                   1253:        TRACELOW(("get_region: no memory left in this map"));
                   1254: 
1.1       root     1255:        return NULL;
                   1256: 
1.1.1.3   root     1257: 
                   1258: 
                   1259: win:
                   1260: 
                   1261:        mark_region(n, mode & PROT_PROTMODE);
                   1262: 
                   1263:        if (mode & M_KEEP) n->mflags |= M_KEEP;
                   1264: 
                   1265: 
                   1266: 
                   1267:        return n;
                   1268: 
1.1       root     1269: }
                   1270: 
                   1271: 
                   1272: 
                   1273: /*
                   1274: 
                   1275:  * free_region(MEMREGION *reg): free the indicated region. The map
                   1276: 
                   1277:  * in which the region is contained is given by reg->mflags.
                   1278: 
                   1279:  * the caller is responsible for making sure that the region
                   1280: 
                   1281:  * really should be freed, i.e. that reg->links == 0.
                   1282: 
1.1.1.2   root     1283:  *
                   1284: 
                   1285:  * special things to do:
                   1286: 
                   1287:  * if the region is a shared text region, we must close the
                   1288: 
                   1289:  * associated file descriptor
                   1290: 
1.1       root     1291:  */
                   1292: 
                   1293: 
                   1294: 
                   1295: void
                   1296: 
                   1297: free_region(reg)
                   1298: 
                   1299:        MEMREGION *reg;
                   1300: 
                   1301: {
                   1302: 
                   1303:        MMAP map;
                   1304: 
                   1305:        MEMREGION *m;
                   1306: 
1.1.1.2   root     1307:        SHTEXT *s, **old;
                   1308: 
1.1       root     1309: 
                   1310: 
                   1311:        if (!reg) return;
                   1312: 
                   1313: 
                   1314: 
                   1315:        assert(ISFREE(reg));
                   1316: 
                   1317: 
                   1318: 
1.1.1.2   root     1319:        if (reg->mflags & M_SHTEXT) {
                   1320: 
                   1321:                TRACE(("freeing shared text region"));
                   1322: 
                   1323:                old = &text_reg;
                   1324: 
                   1325:                for(;;) {
                   1326: 
                   1327:                        s = *old;
                   1328: 
                   1329:                        if (!s) break;
                   1330: 
                   1331:                        if (s->text == reg) {
                   1332: 
1.1.1.3   root     1333:                                if (s->f)
                   1334: 
                   1335:                                        do_close(s->f);
1.1.1.2   root     1336: 
                   1337:                                *old = s->next;
                   1338: 
                   1339:                                kfree(s);
                   1340: 
                   1341:                                break;
                   1342: 
                   1343:                        }
                   1344: 
                   1345:                        old = &s->next;
                   1346: 
                   1347:                }
                   1348: 
                   1349:                if (!s) {
                   1350: 
                   1351:                    DEBUG(("No shared text entry for M_SHTEXT region??"));
                   1352: 
                   1353:                }
                   1354: 
                   1355:        }
                   1356: 
                   1357: 
                   1358: 
1.1       root     1359:        if (reg->mflags & M_CORE)
                   1360: 
                   1361:                map = core;
                   1362: 
                   1363:        else if (reg->mflags & M_ALT)
                   1364: 
                   1365:                map = alt;
                   1366: 
                   1367:        else if (reg->mflags & M_KER)
                   1368: 
                   1369:                map = ker;
                   1370: 
                   1371:        else {
                   1372: 
                   1373:                FATAL("free_region: region flags not valid (%x)", reg->mflags);
                   1374: 
                   1375:        }
                   1376: 
                   1377:        reg->mflags &= M_MAP;
                   1378: 
                   1379: 
                   1380: 
1.1.1.3   root     1381: /* unhook any vectors pointing into this region */
                   1382: 
                   1383:        unlink_vectors(reg->loc, reg->loc + reg->len);
1.1       root     1384: 
                   1385: 
1.1.1.3   root     1386: 
                   1387: /* BUG(?): should invalidate caches entries - a copyback cache could stuff
1.1.1.2   root     1388: 
                   1389:  * things into freed memory.
                   1390: 
1.1.1.3   root     1391:  *     cinv(reg->loc, reg->len);
1.1.1.2   root     1392: 
                   1393:  */
                   1394: 
1.1.1.3   root     1395:        m = *map;
                   1396: 
                   1397:        assert(m);
                   1398: 
                   1399: 
                   1400: 
                   1401:        /* MEMPROT: invalidate */
                   1402: 
                   1403:        if (map == core || map == alt)
                   1404: 
                   1405:            mark_region(reg,PROT_I);
                   1406: 
                   1407: 
                   1408: 
1.1       root     1409:        if (m == reg) goto merge_after;
                   1410: 
                   1411: 
                   1412: 
                   1413: /* merge previous region if it's free and contiguous with 'reg' */
                   1414: 
                   1415: 
                   1416: 
                   1417: /* first, we find the region */
                   1418: 
                   1419:        while (m && m->next != reg)
                   1420: 
                   1421:                m = m->next;
                   1422: 
                   1423: 
                   1424: 
1.1.1.2   root     1425:        if (m == NULL) {
                   1426: 
                   1427:                FATAL("couldn't find region %lx: loc: %lx len: %ld",
                   1428: 
                   1429:                        reg, reg->loc, reg->len);
                   1430: 
                   1431:        }
1.1       root     1432: 
                   1433: 
                   1434: 
                   1435:        if (ISFREE(m) && (m->loc + m->len == reg->loc)) {
                   1436: 
                   1437:                m->len += reg->len;
                   1438: 
                   1439:                assert(m->next == reg);
                   1440: 
                   1441:                m->next = reg->next;
                   1442: 
                   1443:                reg->next = 0;
                   1444: 
                   1445:                dispose_region(reg);
                   1446: 
                   1447:                reg = m;
                   1448: 
                   1449:        }
                   1450: 
                   1451: 
                   1452: 
                   1453: /* merge next region if it's free and contiguous with 'reg' */
                   1454: 
                   1455: merge_after:
                   1456: 
                   1457:        m = reg->next;
                   1458: 
                   1459:        if (m && ISFREE(m) && reg->loc + reg->len == m->loc) {
                   1460: 
                   1461:                reg->len += m->len;
                   1462: 
                   1463:                reg->next = m->next;
                   1464: 
                   1465:                m->next = 0;
                   1466: 
                   1467:                dispose_region(m);
                   1468: 
                   1469:        }
                   1470: 
                   1471: 
                   1472: 
                   1473:        sanity_check(map);
                   1474: 
                   1475: }
                   1476: 
                   1477: 
                   1478: 
                   1479: /*
                   1480: 
                   1481:  * shrink_region(MEMREGION *reg, ulong newsize):
                   1482: 
                   1483:  *   shrink region 'reg', so that it is now 'newsize' bytes long.
                   1484: 
                   1485:  *   if 'newsize' is bigger than the region's current size, return EGSBF;
                   1486: 
                   1487:  *   otherwise return 0.
                   1488: 
                   1489:  */
                   1490: 
                   1491: 
                   1492: 
                   1493: long
                   1494: 
                   1495: shrink_region(reg, newsize)
                   1496: 
                   1497:        MEMREGION *reg;
                   1498: 
                   1499:        ulong newsize;
                   1500: 
                   1501: {
                   1502: 
                   1503:        MEMREGION *n;
                   1504: 
                   1505:        ulong diff;
                   1506: 
                   1507: 
                   1508: 
                   1509: 
                   1510: 
                   1511:        newsize = ROUND(newsize);
                   1512: 
                   1513: 
                   1514: 
                   1515:        assert(reg->links > 0);
                   1516: 
                   1517: 
                   1518: 
1.1.1.2   root     1519:        if (!(reg->mflags & (M_CORE | M_ALT | M_KER))) {
1.1       root     1520: 
                   1521:                FATAL("shrink_region: bad region flags (%x)", reg->mflags);
                   1522: 
                   1523:        }
                   1524: 
                   1525: 
                   1526: 
                   1527: /* shrinking to 0 is the same as freeing */
                   1528: 
                   1529:        if (newsize == 0) {
                   1530: 
                   1531:                detach_region(curproc, reg);
                   1532: 
                   1533:                return 0;
                   1534: 
                   1535:        }
                   1536: 
                   1537: 
                   1538: 
                   1539: /* if new size is the same as old size, don't do anything */
                   1540: 
                   1541:        if (newsize == reg->len) {
                   1542: 
                   1543:                return 0;       /* nothing to do */
                   1544: 
                   1545:        }
                   1546: 
                   1547: 
                   1548: 
                   1549:        if (newsize > reg->len) {
                   1550: 
1.1.1.2   root     1551:                DEBUG(("shrink_region: request to make region bigger"));
1.1       root     1552: 
                   1553:                return EGSBF;   /* growth failure */
                   1554: 
                   1555:        }
                   1556: 
                   1557: 
                   1558: 
                   1559: /* OK, we're going to free (reg->len - newsize) bytes at the end of
                   1560: 
                   1561:    this block. If the block after us is already free, simply add the
                   1562: 
                   1563:    space to that block.
                   1564: 
                   1565:  */
                   1566: 
                   1567:        n = reg->next;
                   1568: 
                   1569:        diff = reg->len - newsize;
                   1570: 
                   1571: 
                   1572: 
                   1573:        if (n && ISFREE(n) && reg->loc + reg->len == n->loc) {
                   1574: 
                   1575:                reg->len = newsize;
                   1576: 
                   1577:                n->loc -= diff;
                   1578: 
                   1579:                n->len += diff;
                   1580: 
1.1.1.3   root     1581:                /* MEMPROT: invalidate the second half */
                   1582: 
                   1583:                /* (part of it is already invalid; that's OK) */
                   1584: 
                   1585:                mark_region(n,PROT_I);
                   1586: 
                   1587: 
                   1588: 
1.1       root     1589:                return 0;
                   1590: 
                   1591:        }
                   1592: 
                   1593:        else {
                   1594: 
                   1595:                n = new_region();
                   1596: 
                   1597:                if (!n) {
                   1598: 
1.1.1.2   root     1599:                        DEBUG(("shrink_region: new_region failed"));
1.1       root     1600: 
                   1601:                        return EINTRN;
                   1602: 
                   1603:                }
                   1604: 
                   1605:                reg->len = newsize;
                   1606: 
                   1607:                n->loc = reg->loc + newsize;
                   1608: 
                   1609:                n->len = diff;
                   1610: 
                   1611:                n->mflags = reg->mflags & M_MAP;
                   1612: 
                   1613:                n->next = reg->next;
                   1614: 
                   1615:                reg->next = n;
                   1616: 
1.1.1.3   root     1617:                /* MEMPROT: invalidate the new, free region */
                   1618: 
                   1619:                mark_region(n,PROT_I);
                   1620: 
1.1       root     1621:        }
                   1622: 
                   1623:        return 0;
                   1624: 
                   1625: }
                   1626: 
                   1627: 
                   1628: 
                   1629: /*
                   1630: 
                   1631:  * max_rsize(map): return the length of the biggest free region
                   1632: 
                   1633:  * in the given memory map, or 0 if no regions remain.
                   1634: 
                   1635:  */
                   1636: 
                   1637: 
                   1638: 
                   1639: long
                   1640: 
                   1641: max_rsize(map)
                   1642: 
                   1643:        MMAP map;
                   1644: 
                   1645: {
                   1646: 
1.1.1.2   root     1647:        MEMREGION *m;
1.1       root     1648: 
                   1649:        long size = 0;
                   1650: 
                   1651: 
                   1652: 
                   1653:        for (m = *map; m; m = m->next) {
                   1654: 
                   1655:                if (ISFREE(m)) {
                   1656: 
                   1657:                        if (m->len > size) {
                   1658: 
                   1659:                                size = m->len;
                   1660: 
                   1661:                        }
                   1662: 
                   1663:                }
                   1664: 
                   1665:        }
                   1666: 
                   1667:        return size;
                   1668: 
                   1669: }
                   1670: 
                   1671: 
                   1672: 
                   1673: /*
                   1674: 
                   1675:  * tot_rsize(map, flag): if flag == 1, return the total number of bytes in
                   1676: 
                   1677:  * the given memory map; if flag == 0, return only the number of free
                   1678: 
                   1679:  * bytes
                   1680: 
                   1681:  */
                   1682: 
                   1683: 
                   1684: 
                   1685: long
                   1686: 
                   1687: tot_rsize(map, flag)
                   1688: 
                   1689:        MMAP map;
                   1690: 
                   1691:        int flag;
                   1692: 
                   1693: {
                   1694: 
                   1695:        MEMREGION *m;
                   1696: 
                   1697:        long size = 0;
                   1698: 
                   1699: 
                   1700: 
                   1701:        for (m = *map; m; m = m->next) {
                   1702: 
                   1703:                if (flag || ISFREE(m)) {
                   1704: 
                   1705:                        size += m->len;
                   1706: 
                   1707:                }
                   1708: 
                   1709:        }
                   1710: 
                   1711:        return size;
                   1712: 
                   1713: }
                   1714: 
                   1715: 
                   1716: 
                   1717: /*
                   1718: 
1.1.1.3   root     1719:  * alloc_region(MMAP map, ulong size, int mode): allocate a new region and
1.1       root     1720: 
1.1.1.3   root     1721:  * attach it to the current process; returns the address at which the region
1.1       root     1722: 
1.1.1.3   root     1723:  * was attached, or NULL. The mode argument is the memory protection mode to
1.1       root     1724: 
1.1.1.3   root     1725:  * give to get_region, and in turn to mark_region.
1.1       root     1726: 
                   1727:  */
                   1728: 
                   1729: 
                   1730: 
                   1731: virtaddr
                   1732: 
1.1.1.3   root     1733: alloc_region(map, size, mode)
1.1       root     1734: 
                   1735:        MMAP map;
                   1736: 
                   1737:        ulong size;
                   1738: 
1.1.1.3   root     1739:        int mode;
                   1740: 
1.1       root     1741: {
                   1742: 
                   1743:        MEMREGION *m;
                   1744: 
                   1745:        PROC *proc = curproc;
                   1746: 
                   1747:        virtaddr v;
                   1748: 
                   1749: 
                   1750: 
1.1.1.3   root     1751:        TRACELOW(("alloc_region(map,size: %lx,mode: %x)",size,mode));
                   1752: 
                   1753:        if (!size) {
                   1754: 
                   1755:            DEBUG(("alloc_region of zero bytes?!"));
                   1756: 
                   1757:            return 0;
                   1758: 
                   1759:        }
                   1760: 
                   1761: 
                   1762: 
                   1763:        m = get_region(map, size, mode);
1.1       root     1764: 
                   1765:        if (!m) {
                   1766: 
1.1.1.3   root     1767:                TRACELOW(("alloc_region: get_region failed"));
                   1768: 
1.1       root     1769:                return 0;
                   1770: 
                   1771:        }
                   1772: 
                   1773: 
                   1774: 
1.1.1.2   root     1775: /* sanity check: even addresses only, please */
                   1776: 
                   1777:        assert((m->loc & MASKBITS) == 0);
                   1778: 
                   1779: 
                   1780: 
1.1       root     1781:        v = attach_region(proc, m);
                   1782: 
                   1783: /* NOTE: get_region returns a region with link count 1; since attach_region
                   1784: 
                   1785:  * increments the link count, we restore it after calling attach_region
                   1786: 
                   1787:  */
                   1788: 
                   1789:        m->links = 1;
                   1790: 
                   1791:        if (!v) {
                   1792: 
                   1793:                m->links = 0;
                   1794: 
                   1795:                free_region(m);
                   1796: 
1.1.1.3   root     1797:                TRACE(("alloc_region: attach_region failed"));
                   1798: 
1.1       root     1799:                return 0;
                   1800: 
                   1801:        }
                   1802: 
                   1803:        return v;
                   1804: 
                   1805: }
                   1806: 
                   1807: 
                   1808: 
                   1809: /*
                   1810: 
                   1811:  * routines for creating a copy of an environment, and a new basepage.
                   1812: 
                   1813:  * note that the memory regions created should immediately be attached to
                   1814: 
                   1815:  * a process! Also note that create_env always operates in ST RAM, but
                   1816: 
                   1817:  * create_base might not.
                   1818: 
                   1819:  */
                   1820: 
                   1821: 
                   1822: 
                   1823: MEMREGION *
                   1824: 
1.1.1.4   root     1825: create_env(env, flags)
1.1       root     1826: 
                   1827:        const char *env;
                   1828: 
1.1.1.4   root     1829:        ulong flags;
                   1830: 
1.1       root     1831: {
                   1832: 
                   1833:        long size;
                   1834: 
                   1835:        MEMREGION *m;
                   1836: 
                   1837:        virtaddr v;
                   1838: 
                   1839:        const char *old;
                   1840: 
                   1841:        char *new;
                   1842: 
1.1.1.4   root     1843:        short protmode;
                   1844: 
1.1.1.3   root     1845: 
1.1       root     1846: 
                   1847:        if (!env) {
                   1848: 
                   1849:                env = ((BASEPAGE *)curproc->base)->p_env;
                   1850: 
                   1851:                        /* duplicate parent's environment */
                   1852: 
                   1853:        }
                   1854: 
                   1855:        size = 2;
                   1856: 
                   1857:        old = env;
                   1858: 
                   1859:        while (*env || *(env+1))
                   1860: 
                   1861:                env++,size++;
                   1862: 
1.1.1.3   root     1863: 
                   1864: 
1.1.1.4   root     1865:        protmode = (flags & F_PROTMODE) >> F_PROTSHIFT;
                   1866: 
                   1867: 
                   1868: 
                   1869:        v = alloc_region(core, size, protmode);
1.1.1.3   root     1870: 
                   1871:        /* if core fails, try alt */
                   1872: 
                   1873:        if (!v)
                   1874: 
1.1.1.4   root     1875:            v = alloc_region(alt, size, protmode);
1.1.1.3   root     1876: 
                   1877: 
1.1       root     1878: 
                   1879:        if (!v) {
                   1880: 
1.1.1.2   root     1881:                DEBUG(("create_env: alloc_region failed"));
1.1       root     1882: 
                   1883:                return (MEMREGION *)0;
                   1884: 
                   1885:        }
                   1886: 
                   1887:        m = addr2mem(v);
                   1888: 
                   1889: 
                   1890: 
                   1891: /* copy the old environment into the new */
                   1892: 
                   1893:        new = (char *) m->loc;
                   1894: 
1.1.1.3   root     1895:        TRACE(("copying environment: from %lx to %lx", old, new));
                   1896: 
1.1       root     1897:        while (size > 0) {
                   1898: 
                   1899:                *new++ = *old++;
                   1900: 
                   1901:                --size;
                   1902: 
                   1903:        }
                   1904: 
1.1.1.3   root     1905:        TRACE(("finished copying environment"));
                   1906: 
                   1907: 
                   1908: 
1.1       root     1909:        return m;
                   1910: 
                   1911: }
                   1912: 
                   1913: 
                   1914: 
                   1915: MEMREGION *
                   1916: 
                   1917: create_base(cmd, env, flags, prgsize)
                   1918: 
                   1919:        const char *cmd;
                   1920: 
                   1921:        MEMREGION *env;
                   1922: 
                   1923:        ulong flags, prgsize;
                   1924: 
                   1925: {
                   1926: 
                   1927:        long len, coresize, altsize;
                   1928: 
                   1929:        MMAP map;
                   1930: 
                   1931:        MEMREGION *m;
                   1932: 
                   1933:        BASEPAGE *b;
                   1934: 
1.1.1.3   root     1935:        short protmode;
                   1936: 
1.1       root     1937: 
                   1938: 
                   1939: /* if flags & F_ALTLOAD == 1, then we might decide to load in alternate
                   1940: 
                   1941:    RAM if enough is available. "enough" is: if more alt ram than ST ram,
                   1942: 
                   1943:    load there; otherwise, if more than (minalt+1)*128K alt ram available
                   1944: 
                   1945:    for heap space, load in alt ram ("minalt" is the high byte of flags)
                   1946: 
                   1947:  */
                   1948: 
                   1949:        if (flags & F_ALTLOAD) {
                   1950: 
                   1951:                coresize = max_rsize(core);
                   1952: 
                   1953:                altsize = max_rsize(alt);
                   1954: 
                   1955:                if (altsize >= coresize)
                   1956: 
                   1957:                        map = alt;
                   1958: 
                   1959:                else {
                   1960: 
1.1.1.2   root     1961:                        len = (flags & F_MINALT) >> 28L;
1.1       root     1962: 
                   1963:                        len = (len+1)*128*1024L + prgsize + 256;
                   1964: 
                   1965:                        if (altsize >= len)
                   1966: 
                   1967:                                map = alt;
                   1968: 
                   1969:                        else
                   1970: 
                   1971:                                map = core;
                   1972: 
                   1973:                }
                   1974: 
                   1975:        }
                   1976: 
                   1977:        else
                   1978: 
                   1979:                map = core;
                   1980: 
                   1981: 
                   1982: 
                   1983:        len = max_rsize(map);
                   1984: 
1.1.1.5 ! root     1985:        if (curproc->maxmem && len > curproc->maxmem) {
        !          1986: 
        !          1987:                len = curproc->maxmem;
        !          1988: 
        !          1989:        }
        !          1990: 
        !          1991: 
        !          1992: 
1.1.1.3   root     1993:        if (len < prgsize) {
                   1994: 
                   1995:            /* can't possibly load this file in its eligible regions */
                   1996: 
                   1997:            DEBUG(("create_base: max_rsize smaller than prgsize"));
                   1998: 
                   1999:            return 0;
                   2000: 
                   2001:        }
                   2002: 
1.1       root     2003: 
                   2004: 
                   2005: /* make sure that a little bit of memory is left over */
                   2006: 
                   2007:        if (len > 2*KEEP_MEM) {
                   2008: 
                   2009:                len -= KEEP_MEM;
                   2010: 
                   2011:        }
                   2012: 
1.1.1.3   root     2013: 
                   2014: 
                   2015:        protmode = (flags & F_PROTMODE) >> F_PROTSHIFT;
                   2016: 
                   2017: 
                   2018: 
                   2019:        m = addr2mem(alloc_region(map, len, protmode));
1.1       root     2020: 
                   2021:        if (!m) {
                   2022: 
1.1.1.2   root     2023:                DEBUG(("create_base: alloc_region failed"));
1.1       root     2024: 
                   2025:                return 0;
                   2026: 
                   2027:        }
                   2028: 
                   2029:        b = (BASEPAGE *)(m->loc);
                   2030: 
                   2031: 
                   2032: 
                   2033:        zero((char *)b, (long)sizeof(BASEPAGE));
                   2034: 
                   2035:        b->p_lowtpa = (long)b;
                   2036: 
                   2037:        b->p_hitpa = m->loc + m->len;
                   2038: 
                   2039:        b->p_env = (char *)env->loc;
                   2040: 
                   2041:        b->p_flags = flags;
                   2042: 
                   2043: 
                   2044: 
                   2045:        if (cmd)
                   2046: 
                   2047:                strncpy(b->p_cmdlin, cmd, 126);
                   2048: 
                   2049:        return m;
                   2050: 
                   2051: }
                   2052: 
                   2053: 
                   2054: 
                   2055: /*
                   2056: 
1.1.1.2   root     2057:  * load_region(): loads the program with the given file name
1.1       root     2058: 
1.1.1.2   root     2059:  * into a new region, and returns a pointer to that region. On
1.1       root     2060: 
1.1.1.2   root     2061:  * an error, returns 0 and leaves the error number in mint_errno.
1.1       root     2062: 
1.1.1.2   root     2063:  * "env" points to an already set up environment region, as returned
1.1       root     2064: 
1.1.1.3   root     2065:  * by create_env. On success, "xp" points to the file attributes, which
                   2066: 
                   2067:  * Pexec has already determined, and "fp" points to the programs
1.1       root     2068: 
1.1.1.3   root     2069:  * prgflags. "text" is a pointer to a MEMREGION
1.1       root     2070: 
1.1.1.2   root     2071:  * pointer, which will be set to the region occupied by the shared
1.1       root     2072: 
1.1.1.2   root     2073:  * text segment of this program (if applicable).
1.1       root     2074: 
1.1.1.2   root     2075:  */
1.1       root     2076: 
                   2077: 
                   2078: 
                   2079: MEMREGION *
                   2080: 
1.1.1.3   root     2081: load_region(filename, env, cmdlin, xp, text, fp)
1.1       root     2082: 
                   2083:        const char *filename;
                   2084: 
                   2085:        MEMREGION *env;
                   2086: 
                   2087:        const char *cmdlin;
                   2088: 
                   2089:        XATTR *xp;              /* attributes for the file just loaded */
                   2090: 
1.1.1.2   root     2091:        MEMREGION **text;       /* set to point to shared text region,
                   2092: 
                   2093:                                   if any */
                   2094: 
1.1.1.3   root     2095:        long *fp;               /* prgflags for this file */
                   2096: 
1.1       root     2097: {
                   2098: 
                   2099:        FILEPTR *f;
                   2100: 
                   2101:        DEVDRV *dev;
                   2102: 
1.1.1.2   root     2103:        MEMREGION *reg, *shtext;
1.1       root     2104: 
                   2105:        BASEPAGE *b;
                   2106: 
1.1.1.2   root     2107:        long size, start;
1.1       root     2108: 
1.1.1.2   root     2109:        FILEHEAD fh;
1.1       root     2110: 
                   2111: 
                   2112: 
1.1.1.2   root     2113: /* bug: this should be O_DENYW mode, not O_DENYNONE */
1.1       root     2114: 
1.1.1.2   root     2115: /* we must use O_DENYNONE because of the desktop and because of the
1.1       root     2116: 
1.1.1.2   root     2117:  * TOS file system brain-damage
1.1       root     2118: 
1.1.1.2   root     2119:  */
1.1       root     2120: 
                   2121:        f = do_open(filename, O_DENYNONE | O_EXEC, 0, xp);
                   2122: 
                   2123:        if (!f) {
                   2124: 
                   2125:                return 0;               /* mint_errno set by do_open */
                   2126: 
                   2127:        }
                   2128: 
                   2129: 
                   2130: 
1.1.1.2   root     2131:        dev = f->dev;
1.1       root     2132: 
1.1.1.2   root     2133:        size = (*dev->read)(f, (void *)&fh, (long)sizeof(fh));
1.1       root     2134: 
1.1.1.2   root     2135:        if (fh.fmagic != GEMDOS_MAGIC || size != (long)sizeof(fh)) {
1.1       root     2136: 
1.1.1.2   root     2137:                DEBUG(("load_region: file not executable"));
1.1       root     2138: 
                   2139:                mint_errno = ENOEXEC;
                   2140: 
                   2141: failed:
                   2142: 
                   2143:                do_close(f);
                   2144: 
                   2145:                return 0;
                   2146: 
                   2147:        }
                   2148: 
                   2149: 
                   2150: 
1.1.1.5 ! root     2151:        if (((fh.flag & F_PROTMODE) >> F_PROTSHIFT) > PROT_MAX_MODE) {
        !          2152: 
        !          2153:            DEBUG (("load_region: invalid protection mode changed to private"));
        !          2154: 
        !          2155:            fh.flag = (fh.flag & ~F_PROTMODE) | F_PROT_P;
        !          2156: 
        !          2157:        }
        !          2158: 
1.1.1.3   root     2159:        *fp = fh.flag;
                   2160: 
                   2161: 
                   2162: 
1.1.1.2   root     2163:        if (fh.flag & F_SHTEXT) {
                   2164: 
                   2165:                TRACE(("loading shared text segment"));
                   2166: 
                   2167:                shtext = get_text_seg(f, &fh, xp);
                   2168: 
                   2169:                if (!shtext) {
                   2170: 
                   2171:                        DEBUG(("load_region: unable to get shared text segment"));
                   2172: 
                   2173: /* mint_errno set in get_text_seg */
                   2174: 
                   2175:                        goto failed;
                   2176: 
                   2177:                }
                   2178: 
                   2179:                size = fh.fdata + fh.fbss;
                   2180: 
                   2181:        } else {
                   2182: 
                   2183:                size = fh.ftext + fh.fdata + fh.fbss;
                   2184: 
                   2185:                shtext = 0;
                   2186: 
                   2187:        }
                   2188: 
                   2189: 
1.1       root     2190: 
1.1.1.3   root     2191:        reg = create_base(cmdlin, env, fh.flag, size);
1.1       root     2192: 
1.1.1.3   root     2193:        if (reg && size+1024L > reg->len) {
1.1       root     2194: 
1.1.1.3   root     2195:                DEBUG(("load_region: insufficient memory to load"));
1.1       root     2196: 
1.1.1.3   root     2197:                detach_region(curproc, reg);
1.1       root     2198: 
1.1.1.3   root     2199:                reg = 0;
1.1       root     2200: 
                   2201:        }
                   2202: 
                   2203: 
                   2204: 
                   2205:        if (reg == 0) {
                   2206: 
1.1.1.2   root     2207:                if (shtext) {
                   2208: 
                   2209:                        detach_region(curproc, shtext);
                   2210: 
                   2211:                }
                   2212: 
1.1       root     2213:                mint_errno = ENSMEM;
                   2214: 
                   2215:                goto failed;
                   2216: 
                   2217:        }
                   2218: 
                   2219: 
                   2220: 
                   2221:        b = (BASEPAGE *)reg->loc;
                   2222: 
                   2223:        b->p_flags = fh.flag;
                   2224: 
1.1.1.2   root     2225:        if (shtext) {
                   2226: 
                   2227:                b->p_tbase = shtext->loc;
1.1       root     2228: 
1.1.1.2   root     2229:                b->p_tlen = 0;
1.1       root     2230: 
1.1.1.2   root     2231:                b->p_dbase = b->p_lowtpa + 256;
                   2232: 
                   2233:        } else {
                   2234: 
                   2235:                b->p_tbase = b->p_lowtpa + 256;
                   2236: 
                   2237:                b->p_tlen = fh.ftext;
                   2238: 
                   2239:                b->p_dbase = b->p_tbase + b->p_tlen;
                   2240: 
                   2241:        }
1.1       root     2242: 
                   2243:        b->p_dlen = fh.fdata;
                   2244: 
                   2245:        b->p_bbase = b->p_dbase + b->p_dlen;
                   2246: 
1.1.1.2   root     2247:        b->p_blen = fh.fbss;
1.1       root     2248: 
                   2249: 
                   2250: 
1.1.1.2   root     2251: /* if shared text, then we start loading at the end of the
1.1       root     2252: 
1.1.1.2   root     2253:  * text region, since that is already set up
                   2254: 
                   2255:  */
                   2256: 
                   2257:        if (shtext) {
                   2258: 
                   2259:        /* skip over text info */
                   2260: 
                   2261:                size = fh.fdata;
                   2262: 
                   2263:                start = fh.ftext;
                   2264: 
                   2265:        } else {
                   2266: 
                   2267:                size = fh.ftext + fh.fdata;
                   2268: 
                   2269:                start = 0;
                   2270: 
                   2271:        }
                   2272: 
                   2273: 
                   2274: 
                   2275:        mint_errno = (int)load_and_reloc(f, &fh, (char *)b+256, start,
                   2276: 
                   2277:                        size, b);
                   2278: 
                   2279: 
                   2280: 
                   2281:        if (mint_errno) {
1.1       root     2282: 
                   2283:                detach_region(curproc, reg);
                   2284: 
1.1.1.2   root     2285:                if (shtext) detach_region(curproc, shtext);
                   2286: 
1.1       root     2287:                goto failed;
                   2288: 
                   2289:        }
                   2290: 
                   2291: 
                   2292: 
                   2293:        if (fh.flag & F_FASTLOAD)                       /* fastload bit */
                   2294: 
                   2295:                size = b->p_blen;
                   2296: 
                   2297:        else
                   2298: 
                   2299:                size = b->p_hitpa - b->p_bbase;
                   2300: 
1.1.1.5 ! root     2301:        if (size > 0) {
        !          2302: 
        !          2303:                start = b->p_bbase;
        !          2304: 
        !          2305:                if (start & 1) {
        !          2306: 
        !          2307:                        *(char *)start = 0;
        !          2308: 
        !          2309:                        start++;
        !          2310: 
        !          2311:                        --size;
        !          2312: 
        !          2313:                }
        !          2314: 
        !          2315:                zero((char *)start, size);
        !          2316: 
        !          2317:        }
1.1       root     2318: 
                   2319: 
                   2320: 
1.1.1.2   root     2321:        do_close(f);
1.1       root     2322: 
1.1.1.2   root     2323:        *text = shtext;
1.1       root     2324: 
1.1.1.2   root     2325:        return reg;
1.1       root     2326: 
1.1.1.2   root     2327: }
                   2328: 
                   2329: 
                   2330: 
                   2331: /*
                   2332: 
                   2333:  * load_and_reloc(f, fh, where, start, nbytes): load and relocate from
                   2334: 
                   2335:  * the open GEMDOS executable file f "nbytes" bytes starting at offset
                   2336: 
                   2337:  * "start" (relative to the end of the file header, i.e. from the first
                   2338: 
                   2339:  * byte of the actual program image in the file). "where" is the address
                   2340: 
                   2341:  * in (physical) memory into which the loaded image must be placed; it is
                   2342: 
                   2343:  * assumed that "where" is big enough to hold "nbytes" bytes!
1.1       root     2344: 
                   2345:  */
                   2346: 
                   2347: 
                   2348: 
1.1.1.2   root     2349: long
                   2350: 
                   2351: load_and_reloc(f, fh, where, start, nbytes, base)
                   2352: 
                   2353:        FILEPTR *f;
                   2354: 
                   2355:        FILEHEAD *fh;
                   2356: 
                   2357:        char *where;
                   2358: 
                   2359:        long start;
                   2360: 
                   2361:        long nbytes;
                   2362: 
                   2363:        BASEPAGE *base;
                   2364: 
                   2365: {
                   2366: 
                   2367:        unsigned char c, *next;
                   2368: 
                   2369:        long r;
                   2370: 
                   2371:        DEVDRV *dev;
                   2372: 
                   2373: #define LRBUFSIZ 8196
                   2374: 
                   2375:        static unsigned char buffer[LRBUFSIZ];
                   2376: 
                   2377:        long fixup, size, bytes_read;
                   2378: 
                   2379:        long reloc;
                   2380: 
                   2381: 
                   2382: 
                   2383: 
                   2384: 
                   2385: TRACE(("load_and_reloc: %ld to %ld at %lx", start, nbytes+start, where));
                   2386: 
                   2387:        dev = f->dev;
                   2388: 
                   2389: 
                   2390: 
                   2391:        r = (*dev->lseek)(f, start+sizeof(FILEHEAD), SEEK_SET);
                   2392: 
                   2393:        if (r < 0) return r;
                   2394: 
                   2395:        r = (*dev->read)(f, where, nbytes);
                   2396: 
                   2397:        if (r != nbytes) {
                   2398: 
                   2399:                DEBUG(("load_region: unexpected EOF"));
                   2400: 
                   2401:                return ENOEXEC;
                   2402: 
                   2403:        }
                   2404: 
                   2405: 
                   2406: 
                   2407: /* now do the relocation */
                   2408: 
                   2409: /* skip over symbol table, etc. */
                   2410: 
                   2411:        r = (*dev->lseek)(f, sizeof(FILEHEAD) + fh->ftext + fh->fdata +
                   2412: 
                   2413:                        fh->fsym, SEEK_SET);
                   2414: 
                   2415:        if (r < 0) return ENOEXEC;
                   2416: 
                   2417: 
                   2418: 
                   2419:        if (fh->reloc != 0 || (*dev->read)(f, (char *)&fixup, 4L) != 4L
                   2420: 
                   2421:            || fixup == 0) {
                   2422: 
                   2423:                return 0;       /* no relocation to be performed */
                   2424: 
                   2425:        }
                   2426: 
                   2427: 
                   2428: 
                   2429:        size = LRBUFSIZ;
                   2430: 
                   2431:        bytes_read = 0;
                   2432: 
                   2433:        next = buffer;
                   2434: 
1.1       root     2435: 
                   2436: 
1.1.1.2   root     2437:        do {
                   2438: 
                   2439:                if (fixup >= nbytes + start) {
                   2440: 
                   2441:                        TRACE(("load_region: end of relocation at %ld", fixup));
                   2442: 
                   2443:                        break;
                   2444: 
                   2445:                }
                   2446: 
                   2447:                else if (fixup >= start) {
1.1       root     2448: 
1.1.1.2   root     2449:                        reloc = *((long *)(where + fixup - start));
                   2450: 
                   2451:                        if (reloc < fh->ftext) {
                   2452: 
                   2453:                                reloc += base->p_tbase;
                   2454: 
                   2455:                        } else if (reloc < fh->ftext + fh->fdata && base->p_dbase) {
                   2456: 
                   2457:                                reloc += base->p_dbase - fh->ftext;
                   2458: 
                   2459:                        } else if (reloc < fh->ftext + fh->fdata + fh->fbss && base->p_bbase) {
                   2460: 
                   2461:                                reloc += base->p_bbase - (fh->ftext + fh->fdata);
                   2462: 
                   2463:                        } else {
                   2464: 
                   2465:                                DEBUG(("load_region: bad relocation: %ld", reloc));
                   2466: 
                   2467:                                if (base->p_dbase)
                   2468: 
                   2469:                                    reloc += base->p_dbase - fh->ftext; /* assume data reloc */
                   2470: 
                   2471:                                else if (base->p_bbase)
                   2472: 
                   2473:                                    reloc += base->p_bbase - (fh->ftext + fh->fdata);
                   2474: 
                   2475:                                else
                   2476: 
                   2477:                                    return ENOEXEC;
                   2478: 
                   2479:                        }
                   2480: 
                   2481:                        *((long *)(where + fixup - start)) = reloc;
                   2482: 
                   2483:                }
1.1       root     2484: 
                   2485:                do {
                   2486: 
1.1.1.2   root     2487:                        if (!bytes_read) {
1.1       root     2488: 
1.1.1.2   root     2489:                                bytes_read =
1.1       root     2490: 
1.1.1.2   root     2491:                                    (*dev->read)(f,(char *)buffer,size);
                   2492: 
                   2493:                                next = buffer;
1.1       root     2494: 
                   2495:                        }
                   2496: 
1.1.1.2   root     2497:                        if (bytes_read < 0) {
1.1       root     2498: 
1.1.1.2   root     2499:                                DEBUG(("load_region: EOF in relocation"));
1.1       root     2500: 
1.1.1.2   root     2501:                                return ENOEXEC;
1.1       root     2502: 
1.1.1.2   root     2503:                        }
1.1       root     2504: 
1.1.1.2   root     2505:                        else if (bytes_read == 0)
1.1       root     2506: 
1.1.1.2   root     2507:                                c = 0;
1.1       root     2508: 
1.1.1.2   root     2509:                        else {
1.1       root     2510: 
1.1.1.2   root     2511:                                c = *next++; bytes_read--;
1.1       root     2512: 
1.1.1.2   root     2513:                        }
1.1       root     2514: 
1.1.1.2   root     2515:                        if (c == 1) fixup += 254;
1.1       root     2516: 
1.1.1.2   root     2517:                } while (c == 1);
1.1       root     2518: 
1.1.1.2   root     2519:                fixup += ( (unsigned) c) & 0xff;
1.1       root     2520: 
1.1.1.2   root     2521:        } while (c);
1.1       root     2522: 
                   2523: 
                   2524: 
1.1.1.2   root     2525:        return 0;
1.1       root     2526: 
1.1.1.2   root     2527: }
                   2528: 
                   2529: 
                   2530: 
                   2531: /*
                   2532: 
                   2533:  * function to check for existence of a shared text region
                   2534: 
                   2535:  * corresponding to file "f", and if none is found, to create one
                   2536: 
                   2537:  * the memory region being returned is attached to the current
                   2538: 
                   2539:  * process
                   2540: 
                   2541:  */
                   2542: 
                   2543: 
                   2544: 
                   2545: MEMREGION *
                   2546: 
                   2547: get_text_seg(f, fh, xp)
                   2548: 
                   2549:        FILEPTR *f;
                   2550: 
                   2551:        FILEHEAD *fh;
                   2552: 
                   2553:        XATTR *xp;
                   2554: 
                   2555: {
                   2556: 
                   2557:        SHTEXT *s;
1.1       root     2558: 
1.1.1.2   root     2559:        MEMREGION *m;
                   2560: 
                   2561:        long r;
                   2562: 
                   2563:        BASEPAGE b;
                   2564: 
                   2565: 
                   2566: 
                   2567:        s = text_reg;
                   2568: 
                   2569: 
                   2570: 
                   2571:        while(s) {
                   2572: 
1.1.1.3   root     2573:                if (s->f && samefile(&f->fc, &s->f->fc) &&
1.1.1.2   root     2574: 
                   2575:                    xp->mtime == s->mtime &&
                   2576: 
                   2577:                    xp->mdate == s->mdate)
                   2578: 
                   2579:                {
1.1       root     2580: 
1.1.1.2   root     2581:                        m = s->text;
1.1       root     2582: 
1.1.1.2   root     2583:                        if (attach_region(curproc, m)) {
1.1       root     2584: 
1.1.1.2   root     2585: TRACE(("re-using shared text region %lx", m));
                   2586: 
                   2587:                                return m;
                   2588: 
                   2589:                        }
                   2590: 
                   2591:                        else {
                   2592: 
                   2593:                                mint_errno = ENSMEM;
                   2594: 
                   2595:                                return 0;
                   2596: 
                   2597:                        }
                   2598: 
                   2599:                }
                   2600: 
                   2601:                s = s->next;
1.1       root     2602: 
                   2603:        }
                   2604: 
                   2605: 
                   2606: 
1.1.1.2   root     2607: /* hmmm, not found; OK, we'll have to create a new text region */
                   2608: 
                   2609: 
                   2610: 
                   2611:        s = kmalloc(SIZEOF(SHTEXT));
                   2612: 
                   2613:        if (!s) {
                   2614: 
                   2615:                mint_errno = ENSMEM;
                   2616: 
                   2617:                return 0;
                   2618: 
                   2619:        }
                   2620: 
                   2621:        m = 0;
                   2622: 
                   2623: /* actually, I can't see why loading in TT RAM is ever undesireable,
                   2624: 
                   2625:  * since shared text programs should be very clean (and since only
                   2626: 
                   2627:  * the text segment is going in there). But better safe than sorry.
                   2628: 
                   2629:  */
                   2630: 
                   2631:        if (fh->flag & F_ALTLOAD) {
                   2632: 
1.1.1.3   root     2633:                m = addr2mem(alloc_region(alt, fh->ftext, PROT_P));
1.1.1.2   root     2634: 
                   2635:        }
                   2636: 
                   2637:        if (!m)
                   2638: 
1.1.1.3   root     2639:                m = addr2mem(alloc_region(core, fh->ftext, PROT_P));
1.1.1.2   root     2640: 
                   2641: 
                   2642: 
                   2643:        if (!m) {
                   2644: 
                   2645:                kfree(s);
                   2646: 
                   2647:                mint_errno = ENSMEM;
                   2648: 
                   2649:                return 0;
                   2650: 
                   2651:        }
                   2652: 
                   2653: 
                   2654: 
                   2655: /* set up a fake "basepage" for load_and_reloc
                   2656: 
                   2657:  * note: the 0 values should make load_and_reloc
                   2658: 
                   2659:  * barf on any attempts at data relocation, since we have
                   2660: 
                   2661:  * no data segment
                   2662: 
                   2663:  */
                   2664: 
                   2665: TRACE(("attempting to create shared text region"));
                   2666: 
                   2667: 
                   2668: 
                   2669:        b.p_tbase = m->loc;
                   2670: 
                   2671:        b.p_tlen = fh->ftext;
                   2672: 
                   2673:        b.p_dbase = 0;
                   2674: 
                   2675:        b.p_dlen = 0;
                   2676: 
                   2677:        b.p_bbase = b.p_blen = 0;
                   2678: 
1.1       root     2679: 
1.1.1.2   root     2680: 
                   2681:        r = load_and_reloc(f, fh, (char *)m->loc, 0, fh->ftext, &b);
                   2682: 
                   2683:        if (r) {
                   2684: 
                   2685:                detach_region(curproc, m);
                   2686: 
                   2687:                kfree(s);
                   2688: 
                   2689:                return 0;
                   2690: 
                   2691:        }
                   2692: 
                   2693: 
                   2694: 
                   2695: /* region has valid shared text data */
                   2696: 
                   2697:        m->mflags |= M_SHTEXT;
                   2698: 
                   2699: 
                   2700: 
                   2701: /*
                   2702: 
                   2703:  * KLUDGE: to make sure we always have up to date shared text
                   2704: 
                   2705:  * info, even across a network, we leave the file passed
                   2706: 
                   2707:  * to us open with DENYWRITE mode, so that nobody will
                   2708: 
                   2709:  * modify it.
                   2710: 
                   2711:  */
                   2712: 
                   2713:        f->links++;     /* keep the file open longer */
                   2714: 
                   2715: 
                   2716: 
                   2717: /* BUG: what if someone already has the file open for
                   2718: 
                   2719:  * writing? Then we could get screwed...
                   2720: 
                   2721:  */
                   2722: 
                   2723:        f->flags = (f->flags & ~O_SHMODE) | O_DENYW;
                   2724: 
                   2725:        s->f = f;
                   2726: 
                   2727:        s->text = m;
                   2728: 
                   2729:        s->next = text_reg;
                   2730: 
                   2731:        s->mtime = xp->mtime;
                   2732: 
                   2733:        s->mdate = xp->mdate;
                   2734: 
                   2735:        text_reg = s;
                   2736: 
                   2737: TRACE(("shared text region %lx created", m));
                   2738: 
                   2739:        return m;
1.1       root     2740: 
                   2741: }
                   2742: 
                   2743: 
                   2744: 
                   2745: /*
                   2746: 
                   2747:  * exec_region(p, mem, thread): create a child process out of a mem region
                   2748: 
                   2749:  * "p" is the process structure set up by the parent; it may be "curproc",
                   2750: 
                   2751:  * if we're overlaying. "mem" is the loaded memory region returned by
                   2752: 
                   2753:  * "load region". Any open files (other than the standard handles) owned
                   2754: 
                   2755:  * by "p" are closed, and if thread !=0 all memory is released; the caller
                   2756: 
                   2757:  * must explicitly attach the environment and base region. The caller must
                   2758: 
                   2759:  * also put "p" on the appropriate queue (most likely READY_Q).
                   2760: 
                   2761:  */
                   2762: 
                   2763: 
                   2764: 
                   2765: extern long mint_dos(), mint_bios();
                   2766: 
                   2767: 
                   2768: 
                   2769: void rts() {}          /* dummy termination routine */
                   2770: 
                   2771: 
                   2772: 
                   2773: PROC *
                   2774: 
                   2775: exec_region(p, mem, thread)
                   2776: 
                   2777:        PROC      *p;
                   2778: 
                   2779:        MEMREGION *mem;
                   2780: 
                   2781:        int thread;
                   2782: 
                   2783: {
                   2784: 
                   2785:        BASEPAGE *b;
                   2786: 
                   2787:        FILEPTR *f;
                   2788: 
                   2789:        int i;
                   2790: 
                   2791:        MEMREGION *m;
                   2792: 
                   2793: 
                   2794: 
1.1.1.2   root     2795:        TRACE(("exec_region"));
1.1       root     2796: 
                   2797: 
                   2798: 
                   2799:        b = (BASEPAGE *) mem->loc;
                   2800: 
                   2801: 
                   2802: 
1.1.1.2   root     2803:        cpush((void *)b->p_tbase, b->p_tlen);   /* flush cached versions of the text */
                   2804: 
                   2805:        
                   2806: 
1.1       root     2807: /* set some (undocumented) variables in the basepage */
                   2808: 
                   2809:        b->p_defdrv = p->curdrv;
                   2810: 
                   2811:        for (i = 0; i < 6; i++)
                   2812: 
                   2813:                b->p_devx[i] = i;
                   2814: 
                   2815: 
                   2816: 
                   2817:        p->dta = (DTABUF *)(b->p_dta = &b->p_cmdlin[0]);
                   2818: 
                   2819:        p->base = b;
                   2820: 
                   2821: 
                   2822: 
                   2823: /* close extra open files */
                   2824: 
                   2825:        for (i = MIN_OPEN; i < MAX_OPEN; i++) {
                   2826: 
1.1.1.2   root     2827:                if ( (f = p->handle[i]) != 0 && (p->fdflags[i] & FD_CLOEXEC) ) {
1.1       root     2828: 
                   2829:                        do_pclose(p, f);
                   2830: 
                   2831:                        p->handle[i] = 0;
                   2832: 
                   2833:                }
                   2834: 
                   2835:        }
                   2836: 
                   2837: 
                   2838: 
                   2839: /* initialize memory */
                   2840: 
                   2841:        recalc_maxmem(p);
                   2842: 
                   2843:        if (p->maxmem) {
                   2844: 
                   2845:                shrink_region(mem, p->maxmem);
                   2846: 
                   2847:                b->p_hitpa = b->p_lowtpa + mem->len;
                   2848: 
                   2849:        }
                   2850: 
                   2851: 
                   2852: 
                   2853:        p->memflags = b->p_flags;
                   2854: 
                   2855: 
                   2856: 
                   2857:        if (!thread) {
                   2858: 
                   2859:                for (i = 0; i < p->num_reg; i++) {
                   2860: 
                   2861:                        m = p->mem[i];
                   2862: 
                   2863:                        if (m) {
                   2864: 
                   2865:                                m->links--;
                   2866: 
                   2867:                                if (m->links <= 0)
                   2868: 
                   2869:                                        free_region(m);
                   2870: 
                   2871:                        }
                   2872: 
                   2873:                }
                   2874: 
                   2875:                if (p->num_reg > NUM_REGIONS) {
                   2876: 
1.1.1.3   root     2877:                        /*
                   2878: 
                   2879:                         * If the proc struct has a larger mem array than
                   2880: 
                   2881:                         * the default, then free it and allocate a
                   2882: 
                   2883:                         * default-sized one.
                   2884: 
                   2885:                         */
1.1       root     2886: 
                   2887: 
                   2888: 
1.1.1.3   root     2889:                        /*
1.1       root     2890: 
1.1.1.3   root     2891:                         * hoo ha! Memory protection problem here. Use
                   2892: 
                   2893:                         * temps and pre-clear p->mem so memprot doesn't try
                   2894: 
                   2895:                         * to walk these structures as we're freeing and
                   2896: 
                   2897:                         * reallocating them!  (Calling kmalloc can cause
                   2898: 
                   2899:                         * a table walk if the alloc results in calling
                   2900: 
                   2901:                         * get_region.)
                   2902: 
                   2903:                         */
                   2904: 
                   2905:                        void *pmem, *paddr;
                   2906: 
                   2907: 
                   2908: 
                   2909:                        pmem = p->mem;
                   2910: 
                   2911:                        paddr = p->addr;
                   2912: 
                   2913:                        p->mem = NULL; p->addr = NULL;
                   2914: 
                   2915:                        kfree(pmem); kfree(paddr);
                   2916: 
                   2917: 
                   2918: 
                   2919:                        pmem = kmalloc(NUM_REGIONS * SIZEOF(MEMREGION *));
                   2920: 
                   2921:                        paddr = kmalloc(NUM_REGIONS * SIZEOF(virtaddr));
                   2922: 
                   2923:                        assert(pmem && paddr);
                   2924: 
                   2925:                        p->mem = pmem;
                   2926: 
                   2927:                        p->addr = paddr;
1.1       root     2928: 
                   2929:                        p->num_reg = NUM_REGIONS;
                   2930: 
                   2931:                }
                   2932: 
                   2933:                zero((char *)p->mem, (p->num_reg)*SIZEOF(MEMREGION *));
                   2934: 
                   2935:                zero((char *)p->addr, (p->num_reg)*SIZEOF(virtaddr));
                   2936: 
                   2937:        }
                   2938: 
                   2939: 
                   2940: 
                   2941: /* initialize signals */
                   2942: 
                   2943:        p->sigmask = 0;
                   2944: 
                   2945:        for (i = 0; i < NSIG; i++) {
                   2946: 
                   2947:                if (p->sighandle[i] != SIG_IGN) {
                   2948: 
                   2949:                        p->sighandle[i] = SIG_DFL;
                   2950: 
                   2951:                        p->sigflags[i] = 0;
                   2952: 
                   2953:                        p->sigextra[i] = 0;
                   2954: 
                   2955:                }
                   2956: 
                   2957:        }
                   2958: 
                   2959: 
                   2960: 
                   2961: /* zero the user registers, and set the FPU in a "clear" state */
                   2962: 
                   2963:        for (i = 0; i < 15; i++)
                   2964: 
                   2965:                p->ctxt[CURRENT].regs[i] = 0;
                   2966: 
                   2967:        p->ctxt[CURRENT].sr = 0;
                   2968: 
                   2969:        p->ctxt[CURRENT].fstate[0] = 0;
                   2970: 
                   2971: 
                   2972: 
                   2973: /* set PC, stack registers, etc. appropriately */
                   2974: 
                   2975:        p->ctxt[CURRENT].pc = b->p_tbase;
                   2976: 
                   2977: 
                   2978: 
                   2979: /* The "-0x20" is to make sure that syscall.s won't run past the end of
                   2980: 
                   2981:  * memory when the user makes a system call and doesn't push very many
                   2982: 
                   2983:  * parameters -- syscall always tries to copy the maximum possible number
                   2984: 
                   2985:  * of parms.
                   2986: 
                   2987:  *
                   2988: 
                   2989:  * NOTE: there's a sanity check here in case programs Mshrink a basepage
                   2990: 
                   2991:  * without fixing the p_hitpa field in the basepage; this is to ensure
                   2992: 
                   2993:  * compatibility with older versions of MiNT, which ignore p_hitpa.
                   2994: 
                   2995:  */
                   2996: 
                   2997:        if (valid_address(b->p_hitpa - 0x20))
                   2998: 
                   2999:                p->ctxt[CURRENT].usp = b->p_hitpa - 0x20;
                   3000: 
                   3001:        else
                   3002: 
                   3003:                p->ctxt[CURRENT].usp = mem->loc + mem->len - 0x20;
                   3004: 
                   3005: 
                   3006: 
                   3007:        p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
                   3008: 
                   3009:        p->ctxt[CURRENT].term_vec = (long)rts;
                   3010: 
                   3011: 
                   3012: 
                   3013: /* set up stack for process */
                   3014: 
                   3015:        *((long *)(p->ctxt[CURRENT].usp + 4)) = (long) b;
                   3016: 
                   3017: 
                   3018: 
                   3019: /* check for a valid text region. some compilers (e.g. Lattice 3) just throw
                   3020: 
                   3021:    everything into the text region, including data; fork() must be careful
                   3022: 
                   3023:    to save the whole region, then. We assume that if the compiler (or
                   3024: 
                   3025:    assembler, or whatever) goes to the trouble of making separate text, data,
                   3026: 
                   3027:    and bss regions, then the text region is code and isn't modified and
                   3028: 
                   3029:    fork doesn't have to save it.
                   3030: 
                   3031:  */
                   3032: 
1.1.1.2   root     3033:        if (b->p_blen != 0 || b->p_dlen != 0)
1.1       root     3034: 
                   3035:                p->txtsize = b->p_tlen;
                   3036: 
                   3037:        else
                   3038: 
                   3039:                p->txtsize = 0;
                   3040: 
                   3041: 
                   3042: 
                   3043: /*
                   3044: 
                   3045:  * An ugly hack: dLibs tries to poke around in the parent's address space
                   3046: 
                   3047:  * to find stuff. For now, we'll allow this by faking a pointer into
                   3048: 
                   3049:  * the parent's address space in the place in the basepage where dLibs is
                   3050: 
                   3051:  * expecting it. This ugly hack only works correctly if the Pexec'ing
                   3052: 
                   3053:  * program (i.e. curproc) is in user mode.
                   3054: 
                   3055:  */
                   3056: 
1.1.1.2   root     3057:        if (curproc != rootproc)
                   3058: 
                   3059:                curproc->base->p_usp = curproc->ctxt[SYSCALL].usp - 0x32;
1.1       root     3060: 
                   3061: 
                   3062: 
                   3063:        return p;
                   3064: 
                   3065: }
                   3066: 
                   3067: 
                   3068: 
                   3069: /*
                   3070: 
                   3071:  * misc. utility routines
                   3072: 
                   3073:  */
                   3074: 
                   3075: 
                   3076: 
                   3077: /*
                   3078: 
                   3079:  * long memused(p): return total memory allocated to process p
                   3080: 
                   3081:  */
                   3082: 
                   3083: 
                   3084: 
                   3085: long
                   3086: 
                   3087: memused(p)
                   3088: 
                   3089:        PROC *p;
                   3090: 
                   3091: {
                   3092: 
                   3093:        int i;
                   3094: 
                   3095:        long size;
                   3096: 
                   3097: 
                   3098: 
1.1.1.3   root     3099:        /* a ZOMBIE owns no memory and its mem array ptr is zero */
                   3100: 
                   3101:        if (p->mem == NULL) return 0;
                   3102: 
                   3103: 
                   3104: 
1.1       root     3105:        size = 0;
                   3106: 
                   3107:        for (i = 0; i < p->num_reg; i++) {
                   3108: 
                   3109:                if (p->mem[i])
                   3110: 
                   3111:                        size += p->mem[i]->len;
                   3112: 
                   3113:        }
                   3114: 
                   3115:        return size;
                   3116: 
                   3117: }
                   3118: 
                   3119: 
                   3120: 
                   3121: /* 
                   3122: 
                   3123:  * recalculate the maximum memory limit on a process; this limit depends
                   3124: 
                   3125:  * on the max. allocated memory and max. total memory limits set by
                   3126: 
                   3127:  * p_setlimit (see dos.c), and (perhaps) on the size of the program
                   3128: 
                   3129:  * that the process is executing. whenever any of these things
                   3130: 
                   3131:  * change (through p_exec or p_setlimit) this routine must be called
                   3132: 
                   3133:  */
                   3134: 
                   3135: 
                   3136: 
                   3137: void
                   3138: 
                   3139: recalc_maxmem(p)
                   3140: 
                   3141:        PROC *p;
                   3142: 
                   3143: {
                   3144: 
                   3145:        BASEPAGE *b;
                   3146: 
                   3147:        long siz;
                   3148: 
                   3149: 
                   3150: 
                   3151:        b = (BASEPAGE *)p->base;
                   3152: 
                   3153:        if (b)
                   3154: 
                   3155:                siz = b->p_tlen + b->p_dlen + b->p_blen;
                   3156: 
                   3157:        else
                   3158: 
                   3159:                siz = 0;
                   3160: 
                   3161:        p->maxmem = 0;
                   3162: 
                   3163:        if (p->maxdata) {
                   3164: 
                   3165:                p->maxmem = p->maxdata + siz;
                   3166: 
                   3167:        }
                   3168: 
                   3169: 
                   3170: 
                   3171:        if (p->maxcore) {
                   3172: 
                   3173:                if (p->maxmem == 0 || p->maxmem > p->maxcore)
                   3174: 
                   3175:                        p->maxmem = p->maxcore;
                   3176: 
                   3177:        }
                   3178: 
                   3179:        if (p->maxmem && p->maxmem < siz)
                   3180: 
                   3181:                p->maxmem = siz;
                   3182: 
                   3183: }
                   3184: 
                   3185: 
                   3186: 
                   3187: /*
                   3188: 
                   3189:  * valid_address: checks to see if the indicated address falls within
                   3190: 
                   3191:  * memory attached to the current process
                   3192: 
                   3193:  */
                   3194: 
                   3195: 
                   3196: 
                   3197: int
                   3198: 
                   3199: valid_address(addr)
                   3200: 
                   3201:        long addr;
                   3202: 
                   3203: {
                   3204: 
                   3205:        int i;
                   3206: 
                   3207:        MEMREGION *m;
                   3208: 
                   3209: 
                   3210: 
                   3211:        for (i = 0; i < curproc->num_reg; i++) {
                   3212: 
                   3213:                if ((m = curproc->mem[i]) != 0) {
                   3214: 
                   3215:                        if (addr >= m->loc && addr <= m->loc + m->len)
                   3216: 
                   3217:                                return 1;
                   3218: 
                   3219:                }
                   3220: 
                   3221:        }
                   3222: 
                   3223:        return 0;
                   3224: 
                   3225: }
                   3226: 
                   3227: 
                   3228: 
                   3229: /*
                   3230: 
1.1.1.3   root     3231:  * convert an address to a memory region; this works only in
                   3232: 
                   3233:  * the ST RAM and TT RAM maps, and will fail for memory that
                   3234: 
                   3235:  * MiNT doesn't own or which is virtualized
                   3236: 
                   3237:  */
                   3238: 
                   3239: 
                   3240: 
                   3241: MEMREGION *
                   3242: 
                   3243: addr2region(addr)
                   3244: 
                   3245:        long addr;
                   3246: 
                   3247: {
                   3248: 
                   3249:        unsigned long ua = (unsigned long) addr;
                   3250: 
                   3251: 
                   3252: 
                   3253:        extern ulong mint_top_st, mint_top_tt;
                   3254: 
                   3255:        MEMREGION *r;
                   3256: 
                   3257:        MMAP map;
                   3258: 
                   3259: 
                   3260: 
                   3261:        if (ua < mint_top_st) {
                   3262: 
                   3263:                map = core;
                   3264: 
                   3265:        } else if (ua < mint_top_tt) {
                   3266: 
                   3267:                map = alt;
                   3268: 
                   3269:        } else {
                   3270: 
                   3271:                return 0;
                   3272: 
                   3273:        }
                   3274: 
                   3275: 
                   3276: 
                   3277:        for (r = *map; r; r = r->next) {
                   3278: 
                   3279:                if (addr >= r->loc && addr < r->loc + r->len)
                   3280: 
                   3281:                        return r;
                   3282: 
                   3283:        }
                   3284: 
                   3285:        return 0;
                   3286: 
                   3287: }
                   3288: 
                   3289: 
                   3290: 
                   3291: /*
                   3292: 
1.1       root     3293:  * some debugging stuff
                   3294: 
                   3295:  */
                   3296: 
                   3297: 
                   3298: 
                   3299: void
                   3300: 
1.1.1.3   root     3301: DUMP_ALL_MEM()
                   3302: 
                   3303: {
                   3304: 
1.1.1.5 ! root     3305: #ifdef DEBUG_INFO
        !          3306: 
1.1.1.3   root     3307:        DUMPMEM(ker);
                   3308: 
                   3309:        DUMPMEM(core);
                   3310: 
                   3311:        DUMPMEM(alt);
                   3312: 
1.1.1.5 ! root     3313:        FORCE("new memory region descriptor pages: %d", num_reg_requests);
        !          3314: 
        !          3315: #endif
        !          3316: 
1.1.1.3   root     3317: }
                   3318: 
                   3319: 
                   3320: 
                   3321: void
                   3322: 
1.1       root     3323: DUMPMEM(map)
                   3324: 
                   3325:        MMAP map;
                   3326: 
                   3327: {
                   3328: 
1.1.1.4   root     3329: #ifdef DEBUG_INFO
1.1.1.2   root     3330: 
1.1       root     3331:        MEMREGION *m;
                   3332: 
                   3333: 
                   3334: 
                   3335:        m = *map;
                   3336: 
1.1.1.3   root     3337:        FORCE("%s memory dump: starting at region %lx",
                   3338: 
                   3339:                (map == ker ? "ker" : (map == core ? "core" : "alt")), m);
1.1       root     3340: 
                   3341:        while (m) {
                   3342: 
1.1.1.3   root     3343:            FORCE("%ld bytes at %lx (%d links); next region %lx", m->len, m->loc,
1.1       root     3344: 
1.1.1.3   root     3345:                    m->links, m->next);
1.1       root     3346: 
1.1.1.3   root     3347:            m = m->next;
1.1       root     3348: 
                   3349:        }
                   3350: 
1.1.1.4   root     3351: #else
                   3352: 
                   3353:        UNUSED(map);
                   3354: 
1.1.1.2   root     3355: #endif
                   3356: 
1.1       root     3357: }
                   3358: 
                   3359: 
                   3360: 
                   3361: void
                   3362: 
                   3363: sanity_check(map)
                   3364: 
                   3365:        MMAP map;
                   3366: 
                   3367: {
                   3368: 
                   3369: #ifdef SANITY_CHECK
                   3370: 
                   3371:        MEMREGION *m, *nxt;
                   3372: 
                   3373:        long end;
                   3374: 
                   3375: 
                   3376: 
                   3377:        m = *map;
                   3378: 
                   3379:        while (m) {
                   3380: 
                   3381:                nxt = m->next;
                   3382: 
                   3383:                if (nxt) {
                   3384: 
                   3385:                        end = m->loc + m->len;
                   3386: 
                   3387:                        if (m->loc < nxt->loc && end > nxt->loc) {
                   3388: 
                   3389:                                FATAL("MEMORY CHAIN CORRUPTED");
                   3390: 
                   3391:                        }
                   3392: 
                   3393:                        else if (end == nxt->loc && ISFREE(m) && ISFREE(nxt)) {
                   3394: 
                   3395:                                ALERT("Continguous memory regions not merged!");
                   3396: 
                   3397:                        }
                   3398: 
                   3399:                }
                   3400: 
                   3401:                m = nxt;
                   3402: 
                   3403:        }
                   3404: 
1.1.1.2   root     3405: #else
                   3406: 
                   3407:        UNUSED(map);
                   3408: 
1.1       root     3409: #endif
                   3410: 
                   3411: }
                   3412: 

unix.superglobalmegacorp.com

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