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_semutx.cpp
15 // Tests the RSemaphore, RMutex and RCriticalSection classes
17 // Tests the RSemaphore, RMutex and RCriticalSection classes
19 // RSemaphore, RMutex, RCriticalSection
21 // - Test RSemaphore and RMutex with the producer/consumer scenario.
22 // Create two threads, use signal and wait to coordinate the
23 // threads. Verify results are as expected.
24 // - Calculate the time required to create, resume and close a thread.
25 // - Test RSemaphore::Wait(timeout) in a variety ways and timeout
26 // values. Verify results are as expected.
27 // - Test RMutex via two threads which write to an array. The writing
28 // and updating of the index is wrapped within a mutex pair. Verify
29 // results are as expected.
30 // - Test RCriticalSection via two threads which write to an array. The
31 // writing and updating of the index is wrapped within a critical section
32 // pair. Verify results are as expected.
33 // Platforms/Drives/Compatibility:
35 // Assumptions/Requirement/Pre-requisites:
36 // Failures and causes:
37 // Base Port information:
43 const TInt KMaxBufferSize=10;
44 const TInt KMaxArraySize=10;
45 const TInt KNumProducerItems=100;
47 enum {EThread1ID=1,EThread2ID};
49 RTest test(_L("T_SEMUTX"));
51 RCriticalSection criticalSn;
52 TInt thread1Count,thread2Count;
54 TInt array[KMaxArraySize];
55 TInt consumerArray[KNumProducerItems];
56 RSemaphore slotAvailable,itemAvailable;
62 void Push(TInt aItem) {iStack[iCount++]=aItem;};
63 TInt Pop(void) {return(iStack[--iCount]);};
65 TInt iStack[KMaxBufferSize];
73 for(TInt ii=0;ii<KNumProducerItems;ii++)
79 itemAvailable.Signal();
87 for(TInt ii=0;ii<KNumProducerItems;ii++)
93 slotAvailable.Signal();
94 consumerArray[item]=item;
99 void BusyWait(TInt aMicroseconds)
107 TTimeIntervalMicroSeconds iv=now.MicroSecondsFrom(begin);
108 if (iv.Int64()>=TInt64(aMicroseconds))
113 TInt MutexThreadEntryPoint1(TAny*)
115 // Mutex test thread 1
125 if (arrayIndex<KMaxArraySize)
127 array[arrayIndex++]=EThread1ID;
137 TInt MutexThreadEntryPoint2(TAny*)
139 // Mutex test thread 2
149 if (arrayIndex<KMaxArraySize)
151 array[arrayIndex++]=EThread2ID;
161 TInt CriticalSnThreadEntryPoint1(TAny*)
163 // Critical Section test thread 1
173 if (arrayIndex<KMaxArraySize)
175 array[arrayIndex++]=EThread1ID;
185 TInt CriticalSnThreadEntryPoint2(TAny*)
187 // Critical Section test thread 2
197 if (arrayIndex<KMaxArraySize)
199 array[arrayIndex++]=EThread2ID;
215 TInt WaitSemThread(TAny* a)
217 SWaitSem& ws = *(SWaitSem*)a;
218 return ws.iSem.Wait(ws.iTimeout);
221 void StartWaitSemThread(RThread& aT, SWaitSem& aW, TThreadPriority aP=EPriorityLess)
223 TInt r = aT.Create(KNullDesC, &WaitSemThread, 0x1000, 0x1000, 0x1000, &aW);
229 void WaitForWaitSemThread(RThread& aT, TInt aResult)
233 User::WaitForRequest(s);
234 test(aT.ExitType()==EExitKill);
235 test(aT.ExitReason()==aResult);
236 test(s.Int()==aResult);
240 TInt DummyThread(TAny*)
245 void TestSemaphore2()
247 test.Start(_L("Test semaphore wait with timeout"));
253 TInt r = ws.iSem.CreateLocal(0);
256 RThread().SetPriority(EPriorityAbsoluteVeryLow);
259 while (elapsed<1000000)
261 r = t.Create(KNullDesC, &DummyThread, 0x1000, NULL, NULL);
263 t.SetPriority(EPriorityMore);
268 elapsed = I64INT(final.Int64()-initial.Int64());
270 RThread().SetPriority(EPriorityNormal);
271 test.Printf(_L("%d threads in 1 sec\n"),threadcount);
272 TInt overhead = 1000000/threadcount;
273 test.Printf(_L("overhead = %dus\n"),overhead);
277 StartWaitSemThread(t, ws);
278 WaitForWaitSemThread(t, KErrTimedOut);
280 elapsed = I64INT(final.Int64()-initial.Int64());
281 test.Printf(_L("Time taken = %dus\n"), elapsed);
282 test(elapsed>=900000+overhead && elapsed<1500000+overhead);
286 StartWaitSemThread(t, ws);
287 WaitForWaitSemThread(t, KErrArgument);
289 elapsed = I64INT(final.Int64()-initial.Int64());
290 test.Printf(_L("Time taken = %dus\n"), elapsed);
294 StartWaitSemThread(t, ws);
295 User::After(1000000);
297 WaitForWaitSemThread(t, KErrNone);
299 elapsed = I64INT(final.Int64()-initial.Int64());
300 test.Printf(_L("Time taken = %dus\n"), elapsed);
301 test(elapsed>=900000+overhead && elapsed<1500000+overhead);
304 StartWaitSemThread(t, ws, EPriorityMore);
309 WaitForWaitSemThread(t, KErrTimedOut);
310 test(ws.iSem.Wait(1)==KErrNone);
313 StartWaitSemThread(t, ws, EPriorityMore);
318 WaitForWaitSemThread(t, KErrNone);
319 test(ws.iSem.Wait(1)==KErrTimedOut);
323 StartWaitSemThread(t, ws, EPriorityMuchMore);
324 StartWaitSemThread(t2, ws, EPriorityMore);
327 test(t2.ExitType()==EExitKill);
328 test(t.ExitType()==EExitPending);
330 WaitForWaitSemThread(t, KErrTimedOut);
331 WaitForWaitSemThread(t2, KErrNone);
332 test(ws.iSem.Wait(1)==KErrTimedOut);
336 StartWaitSemThread(t2, ws, EPriorityMore);
337 StartWaitSemThread(t, ws, EPriorityMuchMore);
339 WaitForWaitSemThread(t, KErrNone);
341 elapsed = I64INT(final.Int64()-initial.Int64());
342 test.Printf(_L("Time taken = %dus\n"), elapsed);
343 WaitForWaitSemThread(t2, KErrTimedOut);
345 elapsed = I64INT(final.Int64()-initial.Int64());
346 test.Printf(_L("Time taken = %dus\n"), elapsed);
347 test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
351 StartWaitSemThread(t2, ws, EPriorityMore);
352 StartWaitSemThread(t, ws, EPriorityMuchMore);
353 WaitForWaitSemThread(t, KErrTimedOut);
355 elapsed = I64INT(final.Int64()-initial.Int64());
356 test.Printf(_L("Time taken = %dus\n"), elapsed);
357 WaitForWaitSemThread(t2, KErrTimedOut);
359 elapsed = I64INT(final.Int64()-initial.Int64());
360 test.Printf(_L("Time taken = %dus\n"), elapsed);
361 test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
365 StartWaitSemThread(t2, ws, EPriorityMore);
366 StartWaitSemThread(t, ws, EPriorityMuchMore);
368 WaitForWaitSemThread(t2, KErrTimedOut);
369 WaitForWaitSemThread(t, 299792458);
371 elapsed = I64INT(final.Int64()-initial.Int64());
372 test.Printf(_L("Time taken = %dus\n"), elapsed);
373 test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
377 StartWaitSemThread(t, ws, EPriorityMore);
378 StartWaitSemThread(t2, ws, EPriorityMuchMore);
379 test(t.ExitType()==EExitPending);
380 test(t2.ExitType()==EExitPending);
382 test(t.ExitType()==EExitKill);
383 test(t2.ExitType()==EExitKill);
384 WaitForWaitSemThread(t2, KErrGeneral);
385 WaitForWaitSemThread(t, KErrGeneral);
387 elapsed = I64INT(final.Int64()-initial.Int64());
388 test.Printf(_L("Time taken = %dus\n"), elapsed);
389 test(elapsed<=50000+3*overhead);
396 /*********** TO DO ************/
397 // Check it panics if the count <0
399 test.Start(_L("Create"));
400 RSemaphore semaphore;
401 RThread thread1, thread2;
403 semaphore.CreateLocal(0); // creates a DPlatSemaphore but casts it to a pointer to a DSemaphore
404 // sets semaphore count to the value of the parameter,
405 // adds object to the K::Semaphores container, sets iHandle
406 // Local sets DSemaphore.iName to NULL & iOwner to Kern::CurrentProcess()
407 // Global sets iName to that passed and iOwner to NULL
408 // Adds a record into CObjectIx containing a pointer to the semaphore object
409 /* test.Next(_L("Find"));
410 fullName=semaphore.FullName();
411 find.Find(fullName); // sets iMatch to fullName (misleadingly named method as it doesn't find anything)
412 test(find.Next(fullName)== KErrNone);
414 test.Next(_L("Producer/Consumer scenario"));
415 // Test Rsemaphore with the producer/consumer scenario RThread thread1, thread2;
416 TRequestStatus stat1, stat2;
417 test(mutex.CreateLocal()==KErrNone);
418 test(slotAvailable.CreateLocal(KMaxBufferSize)==KErrNone);
419 test(itemAvailable.CreateLocal(0)==KErrNone);
420 test(thread1.Create(_L("Thread1"),Producer,KDefaultStackSize,0x200,0x200,NULL)==KErrNone);
421 test(thread2.Create(_L("Thread2"),Consumer,KDefaultStackSize,0x200,0x200,NULL)==KErrNone);
422 thread1.Logon(stat1);
423 thread2.Logon(stat2);
424 test(stat1==KRequestPending);
425 test(stat2==KRequestPending);
428 User::WaitForRequest(stat1);
429 User::WaitForRequest(stat2);
430 test(stat1==KErrNone);
431 test(stat2==KErrNone);
432 for(TInt jj=0;jj<KNumProducerItems;jj++)
433 test(consumerArray[jj]==jj);
435 test.Next(_L("Close"));
437 CLOSE_AND_WAIT(thread1);
438 CLOSE_AND_WAIT(thread2);
445 test.Start(_L("Create"));
446 test(m.CreateLocal()==KErrNone);
448 // Test RMutex::IsHeld()
449 test.Next(_L("IsHeld ?"));
451 test.Next(_L("Wait"));
453 test.Next(_L("IsHeld ?"));
455 test.Next(_L("Signal"));
457 test.Next(_L("IsHeld ?"));
465 test.Start(_L("Create"));
466 test(mutex.CreateLocal()==KErrNone);
468 test.Next(_L("Threads writing to arrays test"));
470 // Create two threads which write to two arrays. The arrays and indexs
471 // are global and each thread writes an identifier to the arrays. For
472 // one array the writing and updating of the index is wrapped in a mutex
473 // pair. The other array is a control and is not wrapaped within mutex.
474 // Each thread records the number of instances it "thinks" it wrote to
475 // each array. For the mutex controlled array the actual instances
476 // written to the array should always be the same as the threads think.
479 RThread thread1,thread2;
480 test(thread1.Create(_L("Thread1"),MutexThreadEntryPoint1,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);
481 test(thread2.Create(_L("Thread2"),MutexThreadEntryPoint2,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);
482 TRequestStatus stat1,stat2;
483 thread1.Logon(stat1);
484 thread2.Logon(stat2);
485 test(stat1==KRequestPending);
486 test(stat2==KRequestPending);
489 User::WaitForRequest(stat1);
490 User::WaitForRequest(stat2);
491 test(stat1==KErrNone);
492 test(stat2==KErrNone);
493 TInt thread1ActualCount=0;
494 TInt thread2ActualCount=0;
496 while(ii<KMaxArraySize)
498 if (array[ii]==EThread1ID)
499 thread1ActualCount++;
500 if (array[ii]==EThread2ID)
501 thread2ActualCount++;
504 test.Printf(_L("T1 %d T1ACT %d T2 %d T2ACT %d"),thread1Count,thread1ActualCount,thread2Count,thread2ActualCount);
505 test(thread1ActualCount==thread1Count);
506 test(thread2ActualCount==thread2Count);
507 test(thread1Count==thread2Count);
508 test(thread1Count==(KMaxArraySize>>1));
510 test.Next(_L("Close"));
511 CLOSE_AND_WAIT(thread1);
512 CLOSE_AND_WAIT(thread2);
517 void TestCriticalSection()
519 //As TestMutex, but for RCriticalSection
523 test.Start(_L("Create"));
524 test(criticalSn.CreateLocal()==KErrNone);
526 /***************** TO DO ***********************
528 test.Next(_L("Find"));
530 // Test finding the RCriticalSection
532 TFindCriticalSection find;
534 fullName=criticalSn.FullName();
536 test(find.Next(fullName)==KErrNone);
537 test(fullName==criticalSn.FullName());
539 ************************************************/
541 test.Next(_L("Threads writing to arrays test"));
543 // Create two threads which write to two arrays. The arrays and indexs
544 // are global and each thread writes an identifier to the arrays. For
545 // one array the writing and updating of the index is wrapped in a critical
546 // section pair. The other array is a control and is not wrapaped within
547 // a critical section. Each thread records the number of instances it
548 // "thinks" it wrote to each array. For the mutex controlled array the
549 // actual instances written to the array should always be the same as the
553 RThread thread1,thread2;
554 test(thread1.Create(_L("Thread1"),CriticalSnThreadEntryPoint1,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);
555 test(thread2.Create(_L("Thread2"),CriticalSnThreadEntryPoint2,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);
556 TRequestStatus stat1,stat2;
557 thread1.Logon(stat1);
558 thread2.Logon(stat2);
559 test(stat1==KRequestPending);
560 test(stat2==KRequestPending);
563 User::WaitForRequest(stat1);
564 User::WaitForRequest(stat2);
565 test(stat1==KErrNone);
566 test(stat2==KErrNone);
567 TInt thread1ActualCount=0;
568 TInt thread2ActualCount=0;
570 while(ii<KMaxArraySize)
572 if (array[ii]==EThread1ID)
573 thread1ActualCount++;
574 if (array[ii]==EThread2ID)
575 thread2ActualCount++;
578 test(thread1ActualCount==thread1Count);
579 test(thread2ActualCount==thread2Count);
580 test(thread1Count==thread2Count);
581 test(thread1Count==(KMaxArraySize>>1));
583 test.Next(_L("Close"));
584 CLOSE_AND_WAIT(thread1);
585 CLOSE_AND_WAIT(thread2);
591 GLDEF_C TInt E32Main()
596 test.Start(_L("Test RSemaphore"));
599 test.Next(_L("Test RMutex"));
602 test.Next(_L("Test RCriticalSection"));
603 TestCriticalSection();