os/kernelhwsrv/kerneltest/e32test/thread/t_thread.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 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\thread\t_thread.cpp
    15 // Overview:
    16 // Tests the RThread class
    17 // API Information:
    18 // RThread, RUndertaker
    19 // Details:
    20 // - Create a thread, verify its priority, change the priority and verify results.
    21 // - Verify naming and renaming threads works as expected.
    22 // - Test logging on, resuming and closing a thread. Verify results are as expected.
    23 // - Test creating threads with a variety of invalid parameters. Verify results.
    24 // - Test the RUndertaker methods: create some threads, logon to the undertaker,
    25 // verify results upon killing a thread and setting the thread handle.
    26 // - Check kernel allocation when creating threads and undertakers. Verify the
    27 // heap has not been corrupted.
    28 // - Run a thread multiple times, panic within the thread, panic external to the
    29 // thread and exit a thread in a variety of ways. Verify results are as expected.
    30 // - Create a semaphore and some threads, verify the threads can wait on and signal
    31 // the semaphore.
    32 // - Test unclosed but completed threads.
    33 // - Suspend and resume some threads in a variety of ways, verify results are as
    34 // expected.
    35 // - Test thread duplication.
    36 // - Test opening a thread using an full name, perform various tests by finding, 
    37 // killing, closing, recreating etc. Verify the results are as expected.
    38 // - Test creating a thread using a duplicate name then reuse the thread with a
    39 // valid name. Verify results are as expected.
    40 // - Verify that a panicked thread releases an existing mutex.
    41 // - Test thread ID: attempt to open a nonexistent thread by ID, verify different
    42 // threads have different IDs, verify open by ID works as expected.
    43 // - Test RThread::StackInfo(), print results and verify results are as expected.
    44 // Platforms/Drives/Compatibility:
    45 // All.
    46 // Assumptions/Requirement/Pre-requisites:
    47 // Failures and causes:
    48 // Base Port information:
    49 // 
    50 //
    51 
    52 #define __E32TEST_EXTENSION__
    53 #include <e32test.h>
    54 #include <e32panic.h>
    55 #include <e32svr.h>
    56 #include <u32hal.h>
    57 #include <e32atomics.h>
    58 #include <e32def.h>
    59 #include <e32def_private.h>
    60 #include "../misc/prbs.h"
    61 
    62 const TInt KNumThreads=20;
    63 
    64 const TInt KExitPanicNum=999;
    65 const TInt KHeapSize=0x200;
    66 const TInt KThreadReturnValue=9999;
    67 const TInt KTerminationReason=1234;
    68 const TInt KKillReason=4321;  
    69 enum TInstruction {ENormal,EInstrPanic,EWait};
    70 
    71 const TInt KWaitTime=800000;
    72 
    73 class TReadInfo
    74 	{
    75 public:
    76 	TDesC* tdesc;
    77 	TPtrC* tptrc;
    78 	TDes* tdes;
    79 	TPtr* tptr;
    80 	HBufC* hbufc;
    81 	TBufC<0x20>* tbufc;
    82 	TBuf<0x20>* tbuf;
    83 	TPtr* tptrdes;
    84 	TAny* anAddress;
    85 	};
    86 
    87 LOCAL_D RTest test(_L("T_THREAD"));
    88 LOCAL_D RTest rtest(_L("Read thread tests"));
    89 LOCAL_D	RTest wtest(_L("Write thread tests"));
    90 
    91 #define rtest(x) rtest(x,__LINE__)
    92 #define wtest(x) wtest(x,__LINE__)
    93 
    94 LOCAL_C TInt LoopyThread(TAny*)
    95 	{
    96 	
    97 	FOREVER
    98 		User::AfterHighRes(1000);
    99 	}
   100 
   101 LOCAL_D void testUndertaker(TOwnerType anOwnerType)
   102 //
   103 // Test RThreadWatcher
   104 //
   105 	{
   106 
   107 	RThread thread1;
   108 	TInt r;
   109 	test.Start(_L("Test the RUndertaker class"));
   110 	test.Next(_L("Create a thread"));
   111 //	if (anOwnerType==EOwnerThread)
   112 //		User::SetDebugMask(0x8000867c);
   113 	r=thread1.Create(_L("Loopy1"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
   114 	test(r==KErrNone);
   115 	thread1.Resume();
   116 
   117 	TRequestStatus stat1;
   118 	TInt threadHandle1;
   119 	RThread w1;
   120 	RUndertaker u1;
   121 	test.Next(_L("Create an RUndertaker"));
   122 	r=u1.Create();
   123 	test(r==KErrNone);
   124 	test.Next(_L("Logon to RUndertaker"));
   125 	r=u1.Logon(stat1,threadHandle1);
   126 	test(r==KErrNone);
   127 	test.Next(_L("Logon again & check we're rejected"));
   128 	r=u1.Logon(stat1,threadHandle1);
   129 	test(r==KErrInUse);
   130 	test.Next(_L("Cancel logon to RUndertaker"));
   131 	r=u1.LogonCancel();
   132 	test(r==KErrNone);
   133 	test(stat1==KErrCancel);
   134 
   135 	test.Next(_L("Logon to RUndertaker again"));
   136 	u1.Logon(stat1,threadHandle1);
   137 	
   138 	test.Next(_L("Create another thread"));
   139 	RThread thread2;
   140 	r=thread2.Create(_L("Loopy2"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
   141 	test(r==KErrNone);
   142 	thread2.Resume();
   143 
   144 	TRequestStatus stat2;
   145 	TInt threadHandle2;
   146 	RThread w2;
   147 	RUndertaker u2;
   148 	test.Next(_L("Create another RUndertaker"));
   149 	r=u2.Create();
   150 	test(r==KErrNone);
   151 	test.Next(_L("Logon to RUndertaker"));
   152 	r=u2.Logon(stat2,threadHandle2);
   153 	test(r==KErrNone);
   154 
   155 	test.Next(_L("Create yet another thread"));
   156 	RThread thread3;
   157 	r=thread3.Create(_L("Loopy3"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
   158 	test(r==KErrNone);
   159 	thread3.Resume();
   160 
   161 	test.Next(_L("Kill the first thread & check the undertakers"));
   162 	thread1.Kill(0x489);
   163 	thread1.Close();
   164 
   165 	User::WaitForRequest(stat1);
   166 	User::WaitForRequest(stat2);
   167 	test(stat1==KErrDied);
   168 	test(stat2==KErrDied);
   169 
   170 	RThread keep1;
   171 	RThread keep2;
   172 	test.Next(_L("Set the RThread handles"));
   173 	keep1.SetHandle(threadHandle1);
   174 	keep2.SetHandle(threadHandle2);
   175 
   176 	test.Next(_L("Test the exit reasons"));
   177 	test(keep1.ExitReason()==0x489);
   178 	test(keep2.ExitReason()==0x489);
   179 //	test.Printf(_L("Thread name %S\n"),&(w1.Name()));
   180 
   181 	test.Next(_L("Logon again with both watchers"));
   182 	r=u1.Logon(stat1,threadHandle1);
   183 	test(r==KErrNone);
   184 	r=u2.Logon(stat2,threadHandle2);
   185 	test(r==KErrNone);
   186 
   187 	test.Next(_L("Kill the 3rd thread & check the undertakers"));
   188 	thread3.Kill(0x999);
   189 	thread3.Close();
   190 
   191 	User::WaitForRequest(stat1);
   192 	User::WaitForRequest(stat2);
   193 	test(stat1==KErrDied);
   194 	test(stat2==KErrDied);
   195 
   196 	test.Next(_L("Set the RThread handles"));
   197 	w1.SetHandle(threadHandle1);
   198 	w2.SetHandle(threadHandle2);
   199 
   200 	test.Next(_L("Test the exit reasons"));
   201 	test(w1.ExitReason()==0x999);
   202 	test(w2.ExitReason()==0x999);
   203 //	test.Printf(_L("Thread name %S\n"),&(w1.Name()));
   204 	w1.Close();
   205 	CLOSE_AND_WAIT(w2);
   206 
   207 	test.Next(_L("Logon again with both undertakers"));
   208 	r=u1.Logon(stat1,threadHandle1);
   209 	test(r==KErrNone);
   210 	r=u2.Logon(stat2,threadHandle2);
   211 	test(r==KErrNone);
   212 
   213 	test.Next(_L("Kill the 2nd thread & check the undertakers"));
   214 	thread2.Kill(0x707);
   215 	thread2.Close();
   216 
   217 	User::WaitForRequest(stat1);
   218 	User::WaitForRequest(stat2);
   219 	test(stat1==KErrDied);
   220 	test(stat2==KErrDied);
   221 
   222 	test.Next(_L("Set the RThread handles"));
   223 	w1.SetHandle(threadHandle1);
   224 	w2.SetHandle(threadHandle2);
   225 
   226 	test.Next(_L("Test the exit reasons"));
   227 	test(w1.ExitReason()==0x707);
   228 	test(w2.ExitReason()==0x707);
   229 //	test.Printf(_L("Thread name %S\n"),&(w1.Name()));
   230 
   231 	test.Next(_L("Check kernel allocation"));
   232 	test.Next(_L("Please wait while I create & close masses of threads"));
   233 	RThread t[KNumThreads];
   234 	TInt j;
   235 	for (j=0; j<KNumThreads; j++)
   236 		{
   237 		TBuf<0x10> name;
   238 		name.Format(_L("LoopyThread%d"),j);
   239 		test(t[j].Create(name, LoopyThread, KDefaultStackSize, KHeapSize, KHeapSize, (TAny*)NULL,anOwnerType)==KErrNone);
   240 		}
   241 	for (j=0; j<KNumThreads-1; j++)
   242 		{
   243 		t[j].Kill(666);
   244 		CLOSE_AND_WAIT(t[j]);
   245 		}
   246 
   247 	test.Next(_L("Please wait while I close & create some undertakers"));
   248 	u1.Close();
   249 	u2.Close();
   250 	r=u1.Create();
   251 	test(r==KErrNone);
   252 	r=u2.Create();
   253 	test(r==KErrNone);
   254 
   255 	test.Next(_L("Mark kernel heap"));
   256 	__KHEAP_MARK;
   257 
   258 	test.Next(_L("Create thread"));
   259 	RThread threadx;
   260 	r=threadx.Create(_L("Loopyx"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
   261 	test(r==KErrNone);
   262 	test.Next(_L("Resume thread"));
   263 	threadx.Resume();
   264 
   265 	test.Next(_L("Create undertaker"));
   266 	TRequestStatus statx;
   267 	TInt threadHandlex;
   268 	RUndertaker ux;
   269 	r=ux.Create();
   270 	test(r==KErrNone);
   271 	test.Next(_L("Logon to undertaker"));
   272 	r=ux.Logon(statx,threadHandlex);
   273 	test(r==KErrNone);
   274 	test.Next(_L("Kill thread"));
   275 	threadx.Kill(0x666);
   276 	threadx.Close();
   277 	User::WaitForRequest(statx);
   278 	test(statx==KErrDied);
   279 	test.Next(_L("Close thread"));
   280 	RThread wx;
   281 	wx.SetHandle(threadHandlex);
   282 	CLOSE_AND_WAIT(wx);
   283 
   284 	test.Next(_L("Close undertaker"));
   285 	ux.Close();
   286 
   287 	test.Next(_L("Check kernel heap"));
   288 	__KHEAP_MARKEND;
   289 	w1.Close();
   290 	CLOSE_AND_WAIT(w2);
   291 	keep1.Close();
   292 	CLOSE_AND_WAIT(keep2);
   293 	t[KNumThreads-1].Kill(666);
   294 	CLOSE_AND_WAIT(t[KNumThreads-1]);
   295 
   296 	test.Next(_L("Close RUndertakers"));
   297 	u1.Close();
   298 	u2.Close();
   299 	test.End();
   300 	}
   301 
   302 volatile TInt IFLAG;
   303 
   304 TInt InstructionThread(TAny* anInstruction)
   305 	{
   306 	__e32_atomic_store_ord32(&IFLAG, 1);
   307 	RThread::Rendezvous(KErrNone);
   308 	TInstruction what=(TInstruction)(TInt)anInstruction;
   309 	if (what==EInstrPanic)
   310 		User::Panic(_L("Hello"), KExitPanicNum);
   311 	if (what==ENormal)
   312 		return(KThreadReturnValue);
   313 	User::After(500000);
   314 	return(KErrNone);
   315 	}
   316 
   317 TInt StartInstructionThread(RThread& aT, const TDesC& aName, TInt aInstruction, TOwnerType aOwnerType, TRequestStatus* aL, TRequestStatus* aR)
   318 	{
   319 	TInt r = aT.Create(aName, &InstructionThread, KDefaultStackSize, KHeapSize, KHeapSize, (TAny*)aInstruction, aOwnerType);
   320 	if (r!=KErrNone)
   321 		return r;
   322 	if (aL)
   323 		{
   324 		aT.Logon(*aL);
   325 		TInt s = aL->Int();
   326 		test_Equal(s, KRequestPending);
   327 		}
   328 	if (aR)
   329 		{
   330 		aT.Rendezvous(*aR);
   331 		TInt s = aR->Int();
   332 		test_Equal(s, KRequestPending);
   333 		aT.Resume();
   334 		User::WaitForRequest(*aR);
   335 		s = aR->Int();
   336 		test_KErrNone(s);
   337 		}
   338 	return r;
   339 	}
   340 
   341 
   342 LOCAL_D TInt test4Thread(TAny *aSem)
   343 //
   344 // Wait to be released on the semaphore.
   345 // Then release the semaphore.
   346 //
   347 	{
   348 
   349 	RSemaphore& sem=(*(RSemaphore*)aSem);
   350 	sem.Wait();
   351 	sem.Signal();
   352 	return(KErrNone);
   353 	}
   354 
   355 TInt BadPriority(TAny* aThread)
   356 	{
   357 	((RThread*)aThread)->SetPriority(EPriorityNull);
   358 	return KErrNone;
   359 	}
   360 
   361 _LIT(KLitRomString,"RomStringRomStringRomStringRomStringRomStringRomStringRomString");
   362 
   363 LOCAL_C TInt BadFullNameThread(TAny* aPar)
   364 	{
   365 	RThread thread;
   366 	
   367 	switch ((TInt)aPar)
   368 		{
   369 		case 0:
   370 			{
   371 			HBufC* hBuf = HBufC::New(5);//Size 5 is not sufficient. thread.FullName should panic.
   372 			test(NULL != hBuf);
   373 			RBuf rBuf(hBuf);
   374 			thread.FullName(rBuf);
   375 			rBuf.Close();
   376 			}
   377 			return(KErrNone);
   378 
   379 		case 1:
   380 			{
   381 			TPtr ptr((TText*)(KLitRomString.iBuf), KLitRomString.iTypeLength);
   382 			// Passing descriptor whose data is in ROM. This may behave in different ways
   383 			// on differrent platforms. Here, we just check that Kernel is safe.
   384 			thread.FullName(ptr);
   385 			}
   386 			return(KErrNone);
   387 		}
   388 	return(KErrArgument);
   389 	}
   390 
   391 
   392 LOCAL_D void test1()
   393 //
   394 // Test 1
   395 //
   396 	{
   397 	
   398 	__UHEAP_MARK;
   399 	RThread thread;
   400 	TRequestStatus stat;
   401 	TInt r;
   402 
   403 	test.Start(_L("Close without create"));
   404 	thread.Close();
   405 	
   406 	test.Next(_L("Create ENormal"));
   407 	r = StartInstructionThread(thread, _L("Thread"), ENormal, EOwnerProcess, 0, 0);
   408 	test_KErrNone(r);
   409 
   410 	test.Next(_L("Test priorities"));
   411 	test(thread.Priority()==EPriorityNormal);
   412 	thread.SetPriority(EPriorityRealTime);	// WINS will commute this to EPriorityMuchMore
   413 #if defined(__EPOC32__)
   414 	test(thread.Priority()==EPriorityRealTime);
   415 #endif
   416 	thread.SetPriority(EPriorityMuchMore);
   417 	test(thread.Priority()==EPriorityMuchMore);
   418 //	thread.SetPriority(EPriorityNull);
   419 	RThread badThread;
   420 	r = badThread.Create(_L("Bad Priority"),BadPriority,KDefaultStackSize,KHeapSize,KHeapSize,&thread);
   421 	test(r==KErrNone);
   422 	badThread.Logon(stat);
   423 	test(stat==KRequestPending);
   424 	badThread.Resume();
   425 	User::WaitForRequest(stat);
   426 	test(stat==EBadPriority);
   427 	test(badThread.ExitCategory()==_L("KERN-EXEC"));
   428 	test(badThread.ExitReason()==EBadPriority);
   429 	test(badThread.ExitType()==EExitPanic);
   430 	CLOSE_AND_WAIT(badThread);
   431 	test(thread.Priority()==EPriorityMuchMore);
   432 
   433 #if defined(__EPOC32__)
   434 	test.Next(_L("Test setting process priority from thread"));
   435 	test(thread.ProcessPriority()==EPriorityForeground);
   436 	thread.SetProcessPriority(EPriorityHigh);
   437 	test(thread.ProcessPriority()==EPriorityHigh);
   438 	test(RProcess().Priority()==EPriorityHigh);
   439 	thread.SetProcessPriority(EPriorityForeground);
   440 	test(thread.ProcessPriority()==EPriorityForeground);
   441 	test(RProcess().Priority()==EPriorityForeground);
   442 #endif
   443 
   444 	TBuf<0x100> name;
   445 	test.Next(_L("Test thread name"));
   446 	test(thread.Name()==_L("Thread"));
   447 	test.Next(_L("Get owning process name"));
   448 	RProcess p;
   449 	test(thread.Process(p)==KErrNone);
   450 	name=p.Name();
   451 	name.Append(_L("::"));
   452 	name.Append(thread.Name());
   453 	test.Next(_L("Test fullname - via TFullName RHandleBase::FullName"));
   454 	test(thread.FullName().CompareF(name)==0);
   455 
   456 	test.Next(_L("Test fullname - via void RHandleBase::FullName(TDes& aName)"));
   457 	HBufC* hBuf = HBufC::New(100);
   458 	test(NULL != hBuf);
   459 	TPtr ptr = hBuf->Des();
   460 	thread.FullName(ptr);
   461 	test(ptr.CompareF(name)==0);
   462 	RBuf rBuf(hBuf);
   463 	thread.FullName(rBuf);
   464 	test(rBuf.CompareF(name)==0);
   465 	rBuf.Close();
   466 
   467 	test.Next(_L("Test void RHandleBase::FullName(TDes& aName) when aName is too short"));
   468 	TInt aaa=badThread.Create(_L("BadFullNameThread1"),BadFullNameThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)0);
   469 	test(aaa==KErrNone);
   470 	badThread.Logon(stat);
   471 	test(badThread.ExitType()==EExitPending);
   472 	badThread.Resume();
   473 	User::WaitForRequest(stat);
   474 	test(badThread.ExitCategory()==_L("KERN-EXEC"));
   475 	test(badThread.ExitReason()==EKUDesSetLengthOverflow);
   476 	test(badThread.ExitType()==EExitPanic);
   477 	CLOSE_AND_WAIT(badThread);
   478 
   479 	test.Next(_L("Test void RHandleBase::FullName(TDes& aName) where aName has data in ROM "));
   480 	aaa=badThread.Create(_L("BadFullNameThread2"),BadFullNameThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)1);
   481 	test(aaa==KErrNone);
   482 	badThread.Logon(stat);
   483 	test(badThread.ExitType()==EExitPending);
   484 	badThread.Resume();
   485 	User::WaitForRequest(stat);
   486 	test.Printf(_L("BadFullNameThread2 exited with ExitReason=%d and ExitType=%d\n"),badThread.ExitReason(),badThread.ExitType());
   487 	CLOSE_AND_WAIT(badThread);
   488 
   489 	test.Next(_L("Rename current thread"));
   490 	test(User::RenameThread(_L("renamed"))==KErrNone);
   491 	name=p.Name();
   492 	name.Append(_L("::"));
   493 	RThread me;
   494 	name.Append(me.Name());
   495 	test(me.Name()==_L("renamed"));
   496 	test(me.FullName().CompareF(name)==0);
   497 
   498 	test.Next(_L("Test running exit types"));
   499 	test(thread.ExitType()==EExitPending);
   500 	test(thread.ExitReason()==0);
   501 	// no getters for iUserHeap and iFrame
   502 	test(thread.ExitCategory()==KNullDesC);
   503 
   504 	test.Next(_L("Test logging on"));
   505 	thread.Logon(stat);
   506 	RThread t;
   507 	test(t.RequestCount()==0);
   508 	test(stat==KRequestPending);
   509 	r=thread.LogonCancel(stat); // this generates a signal 
   510 	test(r==KErrNone);
   511 	test(stat==KErrNone);
   512 	test(t.RequestCount()==1); // the request count is 1 due to the signal generated by LogonCancel
   513 	test(thread.RequestCount()==0);
   514 
   515 	test.Next(_L("Resuming thread"));
   516 	thread.Resume();   
   517 	test.Next(_L("Absorb cancel"));
   518 	User::WaitForRequest(stat);	
   519 	test.Next(_L("Test LogonCancel on dead thread is ok"));
   520 	r=thread.LogonCancel(stat);
   521 	test(r==KErrGeneral);
   522 	test.Next(_L("Close thread"));
   523 	CLOSE_AND_WAIT(thread);
   524 	test.Next(_L("Close again"));
   525 	thread.Close();
   526 	thread.Close();
   527 	thread.Close();
   528 	thread.Close();
   529 	__UHEAP_MARKEND;
   530 	test.End();
   531 	}
   532 
   533 
   534 LOCAL_D void test2(TOwnerType anOwnerType)
   535 //
   536 // Test 2
   537 //
   538 	{                                  
   539 
   540 	__UHEAP_MARK;
   541 	RThread thread;
   542 	TRequestStatus stat;
   543 	TRequestStatus rstat;
   544 	TInt r;
   545 
   546 	test.Start(_L("Run thread 10 times"));
   547 	for (TInt xx=0;xx<10;xx++)
   548 		{
   549 		test.Printf(_L("\r%02d"),xx);
   550 		r = StartInstructionThread(thread, _L("Thread1"), ENormal, anOwnerType, &stat, 0);
   551 		test_KErrNone(r);
   552 		thread.Resume();
   553 		User::WaitForRequest(stat);
   554 		CLOSE_AND_WAIT(thread);
   555 		}
   556 	test.Printf(_L("\n"));
   557 
   558 	test.Next(_L("Panic within thread"));
   559 	r = StartInstructionThread(thread, _L("Thread2"), EInstrPanic, anOwnerType, &stat, 0);
   560 	test_KErrNone(r);
   561 	test(thread.ExitType()==EExitPending);
   562 	thread.Resume();
   563 	User::WaitForRequest(stat);
   564 	test(thread.ExitCategory()==_L("Hello"));
   565 	test(thread.ExitReason()==KExitPanicNum);
   566 	test(thread.ExitType()==EExitPanic);
   567 	CLOSE_AND_WAIT(thread);
   568 
   569 	test.Next(_L("Panic external to thread"));
   570 	TInt ijk;
   571 	TUint seed[2] = { 0xadf85458, 0 };
   572 	TUint maxcount = 0;
   573 	for (ijk=0; ijk<8192; ++ijk)
   574 		{
   575 		if (!(ijk&255))
   576 			test.Printf(_L("%d\n"), ijk);
   577 		r = StartInstructionThread(thread, _L("Thread3"), EWait, anOwnerType, &stat, 0);
   578 		test_KErrNone(r);
   579 		__e32_atomic_store_ord32(&IFLAG, 0);
   580 		thread.Resume();
   581 		thread.SetPriority(EPriorityMore);
   582 		if (maxcount==0)
   583 			{
   584 			while (__e32_atomic_load_acq32(&IFLAG)==0 && --maxcount!=0)
   585 				{
   586 				}
   587 			maxcount = 0u - maxcount;
   588 			test.Printf(_L("maxcount=%u\n"), maxcount);
   589 			}
   590 		else
   591 			{
   592 			TUint random = Random(seed);
   593 			random %= maxcount;
   594 			++random;
   595 			while (__e32_atomic_load_acq32(&IFLAG)==0 && --random!=0)
   596 				{
   597 				}
   598 			}
   599 		thread.Panic(_L("panic"), 123);
   600 		User::WaitForRequest(stat);
   601 		test(thread.ExitCategory()==_L("panic"));
   602 		test(thread.ExitReason()==123);
   603 		test(thread.ExitType()==EExitPanic);
   604 		CLOSE_AND_WAIT(thread);
   605 		}
   606 	
   607 	test.Next(_L("Internal exit"));
   608 	r = StartInstructionThread(thread, _L("Thread4"), ENormal, anOwnerType, &stat, 0);
   609 	test_KErrNone(r);
   610 	test(thread.ExitType()==EExitPending);
   611 	thread.Resume();
   612 	User::WaitForRequest(stat);
   613 	test(thread.ExitCategory()==_L("Kill"));
   614 	test(thread.ExitReason()==KThreadReturnValue);
   615 	test(thread.ExitType()==EExitKill);
   616 	CLOSE_AND_WAIT(thread);
   617 
   618 	test.Next(_L("External terminate"));
   619 	r = StartInstructionThread(thread, _L("Thread5"), EWait, anOwnerType, &stat, &rstat);
   620 	test_KErrNone(r);
   621 	test.Next(_L("Terminate"));
   622 	thread.Terminate(KTerminationReason);
   623 	test.Next(_L("Wait"));
   624 	User::WaitForRequest(stat);
   625 	test(thread.ExitCategory()==_L("Terminate"));
   626 	test(thread.ExitReason()==KTerminationReason);
   627 	test(thread.ExitType()==EExitTerminate);
   628 	test.Next(_L("Close"));
   629 	CLOSE_AND_WAIT(thread);
   630   
   631 	test.Next(_L("External kill"));
   632 	r = StartInstructionThread(thread, _L("Thread6"), EWait, anOwnerType, &stat, &rstat);
   633 	test_KErrNone(r);
   634 	thread.Suspend();
   635 	thread.Resume();
   636 	thread.Kill(KKillReason);
   637 	User::WaitForRequest(stat);
   638 	test(thread.ExitCategory()==_L("Kill"));
   639 	test(thread.ExitReason()==KKillReason);
   640 	test(thread.ExitType()==EExitKill);
   641 	test.Next(_L("Kill again"));
   642 	thread.Kill(KErrNone);
   643 	thread.Kill(KErrNone);
   644 	thread.Kill(KErrNone);
   645 	CLOSE_AND_WAIT(thread);
   646 	test.End();
   647   	__UHEAP_MARKEND;
   648 	}
   649 
   650 LOCAL_D void test3()
   651 //
   652 // Test 3.
   653 //
   654 	{
   655 
   656 	test.Start(_L("Read across thread"));
   657 	TReadInfo info;
   658 	TPtrC des1=_L("tdesc");
   659 	info.tdesc=(&des1);
   660 	TPtrC ptr1=_L("tptrc");
   661 	info.tptrc=&ptr1;
   662 	TBuf<0x20> tdes(_L("tdes"));
   663 	info.tdes=&tdes;
   664 	TBuf<0x20> tptrbuf(_L("tptr"));
   665 	TPtr tptr((TText*)tptrbuf.Ptr(),tptrbuf.Length(),tptrbuf.MaxLength());
   666 	info.tptr=&tptr;
   667 	TBuf<0x20> hbufc(_L("hbufc"));
   668 	HBufC *pH=hbufc.Alloc();
   669 	test(pH!=NULL);
   670 	info.hbufc=pH;
   671 	TBufC<0x20> tbufc(_L("tbufc"));
   672 	info.tbufc=&tbufc;
   673 	TBuf<0x20> tbuf(_L("tbuf"));
   674 	info.tbuf=&tbuf;
   675 	TBufC<0x20> tptrdes(_L("tptrdes"));
   676 	TPtr des=tptrdes.Des();
   677 	info.tptrdes=&des;
   678 	TBuf<0x10> b(_L("Hello"));
   679 	info.anAddress=(&b);
   680 	info.anAddress= info.anAddress; //prevents warning (var set but never used)
   681 	delete pH;
   682 	test.End();
   683 	}
   684 
   685 LOCAL_D void test4()
   686 //
   687 // Test 4.
   688 //
   689 	{
   690 
   691 	test.Start(_L("Create sempahore"));
   692 	RSemaphore sem;
   693 	TInt r=sem.CreateLocal(0);
   694 	test(r==KErrNone);
   695 //
   696 	test.Next(_L("Create thread 1"));
   697 	RThread t;
   698 	r=t.Create(_L("Thread1"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
   699 	test(r==KErrNone);
   700 	t.Resume();
   701 	t.Close();
   702 //
   703 	test.Next(_L("Create thread 2"));
   704 	r=t.Create(_L("Thread2"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
   705 	test(r==KErrNone);
   706 	t.Resume();
   707 	t.Close();
   708 //
   709 	test.Next(_L("Create thread 3"));
   710 	r=t.Create(_L("Thread3"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
   711 	test(r==KErrNone);
   712 	t.Resume();
   713 	t.Close();
   714 //
   715 	test.Next(_L("Release threads"));
   716 	sem.Signal(3);
   717 //
   718 	test.Next(_L("Wait 1"));
   719 	sem.Wait();
   720 //
   721 	test.Next(_L("Wait 2"));
   722 	sem.Wait();
   723 //
   724 	test.Next(_L("Wait 2"));
   725 	sem.Wait();
   726 	sem.Close();
   727 //
   728 	test.End();
   729 	}
   730 
   731 TInt MinimalThread(TAny*)
   732 //
   733 // Minimal thread, used in test 5
   734 //
   735 	{
   736 	return(KErrNone);
   737 	}
   738 
   739 LOCAL_D void test5()
   740 //
   741 // Test 5 - tests unclosed but completed threads
   742 //
   743 	{
   744 
   745 	test.Start(_L("Start thread"));
   746 	RThread thread1;
   747 	test(thread1.Create(_L("Test Thread1"),MinimalThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
   748 	TRequestStatus stat1;
   749 	thread1.Logon(stat1);
   750 	thread1.Resume();
   751 	User::WaitForRequest(stat1);
   752 	test(thread1.ExitType()==EExitKill);
   753 	// 'missing'  thread1.Close();
   754 
   755 	test.Next(_L("Start another thread"));
   756 	RThread thread2;
   757 	test(thread2.Create(_L("Test Thread2"),MinimalThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
   758 	TRequestStatus stat2;
   759 	thread2.Logon(stat2);
   760 	thread2.Resume();
   761 	User::WaitForRequest(stat2);  //Goes wrong here in build 48
   762 	test(thread2.ExitType()==EExitKill);
   763 	
   764 	test.Next(_L("Close both threads"));
   765 	CLOSE_AND_WAIT(thread2);
   766 	CLOSE_AND_WAIT(thread1);
   767 
   768 	test.End();
   769 	}
   770 
   771 LOCAL_D TInt test6Thread(TAny *anArg)
   772 //
   773 //
   774 //
   775 	{
   776 	((RSemaphore*)anArg)->Wait();
   777 	RThread t;
   778 	RThread dup;
   779 	dup.Duplicate(t);
   780 	dup.Panic(_L("Test"),0);
   781 
   782 	return KErrNone;
   783 	}
   784 
   785 void test6()
   786 //
   787 // Test thread duplication
   788 //
   789 	{
   790 
   791 	test.Start(_L("Create thread"));
   792 	RSemaphore sem;
   793 	TInt r=sem.CreateLocal(0);
   794 	test(r==KErrNone);
   795 
   796 	RThread t;
   797 	t.Create(_L("test6thread"),test6Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
   798 	test.Next(_L("Resume thread"));
   799 	TRequestStatus stat;
   800 	t.Logon(stat);
   801 	t.Resume();
   802 	sem.Signal();
   803 	User::WaitForRequest(stat);
   804 	test.Next(_L("Close thread"));
   805 	t.Close();
   806 	sem.Close();
   807 	test.End();
   808 	}
   809 
   810 RSemaphore gsem;
   811 enum TThreadProgress { EBeforeStart, EStarted, EWaiting, EDoneWaiting, EFinished };
   812 TThreadProgress progress=EBeforeStart;
   813 LOCAL_D TInt test7thread(TAny * /*anArg*/)
   814 //
   815 //
   816 //
   817 	{
   818 
   819 	progress=EStarted;
   820 	progress=EWaiting;
   821 	gsem.Wait();
   822 	progress=EDoneWaiting;
   823 	gsem.Wait();
   824 	progress=EFinished;
   825 	return KErrNone;
   826 	}
   827 
   828 void test7()
   829 //
   830 //	Suspend/ Resume tests
   831 //
   832 	{
   833 
   834 	TInt r=gsem.CreateLocal(0);
   835 	test(r==KErrNone);
   836 	test.Start(_L("Create thread"));
   837 	RThread t;
   838 	r=t.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
   839 	test(r==KErrNone);
   840 	TRequestStatus stat;
   841 	t.Logon(stat);
   842 	test.Next(_L("Resume thread"));
   843 	t.Resume();
   844 	User::After(KWaitTime); // wait a bit;
   845 	test.Next(_L("Make thread wait on a semaphore"));
   846 	test(progress==EWaiting);
   847 	test.Next(_L("Suspend waiting thread"));
   848 	t.Suspend();
   849 	test.Next(_L("Signal the semaphore"));
   850 	gsem.Signal();
   851 	User::After(KWaitTime);
   852 	test.Next(_L("Test thread still suspended"));
   853 	test(progress==EWaiting);
   854 	test.Next(_L("resume thread"));
   855 	t.Resume();
   856 	test.Next(_L("Test the thread no longer waiting on the semaphore"));
   857 	User::After(KWaitTime);
   858 	test(progress==EDoneWaiting);
   859 	test.Next(_L("Wait for thread to finish"));
   860 	gsem.Signal();
   861 	User::WaitForRequest(stat);
   862 	test(stat==KErrNone);
   863 	test(progress==EFinished);
   864 	CLOSE_AND_WAIT(t);
   865 
   866 	RThread tt;
   867 	progress=EBeforeStart;
   868 	test.Next(_L("Create Thread"));
   869 	r=tt.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
   870 	test(r==KErrNone);
   871 	tt.Logon(stat);
   872 	test.Next(_L("Suspend thread without starting it"));
   873 	tt.Suspend();
   874 	tt.Suspend();
   875 	test.Next(_L("Resume and test suspend/resume balance"));
   876 	tt.Resume();
   877 	tt.Resume();
   878 	User::After(KWaitTime);
   879 	test(progress==EBeforeStart);
   880 	tt.Resume();
   881 	test.Next(_L("test thread is suspended on semaphore"));
   882 	User::After(KWaitTime);
   883 	test(progress==EWaiting);
   884 	test.Next(_L("suspend thread"));
   885 	tt.Suspend();
   886 	tt.Suspend();
   887 	test.Next(_L("resume thread"));
   888 	tt.Resume();
   889 	tt.Resume();
   890 	test.Next(_L("test thread still suspended on semaphore"));
   891 	User::After(KWaitTime);
   892 	test(progress==EWaiting);
   893 	test.Next(_L("Suspend, Suspend, Signal semaphore, Suspend"));
   894 	tt.Suspend();
   895 	tt.Suspend();
   896 	gsem.Signal();
   897 	tt.Suspend();
   898 	test.Next(_L("test thread still suspended on semaphore"));
   899 	User::After(KWaitTime);
   900 	test(progress==EWaiting);
   901 	test.Next(_L("Resume thread, checking suspend/resume balance"));
   902 	tt.Resume();
   903 	User::After(KWaitTime);
   904 	test(progress==EWaiting);
   905 	tt.Resume();
   906 	User::After(KWaitTime);
   907 	test(progress==EWaiting);
   908 	tt.Resume();
   909 	User::After(KWaitTime);
   910 	test(progress==EDoneWaiting);
   911 	test.Next(_L("Resume an executing thread"));
   912 	tt.Resume();
   913 	tt.Resume();
   914 //	test.Next(_L("Suspend and check balance"));
   915 //	tt.Suspend();
   916 //	tt.Suspend();
   917 	test.Next(_L("Wait for thread to finish"));
   918 	gsem.Signal();
   919 	User::After(KWaitTime);
   920 	test(progress==EFinished);
   921 	User::WaitForRequest(stat);
   922 	CLOSE_AND_WAIT(tt);
   923 
   924 //
   925 	test.Next(_L("Create Thread"));
   926 	r=tt.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
   927 	test(r==KErrNone);
   928 	tt.Logon(stat);
   929 	test.Next(_L("Resume"));
   930 	tt.Resume();
   931 	test.Next(_L("Hang thread on semaphore"));
   932 	User::After(KWaitTime);
   933 	test(progress==EWaiting);
   934 	test.Next(_L("Suspend then Resume thread"));
   935 	tt.Suspend();
   936 	tt.Suspend();
   937 	tt.Resume();
   938 	User::After(KWaitTime);
   939 	test(progress==EWaiting);
   940 	tt.Resume();
   941 	test.Next(_L("Check still hanging on semaphore"));
   942 	User::After(KWaitTime);
   943 	test(progress==EWaiting);
   944 	test.Next(_L("Signal Semaphore"));
   945 	gsem.Signal();
   946 	test.Next(_L("Test thread executing again"));
   947 	User::After(KWaitTime);
   948 	test(progress==EDoneWaiting);
   949 	test.Next(_L("Hang thread on another semaphore, and suspend"));
   950 	tt.Suspend();
   951 	test.Next(_L("Signal semaphore, and suspend again"));
   952 	gsem.Signal();
   953 	User::After(KWaitTime);
   954 	test(progress==EDoneWaiting);
   955 	tt.Suspend();
   956 	test.Next(_L("Resume the thread"));
   957 	tt.Resume();
   958 	User::After(KWaitTime);
   959 	test(progress==EDoneWaiting);
   960 	tt.Resume();
   961 	test.Next(_L("Wait for thread to finish"));
   962 	User::After(KWaitTime);
   963 	test(progress==EFinished);
   964 	User::WaitForRequest(stat);
   965 	CLOSE_AND_WAIT(tt);
   966 	test.End();
   967 	}
   968 
   969 #if 0
   970 RSemaphore Sem;
   971 LOCAL_D TInt test8thread(TAny* aPtr)
   972 //
   973 //
   974 //
   975 	{
   976 
   977 	typedef TBuf<0x20> TTestBuf;
   978 	typedef volatile TTestBuf* TTestBufPtr;
   979 	volatile TTestBufPtr& pB=*(volatile TTestBufPtr*)aPtr;
   980 	if ((TUint)pB != 0xc90fdaa2)
   981 		return KErrGeneral;
   982 	Sem.Wait();
   983 	TDesC* pD=(TDesC*)pB;
   984 	test(*pD==_L("Everything's just hunky-dory"));
   985 	delete (TTestBufPtr*)pB;
   986 	__UHEAP_MARKEND;
   987 	return KErrNone;
   988 	}
   989 #endif
   990 
   991 void test8()
   992 //
   993 // Get Heap
   994 //
   995 	{
   996 	// !!! RThread::SetInitialParameter no longer exists
   997 
   998  	/*
   999 	typedef TBuf<0x20> TTestBuf;
  1000 	TTestBuf* buf=(TTestBuf*)0xc90fdaa2;
  1001 
  1002 	test.Start(_L("Create thread"));
  1003 	RThread thread;
  1004 	TInt r=thread.Create(_L("test8thread"),test8thread,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
  1005 	test(r==KErrNone);
  1006 	r=Sem.CreateLocal(0);
  1007 	test(r==KErrNone);
  1008 	test.Next(_L("Set parameter"));
  1009 	r=thread.SetInitialParameter(&buf);
  1010 	test(r==KErrNone);
  1011 	TRequestStatus stat;
  1012 	thread.Logon(stat);
  1013 	thread.SetPriority(EPriorityMore);
  1014 	test.Next(_L("Resume thread"));
  1015 	thread.Resume();
  1016 	test.Next(_L("Set initial parameter NULL"));
  1017 	r=thread.SetInitialParameter(NULL);
  1018 	test(thread.ExitType()==EExitPending);
  1019 
  1020 	test.Next(_L("Get heap"));
  1021 	RHeap* heap;
  1022 	heap=thread.Heap();
  1023 	test.Next(_L("Alloc inside heap"));
  1024 	__RHEAP_MARK(heap);
  1025 	buf=(TTestBuf*)heap->Alloc(sizeof(TTestBuf));
  1026 	test(buf!=NULL);
  1027 	new(buf) TTestBuf;
  1028 	*buf=(_L("Everything's just hunky-dory"));
  1029 
  1030 	Sem.Signal();
  1031 	User::WaitForRequest(stat);
  1032 	test(stat==KErrNone);
  1033 	test(thread.ExitType()==EExitKill);
  1034 	test(thread.ExitReason()==KErrNone);
  1035 
  1036 	test.Next(_L("Close"));
  1037 	thread.Close();
  1038 	Sem.Close();
  1039 	test.End();
  1040 	*/
  1041 	}
  1042 
  1043 TInt Thread(TAny* /*aAny*/)
  1044 	{
  1045 
  1046 	RTest test(_L("Any old thread"));
  1047 	test.Next(_L("Find remote thread"));
  1048 	// find the main thread
  1049 	TFullName name;
  1050 	name=RProcess().Name();
  1051 	name.Append(_L("::*"));
  1052 	TFindThread ft;
  1053 	ft.Find(name);
  1054 	TInt r=ft.Next(name);
  1055 	test(r==KErrNone);
  1056 	RThread t;
  1057 	t.Open(ft);
  1058 
  1059 	t.Close();
  1060 	return KErrNone;
  1061 	}
  1062 
  1063 void test9()
  1064 	{
  1065 
  1066 	test.Start(_L("Test create a NULL TPtr"));
  1067 	TPtr p(NULL, 10, 10);
  1068 	test.Next(_L("Create and run remote thread"));
  1069 	RThread t;
  1070 	TInt r;
  1071 	r=t.Create(_L("Any Old Thread"), Thread, 0x2000, 0x2000, 0x2000, (TAny *)&p);
  1072 	test(KErrNone==r);
  1073 	TRequestStatus stat;
  1074 	t.Logon(stat);
  1075 	t.Resume();
  1076 	test.Next(_L("Wait for thread to complete"));
  1077 	User::WaitForRequest(stat);
  1078 	test(stat==KErrNone);
  1079 	test(t.ExitCategory()==_L("Kill"));
  1080 	test(t.ExitReason()==KErrNone);
  1081 	test(t.ExitType()==EExitKill);
  1082 	CLOSE_AND_WAIT(t);
  1083 	test.End();
  1084     }
  1085 
  1086 
  1087 
  1088 TInt FoghornLeghorn(TAny* aMutex)
  1089 //
  1090 // Thread function
  1091 //
  1092 	{
  1093 
  1094 	((RSemaphore*)aMutex)->Wait();
  1095 	RThread thread;
  1096 	TInt r=thread.Create(_L("I say * boy"),FoghornLeghorn,KDefaultStackSize,NULL,aMutex);
  1097 	test(r==KErrBadName);
  1098 	return KErrNone;
  1099 	}
  1100 
  1101 void testOpen()
  1102 	{
  1103 	
  1104 	test.Start(_L("Create Foghorn Leghorn"));
  1105 	RSemaphore fogMut;
  1106 	fogMut.CreateLocal(0);
  1107 	RThread foghorn;
  1108 	TInt r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
  1109 	test(r==KErrNone);
  1110 	test.Next(_L("Logon"));
  1111 	TRequestStatus stat;
  1112 	foghorn.Logon(stat);
  1113 	test(stat==KRequestPending);
  1114 	test.Next(_L("Resume Foghorn Leghorn"));
  1115 	foghorn.Resume();
  1116 	test.Next(_L("Get full name"));
  1117 	TFindThread find(_L("*Foghorn Leghorn"));
  1118 	TFullName name;
  1119 	r=find.Next(name);
  1120 	test(r==KErrNone);
  1121 	test.Next(_L("Open another handle using full name"));
  1122 	RThread leghorn;
  1123 	r=leghorn.Open(name);
  1124 	test(r==KErrNone);
  1125 	test.Next(_L("Kill using second handle"));
  1126 	leghorn.Kill(34523);
  1127 	User::WaitForRequest(stat);
  1128 	test(stat==34523);
  1129 	test.Next(_L("Close handles"));
  1130 	foghorn.Close();
  1131 	CLOSE_AND_WAIT(leghorn);
  1132 
  1133 	test.Next(_L("Again! - Create Foghorn Leghorn"));
  1134 	r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
  1135 	test(r==KErrNone);
  1136 	test.Next(_L("Logon"));
  1137 	foghorn.Logon(stat);
  1138 	test(stat==KRequestPending);
  1139 	test.Next(_L("Resume Foghorn Leghorn"));
  1140 	foghorn.Resume();
  1141 	test.Next(_L("Get full name"));
  1142 	find.Find(_L("*Foghorn Leghorn"));
  1143 	r=find.Next(name);
  1144 	test(r==KErrNone);
  1145 	test.Next(_L("Open another handle using full name"));
  1146 	r=leghorn.Open(name);
  1147 	test(r==KErrNone);
  1148 	test.Next(_L("Kill using second handle"));
  1149 	leghorn.Kill(67857);
  1150 	User::WaitForRequest(stat);
  1151 	test(stat==67857);
  1152 	test.Next(_L("Close handles"));
  1153 	foghorn.Close();
  1154 	CLOSE_AND_WAIT(leghorn);
  1155 
  1156 	test.Next(_L("Create Foghorn Leghorn"));
  1157 	r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
  1158 	test(r==KErrNone);
  1159 	test.Next(_L("Logon"));
  1160 	foghorn.Logon(stat);
  1161 	test(stat==KRequestPending);
  1162 	test.Next(_L("Resume Foghorn Leghorn"));
  1163 	foghorn.Resume();
  1164 	test.Next(_L("Now close it"));
  1165 	foghorn.Close();
  1166 
  1167 	test.Next(_L("Get full name"));
  1168 	find.Find(_L("*Foghorn Leghorn"));
  1169 	r=find.Next(name);
  1170 	test(r==KErrNone);
  1171 	test.Next(_L("Open using full name"));
  1172 	r=leghorn.Open(name);
  1173 	test(r==KErrNone);
  1174 	test.Next(_L("Kill"));
  1175 	leghorn.Kill(67857);
  1176 	User::WaitForRequest(stat);
  1177 	test(stat==67857);
  1178 	test.Next(_L("Close"));
  1179 	CLOSE_AND_WAIT(leghorn);
  1180 
  1181 	test.Next(_L("Start and get it to try to start a new thread"));
  1182 	r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
  1183 	test(r==KErrNone);
  1184 	foghorn.Logon(stat);
  1185 	test(stat==KRequestPending);
  1186 	foghorn.Resume();
  1187 	fogMut.Signal();
  1188 	User::WaitForRequest(stat);
  1189 	test(stat==KErrNone);
  1190 	test(foghorn.ExitCategory()==_L("Kill"));
  1191 	test(foghorn.ExitReason()==KErrNone);
  1192 	test(foghorn.ExitType()==EExitKill);
  1193 	test.Next(_L("Close"));
  1194 	CLOSE_AND_WAIT(foghorn);
  1195 	fogMut.Close();
  1196 
  1197 	test.End();
  1198 	}
  1199 
  1200 TInt Bunny(TAny*)
  1201 //
  1202 // Thread function
  1203 //
  1204 	{
  1205 
  1206 	FOREVER
  1207 		;
  1208 	}
  1209 
  1210 void testReuse()
  1211 	{
  1212 	
  1213 	test.Start(_L("Create thread with duplicate name"));
  1214 	RThread thread;
  1215 	TFullName name=thread.Name();
  1216 	TInt r=thread.Create(name,Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
  1217 	test(r==KErrAlreadyExists);
  1218 //	thread.Resume(); handle will be invalid since create failed
  1219 	test.Next(_L("Create with a good name"));
  1220 	r=thread.Create(_L("Bugs Bunny"),Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
  1221 	test(r==KErrNone);
  1222 	TRequestStatus stat;
  1223 	thread.Logon(stat);
  1224 	test.Next(_L("Resume"));
  1225 	thread.Resume();
  1226 	test.Next(_L("Kill"));
  1227 	thread.Kill(15);
  1228 	User::WaitForRequest(stat);
  1229 	test(stat==15);
  1230 	CLOSE_AND_WAIT(thread);
  1231 
  1232 	test.End();
  1233 	}
  1234 	
  1235 
  1236 TInt HongKongPhooey(TAny * /*aAny*/)
  1237 	{
  1238 
  1239 	RMutex m;
  1240 	m.OpenGlobal(_L("Test Mutex"));
  1241 	m.Wait();
  1242 	User::Panic(_L("Hello"),900);
  1243 	return KErrNone;
  1244 	}
  1245 
  1246 void testReleaseMutex()
  1247 //
  1248 // Bug HA-187
  1249 //
  1250 	{
  1251 	TInt r;
  1252 	test.Start(_L("Create a global Mutex"));
  1253 	RMutex m;
  1254 	r=m.CreateGlobal(_L("Test Mutex"));
  1255 	test.Next(_L("Create a thread"));
  1256 	RThread number1SuperGuy;
  1257 	r=number1SuperGuy.Create(_L("Hong Kong Phooey"), HongKongPhooey, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
  1258 	test(r==KErrNone);
  1259 	TRequestStatus s;
  1260 	number1SuperGuy.Logon(s);
  1261 	test.Next(_L("Resume Thread"));
  1262 	number1SuperGuy.Resume();
  1263 	test.Next(_L("Wait on Mutex and Panic"));
  1264 	User::WaitForRequest(s);
  1265 	test(number1SuperGuy.ExitType()==EExitPanic);
  1266 	test(number1SuperGuy.ExitCategory()==_L("Hello"));
  1267 	test(number1SuperGuy.ExitReason()==900);
  1268 	User::After(100000);	// wait a bit for everything to be cleaned up
  1269 	m.Wait();
  1270 	test.Next(_L("Close everything"));
  1271 	m.Close();
  1272 	CLOSE_AND_WAIT(number1SuperGuy);
  1273 	test.End();
  1274 	}
  1275 
  1276 void testId()
  1277 	{
  1278 
  1279 	test.Start(_L("Try to open nonexistant thread by ID"));
  1280 	RThread thread;
  1281 	TInt r=thread.Open(*(TThreadId*)&KMaxTUint);
  1282 	test(r==KErrNotFound);
  1283 	test.Next(_L("Get thread ID"));
  1284 	r=thread.Create(_L("Buster Bunny"),Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
  1285 	test(r==KErrNone);
  1286 	TThreadId id=thread.Id();
  1287 	TThreadId id2=thread.Id();
  1288 	test(id==id2);
  1289 	RThread thread2;
  1290 	r=thread2.Create(_L("Babs Bunny"),Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
  1291 	test(r==KErrNone);
  1292 	id2=thread2.Id();
  1293 	test(id!=id2);
  1294 	test(*(TUint*)&id+1==*(TUint*)&id2);
  1295 	test.Next(_L("Open by ID"));
  1296 	TRequestStatus stat;
  1297 	thread.Logon(stat);
  1298 	thread.Kill(54624);
  1299 	User::WaitForRequest(stat);
  1300 	test(stat==54624);
  1301 	thread.Close();
  1302 	r=thread.Open(id2);
  1303 	test(r==KErrNone);
  1304 	test(thread.Name()==_L("Babs Bunny"));
  1305 	test(thread.FullName()==thread2.FullName());
  1306 	thread2.Close();
  1307 	id=thread.Id();
  1308 	test(id==id2);
  1309 	thread.Logon(stat);
  1310 	thread.Kill(88863);
  1311 	User::WaitForRequest(stat);
  1312 	test(stat==88863);
  1313 	CLOSE_AND_WAIT(thread);
  1314 	
  1315 	test.End();
  1316 	}
  1317 
  1318 struct SCreateInfo
  1319 	{
  1320 	TInt iStackSize;
  1321 	TInt iMinHeapSize;
  1322 	TInt iMaxHeapSize;
  1323 	};
  1324 
  1325 TInt BadCreation(TAny* aCreateInfo)
  1326 	{
  1327 	SCreateInfo& info=*((SCreateInfo*)aCreateInfo);
  1328 	RThread thread;
  1329 	thread.Create(_L("Won't work"),Bunny,info.iStackSize,info.iMinHeapSize,info.iMaxHeapSize,NULL);
  1330 	return KErrNone;
  1331 	}
  1332 
  1333 void testCreate()
  1334 	{
  1335 	test.Start(_L("Negative stack size"));
  1336 	RThread thread;
  1337 	TRequestStatus stat;
  1338 	TInt r;
  1339 	{
  1340 	SCreateInfo info={-1,0x1000,0x1000};
  1341 	r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
  1342 	test(KErrNone==r);
  1343 	thread.Logon(stat);
  1344 	thread.Resume();
  1345 	User::WaitForRequest(stat);
  1346 	test(stat==EThrdStackSizeNegative);
  1347 	test(thread.ExitType()==EExitPanic);
  1348 	test(thread.ExitReason()==EThrdStackSizeNegative);
  1349 	test(thread.ExitCategory()==_L("USER"));
  1350 	CLOSE_AND_WAIT(thread);
  1351 	}
  1352 //
  1353 	test.Next(_L("Negative heap min size"));
  1354 	{
  1355 	SCreateInfo info={0x1000,-1,0x1000};
  1356 	r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
  1357 	test(KErrNone==r);
  1358 	thread.Logon(stat);
  1359 	thread.Resume();
  1360 	User::WaitForRequest(stat);
  1361 	test(stat==EThrdHeapMinTooSmall);
  1362 	test(thread.ExitType()==EExitPanic);
  1363 	test(thread.ExitReason()==EThrdHeapMinTooSmall);
  1364 	test(thread.ExitCategory()==_L("USER"));
  1365 	CLOSE_AND_WAIT(thread);
  1366 	}
  1367 	test.Next(_L("Negative heap max size"));
  1368 	{
  1369 	SCreateInfo info={0x1000,0x1000,-1};
  1370 	r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
  1371 	test(KErrNone==r);
  1372 	thread.Logon(stat);
  1373 	thread.Resume();
  1374 	User::WaitForRequest(stat);
  1375 	test(stat==EThrdHeapMaxLessThanMin);
  1376 	test(thread.ExitType()==EExitPanic);
  1377 	test(thread.ExitReason()==EThrdHeapMaxLessThanMin);
  1378 	test(thread.ExitCategory()==_L("USER"));
  1379 	CLOSE_AND_WAIT(thread);
  1380 	}
  1381 	test.Next(_L("heap max size < heap min size"));
  1382 	{
  1383 	SCreateInfo info={0x1000,0x2001,0x1000};
  1384 	r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
  1385 	test(KErrNone==r);
  1386 	thread.Logon(stat);
  1387 	thread.Resume();
  1388 	User::WaitForRequest(stat);
  1389 	test(stat==EThrdHeapMaxLessThanMin);
  1390 	test(thread.ExitType()==EExitPanic);
  1391 	test(thread.ExitReason()==EThrdHeapMaxLessThanMin);
  1392 	test(thread.ExitCategory()==_L("USER"));
  1393 	CLOSE_AND_WAIT(thread);
  1394 	}
  1395 	test.Next(_L("Little min heap size"));
  1396 	{
  1397 	SCreateInfo info={0x1000,KMinHeapSize-1,0x1000};
  1398 	r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
  1399 	test(KErrNone==r);
  1400 	thread.Logon(stat);
  1401 	thread.Resume();
  1402 	User::WaitForRequest(stat);
  1403 	test(stat==EThrdHeapMinTooSmall);
  1404 	test(thread.ExitType()==EExitPanic);
  1405 	test(thread.ExitReason()==EThrdHeapMinTooSmall);
  1406 	test(thread.ExitCategory()==_L("USER"));
  1407 	CLOSE_AND_WAIT(thread);
  1408 	}
  1409 	test.End();
  1410 	}
  1411 
  1412 TInt StackInfoThread(TAny*)
  1413 	{
  1414 	TInt a;
  1415 	RThread::Rendezvous((TInt)&a);  // Complete rendezvous using address of 'a' which is on the stack
  1416 	return 0;
  1417 	}
  1418 
  1419 void testThreadStackInfo()
  1420 	{
  1421 	// Check the info about the current thread's stack
  1422 	RThread thread;
  1423 	TThreadStackInfo info;
  1424 	TInt r = thread.StackInfo(info);
  1425 	test(r==KErrNone);
  1426 	TLinAddr a = (TLinAddr)&info;
  1427 	test.Printf(_L("address on stack=%x iBase=%x iLimit=%x iExpandLimit=%x"),a,info.iBase,info.iLimit,info.iExpandLimit);
  1428 	test(a<=info.iBase);
  1429 	test(a>=info.iLimit);
  1430 	test(info.iExpandLimit<=info.iLimit);
  1431 
  1432 	// Create another thread
  1433 	r=thread.Create(_L("StackInfoThread"),StackInfoThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL);
  1434 	test(r==KErrNone);
  1435 	thread.SetPriority(EPriorityLess);
  1436 
  1437 	// Resume thread and wait for it to run
  1438 	TRequestStatus stat;
  1439 	thread.Rendezvous(stat);
  1440 	thread.Resume();
  1441 	User::WaitForRequest(stat);
  1442 
  1443 	// Test getting stack info of another thread
  1444 	r = thread.StackInfo(info);
  1445 	test(r==KErrNone);
  1446 	a = stat.Int(); // a = an address on the threads stack
  1447 	test.Printf(_L("address on stack=%x iBase=%x iLimit=%x iExpandLimit=%x"),a,info.iBase,info.iLimit,info.iExpandLimit);
  1448 	test(a<=info.iBase);
  1449 	test(a>=info.iLimit);
  1450 	test(info.iExpandLimit<=info.iLimit);
  1451 
  1452 	// Let thread run to end
  1453 	thread.Logon(stat);
  1454 	User::WaitForRequest(stat);
  1455 	test(stat.Int()==0);
  1456 	}
  1457 
  1458 GLDEF_C TInt E32Main()
  1459 //
  1460 // Main
  1461 //
  1462 	{	
  1463  
  1464 	// don't want just in time debugging as we trap panics
  1465 	TBool justInTime=User::JustInTime(); 
  1466 	User::SetJustInTime(EFalse); 
  1467 
  1468 	test.Title();
  1469 	__UHEAP_MARK;
  1470 	
  1471 
  1472 	TFullName name;
  1473 	name=RThread().Name();
  1474 
  1475 	test.Start(_L("Test threads"));
  1476 
  1477 	test.Next(_L("Test 1"));
  1478 	test1();
  1479  
  1480 	test.Next(_L("Test create"));
  1481 	testCreate();
  1482 
  1483 	test.Next(_L("Test RUndertaker"));
  1484 	testUndertaker(EOwnerProcess);
  1485 
  1486 	test.Next(_L("Test2"));
  1487 	test2(EOwnerProcess);
  1488 	User::SetJustInTime(justInTime);	
  1489 	test.Next(_L("Test3"));
  1490 	test3();
  1491 	test.Next(_L("Test4"));
  1492 	test4();
  1493 	test.Next(_L("Completed but unclosed thread"));
  1494 	User::SetJustInTime(EFalse);
  1495 	test5();
  1496 	User::SetJustInTime(justInTime);
  1497 	test.Next(_L("Suspend/Resume"));
  1498 	test7();
  1499 	test.Next(_L("Testing thread duplication"));
  1500 	User::SetJustInTime(EFalse);
  1501 	test6();
  1502 	User::SetJustInTime(justInTime);
  1503 	test.Next(_L("Get thread's heap"));
  1504 	test8();
  1505 	test.Next(_L("Test read NULL remotely (HA-178)"));
  1506 	test9();
  1507 	test.Next(_L("Test Open(aFullName)"));
  1508 	testOpen();
  1509 	test.Next(_L("Test Reuse after a failed create"));
  1510 	testReuse();
  1511 	test.Next(_L("Test thread releases Mutex (HA-178)"));
  1512 	User::SetJustInTime(EFalse);
  1513 	testReleaseMutex();
  1514 	User::SetJustInTime(justInTime);
  1515 	test.Next(_L("Test Thread ID"));
  1516 	testId();
  1517 	test.Next(_L("Test RThread::StackInfo"));
  1518 	testThreadStackInfo();
  1519 	test.End();
  1520 	__UHEAP_MARKEND;
  1521 	return(KErrNone);
  1522 	}
  1523 
  1524 
  1525