Update contrib.
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\prime\t_semutx2.cpp
15 // Test RSemaphore and RMutex
17 // Tests the RSemaphore and RMutex
21 // - Test and verify that thread priorities work as expected.
22 // - Test and verify that signalling an RMutex from the wrong
23 // thread fails as expected.
24 // - Test and verify that mutex priority inheritance works as
26 // - Perform an exhaustive state transition test using mutexs
27 // and up to ten threads. Verify priorities, order of execution,
28 // mutex signalling, suspend, resume, kill and close. Verify
29 // results are as expected.
30 // - Test semaphore speed by counting how many Wait/Signal
31 // operations can be completed in one second.
32 // Platforms/Drives/Compatibility:
34 // Assumptions/Requirement/Pre-requisites:
35 // Failures and causes:
36 // Base Port information:
46 const TInt KBufferSize=4096;
47 TUint ThreadId[KBufferSize];
54 RTest test(_L("T_SEMUTX2"));
56 /*****************************************************************************
57 * Utility functions / macros
58 *****************************************************************************/
59 #define TRACE_ON User::SetDebugMask(0xffdfffff);
60 #define TRACE_OFF User::SetDebugMask(0x80000000);
62 //#define MCOUNT(m,c) test((m).Count() ==(c))
63 // mutex count value is not visible for user any more
64 #define MCOUNT(m,c) (void)(1)
65 #define IDCHECK(x) test(GetNextId()==(x))
66 #define NUMCHECK(x) test(NumIdsPending()==(x))
80 TBool Exists(const TDesC& aName)
82 TFullName n(RProcess().Name());
87 return ft.Next(fn)==KErrNone;
90 TBool Exists(TInt aNum)
97 void BusyWait(TInt aMicroseconds)
105 TTimeIntervalMicroSeconds iv=now.MicroSecondsFrom(begin);
106 if (iv.Int64()>=TInt64(aMicroseconds))
111 void Kick(RThread& t)
114 TRequestStatus* pS=&s;
115 t.RequestComplete(pS,0);
121 return ThreadId[GetIx++];
130 /*****************************************************************************
132 *****************************************************************************/
133 TInt Test0Thread(TAny* aPtr)
135 TInt& count=*(TInt*)aPtr;
137 Main.SetPriority(EPriorityMuchMore);
139 Main.SetPriority(EPriorityMuchMore);
141 RThread().SetPriority(EPriorityNormal);
148 User::After(100000); // Test fails intermittently on hardware unless we pause here
150 test.Start(_L("Test thread priorities work"));
151 test.Next(_L("Create thread"));
155 TInt r=t.Create(_L("Test0"),Test0Thread,0x1000,NULL,&count);
159 User::After(10000); // make sure we have a full timeslice
162 test(count==0); // t shouldn't have run yet
163 RThread().SetPriority(EPriorityMuchMore); // shouldn't reschedule (priority unchanged)
165 RThread().SetPriority(EPriorityMore); // shouldn't reschedule (priority decreasing, but not enough)
167 RThread().SetPriority(EPriorityMuchMore); // shouldn't reschedule (priority increasing)
169 RThread().SetPriority(EPriorityNormal); // should reschedule (we go behind t)
171 RThread().SetPriority(EPriorityLess); // should reschedule (priority decreasing to below t)
173 t.SetPriority(EPriorityMuchMore); // shouldn't reschedule (round-robin, timeslice not expired)
175 t.SetPriority(EPriorityNormal); // shouldn't reschedule (t's priority decreasing)
177 t.SetPriority(EPriorityNormal); // shouldn't reschedule (t's priority unchanged)
179 BusyWait(100000); // use up our timeslice
180 t.SetPriority(EPriorityMuchMore); // should reschedule (round-robin, timeslice expired)
182 test(s==KRequestPending);
183 test(t.ExitType()==EExitPending);
184 t.SetPriority(EPriorityRealTime); // should reschedule (t increases above current)
186 test(s==KErrNone); // t should have exited
187 test(t.ExitType()==EExitKill);
188 User::WaitForRequest(s);
189 RThread().SetPriority(EPriorityMuchMore);
194 TInt Test1Thread(TAny*)
202 test.Start(_L("Test signalling from wrong thread"));
203 TInt r=M1.CreateLocal();
207 r=t.Create(_L("Test1"),Test1Thread,0x1000,NULL,NULL);
212 TBool jit = User::JustInTime();
213 User::SetJustInTime(EFalse);
214 User::WaitForRequest(s);
215 User::SetJustInTime(jit);
216 test(s==EAccessDenied);
217 test(t.ExitType()==EExitPanic);
218 test(t.ExitReason()==EAccessDenied);
219 test(t.ExitCategory()==_L("KERN-EXEC"));
225 /*****************************************************************************
226 * Mutex priority inheritance
227 *****************************************************************************/
229 const TInt KTestDelay = 1000000;
231 TInt LowThread(TAny* aPtr)
233 TInt& count=*(TInt*)aPtr;
238 BusyWait(KTestDelay);
240 User::WaitForAnyRequest();
244 TInt MedThread(TAny* aPtr)
246 TInt& count=*(TInt*)aPtr;
250 User::WaitForAnyRequest();
254 TInt HighThread(TAny* aPtr)
256 TInt& count=*(TInt*)aPtr;
263 BusyWait(KTestDelay);
266 User::WaitForAnyRequest();
272 test.Start(_L("Test mutex priority inheritance"));
274 test.Next(_L("Create mutex"));
275 TInt r=M1.CreateLocal();
278 test.Next(_L("Create low priority thread"));
281 r=low.Create(_L("low"),LowThread,0x1000,NULL,&lowcount);
283 low.SetPriority(EPriorityMuchLess);
284 test(Exists(_L("low")));
286 test.Next(_L("Create medium priority thread"));
289 r=med.Create(_L("med"),MedThread,0x1000,NULL,&medcount);
291 med.SetPriority(EPriorityNormal);
292 test(Exists(_L("med")));
294 test.Next(_L("Start low priority thread"));
296 User::AfterHighRes(KTestDelay/10);
300 test.Next(_L("Start medium priority thread"));
302 User::AfterHighRes(KTestDelay/10);
305 User::AfterHighRes(KTestDelay/10);
312 test.Next(_L("Wait, check medium runs"));
313 User::AfterHighRes(KTestDelay/10);
317 test.Next(_L("Create mutex 2"));
321 test.Next(_L("Create high priority thread"));
324 r=high.Create(_L("high"),HighThread,0x1000,NULL,&highcount);
326 high.SetPriority(EPriorityMore);
327 test(Exists(_L("high")));
330 User::AfterHighRes(KTestDelay/10);
336 User::AfterHighRes(KTestDelay/10);
345 test.Next(_L("Wait, check medium runs"));
346 User::AfterHighRes(KTestDelay/10);
350 test.Next(_L("Kill threads"));
357 test(!Exists(_L("low")));
358 test(!Exists(_L("med")));
359 test(!Exists(_L("high")));
365 /*****************************************************************************
366 * Utilities for mutex exhaustive state transition test
367 *****************************************************************************/
372 ThreadId[PutIx++]=(TUint)RThread().Id();
380 typedef void (*PFV)(void);
381 TInt ThreadFunction(TAny* aPtr)
390 User::WaitForAnyRequest();
399 TUint CreateThread(RThread& t, TInt n, TAny* aPtr)
403 TInt r=t.Create(b,ThreadFunction,0x1000,NULL,aPtr);
407 test.Printf(_L("id=%d\n"),id);
412 Possible thread relationships with mutex:
418 Need to verify correct behaviour when the following actions occur for each of these states:
421 Change thread priority
432 User::WaitForAnyRequest();
433 me.SetPriority(EPriorityMuchMore);
434 MutexSignal(); // this should wake up t8
436 MutexSignal(); // this should wake up t9
439 User::WaitForAnyRequest();
444 void RackEmUp(RThread* t, PFV* f, TUint* id)
447 // t1, t2, t5, t10 waiting
448 // t3, t6, t7 waiting+suspended
450 MCOUNT(M1,1); // check mutex free
453 User::WaitForAnyRequest();
454 MCOUNT(M1,0); // check mutex now held
456 for (i=1; i<=10; ++i)
458 Kick(t[i]); // wake up threads
459 User::After(50000); // let threads wait
460 MCOUNT(M1,-9); // check 9 threads waiting
462 User::WaitForAnyRequest();
463 MCOUNT(M1,-7); // check 7 threads waiting
465 IDCHECK(id4); // from the initial wait
466 IDCHECK(id4); // now have t8, t9 pending, t4 holding, rest waiting
467 IDCHECK(id4); // now have t8, t9 pending, t4 holding, rest waiting
468 t[4].SetPriority(EPriorityNormal);
469 t[7].Resume(); // test resume when not suspended
470 MCOUNT(M1,-7); // check 7 threads waiting
473 t[7].Suspend(); // now have required state
474 t[3].Suspend(); // suspend and resume t3 again for good measure
476 MCOUNT(M1,-7); // check 7 threads waiting
480 void SimpleCheck(TInt n, const TUint* id, ...)
484 User::After(50000); // let stuff happen
489 TInt tn=VA_ARG(list,TInt);
494 void Resurrect(TInt n, TThreadPriority aPriority, RThread* t, PFV* f, TUint* id)
497 id[n]=CreateThread(t[n],n,f+n);
498 t[n].SetPriority(EPriorityRealTime);
499 t[n].SetPriority(aPriority);
504 /*****************************************************************************
505 * Mutex exhaustive state transition test
506 *****************************************************************************/
509 test.Start(_L("Test mutex state transitions"));
512 PFV f[11]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
513 id[0]=(TUint)RThread().Id();
517 test.Next(_L("Create mutex"));
518 TInt r=M1.CreateLocal();
524 test.Next(_L("Create threads"));
527 id[i]=CreateThread(t[i],i,f+i);
528 User::After(50000); // let threads wait on mutex
529 MCOUNT(M1,-5); // check 5 threads waiting
530 for (i=-4; i<=0; ++i)
532 MutexSignal(); // wake up next thread
534 MCOUNT(M1,i); // check right number of threads waiting
535 IDCHECK(id0); // check we got mutex back straight away
538 User::After(50000); // let threads claim mutex
540 MCOUNT(M1,0); // check no threads waiting
543 IDCHECK(id[i]); // check they ran in order t1...t5
544 Kick(t[i]); // wake up thread
546 IDCHECK(id0); // check we got it back last
547 t[4].SetPriority(EPriorityMore); // make t4 higher priority
548 User::After(50000); // let threads wait on mutex
549 MCOUNT(M1,-5); // check 5 threads waiting
550 // temp = M1.Count();
552 // temp = M1.Count();
553 User::After(50000); // let threads claim mutex
555 // temp = M1.Count();
556 MCOUNT(M1,0); // check no threads waiting
557 IDCHECK(id4); // check they ran in order t4,t1,t2,t3,t5
563 t[4].SetPriority(EPriorityNormal); // make t4 normal priority
565 Kick(t[i]); // wake up thread
566 User::After(50000); // let threads wait on mutex
567 MCOUNT(M1,-5); // check 5 threads waiting
569 t[3].SetPriority(EPriorityMore); // make t3 higher priority
570 // temp = M1.Count();
572 // temp = M1.Count();
573 User::After(50000); // let threads claim mutex
575 // temp = M1.Count();
576 MCOUNT(M1,0); // check no threads waiting
577 IDCHECK(id3); // check they ran in order t3,t1,t2,t4,t5
583 t[3].SetPriority(EPriorityNormal); // make t4 normal priority
585 Kick(t[i]); // wake up threads
586 User::After(50000); // let threads wait on mutex
587 MCOUNT(M1,-5); // check 5 threads waiting
589 t[2].SetPriority(EPriorityMore); // make t2 higher priority
590 t[1].SetPriority(EPriorityLess); // make t1 lower priority
592 User::After(50000); // let threads claim mutex
594 MCOUNT(M1,0); // check no threads waiting
595 IDCHECK(id2); // check they ran in order t2,t3,t4,t5,t1
603 Kick(t[i]); // wake up threads
604 User::After(50000); // let threads wait on mutex
605 MCOUNT(M1,-5); // check 5 threads waiting
607 User::After(50000); // let threads claim mutex
609 MCOUNT(M1,0); // check no threads waiting
610 IDCHECK(id2); // check they ran in order t2,t3,t4,t5,t1
619 Kick(t[i]); // wake up threads
620 User::After(50000); // let threads wait on mutex
621 MCOUNT(M1,-5); // check 5 threads waiting
622 f[2]=&Exit; // make t2 exit while holding the mutex
624 User::After(50000); // let threads claim mutex
626 MCOUNT(M1,0); // check no threads waiting
627 test(t[2].ExitType()==EExitKill); // check t2 has exited
630 IDCHECK(id2); // check they ran in order t2,t3,t4,t5,t1
637 id[2]=CreateThread(t[2],2,f+2); // recreate t2
638 User::After(50000); // let new t2 wait on mutex
639 MCOUNT(M1,-1); // check 1 thread waiting
641 User::After(50000); // let t2 claim mutex
643 MCOUNT(M1,0); // check no threads waiting
647 t[2].SetPriority(EPriorityLess); // make t2 lower priority
649 Kick(t[i]); // wake up threads
650 User::After(50000); // let threads wait on mutex
651 MCOUNT(M1,-5); // check 5 threads waiting
652 MutexSignal(); // t3 now pending
653 MCOUNT(M1,-3); // check 4 threads waiting, mutex free
654 t[3].Suspend(); // this should wake up t4
655 MCOUNT(M1,-2); // check 3 threads waiting, mutex free
656 User::After(50000); // let threads claim mutex
658 MCOUNT(M1,0); // check no threads still waiting
659 IDCHECK(id4); // check they ran in order t4,t5,t1,t2
664 Kick(t[1]); // wake up t1
665 User::After(50000); // let thread wait on mutex
666 MCOUNT(M1,-1); // check 1 thread waiting
667 t[3].Resume(); // resume pending t3
669 User::After(50000); // let t2 claim mutex
671 MCOUNT(M1,0); // check no threads waiting
672 IDCHECK(id3); // check order t3,t1
677 Kick(t[i]); // wake up threads
678 User::After(50000); // let threads wait on mutex
679 MCOUNT(M1,-5); // check 5 threads waiting
680 t[4].Suspend(); // suspend t4
681 MCOUNT(M1,-5); // check 5 threads waiting
682 t[4].Suspend(); // suspend t4 again
683 MCOUNT(M1,-5); // check 5 threads waiting
685 User::After(50000); // let threads claim mutex
687 MCOUNT(M1,-1); // check 1 thread still waiting
688 IDCHECK(id3); // check they ran in order t3,t5,t1,t2
695 User::After(50000); // let threads claim mutex
697 IDCHECK(id0); // check thread didn't get mutex (still suspended)
700 User::After(50000); // let threads claim mutex
702 IDCHECK(id4); // check order t4 then this
706 Kick(t[i]); // wake up threads
707 User::After(50000); // let threads wait on mutex
708 MCOUNT(M1,-5); // check 5 threads waiting
709 MutexWait(); // wait on mutex again
711 MutexSignal(); // signal once
712 MCOUNT(M1,-5); // check 5 threads still waiting
713 MutexSignal(); // signal again
714 MCOUNT(M1,-3); // check one thread has been woken up and mutex is now free
715 User::After(50000); // let threads claim mutex
717 MCOUNT(M1,0); // check no threads still waiting
718 IDCHECK(id3); // check they ran in order t3,t4,t5,t1,t2
725 test.Next(_L("Create more threads"));
726 for (i=6; i<=10; ++i)
727 id[i]=CreateThread(t[i],i,f+i);
728 User::After(50000); // let threads wait on mutex
729 MCOUNT(M1,-5); // check 5 threads waiting
731 User::After(50000); // let threads claim mutex
732 MCOUNT(M1,1); // check no threads still waiting and mutex free
733 IDCHECK(id6); // check they ran in order t6,t7,t8,t9,t10
738 t[8].SetPriority(EPriorityMore); // t1-t3=less, t4-t7=normal, t8-t10 more, t0 much more
739 t[9].SetPriority(EPriorityMore);
740 t[10].SetPriority(EPriorityMore);
741 t[2].SetPriority(EPriorityLess);
742 t[3].SetPriority(EPriorityLess);
745 SimpleCheck(0,NULL,NULL); // holding thread still blocked
747 SimpleCheck(6,id,10,8,9,5,1,2); // 3,6,7 suspended
751 SimpleCheck(3,id,6,7,3); // 3,6,7 resumed
754 SimpleCheck(0,NULL,NULL); // holding thread still blocked
757 SimpleCheck(0,NULL,NULL); // holding thread suspended
759 SimpleCheck(6,id,10,8,9,5,1,2); // 3,6,7 suspended
763 SimpleCheck(3,id,6,7,3); // 3,6,7 resumed
767 t[4].SetPriority(EPriorityRealTime);
768 MCOUNT(M1,-5); // should be 6 waiting, mutex free
769 t[4].SetPriority(EPriorityNormal);
770 t[8].SetPriority(EPriorityRealTime); // change pending thread priority
771 MCOUNT(M1,-4); // should be 5 waiting, mutex free
772 t[8].SetPriority(EPriorityMore);
775 t[3].SetPriority(EPriorityRealTime); // change suspended thread priority
776 SimpleCheck(5,id,9,10,5,1,2); // 3,6,7 suspended
779 t[3].Resume(); // this should run right away
782 SimpleCheck(2,id,6,7); // 6,7 resumed
783 t[3].SetPriority(EPriorityLess);
787 t[1].SetPriority(EPriorityRealTime); // change waiting thread priority
788 // this should run right away
791 t[1].SetPriority(EPriorityLess);
792 // t8,t9,t10 should now be pending
794 t[8].Suspend(); // this should wake up t5
795 t[9].Suspend(); // this should wake up t2
797 t[8].Suspend(); // this should have no further effect
798 t[8].Resume(); // this should have no further effect
800 SimpleCheck(3,id,10,5,2);
807 SimpleCheck(5,id,8,9,6,7,3);
811 t[8].Suspend(); // this shouldn't wake anything up
812 t[9].Suspend(); // this shouldn't wake anything up
815 t[4].SetPriority(EPriorityRealTime);
816 MCOUNT(M1,1-6); // should be 6 waiting, mutex free, t10 pending
817 t[4].SetPriority(EPriorityNormal);
818 t[10].SetPriority(EPriorityLess); // this should wake up t5
819 MCOUNT(M1,1-5); // should be 5 waiting, mutex free, t10, t5 pending
820 SimpleCheck(4,id,5,10,1,2);
821 t[3].SetPriority(EPriorityRealTime); // boost suspended+waiting thread
822 MCOUNT(M1,1-3); // should be 3 waiting+suspended, mutex free, t8, t9 pending+suspended
827 t[3].Resume(); // this should run immediately
828 MCOUNT(M1,1); // t8,t9,t6,t7 pending, mutex free
830 IDCHECK(id3); // t3 should have run
831 t[3].SetPriority(EPriorityLess);
832 t[9].SetPriority(EPriorityMuchLess); // lower pending thread priority
833 SimpleCheck(4,id,8,6,7,9);
834 t[9].SetPriority(EPriorityMore);
835 t[10].SetPriority(EPriorityMore);
839 t[8].Suspend(); // this shouldn't wake anything up
840 t[9].Suspend(); // this shouldn't wake anything up
844 t[4].SetPriority(EPriorityRealTime);
845 MCOUNT(M1,1-6); // should be 6 waiting, mutex free, t10 pending, t8,t9 pending+suspended
846 t[4].SetPriority(EPriorityNormal);
847 t[10].SetPriority(EPriorityMuchLess); // lower pending thread priority
848 MCOUNT(M1,1-5); // should now be 5 waiting, mutex free, t10,t5 pending, t8,t9 pending+suspended
851 t[3].Resume(); // this gets made READY straight away
852 SimpleCheck(7,id,5,6,7,3,1,2,10);
855 SimpleCheck(2,id,8,9);
856 t[10].SetPriority(EPriorityMore);
861 t[9].Kill(0); // kill pending thread
864 t[1].Kill(0); // kill waiting thread
867 t[6].Kill(0); // kill suspended+waiting thread
872 SimpleCheck(6,id,10,8,5,7,2,3); // 8 runs first and gets blocked behind 10
873 Resurrect(9,EPriorityMore,t,f,id);
874 Resurrect(1,EPriorityLess,t,f,id);
875 Resurrect(6,EPriorityNormal,t,f,id);
879 t[8].Suspend(); // this shouldn't wake anything up
880 t[9].Suspend(); // this shouldn't wake anything up
884 t[4].SetPriority(EPriorityRealTime);
885 MCOUNT(M1,1-6); // should be 6 waiting, mutex free, t10 pending, t8,t9 pending+suspended
886 t[4].SetPriority(EPriorityNormal);
887 t[10].Kill(0); // kill pending thread - this should wake up t5
890 MCOUNT(M1,1-5); // should be 5 waiting, mutex free, t5 pending, t8,t9 pending+suspended
891 t[5].SetPriority(EPriorityRealTime); // this should make t5 run
892 MCOUNT(M1,1-4); // should be 4 waiting, mutex free, t1 pending, t8,t9 pending+suspended
893 t[5].SetPriority(EPriorityNormal);
896 t[8].SetPriority(EPriorityRealTime); // this shouldn't make anything happen
897 MCOUNT(M1,1-4); // mutex free, t1 pending, t8,t9 pending+suspended, t3,t6,t7 wait+susp, t2 waiting
900 MCOUNT(M1,1-3); // mutex free, t1,t2 pending, t9 pending+suspended, t3,t6,t7 wait+susp
903 t[8].SetPriority(EPriorityMore);
908 SimpleCheck(6,id,9,6,7,1,2,3);
909 Resurrect(10,EPriorityMore,t,f,id);
913 t[8].Suspend(); // this shouldn't wake anything up
914 t[9].Suspend(); // this shouldn't wake anything up
918 t[4].SetPriority(EPriorityRealTime);
919 MCOUNT(M1,1-6); // mutex free, t10 pending, t8,t9 pending+susp, t3,t6,t7 wait+susp, t1,t2,t5 wait
920 t[4].SetPriority(EPriorityNormal);
921 t[1].SetPriority(EPriorityRealTime); // this should be able to run and claim the mutex
924 MCOUNT(M1,1-4); // mutex free, t10,t5 pending, t8,t9 pending+susp, t3,t6,t7 wait+susp, t2 wait
925 t[1].SetPriority(EPriorityLess);
931 SimpleCheck(8,id,10,9,8,5,6,7,3,2);
936 M1.Close(); // close the mutex - non-suspended threads should all panic with KERN-EXEC 0
937 TBool jit = User::JustInTime();
938 User::SetJustInTime(EFalse);
939 User::After(1000000);
940 User::SetJustInTime(jit);
941 for (i=1; i<=10; ++i)
943 if (i==3 || i==6 || i==7)
945 test(t[i].ExitType()==EExitPending);
949 test(t[i].ExitType()==EExitPanic);
950 test(t[i].ExitReason()==EBadHandle);
951 test(t[i].ExitCategory()==_L("KERN-EXEC"));
959 User::SetJustInTime(EFalse);
960 User::After(1000000);
961 User::SetJustInTime(jit);
962 for (i=1; i<=10; ++i)
964 if (i==3 || i==6 || i==7)
966 test(t[i].ExitType()==EExitPanic);
967 test(t[i].ExitReason()==EBadHandle);
968 test(t[i].ExitCategory()==_L("KERN-EXEC"));
977 /*****************************************************************************
979 *****************************************************************************/
980 TInt MutexSpeed(TAny* aPtr)
982 TInt& count=*(TInt*)aPtr;
983 RThread().SetPriority(EPriorityMore);
992 TInt MutexSpeed2(TAny* aPtr)
994 TInt& count=*(TInt*)aPtr;
995 RThread().SetPriority(EPriorityMore);
1006 void TestMutexSpeed()
1008 test.Start(_L("Test mutex speed"));
1010 TInt r=M1.CreateLocal();
1014 r=t.Create(_L("Speed"),MutexSpeed,0x1000,NULL,&count);
1016 t.SetPriority(EPriorityRealTime);
1018 User::AfterHighRes(1000000);
1021 test(!Exists(_L("Speed")));
1022 test.Printf(_L("%d wait/signal in 1 second\n"),count);
1025 r=t.Create(_L("Speed2"),MutexSpeed2,0x1000,NULL,&count2);
1027 t.SetPriority(EPriorityRealTime);
1029 User::AfterHighRes(1000000);
1032 test(!Exists(_L("Speed2")));
1033 test.Printf(_L("%d double wait/signal in 1 second\n"),count2);
1039 /*****************************************************************************
1040 * Utilities for semaphore test
1041 *****************************************************************************/
1046 ThreadId[PutIx++]=(TUint)RThread().Id();
1054 TInt SemThreadFunction(TAny* aPtr)
1063 User::WaitForAnyRequest();
1069 User::WaitForAnyRequest();
1072 TUint CreateSemThread(RThread& t, TInt n, TAny* aPtr)
1076 TInt r=t.Create(b,SemThreadFunction,0x1000,NULL,aPtr);
1084 Possible thread relationships with semaphore:
1088 Need to verify correct behaviour when the following actions occur for each of these states:
1091 Change thread priority
1097 void RackEmUp2(RThread* t, PFV* f, TUint* id)
1100 // t1, t2, t4, t5, t6, t8, t9 waiting
1101 // t3, t7, t10 waiting+suspended
1103 MCOUNT(S,2); // check semaphore level = 2
1106 MCOUNT(S,0); // check semaphore level = 0
1111 for (i=1; i<=10; ++i)
1112 Kick(t[i]); // wake up threads
1113 User::After(50000); // let threads wait
1114 MCOUNT(S,-10); // check 10 threads waiting
1115 t[7].Resume(); // test resume when not suspended
1116 MCOUNT(S,-10); // check 7 threads waiting
1119 t[10].Suspend(); // now have required state
1120 t[3].Suspend(); // suspend and resume t3 again for good measure
1122 MCOUNT(S,-7); // check 7 threads waiting
1125 void Resurrect2(TInt n, TThreadPriority aPriority, RThread* t, PFV* f, TUint* id)
1128 id[n]=CreateSemThread(t[n],n,f+n);
1129 t[n].SetPriority(EPriorityRealTime);
1130 t[n].SetPriority(aPriority);
1135 /*****************************************************************************
1136 * Semaphore exhaustive state transition test
1137 *****************************************************************************/
1138 void TestSemaphore()
1140 test.Start(_L("Test semaphore state transitions"));
1143 PFV f[11]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
1144 id[0]=(TUint)RThread().Id();
1148 test.Next(_L("Create semaphore"));
1149 TInt r=S.CreateLocal(2);
1165 test.Next(_L("Create threads"));
1167 for (i=1; i<=10; ++i)
1169 id[i]=CreateSemThread(t[i],i,f+i);
1172 t[8].SetPriority(EPriorityMore); // t1-t3=less, t4-t7=normal, t8-t10 more, t0 much more
1173 t[9].SetPriority(EPriorityMore);
1174 t[10].SetPriority(EPriorityMore);
1175 t[1].SetPriority(EPriorityLess);
1176 t[2].SetPriority(EPriorityLess);
1177 t[3].SetPriority(EPriorityLess);
1179 MCOUNT(S,-8); // check 8 waiting
1182 IDCHECK(id9); // check t8,t9 got through
1183 t[8].SetPriority(EPriorityRealTime);
1184 Kick(t[8]); // let t8 run and signal
1185 t[8].SetPriority(EPriorityMore);
1186 MCOUNT(S,-7); // check 7 waiting
1187 User::After(50000); // let next thread obtain semaphore
1188 MCOUNT(S,-7); // check 7 waiting
1190 IDCHECK(id10); // check t10 got it
1191 Kick(t[10]); // let t10 run and signal
1192 User::After(50000); // let next thread obtain semaphore
1193 MCOUNT(S,-6); // check 6 waiting
1195 IDCHECK(id4); // check t4 got it
1196 t[1].SetPriority(EPriorityRealTime); // boost t1
1197 MCOUNT(S,-6); // check 6 still waiting
1198 User::After(50000); // let next thread obtain semaphore
1199 MCOUNT(S,-6); // check 6 still waiting
1201 Kick(t[9]); // make t9 ready to run and signal
1202 MCOUNT(S,-6); // check 6 still waiting
1203 User::After(50000); // let next thread obtain semaphore
1204 MCOUNT(S,-5); // check 5 waiting
1206 IDCHECK(id1); // check t1 got it
1207 t[1].SetPriority(EPriorityLess);
1208 Kick(t[1]); // kick all remaining threads
1215 User::After(50000); // let them run and obtain/signal the semaphore
1216 MCOUNT(S,2); // check semaphore now back to initial level
1217 SimpleCheck(5,id,5,6,7,2,3);
1219 for (i=1; i<=10; ++i)
1221 RackEmUp2(t,f,id); // set up threads waiting on semaphore again
1223 SimpleCheck(7,id,8,9,4,5,6,1,2); // let them go
1226 t[3].SetPriority(EPriorityRealTime); // change suspended thread priority
1228 SimpleCheck(0,id); // t7 should wait for signal
1230 SimpleCheck(1,id,7);
1235 IDCHECK(id3); // t3 should have grabbed semaphore as soon as we resumed it
1236 SimpleCheck(1,id,10);
1237 t[3].SetPriority(EPriorityLess);
1238 S.Signal(); // put level back to 2
1240 RackEmUp2(t,f,id); // set up threads waiting on semaphore again
1242 SimpleCheck(7,id,8,9,4,5,6,1,2); // let them go
1245 t[3].SetPriority(EPriorityRealTime); // change suspended thread priority
1247 SimpleCheck(0,id); // t7 should wait for signal
1249 SimpleCheck(1,id,7);
1252 t[3].Resume(); // t3 not woken up here since t10 has already been given the semaphore
1254 SimpleCheck(2,id,10,3);
1255 t[3].SetPriority(EPriorityLess);
1256 S.Signal(); // put level back to 2
1258 RackEmUp2(t,f,id); // set up threads waiting on semaphore again
1260 SimpleCheck(7,id,8,9,4,5,6,1,2); // let them go
1263 t[3].SetPriority(EPriorityRealTime); // change suspended thread priority
1265 SimpleCheck(0,id); // t7 should wait for signal
1267 S.Signal(); // put level back to 2
1268 SimpleCheck(1,id,7);
1271 t[3].Resume(); // t3 and t10 both woken up here, t3 should run and signal
1275 SimpleCheck(1,id,10);
1276 t[3].SetPriority(EPriorityLess);
1278 RackEmUp2(t,f,id); // set up threads waiting on semaphore again
1279 t[9].Kill(0); // kill waiting thread
1282 t[10].Kill(0); // kill suspended thread
1286 f[5]=&Exit; // get t5 to exit after acquiring semaphore
1288 SimpleCheck(3,id,8,4,5); // let them go
1289 MCOUNT(S,-3); // check one signal has been lost due to t5 exiting
1296 SimpleCheck(5,id,6,7,1,2,3); // let them go
1298 Resurrect2(9,EPriorityMore,t,f,id);
1299 Resurrect2(10,EPriorityMore,t,f,id);
1300 Resurrect2(5,EPriorityNormal,t,f,id);
1303 RackEmUp2(t,f,id); // set up threads waiting on semaphore again
1304 f[5]=&Exit; // get t5 to exit after acquiring semaphore
1305 S.Close(); // close semaphore - threads should panic except for 5
1307 TBool jit = User::JustInTime();
1308 User::SetJustInTime(EFalse);
1309 User::After(1000000);
1310 User::SetJustInTime(jit);
1311 for (i=1; i<=10; ++i)
1313 if (i==3 || i==7 || i==10)
1315 test(t[i].ExitType()==EExitPending);
1319 test(t[i].ExitType()==EExitPanic);
1320 test(t[i].ExitReason()==EBadHandle);
1321 test(t[i].ExitCategory()==_L("KERN-EXEC"));
1327 test(t[i].ExitType()==EExitKill);
1328 test(t[i].ExitReason()==0);
1336 User::SetJustInTime(EFalse);
1337 User::After(1000000);
1338 User::SetJustInTime(jit);
1339 for (i=1; i<=10; ++i)
1341 if (i==3 || i==7 || i==10)
1343 test(t[i].ExitType()==EExitPanic);
1344 test(t[i].ExitReason()==EBadHandle);
1345 test(t[i].ExitCategory()==_L("KERN-EXEC"));
1354 /*****************************************************************************
1355 * Semaphore benchmarks
1356 *****************************************************************************/
1357 TInt SemSpeed(TAny* aPtr)
1359 TInt& count=*(TInt*)aPtr;
1360 RThread().SetPriority(EPriorityMore);
1371 test.Start(_L("Test semaphore speed"));
1373 TInt r=S.CreateLocal(1);
1377 r=t.Create(_L("SemSpeed"),SemSpeed,0x1000,NULL,&count);
1379 t.SetPriority(EPriorityRealTime);
1381 User::AfterHighRes(1000000);
1384 test(!Exists(_L("SemSpeed")));
1385 test.Printf(_L("%d wait/signal in 1 second\n"),count);
1392 GLDEF_C TInt E32Main()
1396 test.Start(_L("Test mutexes and semaphores"));
1397 RThread().SetPriority(EPriorityMuchMore);
1398 TInt r=Main.Duplicate(RThread());