os/kernelhwsrv/kerneltest/e32test/demandpaging/d_pagestress.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2005-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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\demandpaging\d_pagestrss.cpp
    15 // 
    16 //
    17 
    18 #include <kernel/kern_priv.h>
    19 #include <kernel/cache.h>
    20 #include "d_pagestress.h"
    21 
    22 //
    23 // Class definitions
    24 //
    25 
    26 class DPageStressTestFactory : public DLogicalDevice
    27 	{
    28 public:
    29 	~DPageStressTestFactory();
    30 	virtual TInt Install();
    31 	virtual void GetCaps(TDes8& aDes) const;
    32 	virtual TInt Create(DLogicalChannelBase*& aChannel);
    33 	};
    34 
    35 class DPageStressTestChannel : public DLogicalChannelBase
    36 	{
    37 public:
    38 	DPageStressTestChannel();
    39 	~DPageStressTestChannel();
    40 	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
    41 	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
    42 
    43 	TInt DoConsumeRamSetup(TInt aNumPagesLeft, TInt aPagesInBlock);
    44 	TInt DoConsumeRamFinish(void);
    45 	TInt DoConsumeSomeRam(TInt aBlocks);
    46 	TInt DoReleaseSomeRam(TInt aBlocks);
    47 	TInt FreeRam();
    48 	TInt DoSetDebugFlag(TInt aState);
    49 public:
    50 	DPageStressTestFactory*	iFactory;
    51 	
    52 private:
    53 	TBool		 iRamAllocd;
    54 	TInt		 iInitialFreeRam;
    55 	TInt		 iTotalBlocks;
    56 	TInt		 iBlockSize;
    57 	TInt		 iLastBlockAllocd;
    58 	TPhysAddr*	 iAddrArray;
    59 	TInt		 iDebug;
    60 	DMutex*      iMutex;
    61 	TInt		 iThreadCounter;
    62 	TPhysAddr	 iAddrMin;
    63 	TPhysAddr	 iAddrMax;
    64 	TBool		 iDemandPaging;
    65 	};
    66 
    67 //
    68 // DPageStressTestFactory
    69 //
    70 
    71 TInt DPageStressTestFactory::Install()
    72 	{
    73 	return SetName(&KPageStressTestLddName);
    74 	}
    75 
    76 DPageStressTestFactory::~DPageStressTestFactory()
    77 	{
    78 	}
    79 
    80 void DPageStressTestFactory::GetCaps(TDes8& /*aDes*/) const
    81 	{
    82 	// Not used but required as DLogicalDevice::GetCaps is pure virtual
    83 	}
    84 
    85 TInt DPageStressTestFactory::Create(DLogicalChannelBase*& aChannel)
    86 	{
    87 	aChannel = NULL;
    88 	DPageStressTestChannel* channel=new DPageStressTestChannel;
    89 	if(!channel)
    90 		return KErrNoMemory;
    91 	channel->iFactory = this;
    92 	aChannel = channel;
    93 	return KErrNone;
    94 	}
    95 
    96 DECLARE_STANDARD_LDD()
    97 	{
    98 	return new DPageStressTestFactory;
    99 	}
   100 
   101 //
   102 // DPageStressTestChannel
   103 //
   104 
   105 TInt DPageStressTestChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
   106 	{
   107 	return KErrNone;
   108 	}
   109 
   110 DPageStressTestChannel::DPageStressTestChannel()
   111 	: iRamAllocd(EFalse), iInitialFreeRam(0), iTotalBlocks(0), iBlockSize(0), iLastBlockAllocd(0), 
   112 	iAddrArray(NULL), iDebug(0), iThreadCounter(1), iAddrMin(0), iAddrMax(0), iDemandPaging(ETrue)
   113 	{
   114 	_LIT(KMutexName,"TPageStressMutex");
   115 	NKern::ThreadEnterCS();
   116 	Kern::MutexCreate(iMutex, KMutexName,KMutexOrdNone);
   117 	NKern::ThreadLeaveCS();
   118 	SVMCacheInfo tempPages;
   119 	if (Kern::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0) != KErrNone)
   120 		{
   121 		iDemandPaging = EFalse;
   122 		}
   123 	}
   124 
   125 DPageStressTestChannel::~DPageStressTestChannel()
   126 	{
   127 	if (iRamAllocd)
   128 		{
   129 		DoConsumeRamFinish();
   130 		}
   131 	if (iMutex)
   132         {
   133 		iMutex->Close(NULL);
   134 		iMutex = NULL;
   135 		}
   136 	}
   137 
   138 TInt DPageStressTestChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
   139 	{
   140 	TInt threadCount = __e32_atomic_tas_ord32(&iThreadCounter, 1, 1, 0);
   141 	if (threadCount >= 2)
   142 		{
   143 		Kern::Printf("DPageStressTestChannel::Request threadCount = %d\n", threadCount);
   144 		}
   145 	NKern::ThreadEnterCS();
   146 	Kern::MutexWait(*iMutex);
   147 	TInt retVal = KErrNotSupported;
   148 	switch(aFunction)
   149 		{
   150 		case RPageStressTestLdd::EDoConsumeRamSetup:
   151 			{
   152 			retVal = DPageStressTestChannel::DoConsumeRamSetup((TInt)a1, (TInt)a2);
   153 			}
   154 		break;
   155 
   156 		case RPageStressTestLdd::EDoConsumeRamFinish:
   157 			{
   158 			retVal = DPageStressTestChannel::DoConsumeRamFinish();
   159 			}
   160 		break;
   161 
   162 		case RPageStressTestLdd::EDoConsumeSomeRam:
   163 			{
   164 			retVal = DPageStressTestChannel::DoConsumeSomeRam((TInt)a1);
   165 			}
   166 		break;
   167 
   168 		case RPageStressTestLdd::EDoReleaseSomeRam:
   169 			{
   170 			retVal = DPageStressTestChannel::DoReleaseSomeRam((TInt)a1);
   171 			}
   172 		break;
   173 		
   174 		case RPageStressTestLdd::EDoSetDebugFlag:
   175 			{
   176 			retVal = DoSetDebugFlag((TInt) a1);
   177 			}
   178 		break;
   179 		
   180 		default: break;
   181 		}
   182 	Kern::MutexSignal(*iMutex);
   183 	NKern::ThreadLeaveCS();
   184 	__e32_atomic_tas_ord32(&iThreadCounter, 1, -1, 0);
   185 	return retVal;
   186 	}
   187 
   188 // 
   189 // DPageStressTestChannel::DoConsumeRamSetup
   190 //
   191 // This test attempts to consume most of the available Contiguous Ram until we need to ask the 
   192 // demand paging code to release memory for it.
   193 // 
   194 // 
   195 //
   196 #define CHECK(c) { if(!(c)) { Kern::Printf("Fail  %d", __LINE__); ; retVal = __LINE__;} }
   197 
   198 TInt DPageStressTestChannel::DoConsumeRamSetup(TInt aNumPagesLeft, TInt aPagesInBlock)
   199 	{
   200 	if (iRamAllocd)
   201 		{
   202 		Kern::Printf("DPageStressTestChannel trying to start again when RAM alloc'd\n");
   203 		DoConsumeRamFinish();
   204 		}
   205 
   206 	TInt retVal = KErrNone;
   207 
   208 	TInt pageSize = 0;
   209 	CHECK(Kern::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&pageSize,0)==KErrNone);
   210 	
   211 	iBlockSize = aPagesInBlock * pageSize;
   212 	iInitialFreeRam = FreeRam();
   213 	iTotalBlocks = (iInitialFreeRam/iBlockSize) + 10;
   214 	
   215 	iAddrArray = (TPhysAddr *)Kern::AllocZ(sizeof(TPhysAddr) * iTotalBlocks);
   216 
   217 	CHECK(iAddrArray);
   218 	if(!iAddrArray)
   219 		{
   220 		return KErrNoMemory;
   221 		}
   222 	
   223 	SVMCacheInfo tempPages;
   224 
   225 	iRamAllocd = ETrue;
   226 
   227 	// get the initial free ram again as the heap may have grabbed a page during the alloc
   228 	iInitialFreeRam = FreeRam();
   229 
   230 
   231 	if (iDemandPaging)
   232 		{
   233 		CHECK(Kern::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0) == KErrNone);
   234 		if (iDebug)
   235 			{
   236 			Kern::Printf("Start : min %d max %d current %d maxFree %d freeRam %d",
   237 						 tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize, FreeRam());
   238 			}
   239 		}
   240 	// allocate blocks to use up RAM until we fail to allocate any further...
   241 	TInt index;
   242 	// only alloc upto the point where we have a number of pages left.
   243 	iLastBlockAllocd = iTotalBlocks - (aNumPagesLeft / aPagesInBlock);
   244 	for (index = 0; index < iLastBlockAllocd; index ++)
   245 		{
   246 		if (iDemandPaging)
   247 			{
   248 			CHECK(Kern::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0) == KErrNone);
   249 			}
   250 
   251 		if (KErrNone != Epoc::AllocPhysicalRam(iBlockSize, iAddrArray[index], 0))
   252 			{
   253 			iAddrArray[index] = NULL;
   254 			break;
   255 			}
   256 
   257 		if ((iAddrMin == 0) || (iAddrMin > iAddrArray[index]))
   258 			{
   259 			iAddrMin = iAddrArray[index];
   260 			}
   261 		
   262 		if (iAddrMax < iAddrArray[index])
   263 			{
   264 			iAddrMax = iAddrArray[index];
   265 			}
   266 
   267 		if (iDemandPaging)
   268 			{
   269 			CHECK(Kern::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0) == KErrNone);
   270 			}
   271 		}
   272 	iLastBlockAllocd = index - 1;
   273 
   274 	if (iDemandPaging)
   275 		{
   276 		CHECK(Kern::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0) == KErrNone);
   277 		if (iDebug)
   278 			{
   279 			Kern::Printf("Alloc'd : min %d max %d current %d maxFree %d freeRam %d lastIndex %d addrMin 0x%08x addrMax 0x%08x",
   280 						 tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize, FreeRam(), iLastBlockAllocd, iAddrMin, iAddrMax);
   281 			}
   282 		}
   283 	return retVal;
   284 	}
   285 
   286 TInt DPageStressTestChannel::DoConsumeRamFinish(void)
   287 	{
   288 	TInt retVal = KErrNone;
   289 	if (iRamAllocd)
   290 		{
   291 		SVMCacheInfo tempPages;
   292 
   293 		if (iDemandPaging)
   294 			{
   295 			CHECK(Kern::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0) == KErrNone);
   296 			if (iDebug)
   297 				{
   298 				Kern::Printf("Cleanup cache info: iMinSize %d iMaxSize %d iCurrentSize %d iMaxFreeSize %d",
   299 							 tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize);
   300 				}
   301 			}
   302 		TInt index = iTotalBlocks - 1;
   303 
   304 		TBool firstTime = ETrue;
   305 
   306 		// free the memory we allocated...
   307 		while(index >= 0)
   308 			{
   309 			if (iAddrArray[index])
   310 				{
   311 				if ((iAddrArray[index] < iAddrMin) || (iAddrArray[index] > iAddrMax))
   312 					{
   313 					Kern::Printf("ERROR: DoConsumeRamFinish : index %d addr 0x%08x min 0x%08x max 0x%08x\n     : firstTime %d iLastBlockAllocd %d iTotalBlock %d", index, iAddrArray[index], iAddrMin, iAddrMax, firstTime, iLastBlockAllocd, iTotalBlocks);
   314 					TInt tempIndex = index - 8;
   315 					while (tempIndex < (index + 8))
   316 						{
   317 						Kern::Printf("      --> index %d addr 0x%08x", tempIndex, iAddrArray[tempIndex]);
   318 						tempIndex ++;
   319 						}
   320 					
   321 					iAddrArray[index] = NULL;
   322 					}
   323 				else
   324 					{
   325 					TInt r = Epoc::FreePhysicalRam(iAddrArray[index], iBlockSize);
   326 					iAddrArray[index] = NULL;
   327 					CHECK(r==KErrNone);
   328 					}
   329 				}
   330 
   331 			firstTime = EFalse;
   332 			--index;
   333 			}
   334 
   335 		if (iDebug)
   336 			{
   337 			Kern::Printf("DoConsumeRamFinish : FreeRam Initial 0x%x now 0x%x",iInitialFreeRam, FreeRam());
   338 			}
   339 		//CHECK(FreeRam() == iInitialFreeRam)
   340 		if (FreeRam() != iInitialFreeRam)
   341 			{
   342 			Kern::Printf("DoConsumeRamFinish : FreeRam Initial 0x%x now 0x%x NOT EQUAL!",iInitialFreeRam, FreeRam());
   343 			}
   344 
   345 		Kern::Free(iAddrArray);
   346 		iAddrArray = NULL;
   347 		iAddrMin = 0;
   348 		iAddrMax = 0;
   349 		iLastBlockAllocd = -1;
   350 		iTotalBlocks = 0;
   351 		iRamAllocd = EFalse;
   352 
   353 		if (iDemandPaging)
   354 			{
   355 			CHECK(Kern::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0) == KErrNone);
   356 			if (iDebug)
   357 				{
   358 				Kern::Printf("End cache info: iMinSize %d iMaxSize %d iCurrentSize %d iMaxFreeSize %d",
   359 							 tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize);
   360 				}
   361 			}
   362 		}	
   363 	return retVal;
   364 	}
   365 
   366 TInt DPageStressTestChannel::DoConsumeSomeRam(TInt aBlocks)
   367 	{
   368 	TInt retVal = KErrNone;
   369 
   370 	return retVal;
   371 	}
   372 
   373 TInt DPageStressTestChannel::DoReleaseSomeRam(TInt aBlocks)
   374 	{
   375 	if(iLastBlockAllocd<0)
   376 		return KErrUnderflow;
   377 
   378 	TInt retVal = KErrNone;
   379 	if (iRamAllocd)
   380 		{
   381 		SVMCacheInfo tempPages;
   382 
   383 		if (iDemandPaging)
   384 			{
   385 			CHECK(Kern::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0) == KErrNone);
   386 			if (iDebug)
   387 				{
   388 				Kern::Printf("Release  : min %d max %d current %d maxFree %d freeRam %d lastIndex %d",
   389 							 tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize, FreeRam(), iLastBlockAllocd);
   390 				}
   391 			}
   392 		
   393 		TInt index = iLastBlockAllocd;
   394 		iLastBlockAllocd -= aBlocks;
   395 		
   396 		TBool firstTime = ETrue;
   397 
   398 		// free the memory we allocated...
   399 		while((index >= 0) && (index > iLastBlockAllocd))
   400 			{
   401 			if (iAddrArray[index])
   402 				{
   403 				//Kern::Printf("DoReleaseSomeRam : index %d addr 0x%08x size %d", index, iAddrArray[index], iBlockSize);
   404 				if ((iAddrArray[index] < iAddrMin) || (iAddrArray[index] > iAddrMax))
   405 					{
   406 					Kern::Printf("ERROR: DoReleaseSomeRam : index %d addr 0x%08x min 0x%08x max 0x%08x\n     : firstTime %d iLastBlockAllocd %d iTotalBlock %d", index, iAddrArray[index], iAddrMin, iAddrMax, firstTime, iLastBlockAllocd + aBlocks, iTotalBlocks);
   407 					TInt tempIndex = index - 8;
   408 					while (tempIndex < (index + 8))
   409 						{
   410 						Kern::Printf("      --> index %d addr 0x%08x", tempIndex, iAddrArray[tempIndex]);
   411 						tempIndex ++;
   412 						}
   413 
   414 					iAddrArray[index] = NULL;
   415 					}
   416 				else
   417 					{
   418 					TInt r = Epoc::FreePhysicalRam(iAddrArray[index], iBlockSize);
   419 					iAddrArray[index] = NULL;
   420 					CHECK(r==KErrNone);
   421 					}
   422 				}
   423 			else
   424 				{
   425 				Kern::Printf("ERROR: DoReleaseSomeRam : trying to free NULL index %d", index, iAddrArray[index], iAddrMin, iAddrMax);
   426 				TInt tempIndex = index - 8;
   427 				while (tempIndex < (index + 8))
   428 					{
   429 					Kern::Printf("      --> index %d addr 0x%08x", tempIndex, iAddrArray[tempIndex]);
   430 					tempIndex ++;
   431 					}
   432 
   433 				}
   434 			firstTime = EFalse;
   435 			--index;
   436 			}
   437 		if (index <= 0)
   438 			{
   439 			Kern::Printf("WARNING : DoReleaseSomeRam : index %d !!!!!", index);
   440 			}
   441 
   442 		if (iDemandPaging)
   443 			{
   444 			CHECK(Kern::HalFunction(EHalGroupVM,EVMHalGetCacheSize,&tempPages,0) == KErrNone);
   445 			if (iDebug)
   446 				{
   447 				Kern::Printf("Released : min %d max %d current %d maxFree %d freeRam %d lastIndex %d",
   448 							 tempPages.iMinSize, tempPages.iMaxSize, tempPages.iCurrentSize ,tempPages.iMaxFreeSize, FreeRam(), iLastBlockAllocd);
   449 				}	
   450 			}
   451 		}
   452 	return retVal;
   453 	}
   454 
   455 
   456 TInt DPageStressTestChannel::FreeRam()
   457 	{
   458 	return Kern::FreeRamInBytes();
   459 	}
   460 
   461 TInt DPageStressTestChannel::DoSetDebugFlag(TInt aState)
   462 	{
   463 	iDebug = aState;
   464 	return KErrNone;
   465 	}