sl@0
|
1 |
// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
2 |
// All rights reserved.
|
sl@0
|
3 |
// This component and the accompanying materials are made available
|
sl@0
|
4 |
// under the terms of the License "Eclipse Public License v1.0"
|
sl@0
|
5 |
// which accompanies this distribution, and is available
|
sl@0
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
7 |
//
|
sl@0
|
8 |
// Initial Contributors:
|
sl@0
|
9 |
// Nokia Corporation - initial contribution.
|
sl@0
|
10 |
//
|
sl@0
|
11 |
// Contributors:
|
sl@0
|
12 |
//
|
sl@0
|
13 |
// Description:
|
sl@0
|
14 |
// x86pc\nkern\tlsf.cpp
|
sl@0
|
15 |
//
|
sl@0
|
16 |
//
|
sl@0
|
17 |
|
sl@0
|
18 |
#include <nktest/nkutils.h>
|
sl@0
|
19 |
|
sl@0
|
20 |
extern "C" {
|
sl@0
|
21 |
extern TLinAddr RomHeaderAddress;
|
sl@0
|
22 |
extern TLinAddr SuperPageAddress;
|
sl@0
|
23 |
}
|
sl@0
|
24 |
|
sl@0
|
25 |
#define BLOCK_STATUS_FREE 1u // bit set if SBlock free
|
sl@0
|
26 |
#define BLOCK_STATUS_FINAL 2u // bit set if this is last physical SBlock
|
sl@0
|
27 |
#define BLOCK_SIZE_MASK 0xfffffffcu
|
sl@0
|
28 |
|
sl@0
|
29 |
struct SBlock
|
sl@0
|
30 |
{
|
sl@0
|
31 |
TUint32 size; // bits 2-31 give size, bits 0,1 are status bits
|
sl@0
|
32 |
SBlock* predecessor; // previous SBlock in physical address order
|
sl@0
|
33 |
};
|
sl@0
|
34 |
|
sl@0
|
35 |
struct SFreeBlock
|
sl@0
|
36 |
{
|
sl@0
|
37 |
SBlock b;
|
sl@0
|
38 |
SFreeBlock* next; // next SBlock in same bucket, circular list
|
sl@0
|
39 |
SFreeBlock* prev; // previous SBlock in same bucket, circular list
|
sl@0
|
40 |
};
|
sl@0
|
41 |
|
sl@0
|
42 |
struct STlsfAllocator
|
sl@0
|
43 |
{
|
sl@0
|
44 |
public:
|
sl@0
|
45 |
static STlsfAllocator* Create(TAny* aBase, TUint32 aTotalSize);
|
sl@0
|
46 |
TAny* Alloc(TUint32 aSize);
|
sl@0
|
47 |
void Free(TAny* aCell);
|
sl@0
|
48 |
TAny* ReAlloc(TAny* aCell, TUint32 aSize);
|
sl@0
|
49 |
|
sl@0
|
50 |
void Init(TUint32 aTotalSize);
|
sl@0
|
51 |
void InsertFree(SFreeBlock* aB);
|
sl@0
|
52 |
TUint32 MapSize(TUint32 aSize, TUint32* p_sli, TInt round_up);
|
sl@0
|
53 |
SFreeBlock* FindFree(TUint32 aSize);
|
sl@0
|
54 |
void RemoveFree(SFreeBlock* aB);
|
sl@0
|
55 |
TUint32 ConsistencyCheck();
|
sl@0
|
56 |
public:
|
sl@0
|
57 |
TUint32 imin_size; // minimum SBlock size
|
sl@0
|
58 |
TUint32 itotal_size; // total size of allocated and free blocks
|
sl@0
|
59 |
TUint32 il2min; // log2 min size
|
sl@0
|
60 |
TUint32 infl; // number of first level lists
|
sl@0
|
61 |
TUint32 insl; // number of second level lists
|
sl@0
|
62 |
TUint32 il2nsl;
|
sl@0
|
63 |
SFreeBlock** isll; // pointer to first second level list pointer for minimum size
|
sl@0
|
64 |
TUint32 iflb; // first level bitmap
|
sl@0
|
65 |
SBlock* iff; // first free address
|
sl@0
|
66 |
TUint32 islb[1]; // second level bitmaps, one for each first level list
|
sl@0
|
67 |
// second level lists follow, nsl pointers for each first level list
|
sl@0
|
68 |
};
|
sl@0
|
69 |
|
sl@0
|
70 |
STlsfAllocator* TheAllocator;
|
sl@0
|
71 |
NFastMutex AllocMutex;
|
sl@0
|
72 |
|
sl@0
|
73 |
STlsfAllocator* STlsfAllocator::Create(void* aBase, TUint32 aTotalSize)
|
sl@0
|
74 |
{
|
sl@0
|
75 |
STlsfAllocator* p = (STlsfAllocator*)aBase;
|
sl@0
|
76 |
p->Init(aTotalSize);
|
sl@0
|
77 |
return p;
|
sl@0
|
78 |
}
|
sl@0
|
79 |
|
sl@0
|
80 |
void STlsfAllocator::Init(TUint32 total_size)
|
sl@0
|
81 |
{
|
sl@0
|
82 |
TUint32 a;
|
sl@0
|
83 |
imin_size = 16;
|
sl@0
|
84 |
il2min = 4;
|
sl@0
|
85 |
insl = 16;
|
sl@0
|
86 |
il2nsl = 4;
|
sl@0
|
87 |
itotal_size = total_size;
|
sl@0
|
88 |
infl = __e32_find_ms1_32(total_size) - il2min + 1;
|
sl@0
|
89 |
iflb = 0;
|
sl@0
|
90 |
a = (TUint32)&islb[infl];
|
sl@0
|
91 |
a = (a+63)&~63;
|
sl@0
|
92 |
isll = (SFreeBlock**)a;
|
sl@0
|
93 |
a += insl * infl * sizeof(TUint32*);
|
sl@0
|
94 |
iff = (SBlock*)a;
|
sl@0
|
95 |
a -= (TUint32)this;
|
sl@0
|
96 |
memset(islb, 0, total_size - sizeof(STlsfAllocator) + sizeof(TUint32));
|
sl@0
|
97 |
iff->size = (total_size - a) | BLOCK_STATUS_FINAL;
|
sl@0
|
98 |
iff->predecessor = 0;
|
sl@0
|
99 |
Free(iff+1);
|
sl@0
|
100 |
}
|
sl@0
|
101 |
|
sl@0
|
102 |
// size already rounded up to multiple of min_size
|
sl@0
|
103 |
TUint32 STlsfAllocator::MapSize(TUint32 size, TUint32* p_sli, TInt round_up)
|
sl@0
|
104 |
{
|
sl@0
|
105 |
TUint32 sli = size >> il2min;
|
sl@0
|
106 |
TUint32 fli = __e32_find_ms1_32(sli);
|
sl@0
|
107 |
sli -= (1u<<fli);
|
sl@0
|
108 |
if (fli > il2nsl)
|
sl@0
|
109 |
{
|
sl@0
|
110 |
TUint32 sls = (fli - il2nsl);
|
sl@0
|
111 |
TUint32 sz2 = sli;
|
sl@0
|
112 |
sli >>= sls;
|
sl@0
|
113 |
if (round_up && ((sli << sls) < sz2) )
|
sl@0
|
114 |
{
|
sl@0
|
115 |
if (++sli == insl)
|
sl@0
|
116 |
sli=0, ++fli;
|
sl@0
|
117 |
}
|
sl@0
|
118 |
}
|
sl@0
|
119 |
*p_sli = sli;
|
sl@0
|
120 |
return fli;
|
sl@0
|
121 |
}
|
sl@0
|
122 |
|
sl@0
|
123 |
SFreeBlock* STlsfAllocator::FindFree(TUint32 size)
|
sl@0
|
124 |
{
|
sl@0
|
125 |
TUint32 sli;
|
sl@0
|
126 |
TUint32 fli = MapSize(size, &sli, 1);
|
sl@0
|
127 |
TUint32 sli2;
|
sl@0
|
128 |
TUint32 fli2;
|
sl@0
|
129 |
SFreeBlock** sll;
|
sl@0
|
130 |
SFreeBlock* b;
|
sl@0
|
131 |
TUint32 act_sz;
|
sl@0
|
132 |
|
sl@0
|
133 |
if ((iflb >> fli) & 1)
|
sl@0
|
134 |
{
|
sl@0
|
135 |
if ((islb[fli]>>sli)==0)
|
sl@0
|
136 |
++fli, sli=0;
|
sl@0
|
137 |
}
|
sl@0
|
138 |
else
|
sl@0
|
139 |
sli = 0;
|
sl@0
|
140 |
if (fli >= infl)
|
sl@0
|
141 |
return 0;
|
sl@0
|
142 |
fli2 = __e32_find_ls1_32(iflb >> fli);
|
sl@0
|
143 |
if ((TInt)fli2 < 0)
|
sl@0
|
144 |
return 0;
|
sl@0
|
145 |
fli2 += fli;
|
sl@0
|
146 |
sli2 = __e32_find_ls1_32(islb[fli2] >> sli) + sli; // must find a 1
|
sl@0
|
147 |
sll = &isll[(fli2 << il2nsl) | sli2];
|
sl@0
|
148 |
b = *sll;
|
sl@0
|
149 |
if (b->next == b)
|
sl@0
|
150 |
{
|
sl@0
|
151 |
// list now empty
|
sl@0
|
152 |
*sll = 0;
|
sl@0
|
153 |
if ( (islb[fli2] &= ~(1u<<sli2)) == 0 )
|
sl@0
|
154 |
iflb &= ~(1u<<fli2);
|
sl@0
|
155 |
}
|
sl@0
|
156 |
else
|
sl@0
|
157 |
{
|
sl@0
|
158 |
*sll = b->next;
|
sl@0
|
159 |
b->next->prev = b->prev;
|
sl@0
|
160 |
b->prev->next = b->next;
|
sl@0
|
161 |
}
|
sl@0
|
162 |
act_sz = b->b.size & BLOCK_SIZE_MASK;
|
sl@0
|
163 |
if (act_sz > size)
|
sl@0
|
164 |
{
|
sl@0
|
165 |
// free the extra
|
sl@0
|
166 |
SBlock* nfb = (SBlock*)((TUint32)b + size);
|
sl@0
|
167 |
nfb->size = (act_sz - size) | (b->b.size & BLOCK_STATUS_FINAL);
|
sl@0
|
168 |
nfb->predecessor = &b->b;
|
sl@0
|
169 |
if (!(b->b.size & BLOCK_STATUS_FINAL))
|
sl@0
|
170 |
{
|
sl@0
|
171 |
// if this isn't final SBlock, update predecessor of following SBlock
|
sl@0
|
172 |
SBlock* nb = (SBlock*)((TUint32)b + act_sz);
|
sl@0
|
173 |
nb->predecessor = nfb;
|
sl@0
|
174 |
}
|
sl@0
|
175 |
InsertFree((SFreeBlock*)nfb);
|
sl@0
|
176 |
b->b.size = 0; // allocated SBlock can't be final
|
sl@0
|
177 |
}
|
sl@0
|
178 |
b->b.size &= BLOCK_STATUS_FINAL;
|
sl@0
|
179 |
b->b.size |= size;
|
sl@0
|
180 |
return b;
|
sl@0
|
181 |
}
|
sl@0
|
182 |
|
sl@0
|
183 |
void STlsfAllocator::InsertFree(SFreeBlock* b)
|
sl@0
|
184 |
{
|
sl@0
|
185 |
TUint32 size = b->b.size & BLOCK_SIZE_MASK;
|
sl@0
|
186 |
TUint32 sli;
|
sl@0
|
187 |
TUint32 fli = MapSize(size, &sli, 0);
|
sl@0
|
188 |
SFreeBlock** sll = &isll[(fli << il2nsl) | sli];
|
sl@0
|
189 |
if (*sll)
|
sl@0
|
190 |
{
|
sl@0
|
191 |
SFreeBlock* first = *sll;
|
sl@0
|
192 |
b->next = first;
|
sl@0
|
193 |
b->prev = first->prev;
|
sl@0
|
194 |
first->prev->next = b;
|
sl@0
|
195 |
first->prev = b;
|
sl@0
|
196 |
}
|
sl@0
|
197 |
else
|
sl@0
|
198 |
{
|
sl@0
|
199 |
b->next = b;
|
sl@0
|
200 |
b->prev = b;
|
sl@0
|
201 |
islb[fli] |= (1u<<sli);
|
sl@0
|
202 |
iflb |= (1u<<fli);
|
sl@0
|
203 |
}
|
sl@0
|
204 |
*sll = b;
|
sl@0
|
205 |
b->b.size |= BLOCK_STATUS_FREE;
|
sl@0
|
206 |
}
|
sl@0
|
207 |
|
sl@0
|
208 |
void STlsfAllocator::RemoveFree(SFreeBlock* b)
|
sl@0
|
209 |
{
|
sl@0
|
210 |
TUint32 size = b->b.size & BLOCK_SIZE_MASK;
|
sl@0
|
211 |
TUint32 sli;
|
sl@0
|
212 |
TUint32 fli = MapSize(size, &sli, 0);
|
sl@0
|
213 |
SFreeBlock** sll = &isll[(fli << il2nsl) | sli];
|
sl@0
|
214 |
if (b->next != b)
|
sl@0
|
215 |
{
|
sl@0
|
216 |
if (*sll == b)
|
sl@0
|
217 |
*sll = b->next;
|
sl@0
|
218 |
b->next->prev = b->prev;
|
sl@0
|
219 |
b->prev->next = b->next;
|
sl@0
|
220 |
return;
|
sl@0
|
221 |
}
|
sl@0
|
222 |
*sll = 0;
|
sl@0
|
223 |
if ( (islb[fli] &= ~(1u<<sli)) == 0)
|
sl@0
|
224 |
iflb &= ~(1u<<fli);
|
sl@0
|
225 |
}
|
sl@0
|
226 |
|
sl@0
|
227 |
TAny* STlsfAllocator::Alloc(TUint32 size)
|
sl@0
|
228 |
{
|
sl@0
|
229 |
SFreeBlock* b;
|
sl@0
|
230 |
TUint32 msm = imin_size - 1;
|
sl@0
|
231 |
|
sl@0
|
232 |
size = (size + sizeof(SBlock) + msm) &~ msm;
|
sl@0
|
233 |
|
sl@0
|
234 |
b = FindFree(size);
|
sl@0
|
235 |
if (b)
|
sl@0
|
236 |
return &b->next;
|
sl@0
|
237 |
return 0;
|
sl@0
|
238 |
}
|
sl@0
|
239 |
|
sl@0
|
240 |
void STlsfAllocator::Free(TAny* cell)
|
sl@0
|
241 |
{
|
sl@0
|
242 |
SBlock* b = ((SBlock*)cell) - 1;
|
sl@0
|
243 |
// SFreeBlock* fb = (SFreeBlock*)b;
|
sl@0
|
244 |
TUint32 size;
|
sl@0
|
245 |
if (!cell)
|
sl@0
|
246 |
return;
|
sl@0
|
247 |
size = b->size & BLOCK_SIZE_MASK;
|
sl@0
|
248 |
if (!(b->size & BLOCK_STATUS_FINAL))
|
sl@0
|
249 |
{
|
sl@0
|
250 |
// not last SBlock
|
sl@0
|
251 |
SBlock* nb = (SBlock*)((TUint32)b + size);
|
sl@0
|
252 |
TUint32 nbs = nb->size;
|
sl@0
|
253 |
if (nbs & BLOCK_STATUS_FREE)
|
sl@0
|
254 |
{
|
sl@0
|
255 |
// following SBlock is free
|
sl@0
|
256 |
RemoveFree((SFreeBlock*)nb);
|
sl@0
|
257 |
b->size = size + (nbs &~ BLOCK_STATUS_FREE); // keeps final flag from following SBlock
|
sl@0
|
258 |
size = b->size & BLOCK_SIZE_MASK;
|
sl@0
|
259 |
if (!(nbs & BLOCK_STATUS_FINAL))
|
sl@0
|
260 |
{
|
sl@0
|
261 |
nb = (SBlock*)((TUint32)b + size);
|
sl@0
|
262 |
nb->predecessor = b;
|
sl@0
|
263 |
}
|
sl@0
|
264 |
}
|
sl@0
|
265 |
}
|
sl@0
|
266 |
if (b->predecessor && b->predecessor->size & BLOCK_STATUS_FREE)
|
sl@0
|
267 |
{
|
sl@0
|
268 |
// predecessor SBlock is free
|
sl@0
|
269 |
TUint32 psz = b->predecessor->size & BLOCK_SIZE_MASK;
|
sl@0
|
270 |
RemoveFree((SFreeBlock*)b->predecessor);
|
sl@0
|
271 |
psz += b->size; // keeps final flag if necessary
|
sl@0
|
272 |
b->predecessor->size = psz;
|
sl@0
|
273 |
b = b->predecessor;
|
sl@0
|
274 |
if (!(psz & BLOCK_STATUS_FINAL))
|
sl@0
|
275 |
{
|
sl@0
|
276 |
// need to adjust prev pointer of following SBlock
|
sl@0
|
277 |
SBlock* nb = (SBlock*)((TUint32)b + psz);
|
sl@0
|
278 |
nb->predecessor = b;
|
sl@0
|
279 |
}
|
sl@0
|
280 |
}
|
sl@0
|
281 |
InsertFree((SFreeBlock*)b);
|
sl@0
|
282 |
}
|
sl@0
|
283 |
|
sl@0
|
284 |
TAny* STlsfAllocator::ReAlloc(TAny* cell, TUint32 newsize)
|
sl@0
|
285 |
{
|
sl@0
|
286 |
SBlock* b;
|
sl@0
|
287 |
TUint32 size;
|
sl@0
|
288 |
TUint32 msm;
|
sl@0
|
289 |
SBlock* nb;
|
sl@0
|
290 |
TAny* newcell;
|
sl@0
|
291 |
|
sl@0
|
292 |
if (!cell)
|
sl@0
|
293 |
return (newsize>0) ? Alloc(newsize) : 0;
|
sl@0
|
294 |
if (newsize == 0)
|
sl@0
|
295 |
{
|
sl@0
|
296 |
Free(cell);
|
sl@0
|
297 |
return 0;
|
sl@0
|
298 |
}
|
sl@0
|
299 |
b = ((SBlock*)cell) - 1;
|
sl@0
|
300 |
size = b->size & BLOCK_SIZE_MASK;
|
sl@0
|
301 |
msm = imin_size - 1;
|
sl@0
|
302 |
newsize = (newsize + sizeof(SBlock) + msm) &~ msm;
|
sl@0
|
303 |
if (newsize > size)
|
sl@0
|
304 |
{
|
sl@0
|
305 |
nb = (SBlock*)((TUint32)b + size);
|
sl@0
|
306 |
if (nb->size & BLOCK_STATUS_FREE)
|
sl@0
|
307 |
{
|
sl@0
|
308 |
// following SBlock is free
|
sl@0
|
309 |
TUint32 nbs = nb->size;
|
sl@0
|
310 |
if (nbs + size >= newsize)
|
sl@0
|
311 |
{
|
sl@0
|
312 |
// we can expand in place - grab the entire free SBlock for now
|
sl@0
|
313 |
// it will be split if necessary in the next section of code
|
sl@0
|
314 |
RemoveFree((SFreeBlock*)nb);
|
sl@0
|
315 |
b->size = size + (nbs &~ BLOCK_STATUS_FREE); // keeps final flag from following SBlock
|
sl@0
|
316 |
size = b->size & BLOCK_SIZE_MASK;
|
sl@0
|
317 |
if (!(nbs & BLOCK_STATUS_FINAL))
|
sl@0
|
318 |
{
|
sl@0
|
319 |
SBlock* nnb = (SBlock*)((TUint32)b + size);
|
sl@0
|
320 |
nnb->predecessor = b;
|
sl@0
|
321 |
}
|
sl@0
|
322 |
}
|
sl@0
|
323 |
}
|
sl@0
|
324 |
}
|
sl@0
|
325 |
if (newsize == size)
|
sl@0
|
326 |
return cell;
|
sl@0
|
327 |
if (newsize < size)
|
sl@0
|
328 |
{
|
sl@0
|
329 |
// shrinking - split SBlock
|
sl@0
|
330 |
TUint32 final = b->size & BLOCK_STATUS_FINAL;
|
sl@0
|
331 |
SBlock* nfb = (SBlock*)((TUint32)b + newsize);
|
sl@0
|
332 |
nfb->size = (size - newsize) | final;
|
sl@0
|
333 |
nfb->predecessor = b;
|
sl@0
|
334 |
if (!final)
|
sl@0
|
335 |
{
|
sl@0
|
336 |
// if this isn't final SBlock, update predecessor of following SBlock
|
sl@0
|
337 |
nb = (SBlock*)((TUint32)b + size);
|
sl@0
|
338 |
nb->predecessor = nfb;
|
sl@0
|
339 |
}
|
sl@0
|
340 |
b->size = newsize; // original SBlock can't be final
|
sl@0
|
341 |
Free((SBlock*)nfb + 1);
|
sl@0
|
342 |
return cell;
|
sl@0
|
343 |
}
|
sl@0
|
344 |
|
sl@0
|
345 |
// must move SBlock to expand
|
sl@0
|
346 |
newcell = Alloc(newsize);
|
sl@0
|
347 |
if (newcell)
|
sl@0
|
348 |
{
|
sl@0
|
349 |
memcpy(newcell, cell, size);
|
sl@0
|
350 |
Free(cell);
|
sl@0
|
351 |
}
|
sl@0
|
352 |
return newcell;
|
sl@0
|
353 |
}
|
sl@0
|
354 |
|
sl@0
|
355 |
TUint32 STlsfAllocator::ConsistencyCheck()
|
sl@0
|
356 |
{
|
sl@0
|
357 |
TUint32 a;
|
sl@0
|
358 |
TUint32 szs = 0;
|
sl@0
|
359 |
TUint32 size;
|
sl@0
|
360 |
TUint32 total_user_size;
|
sl@0
|
361 |
TUint32 total_block_size = 0;
|
sl@0
|
362 |
TUint32 block_count = 0;
|
sl@0
|
363 |
TUint32 flb = 0;
|
sl@0
|
364 |
TUint32 slb[32];
|
sl@0
|
365 |
TUint32 sli;
|
sl@0
|
366 |
TUint32 fli;
|
sl@0
|
367 |
TUint32 total_free = 0;
|
sl@0
|
368 |
SBlock* b = iff;
|
sl@0
|
369 |
SBlock* pb = 0;
|
sl@0
|
370 |
|
sl@0
|
371 |
memset(slb, 0, sizeof(slb));
|
sl@0
|
372 |
__NK_ASSERT_DEBUG(imin_size == 16);
|
sl@0
|
373 |
__NK_ASSERT_DEBUG(insl == 16);
|
sl@0
|
374 |
__NK_ASSERT_DEBUG(il2min == 4);
|
sl@0
|
375 |
__NK_ASSERT_DEBUG(il2nsl == 4);
|
sl@0
|
376 |
__NK_ASSERT_DEBUG(infl == __e32_find_ms1_32(itotal_size) - il2min + 1);
|
sl@0
|
377 |
a = (TUint32)&islb[infl];
|
sl@0
|
378 |
a = (a+63)&~63;
|
sl@0
|
379 |
__NK_ASSERT_DEBUG(isll == (SFreeBlock**)a);
|
sl@0
|
380 |
a += insl * infl * sizeof(TUint32*);
|
sl@0
|
381 |
__NK_ASSERT_DEBUG(iff == (SBlock*)a);
|
sl@0
|
382 |
total_user_size = itotal_size - (a - (TUint32)this);
|
sl@0
|
383 |
|
sl@0
|
384 |
do {
|
sl@0
|
385 |
szs = b->size;
|
sl@0
|
386 |
size = szs & BLOCK_SIZE_MASK;
|
sl@0
|
387 |
__NK_ASSERT_DEBUG(b->predecessor == pb);
|
sl@0
|
388 |
__NK_ASSERT_DEBUG(size > 0);
|
sl@0
|
389 |
__NK_ASSERT_DEBUG(size <= total_user_size);
|
sl@0
|
390 |
__NK_ASSERT_DEBUG(size == ((size >> il2min) << il2min));
|
sl@0
|
391 |
total_block_size += size;
|
sl@0
|
392 |
++block_count;
|
sl@0
|
393 |
pb = b;
|
sl@0
|
394 |
b = (SBlock*)((TUint32)b + size);
|
sl@0
|
395 |
} while(!(szs & BLOCK_STATUS_FINAL));
|
sl@0
|
396 |
__NK_ASSERT_DEBUG((TUint32)b == (TUint32)this + itotal_size);
|
sl@0
|
397 |
__NK_ASSERT_DEBUG(total_block_size == total_user_size);
|
sl@0
|
398 |
|
sl@0
|
399 |
b = iff;
|
sl@0
|
400 |
do {
|
sl@0
|
401 |
szs = b->size;
|
sl@0
|
402 |
size = szs & BLOCK_SIZE_MASK;
|
sl@0
|
403 |
if (szs & BLOCK_STATUS_FREE)
|
sl@0
|
404 |
{
|
sl@0
|
405 |
SFreeBlock* fb = (SFreeBlock*)b;
|
sl@0
|
406 |
SFreeBlock* pfb = fb;
|
sl@0
|
407 |
SFreeBlock* lh;
|
sl@0
|
408 |
TUint32 lhi;
|
sl@0
|
409 |
TInt lh_found = 0;
|
sl@0
|
410 |
TInt c = (TInt)block_count;
|
sl@0
|
411 |
TUint32 fli = __e32_find_ms1_32(size) - il2min;
|
sl@0
|
412 |
TUint32 sli = (size >> il2min) - (1u << fli);
|
sl@0
|
413 |
TUint32 sli2;
|
sl@0
|
414 |
TUint32 fli2 = MapSize(size, &sli2, 0);
|
sl@0
|
415 |
(void)sli2, (void)fli2;
|
sl@0
|
416 |
if (fli > il2nsl)
|
sl@0
|
417 |
sli >>= (fli - il2nsl);
|
sl@0
|
418 |
__NK_ASSERT_DEBUG(fli == fli2);
|
sl@0
|
419 |
__NK_ASSERT_DEBUG(sli == sli2);
|
sl@0
|
420 |
flb |= (1u << fli);
|
sl@0
|
421 |
slb[fli] |= (1u << sli);
|
sl@0
|
422 |
lhi = (fli << il2nsl) | sli;
|
sl@0
|
423 |
lh = isll[lhi];
|
sl@0
|
424 |
do {
|
sl@0
|
425 |
if (fb == lh)
|
sl@0
|
426 |
lh_found = 1;
|
sl@0
|
427 |
pfb = fb;
|
sl@0
|
428 |
fb = fb->next;
|
sl@0
|
429 |
__NK_ASSERT_DEBUG(fb->prev == pfb);
|
sl@0
|
430 |
__NK_ASSERT_DEBUG(fb->b.size & BLOCK_STATUS_FREE);
|
sl@0
|
431 |
} while ((fb != (SFreeBlock*)b) && --c>=0);
|
sl@0
|
432 |
__NK_ASSERT_DEBUG(fb == (SFreeBlock*)b);
|
sl@0
|
433 |
__NK_ASSERT_DEBUG(lh_found);
|
sl@0
|
434 |
total_free += size;
|
sl@0
|
435 |
}
|
sl@0
|
436 |
b = (SBlock*)((TUint32)b + size);
|
sl@0
|
437 |
} while(!(szs & BLOCK_STATUS_FINAL));
|
sl@0
|
438 |
|
sl@0
|
439 |
__NK_ASSERT_DEBUG(flb == iflb);
|
sl@0
|
440 |
for (fli=0; fli<infl; ++fli)
|
sl@0
|
441 |
{
|
sl@0
|
442 |
__NK_ASSERT_DEBUG(slb[fli] == islb[fli]);
|
sl@0
|
443 |
if (!(flb & (1u<<fli)))
|
sl@0
|
444 |
__NK_ASSERT_DEBUG(slb[fli]==0);
|
sl@0
|
445 |
for (sli=0; sli<insl; ++sli)
|
sl@0
|
446 |
{
|
sl@0
|
447 |
TUint32 lhi = (fli << il2nsl) | sli;
|
sl@0
|
448 |
(void)lhi;
|
sl@0
|
449 |
if (!(slb[fli] & (1u<<sli)))
|
sl@0
|
450 |
__NK_ASSERT_DEBUG(!isll[lhi]);
|
sl@0
|
451 |
}
|
sl@0
|
452 |
}
|
sl@0
|
453 |
return total_free;
|
sl@0
|
454 |
}
|
sl@0
|
455 |
|
sl@0
|
456 |
#define __E32CMN_H__
|
sl@0
|
457 |
|
sl@0
|
458 |
#undef EXPORT_C
|
sl@0
|
459 |
#define EXPORT_C /* */
|
sl@0
|
460 |
|
sl@0
|
461 |
class TVersion
|
sl@0
|
462 |
{
|
sl@0
|
463 |
public:
|
sl@0
|
464 |
TInt8 iMajor;
|
sl@0
|
465 |
TInt8 iMinor;
|
sl@0
|
466 |
TInt16 iBuild;
|
sl@0
|
467 |
};
|
sl@0
|
468 |
|
sl@0
|
469 |
class TDesC;
|
sl@0
|
470 |
|
sl@0
|
471 |
#include <e32rom.h>
|
sl@0
|
472 |
#include "kernboot.h"
|
sl@0
|
473 |
|
sl@0
|
474 |
extern "C" {
|
sl@0
|
475 |
void SetupMemoryAllocator()
|
sl@0
|
476 |
{
|
sl@0
|
477 |
const SSuperPageBase& sp = *(const SSuperPageBase*)SuperPageAddress;
|
sl@0
|
478 |
const TRomHeader& romHdr = *(const TRomHeader*)RomHeaderAddress;
|
sl@0
|
479 |
const TRomEntry* primaryEntry = (const TRomEntry*)sp.iPrimaryEntry;
|
sl@0
|
480 |
const TRomImageHeader* primaryImageHeader = (const TRomImageHeader*)primaryEntry->iAddressLin;
|
sl@0
|
481 |
TLinAddr stack = romHdr.iKernDataAddress + round_to_page(romHdr.iTotalSvDataSize);
|
sl@0
|
482 |
TLinAddr heapbase = stack + round_to_page(primaryImageHeader->iStackSize);
|
sl@0
|
483 |
TLinAddr heapsize = sp.iInitialHeapSize;
|
sl@0
|
484 |
|
sl@0
|
485 |
KPrintf("Heap base %08x size %08x", heapbase, heapsize);
|
sl@0
|
486 |
TheAllocator = STlsfAllocator::Create((TAny*)heapbase, heapsize);
|
sl@0
|
487 |
}
|
sl@0
|
488 |
|
sl@0
|
489 |
extern TBool InitialThreadDefined;
|
sl@0
|
490 |
|
sl@0
|
491 |
TAny* malloc(TUint32 aSize)
|
sl@0
|
492 |
{
|
sl@0
|
493 |
// __KTRACE_OPT(KMMU,DEBUGPRINT("malloc(%d)",aSize));
|
sl@0
|
494 |
if (InitialThreadDefined)
|
sl@0
|
495 |
NKern::FMWait(&AllocMutex);
|
sl@0
|
496 |
TAny* p = TheAllocator->Alloc(aSize);
|
sl@0
|
497 |
if (InitialThreadDefined)
|
sl@0
|
498 |
NKern::FMSignal(&AllocMutex);
|
sl@0
|
499 |
__KTRACE_OPT(KMMU,DEBUGPRINT("malloc(%d)->%08x",aSize,p));
|
sl@0
|
500 |
return p;
|
sl@0
|
501 |
}
|
sl@0
|
502 |
|
sl@0
|
503 |
void free(TAny* aCell)
|
sl@0
|
504 |
{
|
sl@0
|
505 |
__KTRACE_OPT(KMMU,DEBUGPRINT("free(%08x)",aCell));
|
sl@0
|
506 |
#ifdef _DEBUG
|
sl@0
|
507 |
if (aCell)
|
sl@0
|
508 |
{
|
sl@0
|
509 |
SBlock* b = (SBlock*)aCell;
|
sl@0
|
510 |
TUint32 size = b[-1].size & BLOCK_SIZE_MASK;
|
sl@0
|
511 |
memset(aCell, 0xde, size - sizeof(SBlock));
|
sl@0
|
512 |
}
|
sl@0
|
513 |
#endif
|
sl@0
|
514 |
NKern::FMWait(&AllocMutex);
|
sl@0
|
515 |
TheAllocator->Free(aCell);
|
sl@0
|
516 |
NKern::FMSignal(&AllocMutex);
|
sl@0
|
517 |
}
|
sl@0
|
518 |
|
sl@0
|
519 |
TAny* realloc(TAny* aCell, TUint32 aSize)
|
sl@0
|
520 |
{
|
sl@0
|
521 |
NKern::FMWait(&AllocMutex);
|
sl@0
|
522 |
TAny* p = TheAllocator->ReAlloc(aCell, aSize);
|
sl@0
|
523 |
NKern::FMSignal(&AllocMutex);
|
sl@0
|
524 |
return p;
|
sl@0
|
525 |
}
|
sl@0
|
526 |
}
|
sl@0
|
527 |
|