1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/mmu/d_gobble.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,276 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\misc\d_gobble.cpp
1.18 +// LDD for gobbling RAM
1.19 +//
1.20 +//
1.21 +
1.22 +#include "platform.h"
1.23 +#include <kernel/kern_priv.h>
1.24 +#include "d_gobble.h"
1.25 +
1.26 +const TInt KMajorVersionNumber=0;
1.27 +const TInt KMinorVersionNumber=1;
1.28 +const TInt KBuildVersionNumber=1;
1.29 +
1.30 +class DGobblerFactory : public DLogicalDevice
1.31 +//
1.32 +// Gobbler LDD factory
1.33 +//
1.34 + {
1.35 +public:
1.36 + DGobblerFactory();
1.37 + ~DGobblerFactory();
1.38 + virtual TInt Install();
1.39 + virtual void GetCaps(TDes8& aDes) const;
1.40 + virtual TInt Create(DLogicalChannelBase*& aChannel);
1.41 + };
1.42 +
1.43 +class DGobbler : public DLogicalChannelBase
1.44 +//
1.45 +// RAM Gobbler LDD channel
1.46 +//
1.47 + {
1.48 +public:
1.49 + DGobbler();
1.50 + virtual ~DGobbler();
1.51 +private:
1.52 + virtual TInt Request(TInt aFunc, TAny* a1, TAny* a2);
1.53 + virtual TInt DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer);
1.54 +private:
1.55 + enum {ESmallBufferSize = 64};
1.56 +
1.57 + TUint32 Gobble(TUint32 aLeave);
1.58 +#ifdef __EPOC32__
1.59 + TInt GobbleMultiPages(TUint32& aTake, TUint32* aMultiPageBuf, TInt aMaxMultiPages);
1.60 + void FreeMultiPage(TPhysAddr aMultiPage);
1.61 + TUint32 AllocMultiPage(TUint32 aSize);
1.62 + TUint32 Size(TUint32 aMultiPage);
1.63 +#endif
1.64 +private:
1.65 +#ifdef __EPOC32__
1.66 + TPhysAddr iPhys[ESmallBufferSize];
1.67 +#endif
1.68 + DChunk* iSharedChunk;
1.69 + TUint32 iPageShift;
1.70 + TUint32 iPageSize;
1.71 + };
1.72 +
1.73 +DGobblerFactory::DGobblerFactory()
1.74 + {
1.75 + iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
1.76 + //iParseMask=0;//No units, no info, no PDD
1.77 + //iUnitsMask=0;//Only one thing
1.78 + }
1.79 +
1.80 +DGobblerFactory::~DGobblerFactory()
1.81 + {
1.82 + }
1.83 +
1.84 +TInt DGobblerFactory::Create(DLogicalChannelBase*& aChannel)
1.85 + {
1.86 + aChannel = new DGobbler;
1.87 + return aChannel ? KErrNone : KErrNoMemory;
1.88 + }
1.89 +
1.90 +TInt DGobblerFactory::Install()
1.91 +//
1.92 +// Install the LDD - overriding pure virtual
1.93 +//
1.94 + {
1.95 + return SetName(&KGobblerLddName);
1.96 + }
1.97 +
1.98 +void DGobblerFactory::GetCaps(TDes8& aDes) const
1.99 +//
1.100 +// Get capabilities - overriding pure virtual
1.101 +//
1.102 + {
1.103 + TCapsGobblerV01 b;
1.104 + b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
1.105 + Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
1.106 + }
1.107 +
1.108 +DGobbler::DGobbler()
1.109 + {
1.110 + iPageSize = Kern::RoundToPageSize(1);
1.111 + iPageShift = __e32_find_ms1_32(iPageSize);
1.112 + }
1.113 +
1.114 +DGobbler::~DGobbler()
1.115 + {
1.116 + // Free all the RAM we've gobbled
1.117 +
1.118 +#ifdef __EPOC32__
1.119 + // Free the addresses held in the shared chunk
1.120 + if (iSharedChunk)
1.121 + {
1.122 + TLinAddr ka;
1.123 + TInt r = Kern::ChunkAddress(iSharedChunk, 0, 1, ka);
1.124 + if (r==KErrNone)
1.125 + {
1.126 + const TUint32* p = (const TUint32*)ka;
1.127 + const TUint32* pE = p + (iSharedChunk->Size() / sizeof(TUint32));
1.128 + while (p<pE)
1.129 + {
1.130 + TUint32 mp = *p++;
1.131 + if (mp)
1.132 + FreeMultiPage(mp);
1.133 + }
1.134 + }
1.135 + }
1.136 +#endif
1.137 + if (iSharedChunk)
1.138 + Kern::ChunkClose(iSharedChunk);
1.139 +#ifdef __EPOC32__
1.140 + TInt i;
1.141 + for (i=0; i<ESmallBufferSize; ++i)
1.142 + {
1.143 + TUint32 mp = iPhys[i];
1.144 + if (mp)
1.145 + FreeMultiPage(mp);
1.146 + }
1.147 +#endif
1.148 + }
1.149 +
1.150 +TInt DGobbler::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
1.151 +//
1.152 +// Create channel
1.153 +//
1.154 + {
1.155 +
1.156 + if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
1.157 + return KErrNotSupported;
1.158 + return KErrNone;
1.159 + }
1.160 +
1.161 +
1.162 +#ifdef __EPOC32__
1.163 +void DGobbler::FreeMultiPage(TPhysAddr aMultiPage)
1.164 + {
1.165 + TPhysAddr base = (aMultiPage>>iPageShift) << iPageShift;
1.166 + TUint32 size = Size(aMultiPage);
1.167 + Epoc::FreePhysicalRam(base, size);
1.168 + }
1.169 +
1.170 +TUint32 DGobbler::AllocMultiPage(TUint32 aSize)
1.171 + {
1.172 + TUint32 sz = 1u << __e32_find_ms1_32(aSize); // round size down to power of 2
1.173 + while (sz > iPageSize)
1.174 + {
1.175 + TPhysAddr pa;
1.176 + TInt r = Epoc::AllocPhysicalRam(sz, pa);
1.177 + if (r == KErrNone)
1.178 + return pa | __e32_find_ms1_32(sz);
1.179 + sz >>= 1;
1.180 + }
1.181 + return 0;
1.182 + }
1.183 +
1.184 +TUint32 DGobbler::Size(TUint32 aMultiPage)
1.185 + {
1.186 + return 1u << (aMultiPage & 0x1f);
1.187 + }
1.188 +#endif
1.189 +
1.190 +#ifdef __EPOC32__
1.191 +TInt DGobbler::GobbleMultiPages(TUint32& aTake, TUint32* aMultiPageBuf, TInt aMaxMultiPages)
1.192 + {
1.193 + TInt i = 0;
1.194 + TUint32 mp = 0;
1.195 + while (i<aMaxMultiPages && aTake)
1.196 + {
1.197 + mp = AllocMultiPage(aTake);
1.198 + if (mp==0)
1.199 + break; // someone else gobbled all the RAM
1.200 + aTake -= Size(mp);
1.201 + aMultiPageBuf[i] = mp;
1.202 + ++i;
1.203 + }
1.204 + if (mp == 0)
1.205 + return KErrNoMemory; // someone else gobbled all the RAM
1.206 + if (aTake==0)
1.207 + return KErrNone;
1.208 + return KErrOverflow; // buffer filled up
1.209 + }
1.210 +#endif
1.211 +
1.212 +TUint32 DGobbler::Gobble(TUint32 aLeave)
1.213 + {
1.214 + TUint32 free = Kern::FreeRamInBytes();
1.215 + if (free < aLeave)
1.216 + return 0; // no need to gobble anything
1.217 + TUint32 take = free - aLeave;
1.218 + TUint32 take2 = take;
1.219 + TInt r = KErrNone;
1.220 +#ifdef __EPOC32__
1.221 + r = GobbleMultiPages(take2, iPhys, ESmallBufferSize);
1.222 + if (r==KErrNoMemory)
1.223 + return take - take2; // someone else gobbled all the RAM
1.224 + if (r==KErrNone)
1.225 + return take; // small buffer did the job
1.226 +
1.227 + TUint32 chunkMax = (take >> iPageShift) * sizeof(TPhysAddr);
1.228 +#else
1.229 + TUint32 chunkMax = take;
1.230 +#endif
1.231 + TChunkCreateInfo info;
1.232 + info.iType = TChunkCreateInfo::ESharedKernelSingle;
1.233 + info.iMaxSize = chunkMax;
1.234 +#ifdef __EPOC32__
1.235 + info.iMapAttr = EMapAttrCachedMax;
1.236 +#else
1.237 + info.iMapAttr = 0;
1.238 +#endif
1.239 + info.iOwnsMemory = 1;
1.240 + info.iDestroyedDfc = 0;
1.241 + TLinAddr ka = 0;
1.242 + TUint32 ma = 0;
1.243 + r = Kern::ChunkCreate(info, iSharedChunk, ka, ma);
1.244 + if (r!=KErrNone)
1.245 + return take - take2; // someone else gobbled all the RAM
1.246 + TUint32 chunkSz = (chunkMax + iPageSize - 1) &~ (iPageSize - 1);
1.247 + r = Kern::ChunkCommit(iSharedChunk, 0, chunkSz);
1.248 + if (r!=KErrNone)
1.249 + return take - take2; // someone else gobbled all the RAM
1.250 +#ifndef __EPOC32__
1.251 + return take; // on emulator we are finished here
1.252 +#else
1.253 + TUint32* p = (TUint32*)ka;
1.254 + memclr(p, chunkSz);
1.255 + r = GobbleMultiPages(take2, p, chunkSz/sizeof(TUint32));
1.256 + if (r==KErrNoMemory)
1.257 + return take - take2; // someone else gobbled all the RAM
1.258 + return take; // done
1.259 +#endif
1.260 + }
1.261 +
1.262 +TInt DGobbler::Request(TInt aFunc, TAny* a1, TAny*)
1.263 + {
1.264 + if (aFunc == RGobbler::EControlGobbleRAM)
1.265 + {
1.266 + NKern::ThreadEnterCS();
1.267 + TUint32 ret = Gobble(TUint32(a1));
1.268 + NKern::ThreadLeaveCS();
1.269 + return ret;
1.270 + }
1.271 + else
1.272 + return KErrNotSupported;
1.273 + }
1.274 +
1.275 +DECLARE_STANDARD_LDD()
1.276 + {
1.277 + return new DGobblerFactory;
1.278 + }
1.279 +