os/kernelhwsrv/kerneltest/e32test/mmu/t_chunk4.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1995-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\mmu\t_chunk4.cpp
    15 // Overview:
    16 // Test disconnected chunks
    17 // API Information:
    18 // RChunk, CBase
    19 // Details:
    20 // - Check Allocate/Commit/Decommit methods on local disconnected chunk and write/read 
    21 // access to both committed and uncommitted regions.
    22 // - Check IPC that involves local disconnected chunk and verify results are as expected.
    23 // Platforms/Drives/Compatibility:
    24 // All.
    25 // Assumptions/Requirement/Pre-requisites:
    26 // Failures and causes:
    27 // Base Port information:
    28 // 
    29 //
    30 
    31 #define __E32TEST_EXTENSION__
    32 #include <e32test.h>
    33 #include "u32std.h"
    34 #include "mmudetect.h"
    35 #include "../misc/prbs.h"
    36 #include "d_memorytest.h"
    37 #include "freeram.h"
    38 
    39 RTest test(_L("T_CHUNK4"));
    40 
    41 RMemoryTestLdd TestLdd;
    42 
    43 TUint RndSeed[2];
    44 
    45 class CChunk : public CBase
    46 	{
    47 public:
    48 	static CChunk* New(TInt aMaxSize);
    49 public:
    50 	virtual ~CChunk();
    51 	TInt Verify();
    52 	TInt Commit(TInt anOffset, TInt aSize);
    53 	TInt Allocate(TInt aSize);
    54 	TInt Decommit(TInt anOffset, TInt aSize);
    55 	void CheckL(volatile TUint* aPtr);
    56 	TInt AddPages(TInt anOffset, TInt aSize);
    57 	TInt RemovePages(TInt anOffset, TInt aSize);
    58 public:
    59 	RChunk iChunk;
    60 	TUint8* iPageInfo;
    61 	TInt iPageSize;
    62 	TInt iMaxSize;
    63 	TInt iNumPages;
    64 	};
    65 
    66 CChunk* CChunk::New(TInt aMaxSize)
    67 	{
    68 	CChunk* pC=new CChunk;
    69 	if (pC)
    70 		{
    71 		TInt p;
    72 		UserHal::PageSizeInBytes(p);
    73 		pC->iPageSize=p;
    74 		pC->iMaxSize=aMaxSize;
    75 		TInt n=aMaxSize/p;
    76 		pC->iNumPages=n;
    77 		TInt r=pC->iChunk.CreateDisconnectedLocal(0,0,aMaxSize);
    78 		if (r==KErrNone)
    79 			{
    80 			TUint8* pI=(TUint8*)User::Alloc(n);
    81 			if (pI)
    82 				{
    83 				pC->iPageInfo=pI;
    84 				Mem::FillZ(pI,n);
    85 				}
    86 			else
    87 				r=KErrNoMemory;
    88 			}
    89 		if (r!=KErrNone)
    90 			{
    91 			delete pC;
    92 			pC=NULL;
    93 			}
    94 		}
    95 	return pC;
    96 	}
    97 
    98 CChunk::~CChunk()
    99 	{
   100 	delete iPageInfo;
   101 	iChunk.Close();
   102 	}
   103 
   104 void CChunk::CheckL(volatile TUint* aPtr)
   105 	{
   106 	TUint x=*aPtr;
   107 	*aPtr=x;
   108 	}
   109 
   110 TInt CChunk::Verify()
   111 	{
   112 //	test.Getch();
   113 	TInt i;
   114 	TUint8* base=iChunk.Base();
   115 	for (i=0; i<iNumPages; i++)
   116 		{
   117 		volatile TUint* pX=(volatile TUint*)base;
   118 		TInt r=TestLdd.ReadWriteMemory((TAny*)pX);
   119 		TUint8 info=iPageInfo[i];
   120 		if (info==0 && r==KErrNone)
   121 			return KErrGeneral;
   122 		if (info!=0 && r!=KErrNone)
   123 			return KErrAccessDenied;
   124 		if (info!=0)
   125 			{
   126 			TUint seed[2];
   127 			seed[0]=info<<8;
   128 			seed[1]=0;
   129 			TInt j;
   130 			for (j=0; j<iPageSize; j+=4)
   131 				{
   132 				if (*pX++!=Random(seed))
   133 					return KErrArgument;
   134 				}
   135 			}
   136 		base+=iPageSize;
   137 		}
   138 	return KErrNone;
   139 	}
   140 
   141 TInt CChunk::AddPages(TInt anOffset, TInt aSize)
   142 	{
   143 	TInt i=anOffset/iPageSize;
   144 	TInt n=aSize/iPageSize;
   145 	TInt e=i+n;
   146 	TUint* p=(TUint*)(iChunk.Base()+anOffset);
   147 	for (; i<e; i++)
   148 		{
   149 		TUint8 s=(TUint8)Random(RndSeed);
   150 		if (s==0)
   151 			s=1;
   152 		iPageInfo[i]=s;
   153 		TUint seed[2];
   154 		seed[0]=s<<8;
   155 		seed[1]=0;
   156 		TInt j;
   157 		for (j=0; j<iPageSize; j+=4)
   158 			{
   159 			*p++=Random(seed);
   160 			}
   161 		}
   162 	return KErrNone;
   163 	}
   164 
   165 TInt CChunk::RemovePages(TInt anOffset, TInt aSize)
   166 	{
   167 	TInt i=anOffset/iPageSize;
   168 	TInt n=aSize/iPageSize;
   169 	TInt e=i+n;
   170 	for (; i<e; i++)
   171 		iPageInfo[i]=0;
   172 	return KErrNone;
   173 	}
   174 
   175 TInt CChunk::Commit(TInt anOffset, TInt aSize)
   176 	{
   177 	TInt r=iChunk.Commit(anOffset,aSize);
   178 	if (r==KErrNone)
   179 		{
   180 		AddPages(anOffset,aSize);
   181 		}
   182 	return r;
   183 	}
   184 
   185 TInt CChunk::Allocate(TInt aSize)
   186 	{
   187 	TInt r=iChunk.Allocate(aSize);
   188 	if (r>=0)
   189 		{
   190 		AddPages(r,aSize);
   191 		}
   192 	return r;
   193 	}
   194 
   195 TInt CChunk::Decommit(TInt anOffset, TInt aSize)
   196 	{
   197 	TInt r=iChunk.Decommit(anOffset,aSize);
   198 	if (r==KErrNone)
   199 		{
   200 		RemovePages(anOffset,aSize);
   201 		}
   202 	return r;
   203 	}
   204 
   205 // Stuff to test remote writes
   206 _LIT(KServerName, "Chunk4Test");
   207 
   208 class CTestSession : public CSession2
   209 	{
   210 public:
   211 	CTestSession();
   212 	virtual void ServiceL(const RMessage2& aMessage);
   213 	};
   214 
   215 class CTestServer : public CServer2
   216 	{
   217 public:
   218 	CTestServer();
   219 	virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
   220 	};
   221 
   222 class RTestSession : public RSessionBase
   223 	{
   224 public:
   225 	enum {ETestIpc, ETestStop};
   226 	TInt Connect();
   227 	void Stop();
   228 	TInt TestRemoteWrite(TInt aLength, TInt anOffset1, TInt anOffset2, TInt anOffset3, TInt anOffset4);
   229 	TInt IpcWrite(TDes8* aRemoteDest, const TAny* aLocalSrc, TInt aOffset);
   230 	};
   231 
   232 CTestSession::CTestSession()
   233 	{
   234 	}
   235 
   236 void CTestSession::ServiceL(const RMessage2& aMessage)
   237 	{
   238 	switch (aMessage.Function())
   239 		{
   240 		case RTestSession::ETestIpc:
   241 			{
   242 			const TDesC8& localSrc = *(const TDesC8*)aMessage.Ptr1();
   243 			TInt offset = aMessage.Int2();
   244 			TInt r = aMessage.Write(0, localSrc, offset);
   245 			aMessage.Complete(r);
   246 			break;
   247 			}
   248 		case RTestSession::ETestStop:
   249 			CActiveScheduler::Stop();
   250 			break;
   251 		default:
   252 			User::Invariant();
   253 		}
   254 	}
   255 
   256 CTestServer::CTestServer()
   257 	: CServer2(0)
   258 	{
   259 	}
   260 
   261 CSession2* CTestServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const
   262 	{
   263 	return new (ELeave) CTestSession;
   264 	}
   265 
   266 TInt ServerThread(TAny*)
   267 	{
   268 	CActiveScheduler* pA = new CActiveScheduler;
   269 	CTestServer* pS = new CTestServer;
   270 	if (!pA || !pS)
   271 		return KErrNoMemory;
   272 	CActiveScheduler::Install(pA);
   273 	TInt r = pS->Start(KServerName);
   274 	if (r!=KErrNone)
   275 		return r;
   276 	RThread::Rendezvous(KErrNone);
   277 	CActiveScheduler::Start();
   278 	return KErrNone;
   279 	}
   280 
   281 TInt RTestSession::Connect()
   282 	{
   283 	RThread t;
   284 	TInt r = t.Create(KServerName, ServerThread, 0x1000, 0x1000, 0x10000, NULL);
   285 	test(r==KErrNone);
   286 	t.SetPriority(EPriorityMore);
   287 	TRequestStatus s;
   288 	t.Rendezvous(s);
   289 	test(s==KRequestPending);
   290 	t.Resume();
   291 	User::WaitForRequest(s);
   292 	test(t.ExitType()==EExitPending);
   293 	test(s==KErrNone);
   294 	t.Close();
   295 	r = CreateSession(KServerName, TVersion());
   296 	return r;
   297 	}
   298 
   299 void RTestSession::Stop()
   300 	{
   301 	TInt r = SendReceive(ETestStop);
   302 	test(r==KErrServerTerminated);
   303 	Close();
   304 	}
   305 
   306 TInt RTestSession::IpcWrite(TDes8* aRemoteDest, const TAny* aLocalSrc, TInt aOffset)
   307 	{
   308 	return SendReceive(ETestIpc, TIpcArgs(aRemoteDest, aLocalSrc, aOffset));
   309 	}
   310 
   311 TInt RTestSession::TestRemoteWrite(TInt aLength, TInt anOffset1, TInt anOffset2, TInt anOffset3, TInt anOffset4)
   312 	{
   313 	test.Printf(_L("%x %x %x %x %x\n"),aLength,anOffset1,anOffset2,anOffset3,anOffset4);
   314 
   315 	TBool ptr=(anOffset1>=0);
   316 	TDes8* pDes;
   317 	TUint8* pData;
   318 	RChunk c;
   319 	TInt r=c.CreateDisconnectedLocal(0,0,0x800000);
   320 	test(r==KErrNone);
   321 	TUint8* base=c.Base();
   322 	if (ptr)
   323 		{
   324 		r=c.Commit(anOffset1,(TInt)sizeof(TPtr8));
   325 		test(r==KErrNone);
   326 		pDes=(TDes8*)(base+anOffset1);
   327 		Mem::FillZ(pDes,(TInt)sizeof(TPtr8));
   328 		r=c.Commit(anOffset2,aLength);
   329 		test(r==KErrNone);
   330 		pData=base+anOffset2;
   331 		Mem::FillZ(pData,aLength);
   332 		new(pDes) TPtr8(pData,0,aLength);
   333 		test(pDes->Length()==0);
   334 		test(pDes->MaxLength()==aLength);
   335 		test(pDes->Ptr()==pData);
   336 		}
   337 	else
   338 		{
   339 		TInt len=(TInt)sizeof(TDes8)+aLength;
   340 		r=c.Commit(anOffset2,len);
   341 		test(r==KErrNone);
   342 		pDes=(TDes8*)(base+anOffset2);
   343 		Mem::FillZ(pDes,len);
   344 		pData=base+anOffset2+(TInt)sizeof(TDes8);
   345 		new(pDes) TBuf8<1>;
   346 		((TInt*)pDes)[1]=aLength;
   347 		test(pDes->Length()==0);
   348 		test(pDes->MaxLength()==aLength);
   349 		test(pDes->Ptr()==pData);
   350 		}
   351 	TInt slen=aLength-anOffset3;
   352 	TUint8* pS=(TUint8*)User::Alloc(aLength);
   353 	test(pS!=NULL);
   354 	Mem::FillZ(pS,aLength);
   355 	TPtrC8 src(pS+anOffset3,slen);
   356 	TInt i;
   357 	for (i=anOffset3; i<aLength; i++)
   358 		pS[i]=(TUint8)Random(RndSeed);
   359 	if (anOffset4>=0)
   360 		c.Decommit(anOffset4,0x1000);
   361 	r = IpcWrite(pDes, &src, anOffset3);
   362 	if (r==KErrNone)
   363 		{
   364 		TPtrC8 tsrc(pS,aLength);
   365 		if (*pDes!=tsrc)
   366 			r=KErrCorrupt;
   367 		}
   368 	User::Free(pS);
   369 	c.Close();
   370 	test.Printf(_L("Return value %d\n"),r);
   371 	return r;
   372 	}
   373 
   374 GLDEF_C TInt E32Main()
   375 	{
   376 	RndSeed[0]=0xddb3d743;
   377 	RndSeed[1]=0;
   378 
   379 	test.Title();
   380 	if (!HaveVirtMem())
   381 		{
   382 		test.Printf(_L("This test requires an MMU\n"));
   383 		return KErrNone;
   384 		}
   385 	test.Start(_L("Testing Disconnected Chunks"));
   386 
   387 	test.Printf(_L("Load test LDD\n"));
   388 	test(TestLdd.Open()==KErrNone);
   389 
   390 	CChunk* pC=CChunk::New(0x800000);
   391 	test(pC!=NULL);
   392 	TInt free=FreeRam();
   393 	test.Printf(_L("Free RAM %08x\n"),free);
   394 	test(pC->Verify()==KErrNone);
   395 	test.Printf(_L("Commit 0+0x1000\n"));
   396 	test(pC->Commit(0,0x1000)==KErrNone);
   397 	test(pC->Verify()==KErrNone);
   398 	test.Printf(_L("Commit 0+0x1000 (again)\n"));
   399 	test(pC->Commit(0,0x1000)==KErrAlreadyExists);
   400 	test(pC->Verify()==KErrNone);
   401 	test.Printf(_L("Commit 0x3000+0x1000\n"));
   402 	test(pC->Commit(0x3000,0x1000)==KErrNone);
   403 	test(pC->Verify()==KErrNone);
   404 	test.Printf(_L("Commit 0x2000+0x3000 (overlaps previous)\n"));
   405 	test(pC->Commit(0x2000,0x3000)==KErrAlreadyExists);
   406 	test(pC->Verify()==KErrNone);
   407 	test.Printf(_L("Allocate 0x5000\n"));
   408 	test(pC->Allocate(0x5000)==0x4000);
   409 	test(pC->Verify()==KErrNone);
   410 	test.Printf(_L("Allocate 0x1000\n"));
   411 	test(pC->Allocate(0x1000)==0x1000);
   412 	test(pC->Verify()==KErrNone);
   413 	test.Printf(_L("Decommit 0+0x4000\n"));
   414 	test(pC->Decommit(0,0x4000)==KErrNone);
   415 	test(pC->Verify()==KErrNone);
   416 	test.Printf(_L("Decommit 0+0x4000 (again)\n"));
   417 	test(pC->Decommit(0,0x4000)==KErrNone);
   418 	test(pC->Verify()==KErrNone);
   419 	test.Printf(_L("Allocate 0x4000\n"));
   420 	test(pC->Allocate(0x4000)==0x0000);
   421 	test(pC->Verify()==KErrNone);
   422 	test.Printf(_L("Decommit 0+0x10000\n"));
   423 	test(pC->Decommit(0,0x10000)==KErrNone);
   424 	test(pC->Verify()==KErrNone);
   425 	test.Printf(_L("Check Free RAM\n"));
   426 	test(FreeRam()==free);
   427 
   428 	test.Printf(_L("Commit 0x700000+0x10000\n"));
   429 	test(pC->Commit(0x700000,0x10000)==KErrNone);
   430 	test(pC->Verify()==KErrNone);
   431 	test.Printf(_L("Allocate 0x4000\n"));
   432 	test(pC->Allocate(0x4000)==0x0000);
   433 	test(pC->Verify()==KErrNone);
   434 	test.Printf(_L("Decommit 0+0x800000\n"));
   435 	test(pC->Decommit(0,0x800000)==KErrNone);
   436 	test(pC->Verify()==KErrNone);
   437 	test.Printf(_L("Check Free RAM\n"));
   438 	test(FreeRam()==free);
   439 
   440 	delete pC;
   441 
   442 	// Test decommiting from a chunk which has no memory commited
   443 	// in the first megabyte. On the moving memory model, such
   444 	// chunks have a non-zero iHomeRegionOffset value and has been
   445 	// the cause of defects (DEF121857)
   446 	test.Printf(_L("Create new chunk\n"));
   447 	pC=CChunk::New(0x800000);
   448 	test(pC!=NULL);
   449 	test.Printf(_L("Commit 0x100000+0x3000\n"));
   450 	test(pC->Commit(0x100000,0x3000)==KErrNone);
   451 	test(pC->Verify()==KErrNone);
   452 	test.Printf(_L("Decommit 0+0x101000\n"));
   453 	test(pC->Decommit(0,0x101000)==KErrNone);
   454 	test(pC->Verify()==KErrNone);
   455 	test.Printf(_L("Decommit 0x101000+0x1000\n"));
   456 	test(pC->Decommit(0x101000,0x1000)==KErrNone);
   457 	test(pC->Verify()==KErrNone);
   458 	test.Printf(_L("Decommit 0x100000+0x100000\n"));
   459 	test(pC->Decommit(0x100000,0x100000)==KErrNone);
   460 	test(pC->Verify()==KErrNone);
   461 	delete pC;
   462 
   463 	test.Next(_L("Testing RThread::Write to disconnected chunks"));
   464 	RTestSession ts;
   465 	TInt r = ts.Connect();
   466 	test(r==KErrNone);
   467 	test(ts.TestRemoteWrite(64,0,0x3000,0,-1)==KErrNone);
   468 	test(ts.TestRemoteWrite(64,0xffc,0x8000,0,-1)==KErrNone);
   469 	test(ts.TestRemoteWrite(256,0xffc,0x7f80,0,-1)==KErrNone);
   470 	test(ts.TestRemoteWrite(256,0xffc,0x7f80,128,-1)==KErrNone);
   471 	test(ts.TestRemoteWrite(0x10000,0xffc,0x707f80,0,-1)==KErrNone);
   472 	test(ts.TestRemoteWrite(0x10000,0xffc,0x707f80,0x2000,-1)==KErrNone);
   473 	test(ts.TestRemoteWrite(64,-1,0x3000,0,-1)==KErrNone);
   474 	test(ts.TestRemoteWrite(0x10000,-1,0xfff00,0x2000,-1)==KErrNone);
   475 	test(ts.TestRemoteWrite(256,0xffc,0x7f80,16,0)==KErrBadDescriptor);
   476 	test(ts.TestRemoteWrite(256,0xffc,0x7f80,16,0x1000)==KErrBadDescriptor);
   477 	test(ts.TestRemoteWrite(256,0xffc,0x7f80,16,0x7000)==KErrBadDescriptor);
   478 	test(ts.TestRemoteWrite(256,0xffc,0x7f80,16,0x8000)==KErrBadDescriptor);
   479 	test(ts.TestRemoteWrite(0x10000,0xffc,0x707f80,0x2000,0x710000)==KErrBadDescriptor);
   480 	test(ts.TestRemoteWrite(0x10000,-1,0xfff00,0x1000,0x100000)==KErrBadDescriptor);
   481 	ts.Stop();
   482 
   483 	test.End();
   484 	return 0;
   485 	}