libraries/ltkutils/tsrc/tallochelper.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/ltkutils/tsrc/tallochelper.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,219 @@
+// tallochelper.cpp
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "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:
+// Accenture - Initial contribution
+//
+
+#include <fshell/ioutils.h>
+#include <fshell/common.mmh>
+#include <fshell/heaputils.h>
+#include <fshell/ltkutils.h>
+
+using namespace IoUtils;
+using LtkUtils::RAllocatorHelper;
+
+class CCmdTAllocHelper : public CCommandBase
+	{
+public:
+	static CCommandBase* NewLC();
+	~CCmdTAllocHelper();
+private:
+	CCmdTAllocHelper();
+	void PrintStats(const TDesC& aDesc);
+
+	void AllocL(TInt aSize, TInt aNumber=1);
+	void Free(TInt aNumber=1);
+	void FormatSize(TDes& aBuf, TInt64 aSize);
+	static TBool WalkCallback(RAllocatorHelper& aAlloc, TAny* aContext, RAllocatorHelper::TExtendedCellType aType, TLinAddr aAddress, TInt aLength);
+	static void RHeapWalkCallback(TAny* aContext, RHeap::TCellType aType, TAny* aCell, TInt aLength);
+
+private: // From CCommandBase.
+	virtual const TDesC& Name() const;
+	virtual const TDesC& Description() const;
+	virtual void DoRunL();
+	virtual void ArgumentsL(RCommandArgumentList& aArguments);
+	virtual void OptionsL(RCommandOptionList& aOptions);
+private:
+	RAllocatorHelper iAlloc;
+	RArray<TAny*> iAllocations;
+	TBool iBytes;
+	TBool iWaitOnExit;
+
+	TInt iAllocationsAccordingToRHeapWalker;
+	};
+
+EXE_BOILER_PLATE(CCmdTAllocHelper)
+
+CCommandBase* CCmdTAllocHelper::NewLC()
+	{
+	CCmdTAllocHelper* self = new(ELeave) CCmdTAllocHelper();
+	CleanupStack::PushL(self);
+	self->BaseConstructL();
+	return self;
+	}
+
+CCmdTAllocHelper::~CCmdTAllocHelper()
+	{
+	iAlloc.Close();
+	Free(iAllocations.Count());
+	iAllocations.Close();
+	}
+
+CCmdTAllocHelper::CCmdTAllocHelper()
+	: CCommandBase(EManualComplete)
+	{
+	}
+
+const TDesC& CCmdTAllocHelper::Name() const
+	{
+	_LIT(KName, "tallochelper");	
+	return KName;
+	}
+
+const TDesC& CCmdTAllocHelper::Description() const
+	{
+	_LIT(KDescription, "Test code for RAllocatorHelper");
+	return KDescription;
+	}
+
+void CCmdTAllocHelper::ArgumentsL(RCommandArgumentList& /*aArguments*/)
+	{
+	}
+
+void CCmdTAllocHelper::OptionsL(RCommandOptionList& aOptions)
+	{
+	aOptions.AppendBoolL(iBytes, 'b', _L("bytes"), _L("Display sizes in bytes rather than rounded off KB or MB"));
+	aOptions.AppendBoolL(iWaitOnExit, 'w', _L("wait"), _L("Wait indefinitely before exiting - for testing remote heap walking"));
+	}
+
+void CCmdTAllocHelper::DoRunL()
+	{
+	LeaveIfErr(iAlloc.Open(&User::Allocator()), _L("Couldn't open RAllocatorHelper"));
+	iAllocations.ReserveL(128);
+
+	Printf(_L("Udeb allocator=%d\r\n"), iAlloc.AllocatorIsUdeb());
+
+	PrintStats(_L("Initial stats"));
+	// And do an RHeap walk, just to compare
+	User::Allocator().DebugFunction(128, (TAny*)&RHeapWalkCallback, this);
+	Printf(_L("allocated size according to RHeap::Walk: %d\r\n"), iAllocationsAccordingToRHeapWalker);
+
+	AllocL(64*1024);
+	PrintStats(_L("Stats after 1 64K alloc"));
+	User::Allocator().DebugFunction(128, (TAny*)&RHeapWalkCallback, this); // debug
+
+
+	AllocL(4, 50);
+	PrintStats(_L("Stats after 50 small allocs"));
+
+	/*
+	// Open a new RAllocatorHelper cos the stats will be cached otherwise
+	RAllocatorHelper h; h.Open(&User::Allocator());
+	iAllocationsAccordingToRHeapWalker = 0;
+	User::Allocator().DebugFunction(128, (TAny*)&RHeapWalkCallback, this);
+	Printf(_L("allocated size according to RHeap::Walk: %d\r\n"), iAllocationsAccordingToRHeapWalker);
+	Printf(_L("iTotalAllocSize is %d\r\n"), h.AllocatedSize());
+	h.Close();
+	*/
+
+	if (!iWaitOnExit)
+		{
+		Free(50);
+		PrintStats(_L("Stats after freeing them"));
+		Complete();
+		}
+	}
+
+void CCmdTAllocHelper::PrintStats(const TDesC& aDesc)
+	{
+	iAlloc.RefreshDetails();
+	TBuf<16> allocSize, freeSize, dlaSize, slabSize, freeDlaSize, partiallyFreeSlabSize, freeSlabSize, pageSize;
+	FormatSize(allocSize, iAlloc.SizeForCellType(RAllocatorHelper::EAllocationMask));
+	FormatSize(freeSize, iAlloc.SizeForCellType(RAllocatorHelper::EFreeMask));
+	FormatSize(dlaSize, iAlloc.SizeForCellType(RAllocatorHelper::EDlaAllocation));
+	FormatSize(slabSize, iAlloc.SizeForCellType(RAllocatorHelper::ESlabAllocation));
+	FormatSize(freeDlaSize, iAlloc.SizeForCellType(RAllocatorHelper::EDlaFreeCell));
+	FormatSize(partiallyFreeSlabSize, iAlloc.SizeForCellType(RAllocatorHelper::ESlabFreeCell));
+	FormatSize(freeSlabSize, iAlloc.SizeForCellType(RAllocatorHelper::ESlabFreeSlab));
+	FormatSize(pageSize, iAlloc.SizeForCellType(RAllocatorHelper::EPageAllocation));
+
+	Printf(_L("\r\n%S:\r\n\
+Alloc: %d (%S), DLA: %d (%S) Slab: %d (%S) Paged: %d (%S)\r\n\
+Free: %d (%S), DLA: %d (%S) Slab: %d (%S) Free slabs: %d (%S)\r\n"), 
+		&aDesc, iAlloc.AllocationCount(), &allocSize,
+		iAlloc.CountForCellType(RAllocatorHelper::EDlaAllocation), &dlaSize,
+		iAlloc.CountForCellType(RAllocatorHelper::ESlabAllocation), &slabSize,
+		iAlloc.CountForCellType(RAllocatorHelper::EPageAllocation), &pageSize,
+		iAlloc.CountForCellType(RAllocatorHelper::EFreeMask), &freeSize,
+		iAlloc.CountForCellType(RAllocatorHelper::EDlaFreeCell), &freeDlaSize,
+		iAlloc.CountForCellType(RAllocatorHelper::ESlabFreeCell), &partiallyFreeSlabSize,
+		iAlloc.CountForCellType(RAllocatorHelper::ESlabFreeSlab), &freeSlabSize
+		);
+
+	iAlloc.Walk(&WalkCallback, this); // Check cell lengths match up
+	}
+
+void CCmdTAllocHelper::AllocL(TInt aSize, TInt aNumber)
+	{
+	while (aNumber--)
+		{
+		TAny* result = User::AllocL(aSize);
+		TInt err = iAllocations.Append(result);
+		if (err)
+			{
+			User::Free(result);
+			User::Leave(KErrNoMemory);
+			}
+		}
+	}
+
+void CCmdTAllocHelper::Free(TInt aNumber)
+	{
+	while (aNumber--)
+		{
+		TInt i = iAllocations.Count() - 1;
+		User::Free(iAllocations[i]);
+		iAllocations.Remove(i);
+		}
+	}
+
+void CCmdTAllocHelper::FormatSize(TDes& aBuf, TInt64 aSize)
+	{
+	if (iBytes)
+		{
+		aBuf.Num(aSize);
+		}
+	else
+		{
+		LtkUtils::FormatSize(aBuf, aSize);
+		}
+	}
+
+TBool CCmdTAllocHelper::WalkCallback(RAllocatorHelper& /*aAlloc*/, TAny* aContext, RAllocatorHelper::TExtendedCellType aType, TLinAddr aAddress, TInt aLength)
+	{
+	if (aType & RAllocatorHelper::EAllocationMask)
+		{
+		TInt lenFromAllocLen = User::AllocLen((TAny*)aAddress);
+		if (lenFromAllocLen != aLength)
+			{
+			static_cast<CCmdTAllocHelper*>(aContext)->PrintWarning(_L("Walker reports cell 0x%08x size %d but AllocLen says %d\r\n"), aAddress, aLength, lenFromAllocLen);
+			}
+		}
+
+	return ETrue; // Keep walking
+	}
+
+void CCmdTAllocHelper::RHeapWalkCallback(TAny* aContext, RHeap::TCellType aType, TAny* aCell, TInt aLength)
+	{
+	if (aType == RHeap::EGoodAllocatedCell)
+		{
+		CCmdTAllocHelper* self = static_cast<CCmdTAllocHelper*>(aContext);
+		self->iAllocationsAccordingToRHeapWalker += aLength;
+		}
+	}