kerneltest/e32test/mmu/t_sharedchunk.cpp
changeset 0 a41df078684a
child 4 56f325a607ea
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2004-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_sharedchunk.cpp
       
    15 // Overview:
       
    16 // Test sharing an RChunk with a logical device
       
    17 // API Information:
       
    18 // RChunk
       
    19 // Details:
       
    20 // - Load and open the logical device driver ("D_SHAREDCHUNK"). Verify
       
    21 // results.
       
    22 // - Test and verify results of creating shared chunks under OOM conditions. Also verify 
       
    23 // creating a chunk with a bad type, bad size and too large all fail as 
       
    24 // expected.
       
    25 // - Test and verify opening and closing chunk user handles work as expected.
       
    26 // - Test and verify setting restrictions on RChunk if created as shared chunk are as expected.
       
    27 // - Test and verify memory access for multiply and singly shared chunks, 
       
    28 // is as expected. Including IPC, kernel, DFC and ISR reads & writes.
       
    29 // - Test and verify discontinuous memory commits for multiply and singly 
       
    30 // shared chunks are as expected.
       
    31 // - Test and verify continuous memory commits for multiply and singly shared
       
    32 // chunks are as expected.
       
    33 // - Test and verify discontinuous and continuous physical memory commits for 
       
    34 // multiply and singly shared chunks is as expected.
       
    35 // - Test Kern::OpenSharedChunk for multiply and singly shared chunks. Verify
       
    36 // results are as expected.
       
    37 // - Test that physical memory can be freed immediately after the chunk that mapped 
       
    38 // it has been closed.
       
    39 // Platforms/Drives/Compatibility:
       
    40 // All.
       
    41 // Assumptions/Requirement/Pre-requisites:
       
    42 // Failures and causes:
       
    43 // Base Port information:
       
    44 // 
       
    45 //
       
    46 
       
    47 //! @file
       
    48 //! @SYMTestCaseID KBASE-T_SHAREDCHUNK
       
    49 //! @SYMREQ 3699
       
    50 //! @SYMTestPriority High
       
    51 //! @SYMTestActions Check creation, memory allocation and access to Shared Chunks
       
    52 //! @SYMTestExpectedResults Test runs until this message is emitted: RTEST: SUCCESS : T_SHAREDCHUNK test completed O.K.
       
    53 //! @SYMTestType UT
       
    54 #define __E32TEST_EXTENSION__
       
    55 
       
    56 #include "d_sharedchunk.h"
       
    57 #include "d_gobble.h"
       
    58 #include <e32test.h>
       
    59 #include <e32hal.h>
       
    60 #include "u32std.h"
       
    61 #include <u32hal.h>
       
    62 #include <e32svr.h>
       
    63 #include <f32dbg.h>
       
    64 #include <e32def.h>
       
    65 #include <e32def_private.h>
       
    66 #include "freeram.h"
       
    67 
       
    68 enum TSlaveCommand
       
    69 	{
       
    70 	ESlaveCheckChunk,
       
    71 	ESlaveCreateChunk,
       
    72 	};
       
    73 
       
    74 //
       
    75 // Global data
       
    76 //
       
    77 
       
    78 
       
    79 RSharedChunkLdd Ldd;
       
    80 RChunk TheChunk;
       
    81 TInt PageSize;
       
    82 TUint32 MemModelAttributes;
       
    83 TBool PhysicalCommitSupported;
       
    84 TBool CachingAttributesSupported;
       
    85 TUint8 BssMem[100];
       
    86 
       
    87 const TUint ChunkSize = 0x400000;	// 4 meg reserved space for test chunk
       
    88 
       
    89 _LIT(KSecondProcessName,"t_sharedchunk");
       
    90 #ifdef __T_SHAREDCHUNKF__
       
    91 _LIT(KOtherProcessName,"t_sharedchunk");
       
    92 LOCAL_D RTest test(_L("T_SHAREDCHUNKF"));
       
    93 #else
       
    94 _LIT(KOtherProcessName,"t_sharedchunkf");
       
    95 LOCAL_D RTest test(_L("T_SHAREDCHUNK"));
       
    96 #endif
       
    97 
       
    98 _LIT8(KTestString, "lks4b7qeyfcea5fyaifyaefyi4flwdysuxanabxa");
       
    99 _LIT8(KTestString2,"jhfcalurnhfirlxszhrvcvduhrvndrucxnshxcsx");
       
   100 const TUint32 KTestValue = 0x12345678;
       
   101 const TUint32 KTestValue2 = KTestValue^0x0f0f0f0f;
       
   102 
       
   103 //
       
   104 // Utilitiies for use by tests
       
   105 //
       
   106 
       
   107 
       
   108 _LIT(KLitKernExec, "KERN-EXEC");
       
   109 
       
   110 void CheckFailMessage(const char* n,const char* c,const char* f,TInt r)
       
   111 	{
       
   112 	TPtrC8 nn((const TUint8*)n);
       
   113 	TPtrC8 cc((const TUint8*)c);
       
   114 	TPtrC8 ff((const TUint8*)f);
       
   115 	RBuf8 buf;
       
   116 	buf.Create((nn.Size()+cc.Size()+ff.Size()+64)*2);
       
   117 	buf.AppendFormat(_L8("\nCHECK failed: %S == 0x%x but was tested for %S%S\n"),&ff,r,&cc,&nn);
       
   118 	test.Printf(buf.Expand());
       
   119 	buf.Close();
       
   120 	}
       
   121 
       
   122 #define CHECK(n,c,f) \
       
   123 	{	\
       
   124 	TInt _r=(TInt)(f);	\
       
   125 	if(!((TInt)(n)c(_r)))	\
       
   126 		{	\
       
   127 		CheckFailMessage(#n,#c,#f,_r);	\
       
   128 		test(0);	\
       
   129 		}	\
       
   130 	}
       
   131 
       
   132 #define KCHECK_MEMORY(result,offset)	\
       
   133 	{	\
       
   134 	/* test.Printf(_L("check offset 0x%08x\r"),offset); */	\
       
   135 	CHECK(result,==,Ldd.CheckMemory(offset));	\
       
   136 	}
       
   137 
       
   138 #define KWRITE_MEMORY(offset,value)	\
       
   139 	{	\
       
   140 	CHECK(KErrNone,==,Ldd.WriteMemory(offset,value));	\
       
   141 	}
       
   142 
       
   143 #define UREAD_MEMORY(offset,value)	\
       
   144 	{	\
       
   145 	CHECK(value,==,*(TUint*)(Base+offset));	\
       
   146 	}
       
   147 
       
   148 inline TUint32 Tag(TUint32 offset)
       
   149 	{ return (69069u*(offset*4+1)); }
       
   150 
       
   151 TInt MemoryAccessThread(TAny* aAddress)
       
   152 	{
       
   153 	TInt r = *(volatile TUint8*)aAddress;	// read from aAddress
       
   154 	(void)r;
       
   155 	return 0;
       
   156 	}
       
   157 
       
   158 TInt CheckUMemory(TAny* aAddress)
       
   159 	{
       
   160 	RThread thread;
       
   161 	thread.Create(KNullDesC,MemoryAccessThread,PageSize,&User::Heap(),aAddress);
       
   162 	TRequestStatus status;
       
   163 	thread.Logon(status);
       
   164 	TBool jit = User::JustInTime();
       
   165 	User::SetJustInTime(EFalse);
       
   166 	thread.Resume();
       
   167 	User::WaitForRequest(status);
       
   168 	User::SetJustInTime(jit);
       
   169 	TInt r;
       
   170 	if(thread.ExitType()==EExitKill && thread.ExitReason()==0)
       
   171 		r = 1;	// Memory access pass
       
   172 	else if(thread.ExitType()==EExitPanic && thread.ExitCategory()==KLitKernExec && thread.ExitReason()==3 )
       
   173 		r = 0;	// Memory access failed
       
   174 	else
       
   175 		r = -1;	// Unexpected result
       
   176 	CLOSE_AND_WAIT(thread);
       
   177 	return r;
       
   178 	}
       
   179 
       
   180 #define UCHECK_MEMORY(result,offset)	\
       
   181 	{	\
       
   182 	/* test.Printf(_L("ucheck offset 0x%08x\r"),offset); */	\
       
   183 	CHECK(result,==,CheckUMemory(Base+offset));	\
       
   184 	}
       
   185 
       
   186 TInt CheckPlatSecPanic(TThreadFunction aThreadFunction,TInt aThreadArgument)
       
   187 	{
       
   188 	RThread thread;
       
   189 	thread.Create(KNullDesC,aThreadFunction,PageSize,&User::Heap(),(TAny*)aThreadArgument);
       
   190 	TRequestStatus status;
       
   191 	thread.Logon(status);
       
   192 	TBool jit = User::JustInTime();
       
   193 	User::SetJustInTime(EFalse);
       
   194 	thread.Resume();
       
   195 	User::WaitForRequest(status);
       
   196 	User::SetJustInTime(jit);
       
   197 	TInt r;
       
   198 	if(thread.ExitType()==EExitPanic && thread.ExitCategory()==KLitKernExec && thread.ExitReason()==46 )
       
   199 		r = 1;	// PlatSec panic
       
   200 	else if(thread.ExitType()==EExitKill && thread.ExitReason()==0)
       
   201 		r = 0;	// Exit without error
       
   202 	else
       
   203 		r = -1;	// Unexpected result
       
   204 	CLOSE_AND_WAIT(thread);
       
   205 	return r;
       
   206 	}
       
   207 
       
   208 //
       
   209 // The tests
       
   210 //
       
   211 
       
   212 void CreateWithOomCheck(TInt aCreateFlags)
       
   213 	{
       
   214 	TInt failResult=KErrGeneral;
       
   215 	for(TInt failCount=1; failCount<1000; failCount++)
       
   216 		{
       
   217 		test.Printf(_L("alloc fail count = %d\n"),failCount);
       
   218 		User::__DbgSetBurstAllocFail(ETrue,RAllocator::EFailNext,failCount,1000);
       
   219 		__KHEAP_MARK;
       
   220 		failResult = Ldd.CreateChunk(aCreateFlags);
       
   221 		if(failResult==KErrNone)
       
   222 			break;
       
   223 		CHECK(KErrNoMemory,==,failResult);
       
   224 		Ldd.IsDestroyed();	// This includes delay to let idle thread do cleanup
       
   225 		__KHEAP_MARKEND;
       
   226 		}
       
   227 	User::__DbgSetAllocFail(ETrue,RAllocator::ENone,0);
       
   228 	__KHEAP_RESET;
       
   229 	CHECK(KErrNone,==,failResult);
       
   230 	}
       
   231 
       
   232 void TestCreate()
       
   233 	{
       
   234 	test.Start(_L("Creating chunk type Single,OwnsMemory"));
       
   235 	CreateWithOomCheck(ChunkSize|ESingle|EOwnsMemory);
       
   236 	CHECK(0,==,Ldd.IsDestroyed());
       
   237 
       
   238 	test.Next(_L("Close kernel handle"));
       
   239 	CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
       
   240 	CHECK(1,==,Ldd.IsDestroyed());
       
   241 
       
   242 	test.Next(_L("Creating chunk type Multiple,OwnsMemory"));
       
   243 	CreateWithOomCheck(ChunkSize|EMultiple|EOwnsMemory);
       
   244 	CHECK(0,==,Ldd.IsDestroyed());
       
   245 
       
   246 	test.Next(_L("Close kernel handle"));
       
   247 	CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
       
   248 	CHECK(1,==,Ldd.IsDestroyed());
       
   249 
       
   250 	if(PhysicalCommitSupported)
       
   251 		{
       
   252 		test.Next(_L("Creating chunk type Single,!OwnsMemory"));
       
   253 		CreateWithOomCheck(ChunkSize|ESingle);
       
   254 		CHECK(0,==,Ldd.IsDestroyed());
       
   255 
       
   256 		test.Next(_L("Close kernel handle"));
       
   257 		CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
       
   258 		CHECK(1,==,Ldd.IsDestroyed());
       
   259 
       
   260 		test.Next(_L("Creating chunk type Multiple,!OwnsMemory"));
       
   261 		CreateWithOomCheck(ChunkSize|EMultiple);
       
   262 		CHECK(0,==,Ldd.IsDestroyed());
       
   263 
       
   264 		test.Next(_L("Close kernel handle"));
       
   265 		CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
       
   266 		CHECK(1,==,Ldd.IsDestroyed());
       
   267 		}
       
   268 	else
       
   269 		{
       
   270 		test.Next(_L("Try creating unsupported chunk type Single,!OwnsMemory"));
       
   271 		CHECK(KErrNotSupported,==,Ldd.CreateChunk(ChunkSize|ESingle));
       
   272 
       
   273 		test.Next(_L("Try creating unsupported chunk type Multiple,!OwnsMemory"));
       
   274 		CHECK(KErrNotSupported,==,Ldd.CreateChunk(ChunkSize|EMultiple));
       
   275 		}
       
   276 
       
   277 	test.Next(_L("__KHEAP_MARK"));
       
   278 	__KHEAP_MARK;
       
   279 
       
   280 	test.Next(_L("Creating chunk (bad type)"));
       
   281 	CHECK(KErrArgument,==,Ldd.CreateChunk(EBadType|EOwnsMemory|ChunkSize));
       
   282 
       
   283 	test.Next(_L("Creating chunk (bad size)"));
       
   284 	CHECK(KErrArgument,==,Ldd.CreateChunk(ESingle|EOwnsMemory|0xffffff00));
       
   285 
       
   286 	test.Next(_L("Creating chunk (size too big)"));
       
   287 	CHECK(KErrNoMemory,==,Ldd.CreateChunk(ESingle|EOwnsMemory|0x7fffff00));
       
   288 
       
   289 	test.Next(_L("__KHEAP_MARKEND"));
       
   290 	__KHEAP_MARKEND;
       
   291 
       
   292 	test.End();
       
   293 	}
       
   294 
       
   295 
       
   296 void OpenWithOomCheck(RChunk& aChunk)
       
   297 	{
       
   298 	TInt failResult=KErrGeneral;
       
   299 	for(TInt failCount=1; failCount<1000; failCount++)
       
   300 		{
       
   301 		test.Printf(_L("alloc fail count = %d\n"),failCount);
       
   302 		User::__DbgSetBurstAllocFail(ETrue,RAllocator::EFailNext,failCount,1000);
       
   303 		__KHEAP_MARK;
       
   304 		failResult = Ldd.GetChunkHandle(aChunk);
       
   305 		if(failResult==KErrNone)
       
   306 			break;
       
   307 		CHECK(KErrNoMemory,==,failResult);
       
   308 		Ldd.IsDestroyed();	// This includes delay to let idle thread do cleanup
       
   309 		__KHEAP_MARKEND;
       
   310 		}
       
   311 	User::__DbgSetAllocFail(ETrue,RAllocator::ENone,0);
       
   312 	__KHEAP_RESET;
       
   313 	CHECK(KErrNone,==,failResult);
       
   314 	}
       
   315 
       
   316 void TestHandles()
       
   317 	{
       
   318 	TUint ChunkAttribs = ChunkSize|ESingle|EOwnsMemory;
       
   319 
       
   320 	test.Start(_L("Create chunk"));
       
   321 	CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
       
   322 
       
   323 	test.Next(_L("Open user handle"));
       
   324 	OpenWithOomCheck(TheChunk);
       
   325 
       
   326 	test.Next(_L("Close user handle"));
       
   327 	TheChunk.Close();
       
   328 
       
   329 	test.Next(_L("Check chunk not destroyed"));
       
   330 	CHECK(0,==,Ldd.IsDestroyed());
       
   331 
       
   332 	test.Next(_L("Close kernel handle"));
       
   333 	CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
       
   334 
       
   335 	test.Next(_L("Check chunk destroyed"));
       
   336 	CHECK(1,==,Ldd.IsDestroyed());
       
   337 
       
   338 	// Another chunk - closing handles in reverse order
       
   339 
       
   340 	test.Next(_L("Create chunk"));
       
   341 	CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
       
   342 
       
   343 	test.Next(_L("Open user handle"));
       
   344 	OpenWithOomCheck(TheChunk);
       
   345 
       
   346 	test.Next(_L("Close kernel handle"));
       
   347 	CHECK(KErrNone,==,Ldd.CloseChunk());
       
   348 
       
   349 	test.Next(_L("Check chunk not destroyed"));
       
   350 	CHECK(0,==,Ldd.IsDestroyed());
       
   351 
       
   352 	test.Next(_L("Using user handle to check chunk info"));
       
   353 	if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
       
   354 		{
       
   355 		CHECK(0,==,TheChunk.Size());
       
   356 		}
       
   357 	CHECK(ChunkSize,==,TheChunk.MaxSize());
       
   358 
       
   359 	test.Next(_L("Close user handle"));
       
   360 	TheChunk.Close();
       
   361 
       
   362 	test.Next(_L("Check chunk destroyed"));
       
   363 	CHECK(1,==,Ldd.IsDestroyed());
       
   364 
       
   365 	test.End();
       
   366 	}
       
   367 
       
   368 
       
   369 void SetCreateFlags(TUint& aCreateFlags,TCommitType aCommitType)
       
   370 	{
       
   371 	if(!((TInt)aCommitType&EPhysicalMask))
       
   372 		aCreateFlags |= EOwnsMemory;
       
   373 	else
       
   374 		aCreateFlags &= ~EOwnsMemory;
       
   375 	}
       
   376 
       
   377 
       
   378 void TestAccess(TUint aCreateFlags,TCommitType aCommitType)
       
   379 	{
       
   380 	const TUint32 offset = 0;
       
   381 	const TUint32 size = PageSize;
       
   382 
       
   383 	SetCreateFlags(aCreateFlags,aCommitType);
       
   384 
       
   385 	test.Start(_L("Create chunk"));
       
   386 	TUint8* kernelAddress;
       
   387 	CHECK(KErrNone,==,Ldd.CreateChunk(aCreateFlags|ChunkSize,(TAny**)&kernelAddress));
       
   388 
       
   389 	if((MemModelAttributes&TUint32(EMemModelAttrNonExProt)) && (MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
       
   390 		{
       
   391 		test.Next(_L("Check can't access memory"));
       
   392 		KCHECK_MEMORY(EFalse,offset);
       
   393 		}
       
   394 
       
   395 	test.Next(_L("Commit page to chunk"));
       
   396 	CHECK(KErrNone,==,Ldd.CommitMemory(aCommitType|offset,size));
       
   397 
       
   398 	test.Next(_L("Check can access memory kernel side"));
       
   399 	KCHECK_MEMORY(ETrue, offset);
       
   400 
       
   401 	if((MemModelAttributes&EMemModelAttrKernProt) && (MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
       
   402 		{
       
   403 		test.Next(_L("Check user side can't access kernel memory"));
       
   404 		TUint8* Base = kernelAddress;
       
   405 		UCHECK_MEMORY(EFalse, offset);
       
   406 		}
       
   407 
       
   408 	test.Next(_L("Open user handle"));
       
   409 	CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
       
   410 
       
   411 	test.Next(_L("Get memory size info"));
       
   412 	if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
       
   413 		{
       
   414 		CHECK(PageSize,==,TheChunk.Size());
       
   415 		}
       
   416 	CHECK(ChunkSize,==,TheChunk.MaxSize());
       
   417 	TUint8* Base = TheChunk.Base();
       
   418 	CHECK(Base,!=,0);
       
   419 
       
   420 	test.Next(_L("Check can access memory user side"));
       
   421 	UCHECK_MEMORY(ETrue, offset);
       
   422 
       
   423 	test.Next(_L("Check user and kernel access same memory"));
       
   424 	KWRITE_MEMORY(offset,~Tag(offset));
       
   425 	UREAD_MEMORY(offset,~Tag(offset));
       
   426 	KWRITE_MEMORY(offset,Tag(offset));
       
   427 	UREAD_MEMORY(offset,Tag(offset));
       
   428 
       
   429 	test.Next(_L("Close user handle"));
       
   430 	CHECK(0,==,Ldd.CloseChunkHandle(TheChunk));
       
   431 	CHECK(0,==,Ldd.IsDestroyed());
       
   432 
       
   433 	if((MemModelAttributes&EMemModelAttrKernProt) && (MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
       
   434 		{
       
   435 		test.Next(_L("Check can no-longer access memory user side"));
       
   436 		UCHECK_MEMORY(EFalse,offset);
       
   437 		}
       
   438 
       
   439 	test.Next(_L("Check can still access memory kernel side"));
       
   440 	KCHECK_MEMORY(ETrue, offset);
       
   441 
       
   442 	test.Next(_L("Open user handle again"));
       
   443 	CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
       
   444 
       
   445 	test.Next(_L("Check can access chunk user side again"));
       
   446 	CHECK(Base,==,TheChunk.Base());
       
   447 	CHECK(ChunkSize,==,TheChunk.MaxSize());
       
   448 	if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
       
   449 		{
       
   450 		CHECK(size,==,TheChunk.Size());
       
   451 		}
       
   452 	UREAD_MEMORY(offset,Tag(offset));
       
   453 
       
   454 	test.Next(_L("Close kernel handle"));
       
   455 	CHECK(0,==,Ldd.CloseChunk());
       
   456 	CHECK(0,==,Ldd.IsDestroyed());
       
   457 
       
   458 	test.Next(_L("Check can still access chunk user side"));
       
   459 	CHECK(Base,==,TheChunk.Base());
       
   460 	CHECK(ChunkSize,==,TheChunk.MaxSize());
       
   461 	if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
       
   462 		{
       
   463 		CHECK(size,==,TheChunk.Size());
       
   464 		}
       
   465 	UREAD_MEMORY(offset,Tag(offset));
       
   466 
       
   467 	test.Next(_L("Close user handle"));
       
   468 	TheChunk.Close();
       
   469 	CHECK(1,==,Ldd.IsDestroyed());
       
   470 
       
   471 	test.Next(_L("Create chunk in another process"));
       
   472 
       
   473 	// Create test server
       
   474 	RServer2 server;
       
   475 	RMessage2 message;
       
   476 	TRequestStatus status;
       
   477 	CHECK(KErrNone,==,server.CreateGlobal(KSecondProcessName));
       
   478 	server.Receive(message,status);
       
   479 
       
   480 	// Launch slave process
       
   481 	RProcess process;
       
   482 	CHECK(KErrNone,==,process.Create(KSecondProcessName,KNullDesC));
       
   483 	CHECK(KErrNone,==,process.SetParameter(1,ESlaveCreateChunk));
       
   484 	CHECK(KErrNone,==,process.SetParameter(2,(RBusLogicalChannel&)Ldd));
       
   485 	CHECK(KErrNone,==,process.SetParameter(3,ChunkSize|aCreateFlags));
       
   486 	CHECK(KErrNone,==,process.SetParameter(4,aCommitType));
       
   487 	CHECK(KErrNone,==,process.SetParameter(5,PageSize));
       
   488 	TRequestStatus logon;
       
   489 	process.Logon(logon);
       
   490 	process.Resume();
       
   491 
       
   492 	// Wait for slave to connect to test server
       
   493 	User::WaitForRequest(logon,status);
       
   494 	CHECK(KRequestPending,==,logon.Int())
       
   495 	CHECK(KErrNone,==,status.Int());
       
   496 	CHECK(RMessage2::EConnect,==,message.Function());
       
   497 	message.Complete(KErrNone);
       
   498 	server.Receive(message,status);
       
   499 
       
   500 	// Wait for message
       
   501 	User::WaitForRequest(logon,status);
       
   502 	CHECK(KRequestPending,==,logon.Int())
       
   503 	CHECK(KErrNone,==,status.Int());
       
   504 	CHECK(0,==,message.Function());
       
   505 
       
   506 	test.Next(_L("Check IPC read/write"));
       
   507 	RBuf8 buf;
       
   508 	buf.Create(KTestString().Size());
       
   509 	CHECK(KErrNone,==,message.Read(0,buf));
       
   510 	CHECK(ETrue,==,buf==KTestString());
       
   511 	CHECK(KErrNone,==,message.Write(0,KTestString2));
       
   512 	CHECK(KErrNone,==,message.Read(0,buf));
       
   513 	CHECK(ETrue,==,buf==KTestString2());
       
   514 
       
   515 	test.Next(_L("Check Kernel read/write"));
       
   516 	TInt n;
       
   517 	TUint32 value;
       
   518 	for(n=0; n<KTestString2().Size()-(TInt)sizeof(TInt)+1; n+=sizeof(TInt))
       
   519 		{
       
   520 		Ldd.ReadMemory(n,value);
       
   521 		CHECK(*(TInt*)&KTestString2()[n],==,value);
       
   522 		CHECK(KErrNone,==,Ldd.WriteMemory(n,*(TInt*)&KTestString()[n]));
       
   523 		Ldd.ReadMemory(n,value);
       
   524 		CHECK(*(TInt*)&KTestString()[n],==,value);
       
   525 		}
       
   526 	CHECK(KErrNone,==,message.Read(0,buf));
       
   527 	CHECK(ETrue,==,buf==KTestString());
       
   528 	buf.Close();
       
   529 
       
   530 	test.Next(_L("Check read/write from DFC"));
       
   531 	CHECK(KErrNone,==,Ldd.WriteMemory(0,KTestValue));
       
   532 	value = KTestValue2;
       
   533 	CHECK(KErrNone,==,Ldd.DfcReadWrite(0,value));
       
   534 	CHECK(KTestValue,==,value);
       
   535 	CHECK(KErrNone,==,Ldd.ReadMemory(0,value));
       
   536 	CHECK(KTestValue2,==,value);
       
   537 	
       
   538 	test.Next(_L("Check read/write from ISR"));
       
   539 	CHECK(KErrNone,==,Ldd.WriteMemory(0,KTestValue));
       
   540 	value = KTestValue2;
       
   541 	CHECK(KErrNone,==,Ldd.IsrReadWrite(0,value));
       
   542 	CHECK(KTestValue,==,value);
       
   543 	CHECK(KErrNone,==,Ldd.ReadMemory(0,value));
       
   544 	CHECK(KTestValue2,==,value);
       
   545 
       
   546 	test.Next(_L("Cleanup resources"));
       
   547 	server.Close();
       
   548 	User::WaitForRequest(logon);
       
   549 	CLOSE_AND_WAIT(process);
       
   550 
       
   551 	test.End();
       
   552 	}
       
   553 
       
   554 
       
   555 RProcess OtherProcess;
       
   556 
       
   557 TInt HandleShare(TAny* aHandle)
       
   558 	{
       
   559 	TInt r=OtherProcess.Create(KOtherProcessName,KNullDesC,EOwnerProcess);
       
   560 	if(r==KErrNone)
       
   561 		{
       
   562 		r = OtherProcess.SetParameter(1,(RChunk&)aHandle);
       
   563 		}
       
   564 	return r;
       
   565 	}
       
   566 
       
   567 void TestRestrictions(TInt aAttrib)
       
   568 	{
       
   569 	TUint ChunkAttribs = ChunkSize|aAttrib|EOwnsMemory;
       
   570 
       
   571 	test.Start(_L("Create chunk"));
       
   572 	CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
       
   573 
       
   574 	test.Next(_L("Open user handle"));
       
   575 	CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
       
   576 
       
   577 	test.Next(_L("Try changing restrictions"));
       
   578 	CHECK(KErrAccessDenied,==,TheChunk.SetRestrictions(0));
       
   579 
       
   580 	test.Next(_L("Check allocation restrictions"));
       
   581 	CHECK(KErrAccessDenied,==,TheChunk.Adjust(ChunkSize/2));
       
   582 	CHECK(KErrAccessDenied,==,TheChunk.AdjustDoubleEnded(PageSize,ChunkSize));
       
   583 	CHECK(KErrAccessDenied,==,TheChunk.Commit(PageSize,PageSize));
       
   584 	CHECK(KErrAccessDenied,==,TheChunk.Allocate(PageSize));
       
   585 	CHECK(KErrAccessDenied,==,TheChunk.Decommit(PageSize,PageSize));
       
   586 
       
   587 	test.Next(_L("Duplicate handle in same process"));
       
   588 	RChunk chunk2;
       
   589 	chunk2.SetHandle(TheChunk.Handle());
       
   590 	CHECK(KErrNone,==,chunk2.Duplicate(RThread(),EOwnerProcess));
       
   591 
       
   592 	test.Next(_L("Try passing handle to other process"));
       
   593 	if(aAttrib==EMultiple)
       
   594 		{
       
   595 		CHECK(0,==,CheckPlatSecPanic(HandleShare,*(TInt*)&chunk2));
       
   596 		}
       
   597 	else
       
   598 		{
       
   599 		CHECK(1,==,CheckPlatSecPanic(HandleShare,*(TInt*)&chunk2));
       
   600 		}
       
   601 	// Cleanup leftover process
       
   602 	OtherProcess.Kill(0);
       
   603 	OtherProcess.Close();
       
   604 
       
   605 	test.Next(_L("Close handles"));
       
   606 	chunk2.Close();
       
   607 	CHECK(0,==,Ldd.CloseChunk());
       
   608 	TheChunk.Close();
       
   609 
       
   610 	test.End();
       
   611 	}
       
   612 
       
   613 
       
   614 class TCommitRegion
       
   615 	{
       
   616 public:
       
   617 	TInt iOffset;
       
   618 	TInt iSize;
       
   619 	TInt iExpectedResult;
       
   620 	};
       
   621 
       
   622 void CheckRegion(TCommitRegion aRegion, TBool aCheckClear)
       
   623 	{
       
   624 	TUint8* Base = TheChunk.Base();
       
   625 	TInt offset = aRegion.iOffset*PageSize;
       
   626 	TInt limit = offset+aRegion.iSize*PageSize;
       
   627 	while(offset<limit)
       
   628 		{
       
   629 		KCHECK_MEMORY(1,offset);
       
   630 		UCHECK_MEMORY(1,offset);
       
   631 		offset += PageSize;
       
   632 		}
       
   633 	if(!aCheckClear)
       
   634 		return;
       
   635 
       
   636 	TUint32* ptr = (TUint32*)(Base+aRegion.iOffset*PageSize);
       
   637 	TUint32* end = (TUint32*)((TInt)ptr+aRegion.iSize*PageSize);
       
   638 	while(ptr<end)
       
   639 		if(*ptr++!=0x03030303u)
       
   640 			{
       
   641 			CHECK(0x03030303u,==,*ptr);
       
   642 			}
       
   643 	};
       
   644 
       
   645 void SetTags(TCommitRegion aRegion)
       
   646 	{
       
   647 	TUint8* Base = TheChunk.Base();
       
   648 	TInt offset = aRegion.iOffset*PageSize;
       
   649 	TInt limit = offset+aRegion.iSize*PageSize;
       
   650 	while(offset<limit)
       
   651 		{
       
   652 		*(TUint*)(Base+offset) = Tag(offset);
       
   653 		offset += sizeof(TUint);
       
   654 		}
       
   655 	};
       
   656 
       
   657 void CheckTags(const TCommitRegion& aRegion)
       
   658 	{
       
   659 	TUint8* Base = TheChunk.Base();
       
   660 	TInt offset = aRegion.iOffset*PageSize;
       
   661 	TInt limit = offset+aRegion.iSize*PageSize;
       
   662 	while(offset<limit)
       
   663 		{
       
   664 		KCHECK_MEMORY(1,offset);	// Check page exists
       
   665 		TInt limit2 = offset+PageSize;
       
   666 		while(offset<limit2)
       
   667 			{
       
   668 			UREAD_MEMORY(offset,Tag(offset));	// Check contents match tags we set previousely
       
   669 			offset += sizeof(TUint);
       
   670 			}
       
   671 		}
       
   672 	};
       
   673 
       
   674 void CheckOldTags(const TCommitRegion& aRegion, TInt aNewOffset)
       
   675 	{
       
   676 	TUint8* Base = TheChunk.Base();
       
   677 	TInt oldOffset = aRegion.iOffset*PageSize;
       
   678 	TInt offset = aNewOffset;
       
   679 	TInt limit = offset+aRegion.iSize*PageSize;
       
   680 	while(offset<limit)
       
   681 		{
       
   682 		KCHECK_MEMORY(1,offset);	// Check page exists
       
   683 		TInt limit2 = offset+PageSize;
       
   684 		while(offset<limit2)
       
   685 			{
       
   686 			UREAD_MEMORY(offset,Tag(oldOffset));	// Check contents matched old tags
       
   687 			offset += sizeof(TUint);
       
   688 			oldOffset += sizeof(TUint);
       
   689 			}
       
   690 		}
       
   691 	};
       
   692 
       
   693 // Following assumes 4k pages...
       
   694 static const TCommitRegion CommitList[] =
       
   695 	{
       
   696 		{0,0},		// zero size commit
       
   697 		{1,1},		// page 1
       
   698 
       
   699 		// Regions which overlap previous commit
       
   700 		{1,1,KErrAlreadyExists},
       
   701 		{0,2,KErrAlreadyExists},
       
   702 		{1,2,KErrAlreadyExists},
       
   703 		{0,3,KErrAlreadyExists},
       
   704 
       
   705 		{0,1},		// page 0
       
   706 		{2,1},		// page 2
       
   707 
       
   708 		{250,6},	// pages at end of chunk boundary
       
   709 
       
   710 		{768,256},	// whole 1meg chunk
       
   711 
       
   712 		{400,512,KErrAlreadyExists},	// Monster commit which overlaps previous regions
       
   713 
       
   714 		{256,257},	// big commit which straddles more than one 1meg chunk
       
   715 
       
   716 		{-1,-1} // End marker
       
   717 	};
       
   718 
       
   719 void CheckCommitedContents(TInt aIndex)
       
   720 	{
       
   721 	while(--aIndex>=0)
       
   722 		if(CommitList[aIndex].iExpectedResult==KErrNone)
       
   723 			CheckTags(CommitList[aIndex]);
       
   724 	};
       
   725 
       
   726 void CheckCommitState(TInt aIndex)
       
   727 	{
       
   728 	TInt page=0;
       
   729 	TInt lastPage=TheChunk.MaxSize()/PageSize;
       
   730 	while(page<lastPage)
       
   731 		{
       
   732 		TInt i=aIndex;
       
   733 		while(--i>=0)
       
   734 			if(CommitList[i].iExpectedResult==KErrNone)
       
   735 				if((TUint)(page-CommitList[i].iOffset) < (TUint)CommitList[i].iSize)
       
   736 					break;
       
   737 		TInt offset = page*PageSize;
       
   738 		if(i>=0)
       
   739 			{
       
   740 			KCHECK_MEMORY(1,offset);	// Check page exists
       
   741 			}
       
   742 		else
       
   743 			{
       
   744 			KCHECK_MEMORY(0,offset);	// Check page doesn't exists
       
   745 			}
       
   746 		++page;
       
   747 		}
       
   748 	};
       
   749 
       
   750 
       
   751 void TestCommit(TUint aCreateFlags,TCommitType aCommitType)
       
   752 	{
       
   753 	SetCreateFlags(aCreateFlags,aCommitType);
       
   754 	TUint ChunkAttribs = ChunkSize|aCreateFlags;
       
   755 
       
   756 	test.Start(_L("Create chunk"));
       
   757 	CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
       
   758 
       
   759 	test.Next(_L("Check wrong commit type"));
       
   760 	CHECK(KErrNotSupported,==,Ldd.CommitMemory((aCommitType^EPhysicalMask)|0,PageSize));
       
   761 	CHECK(KErrNotSupported,==,Ldd.CommitMemory((aCommitType^EPhysicalMask^EContiguous)|0,PageSize));
       
   762 
       
   763 	if((TInt)aCommitType&EPhysicalMask)
       
   764 		{
       
   765 		test.Next(_L("Check commit with bad pysical address"));
       
   766 		CHECK(KErrArgument,==,Ldd.CommitMemory((aCommitType|EBadPhysicalAddress)|0,PageSize));
       
   767 		}
       
   768 
       
   769 	test.Next(_L("Open user handle"));
       
   770 	CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
       
   771 
       
   772 	const TCommitRegion* list = CommitList;
       
   773 	for(;list->iOffset>=0; ++list)
       
   774 		{
       
   775 		TInt offset = list->iOffset*PageSize;
       
   776 		TInt size = list->iSize*PageSize;
       
   777 		TInt expectedResult = list->iExpectedResult;
       
   778 		if((MemModelAttributes&EMemModelTypeMask)==EMemModelTypeDirect && expectedResult==KErrAlreadyExists)
       
   779 			continue;
       
   780 		TBuf<100> text;
       
   781 		text.AppendFormat(_L("Commit pages: offset=%08x size=%08x expectedResult=%d"),offset,size,expectedResult);
       
   782 		test.Next(text);
       
   783 
       
   784 		test.Start(_L("Do the Commit"));
       
   785 		CHECK(expectedResult,==,Ldd.CommitMemory(aCommitType|offset,size));
       
   786 
       
   787 		if(expectedResult==KErrNone)
       
   788 			{
       
   789 			test.Next(_L("Check new memory has been comitted"));
       
   790 			CheckRegion(*list,!(aCommitType&EPhysicalMask));
       
   791 			}
       
   792 
       
   793 		if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
       
   794 			{
       
   795 			test.Next(_L("Check commit state of all pages in chunk"));
       
   796 			CheckCommitState(list-CommitList+1);
       
   797 			}
       
   798 
       
   799 		test.Next(_L("Check contents of previous commited regions are unchanged"));
       
   800 		CheckCommitedContents(list-CommitList);
       
   801 
       
   802 		if(expectedResult==KErrNone)
       
   803 			{
       
   804 			test.Next(_L("Mark new memory"));
       
   805 			SetTags(*list);
       
   806 			}
       
   807 		test.End();
       
   808 		}
       
   809 
       
   810 	if((aCreateFlags&EMultiple) && (MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
       
   811 		{
       
   812 		test.Next(_L("Check another process sees same chunk state"));
       
   813 		TInt regionCount = list-CommitList;
       
   814 
       
   815 		// create another process
       
   816 		RProcess process;
       
   817 		CHECK(KErrNone,==,process.Create(KOtherProcessName,KNullDesC));
       
   818 		CHECK(KErrNone,==,process.SetParameter(1,ESlaveCheckChunk));
       
   819 		CHECK(KErrNone,==,process.SetParameter(2,(RBusLogicalChannel&)Ldd));
       
   820 		CHECK(KErrNone,==,process.SetParameter(3,(RChunk&)TheChunk));
       
   821 		CHECK(KErrNone,==,process.SetParameter(4,regionCount));
       
   822 		TRequestStatus status;
       
   823 		process.Logon(status);
       
   824 		process.Resume();
       
   825 
       
   826 		// Check chunk again in this process, concurrently with other process
       
   827 		CheckCommitedContents(regionCount);
       
   828 		CheckCommitState(regionCount);
       
   829 
       
   830 		// wait for other process to finish
       
   831 		User::WaitForRequest(status);
       
   832 		CHECK(EExitKill,==,process.ExitType());
       
   833 		CHECK(0,==,process.ExitReason());
       
   834 		CLOSE_AND_WAIT(process);
       
   835 		}
       
   836 
       
   837 	test.Next(_L("Close handles"));
       
   838 	TheChunk.Close();
       
   839 	CHECK(1,==,Ldd.CloseChunk());
       
   840 
       
   841 	if(aCommitType&EPhysicalMask)
       
   842 		{
       
   843 		// For Physical commit tests, check correct allocation by creating a new chunk
       
   844 		// and checking that pages comitted contain the old TAGs placed there by the
       
   845 		// tests above.
       
   846 
       
   847 		test.Next(_L("Check commit uses correct physical pages"));
       
   848 
       
   849 		test.Start(_L("Create chunk"));
       
   850 		CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
       
   851 
       
   852 		test.Next(_L("Open user handle"));
       
   853 		CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
       
   854 
       
   855 		TInt offset = 0;
       
   856 		for(list=CommitList; list->iOffset>=0; ++list)
       
   857 			{
       
   858 			if(list->iExpectedResult!=KErrNone)
       
   859 				continue;
       
   860 
       
   861 			TInt size = list->iSize*PageSize;
       
   862 			TBuf<100> text;
       
   863 			text.AppendFormat(_L("Commit pages: offset=%08x size=%08x"),offset,size);
       
   864 			test.Next(text);
       
   865 			CHECK(KErrNone,==,Ldd.CommitMemory(aCommitType|offset,size));
       
   866 
       
   867 			test.Next(_L("Check RAM contents preserved from previous usage"));
       
   868 			CheckOldTags(*list,offset);
       
   869 			offset += size;
       
   870 			}
       
   871 
       
   872 		test.Next(_L("Close handles"));
       
   873 		TheChunk.Close();
       
   874 		CHECK(1,==,Ldd.CloseChunk());
       
   875 
       
   876 		test.End();
       
   877 		}
       
   878 	else
       
   879 		{
       
   880 		// We don't do these OOM tests for Physical commit because we can't do it reliably
       
   881 		// (as only a couple of page tables come from the free pool not the whole memory
       
   882 		// to be comitted)
       
   883 		test.Next(_L("Check Out Of Memory conditions"));
       
   884 
       
   885 		// Make sure any clean up has happened otherwise the amount of free RAM may change.
       
   886 		UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
       
   887 
       
   888 		test.Start(_L("Gobble up most of RAM"));
       
   889 		test.Next(_L("Load gobbler LDD"));
       
   890 		TInt r = User::LoadLogicalDevice(KGobblerLddFileName);
       
   891 		test(r==KErrNone || r==KErrAlreadyExists);
       
   892 		RGobbler gobbler;
       
   893 		r = gobbler.Open();
       
   894 		test(r==KErrNone);
       
   895 		TUint32 taken = gobbler.GobbleRAM(2*1024*1024);
       
   896 		test.Printf(_L("Gobbled: %dK\n"), taken/1024);
       
   897 		test.Printf(_L("Free RAM 0x%08X bytes\n"),FreeRam());
       
   898 
       
   899 		test.Next(_L("Get baseline free memory"));
       
   900 		__KHEAP_MARK;
       
   901 		TInt freeRam1 = FreeRam();
       
   902 
       
   903 		test.Next(_L("Create shared chunk"));
       
   904 		CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
       
   905 		TInt freeRam2 = FreeRam();
       
   906 
       
   907 		test.Next(_L("Commit memory which will causes OOM"));
       
   908 		CHECK(KErrNoMemory,==,Ldd.CommitMemory(aCommitType,4096*1024));
       
   909 
       
   910 		test.Next(_L("Check free RAM unchanged"));
       
   911 		CHECK(freeRam2,==,FreeRam());
       
   912 
       
   913 		test.Next(_L("Check OOM during ChunkCommit"));
       
   914 		TInt failResult=KErrGeneral;
       
   915 		for(TInt failCount=1; failCount<1000; failCount++)
       
   916 			{
       
   917 			User::__DbgSetAllocFail(ETrue,RAllocator::EFailNext,failCount);
       
   918 			failResult = Ldd.CommitMemory(aCommitType,1);
       
   919 			if(failResult==KErrNone)
       
   920 				break;
       
   921 			CHECK(KErrNoMemory,==,failResult);
       
   922 			}
       
   923 		User::__DbgSetAllocFail(ETrue,RAllocator::ENone,0);
       
   924 		CHECK(KErrNone,==,failResult);
       
   925 
       
   926 		test.Next(_L("Destroy shared chunk"));
       
   927 		CHECK(1,==,Ldd.CloseChunk());
       
   928 		CHECK(1,==,Ldd.IsDestroyed());
       
   929 
       
   930 		test.Next(_L("Check free memory returns to baseline"));
       
   931 		CHECK(freeRam1,==,FreeRam());
       
   932 		__KHEAP_MARKEND;
       
   933 
       
   934 		test.Next(_L("Free gobbled RAM"));
       
   935 		gobbler.Close();
       
   936 
       
   937 		test.End();
       
   938 		}
       
   939 
       
   940 	test.End();
       
   941 	}
       
   942 
       
   943 
       
   944 void TestOpenSharedChunk(TUint aCreateFlags,TCommitType aCommitType)
       
   945 	{
       
   946 	SetCreateFlags(aCreateFlags,aCommitType);
       
   947 	TUint ChunkAttribs = ChunkSize|aCreateFlags;
       
   948 
       
   949 	test.Start(_L("Create chunk"));
       
   950 	CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
       
   951 
       
   952 	test.Next(_L("Open user handle"));
       
   953 	CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
       
   954 
       
   955 	test.Next(_L("Commit some memory"));
       
   956 	CHECK(KErrNone,==,Ldd.CommitMemory(aCommitType|1*PageSize,PageSize));
       
   957 	CHECK(KErrNone,==,Ldd.CommitMemory(aCommitType|2*PageSize,PageSize));
       
   958 	CHECK(KErrNone,==,Ldd.CommitMemory(aCommitType|4*PageSize,PageSize));
       
   959 
       
   960 	test.Next(_L("Check OpenSharedChunk with handle"));
       
   961 	CHECK(KErrNone,==,Ldd.TestOpenHandle(TheChunk.Handle()));
       
   962 
       
   963 	test.Next(_L("Check OpenSharedChunk with wrong chunk handle"));
       
   964 	RChunk testChunk;
       
   965 	CHECK(KErrNone,==,testChunk.CreateLocal(PageSize,PageSize));
       
   966 	CHECK(KErrNotFound,==,Ldd.TestOpenHandle(testChunk.Handle()));
       
   967 	testChunk.Close();
       
   968 
       
   969 	test.Next(_L("Check OpenSharedChunk with wrong handle type"));
       
   970 	CHECK(KErrNotFound,==,Ldd.TestOpenHandle(RThread().Handle()));
       
   971 
       
   972 	test.Next(_L("Check OpenSharedChunk with bad handle"));
       
   973 	CHECK(KErrNotFound,==,Ldd.TestOpenHandle(0));
       
   974 
       
   975 	test.Next(_L("Check OpenSharedChunk with address"));
       
   976 	TUint8* Base = TheChunk.Base();
       
   977 	CHECK(KErrNone,==,Ldd.TestOpenAddress(Base));
       
   978 	CHECK(KErrNone,==,Ldd.TestOpenAddress(Base+ChunkSize-1));
       
   979 
       
   980 	test.Next(_L("Check OpenSharedChunk with bad address"));
       
   981 	CHECK(KErrNotFound,==,Ldd.TestOpenAddress(Base-1));
       
   982 	CHECK(KErrNotFound,==,Ldd.TestOpenAddress(Base+ChunkSize));
       
   983 	CHECK(KErrNotFound,==,Ldd.TestOpenAddress(0));
       
   984 	CHECK(KErrNotFound,==,Ldd.TestOpenAddress((TAny*)~0));
       
   985 
       
   986 	test.Next(_L("Check OpenSharedChunk with stack memory address"));
       
   987 	TUint8 stackMem[100];
       
   988 	CHECK(KErrNotFound,==,Ldd.TestOpenAddress(stackMem));
       
   989 
       
   990 	test.Next(_L("Check OpenSharedChunk with heap memory address"));
       
   991 	TUint8* heapMem = new TUint8[100];
       
   992 	CHECK(0,!=,heapMem);
       
   993 	CHECK(KErrNotFound,==,Ldd.TestOpenAddress(heapMem));
       
   994 	delete [] heapMem;
       
   995 
       
   996 	test.Next(_L("Check OpenSharedChunk with BSS memory address"));
       
   997 	CHECK(KErrNotFound,==,Ldd.TestOpenAddress(BssMem));
       
   998 
       
   999 	test.Next(_L("Check OpenSharedChunk with code memory address"));
       
  1000 	CHECK(KErrNotFound,==,Ldd.TestOpenAddress((TAny*)&TestOpenSharedChunk));
       
  1001 
       
  1002 	test.Next(_L("Check OpenSharedChunk with NULL address"));
       
  1003 	CHECK(KErrNotFound,==,Ldd.TestOpenAddress(0));
       
  1004 
       
  1005 	test.Next(_L("Check ChunkAddress for given memory region"));
       
  1006 	static const TCommitRegion regions[] = 
       
  1007 		{
       
  1008 			{0,1,KErrNotFound},
       
  1009 			{0,2,KErrNotFound},
       
  1010 			{0,3,KErrNotFound},
       
  1011 			{1,1},
       
  1012 			{1,2},
       
  1013 			{1,3,KErrNotFound},
       
  1014 			{2,1},
       
  1015 			{2,2,KErrNotFound},
       
  1016 			{2,3,KErrNotFound},
       
  1017 			{3,1,KErrNotFound},
       
  1018 			{3,2,KErrNotFound},
       
  1019 			{3,3,KErrNotFound},
       
  1020 			{4,1},
       
  1021 			{4,2,KErrNotFound},
       
  1022 			{4,3,KErrNotFound},
       
  1023 			{0,10240,KErrArgument}, // too big
       
  1024 			{1,0,KErrArgument}, // bad size
       
  1025 			{1,-1,KErrArgument}, // bad size
       
  1026 			{10240,1,KErrArgument}, // bad offset
       
  1027 			{-2,2,KErrArgument}, // bad offset
       
  1028 			{-1}
       
  1029 		};
       
  1030 	const TCommitRegion* region = regions;
       
  1031 	for(;region->iOffset!=-1; ++region)
       
  1032 		{
       
  1033 		TUint32 offset = region->iOffset*PageSize;
       
  1034 		TUint32 size = region->iSize*PageSize;
       
  1035 		TInt expectedResult = region->iExpectedResult;
       
  1036 		if((MemModelAttributes&EMemModelTypeMask)==EMemModelTypeDirect && expectedResult==KErrNotFound)
       
  1037 			continue;
       
  1038 		TBuf<100> text;
       
  1039 		text.AppendFormat(_L("Memory region: offset=%08x size=%08x expectedResult=%d"),offset,size,expectedResult);
       
  1040 		test.Next(text);
       
  1041 		CHECK(expectedResult,==,Ldd.TestAddress(offset,size));
       
  1042 		}
       
  1043 
       
  1044 	test.Next(_L("Close handles"));
       
  1045 	TheChunk.Close();
       
  1046 	CHECK(1,==,Ldd.CloseChunk());
       
  1047 
       
  1048 	test.End();
       
  1049 	}
       
  1050 
       
  1051 
       
  1052 void AccessSpeed(TCreateFlags aCreateFlags, TInt& aRead,TInt& aWrite)
       
  1053 	{
       
  1054 //	test.Start(_L("Create chunk"));
       
  1055 	CHECK(KErrNone,==,Ldd.CreateChunk(ChunkSize|ESingle|EOwnsMemory|aCreateFlags));
       
  1056 
       
  1057 //	test.Next(_L("Commit some memory"));
       
  1058 	if((MemModelAttributes&EMemModelTypeMask)==EMemModelTypeDirect)
       
  1059 		{
       
  1060 		CHECK(KErrNone,==,Ldd.CommitMemory(EDiscontiguous|0*PageSize,PageSize));
       
  1061 		}
       
  1062 	else
       
  1063 		{
       
  1064 		// Allocate contiguous memory when possible so that the
       
  1065 		// Cache::SyncMemoryBeforeXxxx calls in the test driver get exercised
       
  1066 		CHECK(KErrNone,==,Ldd.CommitMemory(EContiguous|0*PageSize,PageSize));
       
  1067 		}
       
  1068 
       
  1069 //	test.Next(_L("Open user handle"));
       
  1070 	CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
       
  1071 	volatile TUint32* p = (TUint32*)TheChunk.Base();
       
  1072 
       
  1073 	TUint32 time;
       
  1074 	TInt itterCount=128;
       
  1075 	do
       
  1076 		{
       
  1077 		itterCount *= 2;
       
  1078 		TUint32 lastCount=User::NTickCount();
       
  1079 		for(TInt i=itterCount; i>0; --i)
       
  1080 			{
       
  1081 			TUint32 x=p[0]; x=p[1]; x=p[2]; x=p[3]; x=p[4]; x=p[5]; x=p[6]; x=p[7];
       
  1082 			}
       
  1083 		time = User::NTickCount()-lastCount;
       
  1084 		}
       
  1085 	while(time<200);
       
  1086 	aRead = itterCount*8/time;
       
  1087 
       
  1088 	itterCount=128;
       
  1089 	do
       
  1090 		{
       
  1091 		itterCount *= 2;
       
  1092 		TUint32 lastCount=User::NTickCount();
       
  1093 		for(TInt i=itterCount; i>0; --i)
       
  1094 			{
       
  1095 			p[0]=i; p[1]=i; p[2]=i; p[3]=i; p[4]=i; p[5]=i; p[6]=i; p[7]=i;
       
  1096 			}
       
  1097 		time = User::NTickCount()-lastCount;
       
  1098 		}
       
  1099 	while(time<200);
       
  1100 	aWrite = itterCount*8/time;
       
  1101 
       
  1102 	TBuf<100> text;
       
  1103 	text.AppendFormat(_L("Read speed=%7d    Write speed=%7d\n"),aRead,aWrite);
       
  1104 	test.Printf(text);
       
  1105 
       
  1106 //	test.Next(_L("Close handles"));
       
  1107 	TheChunk.Close();
       
  1108 	CHECK(1,==,Ldd.CloseChunk());
       
  1109 
       
  1110 //	test.End();
       
  1111 	}
       
  1112 
       
  1113 void TestMappingAttributes()
       
  1114 	{
       
  1115 	test.Start(_L("Fully Blocking"));
       
  1116 	TInt blockedRead;
       
  1117 	TInt blockedWrite;
       
  1118 	AccessSpeed(EBlocking,blockedRead,blockedWrite);
       
  1119 
       
  1120 	TInt read;
       
  1121 	TInt write;
       
  1122 
       
  1123 	test.Next(_L("Write Buffered"));
       
  1124 	AccessSpeed(EBuffered,read,write);
       
  1125 	CHECK(2*blockedRead,>,read);
       
  1126 //	CHECK(2*blockedWrite,<,write);  // Write buffering doesn't seem to work when cache disabled (?)
       
  1127 
       
  1128 	test.Next(_L("Fully Cached"));
       
  1129 	AccessSpeed(ECached,read,write);
       
  1130 	CHECK(2*blockedRead,<,read);
       
  1131 #ifndef __X86__	// X86 seems to do always do write buffering
       
  1132 	// Following check disabled because most dev boards only seem to be a bit faster
       
  1133 	// and asserting a particular speed improvement is unreliable
       
  1134 //	CHECK(2*blockedWrite,<,write);
       
  1135 #endif
       
  1136 
       
  1137 	test.End();
       
  1138 	}
       
  1139 
       
  1140 class RSession : public RSessionBase
       
  1141 	{
       
  1142 public:
       
  1143 	inline TInt CreateSession(const TDesC& aServer,const TVersion& aVersion)
       
  1144 		{ return RSessionBase::CreateSession(aServer,aVersion); }
       
  1145 	inline TInt SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
       
  1146 		{ return RSessionBase::SendReceive(aFunction,aArgs); }
       
  1147 	};
       
  1148 
       
  1149 TInt SlaveCommand(TSlaveCommand aCommand)
       
  1150 	{
       
  1151 	RDebug::Print(_L("Slave Process - Command %d\n"),aCommand);
       
  1152 	CHECK(KErrNone,==,UserHal::PageSizeInBytes(PageSize));
       
  1153 	CHECK(KErrNone,==,((RBusLogicalChannel&)Ldd).Open(2,EOwnerProcess));
       
  1154 	switch(aCommand)
       
  1155 		{
       
  1156 	case ESlaveCheckChunk:
       
  1157 		{
       
  1158 		RDebug::Print(_L("Slave Process - TheChunk.Open()\n"));
       
  1159 		CHECK(KErrNone,==,TheChunk.Open(3));
       
  1160 		RDebug::Print(_L("Slave Process - Get Region Count\n"));
       
  1161 		TInt regionCount;
       
  1162 		CHECK(KErrNone,==,User::GetTIntParameter(4,regionCount));
       
  1163 		RDebug::Print(_L("Slave Process - CheckCommitedContents(%d)\n"),regionCount);
       
  1164 		CheckCommitedContents(regionCount);
       
  1165 		RDebug::Print(_L("Slave Process - CheckCommitState(%d)\n"),regionCount);
       
  1166 		CheckCommitState(regionCount);
       
  1167 		RDebug::Print(_L("Slave Process - Done\n"));
       
  1168 		return 0;
       
  1169 		}
       
  1170 
       
  1171 	case ESlaveCreateChunk:
       
  1172 		{
       
  1173 		RDebug::Print(_L("Slave Process - Get parameters\n"));
       
  1174 		TInt createFlags;
       
  1175 		TInt commitType;
       
  1176 		TInt commitSize;
       
  1177 		CHECK(KErrNone,==,User::GetTIntParameter(3,createFlags));
       
  1178 		CHECK(KErrNone,==,User::GetTIntParameter(4,commitType));
       
  1179 		CHECK(KErrNone,==,User::GetTIntParameter(5,commitSize));
       
  1180 
       
  1181 		RDebug::Print(_L("Slave Process - Create Chunk\n"));
       
  1182 		CHECK(KErrNone,==,Ldd.CreateChunk(createFlags));
       
  1183 		CHECK(KErrNone,==,Ldd.CommitMemory(commitType,commitSize));
       
  1184 		CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
       
  1185 		TUint8* chunkBase=TheChunk.Base();
       
  1186 		memcpy(chunkBase,KTestString().Ptr(),KTestString().Size());
       
  1187 
       
  1188 		RDebug::Print(_L("Slave Process - Connecting to test server\n"));
       
  1189 		RSession session;
       
  1190 		CHECK(KErrNone,==,session.CreateSession(KSecondProcessName,TVersion()));
       
  1191 
       
  1192 		RDebug::Print(_L("Slave Process - Sending message\n"));
       
  1193 		TPtr8 ptr(chunkBase,commitSize,commitSize);
       
  1194 		session.SendReceive(0,TIpcArgs(&ptr));
       
  1195 
       
  1196 		RDebug::Print(_L("Slave Process - Destroy Chunk\n"));
       
  1197 		TheChunk.Close();
       
  1198 		CHECK(1,==,Ldd.CloseChunk()); // 1==DObject::EObjectDeleted
       
  1199 		CHECK(1,==,Ldd.IsDestroyed());
       
  1200 		return 0;
       
  1201 		}
       
  1202 
       
  1203 	default:
       
  1204 		RDebug::Print(_L("Slave Process - Bad Command\n"));
       
  1205 		return KErrArgument;
       
  1206 		}
       
  1207 	}
       
  1208 
       
  1209 void TestChunkUserBase()
       
  1210 	{
       
  1211 	TUint ChunkAttribs = ChunkSize|ESingle|EOwnsMemory;
       
  1212 
       
  1213 	test.Start(_L("Create chunk"));
       
  1214 	CHECK(KErrNone,==,Ldd.CreateChunk(ChunkAttribs));
       
  1215 
       
  1216 	test.Next(_L("Open user handle"));
       
  1217 	CHECK(KErrNone,==,Ldd.GetChunkHandle(TheChunk));
       
  1218 
       
  1219 	test.Next(_L("Commit some memory"));
       
  1220 	CHECK(KErrNone,==,Ldd.CommitMemory(EDiscontiguous|1*PageSize,PageSize));
       
  1221 
       
  1222 	test.Next(_L("Check OpenSharedChunk with handle"));
       
  1223 	CHECK(KErrNone,==,Ldd.TestOpenHandle(TheChunk.Handle()));
       
  1224 
       
  1225 	test.Next(_L("Get Kernel's user base"));
       
  1226 	TAny *kernelUserAddress;
       
  1227 	CHECK(KErrNone,==,Ldd.GetChunkUserBase(&kernelUserAddress));
       
  1228 	TAny *userAddress = TheChunk.Base();
       
  1229 	test(kernelUserAddress == userAddress);
       
  1230 	
       
  1231 	TheChunk.Close();
       
  1232 	CHECK(1,==,Ldd.CloseChunk());
       
  1233 
       
  1234 	test.End();
       
  1235 	}
       
  1236 
       
  1237 
       
  1238 TInt E32Main()
       
  1239 	{
       
  1240 	// Running as slave?
       
  1241 	TInt slaveCommand;
       
  1242 	if(User::GetTIntParameter(1,slaveCommand)==KErrNone)
       
  1243 		return SlaveCommand((TSlaveCommand)slaveCommand);
       
  1244 
       
  1245 // Turn off lazy dll unloading
       
  1246 	RLoader l;
       
  1247 	test(l.Connect()==KErrNone);
       
  1248 	test(l.CancelLazyDllUnload()==KErrNone);
       
  1249 	l.Close();
       
  1250 
       
  1251 	test.Title();
       
  1252 
       
  1253 	MemModelAttributes=UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
       
  1254 	TUint mm=MemModelAttributes&EMemModelTypeMask;
       
  1255 #ifdef __T_SHAREDCHUNKF__
       
  1256 	if(mm!=EMemModelTypeMoving)
       
  1257 		{
       
  1258 		test.Start(_L("TESTS NOT RUN - Only valid on Moving Memory Model"));
       
  1259 		test.End();
       
  1260 		return 0;
       
  1261 		}
       
  1262 #endif
       
  1263 
       
  1264 	test.Start(_L("Initialise"));
       
  1265 	CHECK(KErrNone,==,UserHal::PageSizeInBytes(PageSize));
       
  1266 	PhysicalCommitSupported = mm!=EMemModelTypeDirect && mm!=EMemModelTypeEmul;
       
  1267 	CachingAttributesSupported = mm!=EMemModelTypeDirect && mm!=EMemModelTypeEmul;
       
  1268 
       
  1269 
       
  1270 	test.Next(_L("Loading test driver"));
       
  1271 	TInt r = User::LoadLogicalDevice(KSharedChunkLddName);
       
  1272 	test(r==KErrNone || r==KErrAlreadyExists);
       
  1273 
       
  1274 	test.Next(_L("Opening channel"));
       
  1275 	CHECK(KErrNone,==,Ldd.Open());
       
  1276 
       
  1277 	// now 'unload' test driver, however, it will remain loaded whilst
       
  1278 	// we still have a channel open with it... 
       
  1279 	User::FreeLogicalDevice(KSharedChunkLddName);
       
  1280 
       
  1281 	test.Next(_L("Test chunk create"));
       
  1282 	TestCreate();
       
  1283 
       
  1284 	test.Next(_L("Test handles"));
       
  1285 	TestHandles();
       
  1286 
       
  1287 	test.Next(_L("Test restrictions for multiply shared chunks"));
       
  1288 	TestRestrictions(EMultiple);
       
  1289 	test.Next(_L("Test restrictions for singly shared chunks"));
       
  1290 	TestRestrictions(ESingle);
       
  1291 
       
  1292 	test.Next(_L("Test memory access for multiply shared chunks"));
       
  1293 	TestAccess(EMultiple|EOwnsMemory,EDiscontiguous);
       
  1294 	test.Next(_L("Test memory access for singly shared chunks"));
       
  1295 	TestAccess(ESingle|EOwnsMemory,EDiscontiguous);
       
  1296 
       
  1297 	test.Next(_L("Test Discontiguous memory commit for multiply shared chunks"));
       
  1298 	TestCommit(EMultiple,EDiscontiguous);
       
  1299 	test.Next(_L("Test Discontiguous memory commit for singly shared chunks"));
       
  1300 	TestCommit(ESingle,EDiscontiguous);
       
  1301 
       
  1302 	if((MemModelAttributes&EMemModelTypeMask)!=EMemModelTypeDirect)
       
  1303 		{
       
  1304 		test.Next(_L("Test Contiguous memory commit for multiply shared chunks"));
       
  1305 		TestCommit(EMultiple,EContiguous);
       
  1306 		test.Next(_L("Test Contiguous memory commit for singly shared chunks"));
       
  1307 		TestCommit(ESingle,EContiguous);
       
  1308 		}
       
  1309 
       
  1310 	if(PhysicalCommitSupported)
       
  1311 		{
       
  1312 		test.Next(_L("Test Discontiguous Physical commit for multiply shared chunks"));
       
  1313 		TestCommit(EMultiple,EDiscontiguousPhysical);
       
  1314 		test.Next(_L("Test Discontiguous Physical commit for singly shared chunks"));
       
  1315 		TestCommit(ESingle,EDiscontiguousPhysical);
       
  1316 
       
  1317 		test.Next(_L("Test Contiguous Physical commit for multiply shared chunks"));
       
  1318 		TestCommit(EMultiple,EContiguousPhysical);
       
  1319 		test.Next(_L("Test Contiguous Physical commit for singly shared chunks"));
       
  1320 		TestCommit(ESingle,EContiguousPhysical);
       
  1321 		}
       
  1322 
       
  1323 	test.Next(_L("Test Kern::OpenSharedChunk for multiply shared chunks"));
       
  1324 	TestOpenSharedChunk(EMultiple,EDiscontiguous);
       
  1325 	test.Next(_L("Test Kern::OpenSharedChunk for singly shared chunks"));
       
  1326 	TestOpenSharedChunk(ESingle,EDiscontiguous);
       
  1327 
       
  1328 	if(CachingAttributesSupported)
       
  1329 		{
       
  1330 		test.Next(_L("Test Mapping Attributes"));
       
  1331 		TestMappingAttributes();
       
  1332 		}
       
  1333 	
       
  1334 	test.Next(_L("Testing Kern::ChunkUserBase for shared chunks"));
       
  1335 	TestChunkUserBase();
       
  1336 
       
  1337 	if (PhysicalCommitSupported)
       
  1338 		{
       
  1339 		test.Next(_L("Testing Kern::ChunkClose allows immediate freeing of physical ram"));
       
  1340 		test_KErrNone(Ldd.TestChunkCloseAndFree());
       
  1341 		}
       
  1342 
       
  1343 	test.Next(_L("Close test driver"));
       
  1344 	Ldd.Close();
       
  1345 
       
  1346 	test.End();
       
  1347 
       
  1348 	return 0;
       
  1349 	}