kerneltest/e32test/mmu/t_chunk.cpp
changeset 0 a41df078684a
child 4 56f325a607ea
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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_chunk.cpp
       
    15 // Overview:
       
    16 // Test RChunk class
       
    17 // API Information:
       
    18 // RChunk, RChangeNotifier, TFindChunk
       
    19 // Details:
       
    20 // - Test adjusting chunks: create a global chunk, adjust it, do some size 
       
    21 // checks, verify Create() rounds up to chunk multiple, verify that adjust
       
    22 // request for size greater than MaxSize returns an error.
       
    23 // - Test creating chunks with small sizes (0 and 1), verify results are as expected.
       
    24 // - Create multiple local and global chunks, verify that Size,MaxSize,Name & FullName methods 
       
    25 // are as expected. 
       
    26 // Check Create method of global chunk if the name is already in use. Check the name can be 
       
    27 // reused after the chunk is closed.
       
    28 // - Perform adjust tests on a chunk, verify results are as expected.
       
    29 // - Open and test global chunks with multiple references, verify results are as expected.
       
    30 // - Open and test local chunks, check TFindChunk::Next method, verify results are as expected.
       
    31 // - Check user thread is panicked if it creates or adjusts chunk with negative size or of an
       
    32 // invalid type or with an invalid name.
       
    33 // - Check the chunk is filled in with the appropriate clear value after creation, verify results
       
    34 // are as expected.
       
    35 // - Test sharing a chunk between threads, verify results are as expected.
       
    36 // - Create a thread to watch for notification of changes in free memory and
       
    37 // changes in out of memory status. Verify adjusting an RChunk generates
       
    38 // the expected notifications.
       
    39 // - Test finding a global chunk by name and verify results are as expected.
       
    40 // Platforms/Drives/Compatibility:
       
    41 // All.
       
    42 // Assumptions/Requirement/Pre-requisites:
       
    43 // Failures and causes:
       
    44 // Base Port information:
       
    45 // 
       
    46 //
       
    47 
       
    48 #define __E32TEST_EXTENSION__
       
    49 
       
    50 #include <e32test.h>
       
    51 #include <e32panic.h>
       
    52 #include <e32svr.h>
       
    53 #include "mmudetect.h"
       
    54 #include "d_gobble.h"
       
    55 #include "freeram.h"
       
    56 
       
    57 const TInt KHeapSize=0x200;
       
    58 
       
    59 //const TInt KNumberOfChunks=10; can't have that many
       
    60 const TInt KNumberOfChunks=3;
       
    61 
       
    62 const TInt KChunkNum=5;
       
    63 const TInt KNormalReturn=194;
       
    64 
       
    65 #ifdef __WINS__
       
    66 const TInt KMinChunkSizeInBytesMinus1=0x0000ffff;
       
    67 const TUint KMinChunkSizeInBytesMask=0xffff0000;
       
    68 #elif defined (__X86__)
       
    69 const TInt KMinChunkSizeInBytesMinus1=0x003fffff;
       
    70 const TUint KMinChunkSizeInBytesMask=0xffc00000;
       
    71 #else
       
    72 const TInt KMinChunkSizeInBytesMinus1=0x000fffff;
       
    73 const TUint KMinChunkSizeInBytesMask=0xfff00000;
       
    74 #endif
       
    75 
       
    76 const TInt KMinPageSizeInBytesMinus1=0x00000fff;
       
    77 const TUint KMinPageSizeInBytesMask=0xfffff000;
       
    78 TInt gPageSize;
       
    79 
       
    80 LOCAL_D RTest test(_L("T_CHUNK"));
       
    81 LOCAL_D RTest t(_L("ShareThread"));
       
    82 LOCAL_D RChunk gChunk;
       
    83 
       
    84 LOCAL_D TPtr nullPtr(NULL,0);
       
    85 
       
    86 TUint32 MemModel;
       
    87 
       
    88 enum TDirective
       
    89 	{
       
    90 	ENormal,
       
    91 	ECreateNegative,
       
    92 	EAdjustNegative,
       
    93 	ECreateInvalidType,
       
    94 	ECreateInvalidName,
       
    95 	ECreateNoName,
       
    96 	};
       
    97 
       
    98 const TUint8 KDfltClearByte = 0x3;
       
    99 TBool CheckChunkCleared(RChunk& aRC, TInt aOffset=0, TUint8 aClearByte = KDfltClearByte)
       
   100 	{
       
   101 	TUint8* base = aRC.Base()+aOffset;
       
   102 	TInt size = aRC.Size();
       
   103 	test.Printf(_L("Testing chunk for 0x%x - size: %d!\n"), aClearByte, size);
       
   104 	TBool ret=ETrue;
       
   105 	for(TInt i = 0; i<size; i++)
       
   106 		if(base[i] != aClearByte)
       
   107 			ret=EFalse;
       
   108 	memset((TAny*)base, 0x05, size);
       
   109 	return ret;
       
   110 	}
       
   111 
       
   112 TInt roundToPageSize(TInt aSize)
       
   113 	{
       
   114 
       
   115 	return(((aSize+KMinPageSizeInBytesMinus1)&KMinPageSizeInBytesMask));
       
   116 	}
       
   117 
       
   118 TInt roundToChunkSize(TInt aSize)
       
   119 	{
       
   120 	if(MemModel==EMemModelTypeFlexible)
       
   121 		return roundToPageSize(aSize);
       
   122 	return(((aSize+KMinChunkSizeInBytesMinus1)&KMinChunkSizeInBytesMask));
       
   123 	}
       
   124 
       
   125 TInt ThreadEntry2(TAny* /*aParam*/)
       
   126 //
       
   127 //	Thread to read from shared chunk
       
   128 //
       
   129 	{
       
   130 	RChunk c;
       
   131 	TInt r;
       
   132 	r=c.OpenGlobal(_L("Marmalade"),ETrue);
       
   133 	t(r==KErrNone);
       
   134 	TUint8* base=c.Base();
       
   135 	for (TInt8 i=0;i<10;i++)
       
   136 		t(*base++==i); // check the chunk has 0-9
       
   137 	c.Close();
       
   138 	return(KErrNone);
       
   139 	}
       
   140 
       
   141 TInt ThreadEntry(TAny* aDirective)
       
   142 //
       
   143 //	Thread to create a Panic in a variety of ways
       
   144 //
       
   145 	{
       
   146 
       
   147 	switch((TUint)aDirective)
       
   148 		{
       
   149 	case ENormal:
       
   150 		{
       
   151 		return KNormalReturn;
       
   152 		}
       
   153 	case ECreateNegative:
       
   154 		{
       
   155 		gChunk.CreateLocal(0x10,-0x10);
       
   156 		test(EFalse); 
       
   157 		}
       
   158 	case EAdjustNegative:
       
   159 		{
       
   160 		gChunk.Adjust(-0x10);
       
   161 		test(EFalse);
       
   162 		}
       
   163 	case ECreateInvalidType :
       
   164 		{
       
   165 		TChunkCreateInfo createInfo;
       
   166 		createInfo.SetCode(gPageSize, gPageSize);
       
   167 		_LIT(KChunkName, "Chunky");
       
   168 		createInfo.SetGlobal(KChunkName);
       
   169 		RChunk chunk;
       
   170 		chunk.Create(createInfo);
       
   171 		test(EFalse);
       
   172 		}
       
   173 	default:
       
   174 		test(EFalse);
       
   175 		}
       
   176 	return(KErrNone);
       
   177 	}
       
   178 
       
   179 //
       
   180 //	Test the clear flags for the specified chunk.
       
   181 //	Assumes chunk has one commited region from base to aBytes.
       
   182 //
       
   183 void TestClearChunk(RChunk& aChunk, TUint aBytes, TUint8 aClearByte)
       
   184 	{
       
   185 	test_Equal(ETrue, CheckChunkCleared(aChunk, 0, aClearByte));
       
   186 	test_KErrNone(aChunk.Adjust(0));
       
   187 	test_KErrNone(aChunk.Adjust(aBytes));
       
   188 	test_Equal(ETrue, CheckChunkCleared(aChunk, 0, aClearByte));
       
   189 	aChunk.Close();
       
   190 	}
       
   191 
       
   192 
       
   193 //
       
   194 // Create the specified thread and verify the exit reason.
       
   195 //
       
   196 void TestThreadExit(TExitType aExitType, TInt aExitReason, TThreadFunction aFunc, TAny* aThreadParam)
       
   197 	{
       
   198 	RThread thread;
       
   199 	test_KErrNone(thread.Create(_L("RChunkPanicThread"), aFunc, KDefaultStackSize, 
       
   200 								KHeapSize, KHeapSize, aThreadParam));
       
   201 	// Disable JIT debugging.
       
   202 	TBool justInTime=User::JustInTime();
       
   203 	User::SetJustInTime(EFalse);
       
   204 
       
   205 	TRequestStatus status;
       
   206 	thread.Logon(status); 
       
   207 	thread.Resume();
       
   208 	User::WaitForRequest(status);
       
   209 	test_Equal(aExitType, thread.ExitType());
       
   210 	test_Equal(aExitReason, status.Int());
       
   211 	test_Equal(aExitReason, thread.ExitReason());
       
   212 	if (aExitType == EExitPanic)
       
   213 		test(thread.ExitCategory()==_L("USER"));
       
   214 	CLOSE_AND_WAIT(thread);
       
   215 
       
   216 	// Put JIT debugging back to previous status.
       
   217 	User::SetJustInTime(justInTime);
       
   218 	}
       
   219 
       
   220 
       
   221 //
       
   222 // Thread function to create a chunk with invalid attributes
       
   223 //
       
   224 TInt ChunkPanicThread(TAny* aCreateInfo)
       
   225 	{
       
   226 	// This should panic.
       
   227 	RChunk chunk;
       
   228 	chunk.Create((*(TChunkCreateInfo*) aCreateInfo));
       
   229 	test(EFalse);
       
   230 
       
   231 	return KErrGeneral;	// Shouldn't reach here.
       
   232 	}
       
   233 
       
   234 void testInitialise()
       
   235 	{
       
   236 	test.Next(_L("Load gobbler LDD"));
       
   237 	TInt r = User::LoadLogicalDevice(KGobblerLddFileName);
       
   238 	test(r==KErrNone || r==KErrAlreadyExists);
       
   239 
       
   240 	// get system info...
       
   241 	MemModel = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL) & EMemModelTypeMask;
       
   242 
       
   243 	test_KErrNone(UserHal::PageSizeInBytes(gPageSize));
       
   244 	}
       
   245 
       
   246 
       
   247 void test1()
       
   248 //
       
   249 //	Test creating chunks with silly sizes
       
   250 //
       
   251 	{
       
   252 
       
   253 	__KHEAP_MARK;
       
   254 	RChunk chunk;
       
   255 	TInt r;
       
   256 	test.Start(_L("Create global chunks"));
       
   257 	r=chunk.CreateGlobal(_L("Fopp"),1,1);
       
   258 	test(r==KErrNone);
       
   259 	chunk.Close();
       
   260 	r=chunk.CreateGlobal(_L("Fopp"),0,0);
       
   261 	test(r==KErrArgument);
       
   262 
       
   263 	__KHEAP_CHECK(0);
       
   264 
       
   265 	test.Next(_L("Create local chunks"));	  
       
   266 	r=chunk.CreateLocal(1,1);
       
   267 	test(r==KErrNone);
       
   268 	chunk.Close();
       
   269 	r=chunk.CreateLocal(0,0);
       
   270 	test(r==KErrArgument);
       
   271 	test.End();
       
   272 	__KHEAP_MARKEND;
       
   273 	}
       
   274 
       
   275 
       
   276 void test2(TInt aSize)
       
   277 //
       
   278 //	Test local/global chunk creation
       
   279 //
       
   280 	{
       
   281 
       
   282 	RChunk lchunk[KNumberOfChunks];
       
   283 	RChunk gchunk[KNumberOfChunks];
       
   284 	RChunk chunk;
       
   285 
       
   286 	__KHEAP_MARK;
       
   287 	test.Start(_L("Create multiple local and global chunks"));
       
   288 
       
   289 	TInt i;
       
   290 	TBuf<0x40> name;
       
   291 	TFullName fullname;
       
   292 	for (i=0; i<KNumberOfChunks; i++)
       
   293 		{
       
   294 		TInt r;
       
   295 		// create a local chunk
       
   296 		r=lchunk[i].CreateLocal(aSize,aSize);
       
   297 		test(r==KErrNone);
       
   298 		r=lchunk[i].MaxSize();
       
   299 		test(r==roundToChunkSize(aSize));
       
   300 		test(lchunk[i].Size()==roundToPageSize(aSize)); // was 0
       
   301 		test(lchunk[i].Name().Left(6)==_L("Local-"));
       
   302 
       
   303 		fullname=RProcess().Name();
       
   304 		fullname+=_L("::");
       
   305 		fullname+=lchunk[i].Name();
       
   306 		test(lchunk[i].FullName().CompareF(fullname)==0);
       
   307 
       
   308 		// create a global chunk
       
   309 		name.Format(_L("Chunk%d"),i);
       
   310 		r=gchunk[i].CreateGlobal(name,aSize,aSize);
       
   311 		test(r==KErrNone);
       
   312   		test(gchunk[i].MaxSize()==roundToChunkSize(aSize));
       
   313 		test(gchunk[i].Size()==roundToPageSize(aSize)); // was 0
       
   314 		test(gchunk[i].Name()==name);
       
   315 		}
       
   316 
       
   317 	// make room for another chunk
       
   318 	lchunk[KNumberOfChunks-1].Close();
       
   319 	gchunk[KNumberOfChunks-1].Close();
       
   320 
       
   321 //	Try to create a global chunk with a duplicate name
       
   322 	test.Next(_L("Create a chunk with a duplicate name"));
       
   323 	TInt r=chunk.CreateGlobal(_L("Chunk0"),aSize,aSize);
       
   324 	test(r==KErrAlreadyExists);
       
   325 
       
   326  	test.Next(_L("Close all chunks"));
       
   327 	for (i=0; i<KNumberOfChunks-1; i++)
       
   328 		{
       
   329 		lchunk[i].Close();
       
   330 		gchunk[i].Close();
       
   331 		}
       
   332 
       
   333 	test.Next(_L("Reuse a name"));
       
   334 	r=chunk.CreateGlobal(_L("Chunk1"),aSize,aSize);
       
   335 	test(r==KErrNone);
       
   336 	test(chunk.MaxSize()==roundToChunkSize(aSize));
       
   337    	test(chunk.Size()==roundToPageSize(aSize));	
       
   338 	test(chunk.Name()==_L("Chunk1"));
       
   339   	chunk.Close();
       
   340 
       
   341 	test.End();
       
   342 	__KHEAP_MARKEND;
       
   343 	}
       
   344 
       
   345 void test3_2(RChunk& aChunk, TInt aSize)
       
   346 //
       
   347 //	Perform Adjust tests on aChunk
       
   348 //
       
   349 	{
       
   350 
       
   351 	TInt r;
       
   352 	test.Start(_L("Adjust to full size"));
       
   353 	r=aChunk.Adjust(aSize);
       
   354  	test(r==KErrNone);
       
   355 	test(aChunk.Size()==roundToPageSize(aSize));
       
   356 	test(aChunk.MaxSize()==roundToChunkSize(aSize));
       
   357 
       
   358 	test.Next(_L("Adjust a chunk to half size"));
       
   359 	r=aChunk.Adjust(aSize/2);
       
   360 	test(r==KErrNone);
       
   361 	test(aChunk.Size()==roundToPageSize(aSize/2));
       
   362 	test(aChunk.MaxSize()==roundToChunkSize(aSize));
       
   363 
       
   364 	test.Next(_L("Adjust to same size"));
       
   365 	r=aChunk.Adjust(aSize/2);
       
   366 	test(r==KErrNone);
       
   367 	test(aChunk.Size()==roundToPageSize(aSize/2));
       
   368 	test(aChunk.MaxSize()==roundToChunkSize(aSize));
       
   369 
       
   370 	test.Next(_L("Adjusting to size=0"));
       
   371  	r=aChunk.Adjust(0);
       
   372 	test(r==KErrNone);
       
   373 	test(aChunk.Size()==0);
       
   374 	test(aChunk.MaxSize()==roundToChunkSize(aSize));
       
   375 
       
   376 	test.Next(_L("Adjust back to half size"));
       
   377 	r=aChunk.Adjust(aSize/2);
       
   378 	test(r==KErrNone);
       
   379 	test(aChunk.Size()==roundToPageSize(aSize/2));
       
   380 	test(aChunk.MaxSize()==roundToChunkSize(aSize));
       
   381 
       
   382 	test.End();
       
   383 	}
       
   384 
       
   385 
       
   386 void test3(TInt aSize)
       
   387 //
       
   388 //	Test Adjust size of chunk	
       
   389 //
       
   390 	{
       
   391 
       
   392 	RChunk chunk;
       
   393 	__KHEAP_MARK;	
       
   394 	TInt r;
       
   395 //	Run Adjust tests with a local chunk
       
   396 	test.Start(_L("Local Chunk.Adjust()"));
       
   397 	r=chunk.CreateLocal(aSize,aSize);
       
   398 	test3_2(chunk, aSize);
       
   399 	chunk.Close();
       
   400 //	Run Adjust tests with a global chunk
       
   401 	test.Next(_L("Global Chunk.Adjust()"));
       
   402 	r=chunk.CreateGlobal(_L("Fopp"),aSize,aSize);
       
   403 	test(KErrNone==r);
       
   404 	test3_2(chunk,aSize);
       
   405 	chunk.Close();
       
   406 	test.End();
       
   407 	__KHEAP_MARKEND;
       
   408 	}
       
   409 
       
   410 void test4(TInt aSize)
       
   411 //
       
   412 //	Test OpenGlobal
       
   413 //
       
   414 	{
       
   415 
       
   416 	RChunk chunk[KChunkNum];
       
   417 	RChunk c1, c2, c3;
       
   418 	TName name;
       
   419 
       
   420 	__KHEAP_MARK;
       
   421 	TInt i,r;
       
   422 	for (i=0; i<KChunkNum; i++)
       
   423 		{
       
   424 		name.Format(_L("Chunk%d"), i);
       
   425 		r=chunk[i].CreateGlobal(name,aSize,aSize);
       
   426 		}
       
   427 
       
   428 	test.Start(_L("Open Global chunks"));
       
   429 	r=c1.OpenGlobal(_L("Chunk1"),EFalse); // 2nd ref to this chunk
       
   430 	test(r==KErrNone);
       
   431 	r=c2.OpenGlobal(_L("Chunk3"),EFalse); // 2nd ref to this chunk
       
   432 	test(r==KErrNone);
       
   433 	r=c3.OpenGlobal(_L("Chunk4"),EFalse); // 2nd ref to this chunk
       
   434 	test(r==KErrNone);
       
   435 	c3.Close();
       
   436 
       
   437 	test.Next(_L("Attempt Open non-existant chunk"));
       
   438 	r=c3.OpenGlobal(_L("Non Existant Chunk"),EFalse);
       
   439 	test(r==KErrNotFound);
       
   440 
       
   441 	for (i=0; i<KChunkNum; i++)
       
   442 		{
       
   443 		test.Printf(_L("Closing chunk %d\n"),i);
       
   444 		chunk[i].Close();
       
   445 		}
       
   446 
       
   447 	test.Next(_L("Test chunks with multiple references are still valid"));
       
   448 	r=c1.Adjust(aSize/2);
       
   449 	test(r==KErrNone);
       
   450 	test(c1.MaxSize()==roundToChunkSize(aSize));
       
   451 	test(c1.Size()==roundToPageSize(aSize/2));
       
   452 	test(c1.Name()==_L("Chunk1"));
       
   453 
       
   454 	r=c2.Adjust(aSize/2);
       
   455 	test(r==KErrNone);
       
   456 	test(c2.MaxSize()==roundToChunkSize(aSize));
       
   457 	test(c2.Size()==roundToPageSize(aSize/2));
       
   458 	test(c2.Name()==_L("Chunk3"));
       
   459 
       
   460 //	Open another reference to a chunk
       
   461 	r=c3.OpenGlobal(_L("Chunk3"),EFalse);
       
   462 	test(r==KErrNone);
       
   463 	test(c3.Base()==c2.Base());
       
   464 	test(c3.Size()==c2.Size());
       
   465 	test(c2.Size()!=aSize);
       
   466 //	Adjust with one reference
       
   467 	r=c3.Adjust(aSize);
       
   468 	test(r==KErrNone);
       
   469 //	Test sizes from the other
       
   470 	test(c2.Size()==roundToPageSize(aSize));
       
   471 	test(c2.MaxSize()==roundToChunkSize(aSize));
       
   472 
       
   473 	c1.Close();
       
   474 	c2.Close();
       
   475 	c3.Close();
       
   476 
       
   477 	test.Next(_L("And check the heap..."));
       
   478 	test.End();
       
   479 	__KHEAP_MARKEND;
       
   480 	}
       
   481 
       
   482 void test5(TInt aSize)
       
   483 //
       
   484 //	Test Open
       
   485 //
       
   486 	{
       
   487 	
       
   488 	RChunk chunk[2*KNumberOfChunks];
       
   489 	RChunk c1;
       
   490 
       
   491 	test.Start(_L("Creating Local and Global Chunks"));
       
   492 	__KHEAP_MARK;
       
   493 	TInt i,r;
       
   494 	TBuf<0x40> b;
       
   495 
       
   496 //	Create KNumberOfChunks Global chunks
       
   497 	for (i=0; i<KNumberOfChunks; i++)
       
   498 		{
       
   499 		b.Format(_L("Chunk%d"), i);
       
   500 		r=chunk[i].CreateGlobal(b,aSize,aSize);
       
   501 		test(chunk[i].Name()==b);
       
   502 		test(r==KErrNone);
       
   503 		
       
   504 		b.Format(_L("This is chunk %d"), i);
       
   505 		b.Append(TChar(0));
       
   506 		chunk[i].Adjust(aSize);
       
   507 		Mem::Copy(chunk[i].Base(), b.Ptr(), b.Size());
       
   508 		test(chunk[i].MaxSize()==roundToChunkSize(aSize));
       
   509 		test(chunk[i].Size()==roundToPageSize(aSize));
       
   510 		}
       
   511 
       
   512 	test.Next(_L("Find and Open the Chunks"));
       
   513 	TFindChunk find;
       
   514 	TFullName name;
       
   515 	for (i=0; i<KNumberOfChunks; i++)
       
   516 		{
       
   517 		test.Printf(_L("Opening chunk %d\n"),i);
       
   518 		find.Find(chunk[i].FullName());
       
   519 		r = find.Next(name);
       
   520 		test(r==KErrNone);
       
   521 		c1.Open(find);
       
   522 		b=TPtrC((TText*)c1.Base());
       
   523 		name.Format(_L("This is chunk %d"), i);
       
   524 		test(b==name);
       
   525 		c1.Close();
       
   526 		}
       
   527 	
       
   528 	test.Next(_L("Close chunks"));
       
   529 	for (i=0; i<KNumberOfChunks; i++)
       
   530 		chunk[i].Close();
       
   531 
       
   532 	test.End();
       
   533 	__KHEAP_MARKEND;
       
   534 	}
       
   535 
       
   536 
       
   537 void test7(TInt aSize)
       
   538 //
       
   539 //	Deliberately cause RChunk panics
       
   540 //
       
   541 	{
       
   542 	__KHEAP_MARK;
       
   543 
       
   544 //	ENormal
       
   545 	test.Start(_L("Test panic thread"));
       
   546 	TestThreadExit(EExitKill, KNormalReturn, ThreadEntry, (TAny*)ENormal);
       
   547 
       
   548 //	ECreateNegative
       
   549 	test.Next(_L("Create Chunk with a negative size"));
       
   550 	TestThreadExit(EExitPanic, EChkCreateMaxSizeNegative, ThreadEntry, (TAny*) ECreateNegative);
       
   551 
       
   552 //	EAdjustNegative
       
   553 	test.Next(_L("Adjust a Chunk to Size = -0x10"));
       
   554 	gChunk.CreateLocal(aSize,aSize);
       
   555 	TestThreadExit(EExitPanic, EChkAdjustNewSizeNegative, ThreadEntry, (TAny*) EAdjustNegative);
       
   556 	gChunk.Close();
       
   557 
       
   558 // ECreateInvalidType
       
   559 	test.Next(_L("Create chunk of invalid type"));
       
   560 	TestThreadExit(EExitPanic, EChkCreateInvalidType, ThreadEntry, (TAny*) ECreateInvalidType);
       
   561 
       
   562 	test.End();
       
   563 
       
   564 	__KHEAP_MARKEND;
       
   565 	}
       
   566 
       
   567 
       
   568 void testClear(TInt aSize)
       
   569 	{
       
   570 	__KHEAP_MARK;
       
   571 	test.Start(_L("Test clearing memory (Platform Security)"));
       
   572 	
       
   573 	RChunk c1,c2,c3,c4,c5,c6,c7,c8,c9,c10;
       
   574 	TInt r;
       
   575 	
       
   576 	TBuf<0x40> b;
       
   577 	
       
   578 	b.Copy(_L("Chunk"));
       
   579 	
       
   580 	r=c1.CreateGlobal(b,aSize,aSize);
       
   581 	test(r==KErrNone);
       
   582 	
       
   583 	test((TBool)ETrue==CheckChunkCleared(c1));
       
   584 	c1.Close();
       
   585 	
       
   586 	r=c2.CreateLocal(aSize,aSize,EOwnerProcess);
       
   587 	test(r==KErrNone);
       
   588 	
       
   589 	test((TBool)ETrue==CheckChunkCleared(c2));
       
   590 	c2.Close();
       
   591 
       
   592 	r=c3.CreateLocalCode(aSize,aSize,EOwnerProcess);
       
   593 	test(r==KErrNone);
       
   594 	
       
   595 	test((TBool)ETrue==CheckChunkCleared(c3));
       
   596 	c3.Close();
       
   597 
       
   598 	r=c4.CreateDoubleEndedLocal(0x1000,0x1000+aSize,0x100000);
       
   599 	test(r==KErrNone);
       
   600 	
       
   601 	test((TBool)ETrue==CheckChunkCleared(c4,c4.Bottom()));
       
   602 	c4.Close();
       
   603 
       
   604 	r=c5.CreateDoubleEndedGlobal(b,0x1000,0x1000+aSize,0x100000,EOwnerProcess);
       
   605 	test(r==KErrNone);
       
   606 	
       
   607 	test((TBool)ETrue==CheckChunkCleared(c5,c5.Bottom()));
       
   608 	c5.Close();
       
   609 
       
   610 	r=c6.CreateDisconnectedLocal(0x1000,0x1000+aSize,0x100000);
       
   611 	test(r==KErrNone);
       
   612 	
       
   613 	test((TBool)ETrue==CheckChunkCleared(c6,0x1000));
       
   614 	c6.Close();
       
   615 
       
   616 	r=c7.CreateDisconnectedGlobal(b,0x1000,0x1000+aSize,0x100000,EOwnerProcess);
       
   617 	test(r==KErrNone);
       
   618 	
       
   619 	test((TBool)ETrue==CheckChunkCleared(c7,0x1000));
       
   620 	c7.Close();
       
   621 
       
   622 	test.Next(_L("Test setting the clear byte of RChunk::Create()"));
       
   623 
       
   624 	TChunkCreateInfo createInfo;
       
   625 	createInfo.SetNormal(aSize, aSize);
       
   626 	test_KErrNone(c10.Create(createInfo));
       
   627 	TestClearChunk(c10, aSize, KDfltClearByte);
       
   628 
       
   629 	createInfo.SetClearByte(0x0);
       
   630 	test_KErrNone(c8.Create(createInfo));
       
   631 	TestClearChunk(c8, aSize, 0x0);
       
   632 
       
   633 	createInfo.SetClearByte(0xff);
       
   634 	test_KErrNone(c9.Create(createInfo));
       
   635 	TestClearChunk(c9, aSize, 0xff);
       
   636 
       
   637 	test.End();
       
   638 	__KHEAP_MARKEND;
       
   639 	}
       
   640 
       
   641 void testShare()
       
   642 //
       
   643 // Test sharing a chunk between threads
       
   644 //
       
   645 	{
       
   646 	test.Start(_L("Test chunk sharing between threads"));
       
   647 
       
   648 	test.Next(_L("Create chunk Marmalade"));
       
   649 	TInt r=0;
       
   650 	RChunk chunk;
       
   651 	TInt size=0x1000;
       
   652 	TInt maxSize=0x5000;
       
   653 	r=0;
       
   654 	r=chunk.CreateGlobal(_L("Marmalade"),size,maxSize);
       
   655 	test(r==KErrNone);
       
   656 	test.Next(_L("Write 0-9 to it"));
       
   657 	TUint8* base=chunk.Base();
       
   658 	for (TInt8 j=0;j<10;j++)
       
   659 		*base++=j; // write 0 - 9 to the chunk
       
   660 
       
   661 	RThread t;
       
   662 	TRequestStatus stat;
       
   663 	test.Next(_L("Create reader thread"));
       
   664 	r=t.Create(_L("RChunkShareThread"), ThreadEntry2, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
       
   665 	test(r==KErrNone);
       
   666 	t.Logon(stat);
       
   667 	test.Next(_L("Resume reader thread"));
       
   668 	t.Resume();
       
   669 	User::WaitForRequest(stat);	
       
   670 	CLOSE_AND_WAIT(t);
       
   671 	chunk.Close();
       
   672 
       
   673 	test.End();
       
   674 	}
       
   675 
       
   676 void FindChunks()
       
   677     { // taken from some code written by SteveG
       
   678     test.Start(_L("Finding chunks...\n"));
       
   679 
       
   680     TFullName name=_L("*");
       
   681     TFindChunk find(name);
       
   682 	TInt i=0;
       
   683 
       
   684 
       
   685     while (find.Next(name)==KErrNone)
       
   686         {
       
   687         RChunk chunk;
       
   688         test.Printf(_L("Chunk name %S\n"),&name);
       
   689 		TInt err=chunk.Open(find);
       
   690         if (err)
       
   691             test.Printf(_L("Error %d opening chunk"),err);
       
   692         else
       
   693         	{
       
   694 			TBuf<16> access;
       
   695 			if (chunk.IsWritable())
       
   696 				access=_L("ReadWrite");
       
   697 			else if (chunk.IsReadable())
       
   698 				access=_L("ReadOnly");
       
   699 			else
       
   700 				access=_L("No Access");
       
   701             test.Printf(_L("Chunk size %08x bytes, %S\n"),chunk.Size(),&access);
       
   702 			chunk.Close();
       
   703 			i++;
       
   704 			}
       
   705         User::After(1000000);
       
   706   	    }
       
   707     test.End();
       
   708     }
       
   709 
       
   710 void testAdjustChunk()
       
   711 	{
       
   712 	test.Start(_L("Test adjusting chunks"));
       
   713 
       
   714 	RChunk hermione;
       
   715 	
       
   716 	test.Next(_L("Create global chunk"));
       
   717 	TInt r=hermione.CreateGlobal(_L("Hermione"),0x1000,0x100000);
       
   718 	test(r==KErrNone);
       
   719 	TUint32* base=(TUint32*)hermione.Base();
       
   720 	TUint32* top=(TUint32*)(hermione.Base()+hermione.Size());
       
   721 	TUint32* i;
       
   722 
       
   723 	test.Printf(_L("Base = %08x, Top = %08x\n"),base,top);
       
   724 	test.Next(_L("Check I can write to all of it"));
       
   725 	for (i=base;i<top;i++)
       
   726 		*i=0xdeaddead;
       
   727 
       
   728 	test.Next(_L("Adjust the chunk"));
       
   729 	r=hermione.Adjust(0x1400);
       
   730 	test(r==KErrNone);
       
   731 
       
   732 	base=(TUint32*)hermione.Base();
       
   733 	top=(TUint32*)(hermione.Base()+hermione.Size());
       
   734 	test.Printf(_L("Base = %08x, Top = %08x\n"),base,top);
       
   735 	test.Next(_L("Check I can write to all of the bigger chunk"));
       
   736 	for (i=base;i<top;i++)
       
   737 		*i=0xdeaddead;
       
   738 
       
   739 	hermione.Close();
       
   740 
       
   741 	test.Next(_L("Do some size checks"));
       
   742 	RChunk wibble;
       
   743 	r=wibble.CreateGlobal(_L("Wibble"),0x1,gPageSize*8);
       
   744 	test(r==KErrNone);
       
   745 	test.Next(_L("Check create rounds up to page multiple"));
       
   746 	test(wibble.Size()==(TInt)gPageSize);
       
   747 	test.Next(_L("Check create rounds up to chunk multiple"));
       
   748 	test(wibble.MaxSize()==roundToChunkSize(gPageSize*8));
       
   749 
       
   750 	test.Next(_L("Check adjust rounds up to page multiple"));
       
   751 	r=wibble.Adjust((gPageSize*6)-12);
       
   752 	test(r==KErrNone);
       
   753 	test(wibble.Size()==gPageSize*6);
       
   754 
       
   755 	test.Next(_L("Different number, same size"));
       
   756 	r=wibble.Adjust((gPageSize*6)-18);
       
   757 	test(r==KErrNone);
       
   758 	test(wibble.Size()==gPageSize*6);
       
   759 
       
   760 	test.Next(_L("Check adjust > MaxSize returns error"));
       
   761 	r=wibble.Adjust(wibble.MaxSize()+gPageSize);
       
   762 	test(r==KErrArgument);
       
   763 
       
   764 	wibble.Close();
       
   765 	test.End();
       
   766 	}
       
   767 
       
   768 TInt NotifierCount=0;
       
   769 TInt OOMCount=0;
       
   770 RChangeNotifier Notifier;
       
   771 RThread NtfThrd;
       
   772 _LIT(KNotifierThreadName,"NotifierThread");
       
   773 
       
   774 TInt NotifierThread(TAny*)
       
   775 	{
       
   776 	TInt r=Notifier.Create();
       
   777 	while (r==KErrNone)
       
   778 		{
       
   779 		TRequestStatus s;
       
   780 		r=Notifier.Logon(s);
       
   781 		if (r!=KErrNone)
       
   782 			break;
       
   783 		User::WaitForRequest(s);
       
   784 		if (s.Int()&EChangesFreeMemory)
       
   785 			++NotifierCount;
       
   786 		if (s.Int()&EChangesOutOfMemory)
       
   787 			++OOMCount;
       
   788 		}
       
   789 	Notifier.Close();
       
   790 	return r;
       
   791 	}
       
   792 
       
   793 
       
   794 void WaitForNotifier()
       
   795 	{
       
   796 	User::After(500000);		// wait for notifier
       
   797 	}
       
   798 
       
   799 
       
   800 void CheckNotifierCount(TInt aLevel, TInt aOom)
       
   801 	{
       
   802 	WaitForNotifier();
       
   803 	if (NtfThrd.ExitType()!=EExitPending)
       
   804 		{
       
   805 		TExitCategoryName exitCat=NtfThrd.ExitCategory();
       
   806 		test.Printf(_L("Thread exited: %d,%d,%S"),NtfThrd.ExitType(),NtfThrd.ExitReason(),&exitCat);
       
   807 		test(0);
       
   808 		}
       
   809 	TInt c1=NotifierCount;
       
   810 	TInt c2=OOMCount;
       
   811 	if (c1!=aLevel || c2!=aOom)
       
   812 		{
       
   813 		test.Printf(_L("Count %d,%d Expected %d,%d"),c1,c2,aLevel,aOom);
       
   814 		test(0);
       
   815 		}
       
   816 	}
       
   817 
       
   818 void testNotifiers()
       
   819 	{
       
   820 	RGobbler gobbler;
       
   821 	TInt r = gobbler.Open();
       
   822 	test(r==KErrNone);
       
   823 	TUint32 taken = gobbler.GobbleRAM(128*1024*1024);
       
   824 	test.Printf(_L("Gobbled: %dK\n"), taken/1024);
       
   825 	test.Printf(_L("Free RAM 0x%08X bytes\n"),FreeRam());
       
   826 
       
   827 	test.Next(_L("Create thread"));
       
   828 	r=NtfThrd.Create(KNotifierThreadName,NotifierThread,KDefaultStackSize,NULL,NULL);
       
   829 	test(r==KErrNone);
       
   830 	NtfThrd.SetPriority(EPriorityMore);
       
   831 	NtfThrd.Resume();
       
   832 	test.Next(_L("Check for initial notifier"));
       
   833 	CheckNotifierCount(1,1);
       
   834 	TInt free=FreeRam();
       
   835 	test.Printf(_L("Free RAM: %dK\n"),free/1024);
       
   836 	test(free>=1048576);
       
   837 	test.Next(_L("Set thresholds"));
       
   838 	r=UserSvr::SetMemoryThresholds(65536,524288);	// low=64K good=512K
       
   839 	test(r==KErrNone);
       
   840 	test.Next(_L("Create chunk"));
       
   841 	// Chunk must not be paged otherwise it will not effect the amount 
       
   842 	// of free ram reported plus on h4 swap size is less than the total ram.
       
   843 	TChunkCreateInfo createInfo;
       
   844 	createInfo.SetNormal(0, free+2097152);
       
   845 	createInfo.SetPaging(TChunkCreateInfo::EUnpaged);
       
   846 	RChunk c;
       
   847 	test_KErrNone(c.Create(createInfo));
       
   848 	const TInt KBufferSpace = 768*1024;	// 768K buffer
       
   849 	CheckNotifierCount(1,1);
       
   850 	test.Next(_L("Leave 768K"));
       
   851 	r=c.Adjust(free-KBufferSpace);	// leave 768K
       
   852 	test(r==KErrNone);
       
   853 	CheckNotifierCount(1,1);		// shouldn't get notifier
       
   854 	TInt free2=FreeRam();
       
   855 	test.Printf(_L("Free RAM: %dK\n"),free2/1024);
       
   856 	test(free2<=KBufferSpace);
       
   857 	TInt free3=free-(KBufferSpace-free2);	// this accounts for space used by page tables
       
   858 	test.Next(_L("Leave 32K"));
       
   859 	r=c.Adjust(free3-32768);		// leave 32K
       
   860 	test(r==KErrNone);
       
   861 	CheckNotifierCount(2,1);		// should get notifier
       
   862 	test.Next(_L("Leave 28K"));
       
   863 	r=c.Adjust(free3-28672);		// leave 28K
       
   864 	test(r==KErrNone);
       
   865 	CheckNotifierCount(2,1);		// shouldn't get another notifier
       
   866 	test.Next(_L("Ask for too much"));
       
   867 	r=c.Adjust(free3+4096);			// try to get more than available
       
   868 	test(r==KErrNoMemory);
       
   869 	CheckNotifierCount(2,2);		// should get another notifier
       
   870 	test.Next(_L("Leave 128K"));
       
   871 	r=c.Adjust(free3-131072);		// leave 128K
       
   872 	test(r==KErrNone);
       
   873 	CheckNotifierCount(2,2);		// shouldn't get another notifier
       
   874 	test.Next(_L("Leave 640K"));
       
   875 	r=c.Adjust(free3-655360);		// leave 640K
       
   876 	test(r==KErrNone);
       
   877 	CheckNotifierCount(3,2);		// should get another notifier
       
   878 	test.Next(_L("Leave 1M"));
       
   879 	r=c.Adjust(free3-1048576);		// leave 1M
       
   880 	test(r==KErrNone);
       
   881 	CheckNotifierCount(3,2);		// shouldn't get another notifier
       
   882 	test.Next(_L("Ask for too much"));
       
   883 	r=c.Adjust(free3+4096);			// try to get more than available
       
   884 	test(r==KErrNoMemory);
       
   885 
       
   886 	TInt notifierCount = 3;
       
   887 	if(MemModel==EMemModelTypeFlexible)
       
   888 		{
       
   889 		// on flexible memory model, we get memory changed notifiers
       
   890 		// on failed memory allocation; this hack lets the test code
       
   891 		// pass this as acceptable behaviour...
       
   892 		WaitForNotifier();
       
   893 		notifierCount = NotifierCount; // expect whatever we actually got
       
   894 		}
       
   895 
       
   896 	CheckNotifierCount(notifierCount,3);		// should get another notifier
       
   897 	test.Next(_L("Leave 1M"));
       
   898 	r=c.Adjust(free3-1048576);					// leave 1M
       
   899 	test(r==KErrNone);
       
   900 	CheckNotifierCount(notifierCount,3);		// shouldn't get another notifier
       
   901 
       
   902 	c.Close();
       
   903 	TRequestStatus s;
       
   904 	NtfThrd.Logon(s);
       
   905 	NtfThrd.Kill(0);
       
   906 	User::WaitForRequest(s);
       
   907 	CLOSE_AND_WAIT(NtfThrd);
       
   908 	Notifier.Close();
       
   909 	gobbler.Close();
       
   910 	}
       
   911 
       
   912 
       
   913 // TestFullAddressSpace is used to stress the memory allocation mechanism(beyond the 1GB limit).
       
   914 // However, the memory model can introduce limitations in the total amount of memory a single 
       
   915 // process is allowed to allocate. To make the test more generic before closing the reserved 
       
   916 // chunks for this test we trigger the creation of a new process. This process executes 
       
   917 // t_chunk again, passing argument "extended". The result is that more chunks will be created
       
   918 // through another call to TestFullAddressSpace, with the parameter extendedFlag set to true. 
       
   919 // Eventually the total amount of allocated space will overcome the 1Gb limit in any case.
       
   920 
       
   921 void TestFullAddressSpace(TBool extendedFlag )
       
   922 	{
       
   923 	test.Start(_L("Fill process address space with chunks\n"));
       
   924 	RChunk chunk[2][11];
       
   925 	TInt total = 0;
       
   926 	TInt i;
       
   927 	TInt j;
       
   928 	TInt r;
       
   929 		
       
   930 	for(j=0; j<=1; j++)
       
   931 		{
       
   932 		if(!j)
       
   933 			test.Next(_L("Creating local chunks"));
       
   934 		else
       
   935 			test.Next(_L("Creating global chunks"));
       
   936 		for(i=10; i>=0; --i)
       
   937 			{
       
   938 			TInt size = 1<<(20+i);
       
   939 			
       
   940 			if(!j)
       
   941 				r = chunk[j][i].CreateDisconnectedLocal(0,0,size);
       
   942 			else
       
   943 				r = chunk[j][i].CreateDisconnectedGlobal(KNullDesC,0,0,size);
       
   944 			TBuf<128> text;
       
   945 			text.AppendFormat(_L("Create %dMB chunk returns %d"),1<<i,r);
       
   946 			test.Next(text);
       
   947 			if(r!=KErrNoMemory)
       
   948 				{
       
   949 				test(r==KErrNone);
       
   950 				// commit memory to each 1MB region,
       
   951 				// this excercises page table allocation
       
   952 				volatile TUint8* base = (TUint8*)chunk[j][i].Base();
       
   953 				for(TInt o=0; o<size; o+=1<<20)
       
   954 					{
       
   955 					r = chunk[j][i].Commit(o,1);
       
   956 					test(r==KErrNone);
       
   957 					// access the commited memory...
       
   958 					base[o] = (TUint8)(o&0xff);
       
   959 					test(base[o]==(TUint8)(o&0xff));
       
   960 					base[o] = (TUint8)~(o&0xff);
       
   961 					test(base[o]==(TUint8)~(o&0xff));
       
   962 					}
       
   963 				total += 1<<i;
       
   964 				}
       
   965 			}
       
   966 		}
       
   967 		
       
   968 	if (extendedFlag == EFalse)
       
   969 		{
       
   970 		
       
   971 		test.Printf(_L("Total chunk size created was %d MB\n\n"),total);	  
       
   972 
       
   973 		if(total<1024)
       
   974 			{
       
   975 			_LIT(KOtherProcessName,"t_chunk");
       
   976 			_LIT(KProcessArgs,"extended");
       
   977 			
       
   978 			RProcess process;      
       
   979 			r=process.Create(KOtherProcessName,KProcessArgs );
       
   980 			test.Printf(_L("Creating new process( t_chunk extended) returns %d\n"),r );
       
   981 			test( r == KErrNone);
       
   982 		   
       
   983 			TRequestStatus status;
       
   984 			process.Logon(status);
       
   985 			process.Resume(); 
       
   986 			
       
   987 			User::WaitForRequest(status);
       
   988 			  
       
   989 			test(process.ExitType() == EExitKill);
       
   990 			test(process.ExitReason() == 0);
       
   991 			process.Close();
       
   992 			}
       
   993 	
       
   994 		}           
       
   995   	else
       
   996   		test.Printf(_L("Total chunk size created by the new process was %d MB\n"),total); 
       
   997  
       
   998 	for(j=0; j<=1; j++)
       
   999 		for(i=10; i>=0; --i)
       
  1000 			chunk[j][i].Close();
       
  1001 	test.End();
       
  1002 	}	
       
  1003 
       
  1004 
       
  1005 #ifdef __WINS__
       
  1006 void TestExecLocalCode()
       
  1007 	{
       
  1008 	RChunk c;
       
  1009 	TInt size = 10 * 1024;
       
  1010 	TInt rc = c.CreateLocalCode(size, size, EOwnerProcess);
       
  1011 	test_KErrNone(rc);
       
  1012 	TUint8 *p = c.Base();
       
  1013 	TUint32 (*func)() = (TUint32 (*)())p;
       
  1014 	test.Printf(_L("Create small function in the new code chunk\n"));
       
  1015 	*p++ = 0xB8;		// mov eax, 0x12345678
       
  1016 	*p++ = 0x78;
       
  1017 	*p++ = 0x56;
       
  1018 	*p++ = 0x34;
       
  1019 	*p++ = 0x12;
       
  1020 	*p   = 0xC3;		// ret
       
  1021 	test.Printf(_L("Going to call the new function\n"));
       
  1022 	TUint32 res = (*func)();
       
  1023 	test_Equal(0x12345678, res);
       
  1024 	c.Close();
       
  1025 	}
       
  1026 #endif	//  __WINS__
       
  1027 
       
  1028 
       
  1029 _LIT(KChunkName, "CloseChunk");
       
  1030 
       
  1031 struct TRequestData
       
  1032 	{
       
  1033 	RSemaphore requestSem;
       
  1034 	RSemaphore completionSem;
       
  1035 	RSemaphore nextItSem;
       
  1036 	};
       
  1037 
       
  1038 TInt CloseThread(TAny* data)
       
  1039 	{
       
  1040 	TRequestData* reqData = (TRequestData*)data;
       
  1041 	ASSERT(reqData);
       
  1042 	
       
  1043 	for(;;)
       
  1044 		{
       
  1045 		// Wait for a request to open and close the chunk.
       
  1046 		reqData->requestSem.Wait();
       
  1047 		
       
  1048 		// Try to open the chunk (may have already been closed by another thread).
       
  1049 		RChunk chunk;
       
  1050 		TInt r = chunk.OpenGlobal(KChunkName, EFalse, EOwnerThread);
       
  1051 		if (r != KErrNone)
       
  1052 			{
       
  1053 			// The chunk was already closed...
       
  1054 			r = (r == KErrNotFound) ? KErrNone : r;	// Ensure no debug output for expected failures.
       
  1055 			
       
  1056 			if(r != KErrNone)
       
  1057 				{
       
  1058 				test.Printf(_L("CloseThread RChunk::OpenGlobal Err: %d\n"), r);
       
  1059 				test_KErrNone(r);
       
  1060 				}
       
  1061 			}
       
  1062 		else
       
  1063 			{ 
       
  1064 			// Close the chunk.
       
  1065 			chunk.Close();
       
  1066 			}
       
  1067 		
       
  1068 		// Tell our parent we have completed this iteration and wait for the next.
       
  1069 		reqData->completionSem.Signal();
       
  1070 		reqData->nextItSem.Wait();
       
  1071 		}
       
  1072 	}
       
  1073 
       
  1074 void TestClosure()
       
  1075 	{
       
  1076 	const TUint KCloseThreads = 50;
       
  1077 	RThread thread[KCloseThreads];
       
  1078 	TRequestStatus dead[KCloseThreads];
       
  1079 
       
  1080 	// We need three semaphores or we risk signal stealing if one thread gets ahead of the
       
  1081 	// others and starts a second iteration before the other threads have been signalled
       
  1082 	// and have begun their first iteration.  Such a situation results in deadlock so we
       
  1083 	// force all threads to finish the iteration first using the nextItSem semaphore to
       
  1084 	// ensure we can only move to the next iteration once every thread has completed the
       
  1085 	// current iteration.
       
  1086 	TRequestData reqData;
       
  1087 	test_KErrNone(reqData.requestSem.CreateLocal(0));
       
  1088 	test_KErrNone(reqData.completionSem.CreateLocal(0));
       
  1089 	test_KErrNone(reqData.nextItSem.CreateLocal(0));
       
  1090 	
       
  1091 	TUint i = 0;
       
  1092 
       
  1093 	// Create thread pool.  We do this rather than create 50 threads
       
  1094 	// over and over again for 800 times - the kernel's garbage collection
       
  1095 	// does not keep up and we run out of backing store.
       
  1096 	for (; i < KCloseThreads; i++)
       
  1097 		{
       
  1098 		test_KErrNone(thread[i].Create(KNullDesC, CloseThread, KDefaultStackSize, NULL, (TAny*)&reqData));
       
  1099 		thread[i].Logon(dead[i]);
       
  1100 		thread[i].SetPriority(EPriorityMuchLess);
       
  1101 		thread[i].Resume();
       
  1102 		}
       
  1103 
       
  1104 	for (TUint delay = 200; delay < 1000; delay++)
       
  1105 		{
       
  1106 		test.Printf(_L("Closure delay %dus\r"), delay);
       
  1107 
       
  1108 		// Create a global chunk.
       
  1109 		RChunk chunk;
       
  1110 		test_KErrNone(chunk.CreateGlobal(KChunkName, gPageSize, gPageSize));
       
  1111 
       
  1112 		// Release the threads so they can try to close the handle.
       
  1113 		reqData.requestSem.Signal(KCloseThreads);
       
  1114 
       
  1115 		// Wait for the delay then close the handle ourselves.
       
  1116 		User::AfterHighRes(delay);
       
  1117 		chunk.Close();
       
  1118 
       
  1119 		// Wait for the threads to complete then release them for the next iteration.
       
  1120 		for (i = 0; i < KCloseThreads; i++)
       
  1121 			{
       
  1122 			reqData.completionSem.Wait();
       
  1123 			}
       
  1124 		reqData.nextItSem.Signal(KCloseThreads);
       
  1125 
       
  1126 		// Ensure garbage collection is complete to prevent the kernel's
       
  1127 		// garbage collection from being overwhelmed and causing the
       
  1128 		// backing store to be exhausted.
       
  1129 		UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
       
  1130 		}
       
  1131 
       
  1132 	// Kill thread pool.
       
  1133 	for (i = 0; i < KCloseThreads; i++)
       
  1134 		{
       
  1135 		thread[i].Kill(KErrNone);
       
  1136 		User::WaitForRequest(dead[i]);
       
  1137 		test(KErrNone == thread[i].ExitReason());
       
  1138 		test_Equal(EExitKill, thread[i].ExitType());
       
  1139 		thread[i].Close();
       
  1140 		}
       
  1141 		
       
  1142 	reqData.requestSem.Close();
       
  1143 	reqData.completionSem.Close();
       
  1144 	reqData.nextItSem.Close();
       
  1145 
       
  1146 	// Ensure garbage collection is complete to prevent false positive
       
  1147 	// kernel memory leaks.
       
  1148 	UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
       
  1149 	}
       
  1150 	
       
  1151 
       
  1152 /**Returns true if 'extended' is found in the command line*/
       
  1153 TBool GetExtended()
       
  1154 	{
       
  1155 	_LIT(KExtended,"extended");
       
  1156 	TBuf<64> c;
       
  1157 	User::CommandLine(c);
       
  1158 	if (c.FindF(KExtended) >= 0)
       
  1159 		return ETrue;
       
  1160 	return EFalse;
       
  1161 	}
       
  1162 
       
  1163 
       
  1164 TInt E32Main()
       
  1165 //
       
  1166 //	Test RChunk class
       
  1167 //
       
  1168 	{
       
  1169 	test.Title();
       
  1170 	if (!HaveVirtMem())
       
  1171 		{
       
  1172 		test.Printf(_L("This test requires an MMU\n"));
       
  1173 		return KErrNone;
       
  1174 		}
       
  1175 	testInitialise();
       
  1176 
       
  1177 	// Turn off lazy dll unloading so the kernel heap checking isn't affected.
       
  1178 	RLoader l;
       
  1179 	test(l.Connect()==KErrNone);
       
  1180 	test(l.CancelLazyDllUnload()==KErrNone);
       
  1181 	l.Close();
       
  1182 
       
  1183 	__KHEAP_MARK;
       
  1184 
       
  1185 	if (GetExtended() ) 
       
  1186 		{
       
  1187 		test.Printf(_L("t_chunk extended was called. Ready to call TestFullAddressSpace(Etrue) \n"));
       
  1188 		TestFullAddressSpace(ETrue);	
       
  1189 		}	
       
  1190 	else 
       
  1191 		{
       
  1192 		test.Start(_L("Testing.."));
       
  1193 		testAdjustChunk();
       
  1194 		test.Next(_L("Test1"));
       
  1195 		test1();
       
  1196 		test.Next(_L("Test2"));
       
  1197 		test2(0x80);
       
  1198 		test.Next(_L("Test3"));
       
  1199 		test3(0x7000);
       
  1200 		test.Next(_L("Test4"));
       
  1201 		test4(0x7000);
       
  1202 		test.Next(_L("Test5"));
       
  1203 		test5(0x80);
       
  1204 		test.Next(_L("Test7"));
       
  1205 		test7(0x80);
       
  1206 		test.Next(_L("Test chunk data clearing attributes"));
       
  1207 		testClear(0x500);
       
  1208 		testClear(07000);
       
  1209 		test.Next(_L("Test9"));
       
  1210 		testShare();
       
  1211 		test.Next(_L("Test memory notifiers"));
       
  1212 		testNotifiers();
       
  1213 		test.Next(_L("FindChunks"));
       
  1214 		FindChunks();
       
  1215 		
       
  1216 		test.Next(_L("Test full address space"));
       
  1217 		TestFullAddressSpace(EFalse);
       
  1218 
       
  1219 #ifdef __WINS__
       
  1220 		test.Next(_L("Test execution of code in a local code chunk on emulator"));
       
  1221 		TestExecLocalCode();
       
  1222 #endif	//  __WINS__
       
  1223 
       
  1224 		test.Next(_L("Test for race conditions in chunk closure"));
       
  1225 		TestClosure();
       
  1226 		test.End();
       
  1227 		}	
       
  1228 
       
  1229 	test.Close();
       
  1230 	__KHEAP_MARKEND;
       
  1231 	
       
  1232 	
       
  1233 	return(KErrNone);
       
  1234 	}