diff -r 000000000000 -r 7f656887cf89 libraries/ltkutils/tsrc/tallochelper.cpp --- /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 +#include +#include +#include + +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 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(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(aContext); + self->iAllocationsAccordingToRHeapWalker += aLength; + } + }