os/kernelhwsrv/kerneltest/e32test/nkernsa/tlsf.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
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