kernel/eka/common/alloc.cpp
changeset 0 a41df078684a
child 109 b3a1d9898418
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/common/alloc.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,524 @@
+// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\common\alloc.cpp
+// 
+//
+
+#include "common.h"
+#include <e32atomics.h>
+
+
+
+#ifndef __KERNEL_MODE__
+/**
+Opens this heap for shared access.
+
+Opening the heap increases the heap's access count by one.
+
+@return KErrNone if successful;
+        KErrGeneral, if the original valeu of the access count
+        was not positive.
+*/
+EXPORT_C TInt RAllocator::Open()
+	{
+	TInt c = __e32_atomic_tas_ord32(&iAccessCount, 1, 1, 0);
+	return (c>0) ? KErrNone : KErrGeneral;
+	}
+
+
+
+
+/**
+Closes this shared heap.
+
+Closing the heap decreases the heap's access count by one.
+
+@panic USER 57 if the access count has already reached zero.
+*/
+EXPORT_C void RAllocator::Close()
+	{
+	TInt count = __e32_atomic_tas_ord32(&iAccessCount, 1, -1, 0);
+	__ASSERT_ALWAYS(count>0, Panic(EAllocatorClosedTooManyTimes));
+	if (count==1)
+		DoClose();
+	}
+
+
+
+/**
+@internalComponent
+*/
+EXPORT_C void RAllocator::DoClose()
+	{
+	__ASSERT_ALWAYS(TUint32(iHandleCount)<=TUint32(EMaxHandles), Panic(EAllocatorBadHandleCount));
+	TInt handle[EMaxHandles];
+	TInt c = iHandleCount;
+	wordmove(handle, iHandles, c*sizeof(TInt));
+	memclr(iHandles, c*sizeof(TInt));
+	TInt* pH = handle;
+	TInt* pE = pH + c;
+	while (pH<pE)
+		{
+		RHandleBase h;
+		h.SetHandle(*pH++);
+		h.Close();
+		}
+	}
+
+
+
+
+/**
+Allocates a cell of specified size from the heap, and clears
+it to binary zeroes.
+
+If there is insufficient memory available on the heap from which to
+allocate a cell of the required size, the function returns NULL.
+
+The resulting size of the allocated cell may be rounded up to a value greater 
+than aSize, but is guaranteed to be not less than aSize.
+
+@param aSize The size of the cell to be allocated from the current thread's 
+             heap.
+             
+@return A pointer to the allocated cell. NULL, if there is insufficient memory 
+        available.
+        
+@panic USER 47  if the maximum unsigned value of aSize is greater
+                than or equal to KMaxTInt/2. For example,
+                calling Alloc(-1) raises this panic.
+*/
+EXPORT_C TAny* RAllocator::AllocZ(TInt aSize)
+	{
+	TAny* p = Alloc(aSize);
+	if (p)
+		Mem::FillZ(p, aSize);
+	return p;
+	}
+
+
+
+
+/**
+Allocates a cell of specified size from the heap, clears it to
+binary zeroes, and leaves if there is insufficient memory in the heap.
+
+The resulting size of the allocated cell may be rounded up to a value greater 
+than aSize, but is guaranteed to be not less than aSize.
+
+@param aSize The size of the cell to be allocated from the heap.
+
+@return A pointer to the allocated cell.
+ 
+@panic USER 47  if the maximum unsigned value of aSize is greater
+                than or equal to KMaxTInt/2. For example,
+                calling Alloc(-1) raises this panic.
+*/
+EXPORT_C TAny* RAllocator::AllocZL(TInt aSize)
+	{
+	TAny* p = AllocL(aSize);
+	Mem::FillZ(p, aSize);
+	return p;
+	}
+
+
+
+
+/**
+Allocates a cell of specified size from the heap, and leaves 
+if there is insufficient memory in the heap.
+
+The resulting size of the allocated cell may be rounded up to a value greater 
+than aSize, but is guaranteed to be not less than aSize.
+
+@param aSize The size of the cell to be allocated from the heap.
+
+@return A pointer to the allocated cell.
+
+@panic USER 47  if the maximum unsigned value of aSize is greater
+                than or equal to KMaxTInt/2. For example,
+                calling Alloc(-1) raises this panic.
+*/
+EXPORT_C TAny* RAllocator::AllocL(TInt aSize)
+	{
+	TAny* p = Alloc(aSize);
+	if (!p)
+		User::LeaveNoMemory();
+	return p;
+	}
+
+
+
+
+/**
+Allocates a cell of specified size from the heap, and,
+if successful, places a pointer to the cell onto the cleanup stack.
+
+The function leaves if there is insufficient memory in the heap.
+
+The resulting size of the allocated cell may be rounded up to a value greater 
+than aSize, but is guaranteed to be not less than aSize.
+
+@param aSize The size of the cell to be allocated from the heap.
+             
+@return A pointer to the allocated cell.
+
+@panic USER 47  if the maximum unsigned value of aSize is greater
+                than or equal to KMaxTInt/2. For example,
+                calling Alloc(-1) raises this panic.
+*/
+EXPORT_C TAny* RAllocator::AllocLC(TInt aSize)
+	{
+	TAny* p = AllocL(aSize);
+	CleanupStack::PushL(p);
+	return p;
+	}
+
+
+
+
+/**
+Frees the specified cell, returns it to the heap, and resets 
+the pointer to NULL.
+
+@param aCell A reference to a pointer to a valid cell to be freed. If NULL 
+             this function call will be ignored.
+             
+@panic USER 42  if aCell is not NULL and does not point to a valid cell.             
+*/
+EXPORT_C void RAllocator::FreeZ(TAny*& aCell)
+	{
+	Free(aCell);
+	aCell = NULL;
+	}
+
+
+
+
+/**
+Increases or decreases the size of an existing cell, and leaves 
+if there is insufficient memory in the heap.
+
+If the cell is being decreased in size, then it is guaranteed not to move,
+and the function returns the pointer originally passed in aCell. Note that the
+length of the cell will be the same if the difference between the old size
+and the new size is smaller than the minimum cell size.
+
+If the cell is being increased in size, i.e. aSize is bigger than its
+current size, then the function tries to grow the cell in place.
+If successful, then the function returns the pointer originally
+passed in aCell. If unsuccessful, then:
+
+1. if the cell cannot be moved, i.e. aMode has the ENeverMove bit set, then
+   the function leaves.
+2. if the cell can be moved, i.e. aMode does not have the ENeverMove bit set,
+   then the function tries to allocate a new replacement cell, and, if
+   successful, returns a pointer to the new cell; if unsuccessful, it
+   leaves.
+
+Note that in debug mode, the function leaves if the cell cannot be grown
+in place, regardless of whether the ENeverMove bit is set.
+
+If the reallocated cell is at a different location from the original cell, then
+the content of the original cell is copied to the reallocated cell.
+
+Note the following general points:
+
+1. If reallocation fails, the content of the original cell is preserved.
+
+2. The resulting size of the re-allocated cell may be rounded up to a value
+   greater than aSize, but is guaranteed to be not less than aSize.
+
+@param aCell A pointer to the cell to be reallocated. This may be NULL.
+
+@param aSize The new size of the cell. This may be bigger or smaller than the
+             size of the original cell.
+             
+@param aMode Flags controlling the reallocation. The only bit which has any
+             effect on this function is that defined by the enumeration
+             ENeverMove of the enum RAllocator::TReAllocMode.
+             If this is set, then any successful reallocation guarantees not
+             to have changed the start address of the cell.
+             By default, this parameter is zero.
+
+@return A pointer to the reallocated cell. This may be the same as the original
+        pointer supplied through aCell.
+
+@panic USER 42, if aCell is not NULL, and does not point to a valid cell.
+@panic USER 47, if the maximum unsigned value of aSize is greater
+                than or equal to KMaxTInt/2. For example,
+                calling ReAlloc(someptr,-1) raises this panic.
+
+@see RAllocator::TReAllocMode
+*/
+EXPORT_C TAny* RAllocator::ReAllocL(TAny* aCell, TInt aSize, TInt aMode)
+	{
+	TAny* p = ReAlloc(aCell, aSize, aMode);
+	if (!p)
+		User::LeaveNoMemory();
+	return p;
+	}
+
+
+
+
+/**
+Gets the total number of cells allocated on the heap.
+
+@return The number of cells allocated on the heap.
+*/
+EXPORT_C TInt RAllocator::Count() const
+	{
+	return iCellCount;
+	}
+
+
+
+
+/**
+Gets the the total number of cells allocated, and the number of free cells, 
+on the heap.
+
+@param aFreeCount On return, contains the number of free cells 
+                  on the heap.
+
+@return The number of cells allocated on the heap.
+*/
+EXPORT_C TInt RAllocator::Count(TInt& aFreeCount) const
+	{
+	return ((RAllocator*)this)->DebugFunction(ECount, &aFreeCount);
+	}
+#endif
+
+
+
+
+/**
+Checks the validity of the heap.
+
+The function walks through the list of allocated cells and the list of
+free cells checking that this heap is consistent and complete.
+
+@panic USER 47 if any corruption is found, specifically	a bad allocated
+               heap cell size.
+@panic USER 48 if any corruption is found, specifically a bad allocated
+               heap cell address.
+@panic USER 49 if any corruption is found, specifically a bad free heap
+               cell address.
+*/
+UEXPORT_C void RAllocator::Check() const
+	{
+	((RAllocator*)this)->DebugFunction(ECheck);
+	}
+
+
+
+
+/**
+Marks the start of heap cell checking for this heap.
+
+If earlier calls to __DbgMarkStart() have been made, then this call
+to __DbgMarkStart() marks the start of a new nested level of
+heap cell checking.
+
+Every call to __DbgMarkStart() should be matched by a later call
+to __DbgMarkEnd() to verify that the number of heap cells allocated,
+at the current nested level, is as expected. This expected number of heap cells
+is passed to __DbgMarkEnd() as a parameter; however, the most common expected
+number is zero, reflecting the fact that most developers check that all memory
+allocated since a previous call to __DbgMarkStart() has been freed.
+
+@see RAllocator::__DbgMarkEnd()
+*/
+UEXPORT_C void RAllocator::__DbgMarkStart()
+	{
+	DebugFunction(EMarkStart);
+	}
+
+
+
+
+/**
+Marks the end of heap cell checking at the current nested level for this heap.
+
+A call to this function should match an earlier call to __DbgMarkStart().
+If there are more calls to this function than calls to __DbgMarkStart(),
+then this function raises a USER 51 panic.
+
+The function checks that the number of heap cells allocated, at the current
+nested level, is aCount. The most common value for aCount is zero, reflecting
+the fact that most developers check that all memory allocated since a previous
+call to __DbgMarkStart() has been freed.
+
+If the check fails, the function returns a pointer to the first orphaned
+heap cell.
+
+@param aCount The number of allocated heap cells expected.
+
+@return A pointer to the first orphaned heap cell, if verification fails;
+        zero otherwise.
+
+@see RAllocator::__DbgMarkStart()
+*/
+UEXPORT_C TUint32 RAllocator::__DbgMarkEnd(TInt aCount)
+	{
+	return DebugFunction(EMarkEnd, (TAny*)aCount);
+	}
+
+
+
+
+/**
+Checks the current number of allocated heap cells for this heap.
+
+If aCountAll is true, the function checks that the total number of allocated
+cells on this heap is the same as aCount. If aCountAll is false, then
+the function checks that the number of allocated cells at the current nested
+level is the same as aCount.
+
+If checking fails, the function raises a panic;
+information about the failure is put into the panic category;
+this takes the form:
+
+ALLOC COUNT\\rExpected aaa\\rAllocated bbb\\rLn: ccc ddddd
+
+where
+
+1. aaaa is the value aCount
+
+2. bbbb is the number of allocated heap cells
+
+3. ccc is a line number, copied from aLineNum
+
+4. ddddd is a file name, copied from the descriptor aFileName
+
+Note that the panic number is 1.
+
+@param aCountAll If true, the function checks that the total number of
+                 allocated cells on this heap is the same as aCount.
+                 If false, the function checks that the number of allocated
+                 cells at the current nested level is the same as aCount.
+@param aCount    The expected number of allocated cells.
+@param aFileName A filename; this is displayed as part of the panic
+                 category if the check fails.
+@param aLineNum  A line number; this is displayed as part of the panic category 
+                 if the check fails.
+
+@return KErrNone, if successful; otherwise one of the other system wide error codes.
+*/
+UEXPORT_C TInt RAllocator::__DbgMarkCheck(TBool aCountAll, TInt aCount, const TDesC8& aFileName, TInt aLineNum)
+	{
+	SCheckInfo info;
+	info.iAll = aCountAll;
+	info.iCount = aCount;
+	info.iFileName = &aFileName;
+	info.iLineNum = aLineNum;
+	return DebugFunction(ECheck, &info);
+	}
+
+
+
+
+/**
+Simulates a heap allocation failure for this heap.
+
+The failure occurs on subsequent calls to new or any of the functions which
+allocate memory from this heap.
+
+The timing of the allocation failure depends on the type of 
+allocation failure requested, i.e. on the value of aType.
+
+The simulation of heap allocation failure is cancelled
+if aType is given the value RAllocator::ENone.
+
+Notes:
+
+1. If the failure type is RAllocator::EFailNext, the next attempt to allocate from
+   this heap fails; however, no further failures will occur.
+
+2. For failure types RAllocator::EFailNext and RAllocator::ENone, set aRate to 1.
+
+@param aType  An enumeration which indicates how to simulate heap
+              allocation failure.
+@param aRate The rate of failure; when aType is RAllocator::EDeterministic,
+              heap allocation fails every aRate attempts
+*/
+UEXPORT_C void RAllocator::__DbgSetAllocFail(TAllocFail aType, TInt aRate)
+	{
+	DebugFunction(ESetFail, (TAny*)aType, (TAny*)aRate);
+	}
+
+
+/**
+Simulates a burst of heap allocation failures for this heap.
+
+The failure occurs for aBurst allocations attempt via subsequent calls 
+to new or any of the functions which allocate memory from this heap.
+
+The timing of the allocation failure depends on the type of 
+allocation failure requested, i.e. on the value of aType.
+
+The simulation of heap allocation failure is cancelled
+if aType is given the value RAllocator::ENone.
+
+Notes:
+
+1. If the failure type is RAllocator::EFailNext or RAllocator::EBurstFailNext, 
+the next one or aBurst attempts to allocate from this heap will fail; 
+however, no further failures will occur.
+
+2. For failure types RAllocator::EFailNext and RAllocator::ENone, set aRate to 1.
+
+@param aType  An enumeration which indicates how to simulate heap
+              allocation failure.
+@param aRate The rate of failure; when aType is RAllocator::EDeterministic,
+              heap allocation fails every aRate attempts.
+@param aBurst The number of consecutive heap allocations that will fail each
+time the allocations should fail.
+
+@see RAllocator::TAllocFail
+*/
+UEXPORT_C void RAllocator::__DbgSetBurstAllocFail(TAllocFail aType, TUint aRate, TUint aBurst)
+	{
+	SRAllocatorBurstFail burstFail;
+	burstFail.iRate = aRate;
+	burstFail.iBurst = aBurst;
+	DebugFunction(ESetBurstFail, (TAny*)aType, (TAny*)&burstFail);
+	}
+
+/**
+Returns the number of heap allocation failures the current debug allocator fail
+function has caused so far.
+
+This is intended to only be used with fail types RAllocator::EFailNext,
+RAllocator::EBurstFailNext, RAllocator::EDeterministic and
+RAllocator::EBurstDeterministic.  The return value is unreliable for 
+all other fail types.
+
+@return The number of heap allocation failures the current debug fail 
+function has caused.
+
+@see RAllocator::TAllocFail
+*/
+UEXPORT_C TUint RAllocator::__DbgCheckFailure()
+	{
+	return DebugFunction(ECheckFailure);
+	}
+
+
+UEXPORT_C TInt RAllocator::Extension_(TUint, TAny*& a0, TAny*)
+	{
+	a0 = NULL;
+	return KErrExtensionNotSupported;
+	}