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

1.1       root        1: /*
                      2: 
                      3:  * Copyright 1992 Atari Corporation. All rights reserved.
                      4: 
                      5:  */
                      6: 
                      7: 
                      8: 
                      9: /*
                     10: 
                     11:  * General-purpose memory allocator, on the MWC arena model, with
                     12: 
                     13:  * this added feature:
                     14: 
                     15:  *
                     16: 
                     17:  * All blocks are coalesced when they're freed.  If this results in
                     18: 
                     19:  * an arena with only one block, and that free, it's returned to the
                     20: 
                     21:  * OS.
                     22: 
                     23:  *
                     24: 
                     25:  * The functions here have the same names and bindings as the MWC
                     26: 
                     27:  * memory manager, which is the same as the UNIX names and bindings.
                     28: 
                     29:  *
                     30: 
                     31:  * MiNT version: used for kmalloc to manage kernel memory in small hunks,
                     32: 
                     33:  * rather than using a page at a time.
                     34: 
                     35:  */
                     36: 
                     37: 
                     38: 
                     39: #include "mint.h"
                     40: 
                     41: 
                     42: 
                     43: #if 0
                     44: 
                     45: #define NALLOC_DEBUG(c) TRACE(("nalloc: %c",c));
                     46: 
                     47: #else
                     48: 
                     49: #define NALLOC_DEBUG(c) /* nothing */
                     50: 
                     51: #endif
                     52: 
                     53: 
                     54: 
                     55: #define NKMAGIC 0x19870425L
                     56: 
                     57: 
                     58: 
                     59: /*
                     60: 
                     61:  * block header: every memory block has one.
                     62: 
                     63:  * A block is either allocated or on the free
                     64: 
                     65:  * list of the arena.  There is no allocated list: it's not necessary.
                     66: 
                     67:  * The next pointer is only valid for free blocks: for allocated blocks
                     68: 
                     69:  * maybe it should hold a verification value..?
                     70: 
                     71:  *
                     72: 
                     73:  * Zero-length blocks are possible and free; they hold space which might 
                     74: 
                     75:  * get coalesced usefully later on.
                     76: 
                     77:  */
                     78: 
                     79: 
                     80: 
                     81: struct block {
                     82: 
                     83:     struct block *b_next;   /* NULL for last guy; next alloc or next free */
                     84: 
                     85:     long b_size;
                     86: 
                     87: };
                     88: 
                     89: 
                     90: 
                     91: /*
                     92: 
                     93:  * arena header: every arena has one.  Each arena is always completely
                     94: 
                     95:  * filled with blocks; the first starts right after this header.
                     96: 
                     97:  */
                     98: 
                     99: 
                    100: 
                    101: struct arena {
                    102: 
                    103:     struct arena *a_next;
                    104: 
                    105:     struct block *a_ffirst;
                    106: 
                    107:     long a_size;
                    108: 
                    109: };
                    110: 
                    111: 
                    112: 
                    113: /*
                    114: 
                    115:  * Arena linked-list pointer, and block size.
                    116: 
                    117:  */
                    118: 
                    119: 
                    120: 
                    121: static struct arena *a_first = (struct arena *)NULL;
                    122: 
                    123: 
                    124: 
                    125: void
                    126: 
                    127: nalloc_arena_add(start,len)
                    128: 
                    129: void *start;
                    130: 
                    131: long len;
                    132: 
                    133: {
                    134: 
                    135:     struct arena *a = start;
                    136: 
                    137:     struct block *b;
                    138: 
                    139: 
                    140: 
                    141:     a->a_next = a_first;
                    142: 
                    143:     a_first = a;
                    144: 
                    145:     a->a_ffirst = b = (struct block *)(a+1);
                    146: 
                    147:     a->a_size = len;
                    148: 
                    149:     b->b_next = NULL;
                    150: 
                    151:     b->b_size = (len - sizeof(*a) - sizeof(*b));
                    152: 
                    153: }
                    154: 
                    155:        
                    156: 
                    157: 
                    158: 
                    159: void *
                    160: 
                    161: nalloc(size)
                    162: 
                    163: long size;
                    164: 
                    165: {
                    166: 
                    167:     struct arena *a;
                    168: 
                    169:     struct block *b, *mb, **q;
                    170: 
                    171:     long temp;
                    172: 
                    173: 
                    174: 
                    175:     NALLOC_DEBUG('A');
                    176: 
                    177: 
                    178: 
                    179:     /* force even-sized alloc's */
                    180: 
                    181:     size = (size+1) & ~1;
                    182: 
                    183: 
                    184: 
                    185:     for (a = a_first; a; a = a->a_next) {
                    186: 
                    187:        for (b = *(q = &a->a_ffirst); b; b = *(q = &b->b_next)) {
                    188: 
                    189:            /* if big enough, use it */
                    190: 
                    191:            if (b->b_size >= size) {
                    192: 
                    193: 
                    194: 
                    195:                /* got one */
                    196: 
                    197:                mb = b;
                    198: 
                    199: 
                    200: 
                    201:                /* cut the free block into an allocated part & a free part */
                    202: 
                    203:                temp = mb->b_size - size - sizeof(struct block);
                    204: 
                    205:                if (temp >= 0) {
                    206: 
                    207:                    /* large enough to cut */
                    208: 
                    209:                    NALLOC_DEBUG('c');
                    210: 
                    211:                    b = (struct block *)(((char *)(b+1)) + size);
                    212: 
                    213:                    b->b_size = temp;
                    214: 
                    215:                    b->b_next = mb->b_next;
                    216: 
                    217:                    *q = b;
                    218: 
                    219:                    mb->b_size = size;
                    220: 
                    221:                    mb->b_next = (struct block *)NKMAGIC;
                    222: 
                    223:                }
                    224: 
                    225:                else {
                    226: 
                    227:                    /* not big enough to cut: unlink this from free list */
                    228: 
                    229:                    NALLOC_DEBUG('w');
                    230: 
                    231:                    *q = mb->b_next;
                    232: 
                    233:                }
                    234: 
                    235:                return (void *)(mb+1);
                    236: 
                    237:            }
                    238: 
                    239:        }
                    240: 
                    241:     }
                    242: 
                    243: 
                    244: 
                    245:     /* no block available: get a new arena */
                    246: 
                    247: 
                    248: 
                    249: #if 1
                    250: 
                    251:     return NULL;       /* MiNT: fail. */
                    252: 
                    253: #else
                    254: 
                    255:     if (!minarena) {
                    256: 
                    257:        minarena = Malloc(-1L) / 20;
                    258: 
                    259:        if (minarena > MAXARENA) minarena = MAXARENA;
                    260: 
                    261:     }
                    262: 
                    263: 
                    264: 
                    265:     if (size < minarena) {
                    266: 
                    267:        NALLOC_DEBUG('m');
                    268: 
                    269:        temp = minarena;
                    270: 
                    271:     }
                    272: 
                    273:     else {
                    274: 
                    275:        NALLOC_DEBUG('s');
                    276: 
                    277:        temp = size;
                    278: 
                    279:     }
                    280: 
                    281: 
                    282: 
                    283:     a = (struct arena *)Malloc(temp + 
                    284: 
                    285:                                sizeof(struct arena) +
                    286: 
                    287:                                sizeof(struct block));
                    288: 
                    289: 
                    290: 
                    291:     /* if Malloc failed return failure */
                    292: 
                    293:     if (a == 0) {
                    294: 
                    295:        NALLOC_DEBUG('x');
                    296: 
                    297:        return 0;
                    298: 
                    299:     }
                    300: 
                    301: 
                    302: 
                    303:     a->a_size = temp + sizeof(struct block);
                    304: 
                    305:     a->a_next = a_first;
                    306: 
                    307:     a_first = a;
                    308: 
                    309:     mb = (struct block *)(a+1);
                    310: 
                    311:     mb->b_next = NULL;
                    312: 
                    313:     mb->b_size = size;
                    314: 
                    315: 
                    316: 
                    317:     if (temp > (size + sizeof(struct block))) {
                    318: 
                    319:        NALLOC_DEBUG('c');
                    320: 
                    321:        b = a->a_ffirst = ((char *)(mb+1)) + size;
                    322: 
                    323:        b->b_next = NULL;
                    324: 
                    325:        b->b_size = temp - size - sizeof(struct block);
                    326: 
                    327:     }
                    328: 
                    329:     else {
                    330: 
                    331:        a->a_ffirst = NULL;
                    332: 
                    333:     }
                    334: 
                    335:     return (void *)(++mb);
                    336: 
                    337: #endif
                    338: 
                    339: }
                    340: 
                    341: 
                    342: 
                    343: void
                    344: 
                    345: nfree(start)
                    346: 
                    347: void *start;
                    348: 
                    349: {
                    350: 
                    351:     struct arena *a, **qa;
                    352: 
                    353:     struct block *b;
                    354: 
                    355:     struct block *pb;
                    356: 
                    357:     struct block *fb = (struct block *)start;
                    358: 
                    359: 
                    360: 
                    361:     NALLOC_DEBUG('F');
                    362: 
                    363:     if (fb->b_next != (struct block *)NKMAGIC) {
                    364: 
                    365:        FATAL("nfree: block %lx not allocated by nalloc!",fb);
                    366: 
                    367:     }
                    368: 
                    369: 
                    370: 
                    371:     /* set fb (and b) to header start */
                    372: 
                    373:     b = --fb;
                    374: 
                    375: 
                    376: 
                    377:     /* the arena this block lives in */
                    378: 
                    379:     for (a = *(qa = &a_first); a; a = *(qa = &a->a_next)) {
                    380: 
                    381:        if ((unsigned long)b > (unsigned long)a &&
                    382: 
                    383:            (unsigned long)b < (((unsigned long)a) + a->a_size)) goto found;
                    384: 
                    385:     }
                    386: 
                    387:     FATAL("nfree: block %lx not in any arena!",fb);
                    388: 
                    389: 
                    390: 
                    391: found:
                    392: 
                    393:     /* Found it! */
                    394: 
                    395:     /* a is this block's arena */
                    396: 
                    397: 
                    398: 
                    399:     /* set pb to the previous free block in this arena, b to next */
                    400: 
                    401:     for (pb = NULL, b = a->a_ffirst;
                    402: 
                    403:         b && (b < fb);
                    404: 
                    405:         pb = b, b = b->b_next) ;
                    406: 
                    407: 
                    408: 
                    409:     fb->b_next = b;
                    410: 
                    411: 
                    412: 
                    413:     /* Coalesce backwards: if any prev ... */
                    414: 
                    415:     if (pb) {
                    416: 
                    417:        /* if it's adjacent ... */
                    418: 
                    419:        if ((((unsigned long)(pb+1)) + pb->b_size) == (unsigned long)fb) {
                    420: 
                    421:            NALLOC_DEBUG('b');
                    422: 
                    423:            pb->b_size += sizeof(struct block) + fb->b_size;
                    424: 
                    425:            fb = pb;
                    426: 
                    427:        }
                    428: 
                    429:        else {
                    430: 
                    431:            /* ... else not adjacent, but there is a prev free block */
                    432: 
                    433:            /* so set its next ptr to fb */
                    434: 
                    435:            pb->b_next = fb;
                    436: 
                    437:        }
                    438: 
                    439:     }
                    440: 
                    441:     else {
                    442: 
                    443:        /* ... else no prev free block: set arena's free list ptr to fb */
                    444: 
                    445:        a->a_ffirst = fb;
                    446: 
                    447:     }
                    448: 
                    449: 
                    450: 
                    451:     /* Coalesce forwards: b holds start of free block AFTER fb, if any */
                    452: 
                    453:     if (b && (((unsigned long)(fb+1)) + fb->b_size) == (unsigned long)b) {
                    454: 
                    455:        NALLOC_DEBUG('f');
                    456: 
                    457:        fb->b_size += sizeof(struct block) + b->b_size;
                    458: 
                    459:        fb->b_next = b->b_next;
                    460: 
                    461:     }
                    462: 
                    463: 
                    464: 
                    465: #if 0
                    466: 
                    467:     /* if, after coalescing, this arena is entirely free, Mfree it! */
                    468: 
                    469:     if (a->a_ffirst == a+1 && 
                    470: 
                    471:         (a->a_ffirst->b_size + sizeof(struct block)) == a->a_size) {
                    472: 
                    473:            NALLOC_DEBUG('!');
                    474: 
                    475:            *qa = a->a_next;
                    476: 
                    477:            (void)Mfree(a);
                    478: 
                    479:     }
                    480: 
                    481: #endif
                    482: 
                    483: 
                    484: 
                    485:     return;
                    486: 
                    487: }
                    488: 
                    489: 
                    490: 
                    491: void
                    492: 
                    493: NALLOC_DUMP()
                    494: 
                    495: {
                    496: 
                    497:     struct arena *a;
                    498: 
                    499:     struct block *b;
                    500: 
                    501: 
                    502: 
                    503:     for (a = a_first; a; a = a->a_next) {
                    504: 
                    505:        FORCE("Arena at %lx size %lx: free list:",a,a->a_size);
                    506: 
                    507:        for (b = a->a_ffirst; b; b = b->b_next) {
                    508: 
                    509:            FORCE("    %8lx size %8lx",b,b->b_size);
                    510: 
                    511:        }
                    512: 
                    513:     }
                    514: 
                    515: }
                    516: 

unix.superglobalmegacorp.com

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