First public contribution.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\misc\d_gobble.cpp
15 // LDD for gobbling RAM
20 #include <kernel/kern_priv.h>
23 const TInt KMajorVersionNumber=0;
24 const TInt KMinorVersionNumber=1;
25 const TInt KBuildVersionNumber=1;
27 class DGobblerFactory : public DLogicalDevice
29 // Gobbler LDD factory
35 virtual TInt Install();
36 virtual void GetCaps(TDes8& aDes) const;
37 virtual TInt Create(DLogicalChannelBase*& aChannel);
40 class DGobbler : public DLogicalChannelBase
42 // RAM Gobbler LDD channel
49 virtual TInt Request(TInt aFunc, TAny* a1, TAny* a2);
50 virtual TInt DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer);
52 enum {ESmallBufferSize = 64};
54 TUint32 Gobble(TUint32 aLeave);
56 TInt GobbleMultiPages(TUint32& aTake, TUint32* aMultiPageBuf, TInt aMaxMultiPages);
57 void FreeMultiPage(TPhysAddr aMultiPage);
58 TUint32 AllocMultiPage(TUint32 aSize);
59 TUint32 Size(TUint32 aMultiPage);
63 TPhysAddr iPhys[ESmallBufferSize];
70 DGobblerFactory::DGobblerFactory()
72 iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
73 //iParseMask=0;//No units, no info, no PDD
74 //iUnitsMask=0;//Only one thing
77 DGobblerFactory::~DGobblerFactory()
81 TInt DGobblerFactory::Create(DLogicalChannelBase*& aChannel)
83 aChannel = new DGobbler;
84 return aChannel ? KErrNone : KErrNoMemory;
87 TInt DGobblerFactory::Install()
89 // Install the LDD - overriding pure virtual
92 return SetName(&KGobblerLddName);
95 void DGobblerFactory::GetCaps(TDes8& aDes) const
97 // Get capabilities - overriding pure virtual
101 b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
102 Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
107 iPageSize = Kern::RoundToPageSize(1);
108 iPageShift = __e32_find_ms1_32(iPageSize);
111 DGobbler::~DGobbler()
113 // Free all the RAM we've gobbled
116 // Free the addresses held in the shared chunk
120 TInt r = Kern::ChunkAddress(iSharedChunk, 0, 1, ka);
123 const TUint32* p = (const TUint32*)ka;
124 const TUint32* pE = p + (iSharedChunk->Size() / sizeof(TUint32));
135 Kern::ChunkClose(iSharedChunk);
138 for (i=0; i<ESmallBufferSize; ++i)
140 TUint32 mp = iPhys[i];
147 TInt DGobbler::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
153 if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
154 return KErrNotSupported;
160 void DGobbler::FreeMultiPage(TPhysAddr aMultiPage)
162 TPhysAddr base = (aMultiPage>>iPageShift) << iPageShift;
163 TUint32 size = Size(aMultiPage);
164 Epoc::FreePhysicalRam(base, size);
167 TUint32 DGobbler::AllocMultiPage(TUint32 aSize)
169 TUint32 sz = 1u << __e32_find_ms1_32(aSize); // round size down to power of 2
170 while (sz > iPageSize)
173 TInt r = Epoc::AllocPhysicalRam(sz, pa);
175 return pa | __e32_find_ms1_32(sz);
181 TUint32 DGobbler::Size(TUint32 aMultiPage)
183 return 1u << (aMultiPage & 0x1f);
188 TInt DGobbler::GobbleMultiPages(TUint32& aTake, TUint32* aMultiPageBuf, TInt aMaxMultiPages)
192 while (i<aMaxMultiPages && aTake)
194 mp = AllocMultiPage(aTake);
196 break; // someone else gobbled all the RAM
198 aMultiPageBuf[i] = mp;
202 return KErrNoMemory; // someone else gobbled all the RAM
205 return KErrOverflow; // buffer filled up
209 TUint32 DGobbler::Gobble(TUint32 aLeave)
211 TUint32 free = Kern::FreeRamInBytes();
213 return 0; // no need to gobble anything
214 TUint32 take = free - aLeave;
215 TUint32 take2 = take;
218 r = GobbleMultiPages(take2, iPhys, ESmallBufferSize);
220 return take - take2; // someone else gobbled all the RAM
222 return take; // small buffer did the job
224 TUint32 chunkMax = (take >> iPageShift) * sizeof(TPhysAddr);
226 TUint32 chunkMax = take;
228 TChunkCreateInfo info;
229 info.iType = TChunkCreateInfo::ESharedKernelSingle;
230 info.iMaxSize = chunkMax;
232 info.iMapAttr = EMapAttrCachedMax;
236 info.iOwnsMemory = 1;
237 info.iDestroyedDfc = 0;
240 r = Kern::ChunkCreate(info, iSharedChunk, ka, ma);
242 return take - take2; // someone else gobbled all the RAM
243 TUint32 chunkSz = (chunkMax + iPageSize - 1) &~ (iPageSize - 1);
244 r = Kern::ChunkCommit(iSharedChunk, 0, chunkSz);
246 return take - take2; // someone else gobbled all the RAM
248 return take; // on emulator we are finished here
250 TUint32* p = (TUint32*)ka;
252 r = GobbleMultiPages(take2, p, chunkSz/sizeof(TUint32));
254 return take - take2; // someone else gobbled all the RAM
259 TInt DGobbler::Request(TInt aFunc, TAny* a1, TAny*)
261 if (aFunc == RGobbler::EControlGobbleRAM)
263 NKern::ThreadEnterCS();
264 TUint32 ret = Gobble(TUint32(a1));
265 NKern::ThreadLeaveCS();
269 return KErrNotSupported;
272 DECLARE_STANDARD_LDD()
274 return new DGobblerFactory;