diff -r 000000000000 -r a41df078684a kerneltest/e32test/prime/t_semutx.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/prime/t_semutx.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,609 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\prime\t_semutx.cpp +// Tests the RSemaphore, RMutex and RCriticalSection classes +// Overview: +// Tests the RSemaphore, RMutex and RCriticalSection classes +// API Information: +// RSemaphore, RMutex, RCriticalSection +// Details: +// - Test RSemaphore and RMutex with the producer/consumer scenario. +// Create two threads, use signal and wait to coordinate the +// threads. Verify results are as expected. +// - Calculate the time required to create, resume and close a thread. +// - Test RSemaphore::Wait(timeout) in a variety ways and timeout +// values. Verify results are as expected. +// - Test RMutex via two threads which write to an array. The writing +// and updating of the index is wrapped within a mutex pair. Verify +// results are as expected. +// - Test RCriticalSection via two threads which write to an array. The +// writing and updating of the index is wrapped within a critical section +// pair. Verify results are as expected. +// Platforms/Drives/Compatibility: +// All. +// Assumptions/Requirement/Pre-requisites: +// Failures and causes: +// Base Port information: +// +// + +#include + +const TInt KMaxBufferSize=10; +const TInt KMaxArraySize=10; +const TInt KNumProducerItems=100; + +enum {EThread1ID=1,EThread2ID}; + +RTest test(_L("T_SEMUTX")); +RMutex mutex; +RCriticalSection criticalSn; +TInt thread1Count,thread2Count; +TInt arrayIndex; +TInt array[KMaxArraySize]; +TInt consumerArray[KNumProducerItems]; +RSemaphore slotAvailable,itemAvailable; + +class CStack + { +public: + CStack() {iCount=0;}; + void Push(TInt aItem) {iStack[iCount++]=aItem;}; + TInt Pop(void) {return(iStack[--iCount]);}; +private: + TInt iStack[KMaxBufferSize]; + TInt iCount; + }; +CStack stack; + + +TInt Producer(TAny*) + { + for(TInt ii=0;ii=TInt64(aMicroseconds)) + return; + } + } + +TInt MutexThreadEntryPoint1(TAny*) +// +// Mutex test thread 1 +// + { + + thread1Count=0; + TBool running=ETrue; + do + { + mutex.Wait(); + BusyWait(100000); + if (arrayIndex=900000+overhead && elapsed<1500000+overhead); + + ws.iTimeout=-1; + initial.HomeTime(); + StartWaitSemThread(t, ws); + WaitForWaitSemThread(t, KErrArgument); + final.HomeTime(); + elapsed = I64INT(final.Int64()-initial.Int64()); + test.Printf(_L("Time taken = %dus\n"), elapsed); + + ws.iTimeout=2000000; + initial.HomeTime(); + StartWaitSemThread(t, ws); + User::After(1000000); + ws.iSem.Signal(); + WaitForWaitSemThread(t, KErrNone); + final.HomeTime(); + elapsed = I64INT(final.Int64()-initial.Int64()); + test.Printf(_L("Time taken = %dus\n"), elapsed); + test(elapsed>=900000+overhead && elapsed<1500000+overhead); + + ws.iTimeout=100000; + StartWaitSemThread(t, ws, EPriorityMore); + t.Suspend(); + ws.iSem.Signal(); + User::After(200000); + t.Resume(); + WaitForWaitSemThread(t, KErrTimedOut); + test(ws.iSem.Wait(1)==KErrNone); + + ws.iTimeout=100000; + StartWaitSemThread(t, ws, EPriorityMore); + t.Suspend(); + ws.iSem.Signal(); + User::After(50000); + t.Resume(); + WaitForWaitSemThread(t, KErrNone); + test(ws.iSem.Wait(1)==KErrTimedOut); + + RThread t2; + ws.iTimeout=100000; + StartWaitSemThread(t, ws, EPriorityMuchMore); + StartWaitSemThread(t2, ws, EPriorityMore); + t.Suspend(); + ws.iSem.Signal(); + test(t2.ExitType()==EExitKill); + test(t.ExitType()==EExitPending); + t.Resume(); + WaitForWaitSemThread(t, KErrTimedOut); + WaitForWaitSemThread(t2, KErrNone); + test(ws.iSem.Wait(1)==KErrTimedOut); + + ws.iTimeout=1000000; + initial.HomeTime(); + StartWaitSemThread(t2, ws, EPriorityMore); + StartWaitSemThread(t, ws, EPriorityMuchMore); + ws.iSem.Signal(); + WaitForWaitSemThread(t, KErrNone); + final.HomeTime(); + elapsed = I64INT(final.Int64()-initial.Int64()); + test.Printf(_L("Time taken = %dus\n"), elapsed); + WaitForWaitSemThread(t2, KErrTimedOut); + final.HomeTime(); + elapsed = I64INT(final.Int64()-initial.Int64()); + test.Printf(_L("Time taken = %dus\n"), elapsed); + test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead); + + ws.iTimeout=1000000; + initial.HomeTime(); + StartWaitSemThread(t2, ws, EPriorityMore); + StartWaitSemThread(t, ws, EPriorityMuchMore); + WaitForWaitSemThread(t, KErrTimedOut); + final.HomeTime(); + elapsed = I64INT(final.Int64()-initial.Int64()); + test.Printf(_L("Time taken = %dus\n"), elapsed); + WaitForWaitSemThread(t2, KErrTimedOut); + final.HomeTime(); + elapsed = I64INT(final.Int64()-initial.Int64()); + test.Printf(_L("Time taken = %dus\n"), elapsed); + test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead); + + ws.iTimeout=1000000; + initial.HomeTime(); + StartWaitSemThread(t2, ws, EPriorityMore); + StartWaitSemThread(t, ws, EPriorityMuchMore); + t.Kill(299792458); + WaitForWaitSemThread(t2, KErrTimedOut); + WaitForWaitSemThread(t, 299792458); + final.HomeTime(); + elapsed = I64INT(final.Int64()-initial.Int64()); + test.Printf(_L("Time taken = %dus\n"), elapsed); + test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead); + + ws.iTimeout=1000000; + initial.HomeTime(); + StartWaitSemThread(t, ws, EPriorityMore); + StartWaitSemThread(t2, ws, EPriorityMuchMore); + test(t.ExitType()==EExitPending); + test(t2.ExitType()==EExitPending); + ws.iSem.Close(); + test(t.ExitType()==EExitKill); + test(t2.ExitType()==EExitKill); + WaitForWaitSemThread(t2, KErrGeneral); + WaitForWaitSemThread(t, KErrGeneral); + final.HomeTime(); + elapsed = I64INT(final.Int64()-initial.Int64()); + test.Printf(_L("Time taken = %dus\n"), elapsed); + test(elapsed<=50000+3*overhead); + + test.End(); + } + +void TestSemaphore() + { +/*********** TO DO ************/ +// Check it panics if the count <0 + + test.Start(_L("Create")); + RSemaphore semaphore; + RThread thread1, thread2; + + semaphore.CreateLocal(0); // creates a DPlatSemaphore but casts it to a pointer to a DSemaphore + // sets semaphore count to the value of the parameter, + // adds object to the K::Semaphores container, sets iHandle + // Local sets DSemaphore.iName to NULL & iOwner to Kern::CurrentProcess() + // Global sets iName to that passed and iOwner to NULL + // Adds a record into CObjectIx containing a pointer to the semaphore object +/* test.Next(_L("Find")); + fullName=semaphore.FullName(); + find.Find(fullName); // sets iMatch to fullName (misleadingly named method as it doesn't find anything) + test(find.Next(fullName)== KErrNone); +*/ + test.Next(_L("Producer/Consumer scenario")); + // Test Rsemaphore with the producer/consumer scenario RThread thread1, thread2; + TRequestStatus stat1, stat2; + test(mutex.CreateLocal()==KErrNone); + test(slotAvailable.CreateLocal(KMaxBufferSize)==KErrNone); + test(itemAvailable.CreateLocal(0)==KErrNone); + test(thread1.Create(_L("Thread1"),Producer,KDefaultStackSize,0x200,0x200,NULL)==KErrNone); + test(thread2.Create(_L("Thread2"),Consumer,KDefaultStackSize,0x200,0x200,NULL)==KErrNone); + thread1.Logon(stat1); + thread2.Logon(stat2); + test(stat1==KRequestPending); + test(stat2==KRequestPending); + thread1.Resume(); + thread2.Resume(); + User::WaitForRequest(stat1); + User::WaitForRequest(stat2); + test(stat1==KErrNone); + test(stat2==KErrNone); + for(TInt jj=0;jj>1)); + + test.Next(_L("Close")); + CLOSE_AND_WAIT(thread1); + CLOSE_AND_WAIT(thread2); + mutex.Close(); + test.End(); + } + +void TestCriticalSection() +// +//As TestMutex, but for RCriticalSection +// + { + + test.Start(_L("Create")); + test(criticalSn.CreateLocal()==KErrNone); + +/***************** TO DO *********************** + + test.Next(_L("Find")); +// +// Test finding the RCriticalSection +// + TFindCriticalSection find; + TFullName fullName; + fullName=criticalSn.FullName(); + find.Find(fullName); + test(find.Next(fullName)==KErrNone); + test(fullName==criticalSn.FullName()); + +************************************************/ + + test.Next(_L("Threads writing to arrays test")); +// +// Create two threads which write to two arrays. The arrays and indexs +// are global and each thread writes an identifier to the arrays. For +// one array the writing and updating of the index is wrapped in a critical +// section pair. The other array is a control and is not wrapaped within +// a critical section. Each thread records the number of instances it +// "thinks" it wrote to each array. For the mutex controlled array the +// actual instances written to the array should always be the same as the +// threads think. +// + arrayIndex=0; + RThread thread1,thread2; + test(thread1.Create(_L("Thread1"),CriticalSnThreadEntryPoint1,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone); + test(thread2.Create(_L("Thread2"),CriticalSnThreadEntryPoint2,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone); + TRequestStatus stat1,stat2; + thread1.Logon(stat1); + thread2.Logon(stat2); + test(stat1==KRequestPending); + test(stat2==KRequestPending); + thread1.Resume(); + thread2.Resume(); + User::WaitForRequest(stat1); + User::WaitForRequest(stat2); + test(stat1==KErrNone); + test(stat2==KErrNone); + TInt thread1ActualCount=0; + TInt thread2ActualCount=0; + TInt ii=0; + while(ii>1)); + + test.Next(_L("Close")); + CLOSE_AND_WAIT(thread1); + CLOSE_AND_WAIT(thread2); + criticalSn.Close(); + test.End(); + } + + +GLDEF_C TInt E32Main() + { + + test.Title(); + __UHEAP_MARK; + test.Start(_L("Test RSemaphore")); + TestSemaphore(); + TestSemaphore2(); + test.Next(_L("Test RMutex")); + TestMutex(); + TestMutex2(); + test.Next(_L("Test RCriticalSection")); + TestCriticalSection(); + test.End(); + __UHEAP_MARKEND; + return(KErrNone); + } + +