kernel/eka/common/heap_hybrid.cpp
author hgs
Thu, 10 Jun 2010 11:48:01 +0100
changeset 149 d9f1e5bfe28c
child 200 73ea206103e6
permissions -rw-r--r--
201021_18
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
149
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
     1
// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
     2
// All rights reserved.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
     3
// This component and the accompanying materials are made available
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
     4
// under the terms of the License "Eclipse Public License v1.0"
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
     5
// which accompanies this distribution, and is available
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
     7
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
     8
// Initial Contributors:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
     9
// Nokia Corporation - initial contribution.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    10
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    11
// Contributors:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    12
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    13
// Description:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    14
// kernel\eka\common\heap_hybrid.cpp
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    15
// 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    16
// Uses malloc (aka dlmalloc) written by Doug Lea version 2.8.4
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    17
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    18
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    19
#include "common.h"
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    20
#ifdef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    21
#include <kernel/kern_priv.h>
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    22
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    23
#include "dla.h"
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    24
#ifndef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    25
#include "slab.h"
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    26
#include "page_alloc.h"
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    27
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    28
#include "heap_hybrid.h"
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    29
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    30
// enables btrace code compiling into 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    31
#define ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    32
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    33
// if non zero this causes the iSlabs to be configured only when the chunk size exceeds this level
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    34
#define DELAYED_SLAB_THRESHOLD (64*1024)		// 64KB seems about right based on trace data
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    35
#define SLAB_CONFIG 0xabe						// Use slabs of size 48, 40, 32, 24, 20, 16, 12, and 8 bytes
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    36
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    37
#ifdef _DEBUG
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    38
#define __SIMULATE_ALLOC_FAIL(s)	if (CheckForSimulatedAllocFail()) {s}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    39
#define __ALLOC_DEBUG_HEADER(s)  	(s += EDebugHdrSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    40
#define __SET_DEBUG_DATA(p,n,c)   	(((SDebugCell*)(p))->nestingLevel = (n), ((SDebugCell*)(p))->allocCount = (c))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    41
#define __GET_USER_DATA_BFR(p)   	((p!=0) ? (TUint8*)(p) + EDebugHdrSize : NULL)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    42
#define __GET_DEBUG_DATA_BFR(p)   	((p!=0) ? (TUint8*)(p) - EDebugHdrSize : NULL)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    43
#define	__ZAP_CELL(p)				memset( (TUint8*)p, 0xde, (AllocLen(__GET_USER_DATA_BFR(p))+EDebugHdrSize))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    44
#define __DEBUG_SAVE(p)				TInt dbgNestLevel = ((SDebugCell*)p)->nestingLevel
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    45
#define __DEBUG_RESTORE(p)			if (p) {((SDebugCell*)p)->nestingLevel = dbgNestLevel;}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    46
#define __DEBUG_HDR_SIZE			EDebugHdrSize
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    47
#define __REMOVE_DBG_HDR(n) 		(n*EDebugHdrSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    48
#define __GET_AVAIL_BLOCK_SIZE(s)   ( (s<EDebugHdrSize) ? 0 : s-EDebugHdrSize )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    49
#define __UPDATE_ALLOC_COUNT(o,n,c)	if (o!=n && n) {((SDebugCell*)n)->allocCount = (c);}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    50
#define __INIT_COUNTERS(i)	        iCellCount=i,iTotalAllocSize=i
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    51
#define __INCREMENT_COUNTERS(p)	    iCellCount++, iTotalAllocSize += AllocLen(p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    52
#define __DECREMENT_COUNTERS(p)	    iCellCount--, iTotalAllocSize -= AllocLen(p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    53
#define __UPDATE_TOTAL_ALLOC(p,s)	iTotalAllocSize += (AllocLen(__GET_USER_DATA_BFR(p)) - s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    54
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    55
#else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    56
#define __SIMULATE_ALLOC_FAIL(s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    57
#define __ALLOC_DEBUG_HEADER(s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    58
#define __SET_DEBUG_DATA(p,n,c)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    59
#define __GET_USER_DATA_BFR(p)  (p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    60
#define __GET_DEBUG_DATA_BFR(p) (p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    61
#define	__ZAP_CELL(p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    62
#define __DEBUG_SAVE(p)			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    63
#define __DEBUG_RESTORE(p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    64
#define __DEBUG_HDR_SIZE		0
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    65
#define __REMOVE_DBG_HDR(n) 	0
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    66
#define __GET_AVAIL_BLOCK_SIZE(s)   (s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    67
#define __UPDATE_ALLOC_COUNT(o,n,c)	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    68
#define __INIT_COUNTERS(i)	        iCellCount=i,iTotalAllocSize=i
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    69
#define __INCREMENT_COUNTERS(p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    70
#define __DECREMENT_COUNTERS(p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    71
#define __UPDATE_TOTAL_ALLOC(p,s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    72
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    73
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    74
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    75
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    76
#define MEMORY_MONITORED  (iFlags & EMonitorMemory)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    77
#define GM  (&iGlobalMallocState)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    78
#define IS_FIXED_HEAP  (iFlags & EFixedSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    79
#define __INIT_COUNTERS(i)	iCellCount=i,iTotalAllocSize=i
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    80
#define __POWER_OF_2(x)		(!((x)&((x)-1)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    81
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    82
#define __DL_BFR_CHECK(M,P) \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    83
		  if ( MEMORY_MONITORED ) \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    84
             if ( !IS_ALIGNED(P) || ((TUint8*)(P)<M->iSeg.iBase) || ((TUint8*)(P)>(M->iSeg.iBase+M->iSeg.iSize))) \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    85
                  BTraceContext12(BTrace::EHeap, BTrace::EHeapCorruption, (TUint32)this, (TUint32)P, (TUint32)0), HEAP_PANIC(ETHeapBadCellAddress); \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    86
			 else DoCheckInuseChunk(M, MEM2CHUNK(P)) 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    87
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    88
#ifndef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    89
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    90
#define __SLAB_BFR_CHECK(S,P,B) \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    91
	  if ( MEMORY_MONITORED ) \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    92
		  if ( ((TUint32)P & 0x3) || ((TUint8*)P<iMemBase) || ((TUint8*)(P)>(TUint8*)this))  \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    93
			   BTraceContext12(BTrace::EHeap, BTrace::EHeapCorruption, (TUint32)this, (TUint32)P, (TUint32)S), HEAP_PANIC(ETHeapBadCellAddress); \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    94
		  else DoCheckSlab(S, EPartialFullSlab, P), BuildPartialSlabBitmap(B,S,P) 					  
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    95
#define __PAGE_BFR_CHECK(P) \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    96
		if ( MEMORY_MONITORED ) \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    97
			if ( ((TUint32)P &  ((1 << iPageSize)-1)) || ((TUint8*)P<iMemBase) || ((TUint8*)(P)>(TUint8*)this))  \
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    98
				BTraceContext12(BTrace::EHeap, BTrace::EHeapCorruption, (TUint32)this, (TUint32)P, (TUint32)0), HEAP_PANIC(ETHeapBadCellAddress)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
    99
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   100
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   101
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   102
#ifdef _MSC_VER
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   103
// This is required while we are still using VC6 to compile, so as to avoid warnings that cannot be fixed
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   104
// without having to edit the original Doug Lea source.  The 4146 warnings are due to the original code having
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   105
// a liking for negating unsigned numbers and the 4127 warnings are due to the original code using the RTCHECK
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   106
// macro with values that are always defined as 1.  It is better to turn these warnings off than to introduce
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   107
// diffs between the original Doug Lea implementation and our adaptation of it
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   108
#pragma warning( disable : 4146 ) /* unary minus operator applied to unsigned type, result still unsigned */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   109
#pragma warning( disable : 4127 ) /* conditional expression is constant */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   110
#endif // _MSC_VER
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   111
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   112
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   113
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   114
@SYMPatchable
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   115
@publishedPartner
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   116
@released
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   117
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   118
Defines the minimum cell size of  a heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   119
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   120
The constant can be changed at ROM build time using patchdata OBY keyword.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   121
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   122
@deprecated Patching this constant no longer has any effect.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   123
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   124
#ifdef __X86GCC__	// For X86GCC we dont use the proper data import attribute
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   125
#undef IMPORT_D		// since the constants are not really imported. GCC doesn't 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   126
#define IMPORT_D	// allow imports from self.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   127
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   128
IMPORT_D extern const TInt KHeapMinCellSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   129
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   130
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   131
@SYMPatchable
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   132
@publishedPartner
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   133
@released
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   134
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   135
This constant defines the ratio that determines the amount of hysteresis between heap growing and heap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   136
shrinking.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   137
It is a 32-bit fixed point number where the radix point is defined to be
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   138
between bits 7 and 8 (where the LSB is bit 0) i.e. using standard notation, a Q8 or a fx24.8
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   139
fixed point number.  For example, for a ratio of 2.0, set KHeapShrinkHysRatio=0x200.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   140
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   141
The heap shrinking hysteresis value is calculated to be:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   142
@code
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   143
KHeapShrinkHysRatio*(iGrowBy>>8)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   144
@endcode
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   145
where iGrowBy is a page aligned value set by the argument, aGrowBy, to the RHeap constructor.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   146
The default hysteresis value is iGrowBy bytes i.e. KHeapShrinkHysRatio=2.0.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   147
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   148
Memory usage may be improved by reducing the heap shrinking hysteresis
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   149
by setting 1.0 < KHeapShrinkHysRatio < 2.0.  Heap shrinking hysteresis is disabled/removed
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   150
when KHeapShrinkHysRatio <= 1.0.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   151
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   152
The constant can be changed at ROM build time using patchdata OBY keyword.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   153
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   154
IMPORT_D extern const TInt KHeapShrinkHysRatio;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   155
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   156
UEXPORT_C TInt RHeap::AllocLen(const TAny* aCell) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   157
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   158
	const MAllocator* m = this;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   159
	return m->AllocLen(aCell);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   160
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   161
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   162
UEXPORT_C TAny* RHeap::Alloc(TInt aSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   163
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   164
	const MAllocator* m = this;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   165
	return ((MAllocator*)m)->Alloc(aSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   166
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   167
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   168
UEXPORT_C void RHeap::Free(TAny* aCell)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   169
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   170
	const MAllocator* m = this;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   171
	((MAllocator*)m)->Free(aCell);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   172
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   173
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   174
UEXPORT_C TAny* RHeap::ReAlloc(TAny* aCell, TInt aSize, TInt aMode)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   175
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   176
	const MAllocator* m = this;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   177
	return ((MAllocator*)m)->ReAlloc(aCell, aSize, aMode);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   178
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   179
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   180
UEXPORT_C TInt RHeap::DebugFunction(TInt aFunc, TAny* a1, TAny* a2)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   181
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   182
	const MAllocator* m = this;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   183
	return ((MAllocator*)m)->DebugFunction(aFunc, a1, a2);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   184
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   185
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   186
UEXPORT_C TInt RHeap::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   187
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   188
	const MAllocator* m = this;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   189
	return ((MAllocator*)m)->Extension_(aExtensionId, a0, a1);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   190
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   191
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   192
#ifndef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   193
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   194
EXPORT_C TInt RHeap::AllocSize(TInt& aTotalAllocSize) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   195
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   196
	const MAllocator* m = this;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   197
	return m->AllocSize(aTotalAllocSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   198
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   199
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   200
EXPORT_C TInt RHeap::Available(TInt& aBiggestBlock) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   201
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   202
	const MAllocator* m = this;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   203
	return m->Available(aBiggestBlock);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   204
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   205
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   206
EXPORT_C void RHeap::Reset()
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   207
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   208
	const MAllocator* m = this;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   209
	((MAllocator*)m)->Reset();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   210
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   211
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   212
EXPORT_C TInt RHeap::Compress()
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   213
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   214
	const MAllocator* m = this;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   215
	return ((MAllocator*)m)->Compress();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   216
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   217
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   218
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   219
RHybridHeap::RHybridHeap()
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   220
	{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   221
	// This initialisation cannot be done in RHeap() for compatibility reasons
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   222
	iMaxLength = iChunkHandle = iNestingLevel = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   223
	iTop = NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   224
	iFailType = ENone;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   225
	iTestData = NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   226
	}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   227
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   228
void RHybridHeap::operator delete(TAny*, TAny*) 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   229
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   230
Called if constructor issued by operator new(TUint aSize, TAny* aBase) throws exception.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   231
This is dummy as corresponding new operator does not allocate memory.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   232
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   233
{}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   234
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   235
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   236
#ifndef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   237
void RHybridHeap::Lock() const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   238
   /**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   239
   @internalComponent
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   240
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   241
   {((RFastLock&)iLock).Wait();}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   242
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   243
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   244
void RHybridHeap::Unlock() const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   245
   /**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   246
   @internalComponent
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   247
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   248
   {((RFastLock&)iLock).Signal();}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   249
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   250
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   251
TInt RHybridHeap::ChunkHandle() const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   252
   /**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   253
   @internalComponent
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   254
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   255
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   256
	return iChunkHandle;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   257
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   258
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   259
#else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   260
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   261
//  This method is implemented in kheap.cpp
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   262
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   263
//void RHybridHeap::Lock() const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   264
   /**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   265
   @internalComponent
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   266
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   267
//   {;}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   268
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   269
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   270
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   271
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   272
//  This method is implemented in kheap.cpp
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   273
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   274
//void RHybridHeap::Unlock() const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   275
   /**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   276
   @internalComponent
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   277
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   278
//   {;}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   279
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   280
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   281
TInt RHybridHeap::ChunkHandle() const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   282
   /**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   283
   @internalComponent
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   284
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   285
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   286
	return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   287
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   288
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   289
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   290
RHybridHeap::RHybridHeap(TInt aChunkHandle, TInt aOffset, TInt aMinLength, TInt aMaxLength, TInt aGrowBy, TInt aAlign, TBool aSingleThread, TBool aDLOnly, TBool aUseAdjust)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   291
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   292
Constructor for a non fixed heap.  Unlike the fixed heap, this heap is quite flexible in terms of its minimum and
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   293
maximum lengths and in that it can use the hybrid allocator if all of its requirements are met.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   294
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   295
	: iOffset(aOffset), iChunkSize(aMinLength)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   296
	{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   297
	__ASSERT_ALWAYS(iOffset>=0, HEAP_PANIC(ETHeapNewBadOffset));	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   298
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   299
	iChunkHandle = aChunkHandle;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   300
	iMinLength = aMinLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   301
	iMaxLength = aMaxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   302
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   303
	// If the user has explicitly specified 0 as the aGrowBy value, set it to 1 so that it will be rounded up to the nearst page size
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   304
	if (aGrowBy == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   305
		aGrowBy = 1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   306
	GET_PAGE_SIZE(iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   307
	iGrowBy = _ALIGN_UP(aGrowBy, iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   308
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   309
	Construct(aSingleThread, aDLOnly, aUseAdjust, aAlign);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   310
	}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   311
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   312
RHybridHeap::RHybridHeap(TInt aMaxLength, TInt aAlign, TBool aSingleThread)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   313
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   314
Constructor for a fixed heap.  We have restrictions in that we have fixed minimum and maximum lengths and cannot grow
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   315
and we only use DL allocator.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   316
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   317
	: iOffset(0), iChunkSize(aMaxLength)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   318
	{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   319
	iChunkHandle = NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   320
	iMinLength = aMaxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   321
	iMaxLength = aMaxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   322
	iGrowBy = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   323
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   324
	Construct(aSingleThread, ETrue, ETrue, aAlign);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   325
	}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   326
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   327
TAny* RHybridHeap::operator new(TUint aSize, TAny* aBase) __NO_THROW
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   328
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   329
	__ASSERT_ALWAYS(aSize>=sizeof(RHybridHeap), HEAP_PANIC(ETHeapNewBadSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   330
	RHybridHeap* h = (RHybridHeap*)aBase;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   331
	h->iBase = ((TUint8*)aBase) + aSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   332
	return aBase;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   333
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   334
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   335
void RHybridHeap::Construct(TBool aSingleThread, TBool aDLOnly, TBool aUseAdjust, TInt aAlign)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   336
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   337
	iAlign = aAlign ? aAlign : RHybridHeap::ECellAlignment;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   338
	__ASSERT_ALWAYS((TUint32)iAlign>=sizeof(TAny*) && __POWER_OF_2(iAlign), HEAP_PANIC(ETHeapNewBadAlignment));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   339
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   340
	// This initialisation cannot be done in RHeap() for compatibility reasons
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   341
	iTop = NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   342
	iFailType = ENone;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   343
	iNestingLevel = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   344
	iTestData = NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   345
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   346
	iHighWaterMark = iMinLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   347
	iAllocCount = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   348
	iFlags = aSingleThread ? ESingleThreaded : 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   349
	iGrowBy = _ALIGN_UP(iGrowBy, iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   350
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   351
	if ( iMinLength == iMaxLength )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   352
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   353
		iFlags |= EFixedSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   354
		aDLOnly = ETrue;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   355
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   356
#ifndef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   357
#ifdef DELAYED_SLAB_THRESHOLD
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   358
	iSlabInitThreshold = DELAYED_SLAB_THRESHOLD;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   359
#else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   360
	iSlabInitThreshold = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   361
#endif // DELAYED_SLAB_THRESHOLD
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   362
	iUseAdjust = aUseAdjust;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   363
	iDLOnly    = aDLOnly;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   364
#else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   365
	(void)aUseAdjust;	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   366
#endif 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   367
	// Initialise suballocators
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   368
	// if DL only is required then it cannot allocate slab or page memory
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   369
	// so these sub-allocators should be disabled. Otherwise initialise with default values
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   370
	if ( aDLOnly )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   371
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   372
		Init(0, 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   373
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   374
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   375
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   376
		Init(SLAB_CONFIG, 16);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   377
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   378
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   379
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   380
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   381
	TUint32 traceData[4];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   382
	traceData[0] = iMinLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   383
	traceData[1] = iMaxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   384
	traceData[2] = iGrowBy;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   385
	traceData[3] = iAlign;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   386
	BTraceContextN(BTrace::ETest1, 90, (TUint32)this, 11, traceData, sizeof(traceData));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   387
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   388
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   389
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   390
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   391
#ifndef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   392
TInt RHybridHeap::ConstructLock(TUint32 aMode)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   393
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   394
	TBool duplicateLock = EFalse;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   395
	TInt r = KErrNone;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   396
	if (!(iFlags & ESingleThreaded))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   397
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   398
		duplicateLock = aMode & UserHeap::EChunkHeapSwitchTo;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   399
		r = iLock.CreateLocal(duplicateLock ? EOwnerThread : EOwnerProcess);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   400
		if( r != KErrNone)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   401
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   402
			iChunkHandle = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   403
			return r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   404
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   405
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   406
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   407
	if ( aMode & UserHeap::EChunkHeapSwitchTo )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   408
		User::SwitchHeap(this);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   409
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   410
	iHandles = &iChunkHandle;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   411
	if (!(iFlags & ESingleThreaded))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   412
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   413
		// now change the thread-relative chunk/semaphore handles into process-relative handles
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   414
		iHandleCount = 2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   415
		if(duplicateLock)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   416
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   417
			RHandleBase s = iLock;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   418
			r = iLock.Duplicate(RThread());
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   419
			s.Close();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   420
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   421
		if (r==KErrNone && (aMode & UserHeap::EChunkHeapDuplicate))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   422
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   423
			r = ((RChunk*)&iChunkHandle)->Duplicate(RThread());
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   424
			if (r!=KErrNone)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   425
				iLock.Close(), iChunkHandle=0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   426
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   427
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   428
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   429
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   430
		iHandleCount = 1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   431
		if (aMode & UserHeap::EChunkHeapDuplicate)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   432
			r = ((RChunk*)&iChunkHandle)->Duplicate(RThread(), EOwnerThread);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   433
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   434
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   435
	return r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   436
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   437
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   438
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   439
void RHybridHeap::Init(TInt aBitmapSlab, TInt aPagePower)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   440
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   441
	/*Moved code which does initilization */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   442
	iTop  = (TUint8*)this + iMinLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   443
	iBase = Ceiling(iBase, ECellAlignment);	// Align iBase address 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   444
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   445
    __INIT_COUNTERS(0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   446
	//	memset(&mparams,0,sizeof(mparams));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   447
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   448
	InitDlMalloc(iTop - iBase, 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   449
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   450
#ifndef __KERNEL_MODE__	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   451
	SlabInit();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   452
	iSlabConfigBits = aBitmapSlab;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   453
	if ( iChunkSize > iSlabInitThreshold )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   454
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   455
		iSlabInitThreshold = KMaxTInt32;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   456
		SlabConfig(aBitmapSlab);   // Delayed slab configuration done
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   457
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   458
	if ( aPagePower )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   459
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   460
		RChunk chunk;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   461
		chunk.SetHandle(iChunkHandle);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   462
		iMemBase = chunk.Base();    // Store base address for paged allocator
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   463
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   464
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   465
	/*10-1K,11-2K,12-4k,13-8K,14-16K,15-32K,16-64K*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   466
	PagedInit(aPagePower);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   467
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   468
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   469
	TUint32 traceData[3];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   470
	traceData[0] = aBitmapSlab;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   471
	traceData[1] = aPagePower;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   472
	traceData[2] = GM->iTrimCheck;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   473
	BTraceContextN(BTrace::ETest1, 90, (TUint32)this, 0, traceData, sizeof(traceData));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   474
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   475
#else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   476
	(void)aBitmapSlab;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   477
	(void)aPagePower;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   478
#endif	// __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   479
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   480
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   481
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   482
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   483
TInt RHybridHeap::AllocLen(const TAny* aCell) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   484
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   485
	aCell = __GET_DEBUG_DATA_BFR(aCell);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   486
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   487
	if (PtrDiff(aCell, this) >= 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   488
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   489
		mchunkptr m = MEM2CHUNK(aCell);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   490
		return CHUNKSIZE(m) - OVERHEAD_FOR(m) - __DEBUG_HDR_SIZE;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   491
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   492
#ifndef __KERNEL_MODE__		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   493
	if ( aCell )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   494
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   495
		if (LowBits(aCell, iPageSize) )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   496
			return SlabHeaderSize(slab::SlabFor(aCell)->iHeader) - __DEBUG_HDR_SIZE;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   497
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   498
		return PagedSize((void*)aCell) - __DEBUG_HDR_SIZE;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   499
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   500
#endif	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   501
	return 0; // NULL pointer situation, should PANIC !!
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   502
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   503
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   504
#ifdef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   505
TAny* RHybridHeap::Alloc(TInt aSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   506
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   507
	__CHECK_THREAD_STATE;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   508
	__ASSERT_ALWAYS((TUint)aSize<(KMaxTInt/2),HEAP_PANIC(ETHeapBadAllocatedCellSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   509
	__SIMULATE_ALLOC_FAIL(return NULL;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   510
	Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   511
	__ALLOC_DEBUG_HEADER(aSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   512
	TAny* addr = DlMalloc(aSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   513
	if ( addr )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   514
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   515
//		iCellCount++;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   516
		__SET_DEBUG_DATA(addr, iNestingLevel, ++iAllocCount);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   517
		addr = __GET_USER_DATA_BFR(addr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   518
		__INCREMENT_COUNTERS(addr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   519
		memclr(addr, AllocLen(addr));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   520
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   521
	Unlock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   522
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   523
	if (iFlags & ETraceAllocs)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   524
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   525
		if ( addr )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   526
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   527
			TUint32 traceData[3];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   528
			traceData[0] = AllocLen(addr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   529
			traceData[1] = aSize - __DEBUG_HDR_SIZE;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   530
			traceData[2] = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   531
			BTraceContextN(BTrace::EHeap, BTrace::EHeapAlloc, (TUint32)this, (TUint32)addr, traceData, sizeof(traceData));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   532
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   533
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   534
			BTraceContext8(BTrace::EHeap, BTrace::EHeapAllocFail, (TUint32)this, (TUint32)(aSize - __DEBUG_HDR_SIZE));			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   535
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   536
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   537
	return addr;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   538
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   539
#else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   540
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   541
TAny* RHybridHeap::Alloc(TInt aSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   542
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   543
	__ASSERT_ALWAYS((TUint)aSize<(KMaxTInt/2),HEAP_PANIC(ETHeapBadAllocatedCellSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   544
	__SIMULATE_ALLOC_FAIL(return NULL;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   545
			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   546
	TAny* addr;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   547
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   548
	TInt aSubAllocator=0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   549
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   550
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   551
	Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   552
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   553
	__ALLOC_DEBUG_HEADER(aSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   554
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   555
	if (aSize < iSlabThreshold)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   556
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   557
		TInt ix = iSizeMap[(aSize+3)>>2];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   558
		HEAP_ASSERT(ix != 0xff);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   559
		addr = SlabAllocate(iSlabAlloc[ix]);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   560
		if ( !addr )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   561
			{ // Slab allocation has failed, try to allocate from DL
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   562
			addr = DlMalloc(aSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   563
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   564
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   565
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   566
			aSubAllocator=1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   567
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   568
		}else if((aSize >> iPageThreshold)==0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   569
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   570
			addr = DlMalloc(aSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   571
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   572
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   573
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   574
			addr = PagedAllocate(aSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   575
			if ( !addr )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   576
				{ // Page allocation has failed, try to allocate from DL
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   577
				addr = DlMalloc(aSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   578
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   579
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   580
			else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   581
	      		aSubAllocator=2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   582
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   583
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   584
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   585
	if ( addr )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   586
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   587
//		iCellCount++;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   588
		__SET_DEBUG_DATA(addr, iNestingLevel, ++iAllocCount);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   589
		addr = __GET_USER_DATA_BFR(addr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   590
		__INCREMENT_COUNTERS(addr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   591
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   592
	Unlock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   593
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   594
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   595
	if (iFlags & ETraceAllocs)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   596
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   597
		if ( addr )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   598
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   599
		    TUint32 traceData[3];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   600
		    traceData[0] = AllocLen(addr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   601
		    traceData[1] = aSize - __DEBUG_HDR_SIZE;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   602
			traceData[2] = aSubAllocator;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   603
		    BTraceContextN(BTrace::EHeap, BTrace::EHeapAlloc, (TUint32)this, (TUint32)addr, traceData, sizeof(traceData));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   604
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   605
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   606
			BTraceContext8(BTrace::EHeap, BTrace::EHeapAllocFail, (TUint32)this, (TUint32)(aSize - __DEBUG_HDR_SIZE));			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   607
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   608
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   609
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   610
	return addr;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   611
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   612
#endif // __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   613
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   614
#ifndef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   615
TInt RHybridHeap::Compress()
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   616
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   617
	if ( IS_FIXED_HEAP )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   618
		return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   619
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   620
	Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   621
	TInt Reduced = SysTrim(GM, 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   622
	if (iSparePage)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   623
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   624
		Unmap(iSparePage, iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   625
		iSparePage = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   626
		Reduced += iPageSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   627
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   628
	Unlock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   629
	return Reduced;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   630
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   631
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   632
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   633
void RHybridHeap::Free(TAny* aPtr)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   634
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   635
	__CHECK_THREAD_STATE;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   636
	if ( !aPtr )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   637
		return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   638
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   639
	TInt aSubAllocator=0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   640
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   641
	Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   642
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   643
	aPtr = __GET_DEBUG_DATA_BFR(aPtr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   644
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   645
#ifndef __KERNEL_MODE__				
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   646
	if (PtrDiff(aPtr, this) >= 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   647
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   648
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   649
		__DL_BFR_CHECK(GM, aPtr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   650
		__DECREMENT_COUNTERS(__GET_USER_DATA_BFR(aPtr));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   651
		__ZAP_CELL(aPtr);		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   652
		DlFree( aPtr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   653
#ifndef __KERNEL_MODE__			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   654
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   655
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   656
	else if ( LowBits(aPtr, iPageSize) == 0 )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   657
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   658
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   659
		aSubAllocator = 2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   660
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   661
		__PAGE_BFR_CHECK(aPtr);	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   662
		__DECREMENT_COUNTERS(__GET_USER_DATA_BFR(aPtr));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   663
		PagedFree(aPtr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   664
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   665
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   666
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   667
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   668
		aSubAllocator = 1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   669
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   670
		TUint32 bm[4];   		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   671
		__SLAB_BFR_CHECK(slab::SlabFor(aPtr),aPtr,bm);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   672
		__DECREMENT_COUNTERS(__GET_USER_DATA_BFR(aPtr));  
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   673
		__ZAP_CELL(aPtr);		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   674
		SlabFree(aPtr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   675
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   676
#endif  // __KERNEL_MODE__	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   677
//	iCellCount--;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   678
	Unlock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   679
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   680
	if (iFlags & ETraceAllocs)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   681
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   682
		TUint32 traceData;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   683
		traceData = aSubAllocator;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   684
		BTraceContextN(BTrace::EHeap, BTrace::EHeapFree, (TUint32)this, (TUint32)__GET_USER_DATA_BFR(aPtr), &traceData, sizeof(traceData));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   685
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   686
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   687
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   688
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   689
#ifndef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   690
void RHybridHeap::Reset()
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   691
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   692
Frees all allocated cells on this heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   693
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   694
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   695
	Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   696
	if ( !IS_FIXED_HEAP )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   697
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   698
		if ( GM->iSeg.iSize > (iMinLength - sizeof(*this)) )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   699
			Unmap(GM->iSeg.iBase + (iMinLength - sizeof(*this)), (GM->iSeg.iSize - (iMinLength - sizeof(*this))));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   700
		ResetBitmap();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   701
		if ( !iDLOnly )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   702
			Init(iSlabConfigBits, iPageThreshold);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   703
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   704
			Init(0,0);		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   705
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   706
	else Init(0,0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   707
	Unlock();	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   708
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   709
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   710
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   711
TAny* RHybridHeap::ReAllocImpl(TAny* aPtr, TInt aSize, TInt aMode)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   712
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   713
	// First handle special case of calling reallocate with NULL aPtr
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   714
	if (!aPtr)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   715
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   716
		if (( aMode & ENeverMove ) == 0 )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   717
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   718
			aPtr = Alloc(aSize - __DEBUG_HDR_SIZE);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   719
			aPtr = __GET_DEBUG_DATA_BFR(aPtr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   720
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   721
		return aPtr;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   722
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   723
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   724
	TInt oldsize = AllocLen(__GET_USER_DATA_BFR(aPtr)) + __DEBUG_HDR_SIZE;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   725
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   726
	// Insist on geometric growth when reallocating memory, this reduces copying and fragmentation
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   727
	// generated during arithmetic growth of buffer/array/vector memory
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   728
	// Experiments have shown that 25% is a good threshold for this policy
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   729
	if (aSize <= oldsize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   730
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   731
		if (aSize >= oldsize - (oldsize>>2))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   732
			return aPtr;		// don't change if >75% original size
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   733
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   734
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   735
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   736
		__SIMULATE_ALLOC_FAIL(return NULL;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   737
		if (aSize < oldsize + (oldsize>>2))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   738
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   739
			aSize = _ALIGN_UP(oldsize + (oldsize>>2), 4);	// grow to at least 125% original size
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   740
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   741
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   742
	__DEBUG_SAVE(aPtr);		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   743
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   744
	TAny* newp;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   745
#ifdef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   746
	Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   747
	__DL_BFR_CHECK(GM, aPtr);				
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   748
	newp = DlRealloc(aPtr, aSize, aMode);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   749
	Unlock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   750
	if ( newp )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   751
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   752
	    if ( aSize > oldsize )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   753
			memclr(((TUint8*)newp) + oldsize, (aSize-oldsize)); // Buffer has grown in place, clear extra
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   754
		__DEBUG_RESTORE(newp);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   755
		__UPDATE_ALLOC_COUNT(aPtr, newp, ++iAllocCount);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   756
		__UPDATE_TOTAL_ALLOC(newp, oldsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   757
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   758
#else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   759
	// Decide how to reallocate based on (a) the current cell location, (b) the mode requested and (c) the new size
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   760
	if ( PtrDiff(aPtr, this) >= 0 )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   761
		{	// current cell in Doug Lea iArena
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   762
		if ( (aMode & ENeverMove) 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   763
			 ||
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   764
			 (!(aMode & EAllowMoveOnShrink) && (aSize < oldsize))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   765
			 ||
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   766
			 ((aSize >= iSlabThreshold) && ((aSize >> iPageThreshold) == 0)) )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   767
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   768
			Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   769
			__DL_BFR_CHECK(GM, aPtr);			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   770
			newp = DlRealloc(aPtr, aSize, aMode);			// old and new in DL allocator
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   771
			Unlock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   772
			__DEBUG_RESTORE(newp);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   773
			__UPDATE_ALLOC_COUNT(aPtr,newp, ++iAllocCount);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   774
			__UPDATE_TOTAL_ALLOC(newp, oldsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   775
			return newp;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   776
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   777
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   778
	else if (LowBits(aPtr, iPageSize) == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   779
		{	// current cell in paged iArena
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   780
		if ( (aMode & ENeverMove)     
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   781
			 ||
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   782
			 (!(aMode & EAllowMoveOnShrink) && (aSize < oldsize)) 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   783
			 ||
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   784
			 ((aSize >> iPageThreshold) != 0) )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   785
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   786
			Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   787
			__PAGE_BFR_CHECK(aPtr);			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   788
			newp = PagedReallocate(aPtr, aSize, aMode);		// old and new in paged allocator
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   789
			Unlock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   790
			__DEBUG_RESTORE(newp);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   791
			__UPDATE_ALLOC_COUNT(aPtr,newp, ++iAllocCount);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   792
			__UPDATE_TOTAL_ALLOC(newp, oldsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   793
			return newp;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   794
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   795
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   796
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   797
		{	// current cell in slab iArena
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   798
		TUint32 bm[4];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   799
		Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   800
		__SLAB_BFR_CHECK(slab::SlabFor(aPtr), aPtr, bm);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   801
		Unlock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   802
		if ( aSize <= oldsize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   803
			return aPtr;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   804
		if (aMode & ENeverMove)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   805
			return NULL;		// cannot grow in slab iArena
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   806
		// just use alloc/copy/free...
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   807
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   808
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   809
	// fallback to allocate and copy
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   810
	// shouldn't get here if we cannot move the cell
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   811
	//  	__ASSERT(mode == emobile || (mode==efixshrink && size>oldsize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   812
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   813
	newp = Alloc(aSize - __DEBUG_HDR_SIZE);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   814
	newp = __GET_DEBUG_DATA_BFR(newp);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   815
	if (newp)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   816
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   817
		memcpy(newp, aPtr, oldsize<aSize ? oldsize : aSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   818
		__DEBUG_RESTORE(newp);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   819
		Free(__GET_USER_DATA_BFR(aPtr));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   820
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   821
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   822
#endif	// __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   823
	return newp;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   824
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   825
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   826
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   827
TAny* RHybridHeap::ReAlloc(TAny* aPtr, TInt aSize, TInt aMode )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   828
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   829
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   830
	aPtr = __GET_DEBUG_DATA_BFR(aPtr);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   831
	__ALLOC_DEBUG_HEADER(aSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   832
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   833
	TAny* retval = ReAllocImpl(aPtr, aSize, aMode);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   834
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   835
	retval = __GET_USER_DATA_BFR(retval);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   836
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   837
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   838
	if (iFlags & ETraceAllocs)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   839
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   840
		if ( retval )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   841
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   842
			TUint32 traceData[3];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   843
			traceData[0] = AllocLen(retval);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   844
			traceData[1] = aSize - __DEBUG_HDR_SIZE;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   845
			traceData[2] = (TUint32)aPtr;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   846
			BTraceContextN(BTrace::EHeap, BTrace::EHeapReAlloc,(TUint32)this, (TUint32)retval, traceData, sizeof(traceData));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   847
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   848
  		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   849
  		    BTraceContext12(BTrace::EHeap, BTrace::EHeapReAllocFail, (TUint32)this, (TUint32)aPtr, (TUint32)(aSize - __DEBUG_HDR_SIZE));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   850
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   851
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   852
	return retval;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   853
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   854
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   855
#ifndef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   856
TInt RHybridHeap::Available(TInt& aBiggestBlock) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   857
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   858
Gets the total free space currently available on the heap and the space
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   859
available in the largest free block.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   860
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   861
Note that this function exists mainly for compatibility reasons.  In a modern
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   862
heap implementation such as that present in Symbian it is not appropriate to
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   863
concern oneself with details such as the amount of free memory available on a
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   864
heap and its largeset free block, because the way that a modern heap implmentation
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   865
works is not simple.  The amount of available virtual memory != physical memory
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   866
and there are multiple allocation strategies used internally, which makes all
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   867
memory usage figures "fuzzy" at best.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   868
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   869
In short, if you want to see if there is enough memory available to allocate a
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   870
block of memory, call Alloc() and if it succeeds then there is enough memory!
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   871
Messing around with functions like this is somewhat pointless with modern heap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   872
allocators.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   873
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   874
@param aBiggestBlock On return, contains the space available in the largest
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   875
                     free block on the heap.  Due to the internals of modern
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   876
                     heap implementations, you can probably still allocate a
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   877
                     block larger than this!
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   878
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   879
@return The total free space currently available on the heap.  Again, you can
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   880
        probably still allocate more than this!
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   881
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   882
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   883
	struct HeapInfo info;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   884
	Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   885
	TInt Biggest  = GetInfo(&info);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   886
	aBiggestBlock = __GET_AVAIL_BLOCK_SIZE(Biggest);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   887
	Unlock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   888
	return __GET_AVAIL_BLOCK_SIZE(info.iFreeBytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   889
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   890
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   891
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   892
TInt RHybridHeap::AllocSize(TInt& aTotalAllocSize) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   893
   /**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   894
   Gets the number of cells allocated on this heap, and the total space 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   895
   allocated to them.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   896
   
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   897
   @param aTotalAllocSize On return, contains the total space allocated
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   898
   to the cells.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   899
   
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   900
   @return The number of cells allocated on this heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   901
*/   
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   902
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   903
	struct HeapInfo info;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   904
	Lock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   905
	GetInfo(&info);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   906
	aTotalAllocSize = info.iAllocBytes - __REMOVE_DBG_HDR(info.iAllocN);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   907
	Unlock();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   908
	return info.iAllocN;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   909
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   910
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   911
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   912
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   913
TInt RHybridHeap::Extension_(TUint /* aExtensionId */, TAny*& /* a0 */, TAny* /* a1 */)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   914
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   915
	return KErrNotSupported;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   916
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   917
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   918
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   919
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   920
///////////////////////////////////////////////////////////////////////////////
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   921
// imported from dla.cpp
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   922
///////////////////////////////////////////////////////////////////////////////
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   923
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   924
//#include <unistd.h>
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   925
//#define DEBUG_REALLOC
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   926
#ifdef DEBUG_REALLOC
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   927
#include <e32debug.h>
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   928
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   929
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   930
inline void RHybridHeap::InitBins(mstate m)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   931
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   932
	/* Establish circular links for iSmallBins */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   933
	bindex_t i;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   934
	for (i = 0; i < NSMALLBINS; ++i) {
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   935
		sbinptr bin = SMALLBIN_AT(m,i);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   936
		bin->iFd = bin->iBk = bin;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   937
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   938
	}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   939
/* ---------------------------- malloc support --------------------------- */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   940
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   941
/* allocate a large request from the best fitting chunk in a treebin */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   942
void* RHybridHeap::TmallocLarge(mstate m, size_t nb) {
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   943
	tchunkptr v = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   944
	size_t rsize = -nb; /* Unsigned negation */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   945
	tchunkptr t;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   946
	bindex_t idx;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   947
	ComputeTreeIndex(nb, idx);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   948
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   949
	if ((t = *TREEBIN_AT(m, idx)) != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   950
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   951
		/* Traverse tree for this bin looking for node with size == nb */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   952
		size_t sizebits = nb << LEFTSHIFT_FOR_TREE_INDEX(idx);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   953
		tchunkptr rst = 0;  /* The deepest untaken right subtree */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   954
		for (;;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   955
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   956
			tchunkptr rt;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   957
			size_t trem = CHUNKSIZE(t) - nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   958
			if (trem < rsize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   959
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   960
				v = t;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   961
				if ((rsize = trem) == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   962
					break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   963
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   964
			rt = t->iChild[1];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   965
			t = t->iChild[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   966
			if (rt != 0 && rt != t)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   967
				rst = rt;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   968
			if (t == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   969
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   970
				t = rst; /* set t to least subtree holding sizes > nb */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   971
				break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   972
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   973
			sizebits <<= 1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   974
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   975
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   976
	if (t == 0 && v == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   977
		{ /* set t to root of next non-empty treebin */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   978
		binmap_t leftbits = LEFT_BITS(IDX2BIT(idx)) & m->iTreeMap;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   979
		if (leftbits != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   980
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   981
			bindex_t i;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   982
			binmap_t leastbit = LEAST_BIT(leftbits);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   983
			ComputeBit2idx(leastbit, i);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   984
			t = *TREEBIN_AT(m, i);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   985
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   986
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   987
	while (t != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   988
		{ /* Find smallest of tree or subtree */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   989
		size_t trem = CHUNKSIZE(t) - nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   990
		if (trem < rsize) {
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   991
			rsize = trem;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   992
			v = t;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   993
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   994
		t = LEFTMOST_CHILD(t);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   995
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   996
	/*  If iDv is a better fit, return 0 so malloc will use it */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   997
	if (v != 0 && rsize < (size_t)(m->iDvSize - nb))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   998
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
   999
		if (RTCHECK(OK_ADDRESS(m, v)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1000
			{ /* split */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1001
			mchunkptr r = CHUNK_PLUS_OFFSET(v, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1002
			HEAP_ASSERT(CHUNKSIZE(v) == rsize + nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1003
			if (RTCHECK(OK_NEXT(v, r)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1004
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1005
				UnlinkLargeChunk(m, v);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1006
				if (rsize < MIN_CHUNK_SIZE)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1007
					SET_INUSE_AND_PINUSE(m, v, (rsize + nb));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1008
				else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1009
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1010
					SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(m, v, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1011
					SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(r, rsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1012
					InsertChunk(m, r, rsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1013
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1014
				return CHUNK2MEM(v);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1015
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1016
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1017
		//    CORRUPTION_ERROR_ACTION(m);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1018
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1019
	return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1020
	}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1021
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1022
/* allocate a small request from the best fitting chunk in a treebin */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1023
void* RHybridHeap::TmallocSmall(mstate m, size_t nb)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1024
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1025
	tchunkptr t, v;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1026
	size_t rsize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1027
	bindex_t i;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1028
	binmap_t leastbit = LEAST_BIT(m->iTreeMap);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1029
	ComputeBit2idx(leastbit, i);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1030
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1031
	v = t = *TREEBIN_AT(m, i);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1032
	rsize = CHUNKSIZE(t) - nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1033
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1034
	while ((t = LEFTMOST_CHILD(t)) != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1035
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1036
		size_t trem = CHUNKSIZE(t) - nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1037
		if (trem < rsize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1038
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1039
			rsize = trem;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1040
			v = t;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1041
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1042
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1043
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1044
	if (RTCHECK(OK_ADDRESS(m, v)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1045
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1046
		mchunkptr r = CHUNK_PLUS_OFFSET(v, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1047
		HEAP_ASSERT(CHUNKSIZE(v) == rsize + nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1048
		if (RTCHECK(OK_NEXT(v, r)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1049
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1050
			UnlinkLargeChunk(m, v);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1051
			if (rsize < MIN_CHUNK_SIZE)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1052
				SET_INUSE_AND_PINUSE(m, v, (rsize + nb));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1053
			else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1054
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1055
				SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(m, v, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1056
				SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(r, rsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1057
				ReplaceDv(m, r, rsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1058
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1059
			return CHUNK2MEM(v);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1060
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1061
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1062
	//  CORRUPTION_ERROR_ACTION(m);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1063
	//  return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1064
	}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1065
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1066
inline void RHybridHeap::InitTop(mstate m, mchunkptr p, size_t psize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1067
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1068
	/* Ensure alignment */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1069
	size_t offset = ALIGN_OFFSET(CHUNK2MEM(p));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1070
	p = (mchunkptr)((TUint8*)p + offset);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1071
	psize -= offset;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1072
	m->iTop = p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1073
	m->iTopSize = psize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1074
	p->iHead = psize | PINUSE_BIT;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1075
	/* set size of fake trailing chunk holding overhead space only once */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1076
	mchunkptr chunkPlusOff = CHUNK_PLUS_OFFSET(p, psize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1077
	chunkPlusOff->iHead = TOP_FOOT_SIZE;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1078
	m->iTrimCheck = KHeapShrinkHysRatio*(iGrowBy>>8);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1079
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1080
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1081
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1082
/* Unlink the first chunk from a smallbin */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1083
inline void RHybridHeap::UnlinkFirstSmallChunk(mstate M,mchunkptr B,mchunkptr P,bindex_t& I)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1084
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1085
	mchunkptr F = P->iFd;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1086
	HEAP_ASSERT(P != B);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1087
	HEAP_ASSERT(P != F);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1088
	HEAP_ASSERT(CHUNKSIZE(P) == SMALL_INDEX2SIZE(I));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1089
	if (B == F)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1090
		CLEAR_SMALLMAP(M, I);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1091
	else if (RTCHECK(OK_ADDRESS(M, F)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1092
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1093
		B->iFd = F;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1094
		F->iBk = B;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1095
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1096
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1097
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1098
		CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1099
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1100
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1101
/* Link a free chunk into a smallbin  */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1102
inline void RHybridHeap::InsertSmallChunk(mstate M,mchunkptr P, size_t S)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1103
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1104
	bindex_t I  = SMALL_INDEX(S);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1105
	mchunkptr B = SMALLBIN_AT(M, I);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1106
	mchunkptr F = B;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1107
	HEAP_ASSERT(S >= MIN_CHUNK_SIZE);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1108
	if (!SMALLMAP_IS_MARKED(M, I))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1109
		MARK_SMALLMAP(M, I);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1110
	else if (RTCHECK(OK_ADDRESS(M, B->iFd)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1111
		F = B->iFd;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1112
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1113
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1114
		CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1115
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1116
	B->iFd = P;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1117
	F->iBk = P;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1118
	P->iFd = F;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1119
	P->iBk = B;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1120
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1121
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1122
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1123
inline void RHybridHeap::InsertChunk(mstate M,mchunkptr P,size_t S)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1124
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1125
	if (IS_SMALL(S))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1126
		InsertSmallChunk(M, P, S);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1127
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1128
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1129
		tchunkptr TP = (tchunkptr)(P); InsertLargeChunk(M, TP, S);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1130
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1131
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1132
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1133
inline void RHybridHeap::UnlinkLargeChunk(mstate M,tchunkptr X)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1134
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1135
	tchunkptr XP = X->iParent;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1136
	tchunkptr R;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1137
	if (X->iBk != X)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1138
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1139
		tchunkptr F = X->iFd;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1140
		R = X->iBk;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1141
		if (RTCHECK(OK_ADDRESS(M, F)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1142
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1143
			F->iBk = R;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1144
			R->iFd = F;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1145
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1146
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1147
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1148
			CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1149
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1150
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1151
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1152
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1153
		tchunkptr* RP;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1154
		if (((R = *(RP = &(X->iChild[1]))) != 0) ||
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1155
			  ((R = *(RP = &(X->iChild[0]))) != 0))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1156
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1157
			tchunkptr* CP;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1158
			while ((*(CP = &(R->iChild[1])) != 0) ||
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1159
				   (*(CP = &(R->iChild[0])) != 0))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1160
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1161
				R = *(RP = CP);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1162
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1163
			if (RTCHECK(OK_ADDRESS(M, RP)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1164
				*RP = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1165
			else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1166
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1167
				CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1168
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1169
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1170
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1171
	if (XP != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1172
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1173
		tbinptr* H = TREEBIN_AT(M, X->iIndex);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1174
		if (X == *H)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1175
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1176
			if ((*H = R) == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1177
				CLEAR_TREEMAP(M, X->iIndex);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1178
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1179
		else if (RTCHECK(OK_ADDRESS(M, XP)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1180
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1181
			if (XP->iChild[0] == X)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1182
				XP->iChild[0] = R;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1183
			else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1184
				XP->iChild[1] = R;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1185
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1186
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1187
			CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1188
		if (R != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1189
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1190
			if (RTCHECK(OK_ADDRESS(M, R)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1191
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1192
				tchunkptr C0, C1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1193
				R->iParent = XP;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1194
				if ((C0 = X->iChild[0]) != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1195
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1196
					if (RTCHECK(OK_ADDRESS(M, C0)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1197
						{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1198
						R->iChild[0] = C0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1199
						C0->iParent = R;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1200
						}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1201
					else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1202
						CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1203
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1204
				if ((C1 = X->iChild[1]) != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1205
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1206
					if (RTCHECK(OK_ADDRESS(M, C1)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1207
						{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1208
						R->iChild[1] = C1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1209
						C1->iParent = R;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1210
						}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1211
					else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1212
						CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1213
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1214
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1215
			else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1216
				CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1217
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1218
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1219
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1220
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1221
/* Unlink a chunk from a smallbin  */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1222
inline void RHybridHeap::UnlinkSmallChunk(mstate M, mchunkptr P,size_t S)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1223
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1224
	mchunkptr F = P->iFd;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1225
	mchunkptr B = P->iBk;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1226
	bindex_t I = SMALL_INDEX(S);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1227
	HEAP_ASSERT(P != B);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1228
	HEAP_ASSERT(P != F);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1229
	HEAP_ASSERT(CHUNKSIZE(P) == SMALL_INDEX2SIZE(I));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1230
	if (F == B)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1231
		CLEAR_SMALLMAP(M, I);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1232
	else if (RTCHECK((F == SMALLBIN_AT(M,I) || OK_ADDRESS(M, F)) &&
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1233
					 (B == SMALLBIN_AT(M,I) || OK_ADDRESS(M, B))))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1234
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1235
		F->iBk = B;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1236
		B->iFd = F;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1237
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1238
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1239
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1240
		CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1241
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1242
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1243
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1244
inline void RHybridHeap::UnlinkChunk(mstate M, mchunkptr P, size_t S)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1245
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1246
	if (IS_SMALL(S))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1247
		UnlinkSmallChunk(M, P, S);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1248
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1249
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1250
		tchunkptr TP = (tchunkptr)(P); UnlinkLargeChunk(M, TP);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1251
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1252
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1253
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1254
// For DL debug functions
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1255
void RHybridHeap::DoComputeTreeIndex(size_t S, bindex_t& I)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1256
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1257
	ComputeTreeIndex(S, I);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1258
}	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1259
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1260
inline void RHybridHeap::ComputeTreeIndex(size_t S, bindex_t& I)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1261
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1262
	size_t X = S >> TREEBIN_SHIFT;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1263
	if (X == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1264
		I = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1265
	else if (X > 0xFFFF)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1266
		I = NTREEBINS-1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1267
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1268
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1269
		unsigned int Y = (unsigned int)X;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1270
		unsigned int N = ((Y - 0x100) >> 16) & 8;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1271
		unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1272
		N += K;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1273
		N += K = (((Y <<= K) - 0x4000) >> 16) & 2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1274
		K = 14 - N + ((Y <<= K) >> 15);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1275
		I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1276
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1277
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1278
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1279
/* ------------------------- Operations on trees ------------------------- */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1280
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1281
/* Insert chunk into tree */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1282
inline void RHybridHeap::InsertLargeChunk(mstate M,tchunkptr X,size_t S)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1283
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1284
	tbinptr* H;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1285
	bindex_t I;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1286
	ComputeTreeIndex(S, I);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1287
	H = TREEBIN_AT(M, I);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1288
	X->iIndex = I;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1289
	X->iChild[0] = X->iChild[1] = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1290
	if (!TREEMAP_IS_MARKED(M, I))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1291
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1292
		MARK_TREEMAP(M, I);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1293
		*H = X;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1294
		X->iParent = (tchunkptr)H;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1295
		X->iFd = X->iBk = X;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1296
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1297
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1298
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1299
		tchunkptr T = *H;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1300
		size_t K = S << LEFTSHIFT_FOR_TREE_INDEX(I);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1301
		for (;;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1302
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1303
			if (CHUNKSIZE(T) != S) {
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1304
				tchunkptr* C = &(T->iChild[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1305
				K <<= 1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1306
				if (*C != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1307
					T = *C;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1308
				else if (RTCHECK(OK_ADDRESS(M, C)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1309
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1310
					*C = X;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1311
					X->iParent = T;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1312
					X->iFd = X->iBk = X;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1313
					break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1314
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1315
				else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1316
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1317
					CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1318
					break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1319
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1320
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1321
			else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1322
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1323
				tchunkptr F = T->iFd;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1324
				if (RTCHECK(OK_ADDRESS(M, T) && OK_ADDRESS(M, F)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1325
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1326
					T->iFd = F->iBk = X;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1327
					X->iFd = F;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1328
					X->iBk = T;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1329
					X->iParent = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1330
					break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1331
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1332
				else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1333
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1334
					CORRUPTION_ERROR_ACTION(M);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1335
					break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1336
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1337
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1338
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1339
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1340
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1341
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1342
/*
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1343
Unlink steps:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1344
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1345
1. If x is a chained node, unlink it from its same-sized iFd/iBk links
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1346
and choose its iBk node as its replacement.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1347
2. If x was the last node of its size, but not a leaf node, it must
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1348
be replaced with a leaf node (not merely one with an open left or
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1349
right), to make sure that lefts and rights of descendents
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1350
correspond properly to bit masks.  We use the rightmost descendent
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1351
of x.  We could use any other leaf, but this is easy to locate and
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1352
tends to counteract removal of leftmosts elsewhere, and so keeps
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1353
paths shorter than minimally guaranteed.  This doesn't loop much
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1354
because on average a node in a tree is near the bottom.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1355
3. If x is the base of a chain (i.e., has iParent links) relink
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1356
x's iParent and children to x's replacement (or null if none).
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1357
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1358
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1359
/* Replace iDv node, binning the old one */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1360
/* Used only when iDvSize known to be small */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1361
inline void RHybridHeap::ReplaceDv(mstate M, mchunkptr P, size_t S)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1362
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1363
	size_t DVS = M->iDvSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1364
	if (DVS != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1365
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1366
		mchunkptr DV = M->iDv;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1367
		HEAP_ASSERT(IS_SMALL(DVS));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1368
		InsertSmallChunk(M, DV, DVS);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1369
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1370
	M->iDvSize = S;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1371
	M->iDv = P;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1372
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1373
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1374
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1375
inline void RHybridHeap::ComputeBit2idx(binmap_t X,bindex_t& I)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1376
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1377
	unsigned int Y = X - 1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1378
	unsigned int K = Y >> (16-4) & 16;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1379
	unsigned int N = K;        Y >>= K;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1380
	N += K = Y >> (8-3) &  8;  Y >>= K;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1381
	N += K = Y >> (4-2) &  4;  Y >>= K;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1382
	N += K = Y >> (2-1) &  2;  Y >>= K;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1383
	N += K = Y >> (1-0) &  1;  Y >>= K;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1384
	I = (bindex_t)(N + Y);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1385
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1386
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1387
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1388
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1389
int RHybridHeap::SysTrim(mstate m, size_t pad)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1390
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1391
	size_t extra = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1392
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1393
	if ( IS_INITIALIZED(m) )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1394
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1395
		pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1396
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1397
		if (m->iTopSize > pad)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1398
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1399
			extra = Floor(m->iTopSize - pad, iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1400
			if ( (m->iSeg.iSize - extra) < (iMinLength - sizeof(*this)) )			  
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1401
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1402
				if ( m->iSeg.iSize > (iMinLength - sizeof(*this)) )				  
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1403
					extra = Floor(m->iSeg.iSize - (iMinLength - sizeof(*this)), iPageSize); /* do not shrink heap below min length */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1404
				else extra = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1405
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1406
			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1407
			if ( extra )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1408
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1409
				Unmap(m->iSeg.iBase + m->iSeg.iSize - extra, extra);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1410
				
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1411
				m->iSeg.iSize -= extra;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1412
				InitTop(m, m->iTop, m->iTopSize - extra);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1413
				CHECK_TOP_CHUNK(m, m->iTop);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1414
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1415
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1416
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1417
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1418
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1419
	return extra;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1420
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1421
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1422
/* Get memory from system using MORECORE */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1423
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1424
void* RHybridHeap::SysAlloc(mstate m, size_t nb)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1425
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1426
	HEAP_ASSERT(m->iTop);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1427
	/* Subtract out existing available iTop space from MORECORE request. */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1428
//	size_t asize = _ALIGN_UP(nb - m->iTopSize + TOP_FOOT_SIZE + SIZE_T_ONE, iGrowBy);  
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1429
  	TInt asize = _ALIGN_UP(nb - m->iTopSize + SYS_ALLOC_PADDING, iGrowBy);  // From DLA version 2.8.4
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1430
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1431
	char* br = (char*)Map(m->iSeg.iBase+m->iSeg.iSize, asize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1432
	if (!br)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1433
		return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1434
	HEAP_ASSERT(br == (char*)m->iSeg.iBase+m->iSeg.iSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1435
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1436
	/* Merge with an existing segment */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1437
	m->iSeg.iSize += asize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1438
	InitTop(m, m->iTop, m->iTopSize + asize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1439
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1440
	if (nb < m->iTopSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1441
		{ /* Allocate from new or extended iTop space */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1442
		size_t rsize = m->iTopSize -= nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1443
		mchunkptr p = m->iTop;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1444
		mchunkptr r = m->iTop = CHUNK_PLUS_OFFSET(p, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1445
		r->iHead = rsize | PINUSE_BIT;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1446
		SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(m, p, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1447
		CHECK_TOP_CHUNK(m, m->iTop);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1448
		CHECK_MALLOCED_CHUNK(m, CHUNK2MEM(p), nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1449
		return CHUNK2MEM(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1450
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1451
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1452
	return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1453
}	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1454
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1455
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1456
void RHybridHeap::InitDlMalloc(size_t capacity, int /*locked*/)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1457
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1458
	memset(GM,0,sizeof(malloc_state));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1459
	// The maximum amount that can be allocated can be calculated as:-
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1460
	// 2^sizeof(size_t) - sizeof(malloc_state) - TOP_FOOT_SIZE - page Size(all accordingly padded)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1461
	// If the capacity exceeds this, no allocation will be done.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1462
	GM->iSeg.iBase = iBase;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1463
	GM->iSeg.iSize = capacity;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1464
	InitBins(GM);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1465
	InitTop(GM, (mchunkptr)iBase, capacity - TOP_FOOT_SIZE);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1466
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1467
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1468
void* RHybridHeap::DlMalloc(size_t bytes) 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1469
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1470
	/*
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1471
	Basic algorithm:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1472
	If a small request (< 256 bytes minus per-chunk overhead):
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1473
	1. If one exists, use a remainderless chunk in associated smallbin.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1474
	(Remainderless means that there are too few excess bytes to
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1475
	represent as a chunk.)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1476
	2. If it is big enough, use the iDv chunk, which is normally the
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1477
	chunk adjacent to the one used for the most recent small request.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1478
	3. If one exists, split the smallest available chunk in a bin,
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1479
	saving remainder in iDv.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1480
	4. If it is big enough, use the iTop chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1481
	5. If available, get memory from system and use it
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1482
	Otherwise, for a large request:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1483
	1. Find the smallest available binned chunk that fits, and use it
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1484
	if it is better fitting than iDv chunk, splitting if necessary.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1485
	2. If better fitting than any binned chunk, use the iDv chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1486
	3. If it is big enough, use the iTop chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1487
	4. If request size >= mmap threshold, try to directly mmap this chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1488
	5. If available, get memory from system and use it
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1489
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1490
	void* mem;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1491
	size_t nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1492
	if (bytes <= MAX_SMALL_REQUEST)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1493
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1494
		bindex_t idx;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1495
		binmap_t smallbits;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1496
		nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : PAD_REQUEST(bytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1497
		idx = SMALL_INDEX(nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1498
		smallbits = GM->iSmallMap >> idx;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1499
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1500
		if ((smallbits & 0x3U) != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1501
			{ /* Remainderless fit to a smallbin. */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1502
			mchunkptr b, p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1503
			idx += ~smallbits & 1;			 /* Uses next bin if idx empty */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1504
			b = SMALLBIN_AT(GM, idx);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1505
			p = b->iFd;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1506
			HEAP_ASSERT(CHUNKSIZE(p) == SMALL_INDEX2SIZE(idx));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1507
			UnlinkFirstSmallChunk(GM, b, p, idx);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1508
			SET_INUSE_AND_PINUSE(GM, p, SMALL_INDEX2SIZE(idx));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1509
			mem = CHUNK2MEM(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1510
			CHECK_MALLOCED_CHUNK(GM, mem, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1511
			return mem;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1512
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1513
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1514
		else if (nb > GM->iDvSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1515
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1516
			if (smallbits != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1517
				{ /* Use chunk in next nonempty smallbin */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1518
				mchunkptr b, p, r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1519
				size_t rsize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1520
				bindex_t i;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1521
				binmap_t leftbits = (smallbits << idx) & LEFT_BITS(IDX2BIT(idx));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1522
				binmap_t leastbit = LEAST_BIT(leftbits);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1523
				ComputeBit2idx(leastbit, i);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1524
				b = SMALLBIN_AT(GM, i);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1525
				p = b->iFd;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1526
				HEAP_ASSERT(CHUNKSIZE(p) == SMALL_INDEX2SIZE(i));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1527
				UnlinkFirstSmallChunk(GM, b, p, i);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1528
				rsize = SMALL_INDEX2SIZE(i) - nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1529
				/* Fit here cannot be remainderless if 4byte sizes */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1530
				if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1531
					SET_INUSE_AND_PINUSE(GM, p, SMALL_INDEX2SIZE(i));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1532
				else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1533
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1534
					SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(GM, p, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1535
					r = CHUNK_PLUS_OFFSET(p, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1536
					SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(r, rsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1537
					ReplaceDv(GM, r, rsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1538
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1539
				mem = CHUNK2MEM(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1540
				CHECK_MALLOCED_CHUNK(GM, mem, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1541
				return mem;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1542
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1543
			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1544
			else if (GM->iTreeMap != 0 && (mem = TmallocSmall(GM, nb)) != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1545
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1546
				CHECK_MALLOCED_CHUNK(GM, mem, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1547
				return mem;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1548
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1549
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1550
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1551
	else if (bytes >= MAX_REQUEST)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1552
		nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1553
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1554
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1555
		nb = PAD_REQUEST(bytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1556
		if (GM->iTreeMap != 0 && (mem = TmallocLarge(GM, nb)) != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1557
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1558
			CHECK_MALLOCED_CHUNK(GM, mem, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1559
			return mem;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1560
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1561
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1562
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1563
	if (nb <= GM->iDvSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1564
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1565
		size_t rsize = GM->iDvSize - nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1566
		mchunkptr p = GM->iDv;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1567
		if (rsize >= MIN_CHUNK_SIZE)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1568
			{ /* split iDv */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1569
			mchunkptr r = GM->iDv = CHUNK_PLUS_OFFSET(p, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1570
			GM->iDvSize = rsize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1571
			SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(r, rsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1572
			SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(GM, p, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1573
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1574
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1575
			{ /* exhaust iDv */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1576
			size_t dvs = GM->iDvSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1577
			GM->iDvSize = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1578
			GM->iDv = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1579
			SET_INUSE_AND_PINUSE(GM, p, dvs);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1580
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1581
		mem = CHUNK2MEM(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1582
		CHECK_MALLOCED_CHUNK(GM, mem, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1583
		return mem;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1584
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1585
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1586
	else if (nb < GM->iTopSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1587
		{ /* Split iTop */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1588
		size_t rsize = GM->iTopSize -= nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1589
		mchunkptr p = GM->iTop;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1590
		mchunkptr r = GM->iTop = CHUNK_PLUS_OFFSET(p, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1591
		r->iHead = rsize | PINUSE_BIT;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1592
		SET_SIZE_AND_PINUSE_OF_INUSE_CHUNK(GM, p, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1593
		mem = CHUNK2MEM(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1594
		CHECK_TOP_CHUNK(GM, GM->iTop);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1595
		CHECK_MALLOCED_CHUNK(GM, mem, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1596
		return mem;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1597
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1598
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1599
	return SysAlloc(GM, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1600
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1601
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1602
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1603
void RHybridHeap::DlFree(void* mem)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1604
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1605
	/*
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1606
	Consolidate freed chunks with preceeding or succeeding bordering
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1607
	free chunks, if they exist, and then place in a bin.	Intermixed
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1608
	with special cases for iTop, iDv, mmapped chunks, and usage errors.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1609
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1610
	mchunkptr p	= MEM2CHUNK(mem);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1611
	CHECK_INUSE_CHUNK(GM, p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1612
	if (RTCHECK(OK_ADDRESS(GM, p) && OK_CINUSE(p)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1613
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1614
		size_t psize = CHUNKSIZE(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1615
		mchunkptr next = CHUNK_PLUS_OFFSET(p, psize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1616
		if (!PINUSE(p))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1617
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1618
			size_t prevsize = p->iPrevFoot;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1619
			mchunkptr prev = CHUNK_MINUS_OFFSET(p, prevsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1620
			psize += prevsize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1621
			p = prev;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1622
			if (RTCHECK(OK_ADDRESS(GM, prev)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1623
				{ /* consolidate backward */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1624
				if (p != GM->iDv)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1625
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1626
					UnlinkChunk(GM, p, prevsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1627
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1628
				else if ((next->iHead & INUSE_BITS) == INUSE_BITS)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1629
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1630
					GM->iDvSize = psize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1631
					SET_FREE_WITH_PINUSE(p, psize, next);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1632
					return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1633
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1634
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1635
			else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1636
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1637
				USAGE_ERROR_ACTION(GM, p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1638
				return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1639
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1640
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1641
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1642
		if (RTCHECK(OK_NEXT(p, next) && OK_PINUSE(next)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1643
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1644
			if (!CINUSE(next))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1645
				{	/* consolidate forward */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1646
				if (next == GM->iTop)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1647
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1648
					size_t tsize = GM->iTopSize += psize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1649
					GM->iTop = p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1650
					p->iHead = tsize | PINUSE_BIT;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1651
					if (p == GM->iDv)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1652
						{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1653
						GM->iDv = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1654
						GM->iDvSize = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1655
						}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1656
					if ( !IS_FIXED_HEAP && SHOULD_TRIM(GM, tsize)  )					
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1657
						SysTrim(GM, 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1658
					return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1659
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1660
				else if (next == GM->iDv)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1661
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1662
					size_t dsize = GM->iDvSize += psize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1663
					GM->iDv = p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1664
					SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(p, dsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1665
					return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1666
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1667
				else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1668
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1669
					size_t nsize = CHUNKSIZE(next);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1670
					psize += nsize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1671
					UnlinkChunk(GM, next, nsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1672
					SET_SIZE_AND_PINUSE_OF_FREE_CHUNK(p, psize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1673
					if (p == GM->iDv)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1674
						{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1675
						GM->iDvSize = psize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1676
						return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1677
						}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1678
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1679
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1680
			else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1681
				SET_FREE_WITH_PINUSE(p, psize, next);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1682
			InsertChunk(GM, p, psize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1683
			CHECK_FREE_CHUNK(GM, p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1684
			return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1685
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1686
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1687
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1688
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1689
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1690
void* RHybridHeap::DlRealloc(void* oldmem, size_t bytes, TInt mode)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1691
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1692
	mchunkptr oldp = MEM2CHUNK(oldmem);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1693
	size_t oldsize = CHUNKSIZE(oldp);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1694
	mchunkptr next = CHUNK_PLUS_OFFSET(oldp, oldsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1695
	mchunkptr newp = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1696
	void* extra = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1697
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1698
	/* Try to either shrink or extend into iTop. Else malloc-copy-free */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1699
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1700
	if (RTCHECK(OK_ADDRESS(GM, oldp) && OK_CINUSE(oldp) &&
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1701
				OK_NEXT(oldp, next) && OK_PINUSE(next)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1702
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1703
		size_t nb = REQUEST2SIZE(bytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1704
		if (oldsize >= nb) { /* already big enough */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1705
			size_t rsize = oldsize - nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1706
			newp = oldp;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1707
			if (rsize >= MIN_CHUNK_SIZE)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1708
				{     
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1709
				mchunkptr remainder = CHUNK_PLUS_OFFSET(newp, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1710
				SET_INUSE(GM, newp, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1711
//				SET_INUSE(GM, remainder, rsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1712
 				SET_INUSE_AND_PINUSE(GM, remainder, rsize);  // corrected in original DLA version V2.8.4
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1713
				extra = CHUNK2MEM(remainder);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1714
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1715
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1716
		else if (next == GM->iTop && oldsize + GM->iTopSize > nb)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1717
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1718
			/* Expand into iTop */
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1719
			size_t newsize = oldsize + GM->iTopSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1720
			size_t newtopsize = newsize - nb;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1721
			mchunkptr newtop = CHUNK_PLUS_OFFSET(oldp, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1722
			SET_INUSE(GM, oldp, nb);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1723
			newtop->iHead = newtopsize |PINUSE_BIT;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1724
			GM->iTop = newtop;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1725
			GM->iTopSize = newtopsize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1726
			newp = oldp;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1727
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1728
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1729
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1730
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1731
		USAGE_ERROR_ACTION(GM, oldmem);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1732
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1733
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1734
	if (newp != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1735
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1736
		if (extra != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1737
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1738
			DlFree(extra);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1739
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1740
		CHECK_INUSE_CHUNK(GM, newp);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1741
		return CHUNK2MEM(newp);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1742
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1743
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1744
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1745
		if ( mode & ENeverMove )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1746
			return 0;		// cannot move
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1747
		void* newmem = DlMalloc(bytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1748
		if (newmem != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1749
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1750
			size_t oc = oldsize - OVERHEAD_FOR(oldp);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1751
			memcpy(newmem, oldmem, (oc < bytes)? oc : bytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1752
			DlFree(oldmem);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1753
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1754
		return newmem;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1755
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1756
	//	return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1757
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1758
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1759
size_t RHybridHeap::DlInfo(struct HeapInfo* i, SWalkInfo* wi) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1760
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1761
	TInt max = ((GM->iTopSize-1) & ~CHUNK_ALIGN_MASK) - CHUNK_OVERHEAD;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1762
	if ( max < 0 )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1763
		max = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1764
	else ++i->iFreeN;			// iTop always free
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1765
	i->iFreeBytes += max;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1766
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1767
	Walk(wi, GM->iTop, max, EGoodFreeCell, EDougLeaAllocator); // Introduce DL iTop buffer to the walk function 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1768
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1769
	for (mchunkptr q = ALIGN_AS_CHUNK(GM->iSeg.iBase); q != GM->iTop; q = NEXT_CHUNK(q))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1770
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1771
		TInt sz = CHUNKSIZE(q);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1772
		if (!CINUSE(q))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1773
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1774
			if ( sz > max )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1775
				max = sz;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1776
			i->iFreeBytes += sz;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1777
			++i->iFreeN;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1778
			Walk(wi, CHUNK2MEM(q), sz, EGoodFreeCell, EDougLeaAllocator); // Introduce DL free buffer to the walk function 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1779
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1780
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1781
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1782
			i->iAllocBytes += sz - CHUNK_OVERHEAD;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1783
			++i->iAllocN;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1784
			Walk(wi, CHUNK2MEM(q), (sz- CHUNK_OVERHEAD), EGoodAllocatedCell, EDougLeaAllocator); // Introduce DL allocated buffer to the walk function 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1785
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1786
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1787
	return max;  // return largest available chunk size
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1788
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1789
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1790
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1791
// get statistics about the state of the allocator
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1792
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1793
TInt RHybridHeap::GetInfo(struct HeapInfo* i, SWalkInfo* wi) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1794
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1795
	memset(i,0,sizeof(HeapInfo));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1796
	i->iFootprint = iChunkSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1797
	i->iMaxSize = iMaxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1798
#ifndef __KERNEL_MODE__		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1799
	PagedInfo(i, wi);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1800
	SlabInfo(i, wi);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1801
#endif	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1802
	return DlInfo(i,wi);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1803
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1804
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1805
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1806
// Methods to commit/decommit memory pages from chunk
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1807
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1808
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1809
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1810
void* RHybridHeap::Map(void* p, TInt sz)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1811
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1812
// allocate pages in the chunk
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1813
// if p is NULL, Find an allocate the required number of pages (which must lie in the lower half)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1814
// otherwise commit the pages specified
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1815
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1816
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1817
	HEAP_ASSERT(sz > 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1818
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1819
	if ( iChunkSize + sz > iMaxLength)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1820
		return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1821
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1822
#ifdef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1823
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1824
	TInt r = ((DChunk*)iChunkHandle)->Adjust(iChunkSize + iOffset + sz);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1825
	if (r < 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1826
		return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1827
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1828
	iChunkSize += sz;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1829
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1830
#else	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1831
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1832
	RChunk chunk;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1833
	chunk.SetHandle(iChunkHandle);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1834
	if ( p )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1835
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1836
		TInt r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1837
		if ( iUseAdjust )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1838
			r = chunk.Adjust(iChunkSize + sz);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1839
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1840
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1841
			HEAP_ASSERT(sz == Ceiling(sz, iPageSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1842
			HEAP_ASSERT(p == Floor(p, iPageSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1843
			r = chunk.Commit(iOffset + PtrDiff(p, this),sz);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1844
			}			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1845
		if (r < 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1846
			return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1847
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1848
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1849
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1850
		TInt r = chunk.Allocate(sz);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1851
		if (r < 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1852
			return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1853
		if (r > iOffset)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1854
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1855
			// can't allow page allocations in DL zone
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1856
			chunk.Decommit(r, sz);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1857
			return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1858
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1859
		p = Offset(this, r - iOffset);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1860
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1861
	iChunkSize += sz;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1862
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1863
	if (iChunkSize >= iSlabInitThreshold)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1864
		{	// set up slab system now that heap is large enough
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1865
		SlabConfig(iSlabConfigBits);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1866
		iSlabInitThreshold = KMaxTInt32;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1867
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1868
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1869
#endif //	__KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1870
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1871
#ifdef ENABLE_BTRACE
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1872
	if(iChunkSize > iHighWaterMark)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1873
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1874
		iHighWaterMark = Ceiling(iChunkSize,16*iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1875
		TUint32 traceData[6];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1876
		traceData[0] = iChunkHandle;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1877
		traceData[1] = iMinLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1878
		traceData[2] = iMaxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1879
		traceData[3] = sz;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1880
		traceData[4] = iChunkSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1881
		traceData[5] = iHighWaterMark;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1882
		BTraceContextN(BTrace::ETest1, 90, (TUint32)this, 33, traceData, sizeof(traceData));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1883
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1884
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1885
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1886
	return p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1887
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1888
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1889
void RHybridHeap::Unmap(void* p, TInt sz)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1890
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1891
	HEAP_ASSERT(sz > 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1892
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1893
#ifdef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1894
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1895
	(void)p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1896
	HEAP_ASSERT(sz == Ceiling(sz, iPageSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1897
#if defined(_DEBUG)		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1898
	TInt r =
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1899
#endif				
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1900
   ((DChunk*)iChunkHandle)->Adjust(iChunkSize + iOffset - sz);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1901
	HEAP_ASSERT(r >= 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1902
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1903
#else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1904
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1905
	RChunk chunk;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1906
	chunk.SetHandle(iChunkHandle);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1907
	if ( iUseAdjust )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1908
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1909
		HEAP_ASSERT(sz == Ceiling(sz, iPageSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1910
#if defined(_DEBUG)		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1911
		TInt r =
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1912
#endif				
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1913
		chunk.Adjust(iChunkSize - sz);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1914
		HEAP_ASSERT(r >= 0);		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1915
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1916
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1917
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1918
		HEAP_ASSERT(sz == Ceiling(sz, iPageSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1919
		HEAP_ASSERT(p == Floor(p, iPageSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1920
#if defined(_DEBUG)		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1921
		TInt r =
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1922
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1923
		chunk.Decommit(PtrDiff(p, Offset(this,-iOffset)), sz);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1924
		HEAP_ASSERT(r >= 0);				
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1925
		}			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1926
#endif  // __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1927
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1928
	iChunkSize -= sz;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1929
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1930
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1931
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1932
#ifndef __KERNEL_MODE__
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1933
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1934
// Slab allocator code
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1935
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1936
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1937
//inline slab* slab::SlabFor(void* p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1938
slab* slab::SlabFor( const void* p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1939
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1940
	return (slab*)(Floor(p, SLABSIZE));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1941
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1942
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1943
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1944
// Remove slab s from its tree/heap (not necessarily the root), preserving the address order
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1945
// invariant of the heap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1946
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1947
void RHybridHeap::TreeRemove(slab* s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1948
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1949
	slab** r = s->iParent;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1950
	slab* c1 = s->iChild1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1951
	slab* c2 = s->iChild2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1952
	for (;;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1953
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1954
		if (!c2)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1955
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1956
			*r = c1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1957
			if (c1)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1958
				c1->iParent = r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1959
			return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1960
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1961
		if (!c1)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1962
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1963
			*r = c2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1964
			c2->iParent = r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1965
			return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1966
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1967
		if (c1 > c2)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1968
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1969
			slab* c3 = c1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1970
			c1 = c2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1971
			c2 = c3;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1972
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1973
		slab* newc2 = c1->iChild2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1974
		*r = c1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1975
		c1->iParent = r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1976
		c1->iChild2 = c2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1977
		c2->iParent = &c1->iChild2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1978
		s = c1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1979
		c1 = s->iChild1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1980
		c2 = newc2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1981
		r = &s->iChild1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1982
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1983
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1984
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1985
// Insert slab s into the tree/heap rooted at r, preserving the address ordering
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1986
// invariant of the heap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1987
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1988
void RHybridHeap::TreeInsert(slab* s,slab** r)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1989
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1990
	slab* n = *r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1991
	for (;;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1992
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1993
		if (!n)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1994
			{	// tree empty
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1995
			*r = s;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1996
			s->iParent = r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1997
			s->iChild1 = s->iChild2 = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1998
			break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  1999
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2000
		if (s < n)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2001
			{	// insert between iParent and n
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2002
			*r = s;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2003
			s->iParent = r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2004
			s->iChild1 = n;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2005
			s->iChild2 = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2006
			n->iParent = &s->iChild1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2007
			break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2008
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2009
		slab* c1 = n->iChild1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2010
		slab* c2 = n->iChild2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2011
		if ((c1 - 1) > (c2 - 1))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2012
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2013
			r = &n->iChild1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2014
			n = c1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2015
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2016
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2017
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2018
			r = &n->iChild2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2019
			n = c2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2020
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2021
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2022
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2023
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2024
void* RHybridHeap::AllocNewSlab(slabset& allocator)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2025
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2026
// Acquire and initialise a new slab, returning a cell from the slab
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2027
// The strategy is:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2028
// 1. Use the lowest address free slab, if available. This is done by using the lowest slab
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2029
//    in the page at the root of the iPartialPage heap (which is address ordered). If the
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2030
//    is now fully used, remove it from the iPartialPage heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2031
// 2. Allocate a new page for iSlabs if no empty iSlabs are available
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2032
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2033
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2034
	page* p = page::PageFor(iPartialPage);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2035
	if (!p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2036
		return AllocNewPage(allocator);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2037
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2038
	unsigned h = p->iSlabs[0].iHeader;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2039
	unsigned pagemap = SlabHeaderPagemap(h);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2040
	HEAP_ASSERT(&p->iSlabs[HIBIT(pagemap)] == iPartialPage);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2041
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2042
	unsigned slabix = LOWBIT(pagemap);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2043
	p->iSlabs[0].iHeader = h &~ (0x100<<slabix);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2044
	if (!(pagemap &~ (1<<slabix)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2045
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2046
		TreeRemove(iPartialPage);	// last free slab in page
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2047
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2048
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2049
	return InitNewSlab(allocator, &p->iSlabs[slabix]);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2050
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2051
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2052
/**Defination of this functionis not there in proto code***/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2053
#if 0
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2054
void RHybridHeap::partial_insert(slab* s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2055
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2056
	// slab has had first cell freed and needs to be linked back into iPartial tree
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2057
	slabset& ss = iSlabAlloc[iSizeMap[s->clz]];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2058
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2059
	HEAP_ASSERT(s->used == slabfull);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2060
	s->used = ss.fulluse - s->clz;		// full-1 loading
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2061
	TreeInsert(s,&ss.iPartial);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2062
	CHECKTREE(&ss.iPartial);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2063
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2064
/**Defination of this functionis not there in proto code***/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2065
#endif
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2066
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2067
void* RHybridHeap::AllocNewPage(slabset& allocator)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2068
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2069
// Acquire and initialise a new page, returning a cell from a new slab
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2070
// The iPartialPage tree is empty (otherwise we'd have used a slab from there)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2071
// The iPartialPage link is put in the highest addressed slab in the page, and the
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2072
// lowest addressed slab is used to fulfill the allocation request
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2073
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2074
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2075
	page* p	 = iSparePage;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2076
	if (p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2077
		iSparePage = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2078
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2079
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2080
		p = static_cast<page*>(Map(0, iPageSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2081
		if (!p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2082
			return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2083
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2084
	HEAP_ASSERT(p == Floor(p, iPageSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2085
	// Store page allocated for slab into paged_bitmap (for RHybridHeap::Reset())
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2086
	if (!PagedSetSize(p, iPageSize))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2087
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2088
		Unmap(p, iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2089
		return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2090
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2091
	p->iSlabs[0].iHeader = ((1<<3) + (1<<2) + (1<<1))<<8;		// set pagemap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2092
	p->iSlabs[3].iParent = &iPartialPage;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2093
	p->iSlabs[3].iChild1 = p->iSlabs[3].iChild2 = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2094
	iPartialPage = &p->iSlabs[3];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2095
	return InitNewSlab(allocator,&p->iSlabs[0]);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2096
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2097
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2098
void RHybridHeap::FreePage(page* p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2099
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2100
// Release an unused page to the OS
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2101
// A single page is cached for reuse to reduce thrashing
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2102
// the OS allocator.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2103
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2104
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2105
	HEAP_ASSERT(Ceiling(p, iPageSize) == p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2106
	if (!iSparePage)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2107
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2108
		iSparePage = p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2109
		return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2110
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2111
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2112
	// unmapped slab page must be cleared from paged_bitmap, too
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2113
	PagedZapSize(p, iPageSize);		// clear page map
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2114
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2115
	Unmap(p, iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2116
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2117
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2118
void RHybridHeap::FreeSlab(slab* s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2119
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2120
// Release an empty slab to the slab manager
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2121
// The strategy is:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2122
// 1. The page containing the slab is checked to see the state of the other iSlabs in the page by
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2123
//    inspecting the pagemap field in the iHeader of the first slab in the page.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2124
// 2. The pagemap is updated to indicate the new unused slab
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2125
// 3. If this is the only unused slab in the page then the slab iHeader is used to add the page to
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2126
//    the iPartialPage tree/heap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2127
// 4. If all the iSlabs in the page are now unused the page is release back to the OS
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2128
// 5. If this slab has a higher address than the one currently used to track this page in
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2129
//    the iPartialPage heap, the linkage is moved to the new unused slab
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2130
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2131
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2132
	TreeRemove(s);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2133
	CHECKTREE(s->iParent);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2134
	HEAP_ASSERT(SlabHeaderUsedm4(s->iHeader) == SlabHeaderSize(s->iHeader)-4);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2135
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2136
	page* p = page::PageFor(s);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2137
	unsigned h = p->iSlabs[0].iHeader;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2138
	int slabix = s - &p->iSlabs[0];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2139
	unsigned pagemap = SlabHeaderPagemap(h);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2140
	p->iSlabs[0].iHeader = h | (0x100<<slabix);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2141
	if (pagemap == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2142
		{	// page was full before, use this slab as link in empty heap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2143
		TreeInsert(s, &iPartialPage);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2144
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2145
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2146
		{	// Find the current empty-link slab
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2147
		slab* sl = &p->iSlabs[HIBIT(pagemap)];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2148
		pagemap ^= (1<<slabix);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2149
		if (pagemap == 0xf)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2150
			{	// page is now empty so recycle page to os
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2151
			TreeRemove(sl);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2152
			FreePage(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2153
			return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2154
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2155
		// ensure the free list link is in highest address slab in page
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2156
		if (s > sl)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2157
			{	// replace current link with new one. Address-order tree so position stays the same
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2158
			slab** r = sl->iParent;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2159
			slab* c1 = sl->iChild1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2160
			slab* c2 = sl->iChild2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2161
			s->iParent = r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2162
			s->iChild1 = c1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2163
			s->iChild2 = c2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2164
			*r = s;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2165
			if (c1)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2166
				c1->iParent = &s->iChild1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2167
			if (c2)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2168
				c2->iParent = &s->iChild2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2169
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2170
		CHECK(if (s < sl) s=sl);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2171
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2172
	HEAP_ASSERT(SlabHeaderPagemap(p->iSlabs[0].iHeader) != 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2173
	HEAP_ASSERT(HIBIT(SlabHeaderPagemap(p->iSlabs[0].iHeader)) == unsigned(s - &p->iSlabs[0]));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2174
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2175
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2176
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2177
void RHybridHeap::SlabInit()
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2178
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2179
	iSlabThreshold=0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2180
	iPartialPage = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2181
	iFullSlab = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2182
	iSparePage = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2183
	memset(&iSizeMap[0],0xff,sizeof(iSizeMap));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2184
	memset(&iSlabAlloc[0],0,sizeof(iSlabAlloc));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2185
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2186
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2187
void RHybridHeap::SlabConfig(unsigned slabbitmap)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2188
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2189
	HEAP_ASSERT((slabbitmap & ~EOkBits) == 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2190
	HEAP_ASSERT(MAXSLABSIZE <= 60);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2191
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2192
	unsigned int ix = 0xff;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2193
	unsigned int bit = 1<<((MAXSLABSIZE>>2)-1);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2194
	for (int sz = MAXSLABSIZE; sz >= 0; sz -= 4, bit >>= 1)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2195
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2196
		if (slabbitmap & bit)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2197
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2198
			if (ix == 0xff)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2199
				iSlabThreshold=sz+1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2200
			ix = (sz>>2)-1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2201
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2202
		iSizeMap[sz>>2] = (TUint8) ix;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2203
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2204
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2205
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2206
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2207
void* RHybridHeap::SlabAllocate(slabset& ss)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2208
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2209
// Allocate a cell from the given slabset
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2210
// Strategy:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2211
// 1. Take the partially full slab at the iTop of the heap (lowest address).
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2212
// 2. If there is no such slab, allocate from a new slab
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2213
// 3. If the slab has a non-empty freelist, pop the cell from the front of the list and update the slab
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2214
// 4. Otherwise, if the slab is not full, return the cell at the end of the currently used region of
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2215
//    the slab, updating the slab
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2216
// 5. Otherwise, release the slab from the iPartial tree/heap, marking it as 'floating' and go back to
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2217
//    step 1
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2218
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2219
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2220
	for (;;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2221
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2222
		slab *s = ss.iPartial;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2223
		if (!s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2224
			break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2225
		unsigned h = s->iHeader;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2226
		unsigned free = h & 0xff;		// extract free cell positioning
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2227
		if (free)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2228
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2229
			HEAP_ASSERT(((free<<2)-sizeof(slabhdr))%SlabHeaderSize(h) == 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2230
			void* p = Offset(s,free<<2);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2231
			free = *(unsigned char*)p;	// get next pos in free list
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2232
			h += (h&0x3C000)<<6;		// update usedm4
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2233
			h &= ~0xff;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2234
			h |= free;					// update freelist
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2235
			s->iHeader = h;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2236
			HEAP_ASSERT(SlabHeaderFree(h) == 0 || ((SlabHeaderFree(h)<<2)-sizeof(slabhdr))%SlabHeaderSize(h) == 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2237
			HEAP_ASSERT(SlabHeaderUsedm4(h) <= 0x3F8u);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2238
			HEAP_ASSERT((SlabHeaderUsedm4(h)+4)%SlabHeaderSize(h) == 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2239
			return p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2240
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2241
		unsigned h2 = h + ((h&0x3C000)<<6);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2242
//		if (h2 < 0xfc00000)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2243
  		if (h2 < MAXUSEDM4BITS)		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2244
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2245
			HEAP_ASSERT((SlabHeaderUsedm4(h2)+4)%SlabHeaderSize(h2) == 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2246
			s->iHeader = h2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2247
			return Offset(s,(h>>18) + sizeof(unsigned) + sizeof(slabhdr));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2248
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2249
		h |= FLOATING_BIT;				// mark the slab as full-floating
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2250
		s->iHeader = h;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2251
		TreeRemove(s);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2252
		slab* c = iFullSlab;			// add to full list
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2253
		iFullSlab = s;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2254
		s->iParent = &iFullSlab;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2255
		s->iChild1 = c;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2256
		s->iChild2 = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2257
		if (c)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2258
			c->iParent = &s->iChild1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2259
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2260
		CHECKTREE(&ss.iPartial);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2261
		// go back and try the next slab...
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2262
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2263
	// no iPartial iSlabs found, so allocate from a new slab
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2264
	return AllocNewSlab(ss);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2265
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2266
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2267
void RHybridHeap::SlabFree(void* p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2268
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2269
// Free a cell from the slab allocator
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2270
// Strategy:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2271
// 1. Find the containing slab (round down to nearest 1KB boundary)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2272
// 2. Push the cell into the slab's freelist, and update the slab usage count
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2273
// 3. If this is the last allocated cell, free the slab to the main slab manager
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2274
// 4. If the slab was full-floating then insert the slab in it's respective iPartial tree
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2275
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2276
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2277
	HEAP_ASSERT(LowBits(p,3)==0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2278
	slab* s = slab::SlabFor(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2279
	CHECKSLAB(s,ESlabAllocator,p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2280
	CHECKSLABBFR(s,p);	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2281
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2282
	unsigned pos = LowBits(p, SLABSIZE);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2283
	unsigned h = s->iHeader;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2284
	HEAP_ASSERT(SlabHeaderUsedm4(h) != 0x3fC);		// slab is empty already
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2285
	HEAP_ASSERT((pos-sizeof(slabhdr))%SlabHeaderSize(h) == 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2286
	*(unsigned char*)p = (unsigned char)h;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2287
	h &= ~0xFF;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2288
	h |= (pos>>2);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2289
	unsigned size = h & 0x3C000;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2290
	if (int(h) >= 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2291
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2292
		h -= size<<6;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2293
		if (int(h)>=0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2294
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2295
			s->iHeader = h;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2296
			return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2297
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2298
		FreeSlab(s);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2299
		return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2300
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2301
	h -= size<<6;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2302
    h &= ~FLOATING_BIT;	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2303
	s->iHeader = h;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2304
	slab** full = s->iParent;		// remove from full list
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2305
	slab* c = s->iChild1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2306
	*full = c;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2307
	if (c)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2308
		c->iParent = full;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2309
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2310
	slabset& ss = iSlabAlloc[iSizeMap[size>>14]];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2311
	TreeInsert(s,&ss.iPartial);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2312
	CHECKTREE(&ss.iPartial);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2313
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2314
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2315
void* RHybridHeap::InitNewSlab(slabset& allocator, slab* s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2316
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2317
// initialise an empty slab for this allocator and return the fist cell
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2318
// pre-condition: the slabset has no iPartial iSlabs for allocation
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2319
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2320
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2321
	HEAP_ASSERT(allocator.iPartial==0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2322
	TInt size = 4 + ((&allocator-&iSlabAlloc[0])<<2);	// infer size from slab allocator address
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2323
	unsigned h = s->iHeader & 0xF00;	// preserve pagemap only
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2324
	h |= (size<<12);					// set size
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2325
	h |= (size-4)<<18;					// set usedminus4 to one object minus 4
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2326
	s->iHeader = h;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2327
	allocator.iPartial = s;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2328
	s->iParent = &allocator.iPartial;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2329
	s->iChild1 = s->iChild2 = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2330
	return Offset(s,sizeof(slabhdr));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2331
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2332
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2333
const unsigned char slab_bitcount[16] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2334
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2335
const unsigned char slab_ext_frag[16] =
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2336
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2337
	0,
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2338
	16 + (1008 % 4),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2339
	16 + (1008 % 8),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2340
	16 + (1008 % 12),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2341
	16 + (1008 % 16),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2342
	16 + (1008 % 20),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2343
	16 + (1008 % 24),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2344
	16 + (1008 % 28),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2345
	16 + (1008 % 32),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2346
	16 + (1008 % 36),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2347
	16 + (1008 % 40),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2348
	16 + (1008 % 44),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2349
	16 + (1008 % 48),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2350
	16 + (1008 % 52),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2351
	16 + (1008 % 56),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2352
	16 + (1008 % 60)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2353
};
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2354
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2355
void RHybridHeap::TreeWalk(slab* const* root, void (*f)(slab*, struct HeapInfo*, SWalkInfo*), struct HeapInfo* i, SWalkInfo* wi)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2356
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2357
	// iterative walk around the tree at root
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2358
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2359
	slab* s = *root;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2360
	if (!s)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2361
		return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2362
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2363
	for (;;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2364
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2365
		slab* c;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2366
		while ((c = s->iChild1) != 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2367
			s = c;		// walk down left side to end
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2368
		for (;;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2369
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2370
			f(s, i, wi);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2371
			c = s->iChild2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2372
			if (c)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2373
				{	// one step down right side, now try and walk down left
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2374
				s = c;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2375
				break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2376
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2377
			for (;;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2378
				{	// loop to walk up right side
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2379
				slab** pp = s->iParent;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2380
				if (pp == root)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2381
					return;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2382
				s = slab::SlabFor(pp);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2383
				if (pp == &s->iChild1)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2384
					break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2385
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2386
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2387
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2388
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2389
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2390
void RHybridHeap::SlabEmptyInfo(slab* s, struct HeapInfo* i, SWalkInfo* wi)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2391
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2392
	Walk(wi, s, SLABSIZE, EGoodFreeCell, EEmptySlab); // Introduce an empty slab to the walk function 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2393
	int nslab = slab_bitcount[SlabHeaderPagemap(page::PageFor(s)->iSlabs[0].iHeader)];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2394
	i->iFreeN += nslab;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2395
	i->iFreeBytes += nslab << SLABSHIFT;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2396
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2397
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2398
void RHybridHeap::SlabPartialInfo(slab* s, struct HeapInfo* i, SWalkInfo* wi)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2399
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2400
	Walk(wi, s, SLABSIZE, EGoodAllocatedCell, EPartialFullSlab); // Introduce a full slab to the walk function 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2401
	unsigned h = s->iHeader;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2402
	unsigned used = SlabHeaderUsedm4(h)+4;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2403
	unsigned size = SlabHeaderSize(h);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2404
	unsigned free = 1024 - slab_ext_frag[size>>2] - used;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2405
	i->iFreeN += (free/size);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2406
	i->iFreeBytes += free;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2407
	i->iAllocN += (used/size);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2408
	i->iAllocBytes += used;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2409
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2410
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2411
void RHybridHeap::SlabFullInfo(slab* s, struct HeapInfo* i, SWalkInfo* wi)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2412
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2413
	Walk(wi, s, SLABSIZE, EGoodAllocatedCell, EFullSlab); // Introduce a full slab to the walk function 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2414
	unsigned h = s->iHeader;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2415
	unsigned used = SlabHeaderUsedm4(h)+4;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2416
	unsigned size = SlabHeaderSize(h);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2417
	HEAP_ASSERT(1024 - slab_ext_frag[size>>2] - used == 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2418
	i->iAllocN += (used/size);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2419
	i->iAllocBytes += used;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2420
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2421
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2422
void RHybridHeap::SlabInfo(struct HeapInfo* i, SWalkInfo* wi) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2423
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2424
	if (iSparePage)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2425
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2426
		i->iFreeBytes += iPageSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2427
		i->iFreeN = 4;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2428
		Walk(wi, iSparePage, iPageSize, EGoodFreeCell, ESlabSpare); // Introduce Slab spare page to the walk function 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2429
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2430
	TreeWalk(&iFullSlab, &SlabFullInfo, i, wi);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2431
	for (int ix = 0; ix < (MAXSLABSIZE>>2); ++ix)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2432
		TreeWalk(&iSlabAlloc[ix].iPartial, &SlabPartialInfo, i, wi);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2433
	TreeWalk(&iPartialPage, &SlabEmptyInfo, i, wi);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2434
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2435
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2436
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2437
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2438
// Bitmap class implementation for large page allocator 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2439
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2440
inline unsigned char* paged_bitmap::Addr() const {return iBase;}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2441
inline unsigned paged_bitmap::Size() const {return iNbits;}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2442
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2443
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2444
void paged_bitmap::Init(unsigned char* p, unsigned size, unsigned bit)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2445
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2446
	iBase = p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2447
	iNbits=size;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2448
	int bytes=Ceiling(size,8)>>3;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2449
	memset(p,bit?0xff:0,bytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2450
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2451
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2452
inline void paged_bitmap::Set(unsigned ix, unsigned bit)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2453
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2454
	if (bit)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2455
		iBase[ix>>3] |= (1<<(ix&7));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2456
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2457
		iBase[ix>>3] &= ~(1<<(ix&7));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2458
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2459
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2460
inline unsigned paged_bitmap::operator[](unsigned ix) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2461
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2462
	return 1U&(iBase[ix>>3] >> (ix&7));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2463
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2464
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2465
void paged_bitmap::Setn(unsigned ix, unsigned len, unsigned bit)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2466
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2467
	int l=len;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2468
	while (--l>=0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2469
		Set(ix++,bit);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2470
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2471
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2472
void paged_bitmap::Set(unsigned ix, unsigned len, unsigned val)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2473
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2474
	int l=len;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2475
	while (--l>=0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2476
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2477
		Set(ix++,val&1);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2478
		val>>=1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2479
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2480
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2481
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2482
unsigned paged_bitmap::Bits(unsigned ix, unsigned len) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2483
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2484
	int l=len;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2485
	unsigned val=0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2486
	unsigned bit=0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2487
	while (--l>=0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2488
		val |= (*this)[ix++]<<bit++;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2489
	return val;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2490
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2491
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2492
bool paged_bitmap::Is(unsigned ix, unsigned len, unsigned bit) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2493
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2494
	unsigned i2 = ix+len;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2495
	if (i2 > iNbits)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2496
		return false;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2497
	for (;;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2498
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2499
		if ((*this)[ix] != bit)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2500
			return false;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2501
		if (++ix==i2)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2502
			return true;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2503
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2504
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2505
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2506
int paged_bitmap::Find(unsigned start, unsigned bit) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2507
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2508
	if (start<iNbits) do
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2509
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2510
		if ((*this)[start]==bit)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2511
			return start;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2512
		} while (++start<iNbits);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2513
	return -1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2514
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2515
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2516
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2517
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2518
// Page allocator code
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2519
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2520
void RHybridHeap::PagedInit(TInt aPagePower)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2521
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2522
	if (aPagePower > 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2523
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2524
		if (aPagePower < MINPAGEPOWER)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2525
			aPagePower = MINPAGEPOWER;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2526
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2527
	else aPagePower = 31;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2528
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2529
	iPageThreshold = aPagePower;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2530
	/*-------------------------------------------------------------
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2531
	 * Initialize page bitmap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2532
	 *-------------------------------------------------------------*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2533
	iPageMap.Init((unsigned char*)&iBitMapBuffer, MAXSMALLPAGEBITS, 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2534
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2535
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2536
void* RHybridHeap::PagedAllocate(unsigned size)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2537
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2538
	TInt nbytes = Ceiling(size, iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2539
	void* p = Map(0, nbytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2540
	if (!p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2541
		return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2542
	if (!PagedSetSize(p, nbytes))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2543
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2544
		Unmap(p, nbytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2545
		return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2546
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2547
	return p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2548
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2549
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2550
void* RHybridHeap::PagedReallocate(void* p, unsigned size, TInt mode)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2551
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2552
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2553
	HEAP_ASSERT(Ceiling(p, iPageSize) == p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2554
	unsigned nbytes = Ceiling(size, iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2555
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2556
	unsigned osize = PagedSize(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2557
	if ( nbytes == 0 )  // Special case to handle shrinking below min page threshold 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2558
		nbytes = Min((1 << MINPAGEPOWER), osize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2559
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2560
	if (osize == nbytes)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2561
		return p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2562
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2563
	if (nbytes < osize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2564
		{	// shrink in place, unmap final pages and rewrite the pagemap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2565
		Unmap(Offset(p, nbytes), osize-nbytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2566
		// zap old code and then write new code (will not fail)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2567
		PagedZapSize(p, osize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2568
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2569
		TBool check = PagedSetSize(p, nbytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2570
        __ASSERT_ALWAYS(check, HEAP_PANIC(ETHeapBadCellAddress));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2571
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2572
		return p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2573
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2574
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2575
	// nbytes > osize
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2576
	// try and extend current region first
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2577
			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2578
	void* newp = Map(Offset(p, osize), nbytes-osize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2579
	if (newp)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2580
		{	// In place growth. Possibility that pagemap may have to grow AND then fails
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2581
		if (!PagedSetSize(p, nbytes))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2582
			{	// must release extra mapping
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2583
			Unmap(Offset(p, osize), nbytes-osize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2584
			return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2585
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2586
		// if successful, the new length code will have overwritten the old one (it is at least as long)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2587
		return p;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2588
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2589
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2590
	// fallback to  allocate/copy/free
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2591
	if (mode & ENeverMove)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2592
		return 0;		// not allowed to move cell
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2593
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2594
	newp = PagedAllocate(nbytes);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2595
	if (!newp)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2596
		return 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2597
	memcpy(newp, p, osize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2598
	PagedFree(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2599
	return newp;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2600
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2601
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2602
void RHybridHeap::PagedFree(void* p)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2603
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2604
	HEAP_ASSERT(Ceiling(p, iPageSize) == p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2605
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2606
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2607
	unsigned size = PagedSize(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2608
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2609
	PagedZapSize(p, size);		// clear page map
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2610
	Unmap(p, size);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2611
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2612
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2613
void RHybridHeap::PagedInfo(struct HeapInfo* i, SWalkInfo* wi) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2614
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2615
	for (int ix = 0;(ix = iPageMap.Find(ix,1)) >= 0;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2616
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2617
		int npage = PagedDecode(ix);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2618
		// Introduce paged buffer to the walk function 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2619
		TAny* bfr = Bitmap2addr(ix);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2620
		int len = npage << PAGESHIFT;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2621
		if ( len > iPageSize )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2622
			{ // If buffer is not larger than one page it must be a slab page mapped into bitmap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2623
			i->iAllocBytes += len;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2624
			++i->iAllocN;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2625
			Walk(wi, bfr, len, EGoodAllocatedCell, EPageAllocator);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2626
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2627
		ix += (npage<<1);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2628
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2629
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2630
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2631
void RHybridHeap::ResetBitmap()
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2632
/*---------------------------------------------------------
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2633
 * Go through paged_bitmap and unmap all buffers to system
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2634
 * This method is called from RHybridHeap::Reset() to unmap all page
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2635
 * allocated - and slab pages which are stored in bitmap, too
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2636
 *---------------------------------------------------------*/ 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2637
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2638
	unsigned iNbits = iPageMap.Size();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2639
	if ( iNbits )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2640
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2641
		for (int ix = 0;(ix = iPageMap.Find(ix,1)) >= 0;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2642
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2643
			int npage = PagedDecode(ix);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2644
			void* p = Bitmap2addr(ix);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2645
			unsigned size = PagedSize(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2646
			PagedZapSize(p, size);		// clear page map
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2647
			Unmap(p, size);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2648
			ix += (npage<<1);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2649
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2650
		if ( (TInt)iNbits > MAXSMALLPAGEBITS )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2651
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2652
			// unmap page reserved for enlarged bitmap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2653
			Unmap(iPageMap.Addr(), (iNbits >> 3) );
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2654
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2655
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2656
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2657
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2658
TBool RHybridHeap::CheckBitmap(void* aBfr, TInt aSize, TUint32& aDummy, TInt& aNPages)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2659
/*---------------------------------------------------------
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2660
 * If aBfr = NULL
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2661
 *   Go through paged_bitmap and unmap all buffers to system
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2662
 *   and assure that by reading the first word of each page of aBfr
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2663
 *   that aBfr is still accessible
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2664
 * else  
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2665
 *   Assure that specified buffer is mapped with correct length in
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2666
 *   page map
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2667
 *---------------------------------------------------------*/ 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2668
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2669
	TBool ret;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2670
	if ( aBfr )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2671
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2672
		__ASSERT_ALWAYS((Ceiling(aBfr, iPageSize) == aBfr), HEAP_PANIC(ETHeapBadCellAddress));		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2673
        ret = ( aSize == (TInt)PagedSize(aBfr));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2674
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2675
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2676
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2677
		ret = ETrue;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2678
		unsigned iNbits = iPageMap.Size();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2679
		if ( iNbits )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2680
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2681
			TInt npage;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2682
			aNPages = 0;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2683
			for (int ix = 0;(ix = iPageMap.Find(ix,1)) >= 0;)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2684
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2685
				npage = PagedDecode(ix);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2686
				aNPages += npage;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2687
				void* p = Bitmap2addr(ix);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2688
				__ASSERT_ALWAYS((Ceiling(p, iPageSize) == p), HEAP_PANIC(ETHeapBadCellAddress));						
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2689
				unsigned s = PagedSize(p);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2690
				__ASSERT_ALWAYS((Ceiling(s, iPageSize) == s), HEAP_PANIC(ETHeapBadCellAddress));	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2691
				while ( s )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2692
					{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2693
					aDummy += *(TUint32*)((TUint8*)p + (s-iPageSize));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2694
					s -= iPageSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2695
					}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2696
				ix += (npage<<1);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2697
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2698
			if ( (TInt)iNbits > MAXSMALLPAGEBITS )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2699
				{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2700
				// add enlarged bitmap page(s) to total page count
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2701
                npage = (iNbits >> 3); 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2702
				__ASSERT_ALWAYS((Ceiling(npage, iPageSize) == npage), HEAP_PANIC(ETHeapBadCellAddress));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2703
				aNPages += (npage / iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2704
				}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2705
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2706
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2707
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2708
	return ret;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2709
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2710
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2711
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2712
// The paged allocations are tracked in a bitmap which has 2 bits per page
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2713
// this allows us to store allocations as small as 4KB
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2714
// The presence and size of an allocation is encoded as follows:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2715
// let N = number of pages in the allocation, then
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2716
// 10            : N = 1			// 4KB
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2717
// 110n			 : N = 2 + n		// 8-12KB
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2718
// 1110nnnn      : N = nnnn			// 16-60KB
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2719
// 1111n[18]	 : N = n[18]		// 64KB-1GB
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2720
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2721
const struct etab { unsigned char offset, len, codelen, code;} encode_table[] =
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2722
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2723
	{1,2,2,0x1},
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2724
	{2,4,3,0x3},
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2725
	{0,8,4,0x7},
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2726
	{0,22,4,0xf}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2727
};
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2728
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2729
// Return code length for specified allocation Size(assumed to be aligned to pages)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2730
inline unsigned paged_codelen(unsigned size, unsigned pagesz)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2731
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2732
	HEAP_ASSERT(size == Ceiling(size, pagesz));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2733
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2734
	if (size == pagesz)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2735
		return 2;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2736
	else if (size < 4*pagesz)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2737
		return 4;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2738
	else if (size < 16*pagesz)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2739
		return 8;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2740
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2741
		return 22;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2742
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2743
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2744
inline const etab& paged_coding(unsigned npage)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2745
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2746
	if (npage < 4)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2747
		return encode_table[npage>>1];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2748
	else if (npage < 16)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2749
		return encode_table[2];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2750
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2751
		return encode_table[3];
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2752
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2753
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2754
bool RHybridHeap::PagedEncode(unsigned pos, unsigned npage)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2755
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2756
	const etab& e = paged_coding(npage);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2757
	if (pos + e.len > iPageMap.Size())
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2758
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2759
		// need to grow the page bitmap to fit the cell length into the map
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2760
		// if we outgrow original bitmap buffer in RHybridHeap metadata, then just get enough pages to cover the full space:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2761
		// * initial 68 byte bitmap mapped (68*8*4kB):2 = 1,1MB
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2762
		// * 4KB can Map(4096*8*4kB):2 = 64MB
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2763
		unsigned maxsize = Ceiling(iMaxLength, iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2764
		unsigned mapbits = maxsize >> (PAGESHIFT-1);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2765
		maxsize = Ceiling(mapbits>>3, iPageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2766
		void* newb = Map(0, maxsize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2767
		if (!newb)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2768
			return false;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2769
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2770
		unsigned char* oldb = iPageMap.Addr();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2771
		iPageMap.Init((unsigned char*)newb, (maxsize<<3), 0);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2772
		memcpy(newb, oldb, Ceiling(MAXSMALLPAGEBITS,8)>>3);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2773
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2774
	// encode the allocation block size into the bitmap, starting at the bit for the start page
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2775
	unsigned bits = e.code;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2776
	bits |= (npage - e.offset) << e.codelen;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2777
	iPageMap.Set(pos, e.len, bits);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2778
	return true;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2779
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2780
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2781
unsigned RHybridHeap::PagedDecode(unsigned pos) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2782
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2783
	__ASSERT_ALWAYS(pos + 2 <= iPageMap.Size(), HEAP_PANIC(ETHeapBadCellAddress));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2784
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2785
	unsigned bits = iPageMap.Bits(pos,2);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2786
	__ASSERT_ALWAYS(bits & 1, HEAP_PANIC(ETHeapBadCellAddress));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2787
	bits >>= 1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2788
	if (bits == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2789
		return 1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2790
	__ASSERT_ALWAYS(pos + 4 <= iPageMap.Size(), HEAP_PANIC(ETHeapBadCellAddress));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2791
	bits = iPageMap.Bits(pos+2,2);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2792
	if ((bits & 1) == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2793
		return 2 + (bits>>1);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2794
	else if ((bits>>1) == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2795
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2796
		__ASSERT_ALWAYS(pos + 8 <= iPageMap.Size(), HEAP_PANIC(ETHeapBadCellAddress));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2797
		return iPageMap.Bits(pos+4, 4);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2798
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2799
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2800
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2801
		__ASSERT_ALWAYS(pos + 22 <= iPageMap.Size(), HEAP_PANIC(ETHeapBadCellAddress));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2802
		return iPageMap.Bits(pos+4, 18);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2803
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2804
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2805
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2806
inline void RHybridHeap::PagedZapSize(void* p, unsigned size)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2807
{iPageMap.Setn(PtrDiff(p, iMemBase) >> (PAGESHIFT-1), paged_codelen(size, iPageSize) ,0);}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2808
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2809
inline unsigned RHybridHeap::PagedSize(void* p) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2810
   { return PagedDecode(PtrDiff(p, iMemBase) >> (PAGESHIFT-1)) << PAGESHIFT; }
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2811
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2812
inline bool RHybridHeap::PagedSetSize(void* p, unsigned size)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2813
{ return PagedEncode(PtrDiff(p, iMemBase) >> (PAGESHIFT-1), size >> PAGESHIFT); }
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2814
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2815
inline void* RHybridHeap::Bitmap2addr(unsigned pos) const
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2816
   { return iMemBase + (1 << (PAGESHIFT-1))*pos; }
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2817
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2818
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2819
//////////////////////////////////////////////////////////////////////////
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2820
//////////////////////////////////////////////////////////////////////////
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2821
//////////////////////////////////////////////////////////////////////////
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2822
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2823
Constructor where minimum and maximum length of the heap can be defined.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2824
It defaults the chunk heap to be created to have use a new local chunk, 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2825
to have a grow by value of KMinHeapGrowBy, to be unaligned, not to be 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2826
single threaded and not to have any mode flags set.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2827
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2828
@param aMinLength    The minimum length of the heap to be created.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2829
@param aMaxLength    The maximum length to which the heap to be created can grow.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2830
                     If the supplied value is less than a page size, then it
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2831
                     is discarded and the page size is used instead.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2832
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2833
EXPORT_C TChunkHeapCreateInfo::TChunkHeapCreateInfo(TInt aMinLength, TInt aMaxLength) :
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2834
   iVersionNumber(EVersion0), iMinLength(aMinLength), iMaxLength(aMaxLength),
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2835
iAlign(0), iGrowBy(1), iSingleThread(EFalse), 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2836
iOffset(0), iPaging(EUnspecified), iMode(0), iName(NULL)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2837
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2838
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2839
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2840
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2841
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2842
Sets the chunk heap to create a new chunk with the specified name.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2843
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2844
This overriddes any previous call to TChunkHeapCreateInfo::SetNewChunkHeap() or
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2845
TChunkHeapCreateInfo::SetExistingChunkHeap() for this TChunkHeapCreateInfo object.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2846
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2847
@param aName	The name to be given to the chunk heap to be created
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2848
If NULL, the function constructs a local chunk to host the heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2849
If not NULL, a pointer to a descriptor containing the name to be 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2850
assigned to the global chunk hosting the heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2851
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2852
EXPORT_C void TChunkHeapCreateInfo::SetCreateChunk(const TDesC* aName)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2853
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2854
	iName = (TDesC*)aName;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2855
	iChunk.SetHandle(KNullHandle);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2856
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2857
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2858
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2859
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2860
Sets the chunk heap to be created to use the chunk specified.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2861
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2862
This overriddes any previous call to TChunkHeapCreateInfo::SetNewChunkHeap() or
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2863
TChunkHeapCreateInfo::SetExistingChunkHeap() for this TChunkHeapCreateInfo object.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2864
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2865
@param aChunk	A handle to the chunk to use for the heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2866
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2867
EXPORT_C void TChunkHeapCreateInfo::SetUseChunk(const RChunk aChunk)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2868
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2869
	iName = NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2870
	iChunk = aChunk;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2871
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2872
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2873
EXPORT_C RHeap* UserHeap::FixedHeap(TAny* aBase, TInt aMaxLength, TInt aAlign, TBool aSingleThread)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2874
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2875
Creates a fixed length heap at a specified location.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2876
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2877
On successful return from this function, the heap is ready to use.  This assumes that
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2878
the memory pointed to by aBase is mapped and able to be used.  You must ensure that you
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2879
pass in a large enough value for aMaxLength.  Passing in a value that is too small to
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2880
hold the metadata for the heap (~1 KB) will result in the size being rounded up and the
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2881
heap thereby running over the end of the memory assigned to it.  But then if you were to
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2882
pass in such as small value then you would not be able to do any allocations from the
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2883
heap anyway.  Moral of the story: Use a sensible value for aMaxLength!
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2884
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2885
@param aBase         A pointer to the location where the heap is to be constructed.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2886
@param aMaxLength    The maximum length in bytes to which the heap can grow.  If the
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2887
                     supplied value is too small to hold the heap's metadata, it
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2888
                     will be increased.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2889
@param aAlign        From Symbian^4 onwards, this value is ignored but EABI 8
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2890
                     byte alignment is guaranteed for all allocations 8 bytes or
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2891
                     more in size.  4 byte allocations will be aligned to a 4
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2892
                     byte boundary.  Best to pass in zero.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2893
@param aSingleThread ETrue if the heap is to be accessed from multiple threads.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2894
                     This will cause internal locks to be created, guaranteeing
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2895
                     thread safety.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2896
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2897
@return A pointer to the new heap, or NULL if the heap could not be created.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2898
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2899
@panic USER 56 if aMaxLength is negative.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2900
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2901
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2902
	__ASSERT_ALWAYS( aMaxLength>=0, ::Panic(ETHeapMaxLengthNegative));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2903
	if ( aMaxLength < (TInt)sizeof(RHybridHeap) )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2904
		aMaxLength = sizeof(RHybridHeap);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2905
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2906
	RHybridHeap* h = new(aBase) RHybridHeap(aMaxLength, aAlign, aSingleThread);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2907
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2908
	if (!aSingleThread)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2909
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2910
		TInt r = h->iLock.CreateLocal();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2911
		if (r!=KErrNone)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2912
			return NULL; // No need to delete the RHybridHeap instance as the new above is only a placement new
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2913
		h->iHandles = (TInt*)&h->iLock;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2914
		h->iHandleCount = 1;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2915
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2916
	return h;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2917
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2918
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2919
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2920
Creates a chunk heap of the type specified by the parameter aCreateInfo.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2921
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2922
@param aCreateInfo	A reference to a TChunkHeapCreateInfo object specifying the
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2923
type of chunk heap to create.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2924
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2925
@return A pointer to the new heap or NULL if the heap could not be created.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2926
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2927
@panic USER 41 if the heap's specified minimum length is greater than the specified maximum length.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2928
@panic USER 55 if the heap's specified minimum length is negative.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2929
@panic USER 172 if the heap's specified alignment is not a power of 2 or is less than the size of a TAny*.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2930
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2931
EXPORT_C RHeap* UserHeap::ChunkHeap(const TChunkHeapCreateInfo& aCreateInfo)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2932
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2933
	// aCreateInfo must have been configured to use a new chunk or an exiting chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2934
	__ASSERT_ALWAYS(!(aCreateInfo.iMode & (TUint32)~EChunkHeapMask), ::Panic(EHeapCreateInvalidMode));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2935
	RHeap* h = NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2936
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2937
	if (aCreateInfo.iChunk.Handle() == KNullHandle)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2938
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2939
		// A new chunk is to be created for this heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2940
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2941
		__ASSERT_ALWAYS(aCreateInfo.iMinLength >= 0, ::Panic(ETHeapMinLengthNegative));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2942
		__ASSERT_ALWAYS(aCreateInfo.iMaxLength >= aCreateInfo.iMinLength, ::Panic(ETHeapCreateMaxLessThanMin));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2943
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2944
		TInt maxLength = aCreateInfo.iMaxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2945
		TInt page_size;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2946
		GET_PAGE_SIZE(page_size);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2947
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2948
		if (maxLength < page_size)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2949
			maxLength = page_size;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2950
		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2951
		TChunkCreateInfo chunkInfo;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2952
#if USE_HYBRID_HEAP
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2953
		if ( aCreateInfo.iOffset )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2954
			chunkInfo.SetNormal(0, maxLength);  // Create DL only heap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2955
		else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2956
			{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2957
			maxLength = 2*maxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2958
			chunkInfo.SetDisconnected(0, 0, maxLength); // Create hybrid heap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2959
			}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2960
#else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2961
		chunkInfo.SetNormal(0, maxLength);  // Create DL only heap		
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2962
#endif			
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2963
		chunkInfo.SetOwner((aCreateInfo.iSingleThread)? EOwnerThread : EOwnerProcess);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2964
		if (aCreateInfo.iName)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2965
			chunkInfo.SetGlobal(*aCreateInfo.iName);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2966
		// Set the paging attributes of the chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2967
		if (aCreateInfo.iPaging == TChunkHeapCreateInfo::EPaged)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2968
			chunkInfo.SetPaging(TChunkCreateInfo::EPaged);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2969
		if (aCreateInfo.iPaging == TChunkHeapCreateInfo::EUnpaged)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2970
			chunkInfo.SetPaging(TChunkCreateInfo::EUnpaged);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2971
		// Create the chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2972
		RChunk chunk;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2973
		if (chunk.Create(chunkInfo) != KErrNone)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2974
			return NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2975
		// Create the heap using the new chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2976
		TUint mode = aCreateInfo.iMode | EChunkHeapDuplicate;	// Must duplicate the handle.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2977
		h = OffsetChunkHeap(chunk, aCreateInfo.iMinLength, aCreateInfo.iOffset,
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2978
							aCreateInfo.iGrowBy, maxLength, aCreateInfo.iAlign,
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2979
							aCreateInfo.iSingleThread, mode);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2980
		chunk.Close();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2981
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2982
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2983
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2984
		h = OffsetChunkHeap(aCreateInfo.iChunk, aCreateInfo.iMinLength, aCreateInfo.iOffset,
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2985
							aCreateInfo.iGrowBy, aCreateInfo.iMaxLength, aCreateInfo.iAlign,
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2986
							aCreateInfo.iSingleThread, aCreateInfo.iMode);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2987
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2988
	return h;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2989
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2990
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2991
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2992
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2993
EXPORT_C RHeap* UserHeap::ChunkHeap(const TDesC* aName, TInt aMinLength, TInt aMaxLength, TInt aGrowBy, TInt aAlign, TBool aSingleThread)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2994
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2995
Creates a heap in a local or global chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2996
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2997
The chunk hosting the heap can be local or global.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2998
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  2999
A local chunk is one which is private to the process creating it and is not
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3000
intended for access by other user processes.  A global chunk is one which is
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3001
visible to all processes.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3002
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3003
The hosting chunk is local, if the pointer aName is NULL, otherwise the
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3004
hosting chunk is global and the descriptor *aName is assumed to contain
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3005
the name to be assigned to it.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3006
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3007
Ownership of the host chunk is vested in the current process.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3008
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3009
A minimum and a maximum size for the heap can be specified. On successful
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3010
return from this function, the size of the heap is at least aMinLength.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3011
If subsequent requests for allocation of memory from the heap cannot be
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3012
satisfied by compressing the heap, the size of the heap is extended in
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3013
increments of aGrowBy until the request can be satisfied.  Attempts to extend
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3014
the heap causes the size of the host chunk to be adjusted.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3015
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3016
Note that the size of the heap cannot be adjusted by more than aMaxLength.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3017
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3018
@param aName         If NULL, the function constructs a local chunk to host
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3019
                     the heap.  If not NULL, a pointer to a descriptor containing
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3020
                     the name to be assigned to the global chunk hosting the heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3021
@param aMinLength    The minimum length of the heap in bytes.  This will be
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3022
                     rounded up to the nearest page size by the allocator.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3023
@param aMaxLength    The maximum length in bytes to which the heap can grow.  This
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3024
                     will be rounded up to the nearest page size by the allocator.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3025
@param aGrowBy       The number of bytes by which the heap will grow when more
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3026
                     memory is required.  This will be rounded up to the nearest
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3027
                     page size by the allocator.  If a value is not explicitly
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3028
                     specified, the page size is taken by default.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3029
@param aAlign        From Symbian^4 onwards, this value is ignored but EABI 8
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3030
                     byte alignment is guaranteed for all allocations 8 bytes or
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3031
                     more in size.  4 byte allocations will be aligned to a 4
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3032
                     byte boundary.  Best to pass in zero.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3033
@param aSingleThread ETrue if the heap is to be accessed from multiple threads.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3034
                     This will cause internal locks to be created, guaranteeing
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3035
                     thread safety.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3036
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3037
@return A pointer to the new heap or NULL if the heap could not be created.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3038
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3039
@panic USER 41 if aMaxLength is < aMinLength.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3040
@panic USER 55 if aMinLength is negative.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3041
@panic USER 56 if aMaxLength is negative.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3042
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3043
	{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3044
	TInt page_size;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3045
	GET_PAGE_SIZE(page_size);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3046
	TInt minLength = _ALIGN_UP(aMinLength, page_size);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3047
	TInt maxLength = Max(aMaxLength, minLength);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3048
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3049
	TChunkHeapCreateInfo createInfo(minLength, maxLength);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3050
	createInfo.SetCreateChunk(aName);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3051
	createInfo.SetGrowBy(aGrowBy);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3052
	createInfo.SetAlignment(aAlign);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3053
	createInfo.SetSingleThread(aSingleThread);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3054
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3055
	return ChunkHeap(createInfo);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3056
	}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3057
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3058
EXPORT_C RHeap* UserHeap::ChunkHeap(RChunk aChunk, TInt aMinLength, TInt aGrowBy, TInt aMaxLength, TInt aAlign, TBool aSingleThread, TUint32 aMode)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3059
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3060
Creates a heap in an existing chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3061
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3062
This function is intended to be used to create a heap in a user writable code
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3063
chunk as created by a call to RChunk::CreateLocalCode().  This type of heap can
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3064
be used to hold code fragments from a JIT compiler.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3065
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3066
@param aChunk        The chunk that will host the heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3067
@param aMinLength    The minimum length of the heap in bytes.  This will be
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3068
                     rounded up to the nearest page size by the allocator.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3069
@param aGrowBy       The number of bytes by which the heap will grow when more
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3070
                     memory is required.  This will be rounded up to the nearest
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3071
                     page size by the allocator.  If a value is not explicitly
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3072
                     specified, the page size is taken by default.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3073
@param aMaxLength    The maximum length in bytes to which the heap can grow.  This
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3074
                     will be rounded up to the nearest page size by the allocator.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3075
                     If 0 is passed in, the maximum lengt of the chunk is used.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3076
@param aAlign        From Symbian^4 onwards, this value is ignored but EABI 8
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3077
                     byte alignment is guaranteed for all allocations 8 bytes or
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3078
                     more in size.  4 byte allocations will be aligned to a 4
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3079
                     byte boundary.  Best to pass in zero.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3080
@param aSingleThread ETrue if the heap is to be accessed from multiple threads.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3081
                     This will cause internal locks to be created, guaranteeing
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3082
                     thread safety.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3083
@param aMode         Flags controlling the heap creation.  See RAllocator::TFlags.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3084
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3085
@return A pointer to the new heap or NULL if the heap could not be created.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3086
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3087
@see UserHeap::OffsetChunkHeap()
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3088
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3089
	{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3090
	return OffsetChunkHeap(aChunk, aMinLength, 0, aGrowBy, aMaxLength, aAlign, aSingleThread, aMode);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3091
	}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3092
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3093
EXPORT_C RHeap* UserHeap::OffsetChunkHeap(RChunk aChunk, TInt aMinLength, TInt aOffset, TInt aGrowBy, TInt aMaxLength, TInt aAlign, TBool aSingleThread, TUint32 aMode)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3094
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3095
Creates a heap in an existing chunk, offset from the beginning of the chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3096
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3097
This function is intended to be used to create a heap using a chunk which has
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3098
some of its memory already used, at the start of that that chunk.  The maximum
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3099
length to which the heap can grow is the maximum size of the chunk, minus the
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3100
data at the start of the chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3101
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3102
The offset at which to create the heap is passed in as the aOffset parameter.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3103
Legacy heap implementations always respected the aOffset value, however more
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3104
modern heap implementations are more sophisticated and cannot necessarily respect
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3105
this value.  Therefore, if possible, you should always use an aOffset of 0 unless
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3106
you have a very explicit requirement for using a non zero value.  Using a non zero
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3107
value will result in a less efficient heap algorithm being used in order to respect
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3108
the offset.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3109
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3110
Another issue to consider when using this function is the type of the chunk passed
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3111
in.  In order for the most efficient heap algorithms to be used, the chunk passed
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3112
in should always be a disconnected chunk.  Passing in a non disconnected chunk will
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3113
again result in a less efficient heap algorithm being used.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3114
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3115
Finally, another requirement for the most efficient heap algorithms to be used is
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3116
for the heap to be able to expand.  Therefore, unless you have a specific reason to
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3117
do so, always specify aMaxLength > aMinLength.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3118
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3119
So, if possible, use aOffset == zero, aMaxLength > aMinLength and a disconnected
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3120
chunk for best results!
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3121
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3122
@param aChunk        The chunk that will host the heap.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3123
@param aMinLength    The minimum length of the heap in bytes.  This will be
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3124
                     rounded up to the nearest page size by the allocator.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3125
@param aOffset       The offset in bytes from the start of the chunk at which to
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3126
                     create the heap.  If used (and it shouldn't really be!)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3127
                     then it will be rounded up to a multiple of 8, to respect
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3128
                     EABI 8 byte alignment requirements.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3129
@param aGrowBy       The number of bytes by which the heap will grow when more
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3130
                     memory is required.  This will be rounded up to the nearest
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3131
                     page size by the allocator.  If a value is not explicitly
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3132
                     specified, the page size is taken by default.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3133
@param aMaxLength    The maximum length in bytes to which the heap can grow.  This
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3134
                     will be rounded up to the nearest page size by the allocator.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3135
                     If 0 is passed in, the maximum length of the chunk is used.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3136
@param aAlign        From Symbian^4 onwards, this value is ignored but EABI 8
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3137
                     byte alignment is guaranteed for all allocations 8 bytes or
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3138
                     more in size.  4 byte allocations will be aligned to a 4
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3139
                     byte boundary.  Best to pass in zero.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3140
@param aSingleThread ETrue if the heap is to be accessed from multiple threads.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3141
                     This will cause internal locks to be created, guaranteeing
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3142
                     thread safety.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3143
@param aMode         Flags controlling the heap creation.  See RAllocator::TFlags.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3144
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3145
@return A pointer to the new heap or NULL if the heap could not be created.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3146
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3147
@panic USER 41 if aMaxLength is < aMinLength.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3148
@panic USER 55 if aMinLength is negative.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3149
@panic USER 56 if aMaxLength is negative.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3150
@panic USER 168 if aOffset is negative.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3151
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3152
	{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3153
	TBool dlOnly = EFalse;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3154
	TInt pageSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3155
	GET_PAGE_SIZE(pageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3156
	TInt align = RHybridHeap::ECellAlignment; // Always use EABI 8 byte alignment
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3157
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3158
	__ASSERT_ALWAYS(aMinLength>=0, ::Panic(ETHeapMinLengthNegative));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3159
	__ASSERT_ALWAYS(aMaxLength>=0, ::Panic(ETHeapMaxLengthNegative));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3160
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3161
	if ( aMaxLength > 0 ) 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3162
		__ASSERT_ALWAYS(aMaxLength>=aMinLength, ::Panic(ETHeapCreateMaxLessThanMin));
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3163
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3164
	// Stick to EABI alignment for the start offset, if any
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3165
	aOffset = _ALIGN_UP(aOffset, align);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3166
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3167
	// Using an aOffset > 0 means that we can't use the hybrid allocator and have to revert to Doug Lea only
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3168
	if (aOffset > 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3169
		dlOnly = ETrue;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3170
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3171
	// Ensure that the minimum length is enough to hold the RHybridHeap object itself
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3172
	TInt minCell = _ALIGN_UP(Max((TInt)RHybridHeap::EAllocCellSize, (TInt)RHybridHeap::EFreeCellSize), align);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3173
	TInt hybridHeapSize = (sizeof(RHybridHeap) + minCell);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3174
	if (aMinLength < hybridHeapSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3175
		aMinLength = hybridHeapSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3176
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3177
	// Round the minimum length up to a multiple of the page size, taking into account that the
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3178
	// offset takes up a part of the chunk's memory
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3179
	aMinLength = _ALIGN_UP((aMinLength + aOffset), pageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3180
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3181
	// If aMaxLength is 0 then use the entire chunk
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3182
	TInt chunkSize = aChunk.MaxSize();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3183
	if (aMaxLength == 0)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3184
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3185
		aMaxLength = chunkSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3186
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3187
	// Otherwise round the maximum length up to a multiple of the page size, taking into account that
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3188
	// the offset takes up a part of the chunk's memory.  We also clip the maximum length to the chunk
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3189
	// size, so the user may get a little less than requested if the chunk size is not large enough
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3190
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3191
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3192
		aMaxLength = _ALIGN_UP((aMaxLength + aOffset), pageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3193
		if (aMaxLength > chunkSize)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3194
			aMaxLength = chunkSize;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3195
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3196
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3197
	// If the rounded up values don't make sense then a crazy aMinLength or aOffset must have been passed
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3198
	// in, so fail the heap creation
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3199
	if (aMinLength > aMaxLength)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3200
		return NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3201
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3202
	// Adding the offset into the minimum and maximum length was only necessary for ensuring a good fit of
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3203
	// the heap into the chunk.  Re-adjust them now back to non offset relative sizes
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3204
	aMinLength -= aOffset;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3205
	aMaxLength -= aOffset;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3206
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3207
	// If we are still creating the hybrid allocator (call parameter
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3208
	// aOffset is 0 and aMaxLength > aMinLength), we must reduce heap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3209
	// aMaxLength size to the value aMaxLength/2 and set the aOffset to point in the middle of chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3210
	TInt offset = aOffset;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3211
	TInt maxLength = aMaxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3212
	if (!dlOnly && (aMaxLength > aMinLength))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3213
		maxLength = offset = _ALIGN_UP(aMaxLength >> 1, pageSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3214
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3215
	// Try to use commit to map aMinLength physical memory for the heap, taking into account the offset.  If
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3216
	// the operation fails, suppose that the chunk is not a disconnected heap and try to map physical memory
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3217
	// with adjust.  In this case, we also can't use the hybrid allocator and have to revert to Doug Lea only
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3218
	TBool useAdjust = EFalse;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3219
	TInt r = aChunk.Commit(offset, aMinLength);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3220
	if (r == KErrGeneral)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3221
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3222
		dlOnly = useAdjust = ETrue;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3223
		r = aChunk.Adjust(aMinLength);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3224
		if (r != KErrNone)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3225
			return NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3226
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3227
	else if (r == KErrNone)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3228
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3229
		// We have a disconnected chunk reset aOffset and aMaxlength
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3230
		aOffset = offset;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3231
		aMaxLength = maxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3232
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3233
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3234
	else
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3235
		return NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3236
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3237
	// Parameters have been mostly verified and we know whether to use the hybrid allocator or Doug Lea only.  The
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3238
	// constructor for the hybrid heap will automatically drop back to Doug Lea if it determines that aMinLength
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3239
	// == aMaxLength, so no need to worry about that requirement here.  The user specified alignment is not used but
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3240
	// is passed in so that it can be sanity checked in case the user is doing something totally crazy with it
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3241
	RHybridHeap* h = new (aChunk.Base() + aOffset) RHybridHeap(aChunk.Handle(), aOffset, aMinLength, aMaxLength,
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3242
		aGrowBy, aAlign, aSingleThread, dlOnly, useAdjust);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3243
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3244
	if (h->ConstructLock(aMode) != KErrNone)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3245
		return NULL;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3246
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3247
	// Return the heap address
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3248
	return h;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3249
	}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3250
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3251
#define UserTestDebugMaskBit(bit) (TBool)(UserSvr::DebugMask(bit>>5) & (1<<(bit&31)))
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3252
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3253
_LIT(KLitDollarHeap,"$HEAP");
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3254
EXPORT_C TInt UserHeap::CreateThreadHeap(SStdEpocThreadCreateInfo& aInfo, RHeap*& aHeap, TInt aAlign, TBool aSingleThread)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3255
/**
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3256
@internalComponent
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3257
*/
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3258
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3259
// Create a user-side heap
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3260
//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3261
{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3262
	TInt page_size;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3263
	GET_PAGE_SIZE(page_size);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3264
	TInt minLength = _ALIGN_UP(aInfo.iHeapInitialSize, page_size);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3265
	TInt maxLength = Max(aInfo.iHeapMaxSize, minLength);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3266
	if (UserTestDebugMaskBit(96)) // 96 == KUSERHEAPTRACE in nk_trace.h
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3267
		aInfo.iFlags |= ETraceHeapAllocs;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3268
	// Create the thread's heap chunk.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3269
	RChunk c;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3270
	TChunkCreateInfo createInfo;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3271
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3272
	createInfo.SetThreadHeap(0, maxLength, KLitDollarHeap());	// Initialise with no memory committed.	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3273
#if USE_HYBRID_HEAP
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3274
	//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3275
	// Create disconnected chunk for hybrid heap with double max length value
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3276
	//
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3277
	maxLength = 2*maxLength;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3278
	createInfo.SetDisconnected(0, 0, maxLength);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3279
#endif	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3280
	// Set the paging policy of the heap chunk based on the thread's paging policy.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3281
	TUint pagingflags = aInfo.iFlags & EThreadCreateFlagPagingMask;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3282
	switch (pagingflags)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3283
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3284
		case EThreadCreateFlagPaged:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3285
			createInfo.SetPaging(TChunkCreateInfo::EPaged);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3286
			break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3287
		case EThreadCreateFlagUnpaged:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3288
			createInfo.SetPaging(TChunkCreateInfo::EUnpaged);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3289
			break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3290
		case EThreadCreateFlagPagingUnspec:
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3291
			// Leave the chunk paging policy unspecified so the process's 
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3292
			// paging policy is used.
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3293
			break;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3294
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3295
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3296
	TInt r = c.Create(createInfo);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3297
	if (r!=KErrNone)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3298
		return r;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3299
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3300
	aHeap = ChunkHeap(c, minLength, page_size, maxLength, aAlign, aSingleThread, EChunkHeapSwitchTo|EChunkHeapDuplicate);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3301
	c.Close();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3302
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3303
	if ( !aHeap )
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3304
		return KErrNoMemory;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3305
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3306
	if (aInfo.iFlags & ETraceHeapAllocs)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3307
		{
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3308
		aHeap->iFlags |= RHeap::ETraceAllocs;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3309
    	BTraceContext8(BTrace::EHeap, BTrace::EHeapCreate,(TUint32)aHeap, RHybridHeap::EAllocCellSize);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3310
		TInt chunkId = ((RHandleBase&)((RHybridHeap*)aHeap)->iChunkHandle).BTraceId();
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3311
		BTraceContext8(BTrace::EHeap, BTrace::EHeapChunkCreate, (TUint32)aHeap, chunkId);
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3312
		}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3313
	if (aInfo.iFlags & EMonitorHeapMemory)
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3314
		aHeap->iFlags |= RHeap::EMonitorMemory;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3315
	
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3316
	return KErrNone;
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3317
}
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3318
d9f1e5bfe28c 201021_18
hgs
parents:
diff changeset
  3319
#endif  // __KERNEL_MODE__