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

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

unix.superglobalmegacorp.com

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