u_mm.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright (C) 1999 Wittawat Yamwong
00004  *
00005  * Permission is hereby granted, free of charge, to any person obtaining a
00006  * copy of this software and associated documentation files (the "Software"),
00007  * to deal in the Software without restriction, including without limitation
00008  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00009  * and/or sell copies of the Software, and to permit persons to whom the
00010  * Software is furnished to do so, subject to the following conditions:
00011  *
00012  * The above copyright notice and this permission notice shall be included
00013  * in all copies or substantial portions of the Software.
00014  *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00018  * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 
00019  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
00020  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
00021  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00022  *
00023  **************************************************************************/
00024 
00025 
00026 #include "pipe/p_compiler.h"
00027 #include "pipe/p_debug.h"
00028 
00029 #include "util/u_memory.h"
00030 #include "util/u_mm.h"
00031 
00032 
00033 void
00034 mmDumpMemInfo(const struct mem_block *heap)
00035 {
00036    debug_printf("Memory heap %p:\n", (void *)heap);
00037    if (heap == 0) {
00038       debug_printf("  heap == 0\n");
00039    } else {
00040       const struct mem_block *p;
00041 
00042       for(p = heap->next; p != heap; p = p->next) {
00043          debug_printf("  Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
00044                  p->free ? 'F':'.',
00045                  p->reserved ? 'R':'.');
00046       }
00047 
00048       debug_printf("\nFree list:\n");
00049 
00050       for(p = heap->next_free; p != heap; p = p->next_free) {
00051          debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
00052                  p->free ? 'F':'.',
00053                  p->reserved ? 'R':'.');
00054       }
00055 
00056    }
00057    debug_printf("End of memory blocks\n");
00058 }
00059 
00060 struct mem_block *
00061 mmInit(int ofs, int size)
00062 {
00063    struct mem_block *heap, *block;
00064   
00065    if (size <= 0) 
00066       return NULL;
00067 
00068    heap = CALLOC_STRUCT(mem_block);
00069    if (!heap) 
00070       return NULL;
00071    
00072    block = CALLOC_STRUCT(mem_block);
00073    if (!block) {
00074       FREE(heap);
00075       return NULL;
00076    }
00077 
00078    heap->next = block;
00079    heap->prev = block;
00080    heap->next_free = block;
00081    heap->prev_free = block;
00082 
00083    block->heap = heap;
00084    block->next = heap;
00085    block->prev = heap;
00086    block->next_free = heap;
00087    block->prev_free = heap;
00088 
00089    block->ofs = ofs;
00090    block->size = size;
00091    block->free = 1;
00092 
00093    return heap;
00094 }
00095 
00096 
00097 static struct mem_block *
00098 SliceBlock(struct mem_block *p, 
00099            int startofs, int size, 
00100            int reserved, int alignment)
00101 {
00102    struct mem_block *newblock;
00103 
00104    /* break left  [p, newblock, p->next], then p = newblock */
00105    if (startofs > p->ofs) {
00106       newblock = CALLOC_STRUCT(mem_block);
00107       if (!newblock)
00108          return NULL;
00109       newblock->ofs = startofs;
00110       newblock->size = p->size - (startofs - p->ofs);
00111       newblock->free = 1;
00112       newblock->heap = p->heap;
00113 
00114       newblock->next = p->next;
00115       newblock->prev = p;
00116       p->next->prev = newblock;
00117       p->next = newblock;
00118 
00119       newblock->next_free = p->next_free;
00120       newblock->prev_free = p;
00121       p->next_free->prev_free = newblock;
00122       p->next_free = newblock;
00123 
00124       p->size -= newblock->size;
00125       p = newblock;
00126    }
00127 
00128    /* break right, also [p, newblock, p->next] */
00129    if (size < p->size) {
00130       newblock = CALLOC_STRUCT(mem_block);
00131       if (!newblock)
00132          return NULL;
00133       newblock->ofs = startofs + size;
00134       newblock->size = p->size - size;
00135       newblock->free = 1;
00136       newblock->heap = p->heap;
00137 
00138       newblock->next = p->next;
00139       newblock->prev = p;
00140       p->next->prev = newblock;
00141       p->next = newblock;
00142 
00143       newblock->next_free = p->next_free;
00144       newblock->prev_free = p;
00145       p->next_free->prev_free = newblock;
00146       p->next_free = newblock;
00147          
00148       p->size = size;
00149    }
00150 
00151    /* p = middle block */
00152    p->free = 0;
00153 
00154    /* Remove p from the free list: 
00155     */
00156    p->next_free->prev_free = p->prev_free;
00157    p->prev_free->next_free = p->next_free;
00158 
00159    p->next_free = 0;
00160    p->prev_free = 0;
00161 
00162    p->reserved = reserved;
00163    return p;
00164 }
00165 
00166 
00167 struct mem_block *
00168 mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch)
00169 {
00170    struct mem_block *p;
00171    const int mask = (1 << align2)-1;
00172    int startofs = 0;
00173    int endofs;
00174 
00175    assert(size >= 0);
00176    assert(align2 >= 0);
00177    assert(align2 <= 12); /* sanity check, 2^12 (4KB) enough? */
00178 
00179    if (!heap || align2 < 0 || size <= 0)
00180       return NULL;
00181 
00182    for (p = heap->next_free; p != heap; p = p->next_free) {
00183       assert(p->free);
00184 
00185       startofs = (p->ofs + mask) & ~mask;
00186       if ( startofs < startSearch ) {
00187          startofs = startSearch;
00188       }
00189       endofs = startofs+size;
00190       if (endofs <= (p->ofs+p->size))
00191          break;
00192    }
00193 
00194    if (p == heap) 
00195       return NULL;
00196 
00197    assert(p->free);
00198    p = SliceBlock(p,startofs,size,0,mask+1);
00199 
00200    return p;
00201 }
00202 
00203 
00204 struct mem_block *
00205 mmFindBlock(struct mem_block *heap, int start)
00206 {
00207    struct mem_block *p;
00208 
00209    for (p = heap->next; p != heap; p = p->next) {
00210       if (p->ofs == start) 
00211          return p;
00212    }
00213 
00214    return NULL;
00215 }
00216 
00217 
00218 static INLINE int
00219 Join2Blocks(struct mem_block *p)
00220 {
00221    /* XXX there should be some assertions here */
00222 
00223    /* NOTE: heap->free == 0 */
00224 
00225    if (p->free && p->next->free) {
00226       struct mem_block *q = p->next;
00227 
00228       assert(p->ofs + p->size == q->ofs);
00229       p->size += q->size;
00230 
00231       p->next = q->next;
00232       q->next->prev = p;
00233 
00234       q->next_free->prev_free = q->prev_free; 
00235       q->prev_free->next_free = q->next_free;
00236      
00237       FREE(q);
00238       return 1;
00239    }
00240    return 0;
00241 }
00242 
00243 int
00244 mmFreeMem(struct mem_block *b)
00245 {
00246    if (!b)
00247       return 0;
00248 
00249    if (b->free) {
00250       debug_printf("block already free\n");
00251       return -1;
00252    }
00253    if (b->reserved) {
00254       debug_printf("block is reserved\n");
00255       return -1;
00256    }
00257 
00258    b->free = 1;
00259    b->next_free = b->heap->next_free;
00260    b->prev_free = b->heap;
00261    b->next_free->prev_free = b;
00262    b->prev_free->next_free = b;
00263 
00264    Join2Blocks(b);
00265    if (b->prev != b->heap)
00266       Join2Blocks(b->prev);
00267 
00268    return 0;
00269 }
00270 
00271 
00272 void
00273 mmDestroy(struct mem_block *heap)
00274 {
00275    struct mem_block *p;
00276 
00277    if (!heap)
00278       return;
00279 
00280    for (p = heap->next; p != heap; ) {
00281       struct mem_block *next = p->next;
00282       FREE(p);
00283       p = next;
00284    }
00285 
00286    FREE(heap);
00287 }

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4