diff -r 000000000000 -r 96e5fb8b040d kerneltest/e32test/mmu/d_gobble.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/mmu/d_gobble.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,276 @@ +// Copyright (c) 2007-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: +// e32test\misc\d_gobble.cpp +// LDD for gobbling RAM +// +// + +#include "platform.h" +#include +#include "d_gobble.h" + +const TInt KMajorVersionNumber=0; +const TInt KMinorVersionNumber=1; +const TInt KBuildVersionNumber=1; + +class DGobblerFactory : public DLogicalDevice +// +// Gobbler LDD factory +// + { +public: + DGobblerFactory(); + ~DGobblerFactory(); + virtual TInt Install(); + virtual void GetCaps(TDes8& aDes) const; + virtual TInt Create(DLogicalChannelBase*& aChannel); + }; + +class DGobbler : public DLogicalChannelBase +// +// RAM Gobbler LDD channel +// + { +public: + DGobbler(); + virtual ~DGobbler(); +private: + virtual TInt Request(TInt aFunc, TAny* a1, TAny* a2); + virtual TInt DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer); +private: + enum {ESmallBufferSize = 64}; + + TUint32 Gobble(TUint32 aLeave); +#ifdef __EPOC32__ + TInt GobbleMultiPages(TUint32& aTake, TUint32* aMultiPageBuf, TInt aMaxMultiPages); + void FreeMultiPage(TPhysAddr aMultiPage); + TUint32 AllocMultiPage(TUint32 aSize); + TUint32 Size(TUint32 aMultiPage); +#endif +private: +#ifdef __EPOC32__ + TPhysAddr iPhys[ESmallBufferSize]; +#endif + DChunk* iSharedChunk; + TUint32 iPageShift; + TUint32 iPageSize; + }; + +DGobblerFactory::DGobblerFactory() + { + iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); + //iParseMask=0;//No units, no info, no PDD + //iUnitsMask=0;//Only one thing + } + +DGobblerFactory::~DGobblerFactory() + { + } + +TInt DGobblerFactory::Create(DLogicalChannelBase*& aChannel) + { + aChannel = new DGobbler; + return aChannel ? KErrNone : KErrNoMemory; + } + +TInt DGobblerFactory::Install() +// +// Install the LDD - overriding pure virtual +// + { + return SetName(&KGobblerLddName); + } + +void DGobblerFactory::GetCaps(TDes8& aDes) const +// +// Get capabilities - overriding pure virtual +// + { + TCapsGobblerV01 b; + b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); + Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b)); + } + +DGobbler::DGobbler() + { + iPageSize = Kern::RoundToPageSize(1); + iPageShift = __e32_find_ms1_32(iPageSize); + } + +DGobbler::~DGobbler() + { + // Free all the RAM we've gobbled + +#ifdef __EPOC32__ + // Free the addresses held in the shared chunk + if (iSharedChunk) + { + TLinAddr ka; + TInt r = Kern::ChunkAddress(iSharedChunk, 0, 1, ka); + if (r==KErrNone) + { + const TUint32* p = (const TUint32*)ka; + const TUint32* pE = p + (iSharedChunk->Size() / sizeof(TUint32)); + while (p>iPageShift) << iPageShift; + TUint32 size = Size(aMultiPage); + Epoc::FreePhysicalRam(base, size); + } + +TUint32 DGobbler::AllocMultiPage(TUint32 aSize) + { + TUint32 sz = 1u << __e32_find_ms1_32(aSize); // round size down to power of 2 + while (sz > iPageSize) + { + TPhysAddr pa; + TInt r = Epoc::AllocPhysicalRam(sz, pa); + if (r == KErrNone) + return pa | __e32_find_ms1_32(sz); + sz >>= 1; + } + return 0; + } + +TUint32 DGobbler::Size(TUint32 aMultiPage) + { + return 1u << (aMultiPage & 0x1f); + } +#endif + +#ifdef __EPOC32__ +TInt DGobbler::GobbleMultiPages(TUint32& aTake, TUint32* aMultiPageBuf, TInt aMaxMultiPages) + { + TInt i = 0; + TUint32 mp = 0; + while (i> iPageShift) * sizeof(TPhysAddr); +#else + TUint32 chunkMax = take; +#endif + TChunkCreateInfo info; + info.iType = TChunkCreateInfo::ESharedKernelSingle; + info.iMaxSize = chunkMax; +#ifdef __EPOC32__ + info.iMapAttr = EMapAttrCachedMax; +#else + info.iMapAttr = 0; +#endif + info.iOwnsMemory = 1; + info.iDestroyedDfc = 0; + TLinAddr ka = 0; + TUint32 ma = 0; + r = Kern::ChunkCreate(info, iSharedChunk, ka, ma); + if (r!=KErrNone) + return take - take2; // someone else gobbled all the RAM + TUint32 chunkSz = (chunkMax + iPageSize - 1) &~ (iPageSize - 1); + r = Kern::ChunkCommit(iSharedChunk, 0, chunkSz); + if (r!=KErrNone) + return take - take2; // someone else gobbled all the RAM +#ifndef __EPOC32__ + return take; // on emulator we are finished here +#else + TUint32* p = (TUint32*)ka; + memclr(p, chunkSz); + r = GobbleMultiPages(take2, p, chunkSz/sizeof(TUint32)); + if (r==KErrNoMemory) + return take - take2; // someone else gobbled all the RAM + return take; // done +#endif + } + +TInt DGobbler::Request(TInt aFunc, TAny* a1, TAny*) + { + if (aFunc == RGobbler::EControlGobbleRAM) + { + NKern::ThreadEnterCS(); + TUint32 ret = Gobble(TUint32(a1)); + NKern::ThreadLeaveCS(); + return ret; + } + else + return KErrNotSupported; + } + +DECLARE_STANDARD_LDD() + { + return new DGobblerFactory; + } +