117158c2f00f5bee29ec8239367fd5498f22e4a91José Fonseca/**************************************************************************
217158c2f00f5bee29ec8239367fd5498f22e4a91José Fonseca *
3df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * Copyright (C) 1999 Wittawat Yamwong
4df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca *
5df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * Permission is hereby granted, free of charge, to any person obtaining a
6df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * copy of this software and associated documentation files (the "Software"),
7df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * to deal in the Software without restriction, including without limitation
8df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * and/or sell copies of the Software, and to permit persons to whom the
10df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * Software is furnished to do so, subject to the following conditions:
11df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca *
12df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * The above copyright notice and this permission notice shall be included
13df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * in all copies or substantial portions of the Software.
14df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca *
15df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca *
2317158c2f00f5bee29ec8239367fd5498f22e4a91José Fonseca **************************************************************************/
24df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
25df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
26df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca#include "pipe/p_compiler.h"
27ea4bf267e4b023b08043f91ac44592fed1736e7fJosé Fonseca#include "util/u_debug.h"
28df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
294f25420bdd834e81a3e22733304efc5261c2998aBrian Paul#include "util/u_memory.h"
3017158c2f00f5bee29ec8239367fd5498f22e4a91José Fonseca#include "util/u_mm.h"
31df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
32df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
33df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonsecavoid
343ad56968f09397a8dd417eae025b9506efaf8414Brian Paulu_mmDumpMemInfo(const struct mem_block *heap)
35df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca{
3694726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul   debug_printf("Memory heap %p:\n", (void *) heap);
37df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (heap == 0) {
38df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      debug_printf("  heap == 0\n");
3994726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul   }
4094726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul   else {
41df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      const struct mem_block *p;
42d228e3cc8e7b6a3d4c6d554c5d9aed5e26be7ff0Zack Rusin      int total_used = 0, total_free = 0;
43df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
4494726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul      for (p = heap->next; p != heap; p = p->next) {
4594726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul	 debug_printf("  Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size,
4694726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul                      p->free ? 'F':'.',
4794726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul                      p->reserved ? 'R':'.');
48d228e3cc8e7b6a3d4c6d554c5d9aed5e26be7ff0Zack Rusin         if (p->free)
49d228e3cc8e7b6a3d4c6d554c5d9aed5e26be7ff0Zack Rusin            total_free += p->size;
50d228e3cc8e7b6a3d4c6d554c5d9aed5e26be7ff0Zack Rusin         else
51d228e3cc8e7b6a3d4c6d554c5d9aed5e26be7ff0Zack Rusin            total_used += p->size;
52df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      }
53df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
54d228e3cc8e7b6a3d4c6d554c5d9aed5e26be7ff0Zack Rusin      debug_printf("'\nMemory stats: total = %d, used = %d, free = %d\n",
55d228e3cc8e7b6a3d4c6d554c5d9aed5e26be7ff0Zack Rusin                   total_used + total_free, total_used, total_free);
56df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      debug_printf("\nFree list:\n");
57df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
5894726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul      for (p = heap->next_free; p != heap; p = p->next_free) {
5994726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul	 debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size,
6094726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul                      p->free ? 'F':'.',
6194726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul                      p->reserved ? 'R':'.');
62df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      }
63df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
64df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   }
65df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   debug_printf("End of memory blocks\n");
66df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca}
67df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
6894726bc69e5f9dbefb34a38695f2f51d81ff433fBrian Paul
69df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonsecastruct mem_block *
703ad56968f09397a8dd417eae025b9506efaf8414Brian Paulu_mmInit(int ofs, int size)
71df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca{
72df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   struct mem_block *heap, *block;
73df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
74df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (size <= 0)
75df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      return NULL;
76df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
77df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   heap = CALLOC_STRUCT(mem_block);
78df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (!heap)
79df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      return NULL;
80df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
81df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   block = CALLOC_STRUCT(mem_block);
82df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (!block) {
83df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      FREE(heap);
84df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      return NULL;
85df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   }
86df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
87df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   heap->next = block;
88df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   heap->prev = block;
89df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   heap->next_free = block;
90df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   heap->prev_free = block;
91df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
92df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   block->heap = heap;
93df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   block->next = heap;
94df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   block->prev = heap;
95df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   block->next_free = heap;
96df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   block->prev_free = heap;
97df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
98df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   block->ofs = ofs;
99df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   block->size = size;
100df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   block->free = 1;
101df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
102df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   return heap;
103df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca}
104df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
105df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
106df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonsecastatic struct mem_block *
107df8ab3140ce05599e1dc983ac211a30fc845d9b5José FonsecaSliceBlock(struct mem_block *p,
108df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca           int startofs, int size,
109df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca           int reserved, int alignment)
110df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca{
111df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   struct mem_block *newblock;
112df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
113df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   /* break left  [p, newblock, p->next], then p = newblock */
114df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (startofs > p->ofs) {
115df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock = CALLOC_STRUCT(mem_block);
116df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      if (!newblock)
117df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca	 return NULL;
118df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->ofs = startofs;
119df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->size = p->size - (startofs - p->ofs);
120df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->free = 1;
121df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->heap = p->heap;
122df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
123df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->next = p->next;
124df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->prev = p;
125df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->next->prev = newblock;
126df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->next = newblock;
127df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
128df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->next_free = p->next_free;
129df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->prev_free = p;
130df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->next_free->prev_free = newblock;
131df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->next_free = newblock;
132df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
133df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->size -= newblock->size;
134df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p = newblock;
135df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   }
136df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
137df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   /* break right, also [p, newblock, p->next] */
138df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (size < p->size) {
139df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock = CALLOC_STRUCT(mem_block);
140df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      if (!newblock)
141df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca	 return NULL;
142df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->ofs = startofs + size;
143df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->size = p->size - size;
144df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->free = 1;
145df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->heap = p->heap;
146df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
147df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->next = p->next;
148df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->prev = p;
149df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->next->prev = newblock;
150df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->next = newblock;
151df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
152df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->next_free = p->next_free;
153df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      newblock->prev_free = p;
154df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->next_free->prev_free = newblock;
155df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->next_free = newblock;
156df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
157df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->size = size;
158df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   }
159df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
160df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   /* p = middle block */
161df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   p->free = 0;
162df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
163df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   /* Remove p from the free list:
164df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca    */
165df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   p->next_free->prev_free = p->prev_free;
166df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   p->prev_free->next_free = p->next_free;
167df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
168df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   p->next_free = 0;
169df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   p->prev_free = 0;
170df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
171df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   p->reserved = reserved;
172df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   return p;
173df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca}
174df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
175df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
176df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonsecastruct mem_block *
1773ad56968f09397a8dd417eae025b9506efaf8414Brian Paulu_mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch)
178df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca{
179df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   struct mem_block *p;
180df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   const int mask = (1 << align2)-1;
181df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   int startofs = 0;
182df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   int endofs;
183df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
184766cb95a4564c48f35b5180155ab40320a68e371Brian Paul   assert(size >= 0);
185766cb95a4564c48f35b5180155ab40320a68e371Brian Paul   assert(align2 >= 0);
186766cb95a4564c48f35b5180155ab40320a68e371Brian Paul   assert(align2 <= 12); /* sanity check, 2^12 (4KB) enough? */
187766cb95a4564c48f35b5180155ab40320a68e371Brian Paul
188df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (!heap || align2 < 0 || size <= 0)
189df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      return NULL;
190df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
191df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   for (p = heap->next_free; p != heap; p = p->next_free) {
192df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      assert(p->free);
193df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
194df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      startofs = (p->ofs + mask) & ~mask;
195df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      if ( startofs < startSearch ) {
196df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca	 startofs = startSearch;
197df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      }
198df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      endofs = startofs+size;
199df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      if (endofs <= (p->ofs+p->size))
200df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca	 break;
201df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   }
202df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
203df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (p == heap)
204df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      return NULL;
205df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
206df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   assert(p->free);
207df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   p = SliceBlock(p,startofs,size,0,mask+1);
208df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
209df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   return p;
210df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca}
211df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
212df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
213df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonsecastruct mem_block *
2143ad56968f09397a8dd417eae025b9506efaf8414Brian Paulu_mmFindBlock(struct mem_block *heap, int start)
215df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca{
216df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   struct mem_block *p;
217df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
218df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   for (p = heap->next; p != heap; p = p->next) {
219df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      if (p->ofs == start)
220df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca	 return p;
221df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   }
222df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
223df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   return NULL;
224df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca}
225df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
226df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
227df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonsecastatic INLINE int
228df8ab3140ce05599e1dc983ac211a30fc845d9b5José FonsecaJoin2Blocks(struct mem_block *p)
229df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca{
230df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   /* XXX there should be some assertions here */
231df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
232df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   /* NOTE: heap->free == 0 */
233df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
234df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (p->free && p->next->free) {
235df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      struct mem_block *q = p->next;
236df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
237df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      assert(p->ofs + p->size == q->ofs);
238df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->size += q->size;
239df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
240df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p->next = q->next;
241df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      q->next->prev = p;
242df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
243df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      q->next_free->prev_free = q->prev_free;
244df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      q->prev_free->next_free = q->next_free;
245df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
246df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      FREE(q);
247df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      return 1;
248df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   }
249df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   return 0;
250df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca}
251df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
252df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonsecaint
2533ad56968f09397a8dd417eae025b9506efaf8414Brian Paulu_mmFreeMem(struct mem_block *b)
254df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca{
255df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (!b)
256df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      return 0;
257df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
258df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (b->free) {
259df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      debug_printf("block already free\n");
260df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      return -1;
261df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   }
262df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (b->reserved) {
263df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      debug_printf("block is reserved\n");
264df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      return -1;
265df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   }
266df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
267df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   b->free = 1;
268df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   b->next_free = b->heap->next_free;
269df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   b->prev_free = b->heap;
270df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   b->next_free->prev_free = b;
271df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   b->prev_free->next_free = b;
272df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
273df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   Join2Blocks(b);
274df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (b->prev != b->heap)
275df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      Join2Blocks(b->prev);
276df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
277df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   return 0;
278df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca}
279df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
280df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
281df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonsecavoid
2823ad56968f09397a8dd417eae025b9506efaf8414Brian Paulu_mmDestroy(struct mem_block *heap)
283df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca{
284df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   struct mem_block *p;
285df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
286df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   if (!heap)
287df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      return;
288df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
289df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   for (p = heap->next; p != heap; ) {
290df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      struct mem_block *next = p->next;
291df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      FREE(p);
292df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca      p = next;
293df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   }
294df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca
295df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca   FREE(heap);
296df8ab3140ce05599e1dc983ac211a30fc845d9b5José Fonseca}
297