sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: sl@0: #include "bm_suite.h" sl@0: sl@0: class Thread : public BMProgram sl@0: { sl@0: public : sl@0: Thread() : BMProgram(_L("Threads")) sl@0: {} sl@0: virtual TBMResult* Run(TBMUInt64 aIter, TInt* aCount); sl@0: sl@0: typedef void (*MeasurementFunc)(TBMResult*, TBMUInt64 aIter); sl@0: struct Measurement sl@0: { sl@0: MeasurementFunc iFunc; sl@0: TPtrC iName; sl@0: sl@0: Measurement(MeasurementFunc aFunc, const TDesC& aName) : sl@0: iFunc(aFunc), iName(aName) {} sl@0: }; sl@0: sl@0: static TBMResult iResults[]; sl@0: static Measurement iMeasurements[]; sl@0: sl@0: static TBMTicks iChildTime; sl@0: sl@0: static void Creation(TBMResult*, TBMUInt64 aIter); sl@0: static TInt CreationChild(TAny*); sl@0: static void CreationSuicide(TBMResult*, TBMUInt64 aIter); sl@0: static TInt CreationSuicideChild(TAny*); sl@0: static void Suicide(TBMResult*, TBMUInt64 aIter); sl@0: static TInt SuicideChild(TAny*); sl@0: static void Killing(TBMResult*, TBMUInt64 aIter); sl@0: static TInt KillingChild(TAny*); sl@0: static void SetTls(TBMResult*, TBMUInt64 aIter); sl@0: static void GetTls(TBMResult*, TBMUInt64 aIter); sl@0: sl@0: void EnableCleanup() sl@0: { sl@0: TInt prio = BMProgram::SetAbsPriority(RThread(), iOrigAbsPriority); sl@0: BMProgram::SetAbsPriority(RThread(), prio); sl@0: } sl@0: }; sl@0: sl@0: Thread::Measurement Thread::iMeasurements[] = sl@0: { sl@0: Measurement(&Thread::Creation, _L("Thread Creation Latency")), sl@0: Measurement(&Thread::CreationSuicide, _L("Thread Creation Suicide")), sl@0: Measurement(&Thread::Suicide, _L("Thread Suicide")), sl@0: Measurement(&Thread::Killing, _L("Thread Killing")), sl@0: Measurement(&Thread::SetTls, _L("Setting per-thread data")), sl@0: Measurement(&Thread::GetTls, _L("Getting per-thread data")) sl@0: }; sl@0: TBMResult Thread::iResults[sizeof(Thread::iMeasurements)/sizeof(Thread::iMeasurements[0])]; sl@0: sl@0: TBMTicks Thread::iChildTime; sl@0: sl@0: static Thread prog; sl@0: sl@0: void Thread::Creation(TBMResult* aResult, TBMUInt64 aIter) sl@0: { sl@0: for (TBMUInt64 i = 0; i < aIter; ++i) sl@0: { sl@0: RThread child; sl@0: TRequestStatus st; sl@0: TBMTicks t1; sl@0: ::bmTimer.Stamp(&t1); sl@0: TInt r = child.Create(KNullDesC, Thread::CreationChild, 0x2000, NULL, NULL); sl@0: BM_ERROR(r, r == KErrNone); sl@0: child.Logon(st); sl@0: BMProgram::SetAbsPriority(RThread(), KBMPriorityHigh); sl@0: child.Resume(); sl@0: User::WaitForRequest(st); sl@0: BM_ERROR(st.Int(), st == KErrNone); sl@0: aResult->Cumulate(TBMTicksDelta(t1, iChildTime)); sl@0: CLOSE_AND_WAIT(child); sl@0: prog.EnableCleanup(); sl@0: } sl@0: } sl@0: sl@0: TInt Thread::CreationChild(TAny*) sl@0: { sl@0: ::bmTimer.Stamp(&iChildTime); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void Thread::CreationSuicide(TBMResult* aResult, TBMUInt64 aIter) sl@0: { sl@0: for (TBMUInt64 i = 0; i < aIter; ++i) sl@0: { sl@0: RThread child; sl@0: TRequestStatus st; sl@0: TBMTicks t1; sl@0: ::bmTimer.Stamp(&t1); sl@0: TInt r = child.Create(KNullDesC, Thread::CreationSuicideChild, 0x2000, NULL, NULL); sl@0: BM_ERROR(r, r == KErrNone); sl@0: child.Logon(st); sl@0: BMProgram::SetAbsPriority(RThread(), KBMPriorityLow); sl@0: child.Resume(); sl@0: User::WaitForRequest(st); sl@0: BM_ERROR(st.Int(), st == KErrNone); sl@0: TBMTicks t2; sl@0: ::bmTimer.Stamp(&t2); sl@0: aResult->Cumulate(TBMTicksDelta(t1, t2)); sl@0: CLOSE_AND_WAIT(child); sl@0: prog.EnableCleanup(); sl@0: } sl@0: } sl@0: sl@0: TInt Thread::CreationSuicideChild(TAny*) sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: void Thread::Suicide(TBMResult* aResult, TBMUInt64 aIter) sl@0: { sl@0: for (TBMUInt64 i = 0; i < aIter; ++i) sl@0: { sl@0: RThread child; sl@0: TRequestStatus st; sl@0: TInt r = child.Create(KNullDesC, Thread::SuicideChild, 0x2000, NULL, NULL); sl@0: BM_ERROR(r, r == KErrNone); sl@0: child.Logon(st); sl@0: BMProgram::SetAbsPriority(RThread(), KBMPriorityLow); sl@0: child.Resume(); sl@0: User::WaitForRequest(st); sl@0: BM_ERROR(st.Int(), st == KErrNone); sl@0: TBMTicks t2; sl@0: ::bmTimer.Stamp(&t2); sl@0: aResult->Cumulate(TBMTicksDelta(iChildTime, t2)); sl@0: CLOSE_AND_WAIT(child); sl@0: prog.EnableCleanup(); sl@0: } sl@0: } sl@0: sl@0: TInt Thread::SuicideChild(TAny*) sl@0: { sl@0: ::bmTimer.Stamp(&iChildTime); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void Thread::Killing(TBMResult* aResult, TBMUInt64 aIter) sl@0: { sl@0: for (TBMUInt64 i = 0; i < aIter; ++i) sl@0: { sl@0: RThread child; sl@0: TRequestStatus st; sl@0: TInt r = child.Create(KNullDesC, Thread::KillingChild, 0x2000, NULL, NULL); sl@0: BM_ERROR(r, r == KErrNone); sl@0: child.Logon(st); sl@0: BMProgram::SetAbsPriority(RThread(), KBMPriorityHigh); sl@0: child.Resume(); sl@0: TBMTicks t1; sl@0: ::bmTimer.Stamp(&t1); sl@0: child.Kill(KErrCancel); sl@0: User::WaitForRequest(st); sl@0: BM_ERROR(st.Int(), st == KErrCancel); sl@0: TBMTicks t2; sl@0: ::bmTimer.Stamp(&t2); sl@0: aResult->Cumulate(TBMTicksDelta(t1, t2)); sl@0: CLOSE_AND_WAIT(child); sl@0: prog.EnableCleanup(); sl@0: } sl@0: } sl@0: sl@0: TInt Thread::KillingChild(TAny*) sl@0: { sl@0: User::WaitForAnyRequest(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: #define TLS_KEY ((TInt32) &Thread::SetTls) sl@0: sl@0: void Thread::SetTls(TBMResult* aResult, TBMUInt64 aIter) sl@0: { sl@0: aIter <<= 4; sl@0: sl@0: TBMTimeInterval ti; sl@0: ti.Begin(); sl@0: for (TBMUInt64 i = 0; i < aIter; ++i) sl@0: { sl@0: TInt r = UserSvr::DllSetTls(TLS_KEY, 0); sl@0: BM_ERROR(r, r == KErrNone); sl@0: } sl@0: TBMTicks t = ti.End(); sl@0: aResult->Cumulate(t, aIter); sl@0: sl@0: UserSvr::DllFreeTls(TLS_KEY); sl@0: } sl@0: sl@0: void Thread::GetTls(TBMResult* aResult, TBMUInt64 aIter) sl@0: { sl@0: aIter <<= 4; sl@0: sl@0: TInt r = UserSvr::DllSetTls(TLS_KEY, 0); sl@0: BM_ERROR(r, r == KErrNone); sl@0: sl@0: TBMTimeInterval ti; sl@0: ti.Begin(); sl@0: for (TBMUInt64 i = 0; i < aIter; ++i) sl@0: { sl@0: UserSvr::DllTls(TLS_KEY); sl@0: } sl@0: TBMTicks t = ti.End(); sl@0: aResult->Cumulate(t, aIter); sl@0: sl@0: UserSvr::DllFreeTls(TLS_KEY); sl@0: } sl@0: sl@0: TBMResult* Thread::Run(TBMUInt64 aIter, TInt* aCount) sl@0: { sl@0: TInt count = sizeof(iResults)/sizeof(iResults[0]); sl@0: sl@0: for (TInt i = 0; i < count; ++i) sl@0: { sl@0: iResults[i].Reset(iMeasurements[i].iName); sl@0: iMeasurements[i].iFunc(&iResults[i], aIter); sl@0: iResults[i].Update(); sl@0: } sl@0: sl@0: *aCount = count; sl@0: return iResults; sl@0: } sl@0: sl@0: void AddThread() sl@0: { sl@0: BMProgram* next = bmSuite; sl@0: bmSuite=(BMProgram*)&prog; sl@0: bmSuite->Next()=next; sl@0: }