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

1.1       root        1: /*
                      2: 
                      3:  * Copyright 1992 Atari Corporation.
                      4: 
                      5:  * All rights reserved.
                      6: 
                      7:  */
                      8: 
                      9: 
                     10: 
                     11: #include "mint.h"
                     12: 
                     13: 
                     14: 
                     15: /* macro for testing whether a memory region is free */
                     16: 
                     17: #define ISFREE(m) ((m)->links == 0)
                     18: 
                     19: 
                     20: 
                     21: /*
                     22: 
                     23:  * long
                     24: 
                     25:  * realloc_region(MEMREGION *reg, long newsize):
                     26: 
                     27:  * attempt to resize "reg" to the indicated size. If newsize is
                     28: 
                     29:  * less than the current region size, the call always
                     30: 
                     31:  * succeeds; otherwise, we look for free blocks next to the
                     32: 
                     33:  * region, and try to merge these.
                     34: 
                     35:  *
                     36: 
                     37:  * If newsize == -1L, simply returns the maximum size that
                     38: 
                     39:  * the block could be allocated to.
                     40: 
                     41:  *
                     42: 
                     43:  * Returns: the (physical) address of the new bottom of the
                     44: 
                     45:  * region, or 0L if the resize attempt fails.
                     46: 
                     47:  *
                     48: 
                     49:  * NOTES: if reg == 0, this call does a last-fit allocation
                     50: 
                     51:  * of memory of the requested size, and returns a MEMREGION *
                     52: 
                     53:  * (cast to a long) pointing at the last region that works
                     54: 
                     55:  *
                     56: 
                     57:  * This call works ONLY in the "core" memory region (aka ST RAM)
                     58: 
                     59:  * and only on non-shared text regions.
                     60: 
                     61:  */
                     62: 
                     63: 
                     64: 
                     65: long
                     66: 
                     67: realloc_region(reg, newsize)
                     68: 
                     69:        MEMREGION *reg;
                     70: 
                     71:        long newsize;
                     72: 
                     73: {
                     74: 
                     75:        MMAP map;
                     76: 
                     77:        MEMREGION *m,*prevptr;
                     78: 
                     79:        long oldsize, trysize;
                     80: 
                     81: 
                     82: 
                     83:        if (newsize != -1L)
                     84: 
                     85:                newsize = ROUND(newsize);
                     86: 
                     87:        oldsize = reg->len;
                     88: 
                     89: 
                     90: 
                     91:        if ( reg == 0 || (reg->mflags & M_CORE))
                     92: 
                     93:                map = core;
                     94: 
                     95:        else {
                     96: 
                     97:                return 0;
                     98: 
                     99:        }
                    100: 
                    101: 
                    102: 
                    103: /* last fit allocation: this is pretty straightforward,
                    104: 
                    105:  * we just look for the last block that would work
                    106: 
                    107:  * and slice off the top part of it.
                    108: 
                    109:  * problem: we don't know what the "last block that would fit"
                    110: 
                    111:  * is for newsize == -1L, so we look for the biggest block
                    112: 
                    113:  */
                    114: 
                    115:        if (reg == 0) {
                    116: 
                    117:                MEMREGION *lastfit = 0;
                    118: 
                    119:                MEMREGION *newm = new_region();
                    120: 
                    121: 
                    122: 
                    123:                for (m = *map; m; m = m->next) {
                    124: 
                    125:                        if (ISFREE(m)) {
                    126: 
                    127:                                if (newsize == -1L && lastfit
                    128: 
                    129:                                    && m->len >= lastfit->len)
                    130: 
                    131:                                        lastfit = m;
                    132: 
                    133:                                else if (m->len >= newsize)
                    134: 
                    135:                                        lastfit = m;
                    136: 
                    137:                        }
                    138: 
                    139:                }
                    140: 
                    141:                if (!lastfit)
                    142: 
                    143:                        return 0;
                    144: 
                    145: 
                    146: 
                    147:                if (newsize == -1L)
                    148: 
                    149:                        return lastfit->len;
                    150: 
                    151: 
                    152: 
                    153:        /* if the sizes match exactly, we save a bit of work */
                    154: 
                    155:                if (lastfit->len == newsize) {
                    156: 
                    157:                        if (newm) dispose_region(newm);
                    158: 
                    159:                        lastfit->links++;
                    160: 
                    161:                        mark_region(lastfit, PROT_G);
                    162: 
                    163:                        return (long)lastfit;
                    164: 
                    165:                }
                    166: 
                    167:                if (!newm) return 0;    /* can't get a new region */
                    168: 
                    169: 
                    170: 
                    171:        /* chop off the top "newsize" bytes from lastfit */
                    172: 
                    173:        /* and add it to "newm" */
                    174: 
                    175:                lastfit->len -= newsize;
                    176: 
                    177:                newm->loc = lastfit->loc + lastfit->len;
                    178: 
                    179:                newm->len = newsize;
                    180: 
                    181:                newm->mflags = lastfit->mflags & M_MAP;
                    182: 
                    183:                newm->links++;
                    184: 
                    185:                newm->next = lastfit->next;
                    186: 
                    187:                lastfit->next = newm;
                    188: 
                    189:                mark_region(newm, PROT_G);
                    190: 
                    191:                return (long)newm;
                    192: 
                    193:        }
                    194: 
                    195: 
                    196: 
                    197: /* check for trivial resize */
                    198: 
                    199:        if (newsize == oldsize) {
                    200: 
                    201:                return reg->loc;
                    202: 
                    203:        }
                    204: 
                    205: 
                    206: 
                    207: /*
                    208: 
                    209:  * find the block just before ours
                    210: 
                    211:  */
                    212: 
                    213:        if (*map == reg)
                    214: 
                    215:                prevptr = 0;
                    216: 
                    217:        else {
                    218: 
                    219:                prevptr = *map;
                    220: 
                    221:                while (prevptr->next != reg && prevptr) {
                    222: 
                    223:                        prevptr = prevptr->next;
                    224: 
                    225:                }
                    226: 
                    227:        }
                    228: 
                    229: /*
                    230: 
                    231:  * If we're shrinking the block, there's not too much to
                    232: 
                    233:  * do (we just free the first "oldsize-newsize" bytes by
                    234: 
                    235:  * creating a new region, putting those bytes into it,
                    236: 
                    237:  * and freeing it).
                    238: 
                    239:  */
                    240: 
                    241:        if (newsize < oldsize && newsize != -1L) {
                    242: 
                    243: 
                    244: 
                    245:                if (prevptr && ISFREE(prevptr)) {
                    246: 
                    247: /* add this memory to the previous free region */
                    248: 
                    249:                        prevptr->len += oldsize - newsize;
                    250: 
                    251:                        reg->loc += oldsize - newsize;
                    252: 
                    253:                        reg->len -= oldsize - newsize;
                    254: 
                    255:                        mark_region(prevptr, PROT_I);
                    256: 
                    257:                        mark_region(reg, PROT_G);
                    258: 
                    259:                        return reg->loc;
                    260: 
                    261:                }
                    262: 
                    263: 
                    264: 
                    265: /* make a new region for the freed memory */
                    266: 
                    267:                m = new_region();
                    268: 
                    269:                if (!m) {
                    270: 
                    271:                /* oops, couldn't get a region -- we lose */
                    272: 
                    273:                /* punt and pretend we succeeded; after all,
                    274: 
                    275:                 * we have enough memory!
                    276: 
                    277:                 */
                    278: 
                    279:                        return reg->loc;
                    280: 
                    281:                }
                    282: 
                    283: 
                    284: 
                    285:        /* set up the fake region */
                    286: 
                    287:                m->links = 0;
                    288: 
                    289:                m->mflags = reg->mflags & M_MAP;
                    290: 
                    291:                m->loc = reg->loc;
                    292: 
                    293:                m->len = oldsize - newsize;
                    294: 
                    295:        /* update our region (it's smaller now) */
                    296: 
                    297:                reg->loc += m->len;
                    298: 
                    299:                reg->len -= m->len;
                    300: 
                    301:        /* link the region in just ahead of us */
                    302: 
                    303:                if (prevptr)
                    304: 
                    305:                        prevptr->next = m;
                    306: 
                    307:                else
                    308: 
                    309:                        *map = m;
                    310: 
                    311:                m->next = reg;
                    312: 
                    313:                mark_region(m, PROT_I);
                    314: 
                    315:                mark_region(reg, PROT_G);
                    316: 
                    317:                return reg->loc;
                    318: 
                    319:        }
                    320: 
                    321: 
                    322: 
                    323: /* OK, here we have to grow the region: to do this, we first try adding
                    324: 
                    325:  * bytes from the region after us (if any) and then the region before
                    326: 
                    327:  * us
                    328: 
                    329:  */
                    330: 
                    331:        trysize = oldsize;
                    332: 
                    333:        if (reg->next && ISFREE(reg->next) &&
                    334: 
                    335:            (reg->loc + reg->len == reg->next->loc)) {
                    336: 
                    337:                trysize += reg->next->len;
                    338: 
                    339:        }
                    340: 
                    341:        if (prevptr && ISFREE(prevptr) &&
                    342: 
                    343:            (prevptr->loc + prevptr->len == reg->loc)) {
                    344: 
                    345:                trysize += prevptr->len;
                    346: 
                    347:        }
                    348: 
                    349:        if (trysize < newsize) {
                    350: 
                    351: FORCE("realloc_region: need %ld bytes, only have %ld", trysize, newsize);
                    352: 
                    353:                return 0;       /* not enough room */
                    354: 
                    355:        }
                    356: 
                    357: 
                    358: 
                    359:        if (newsize == -1L)     /* size inquiry only?? */
                    360: 
                    361:                return trysize;
                    362: 
                    363: 
                    364: 
                    365: /* BUG: we can be a bit too aggressive at sweeping up
                    366: 
                    367:  * memory regions coming after our region; on the other
                    368: 
                    369:  * hand, unless something goes seriously wrong there
                    370: 
                    371:  * never should *be* any such regions
                    372: 
                    373:  */
                    374: 
                    375:        if (reg->next && ISFREE(reg->next) && 
                    376: 
                    377:            (reg->loc + reg->len == reg->next->loc)) {
                    378: 
                    379:                MEMREGION *foo = reg->next;
                    380: 
                    381: 
                    382: 
                    383:                reg->len += foo->len;
                    384: 
                    385:                reg->next = foo->next;
                    386: 
                    387:                dispose_region(foo);
                    388: 
                    389:                mark_region(reg, PROT_G);
                    390: 
                    391:                if (reg->len >= newsize)
                    392: 
                    393:                        return reg->loc;
                    394: 
                    395:                oldsize = reg->len;
                    396: 
                    397:        }
                    398: 
                    399:        assert(prevptr && ISFREE(prevptr) &&
                    400: 
                    401:                prevptr->loc + prevptr->len == reg->loc);
                    402: 
                    403: 
                    404: 
                    405:        if (newsize > oldsize) {
                    406: 
                    407:                reg->loc -= (newsize - oldsize);
                    408: 
                    409:                reg->len += (newsize - oldsize);
                    410: 
                    411:                prevptr->len -= (newsize - oldsize);
                    412: 
                    413:                if (prevptr->len == 0) {
                    414: 
                    415:        /* hmmm, we used up the whole region -- we must dispose of the
                    416: 
                    417:         * region descriptor
                    418: 
                    419:         */
                    420: 
                    421:                        if (*map == prevptr)
                    422: 
                    423:                                *map = prevptr->next;
                    424: 
                    425:                        else {
                    426: 
                    427:                                for (m = *map; m; m = m->next) {
                    428: 
                    429:                                        if (m->next == prevptr) {
                    430: 
                    431:                                                m->next = prevptr->next;
                    432: 
                    433:                                                break;
                    434: 
                    435:                                        }
                    436: 
                    437:                                }
                    438: 
                    439:                        }
                    440: 
                    441:                        dispose_region(prevptr);
                    442: 
                    443:                }
                    444: 
                    445:                mark_region(reg, PROT_G);
                    446: 
                    447:        }
                    448: 
                    449: 
                    450: 
                    451: /* finally! we return the new starting address of "our" region */
                    452: 
                    453:        return reg->loc;
                    454: 
                    455: }
                    456: 
                    457: 
                    458: 
                    459: 
                    460: 
                    461: 
                    462: 
                    463: /*
                    464: 
                    465:  * s_realloc emulation: this isn't quite perfect, since the memory
                    466: 
                    467:  * used up by the "first" screen will be wasted (we could recover
                    468: 
                    469:  * this if we knew the screen start and size, and manually built
                    470: 
                    471:  * a region for that screen and linked it into the "core" map
                    472: 
                    473:  * (probably at the end))
                    474: 
                    475:  * We must always ensure a 256 byte "pad" area is available after
                    476: 
                    477:  * the screen (so that it doesn't abut the end of memory)
                    478: 
                    479:  */
                    480: 
                    481: 
                    482: 
                    483: MEMREGION *screen_region = 0;
                    484: 
                    485: 
                    486: 
                    487: #define PAD 256L
                    488: 
                    489: 
                    490: 
                    491: long ARGS_ON_STACK
                    492: 
                    493: s_realloc(size)
                    494: 
                    495:        long size;
                    496: 
                    497: {
                    498: 
                    499:        long r;
                    500: 
                    501: 
                    502: 
                    503:        TRACE(("s_realloc(%ld)", size));
                    504: 
                    505: 
                    506: 
                    507:        if (size != -1L)
                    508: 
                    509:                size += PAD;
                    510: 
                    511: 
                    512: 
                    513:        if (!screen_region) {
                    514: 
                    515:                r = realloc_region(screen_region, size);
                    516: 
                    517:                if (size == -1L) {      /* inquiry only */
                    518: 
                    519:                        TRACE(("%ld bytes max srealloc", r-PAD));
                    520: 
                    521:                        return r - PAD;
                    522: 
                    523:                }
                    524: 
                    525:                screen_region = (MEMREGION *)r;
                    526: 
                    527:                if (!screen_region) {
                    528: 
                    529:                        DEBUG(("s_realloc: no screen region!!"));
                    530: 
                    531:                        return 0;
                    532: 
                    533:                }
                    534: 
                    535:                return screen_region->loc;
                    536: 
                    537:        }
                    538: 
                    539:        r = realloc_region(screen_region, size);
                    540: 
                    541:        if (size == -1L) {
                    542: 
                    543:                return r - PAD;
                    544: 
                    545:        } else {
                    546: 
                    547:                return r;
                    548: 
                    549:        }
                    550: 
                    551: }
                    552: 

unix.superglobalmegacorp.com

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