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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\thread\t_thread.cpp
16 // Tests the RThread class
18 // RThread, RUndertaker
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
32 // - Test unclosed but completed threads.
33 // - Suspend and resume some threads in a variety of ways, verify results are as
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:
46 // Assumptions/Requirement/Pre-requisites:
47 // Failures and causes:
48 // Base Port information:
52 #define __E32TEST_EXTENSION__
57 #include <e32atomics.h>
59 #include <e32def_private.h>
60 #include "../misc/prbs.h"
62 const TInt KNumThreads=20;
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};
71 const TInt KWaitTime=800000;
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"));
91 #define rtest(x) rtest(x,__LINE__)
92 #define wtest(x) wtest(x,__LINE__)
94 LOCAL_C TInt LoopyThread(TAny*)
98 User::AfterHighRes(1000);
101 LOCAL_D void testUndertaker(TOwnerType anOwnerType)
103 // Test RThreadWatcher
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);
117 TRequestStatus stat1;
121 test.Next(_L("Create an RUndertaker"));
124 test.Next(_L("Logon to RUndertaker"));
125 r=u1.Logon(stat1,threadHandle1);
127 test.Next(_L("Logon again & check we're rejected"));
128 r=u1.Logon(stat1,threadHandle1);
130 test.Next(_L("Cancel logon to RUndertaker"));
133 test(stat1==KErrCancel);
135 test.Next(_L("Logon to RUndertaker again"));
136 u1.Logon(stat1,threadHandle1);
138 test.Next(_L("Create another thread"));
140 r=thread2.Create(_L("Loopy2"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
144 TRequestStatus stat2;
148 test.Next(_L("Create another RUndertaker"));
151 test.Next(_L("Logon to RUndertaker"));
152 r=u2.Logon(stat2,threadHandle2);
155 test.Next(_L("Create yet another thread"));
157 r=thread3.Create(_L("Loopy3"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
161 test.Next(_L("Kill the first thread & check the undertakers"));
165 User::WaitForRequest(stat1);
166 User::WaitForRequest(stat2);
167 test(stat1==KErrDied);
168 test(stat2==KErrDied);
172 test.Next(_L("Set the RThread handles"));
173 keep1.SetHandle(threadHandle1);
174 keep2.SetHandle(threadHandle2);
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()));
181 test.Next(_L("Logon again with both watchers"));
182 r=u1.Logon(stat1,threadHandle1);
184 r=u2.Logon(stat2,threadHandle2);
187 test.Next(_L("Kill the 3rd thread & check the undertakers"));
191 User::WaitForRequest(stat1);
192 User::WaitForRequest(stat2);
193 test(stat1==KErrDied);
194 test(stat2==KErrDied);
196 test.Next(_L("Set the RThread handles"));
197 w1.SetHandle(threadHandle1);
198 w2.SetHandle(threadHandle2);
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()));
207 test.Next(_L("Logon again with both undertakers"));
208 r=u1.Logon(stat1,threadHandle1);
210 r=u2.Logon(stat2,threadHandle2);
213 test.Next(_L("Kill the 2nd thread & check the undertakers"));
217 User::WaitForRequest(stat1);
218 User::WaitForRequest(stat2);
219 test(stat1==KErrDied);
220 test(stat2==KErrDied);
222 test.Next(_L("Set the RThread handles"));
223 w1.SetHandle(threadHandle1);
224 w2.SetHandle(threadHandle2);
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()));
231 test.Next(_L("Check kernel allocation"));
232 test.Next(_L("Please wait while I create & close masses of threads"));
233 RThread t[KNumThreads];
235 for (j=0; j<KNumThreads; j++)
238 name.Format(_L("LoopyThread%d"),j);
239 test(t[j].Create(name, LoopyThread, KDefaultStackSize, KHeapSize, KHeapSize, (TAny*)NULL,anOwnerType)==KErrNone);
241 for (j=0; j<KNumThreads-1; j++)
244 CLOSE_AND_WAIT(t[j]);
247 test.Next(_L("Please wait while I close & create some undertakers"));
255 test.Next(_L("Mark kernel heap"));
258 test.Next(_L("Create thread"));
260 r=threadx.Create(_L("Loopyx"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
262 test.Next(_L("Resume thread"));
265 test.Next(_L("Create undertaker"));
266 TRequestStatus statx;
271 test.Next(_L("Logon to undertaker"));
272 r=ux.Logon(statx,threadHandlex);
274 test.Next(_L("Kill thread"));
277 User::WaitForRequest(statx);
278 test(statx==KErrDied);
279 test.Next(_L("Close thread"));
281 wx.SetHandle(threadHandlex);
284 test.Next(_L("Close undertaker"));
287 test.Next(_L("Check kernel heap"));
292 CLOSE_AND_WAIT(keep2);
293 t[KNumThreads-1].Kill(666);
294 CLOSE_AND_WAIT(t[KNumThreads-1]);
296 test.Next(_L("Close RUndertakers"));
304 TInt InstructionThread(TAny* anInstruction)
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);
312 return(KThreadReturnValue);
317 TInt StartInstructionThread(RThread& aT, const TDesC& aName, TInt aInstruction, TOwnerType aOwnerType, TRequestStatus* aL, TRequestStatus* aR)
319 TInt r = aT.Create(aName, &InstructionThread, KDefaultStackSize, KHeapSize, KHeapSize, (TAny*)aInstruction, aOwnerType);
326 test_Equal(s, KRequestPending);
332 test_Equal(s, KRequestPending);
334 User::WaitForRequest(*aR);
342 LOCAL_D TInt test4Thread(TAny *aSem)
344 // Wait to be released on the semaphore.
345 // Then release the semaphore.
349 RSemaphore& sem=(*(RSemaphore*)aSem);
355 TInt BadPriority(TAny* aThread)
357 ((RThread*)aThread)->SetPriority(EPriorityNull);
361 _LIT(KLitRomString,"RomStringRomStringRomStringRomStringRomStringRomStringRomString");
363 LOCAL_C TInt BadFullNameThread(TAny* aPar)
371 HBufC* hBuf = HBufC::New(5);//Size 5 is not sufficient. thread.FullName should panic.
374 thread.FullName(rBuf);
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);
388 return(KErrArgument);
403 test.Start(_L("Close without create"));
406 test.Next(_L("Create ENormal"));
407 r = StartInstructionThread(thread, _L("Thread"), ENormal, EOwnerProcess, 0, 0);
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);
416 thread.SetPriority(EPriorityMuchMore);
417 test(thread.Priority()==EPriorityMuchMore);
418 // thread.SetPriority(EPriorityNull);
420 r = badThread.Create(_L("Bad Priority"),BadPriority,KDefaultStackSize,KHeapSize,KHeapSize,&thread);
422 badThread.Logon(stat);
423 test(stat==KRequestPending);
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);
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);
445 test.Next(_L("Test thread name"));
446 test(thread.Name()==_L("Thread"));
447 test.Next(_L("Get owning process name"));
449 test(thread.Process(p)==KErrNone);
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);
456 test.Next(_L("Test fullname - via void RHandleBase::FullName(TDes& aName)"));
457 HBufC* hBuf = HBufC::New(100);
459 TPtr ptr = hBuf->Des();
460 thread.FullName(ptr);
461 test(ptr.CompareF(name)==0);
463 thread.FullName(rBuf);
464 test(rBuf.CompareF(name)==0);
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);
470 badThread.Logon(stat);
471 test(badThread.ExitType()==EExitPending);
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);
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);
482 badThread.Logon(stat);
483 test(badThread.ExitType()==EExitPending);
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);
489 test.Next(_L("Rename current thread"));
490 test(User::RenameThread(_L("renamed"))==KErrNone);
492 name.Append(_L("::"));
494 name.Append(me.Name());
495 test(me.Name()==_L("renamed"));
496 test(me.FullName().CompareF(name)==0);
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);
504 test.Next(_L("Test logging on"));
507 test(t.RequestCount()==0);
508 test(stat==KRequestPending);
509 r=thread.LogonCancel(stat); // this generates a signal
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);
515 test.Next(_L("Resuming thread"));
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"));
534 LOCAL_D void test2(TOwnerType anOwnerType)
543 TRequestStatus rstat;
546 test.Start(_L("Run thread 10 times"));
547 for (TInt xx=0;xx<10;xx++)
549 test.Printf(_L("\r%02d"),xx);
550 r = StartInstructionThread(thread, _L("Thread1"), ENormal, anOwnerType, &stat, 0);
553 User::WaitForRequest(stat);
554 CLOSE_AND_WAIT(thread);
556 test.Printf(_L("\n"));
558 test.Next(_L("Panic within thread"));
559 r = StartInstructionThread(thread, _L("Thread2"), EInstrPanic, anOwnerType, &stat, 0);
561 test(thread.ExitType()==EExitPending);
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);
569 test.Next(_L("Panic external to thread"));
571 TUint seed[2] = { 0xadf85458, 0 };
573 for (ijk=0; ijk<8192; ++ijk)
576 test.Printf(_L("%d\n"), ijk);
577 r = StartInstructionThread(thread, _L("Thread3"), EWait, anOwnerType, &stat, 0);
579 __e32_atomic_store_ord32(&IFLAG, 0);
581 thread.SetPriority(EPriorityMore);
584 while (__e32_atomic_load_acq32(&IFLAG)==0 && --maxcount!=0)
587 maxcount = 0u - maxcount;
588 test.Printf(_L("maxcount=%u\n"), maxcount);
592 TUint random = Random(seed);
595 while (__e32_atomic_load_acq32(&IFLAG)==0 && --random!=0)
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);
607 test.Next(_L("Internal exit"));
608 r = StartInstructionThread(thread, _L("Thread4"), ENormal, anOwnerType, &stat, 0);
610 test(thread.ExitType()==EExitPending);
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);
618 test.Next(_L("External terminate"));
619 r = StartInstructionThread(thread, _L("Thread5"), EWait, anOwnerType, &stat, &rstat);
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);
631 test.Next(_L("External kill"));
632 r = StartInstructionThread(thread, _L("Thread6"), EWait, anOwnerType, &stat, &rstat);
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);
656 test.Start(_L("Read across thread"));
658 TPtrC des1=_L("tdesc");
660 TPtrC ptr1=_L("tptrc");
662 TBuf<0x20> tdes(_L("tdes"));
664 TBuf<0x20> tptrbuf(_L("tptr"));
665 TPtr tptr((TText*)tptrbuf.Ptr(),tptrbuf.Length(),tptrbuf.MaxLength());
667 TBuf<0x20> hbufc(_L("hbufc"));
668 HBufC *pH=hbufc.Alloc();
671 TBufC<0x20> tbufc(_L("tbufc"));
673 TBuf<0x20> tbuf(_L("tbuf"));
675 TBufC<0x20> tptrdes(_L("tptrdes"));
676 TPtr des=tptrdes.Des();
678 TBuf<0x10> b(_L("Hello"));
680 info.anAddress= info.anAddress; //prevents warning (var set but never used)
691 test.Start(_L("Create sempahore"));
693 TInt r=sem.CreateLocal(0);
696 test.Next(_L("Create thread 1"));
698 r=t.Create(_L("Thread1"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
703 test.Next(_L("Create thread 2"));
704 r=t.Create(_L("Thread2"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
709 test.Next(_L("Create thread 3"));
710 r=t.Create(_L("Thread3"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
715 test.Next(_L("Release threads"));
718 test.Next(_L("Wait 1"));
721 test.Next(_L("Wait 2"));
724 test.Next(_L("Wait 2"));
731 TInt MinimalThread(TAny*)
733 // Minimal thread, used in test 5
741 // Test 5 - tests unclosed but completed threads
745 test.Start(_L("Start thread"));
747 test(thread1.Create(_L("Test Thread1"),MinimalThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
748 TRequestStatus stat1;
749 thread1.Logon(stat1);
751 User::WaitForRequest(stat1);
752 test(thread1.ExitType()==EExitKill);
753 // 'missing' thread1.Close();
755 test.Next(_L("Start another thread"));
757 test(thread2.Create(_L("Test Thread2"),MinimalThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
758 TRequestStatus stat2;
759 thread2.Logon(stat2);
761 User::WaitForRequest(stat2); //Goes wrong here in build 48
762 test(thread2.ExitType()==EExitKill);
764 test.Next(_L("Close both threads"));
765 CLOSE_AND_WAIT(thread2);
766 CLOSE_AND_WAIT(thread1);
771 LOCAL_D TInt test6Thread(TAny *anArg)
776 ((RSemaphore*)anArg)->Wait();
780 dup.Panic(_L("Test"),0);
787 // Test thread duplication
791 test.Start(_L("Create thread"));
793 TInt r=sem.CreateLocal(0);
797 t.Create(_L("test6thread"),test6Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
798 test.Next(_L("Resume thread"));
803 User::WaitForRequest(stat);
804 test.Next(_L("Close thread"));
811 enum TThreadProgress { EBeforeStart, EStarted, EWaiting, EDoneWaiting, EFinished };
812 TThreadProgress progress=EBeforeStart;
813 LOCAL_D TInt test7thread(TAny * /*anArg*/)
822 progress=EDoneWaiting;
830 // Suspend/ Resume tests
834 TInt r=gsem.CreateLocal(0);
836 test.Start(_L("Create thread"));
838 r=t.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
842 test.Next(_L("Resume thread"));
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"));
849 test.Next(_L("Signal the semaphore"));
851 User::After(KWaitTime);
852 test.Next(_L("Test thread still suspended"));
853 test(progress==EWaiting);
854 test.Next(_L("resume thread"));
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"));
861 User::WaitForRequest(stat);
862 test(stat==KErrNone);
863 test(progress==EFinished);
867 progress=EBeforeStart;
868 test.Next(_L("Create Thread"));
869 r=tt.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
872 test.Next(_L("Suspend thread without starting it"));
875 test.Next(_L("Resume and test suspend/resume balance"));
878 User::After(KWaitTime);
879 test(progress==EBeforeStart);
881 test.Next(_L("test thread is suspended on semaphore"));
882 User::After(KWaitTime);
883 test(progress==EWaiting);
884 test.Next(_L("suspend thread"));
887 test.Next(_L("resume thread"));
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"));
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"));
903 User::After(KWaitTime);
904 test(progress==EWaiting);
906 User::After(KWaitTime);
907 test(progress==EWaiting);
909 User::After(KWaitTime);
910 test(progress==EDoneWaiting);
911 test.Next(_L("Resume an executing thread"));
914 // test.Next(_L("Suspend and check balance"));
917 test.Next(_L("Wait for thread to finish"));
919 User::After(KWaitTime);
920 test(progress==EFinished);
921 User::WaitForRequest(stat);
925 test.Next(_L("Create Thread"));
926 r=tt.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
929 test.Next(_L("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"));
938 User::After(KWaitTime);
939 test(progress==EWaiting);
941 test.Next(_L("Check still hanging on semaphore"));
942 User::After(KWaitTime);
943 test(progress==EWaiting);
944 test.Next(_L("Signal Semaphore"));
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"));
951 test.Next(_L("Signal semaphore, and suspend again"));
953 User::After(KWaitTime);
954 test(progress==EDoneWaiting);
956 test.Next(_L("Resume the thread"));
958 User::After(KWaitTime);
959 test(progress==EDoneWaiting);
961 test.Next(_L("Wait for thread to finish"));
962 User::After(KWaitTime);
963 test(progress==EFinished);
964 User::WaitForRequest(stat);
971 LOCAL_D TInt test8thread(TAny* aPtr)
977 typedef TBuf<0x20> TTestBuf;
978 typedef volatile TTestBuf* TTestBufPtr;
979 volatile TTestBufPtr& pB=*(volatile TTestBufPtr*)aPtr;
980 if ((TUint)pB != 0xc90fdaa2)
983 TDesC* pD=(TDesC*)pB;
984 test(*pD==_L("Everything's just hunky-dory"));
985 delete (TTestBufPtr*)pB;
996 // !!! RThread::SetInitialParameter no longer exists
999 typedef TBuf<0x20> TTestBuf;
1000 TTestBuf* buf=(TTestBuf*)0xc90fdaa2;
1002 test.Start(_L("Create thread"));
1004 TInt r=thread.Create(_L("test8thread"),test8thread,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1006 r=Sem.CreateLocal(0);
1008 test.Next(_L("Set parameter"));
1009 r=thread.SetInitialParameter(&buf);
1011 TRequestStatus stat;
1013 thread.SetPriority(EPriorityMore);
1014 test.Next(_L("Resume thread"));
1016 test.Next(_L("Set initial parameter NULL"));
1017 r=thread.SetInitialParameter(NULL);
1018 test(thread.ExitType()==EExitPending);
1020 test.Next(_L("Get heap"));
1023 test.Next(_L("Alloc inside heap"));
1025 buf=(TTestBuf*)heap->Alloc(sizeof(TTestBuf));
1028 *buf=(_L("Everything's just hunky-dory"));
1031 User::WaitForRequest(stat);
1032 test(stat==KErrNone);
1033 test(thread.ExitType()==EExitKill);
1034 test(thread.ExitReason()==KErrNone);
1036 test.Next(_L("Close"));
1043 TInt Thread(TAny* /*aAny*/)
1046 RTest test(_L("Any old thread"));
1047 test.Next(_L("Find remote thread"));
1048 // find the main thread
1050 name=RProcess().Name();
1051 name.Append(_L("::*"));
1054 TInt r=ft.Next(name);
1066 test.Start(_L("Test create a NULL TPtr"));
1067 TPtr p(NULL, 10, 10);
1068 test.Next(_L("Create and run remote thread"));
1071 r=t.Create(_L("Any Old Thread"), Thread, 0x2000, 0x2000, 0x2000, (TAny *)&p);
1073 TRequestStatus stat;
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);
1088 TInt FoghornLeghorn(TAny* aMutex)
1094 ((RSemaphore*)aMutex)->Wait();
1096 TInt r=thread.Create(_L("I say * boy"),FoghornLeghorn,KDefaultStackSize,NULL,aMutex);
1097 test(r==KErrBadName);
1104 test.Start(_L("Create Foghorn Leghorn"));
1106 fogMut.CreateLocal(0);
1108 TInt r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
1110 test.Next(_L("Logon"));
1111 TRequestStatus stat;
1112 foghorn.Logon(stat);
1113 test(stat==KRequestPending);
1114 test.Next(_L("Resume Foghorn Leghorn"));
1116 test.Next(_L("Get full name"));
1117 TFindThread find(_L("*Foghorn Leghorn"));
1121 test.Next(_L("Open another handle using full name"));
1123 r=leghorn.Open(name);
1125 test.Next(_L("Kill using second handle"));
1126 leghorn.Kill(34523);
1127 User::WaitForRequest(stat);
1129 test.Next(_L("Close handles"));
1131 CLOSE_AND_WAIT(leghorn);
1133 test.Next(_L("Again! - Create Foghorn Leghorn"));
1134 r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
1136 test.Next(_L("Logon"));
1137 foghorn.Logon(stat);
1138 test(stat==KRequestPending);
1139 test.Next(_L("Resume Foghorn Leghorn"));
1141 test.Next(_L("Get full name"));
1142 find.Find(_L("*Foghorn Leghorn"));
1145 test.Next(_L("Open another handle using full name"));
1146 r=leghorn.Open(name);
1148 test.Next(_L("Kill using second handle"));
1149 leghorn.Kill(67857);
1150 User::WaitForRequest(stat);
1152 test.Next(_L("Close handles"));
1154 CLOSE_AND_WAIT(leghorn);
1156 test.Next(_L("Create Foghorn Leghorn"));
1157 r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
1159 test.Next(_L("Logon"));
1160 foghorn.Logon(stat);
1161 test(stat==KRequestPending);
1162 test.Next(_L("Resume Foghorn Leghorn"));
1164 test.Next(_L("Now close it"));
1167 test.Next(_L("Get full name"));
1168 find.Find(_L("*Foghorn Leghorn"));
1171 test.Next(_L("Open using full name"));
1172 r=leghorn.Open(name);
1174 test.Next(_L("Kill"));
1175 leghorn.Kill(67857);
1176 User::WaitForRequest(stat);
1178 test.Next(_L("Close"));
1179 CLOSE_AND_WAIT(leghorn);
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);
1184 foghorn.Logon(stat);
1185 test(stat==KRequestPending);
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);
1213 test.Start(_L("Create thread with duplicate name"));
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);
1222 TRequestStatus stat;
1224 test.Next(_L("Resume"));
1226 test.Next(_L("Kill"));
1228 User::WaitForRequest(stat);
1230 CLOSE_AND_WAIT(thread);
1236 TInt HongKongPhooey(TAny * /*aAny*/)
1240 m.OpenGlobal(_L("Test Mutex"));
1242 User::Panic(_L("Hello"),900);
1246 void testReleaseMutex()
1252 test.Start(_L("Create a global Mutex"));
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);
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
1270 test.Next(_L("Close everything"));
1272 CLOSE_AND_WAIT(number1SuperGuy);
1279 test.Start(_L("Try to open nonexistant thread by ID"));
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);
1286 TThreadId id=thread.Id();
1287 TThreadId id2=thread.Id();
1290 r=thread2.Create(_L("Babs Bunny"),Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
1294 test(*(TUint*)&id+1==*(TUint*)&id2);
1295 test.Next(_L("Open by ID"));
1296 TRequestStatus stat;
1299 User::WaitForRequest(stat);
1304 test(thread.Name()==_L("Babs Bunny"));
1305 test(thread.FullName()==thread2.FullName());
1311 User::WaitForRequest(stat);
1313 CLOSE_AND_WAIT(thread);
1325 TInt BadCreation(TAny* aCreateInfo)
1327 SCreateInfo& info=*((SCreateInfo*)aCreateInfo);
1329 thread.Create(_L("Won't work"),Bunny,info.iStackSize,info.iMinHeapSize,info.iMaxHeapSize,NULL);
1335 test.Start(_L("Negative stack size"));
1337 TRequestStatus stat;
1340 SCreateInfo info={-1,0x1000,0x1000};
1341 r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
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);
1353 test.Next(_L("Negative heap min size"));
1355 SCreateInfo info={0x1000,-1,0x1000};
1356 r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
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);
1367 test.Next(_L("Negative heap max size"));
1369 SCreateInfo info={0x1000,0x1000,-1};
1370 r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
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);
1381 test.Next(_L("heap max size < heap min size"));
1383 SCreateInfo info={0x1000,0x2001,0x1000};
1384 r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
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);
1395 test.Next(_L("Little min heap size"));
1397 SCreateInfo info={0x1000,KMinHeapSize-1,0x1000};
1398 r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
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);
1412 TInt StackInfoThread(TAny*)
1415 RThread::Rendezvous((TInt)&a); // Complete rendezvous using address of 'a' which is on the stack
1419 void testThreadStackInfo()
1421 // Check the info about the current thread's stack
1423 TThreadStackInfo info;
1424 TInt r = thread.StackInfo(info);
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);
1432 // Create another thread
1433 r=thread.Create(_L("StackInfoThread"),StackInfoThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL);
1435 thread.SetPriority(EPriorityLess);
1437 // Resume thread and wait for it to run
1438 TRequestStatus stat;
1439 thread.Rendezvous(stat);
1441 User::WaitForRequest(stat);
1443 // Test getting stack info of another thread
1444 r = thread.StackInfo(info);
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);
1452 // Let thread run to end
1454 User::WaitForRequest(stat);
1455 test(stat.Int()==0);
1458 GLDEF_C TInt E32Main()
1464 // don't want just in time debugging as we trap panics
1465 TBool justInTime=User::JustInTime();
1466 User::SetJustInTime(EFalse);
1473 name=RThread().Name();
1475 test.Start(_L("Test threads"));
1477 test.Next(_L("Test 1"));
1480 test.Next(_L("Test create"));
1483 test.Next(_L("Test RUndertaker"));
1484 testUndertaker(EOwnerProcess);
1486 test.Next(_L("Test2"));
1487 test2(EOwnerProcess);
1488 User::SetJustInTime(justInTime);
1489 test.Next(_L("Test3"));
1491 test.Next(_L("Test4"));
1493 test.Next(_L("Completed but unclosed thread"));
1494 User::SetJustInTime(EFalse);
1496 User::SetJustInTime(justInTime);
1497 test.Next(_L("Suspend/Resume"));
1499 test.Next(_L("Testing thread duplication"));
1500 User::SetJustInTime(EFalse);
1502 User::SetJustInTime(justInTime);
1503 test.Next(_L("Get thread's heap"));
1505 test.Next(_L("Test read NULL remotely (HA-178)"));
1507 test.Next(_L("Test Open(aFullName)"));
1509 test.Next(_L("Test Reuse after a failed create"));
1511 test.Next(_L("Test thread releases Mutex (HA-178)"));
1512 User::SetJustInTime(EFalse);
1514 User::SetJustInTime(justInTime);
1515 test.Next(_L("Test Thread ID"));
1517 test.Next(_L("Test RThread::StackInfo"));
1518 testThreadStackInfo();