00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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
00152 p->free = 0;
00153
00154
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);
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
00222
00223
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 }