diff -r c1f20ce4abcf -r 3e88ff8f41d5 kerneltest/e32test/prime/t_semutx.cpp --- a/kerneltest/e32test/prime/t_semutx.cpp Tue Aug 31 16:34:26 2010 +0300 +++ b/kerneltest/e32test/prime/t_semutx.cpp Wed Sep 01 12:34:56 2010 +0100 @@ -40,9 +40,7 @@ #define __E32TEST_EXTENSION__ #include -#include -#include -#include +#include #include const TInt KMaxBufferSize=10; @@ -53,352 +51,13 @@ RTest test(_L("T_SEMUTX")); RMutex mutex; -RCriticalSection criticalSn; +RCriticalSection criticalSn; TInt thread1Count,thread2Count; TInt arrayIndex; -TInt array[KMaxArraySize]; +TInt array[KMaxArraySize]; TInt consumerArray[KNumProducerItems]; -RSemaphore slotAvailable,itemAvailable; -TBool doCpuLocking = EFalse; - -// return num of cpus in system -TInt NumCpus() - { - TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0); - return r; - } - - -TInt LockCurrentThreadToCpu0(TBool aCallingIsMainTestThread = EFalse) - { - if (aCallingIsMainTestThread) - { - if (NumCpus() > 1) - { - doCpuLocking = ETrue; - return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, 0, 0); - } - else - { - return KErrNone; - } - } - return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, 0, 0); - } - -TInt UnlockCurrentThreadToCpu0(TBool aCallingIsMainTestThread = EFalse) - { - if (aCallingIsMainTestThread) - { - if (NumCpus() > 1) - { - doCpuLocking = EFalse; - return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*) 0xffffffffu, 0); - } - else - { - return KErrNone; - } - } - return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*) 0xffffffffu, 0); - } - - -/****************************************************************************** - * Random Number Generation - ******************************************************************************/ -void Random(TUint64& a) - { - TInt i; - for (i=64; i>0; --i) - { - TUint64 x = a<<1; - TUint64 y = x<<1; - x^=y; - a = (y>>1) | (x>>63); - } - } - -// Returns 256*log2(a/2^64) -TInt Log2(TUint64 a) - { - const TUint64 KBit63 = UI64LIT(0x8000000000000000); - TInt n = __e32_find_ms1_64(a); - a <<= (63-n); - n -= 64; - TInt i; - for (i=0; i<8; ++i) - { - a >>= 32; - a *= a; - n <<= 1; - if (a & KBit63) - { - ++n; - } - else - { - a <<= 1; - } - } - return n; - } - -TUint32 ExpRV(TUint64 aU, TUint32 aMean, TUint32 aTick) - { - TInt n = -Log2(aU); - TUint64 x = TUint64(n) * TUint64(aMean); - x *= TUint64(22713); // 2^15 * ln2 - TUint64 p(aTick); - p <<= 22; - x += p; - p += p; - x /= p; - return I64LOW(x); - } - - - -/*----------------------------------------------------------------------------*/ -class MLock - { -public: - enum {EPollable=1, ETimeoutAvail=2, ENestable=4, ELimit1=8, ELooseTimeout=16}; -public: - virtual TInt Flags()=0; - virtual void Release()=0; - virtual void Wait()=0; - virtual void Signal()=0; - virtual TInt Wait(TInt aTimeout); - virtual TInt Poll(); - }; - -TInt MLock::Wait(TInt) - { return KErrNotSupported; } -TInt MLock::Poll() - { return KErrNotSupported; } - -/*----------------------------------------------------------------------------*/ -class LockS : public MLock - { -public: - LockS(); - virtual TInt Flags(); - virtual void Release(); - virtual void Wait(); - virtual void Signal(); - virtual TInt Wait(TInt aTimeout); - virtual TInt Poll(); -public: - RSemaphore iT; - }; - -LockS::LockS() - { test_KErrNone(iT.CreateLocal(1)); } -TInt LockS::Flags() - { return EPollable|ETimeoutAvail; } -void LockS::Release() - { iT.Close(); } -void LockS::Wait() - { iT.Wait(); } -void LockS::Signal() - { iT.Signal(); } -TInt LockS::Wait(TInt aTimeout) - { return iT.Wait(aTimeout); } -TInt LockS::Poll() - { return iT.Poll(); } - -/*----------------------------------------------------------------------------*/ -class LockM : public MLock - { -public: - LockM(); - virtual TInt Flags(); - virtual void Release(); - virtual void Wait(); - virtual void Signal(); - virtual TInt Wait(TInt aTimeout); - virtual TInt Poll(); -public: - RMutex iT; - }; - -LockM::LockM() - { test_KErrNone(iT.CreateLocal()); } -TInt LockM::Flags() - { return EPollable|ETimeoutAvail|ENestable|ELimit1; } -void LockM::Release() - { iT.Close(); } -void LockM::Wait() - { iT.Wait(); } -void LockM::Signal() - { iT.Signal(); } -TInt LockM::Wait(TInt aTimeout) - { return iT.Wait(aTimeout); } -TInt LockM::Poll() - { return iT.Poll(); } - -/*----------------------------------------------------------------------------*/ - -class LockFL : public MLock - { -public: - LockFL(); - virtual TInt Flags(); - virtual void Release(); - virtual void Wait(); - virtual void Signal(); - virtual TInt Wait(TInt aTimeout); - virtual TInt Poll(); -public: - RFastLock iT; - }; - -LockFL::LockFL() - { test_KErrNone(iT.CreateLocal()); } -TInt LockFL::Flags() - { return ETimeoutAvail|EPollable|ELimit1|ELooseTimeout; } -void LockFL::Release() - { iT.Close(); } -void LockFL::Wait() - { iT.Wait(); } -void LockFL::Signal() - { iT.Signal(); } -TInt LockFL::Wait(TInt aTimeout) - { return iT.Wait(aTimeout); } -TInt LockFL::Poll() - { return iT.Poll(); } - -/*----------------------------------------------------------------------------*/ -class LockCS : public MLock - { -public: - LockCS(); - virtual TInt Flags(); - virtual void Release(); - virtual void Wait(); - virtual void Signal(); -public: - RCriticalSection iT; - }; - -LockCS::LockCS() - { test_KErrNone(iT.CreateLocal()); } -TInt LockCS::Flags() - { return ELimit1; } -void LockCS::Release() - { iT.Close(); } -void LockCS::Wait() - { iT.Wait(); } -void LockCS::Signal() - { iT.Signal(); } - - +RSemaphore slotAvailable,itemAvailable; -/*----------------------------------------------------------------------------*/ -class LFSR - { -public: - LFSR(TInt aBits, TInt aTap2, TInt aTap3=0, TInt aTap4=0); - ~LFSR(); - void Step(); - void Step(TInt aSteps); - TBool operator==(const LFSR& a) const; -public: - TUint32* iData; - TInt iBits; - TInt iTap2; - TInt iTap3; - TInt iTap4; - TInt iNW; - TInt iSh1; - TInt iIx2; - TInt iSh2; - TInt iIx3; - TInt iSh3; - TInt iIx4; - TInt iSh4; - }; - -LFSR::LFSR(TInt aBits, TInt aTap2, TInt aTap3, TInt aTap4) - { - iBits = aBits; - iTap2 = aTap2; - iTap3 = aTap3; - iTap4 = aTap4; - iNW = (aBits + 31) >> 5; - iData = (TUint32*)User::AllocZ(iNW*sizeof(TUint32)); - test(iData!=0); - iData[0] = 1; - iSh1 = (aBits-1)&31; - iIx2 = (iTap2-1)>>5; - iSh2 = (iTap2-1)&31; - if (iTap3) - { - iIx3 = (iTap3-1)>>5; - iSh3 = (iTap3-1)&31; - } - else - { - iIx3 = -1; - iSh3 = 0; - } - if (iTap4) - { - iIx4 = (iTap4-1)>>5; - iSh4 = (iTap4-1)&31; - } - else - { - iIx4 = -1; - iSh4 = 0; - } - } - -LFSR::~LFSR() - { - User::Free(iData); - } - -void LFSR::Step(TInt aSteps) - { - while (aSteps--) - Step(); - } - -void LFSR::Step() - { - TUint32 b = iData[iNW-1]>>iSh1; - b ^= (iData[iIx2]>>iSh2); - if (iIx3>=0) - b ^= (iData[iIx3]>>iSh3); - if (iIx4>=0) - b ^= (iData[iIx4]>>iSh4); - b &= 1; - TInt i; - for (i=0; i> 31; - iData[i] = (iData[i]<<1)|b; - b = bb; - } - iData[iNW-1] &= ((2u< 1) - { - // when the mutex is singaled, due to priority balancing, the other - // thread will be scheduled to run on a CPU other than this one. The delay - // in getting that thread to run means that this one can manage to re-claim the - // mutex before the other thread gets to run. So we add a small delay here - User::After(100); - } - } while (running); return(KErrNone); } @@ -494,7 +142,6 @@ // Mutex test thread 2 // { - TInt n = NumCpus(); thread2Count=0; TBool running=ETrue; @@ -510,17 +157,6 @@ else running=EFalse; mutex.Signal(); - - if (n > 1) - { - // when the mutex is singaled, due to priority balancing, the other - // thread will be scheduled to run on a CPU other than this one. The delay - // in getting that thread to run means that this one can manage to re-claim the - // mutex before the other thread gets to run. So we add a small delay here - User::After(100); - } - - } while (running); return(KErrNone); } @@ -573,80 +209,27 @@ return(KErrNone); } - -/*----------------------------------------------------------------------------*/ -struct SWaitLock +struct SWaitSem { - enum {EDummy=-2, EPoll=-1, EInfinite=0}; - - static TInt WaitLockThread(TAny*); - void Start(RThread& aT, TThreadPriority aP=EPriorityLess); - void Wait(RThread& aT, TInt aResult); - TInt DoTest2(RThread& aT, TInt aTimeout, TInt aResult, TThreadPriority aP=EPriorityLess); - void Test2(); - void TestSignalled(); - void TestNotSignalled(); - void TestState(); - - - MLock* iLock; + RSemaphore iSem; TInt iTimeout; }; -TInt SWaitLock::WaitLockThread(TAny* a) +TInt WaitSemThread(TAny* a) { - - if (doCpuLocking) - { - TInt r = LockCurrentThreadToCpu0(); - if (KErrNone!=r) return r; - // Rendevous was requested - RThread::Rendezvous(KErrNone); - } - - SWaitLock& w = *(SWaitLock*)a; - TInt lfl = w.iLock->Flags(); - TBool limit1 = lfl & MLock::ELimit1; - TInt r; - switch (w.iTimeout) - { - case EDummy: - return KErrNone; - case EPoll: - r = w.iLock->Poll(); - break; - case EInfinite: - w.iLock->Wait(); - r = KErrNone; - break; - default: - r = w.iLock->Wait(w.iTimeout); - break; - } - if (limit1 && r==KErrNone) - w.iLock->Signal(); - return r; + SWaitSem& ws = *(SWaitSem*)a; + return ws.iSem.Wait(ws.iTimeout); } -void SWaitLock::Start(RThread& aT, TThreadPriority aP) +void StartWaitSemThread(RThread& aT, SWaitSem& aW, TThreadPriority aP=EPriorityLess) { - TRequestStatus st; - TInt r = aT.Create(KNullDesC, &WaitLockThread, 0x1000, 0x1000, 0x1000, this); + TInt r = aT.Create(KNullDesC, &WaitSemThread, 0x1000, 0x1000, 0x1000, &aW); test_KErrNone(r); aT.SetPriority(aP); - if (doCpuLocking) - { - aT.Rendezvous(st); - } aT.Resume(); - if (doCpuLocking) - { - User::WaitForRequest(st); - test_KErrNone(st.Int()); - } } -void SWaitLock::Wait(RThread& aT, TInt aResult) +void WaitForWaitSemThread(RThread& aT, TInt aResult) { TRequestStatus s; aT.Logon(s); @@ -657,67 +240,32 @@ CLOSE_AND_WAIT(aT); } -TInt SWaitLock::DoTest2(RThread& aT, TInt aTimeout, TInt aResult, TThreadPriority aP) +TInt DummyThread(TAny*) { - TTime initial; - TTime final; - iTimeout = aTimeout; - initial.HomeTime(); - Start(aT, aP); - Wait(aT, aResult); - final.HomeTime(); - TInt elapsed = I64INT(final.Int64()-initial.Int64()); - return elapsed; - } - -void SWaitLock::TestSignalled() - { - TInt r = iLock->Poll(); - if (r == KErrNotSupported) - r = iLock->Wait(1); - test_KErrNone(r); + return 0; } -void SWaitLock::TestNotSignalled() - { - TInt r = iLock->Poll(); - if (r == KErrNotSupported) - r = iLock->Wait(1); - test_Equal(KErrTimedOut, r); - } - -void SWaitLock::TestState() +void TestSemaphore2() { - if (iLock->Flags() & MLock::ELimit1) - TestSignalled(); // not signalled afterwards - else - TestNotSignalled(); - } - -void SWaitLock::Test2() - { - test.Start(_L("SWaitLock::Test2")); + test.Start(_L("Test semaphore wait with timeout")); + SWaitSem ws; RThread t; - RThread t2; TTime initial; TTime final; - TInt elapsed = 0; - TInt r = 0; - TInt lfl = iLock->Flags(); - TBool nestable = lfl & MLock::ENestable; - TBool limit1 = lfl & MLock::ELimit1; - TBool pollable = lfl & MLock::EPollable; - TBool to = lfl & MLock::ETimeoutAvail; - TBool lto = lfl & MLock::ELooseTimeout; + TInt elapsed=0; + TInt r = ws.iSem.CreateLocal(0); + test_KErrNone(r); RThread().SetPriority(EPriorityAbsoluteVeryLow); TInt threadcount=0; - iTimeout = EDummy; initial.HomeTime(); while (elapsed<1000000) { - Start(t, EPriorityMore); - Wait(t, KErrNone); + r = t.Create(KNullDesC, &DummyThread, 0x1000, NULL, NULL); + test_KErrNone(r); + t.SetPriority(EPriorityMore); + t.Resume(); + t.Close(); ++threadcount; final.HomeTime(); elapsed = I64INT(final.Int64()-initial.Int64()); @@ -727,735 +275,125 @@ TInt overhead = 1000000/threadcount; test.Printf(_L("overhead = %dus\n"),overhead); - iLock->Wait(); + ws.iTimeout=1000000; + initial.HomeTime(); + StartWaitSemThread(t, ws); + WaitForWaitSemThread(t, KErrTimedOut); + final.HomeTime(); + elapsed = I64INT(final.Int64()-initial.Int64()); + test.Printf(_L("Time taken = %dus\n"), elapsed); + test(elapsed>=900000+overhead && elapsed<1500000+overhead); - if (to) - { - elapsed = DoTest2(t, 1000000, KErrTimedOut); - test.Printf(_L("Time taken = %dus\n"), elapsed); - test(elapsed>=900000+overhead && elapsed<1500000+overhead); - elapsed = DoTest2(t, -99, KErrArgument); - test.Printf(_L("Time taken = %dus\n"), elapsed); - } + 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); - if (pollable) - { - test.Printf(_L("Testing Poll() function\n")); - r = iLock->Poll(); - test_Equal((nestable ? KErrNone : KErrTimedOut), r); - if (nestable) - { - iTimeout=EPoll; - r = iLock->Poll(); - test_KErrNone(r); - iLock->Signal(); - Start(t, EPriorityMore); - Wait(t, KErrTimedOut); - } - iLock->Signal(); - if (nestable) - { - iTimeout=EPoll; - r = iLock->Poll(); - test_KErrNone(r); - iLock->Signal(); - Start(t, EPriorityMore); - Wait(t, KErrTimedOut); - iLock->Signal(); - Start(t, EPriorityMore); - Wait(t, KErrNone); - } - r = iLock->Poll(); - test_KErrNone(r); - if (!nestable) - { - r = iLock->Poll(); - test_Equal(KErrTimedOut, r); - iLock->Signal(); - if (!limit1) - { - iLock->Signal(); - r = iLock->Poll(); - test_KErrNone(r); - } - r = iLock->Poll(); - test_KErrNone(r); - r = iLock->Poll(); - test_Equal(KErrTimedOut, r); - } - elapsed = DoTest2(t, EPoll, KErrTimedOut); - test.Printf(_L("Time taken = %dus\n"), elapsed); - test(elapsed<=50000+3*overhead); - iLock->Signal(); - elapsed = DoTest2(t, EPoll, KErrNone); - test.Printf(_L("Time taken = %dus\n"), elapsed); - test(elapsed<=50000+3*overhead); - TestState(); - iLock->Signal(); - r = LockCurrentThreadToCpu0(ETrue); - test_KErrNone(r); - Start(t, EPriorityMuchMore); - Start(t2, EPriorityMore); - test_Equal(EExitKill, t2.ExitType()); - test_Equal(EExitKill, t.ExitType()); - Wait(t2, limit1 ? KErrNone : KErrTimedOut); - Wait(t, KErrNone); - r = UnlockCurrentThreadToCpu0(ETrue); - test_KErrNone(r); - TestState(); - } - else - { - test.Printf(_L("Poll() function not supported\n")); - } + 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); - if (to) - { - iTimeout=2000000; - initial.HomeTime(); - Start(t); - User::After(1000000); - iLock->Signal(); - Wait(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); - TestState(); + ws.iTimeout=100000; + StartWaitSemThread(t, ws, EPriorityMore); + t.Suspend(); + ws.iSem.Signal(); + User::After(200000); + t.Resume(); + WaitForWaitSemThread(t, KErrTimedOut); + test_KErrNone(ws.iSem.Wait(1)); - r = LockCurrentThreadToCpu0(ETrue); - test_KErrNone(r); + ws.iTimeout=100000; + StartWaitSemThread(t, ws, EPriorityMore); + t.Suspend(); + ws.iSem.Signal(); + User::After(50000); + t.Resume(); + WaitForWaitSemThread(t, KErrNone); + test_Equal(KErrTimedOut, ws.iSem.Wait(1)); - if (!lto) - { - iTimeout=100000; - Start(t, EPriorityMore); - t.Suspend(); - iLock->Signal(); - User::After(200000); - t.Resume(); - Wait(t, KErrTimedOut); - TestSignalled(); + RThread t2; + ws.iTimeout=100000; + StartWaitSemThread(t, ws, EPriorityMuchMore); + StartWaitSemThread(t2, ws, EPriorityMore); + t.Suspend(); + ws.iSem.Signal(); + test_Equal(EExitKill, t2.ExitType()); + test_Equal(EExitPending, t.ExitType()); + t.Resume(); + WaitForWaitSemThread(t, KErrTimedOut); + WaitForWaitSemThread(t2, KErrNone); + test_Equal(KErrTimedOut, ws.iSem.Wait(1)); - iTimeout=100000; - Start(t, EPriorityMore); - t.Suspend(); - iLock->Signal(); - User::After(50000); - t.Resume(); - Wait(t, KErrNone); - TestState(); - - iTimeout=100000; - Start(t, EPriorityMuchMore); - Start(t2, EPriorityMore); - t.Suspend(); - iLock->Signal(); - test_Equal(EExitKill, t2.ExitType()); - test_Equal(EExitPending, t.ExitType()); - t.Resume(); - Wait(t, limit1 ? KErrNone : KErrTimedOut); - Wait(t2, KErrNone); - TestState(); - } + 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); - iTimeout=1000000; - initial.HomeTime(); - Start(t2, EPriorityMore); - Start(t, EPriorityMuchMore); - iLock->Signal(); - Wait(t, KErrNone); - final.HomeTime(); - elapsed = I64INT(final.Int64()-initial.Int64()); - test.Printf(_L("Time taken = %dus\n"), elapsed); - Wait(t2, limit1 ? KErrNone : KErrTimedOut); - final.HomeTime(); - elapsed = I64INT(final.Int64()-initial.Int64()); - test.Printf(_L("Time taken = %dus\n"), elapsed); - if (!limit1) - { - test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead); - } - TestState(); - - iTimeout=1000000; - initial.HomeTime(); - Start(t2, EPriorityMore); - Start(t, EPriorityMuchMore); - Wait(t, KErrTimedOut); - final.HomeTime(); - elapsed = I64INT(final.Int64()-initial.Int64()); - test.Printf(_L("Time taken = %dus\n"), elapsed); - Wait(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); - iTimeout=1000000; - initial.HomeTime(); - Start(t2, EPriorityMore); - Start(t, EPriorityMuchMore); - t.Kill(299792458); - Wait(t2, KErrTimedOut); - Wait(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(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); - iTimeout=1000000; - initial.HomeTime(); - Start(t, EPriorityMore); - Start(t2, EPriorityMuchMore); - test_Equal(EExitPending, t.ExitType()); - test_Equal(EExitPending, t2.ExitType()); - iLock->Release(); - test_Equal(EExitKill, t.ExitType()); - test_Equal(EExitKill, t2.ExitType()); - Wait(t2, KErrGeneral); - Wait(t, KErrGeneral); - final.HomeTime(); - elapsed = I64INT(final.Int64()-initial.Int64()); - test.Printf(_L("Time taken = %dus\n"), elapsed); - test(elapsed<=50000+3*overhead); - r = UnlockCurrentThreadToCpu0(ETrue); - test_KErrNone(r); - } - else - { - test.Printf(_L("Timed waits not supported\n")); - iLock->Release(); - } + ws.iTimeout=1000000; + initial.HomeTime(); + StartWaitSemThread(t, ws, EPriorityMore); + StartWaitSemThread(t2, ws, EPriorityMuchMore); + test_Equal(EExitPending, t.ExitType()); + test_Equal(EExitPending, t2.ExitType()); + ws.iSem.Close(); + test_Equal(EExitKill, t.ExitType()); + test_Equal(EExitKill, t2.ExitType()); + 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(); } -volatile TBool NoRepeat = EFalse; -void TestPollTimeout() - { - SWaitLock w; - do { - test.Printf(_L("TestPollTimeout - RSemaphore\n")); - LockS ls; - w.iLock = &ls; - w.Test2(); // Release()s ls - } while(NoRepeat); - do { - test.Printf(_L("TestPollTimeout - RMutex\n")); - LockM lm; - w.iLock = &lm; - w.Test2(); // Release()s lm - } while(NoRepeat); - do { - test.Printf(_L("TestPollTimeout - RFastLock\n")); - LockFL fl; - w.iLock = &fl; - w.Test2(); // Release()s fl - } while(NoRepeat); - } - - -/*----------------------------------------------------------------------------*/ -class CMXThreadGrp; - -struct SStats - { - SStats(); - void Add(TInt aValue); - void Add(const SStats& aS); - TInt Count() const {return iN;} - TInt Min() const; - TInt Max() const; - TInt Mean() const; - - TInt64 iSum; - TInt iMin; - TInt iMax; - TInt iN; - TInt iSp; - }; - -SStats::SStats() - { - iSum = 0; - iMax = KMinTInt; - iMin = ~iMax; - iN = 0; - iSp = 0; - } - -void SStats::Add(TInt aValue) - { - TInt64 v = aValue; - iSum += v; - ++iN; - if (aValue > iMax) - iMax = aValue; - if (aValue < iMin) - iMin = aValue; - } - -void SStats::Add(const SStats& a) - { - iN += a.iN; - iSum += a.iSum; - if (a.iMax > iMax) - iMax = a.iMax; - if (a.iMin < iMin) - iMin = a.iMin; - } - -TInt SStats::Min() const - {return iN ? iMin : 0;} - -TInt SStats::Max() const - {return iN ? iMax : 0;} - -TInt SStats::Mean() const - { - if (iN==0) - return 0; - return (TInt)(iSum/TInt64(iN)); - } - -TUint32 ticks_to_us(TUint32 aTicks, TUint32 aF) - { - TUint64 x = aTicks; - TUint64 f = aF; - x *= TUint64(1000000); - x += (f>>1); - x /= f; - return I64LOW(x); - } - -class CMXThread : public CBase - { -private: - CMXThread(); - ~CMXThread(); - static CMXThread* New(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD); - void Start(); - void Wait(); - TInt Construct(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD); - TInt Steps(); - TInt Action(); - TInt Run(); - static TInt ThreadFunc(TAny*); - void PrintStats(); -private: - TUint64 iSeed; - RThread iThread; - TRequestStatus iExitStatus; - CMXThreadGrp* iG; - LFSR* iDummyLfsr; - TUint32 iId; - TUint32 iLambda; - TUint32 iDummySteps; - TInt iTotalSteps; - TInt iIterations; - TInt iPolls; - TInt iPollFails; - SStats iStats; - SStats iTimeoutStats; -private: - friend class CMXThreadGrp; - }; - -class CMXThreadGrp : public CBase - { -public: - static CMXThreadGrp* New(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime); - CMXThreadGrp(); - ~CMXThreadGrp(); - TBool Run(); - void PrintStats(); -private: - TInt Construct(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime); -private: - TInt iNThreads; - CMXThread** iThreads; - MLock* iLock; - LFSR* iLfsr; - LFSR* iLfsr0; - TUint32 iNTickPeriod; - TUint32 iFCF; - TUint32 iNTicks; - TInt iTotalSteps; - TInt iIterations; - TInt iPolls; - TInt iPollFails; - SStats iStats; - SStats iTimeoutStats; -private: - friend class CMXThread; - }; - -CMXThread::CMXThread() - { - iThread.SetHandle(0); - } - -CMXThread::~CMXThread() - { - delete iDummyLfsr; - if (iThread.Handle()) - { - if (iThread.ExitType() == EExitPending) - { - iThread.Kill(0); - Wait(); - } - CLOSE_AND_WAIT(iThread); - } - } - -void CMXThread::PrintStats() - { - test.Printf(_L("Thread %d:\n"), iId); - test.Printf(_L(" ST:%10d IT:%10d P:%10d PF:%10d TO:%10d\n"), iTotalSteps, iIterations, iPolls, iPollFails, iTimeoutStats.Count()); - TUint32 min, max, mean; - min = ticks_to_us(iStats.Min(), iG->iFCF); - max = ticks_to_us(iStats.Max(), iG->iFCF); - mean = ticks_to_us(iStats.Mean(), iG->iFCF); - test.Printf(_L(" Lock acquire times MIN %10d MAX %10d AVG %10d\n"), min, max, mean); - min = ticks_to_us(iTimeoutStats.Min(), iG->iFCF); - max = ticks_to_us(iTimeoutStats.Max(), iG->iFCF); - mean = ticks_to_us(iTimeoutStats.Mean(), iG->iFCF); - test.Printf(_L(" Lock timeout times MIN %10d MAX %10d AVG %10d\n"), min, max, mean); - } - -TInt CMXThread::Construct(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD) - { - iG = aG; - iId = aId; - iLambda = aL; - iDummySteps = aD; - iSeed = iId + 1; - iDummyLfsr = new LFSR(785,693); - if (!iDummyLfsr) - return KErrNoMemory; - TBuf<16> name = _L("TSThrd"); - name.AppendNum(iId); - TInt r = iThread.Create(name, &ThreadFunc, 0x1000, NULL, this); - if (r!=KErrNone) - return r; - iThread.Logon(iExitStatus); - if (iExitStatus != KRequestPending) - { - iThread.Kill(0); - iThread.Close(); - iThread.SetHandle(0); - return iExitStatus.Int(); - } - iThread.SetPriority(EPriorityLess); - return KErrNone; - } - -CMXThread* CMXThread::New(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD) - { - CMXThread* p = new CMXThread; - if (p) - { - TInt r = p->Construct(aG, aId, aL, aD); - if (r != KErrNone) - { - delete p; - p = 0; - } - } - return p; - } - -void CMXThread::Start() - { - iThread.Resume(); - } - -void CMXThread::Wait() - { - User::WaitForRequest(iExitStatus); - } - -TInt CMXThread::ThreadFunc(TAny* aPtr) - { - CMXThread& a = *(CMXThread*)aPtr; - return a.Run(); - } - -TInt CMXThread::Steps() - { - Random(iSeed); - return ExpRV(iSeed, iLambda, 1); - } - -TInt CMXThread::Action() - { - Random(iSeed); - return I64LOW(iSeed)%3; - } - -TInt CMXThread::Run() - { - MLock* lock = iG->iLock; - LFSR* lfsr = iG->iLfsr; - TInt lfl = lock->Flags(); - TBool pollable = lfl & MLock::EPollable; - TBool to = lfl & MLock::ETimeoutAvail; - TUint32 start_time = User::NTickCount(); - TInt r; - - FOREVER - { - TUint32 now = User::NTickCount(); - if (now - start_time >= iG->iNTicks) - break; - ++iIterations; - iDummyLfsr->Step(iDummySteps); - TInt action = Action(); - TInt steps = Steps(); - TUint32 initial = User::FastCounter(); - if (action==2 && to) - { - r = lock->Wait(1000); - if (r!=KErrNone) - { - TUint32 final = User::FastCounter(); - TInt elapsed = TInt(final - initial); - iTimeoutStats.Add(elapsed); - } - } - else if (action==1 && pollable) - { - ++iPolls; - r = lock->Poll(); - if (r!=KErrNone) - ++iPollFails; - } - else - { - lock->Wait(); - r = KErrNone; - } - if (r == KErrNone) - { - TUint32 final = User::FastCounter(); - lfsr->Step(steps); - lock->Signal(); - TInt elapsed = TInt(final - initial); - iTotalSteps += steps; - iStats.Add(elapsed); - } - } - - return KErrNone; - } - -CMXThreadGrp* CMXThreadGrp::New(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime) - { - CMXThreadGrp* p = new CMXThreadGrp; - if (p) - { - TInt r = p->Construct(aLock, aNThreads, aLambda, aDummySteps, aTime); - if (r != KErrNone) - { - delete p; - p = 0; - } - } - return p; - } - -CMXThreadGrp::CMXThreadGrp() - { - } - -TInt CMXThreadGrp::Construct(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime) - { - iNThreads = aNThreads; - iLock = aLock; - TInt r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)iFCF); - if (r!=KErrNone) - return r; - r = HAL::Get(HAL::ENanoTickPeriod, (TInt&)iNTickPeriod); - if (r!=KErrNone) - return r; - iNTicks = (aTime+iNTickPeriod-1)/iNTickPeriod; - iLfsr = new LFSR(785,693); - iLfsr0 = new LFSR(785,693); - if (!iLfsr || !iLfsr0) - return KErrNoMemory; - iThreads = (CMXThread**)User::AllocZ(iNThreads*sizeof(CMXThread*)); - if (!iThreads) - return KErrNoMemory; - TInt i; - for (i=0; iiLambda, iThreads[0]->iDummySteps, iNTicks); - for (i=0; iStart(); - for (i=0; iWait(); - for (i=0; iiTotalSteps; - iIterations += iThreads[i]->iIterations; - iPolls += iThreads[i]->iPolls; - iPollFails += iThreads[i]->iPollFails; - iStats.Add(iThreads[i]->iStats); - iTimeoutStats.Add(iThreads[i]->iTimeoutStats); - } - test.Printf(_L("Total LFSR steps %d\n"), iTotalSteps); - iLfsr0->Step(iTotalSteps); - TBool ok = (*iLfsr == *iLfsr0); - return ok; - } - -void CMXThreadGrp::PrintStats() - { - TInt i; - for (i=0; iPrintStats(); - } - test.Printf(_L("TOTALS:\n")); - test.Printf(_L(" ST:%10d IT:%10d P:%10d PF:%10d TO:%10d\n"), iTotalSteps, iIterations, iPolls, iPollFails, iTimeoutStats.Count()); - TUint32 min, max, mean; - min = ticks_to_us(iStats.Min(), iFCF); - max = ticks_to_us(iStats.Max(), iFCF); - mean = ticks_to_us(iStats.Mean(), iFCF); - test.Printf(_L(" Lock acquire times MIN %10d MAX %10d AVG %10d\n"), min, max, mean); - min = ticks_to_us(iTimeoutStats.Min(), iFCF); - max = ticks_to_us(iTimeoutStats.Max(), iFCF); - mean = ticks_to_us(iTimeoutStats.Mean(), iFCF); - test.Printf(_L(" Lock timeout times MIN %10d MAX %10d AVG %10d\n"), min, max, mean); - } - -TUint32 Calibrate() - { - TUint32 fcf; - TInt r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)fcf); - test_KErrNone(r); - LFSR* d = new LFSR(785,693); - test(d!=0); - TInt steps = 2; - TUint32 ticks = fcf/10; - TUint32 elapsed; - FOREVER - { - TUint32 h0 = User::FastCounter(); - d->Step(steps); - TUint32 h1 = User::FastCounter(); - elapsed = h1 - h0; - if (elapsed > ticks) - break; - steps *= 2; - } - delete d; - test.Printf(_L("%d steps in %d fast ticks\n"), steps, elapsed); - TUint64 x = elapsed; - TUint64 s = steps; - TUint64 y = fcf; - y /= x; - s *= y; // steps per second - TUint32 res = I64LOW(s); - test.Printf(_L("%d steps per second\n"), res); - return res; - } - -void DoTMX(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime, TBool aShouldFail=EFalse) - { - CMXThreadGrp* g = CMXThreadGrp::New(aLock, aNThreads, aLambda, aDummySteps, aTime); - test(g!=0); - TBool ok = g->Run(); - if (aShouldFail) - { - test(!ok); - } - else - { - test(ok); - } - g->PrintStats(); - delete g; - } - -void DoTMX(MLock* aLock, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime) - { - TInt n; - for (n=1; n<=4; ++n) - { - TUint32 l = (n<2) ? aLambda : (aLambda/(n-1)); - DoTMX(aLock, n, l, aDummySteps, aTime); - } - aLock->Release(); - } - - -void TestMutualExclusion() - { - TInt ntp; - TInt r = HAL::Get(HAL::ENanoTickPeriod, ntp); - test_KErrNone(r); - test.Printf(_L("Nanokernel tick period = %dus\n"), ntp); - TUint32 sps = Calibrate(); - TUint32 lambda = sps/2000; - TUint32 dummy = sps/2000; - TUint32 time = 5000000; - do { - test.Printf(_L("TestMutualExclusion - RSemaphore\n")); - LockS ls; - DoTMX(&ls, lambda, dummy, time); - } while(NoRepeat); - do { - test.Printf(_L("TestMutualExclusion - RSemaphore init=2\n")); - LockS ls2; - ls2.Signal(); // count=2 - DoTMX(&ls2, 4, lambda, dummy, time, ETrue); - } while(NoRepeat); - do { - test.Printf(_L("TestMutualExclusion - RMutex\n")); - LockM lm; - DoTMX(&lm, lambda, dummy, time); - } while(NoRepeat); - do { - test.Printf(_L("TestMutualExclusion - RFastLock\n")); - LockFL fl; - DoTMX(&fl, lambda, dummy, time); - } while(NoRepeat); - do { - test.Printf(_L("TestMutualExclusion - RCriticalSection\n")); - LockCS cs; - DoTMX(&cs, lambda, dummy, time); - } while(NoRepeat); - } - - - - -/*----------------------------------------------------------------------------*/ void TestSemaphore() { /*********** TO DO ************/ @@ -1479,23 +417,23 @@ 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); + test_KErrNone(mutex.CreateLocal()); + test_KErrNone(slotAvailable.CreateLocal(KMaxBufferSize)); + test_KErrNone(itemAvailable.CreateLocal(0)); + test_KErrNone(thread1.Create(_L("Thread1"),Producer,KDefaultStackSize,0x200,0x200,NULL)); + test_KErrNone(thread2.Create(_L("Thread2"),Consumer,KDefaultStackSize,0x200,0x200,NULL)); thread1.Logon(stat1); thread2.Logon(stat2); - test(stat1==KRequestPending); - test(stat2==KRequestPending); + test_Equal(KRequestPending, stat1.Int()); + test_Equal(KRequestPending, stat2.Int()); thread1.Resume(); thread2.Resume(); User::WaitForRequest(stat1); User::WaitForRequest(stat2); - test(stat1==KErrNone); - test(stat2==KErrNone); + test_KErrNone(stat1.Int()); + test_KErrNone(stat2.Int()); for(TInt jj=0;jj>1)); + test.Printf(_L("T1 %d T1ACT %d T2 %d T2ACT %d"),thread1Count,thread1ActualCount,thread2Count,thread2ActualCount); + test_Equal(thread1Count, thread1ActualCount); + test_Equal(thread2Count, thread2ActualCount); + test_Equal(thread2Count, thread1Count); + test_Equal((KMaxArraySize>>1), thread1Count); test.Next(_L("Close")); CLOSE_AND_WAIT(thread1); @@ -1586,7 +524,7 @@ { test.Start(_L("Create")); - test(criticalSn.CreateLocal()==KErrNone); + test_KErrNone(criticalSn.CreateLocal()); /***************** TO DO *********************** @@ -1615,21 +553,20 @@ // 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); + test_KErrNone(thread1.Create(_L("Thread1"),CriticalSnThreadEntryPoint1,KDefaultStackSize,0x2000,0x2000,NULL)); + test_KErrNone(thread2.Create(_L("Thread2"),CriticalSnThreadEntryPoint2,KDefaultStackSize,0x2000,0x2000,NULL)); TRequestStatus stat1,stat2; thread1.Logon(stat1); thread2.Logon(stat2); - test(stat1==KRequestPending); - test(stat2==KRequestPending); + test_Equal(KRequestPending, stat1.Int()); + test_Equal(KRequestPending, stat2.Int()); thread1.Resume(); thread2.Resume(); User::WaitForRequest(stat1); User::WaitForRequest(stat2); - test(stat1==KErrNone); - test(stat2==KErrNone); + test_KErrNone(stat1.Int()); + test_KErrNone(stat2.Int()); TInt thread1ActualCount=0; TInt thread2ActualCount=0; TInt ii=0; @@ -1641,10 +578,10 @@ thread2ActualCount++; ii++; } - test(thread1ActualCount==thread1Count); - test(thread2ActualCount==thread2Count); - test(thread1Count==thread2Count); - test(thread1Count==(KMaxArraySize>>1)); + test_Equal(thread1Count, thread1ActualCount); + test_Equal(thread2Count, thread2ActualCount); + test_Equal(thread2Count, thread1Count); + test_Equal((KMaxArraySize>>1), thread1Count); test.Next(_L("Close")); CLOSE_AND_WAIT(thread1); @@ -1656,13 +593,22 @@ GLDEF_C TInt E32Main() { + TInt cpus = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0); + if (cpus != 1) + { + test(cpus>1); + // This test will require compatibility mode (and probably other changes) + // to work on SMP - it depends on explicit scheduling order. + test.Printf(_L("T_SEMUTX skipped, does not work on SMP\n")); + return KErrNone; + } + test.Title(); __UHEAP_MARK; - TestMutualExclusion(); - TestPollTimeout(); test.Start(_L("Test RSemaphore")); TestSemaphore(); + TestSemaphore2(); test.Next(_L("Test RMutex")); TestMutex(); TestMutex2();