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

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

unix.superglobalmegacorp.com

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