kerneltest/e32test/thread/t_thread.cpp
changeset 0 a41df078684a
child 102 ef2a444a7410
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\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