diff -r 000000000000 -r 7f656887cf89 commands/leak/leak.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/leak/leak.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,169 @@ +// leak.cpp +// +// Copyright (c) 2007 - 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 "leak.h" +#include + +const TInt KMinChunkSize = 4 * 1024; +const TInt KMaxChunkSize = 512 * 1024 * 1024; + +CCommandBase* CCmdLeak::NewLC() + { + CCmdLeak* self = new(ELeave) CCmdLeak(); + CleanupStack::PushL(self); + self->BaseConstructL(); + return self; + } + +CCmdLeak::~CCmdLeak() + { + iChunk.Close(); + if (iChunkHeap) + { + iChunkHeap->Reset(); + iChunkHeap->Close(); + } + } + +CCmdLeak::CCmdLeak() + { + } + +const TDesC& CCmdLeak::Name() const + { + _LIT(KName, "leak"); + return KName; + } + +void CCmdLeak::DoRunL() + { + if ((iAmount < 0) || (iIncrementAmount < 0)) + { + User::Leave(KErrArgument); + } + + if (iArguments.IsPresent(0)) + { + if (iIncrementAmount == 0) + { + iIncrementAmount = iAmount; + } + } + else + { + iAmount = KMaxTInt; + if (iIncrementAmount == 0) + { + iIncrementAmount = KMinChunkSize; + } + } + + if (iUseHeap) + { + iChunkHeap = UserHeap::ChunkHeap(NULL, KMinChunkSize, 256*1024*1024); + if (!iChunkHeap) LeaveIfErr(KErrNoMemory, _L("Couldn't create chunk heap")); + } + else + { + if (iIncrementAmount & 4095) LeaveIfErr(KErrArgument, _L("increment-amount must be a multiple of 4096")); + TInt err = iChunk.CreateLocal(KMinChunkSize, KMaxChunkSize); + LeaveIfErr(err, _L("Failed to create local chunk")); + } + + RIoConsoleWriteHandle stdout = Stdout(); + stdout.SetCursorHeight(0); + TInt err = KErrNone; + do + { + err = LeakStep(Min(iIncrementAmount, iAmount - iCurrentLeak)); + if (iVerbose) + { + Write(_L("\r")); + stdout.ClearToEndOfLine(); + Printf(_L("Allocated %d: %d"), iCurrentLeak, err); + } + if (err && iRetry && iIncrementAmount > 4) + { + // Keep going with a smaller increment + err = KErrNone; + iIncrementAmount /= 2; + continue; + } + + if (iRate > 0) + { + User::After(iRate * 1000); + } + } + while ((err == KErrNone) && (iCurrentLeak < iAmount)); + + if (err == KErrNoMemory) + { + Printf(_L("Out of memory. ")); + } + else if (err) + { + Printf(_L("Error: %d. "), err); + } + + Printf(_L("\r\nLeaked %d bytes. Press any key to exit (and free the memory).\r\n"), iCurrentLeak); + + RIoConsoleReadHandle stdin = Stdin(); + stdin.ReadKey(); + } + +void CCmdLeak::OptionsL(RCommandOptionList& aOptions) + { + _LIT(KOptVerbose, "verbose"); + aOptions.AppendBoolL(iVerbose, KOptVerbose); + + _LIT(KOptIncrementAmount, "increment-amount"); + aOptions.AppendIntL(iIncrementAmount, KOptIncrementAmount); + + _LIT(KOptRate, "rate"); + aOptions.AppendUintL(iRate, KOptRate); + + _LIT(KOptUseHeap, "heap"); + aOptions.AppendBoolL(iUseHeap, KOptUseHeap); + + _LIT(KOptRetry, "retry"); + aOptions.AppendBoolL(iRetry, KOptRetry); + } + +void CCmdLeak::ArgumentsL(RCommandArgumentList& aArguments) + { + _LIT(KArgAmount, "amount"); + aArguments.AppendIntL(iAmount, KArgAmount); + } + + +#ifdef EXE_BUILD +EXE_BOILER_PLATE(CCmdLeak) +#endif + +TInt CCmdLeak::LeakStep(TInt aAmount) + { + TInt err = KErrNone; + if (iChunkHeap) + { + TAny* cell = iChunkHeap->Alloc(aAmount); + if (!cell) err = KErrNoMemory; + } + else + { + if (aAmount < 4096) err = KErrNoMemory; // implies we're retrying - unlike the others that keep retrying down to 4 bytes, we have to stop at page granularity + else err = iChunk.Adjust(iCurrentLeak + aAmount); + } + + if (!err) iCurrentLeak += aAmount; + return err; + }