1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright (C) 1999 Wittawat Yamwong 4848b8605Smrg * 5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6848b8605Smrg * copy of this software and associated documentation files (the "Software"), 7848b8605Smrg * to deal in the Software without restriction, including without limitation 8848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 10848b8605Smrg * Software is furnished to do so, subject to the following conditions: 11848b8605Smrg * 12848b8605Smrg * The above copyright notice and this permission notice shall be included 13848b8605Smrg * in all copies or substantial portions of the Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18848b8605Smrg * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 19848b8605Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20848b8605Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 21848b8605Smrg * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22848b8605Smrg * 23848b8605Smrg **************************************************************************/ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg#include "pipe/p_compiler.h" 27848b8605Smrg#include "util/u_debug.h" 28848b8605Smrg 29848b8605Smrg#include "util/u_memory.h" 30848b8605Smrg#include "util/u_mm.h" 31848b8605Smrg 32848b8605Smrg 33848b8605Smrgvoid 34848b8605Smrgu_mmDumpMemInfo(const struct mem_block *heap) 35848b8605Smrg{ 36848b8605Smrg debug_printf("Memory heap %p:\n", (void *) heap); 37b8e80941Smrg if (heap == NULL) { 38848b8605Smrg debug_printf(" heap == 0\n"); 39848b8605Smrg } 40848b8605Smrg else { 41848b8605Smrg const struct mem_block *p; 42848b8605Smrg int total_used = 0, total_free = 0; 43848b8605Smrg 44848b8605Smrg for (p = heap->next; p != heap; p = p->next) { 45848b8605Smrg debug_printf(" Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size, 46848b8605Smrg p->free ? 'F':'.', 47848b8605Smrg p->reserved ? 'R':'.'); 48848b8605Smrg if (p->free) 49848b8605Smrg total_free += p->size; 50848b8605Smrg else 51848b8605Smrg total_used += p->size; 52848b8605Smrg } 53848b8605Smrg 54848b8605Smrg debug_printf("'\nMemory stats: total = %d, used = %d, free = %d\n", 55848b8605Smrg total_used + total_free, total_used, total_free); 56848b8605Smrg debug_printf("\nFree list:\n"); 57848b8605Smrg 58848b8605Smrg for (p = heap->next_free; p != heap; p = p->next_free) { 59848b8605Smrg debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size, 60848b8605Smrg p->free ? 'F':'.', 61848b8605Smrg p->reserved ? 'R':'.'); 62848b8605Smrg } 63848b8605Smrg 64848b8605Smrg } 65848b8605Smrg debug_printf("End of memory blocks\n"); 66848b8605Smrg} 67848b8605Smrg 68848b8605Smrg 69848b8605Smrgstruct mem_block * 70848b8605Smrgu_mmInit(int ofs, int size) 71848b8605Smrg{ 72848b8605Smrg struct mem_block *heap, *block; 73848b8605Smrg 74848b8605Smrg if (size <= 0) 75848b8605Smrg return NULL; 76848b8605Smrg 77848b8605Smrg heap = CALLOC_STRUCT(mem_block); 78848b8605Smrg if (!heap) 79848b8605Smrg return NULL; 80848b8605Smrg 81848b8605Smrg block = CALLOC_STRUCT(mem_block); 82848b8605Smrg if (!block) { 83848b8605Smrg FREE(heap); 84848b8605Smrg return NULL; 85848b8605Smrg } 86848b8605Smrg 87848b8605Smrg heap->next = block; 88848b8605Smrg heap->prev = block; 89848b8605Smrg heap->next_free = block; 90848b8605Smrg heap->prev_free = block; 91848b8605Smrg 92848b8605Smrg block->heap = heap; 93848b8605Smrg block->next = heap; 94848b8605Smrg block->prev = heap; 95848b8605Smrg block->next_free = heap; 96848b8605Smrg block->prev_free = heap; 97848b8605Smrg 98848b8605Smrg block->ofs = ofs; 99848b8605Smrg block->size = size; 100848b8605Smrg block->free = 1; 101848b8605Smrg 102848b8605Smrg return heap; 103848b8605Smrg} 104848b8605Smrg 105848b8605Smrg 106848b8605Smrgstatic struct mem_block * 107848b8605SmrgSliceBlock(struct mem_block *p, 108848b8605Smrg int startofs, int size, 109b8e80941Smrg int reserved, UNUSED int alignment) 110848b8605Smrg{ 111848b8605Smrg struct mem_block *newblock; 112848b8605Smrg 113848b8605Smrg /* break left [p, newblock, p->next], then p = newblock */ 114848b8605Smrg if (startofs > p->ofs) { 115848b8605Smrg newblock = CALLOC_STRUCT(mem_block); 116848b8605Smrg if (!newblock) 117848b8605Smrg return NULL; 118848b8605Smrg newblock->ofs = startofs; 119848b8605Smrg newblock->size = p->size - (startofs - p->ofs); 120848b8605Smrg newblock->free = 1; 121848b8605Smrg newblock->heap = p->heap; 122848b8605Smrg 123848b8605Smrg newblock->next = p->next; 124848b8605Smrg newblock->prev = p; 125848b8605Smrg p->next->prev = newblock; 126848b8605Smrg p->next = newblock; 127848b8605Smrg 128848b8605Smrg newblock->next_free = p->next_free; 129848b8605Smrg newblock->prev_free = p; 130848b8605Smrg p->next_free->prev_free = newblock; 131848b8605Smrg p->next_free = newblock; 132848b8605Smrg 133848b8605Smrg p->size -= newblock->size; 134848b8605Smrg p = newblock; 135848b8605Smrg } 136848b8605Smrg 137848b8605Smrg /* break right, also [p, newblock, p->next] */ 138848b8605Smrg if (size < p->size) { 139848b8605Smrg newblock = CALLOC_STRUCT(mem_block); 140848b8605Smrg if (!newblock) 141848b8605Smrg return NULL; 142848b8605Smrg newblock->ofs = startofs + size; 143848b8605Smrg newblock->size = p->size - size; 144848b8605Smrg newblock->free = 1; 145848b8605Smrg newblock->heap = p->heap; 146848b8605Smrg 147848b8605Smrg newblock->next = p->next; 148848b8605Smrg newblock->prev = p; 149848b8605Smrg p->next->prev = newblock; 150848b8605Smrg p->next = newblock; 151848b8605Smrg 152848b8605Smrg newblock->next_free = p->next_free; 153848b8605Smrg newblock->prev_free = p; 154848b8605Smrg p->next_free->prev_free = newblock; 155848b8605Smrg p->next_free = newblock; 156848b8605Smrg 157848b8605Smrg p->size = size; 158848b8605Smrg } 159848b8605Smrg 160848b8605Smrg /* p = middle block */ 161848b8605Smrg p->free = 0; 162848b8605Smrg 163848b8605Smrg /* Remove p from the free list: 164848b8605Smrg */ 165848b8605Smrg p->next_free->prev_free = p->prev_free; 166848b8605Smrg p->prev_free->next_free = p->next_free; 167848b8605Smrg 168848b8605Smrg p->next_free = 0; 169848b8605Smrg p->prev_free = 0; 170848b8605Smrg 171848b8605Smrg p->reserved = reserved; 172848b8605Smrg return p; 173848b8605Smrg} 174848b8605Smrg 175848b8605Smrg 176848b8605Smrgstruct mem_block * 177848b8605Smrgu_mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch) 178848b8605Smrg{ 179848b8605Smrg struct mem_block *p; 180848b8605Smrg const int mask = (1 << align2)-1; 181848b8605Smrg int startofs = 0; 182848b8605Smrg int endofs; 183848b8605Smrg 184848b8605Smrg assert(size >= 0); 185848b8605Smrg assert(align2 >= 0); 186b8e80941Smrg /* Make sure that a byte alignment isn't getting passed for our 187b8e80941Smrg * power-of-two alignment arg. 188b8e80941Smrg */ 189b8e80941Smrg assert(align2 < 32); 190848b8605Smrg 191848b8605Smrg if (!heap || align2 < 0 || size <= 0) 192848b8605Smrg return NULL; 193848b8605Smrg 194848b8605Smrg for (p = heap->next_free; p != heap; p = p->next_free) { 195848b8605Smrg assert(p->free); 196848b8605Smrg 197848b8605Smrg startofs = (p->ofs + mask) & ~mask; 198848b8605Smrg if ( startofs < startSearch ) { 199848b8605Smrg startofs = startSearch; 200848b8605Smrg } 201848b8605Smrg endofs = startofs+size; 202848b8605Smrg if (endofs <= (p->ofs+p->size)) 203848b8605Smrg break; 204848b8605Smrg } 205848b8605Smrg 206848b8605Smrg if (p == heap) 207848b8605Smrg return NULL; 208848b8605Smrg 209848b8605Smrg assert(p->free); 210848b8605Smrg p = SliceBlock(p,startofs,size,0,mask+1); 211848b8605Smrg 212848b8605Smrg return p; 213848b8605Smrg} 214848b8605Smrg 215848b8605Smrg 216848b8605Smrgstruct mem_block * 217848b8605Smrgu_mmFindBlock(struct mem_block *heap, int start) 218848b8605Smrg{ 219848b8605Smrg struct mem_block *p; 220848b8605Smrg 221848b8605Smrg for (p = heap->next; p != heap; p = p->next) { 222848b8605Smrg if (p->ofs == start) 223848b8605Smrg return p; 224848b8605Smrg } 225848b8605Smrg 226848b8605Smrg return NULL; 227848b8605Smrg} 228848b8605Smrg 229848b8605Smrg 230b8e80941Smrgstatic inline int 231848b8605SmrgJoin2Blocks(struct mem_block *p) 232848b8605Smrg{ 233848b8605Smrg /* XXX there should be some assertions here */ 234848b8605Smrg 235848b8605Smrg /* NOTE: heap->free == 0 */ 236848b8605Smrg 237848b8605Smrg if (p->free && p->next->free) { 238848b8605Smrg struct mem_block *q = p->next; 239848b8605Smrg 240848b8605Smrg assert(p->ofs + p->size == q->ofs); 241848b8605Smrg p->size += q->size; 242848b8605Smrg 243848b8605Smrg p->next = q->next; 244848b8605Smrg q->next->prev = p; 245848b8605Smrg 246848b8605Smrg q->next_free->prev_free = q->prev_free; 247848b8605Smrg q->prev_free->next_free = q->next_free; 248848b8605Smrg 249848b8605Smrg FREE(q); 250848b8605Smrg return 1; 251848b8605Smrg } 252848b8605Smrg return 0; 253848b8605Smrg} 254848b8605Smrg 255848b8605Smrgint 256848b8605Smrgu_mmFreeMem(struct mem_block *b) 257848b8605Smrg{ 258848b8605Smrg if (!b) 259848b8605Smrg return 0; 260848b8605Smrg 261848b8605Smrg if (b->free) { 262848b8605Smrg debug_printf("block already free\n"); 263848b8605Smrg return -1; 264848b8605Smrg } 265848b8605Smrg if (b->reserved) { 266848b8605Smrg debug_printf("block is reserved\n"); 267848b8605Smrg return -1; 268848b8605Smrg } 269848b8605Smrg 270848b8605Smrg b->free = 1; 271848b8605Smrg b->next_free = b->heap->next_free; 272848b8605Smrg b->prev_free = b->heap; 273848b8605Smrg b->next_free->prev_free = b; 274848b8605Smrg b->prev_free->next_free = b; 275848b8605Smrg 276848b8605Smrg Join2Blocks(b); 277848b8605Smrg if (b->prev != b->heap) 278848b8605Smrg Join2Blocks(b->prev); 279848b8605Smrg 280848b8605Smrg return 0; 281848b8605Smrg} 282848b8605Smrg 283848b8605Smrg 284848b8605Smrgvoid 285848b8605Smrgu_mmDestroy(struct mem_block *heap) 286848b8605Smrg{ 287848b8605Smrg struct mem_block *p; 288848b8605Smrg 289848b8605Smrg if (!heap) 290848b8605Smrg return; 291848b8605Smrg 292848b8605Smrg for (p = heap->next; p != heap; ) { 293848b8605Smrg struct mem_block *next = p->next; 294848b8605Smrg FREE(p); 295848b8605Smrg p = next; 296848b8605Smrg } 297848b8605Smrg 298848b8605Smrg FREE(heap); 299848b8605Smrg} 300