Update contrib.
1 // Copyright (c) 1994-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\system\t_condvar.cpp
16 // Test the use of the RCondVar & RMutex classes.
20 // - Create some local conditional variables and mutexes and verify results
22 // - Create a test thread that waits on conditional variables and mutexes,
23 // append some items on an array, signal the conditional variable and mutex,
24 // the thread then counts the number of items on the array and passes the
25 // result back to the main process. Verify results are as expected. Repeat
26 // with different array data.
27 // - Verify that a RCondVar::Wait() panics when the thread does not hold the
28 // specified mutex (mutex not locked).
29 // - Test using two mutexes with 1 conditional variable, append some items to
30 // an array, verify results from the thread are as expected.
31 // - Create a second thread with higher priority, perform tests similar to
32 // above, verify results are as expected.
33 // - Verify the thread timeout values are as expected.
34 // - Create global conditional variables and global mutexes, using two threads
35 // test the RCondVar::Signal() and RMutex::Wait() results are as expected.
36 // - Test various combinations of creating a thread, suspending and killing it
37 // and signalling a conditional variable and mutex. Verify results are as
39 // - Create a secondary process along with a global chunk, conditional variable
40 // and mutex. Signal the conditional variable and verify the results are as
42 // - Using two threads, benchmark the number of conditional variable/mutex Signal
43 // and Wait iterations that can be completed per second.
44 // Platforms/Drives/Compatibility:
46 // Assumptions/Requirement/Pre-requisites:
47 // Failures and causes:
48 // Base Port information:
53 #include <e32std_private.h>
58 #include <e32def_private.h>
60 RTest test(_L("T_CONDVAR"));
66 #define __TRACE_LINE__ test.Printf(_L("Line %d\n"),__LINE__)
85 const TText* iMutexName;
86 const TText* iCondVarName;
90 SThreadData::SThreadData()
92 memset(this, 0, sizeof(*this));
95 SThreadData2::SThreadData2()
97 memset(this, 0, sizeof(*this));
105 TInt Thread1(TAny* a)
108 SThreadData& d = *(SThreadData*)a;
114 while (d.iA->Count()<=i && r==KErrNone)
116 t1 = User::NTickCount();
118 r = d.iV.TimedWait(d.iM, d.iTimeoutMs*1000);
121 t2 = User::NTickCount();
123 if (r == KErrTimedOut)
126 TInt iv = (TInt)(t2-t1);
135 TInt c = d.iA->Count();
137 d.iTotal += (*d.iA)[i];
142 TInt Thread2(TAny* a)
145 SThreadData& d = *(SThreadData*)a;
148 RThread::Rendezvous(KErrNone);
151 t1 = User::NTickCount();
153 r = d.iV.TimedWait(d.iM, d.iTimeoutMs*1000);
156 t2 = User::NTickCount();
158 if (r == KErrTimedOut)
161 TInt iv = (TInt)(t2-t1);
170 TInt Thread3(TAny* a)
172 SThreadData2& d = *(SThreadData2*)a;
175 TInt r = m.OpenGlobal(TPtrC(d.iMutexName), EOwnerThread);
178 r = cv.OpenGlobal(TPtrC(d.iCondVarName), EOwnerThread);
190 TInt Thread4(TAny* a)
192 volatile TInt& count = *(volatile TInt*)a;
215 test.Next(_L("Benchmark"));
218 TInt r = t4.Create(KNullDesC, &Thread4, 0x1000, 0x1000, 0x1000, &count);
220 t4.SetPriority(EPriorityLess);
221 r = t5.Create(KNullDesC, &Thread5, 0x1000, 0x1000, 0x1000, NULL);
223 t5.SetPriority(EPriorityMuchLess);
228 User::After(5000000);
230 test.Printf(_L("%d iterations per second\n"), (finalc-initc)/5);
237 void CreateThread2(RThread& aThread, SThreadData& aData, TThreadPriority aPri)
239 TInt r = aThread.Create(KNullDesC, &Thread2, 0x1000, 0x1000, 0x1000, &aData);
241 aThread.SetPriority(aPri);
243 aThread.Rendezvous(s);
244 test(s==KRequestPending);
246 User::WaitForRequest(s);
248 test(aThread.ExitType()==EExitPending);
252 void KillThread2(RThread& aThread)
256 test(s==KRequestPending);
257 aThread.Terminate(0);
258 User::WaitForRequest(s);
259 test(aThread.ExitType()==EExitTerminate);
260 test(aThread.ExitReason()==0);
262 CLOSE_AND_WAIT(aThread);
265 void AppendToArray(SThreadData& aD, TInt aCount, ...)
268 VA_START(list,aCount);
272 test(aD.iA->Append(VA_ARG(list,TInt))==KErrNone);
278 void AppendToArrayB(SThreadData& aD, TInt aCount, ...)
281 VA_START(list,aCount);
285 test(aD.iA->Append(VA_ARG(list,TInt))==KErrNone);
291 void AppendToArrayB2(SThreadData& aD, TInt aCount, ...)
294 VA_START(list,aCount);
298 test(aD.iA->Append(VA_ARG(list,TInt))==KErrNone);
306 test.Next(_L("Thread2Test"));
309 TInt r = cv2.CreateLocal();
311 r = m3.CreateLocal();
318 CreateThread2(t1, d1, EPriorityLess);
322 test(d1.iInnerLoops == 1);
325 CreateThread2(t1, d1, EPriorityLess);
328 test(d1.iInnerLoops == 1);
330 CreateThread2(t1, d1, EPriorityLess);
334 test(d1.iInnerLoops == 1);
336 CreateThread2(t1, d1, EPriorityLess);
341 test(d1.iInnerLoops == 1);
343 CreateThread2(t1, d1, EPriorityLess);
347 test(d1.iInnerLoops == 1);
349 CreateThread2(t1, d1, EPriorityLess);
354 test(d1.iInnerLoops == 1);
356 CreateThread2(t1, d1, EPriorityLess);
361 test(d1.iInnerLoops == 1);
363 CreateThread2(t1, d1, EPriorityLess);
369 test(d1.iInnerLoops == 1);
375 const TText* KMutex1Name = _S("mtx1");
376 const TText* KMutex2Name = _S("mtx2");
377 const TText* KCondVar1Name = _S("cv1");
378 const TText* KCondVar2Name = _S("cv2");
382 test.Next(_L("Test Global"));
385 TInt r = mg1.CreateGlobal(TPtrC(KMutex1Name));
387 r = mg2.CreateGlobal(TPtrC(KMutex2Name));
389 r = cvg1.CreateGlobal(TPtrC(KCondVar1Name));
391 r = cvg2.CreateGlobal(TPtrC(KCondVar2Name));
394 d1.iMutexName = KMutex1Name;
395 d1.iCondVarName = KCondVar1Name;
396 d2.iMutexName = KMutex2Name;
397 d2.iCondVarName = KCondVar2Name;
400 r = t1.Create(KNullDesC, &Thread3, 0x1000, 0x1000, 0x1000, &d1);
402 t1.SetPriority(EPriorityMore);
406 r = t2.Create(KNullDesC, &Thread3, 0x1000, 0x1000, 0x1000, &d2);
408 t2.SetPriority(EPriorityMore);
413 test(s1==KRequestPending);
414 test(s2==KRequestPending);
415 test(d1.iInnerLoops == 0);
416 test(d2.iInnerLoops == 0);
418 test(d1.iInnerLoops == 1);
419 test(d2.iInnerLoops == 0);
421 test(d1.iInnerLoops == 1);
422 test(d2.iInnerLoops == 1);
426 test(s1==KRequestPending);
427 test(s2==KRequestPending);
428 test(d1.iInnerLoops == 1);
429 test(d2.iInnerLoops == 1);
433 User::WaitForRequest(s1);
434 User::WaitForRequest(s2);
435 test(t1.ExitType()==EExitKill);
436 test(t1.ExitReason()==0);
437 test(t2.ExitType()==EExitKill);
438 test(t2.ExitReason()==0);
441 r = cvg1.OpenGlobal(TPtrC(KCondVar1Name));
442 test(r==KErrNotFound);
443 test(cvg1.Handle()==0);
448 void TestSecondaryProcess()
450 test.Next(_L("Test Secondary Process"));
457 //cancel lazy dll unloading
459 TInt r = loader.Connect();
461 r = loader.CancelLazyDllUnload();
465 r = c.CreateGlobal(KNullDesC, 0x1000, 0x1000);
467 volatile TInt& x = *(volatile TInt*)c.Base();
469 r = m.CreateGlobal(KNullDesC);
471 r = cv.CreateGlobal(KNullDesC);
473 r = p.Create(RProcess().FileName(), KNullDesC);
475 p.SetPriority(EPriorityHigh);
476 r = p.SetParameter(1, cv);
478 r = p.SetParameter(2, m);
480 r = p.SetParameter(3, c);
485 test(s==KRequestPending);
494 test(s==KRequestPending);
497 User::WaitForRequest(s);
498 test(p.ExitType()==EExitTerminate);
499 test(p.ExitReason()==0);
505 TInt SecondaryProcess(RCondVar aCV)
507 RDebug::Print(_L("SecProc"));
516 volatile TInt& x = *(volatile TInt*)cp.Base();
523 RDebug::Print(_L("SecProc r=%d x=%d"), r, x);
537 return SecondaryProcess(cvp);
539 test.Start(_L("Create condition variable"));
540 r = CV1.CreateLocal();
542 r = CV2.CreateLocal();
545 test.Next(_L("Signal with no-one waiting"));
548 test.Next(_L("Broadcast with no-one waiting"));
551 test.Next(_L("Create mutexes"));
552 r = M1.CreateLocal();
554 r = M2.CreateLocal();
562 test.Next(_L("Create thread to use mutex 2"));
564 r = t0.Create(KNullDesC, &Thread1, 0x1000, 0x1000, 0x1000, &d0);
566 t0.SetPriority(EPriorityMore);
571 AppendToArray(d0, 1, 4);
574 AppendToArray(d0, 2, -3, 17);
577 User::WaitForRequest(s0);
578 test(t0.ExitType()==EExitTerminate);
579 test(t0.ExitReason()==11);
587 test.Next(_L("Create thread to use mutex 1"));
589 r = t.Create(KNullDesC, &Thread1, 0x1000, 0x1000, 0x1000, &d);
591 t.SetPriority(EPriorityMore);
596 test.Next(_L("Test wait with mutex unlocked"));
597 r = t0.Create(KNullDesC, &Thread0, 0x1000, 0x1000, 0x1000, NULL);
599 t0.SetPriority(EPriorityMore);
601 TBool jit = User::JustInTime();
602 User::SetJustInTime(EFalse);
604 User::WaitForRequest(s0);
605 User::SetJustInTime(jit);
606 test(t0.ExitType()==EExitPanic);
607 test(t0.ExitCategory()==_L("KERN-EXEC"));
608 test(t0.ExitReason()==ECondVarWaitMutexNotLocked);
611 test.Next(_L("Test trying to use two mutexes with 1 condition variable"));
619 AppendToArray(d, 1, 3);
622 AppendToArray(d, 2, 3, 19);
625 AppendToArray(d, 4, 15, -1, -2, -30);
627 test(d.iInnerLoops==3);
628 test(d.iOuterLoops==3);
634 test(d.iInnerLoops==4);
635 test(d.iOuterLoops==3);
637 t.SetPriority(EPriorityLess);
639 test(d.iInnerLoops==4);
640 test(d.iOuterLoops==3);
642 t.SetPriority(EPriorityMore);
644 test(d.iInnerLoops==5);
645 test(d.iOuterLoops==3);
649 AppendToArray(d, 1, 4);
651 test(d.iInnerLoops==5);
652 test(d.iOuterLoops==3);
656 test(d.iInnerLoops==6);
657 test(d.iOuterLoops==4);
664 test.Next(_L("Create 2nd thread"));
666 r = t2.Create(KNullDesC, &Thread1, 0x1000, NULL, &d2);
668 t2.SetPriority(EPriorityMuchMore);
674 test(d2.iTotal == 11);
675 test(d2.iInnerLoops == 0);
676 test(d2.iOuterLoops == 1);
678 AppendToArray(d, 2, 9, 10);
679 test(d2.iTotal == 30);
680 test(d2.iInnerLoops == 1);
681 test(d2.iOuterLoops == 2);
683 test(d.iInnerLoops==6);
684 test(d.iOuterLoops==4);
686 AppendToArrayB(d, 2, 20, 30);
687 test(d2.iTotal == 80);
688 test(d2.iInnerLoops == 2);
689 test(d2.iOuterLoops == 3);
690 test(d.iTotal == 80);
691 test(d.iInnerLoops == 7);
692 test(d.iOuterLoops == 5);
694 AppendToArrayB2(d, 2, -10, -6);
695 test(d2.iTotal == 64);
696 test(d2.iInnerLoops == 3);
697 test(d2.iOuterLoops == 4);
698 test(d.iTotal == 64);
699 test(d.iInnerLoops == 8);
700 test(d.iOuterLoops == 6);
704 AppendToArray(d, 2, -8, -8);
705 test(d2.iTotal == 64);
706 test(d2.iInnerLoops == 3);
707 test(d2.iOuterLoops == 4);
708 test(d.iTotal == 48);
709 test(d.iInnerLoops == 9);
710 test(d.iOuterLoops == 7);
713 test(d2.iTotal == 48);
714 test(d2.iInnerLoops == 4);
715 test(d2.iOuterLoops == 5);
716 test(d.iTotal == 48);
717 test(d.iInnerLoops == 9);
718 test(d.iOuterLoops == 7);
726 test(d2.iTotal == 48);
727 test(d2.iInnerLoops == 4);
728 test(d2.iOuterLoops == 5);
729 test(d2.iTimeouts == 0);
730 test(d.iTotal == 48);
731 test(d.iInnerLoops == 10);
732 test(d.iOuterLoops == 7);
733 test(d.iTimeouts == 0);
734 test(array.Append(1)==0);
737 if (d.iTimeouts > nt)
739 test(d.iTimeouts-nt == 1);
741 test.Printf(_L("Timeout %d\n"), nt);
742 test(d2.iTotal == 48);
743 test(d2.iInnerLoops == 4);
744 test(d2.iOuterLoops == 5);
745 test(d2.iTimeouts == 0);
746 test(d.iTotal == 48+nt);
747 test(d.iInnerLoops == 10+nt);
748 test(d.iOuterLoops == 7+nt);
749 test(array.Append(1)==0);
754 AppendToArrayB(d, 0);
755 test(d2.iTotal == 59);
756 test(d2.iInnerLoops == 5);
757 test(d2.iOuterLoops == 6);
758 test(d2.iTimeouts == 0);
759 test(d.iTotal == 59);
760 test(d.iInnerLoops == 21);
761 test(d.iOuterLoops == 18);
762 test(d.iTimeouts == 10);
765 t.SetPriority(EPriorityLess);
767 AppendToArrayB(d, 1, 11);
768 test(d2.iTotal == 70);
769 test(d2.iInnerLoops == 6);
770 test(d2.iOuterLoops == 7);
771 test(d2.iTimeouts == 0);
772 test(d.iTotal == 59);
773 test(d.iInnerLoops == 21);
774 test(d.iOuterLoops == 18);
775 test(d.iTimeouts == 10);
777 test(d2.iTotal == 70);
778 test(d2.iInnerLoops == 6);
779 test(d2.iOuterLoops == 7);
780 test(d2.iTimeouts == 0);
781 test(d.iTotal == 70);
782 test(d.iInnerLoops == 22);
783 test(d.iOuterLoops == 19);
784 test(d.iTimeouts == 10);
790 User::WaitForRequest(s);
791 test(t.ExitType()==EExitKill);
792 test(t.ExitReason()==KErrGeneral);
793 User::WaitForRequest(s2);
794 test(t2.ExitType()==EExitKill);
795 test(t2.ExitReason()==KErrGeneral);
806 TestSecondaryProcess();