1 /**************************************************************************
3 * Copyright (C) 1999 Wittawat Yamwong
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 **************************************************************************/
26 #include "pipe/p_compiler.h"
27 #include "util/u_debug.h"
29 #include "util/u_memory.h"
30 #include "util/u_mm.h"
34 u_mmDumpMemInfo(const struct mem_block
*heap
)
36 debug_printf("Memory heap %p:\n", (void *) heap
);
38 debug_printf(" heap == 0\n");
41 const struct mem_block
*p
;
42 int total_used
= 0, total_free
= 0;
44 for (p
= heap
->next
; p
!= heap
; p
= p
->next
) {
45 debug_printf(" Offset:%08x, Size:%08x, %c%c\n", p
->ofs
, p
->size
,
47 p
->reserved
? 'R':'.');
49 total_free
+= p
->size
;
51 total_used
+= p
->size
;
54 debug_printf("'\nMemory stats: total = %d, used = %d, free = %d\n",
55 total_used
+ total_free
, total_used
, total_free
);
56 debug_printf("\nFree list:\n");
58 for (p
= heap
->next_free
; p
!= heap
; p
= p
->next_free
) {
59 debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n", p
->ofs
, p
->size
,
61 p
->reserved
? 'R':'.');
65 debug_printf("End of memory blocks\n");
70 u_mmInit(int ofs
, int size
)
72 struct mem_block
*heap
, *block
;
77 heap
= CALLOC_STRUCT(mem_block
);
81 block
= CALLOC_STRUCT(mem_block
);
89 heap
->next_free
= block
;
90 heap
->prev_free
= block
;
95 block
->next_free
= heap
;
96 block
->prev_free
= heap
;
106 static struct mem_block
*
107 SliceBlock(struct mem_block
*p
,
108 int startofs
, int size
,
109 int reserved
, int alignment
)
111 struct mem_block
*newblock
;
113 /* break left [p, newblock, p->next], then p = newblock */
114 if (startofs
> p
->ofs
) {
115 newblock
= CALLOC_STRUCT(mem_block
);
118 newblock
->ofs
= startofs
;
119 newblock
->size
= p
->size
- (startofs
- p
->ofs
);
121 newblock
->heap
= p
->heap
;
123 newblock
->next
= p
->next
;
125 p
->next
->prev
= newblock
;
128 newblock
->next_free
= p
->next_free
;
129 newblock
->prev_free
= p
;
130 p
->next_free
->prev_free
= newblock
;
131 p
->next_free
= newblock
;
133 p
->size
-= newblock
->size
;
137 /* break right, also [p, newblock, p->next] */
138 if (size
< p
->size
) {
139 newblock
= CALLOC_STRUCT(mem_block
);
142 newblock
->ofs
= startofs
+ size
;
143 newblock
->size
= p
->size
- size
;
145 newblock
->heap
= p
->heap
;
147 newblock
->next
= p
->next
;
149 p
->next
->prev
= newblock
;
152 newblock
->next_free
= p
->next_free
;
153 newblock
->prev_free
= p
;
154 p
->next_free
->prev_free
= newblock
;
155 p
->next_free
= newblock
;
160 /* p = middle block */
163 /* Remove p from the free list:
165 p
->next_free
->prev_free
= p
->prev_free
;
166 p
->prev_free
->next_free
= p
->next_free
;
171 p
->reserved
= reserved
;
177 u_mmAllocMem(struct mem_block
*heap
, int size
, int align2
, int startSearch
)
180 const int mask
= (1 << align2
)-1;
186 assert(align2
<= 12); /* sanity check, 2^12 (4KB) enough? */
188 if (!heap
|| align2
< 0 || size
<= 0)
191 for (p
= heap
->next_free
; p
!= heap
; p
= p
->next_free
) {
194 startofs
= (p
->ofs
+ mask
) & ~mask
;
195 if ( startofs
< startSearch
) {
196 startofs
= startSearch
;
198 endofs
= startofs
+size
;
199 if (endofs
<= (p
->ofs
+p
->size
))
207 p
= SliceBlock(p
,startofs
,size
,0,mask
+1);
214 u_mmFindBlock(struct mem_block
*heap
, int start
)
218 for (p
= heap
->next
; p
!= heap
; p
= p
->next
) {
228 Join2Blocks(struct mem_block
*p
)
230 /* XXX there should be some assertions here */
232 /* NOTE: heap->free == 0 */
234 if (p
->free
&& p
->next
->free
) {
235 struct mem_block
*q
= p
->next
;
237 assert(p
->ofs
+ p
->size
== q
->ofs
);
243 q
->next_free
->prev_free
= q
->prev_free
;
244 q
->prev_free
->next_free
= q
->next_free
;
253 u_mmFreeMem(struct mem_block
*b
)
259 debug_printf("block already free\n");
263 debug_printf("block is reserved\n");
268 b
->next_free
= b
->heap
->next_free
;
269 b
->prev_free
= b
->heap
;
270 b
->next_free
->prev_free
= b
;
271 b
->prev_free
->next_free
= b
;
274 if (b
->prev
!= b
->heap
)
275 Join2Blocks(b
->prev
);
282 u_mmDestroy(struct mem_block
*heap
)
289 for (p
= heap
->next
; p
!= heap
; ) {
290 struct mem_block
*next
= p
->next
;