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

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

unix.superglobalmegacorp.com

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