--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/power/t_frqchg.cpp Tue Aug 31 16:34:26 2010 +0300
@@ -0,0 +1,775 @@
+// Copyright (c) 2010-2010 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\power\t_frqchg.cpp
+//
+//
+
+#define __E32TEST_EXTENSION__
+#include <e32test.h>
+#include <e32math.h>
+#include <e32atomics.h>
+#include <hal.h>
+#include "d_frqchg.h"
+#include <e32svr.h>
+#include "u32std.h"
+
+RFrqChg Driver;
+RTest test(_L("T_FRQCHG"));
+
+// test will fail if slice is > (expected+KSliceDeltaPercent%of expexted)
+// or < (expected-KSliceDeltaPercent%expected)
+const TInt KSliceDeltaPercent = 5;
+// test will fail for global timer based timestamps if interval measured
+// is > (expected+KTimeStampDeltaPercent%of expexted)
+// or < (expected-KTimeStampDeltaPercent%expected)
+const TInt KTimeStampDeltaPercent = 5;
+
+TInt RealToRatio(SRatio& aRatio, const TRealX& aReal)
+ {
+ aRatio.iSpare1 = 0;
+ aRatio.iSpare2 = 0;
+ if (aReal.iSign || aReal.IsZero() || aReal.IsNaN())
+ {
+ aRatio.iM = 0;
+ aRatio.iX = 0;
+ return (aReal.IsZero()) ? KErrNone : KErrNotSupported;
+ }
+ TRealX rx(aReal);
+ TRealX rr(rx);
+ rr.iExp -= 32;
+ rr.iMantLo = 0;
+ rr.iMantHi = 0x80000000u;
+ rx += rr; // rounding
+ TInt exp = rx.iExp - 32767 - 31;
+ if (exp < -32768)
+ {
+ aRatio.iM = 0;
+ aRatio.iX = 0;
+ return KErrUnderflow;
+ }
+ if (exp > 32767)
+ {
+ aRatio.iM = 0xffffffffu;
+ aRatio.iX = 32767;
+ return KErrOverflow;
+ }
+ aRatio.iM = rx.iMantHi;
+ aRatio.iX = (TInt16)exp;
+ return KErrNone;
+ }
+
+TInt RatioToReal(TRealX& a, const SRatio& aRatio)
+ {
+ a.iSign = 0;
+ a.iFlag = 0;
+ a.iMantLo = 0;
+ a.iMantHi = aRatio.iM;
+ if (!aRatio.iM)
+ {
+ a.SetZero();
+ return KErrNone;
+ }
+ TInt exp = aRatio.iX + 31 + 32767;
+ if (exp > 65534)
+ {
+ a.SetInfinite(EFalse);
+ }
+ else
+ {
+ a.iExp = (TUint16)exp;
+ }
+ return KErrNone;
+ }
+
+TInt RatioSetValue(TRealX& a, TUint32 aInt, TInt aDivisorExp)
+ {
+ a.Set(TUint(aInt));
+ TInt exp = a.iExp;
+ exp -= aDivisorExp;
+ if (exp<1)
+ {
+ a.SetZero();
+ return KErrUnderflow;
+ }
+ if (exp>65534)
+ {
+ a.SetInfinite(EFalse);
+ return KErrOverflow;
+ }
+ a.iExp = (TInt16)exp;
+ return KErrNone;
+ }
+
+TInt RatioReciprocal(SRatio& aRatio)
+ {
+ TRealX rx;
+ TInt r = RatioToReal(rx, aRatio);
+ if (r != KErrNone)
+ return r;
+ rx = TRealX(1) / rx;
+ return RealToRatio(aRatio, rx);
+ }
+
+TInt RatioMult(const SRatio& aRatio, TUint32& aInt32)
+ {
+ TRealX rx;
+ TInt r = RatioToReal(rx, aRatio);
+ if (r != KErrNone)
+ return r;
+ r = rx.MultEq(TRealX((TUint)aInt32));
+ if (r != KErrNone)
+ return r;
+ if (rx.IsZero())
+ {
+ aInt32 = 0;
+ return KErrNone;
+ }
+ rx.AddEq(TRealX(0.5));
+ if (rx<TRealX(1))
+ {
+ aInt32 = 0;
+ return KErrUnderflow;
+ }
+ if (rx.iExp > 32767+31)
+ {
+ aInt32 = ~0u;
+ return KErrOverflow;
+ }
+ aInt32 = rx.operator TUint();
+ return KErrNone;
+ }
+
+void RatioPrint(const char* aTitle, const SRatio& aRatio)
+ {
+ TPtrC8 t8((const TUint8*)aTitle);
+ TBuf<256> t16;
+ t16.Copy(t8);
+ test.Printf(_L("%S: %08x %04x\n"), &t16, aRatio.iM, TUint16(aRatio.iX));
+ }
+
+void RatioPrint2(const char* aTitle, const SRatio& aR1, const SRatio& aR2)
+ {
+ TPtrC8 t8((const TUint8*)aTitle);
+ TBuf<256> t16;
+ t16.Copy(t8);
+ test.Printf(_L("%S: %08x %04x %08x %04x\n"), &t16, aR1.iM, TUint16(aR1.iX), aR2.iM, TUint16(aR2.iX));
+ }
+
+void TestEqual(const SRatio& aActual, const SRatio& aExpected)
+ {
+ if (aActual.iM==aExpected.iM && aActual.iX==aExpected.iX)
+ return;
+ RatioPrint("Actual", aActual);
+ RatioPrint("Expected", aExpected);
+ test(0);
+ }
+
+const TUint32 MultTestIntegers[] =
+ {
+ 0u, 1u, 2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u, 37u, 41u, 43u, 47u,
+ 50u, 51u, 53u, 59u, 61u, 63u, 67u, 71u, 72u, 81u, 100u, 127u, 133u, 187u, 200u,
+ 4u, 8u, 16u, 32u, 64u, 128u, 256u, 512u, 1024u, 2048u, 4096u, 8192u, 16384u,
+ 32768u, 65536u, 131072u, 262144u, 524288u, 1048576u, 2097152u, 4194304u, 8388608u,
+ 16777216u, 33554432u, 67108864u, 134217728u, 268435456u, 536870912u, 1073741824u,
+ 2147483648u, 4294967295u,
+ 9u, 27u, 243u, 729u, 2187u, 6561u, 19683u, 59049u, 177147u, 531441u, 1594323u,
+ 4782969u, 14348907u, 43046721u, 129140163u, 387420489u, 1162261467u, 3486784401u,
+ 25u, 125u, 625u, 3125u, 15625u, 78125u, 390625u, 1953125u, 9765625u,
+ 48828125u, 244140625u, 1220703125u,
+ 49u, 343u, 2401u, 16807u, 117649u, 823543u, 5764801u, 40353607u, 282475249u, 1977326743u
+ };
+
+void Test1M(const SRatio& aRatio)
+ {
+ SRatio ratio = aRatio;
+ const TInt N = sizeof(MultTestIntegers)/sizeof(MultTestIntegers[0]);
+ test.Printf(_L("Testing %d integers\n"), N);
+ TInt i;
+ for (i=0; i<N; ++i)
+ {
+ TUint32 I = MultTestIntegers[i];
+ TUint32 I0 = I;
+ TUint32 I1 = I;
+ TInt r0 = RatioMult(aRatio, I0);
+ TInt r1 = Driver.RatioMult(ratio, I1);
+ if (r0!=KErrNone || r1!=KErrNone)
+ {
+ if (r0!=r1)
+ {
+ test.Printf(_L("Return code mismatch r0=%d r1=%d (I=%08x I0=%08x I1=%08x)\n"), r0, r1, I, I0, I1);
+ test(0);
+ }
+ }
+ else if (I0!=I1)
+ {
+ test.Printf(_L("Result mismatch I=%08x I0=%08x I1=%08x\n"), I, I0, I1);
+ }
+ }
+ }
+
+void Test1(TUint32 aInt, TInt aDivisorExp)
+ {
+ TRealX realx;
+ SRatio r0x;
+ SRatio r0;
+ SRatio r1x;
+ SRatio r1;
+ TInt r;
+ test.Printf(_L("Test1 %08x %d\n"), aInt, aDivisorExp);
+ r = RatioSetValue(realx, aInt, aDivisorExp);
+ test_KErrNone(r);
+ r = RealToRatio(r0x, realx);
+ test_KErrNone(r);
+ r = Driver.RatioSet(r0, aInt, aDivisorExp);
+ RatioPrint2("R0X,R0", r0x, r0);
+ TestEqual(r0, r0x);
+ Test1M(r0);
+ r1x = r0x;
+ r = RatioReciprocal(r1x);
+ test_KErrNone(r);
+ r1 = r0;
+ r = Driver.RatioReciprocal(r1);
+ test_KErrNone(r);
+ RatioPrint2("R1X,R1", r1x, r1);
+ TestEqual(r1, r1x);
+ Test1M(r1);
+ }
+
+void TestRatios()
+ {
+ Test1(1,0);
+ Test1(3,0);
+ Test1(0xb504f334u,32);
+ Test1(0xc90fdaa2u,30);
+ Test1(10,0);
+ Test1(0xcccccccd,35);
+ Test1(100,0);
+ Test1(0xa3d70a3d,38);
+ }
+
+class CircBuf
+ {
+public:
+ static CircBuf* New(TInt aSlots);
+ CircBuf();
+ ~CircBuf();
+ TInt TryPut(TUint32 aIn);
+ void Reset();
+public:
+ volatile TUint32* iBufBase;
+ TUint32 iSlotCount;
+ volatile TUint32 iPutIndex;
+ };
+
+CircBuf* CircBuf::New(TInt aSlots)
+ {
+ test(TUint32(aSlots-1)<65536);
+ CircBuf* p = new CircBuf();
+ p->iSlotCount = aSlots;
+ p->iPutIndex = 0;
+ p->iBufBase = (TUint32*)User::Alloc(aSlots*sizeof(TUint32));
+ if (!p->iBufBase)
+ {
+ delete p;
+ p = 0;
+ }
+ __e32_memory_barrier();
+ return p;
+ }
+
+CircBuf::CircBuf()
+ {
+ iBufBase = 0;
+ }
+
+CircBuf::~CircBuf()
+ {
+ User::Free((TAny*)iBufBase);
+ }
+
+TInt CircBuf::TryPut(TUint32 aIn)
+ {
+ TUint32 orig = __e32_atomic_tau_rlx32(&iPutIndex, iSlotCount, 0, 1);
+ if (orig == iSlotCount)
+ return KErrOverflow;
+ iBufBase[orig] = aIn;
+ return KErrNone;
+ }
+
+void CircBuf::Reset()
+ {
+ __e32_atomic_store_ord32(&iPutIndex, 0);
+ }
+
+
+
+class CTimesliceTestThread : public CBase
+ {
+public:
+ CTimesliceTestThread();
+ ~CTimesliceTestThread();
+ static CTimesliceTestThread* New(TUint32 aId, TInt aCpu, TInt aSlice, CircBuf* aBuf);
+ void Start();
+ void Wait();
+ TBool Finished();
+ TInt Construct(TUint32 aId, TInt aCpu, TInt aSlice, CircBuf* aBuf);
+ static TInt ThreadFunc(TAny*);
+public:
+ RThread iThread;
+ TRequestStatus iExitStatus;
+ TUint32 iId;
+ CircBuf* iBuf;
+ TUint32 iFreq;
+ TUint32 iThresh;
+ TUint32 iThresh2;
+ TInt iCpu;
+ TInt iSlice;
+ };
+
+CTimesliceTestThread::CTimesliceTestThread()
+ {
+ iThread.SetHandle(0);
+ }
+
+CTimesliceTestThread::~CTimesliceTestThread()
+ {
+ if (iThread.Handle())
+ {
+ if (iThread.ExitType() == EExitPending)
+ {
+ iThread.Kill(0);
+ Wait();
+ }
+ CLOSE_AND_WAIT(iThread);
+ }
+ }
+
+TInt CTimesliceTestThread::Construct(TUint32 aId, TInt aCpu, TInt aSlice, CircBuf* aBuf)
+ {
+ iId = aId;
+ iCpu = aCpu;
+ iSlice = aSlice;
+ iBuf = aBuf;
+
+ TInt r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)iFreq);
+ if (r!=KErrNone)
+ return r;
+ iThresh = iFreq / 3000;
+ if (iThresh < 10)
+ iThresh = 10;
+ iThresh2 = iFreq;
+ TBuf<16> name = _L("TSThrd");
+ name.AppendNum(iId);
+ 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();
+ }
+ return KErrNone;
+ }
+
+CTimesliceTestThread* CTimesliceTestThread::New(TUint32 aId, TInt aCpu, TInt aSlice, CircBuf* aBuf)
+ {
+ CTimesliceTestThread* p = new CTimesliceTestThread;
+ if (p)
+ {
+ TInt r = p->Construct(aId, aCpu, aSlice, aBuf);
+ if (r != KErrNone)
+ {
+ delete p;
+ p = 0;
+ }
+ }
+ return p;
+ }
+
+void CTimesliceTestThread::Start()
+ {
+ iThread.Resume();
+ }
+
+TBool CTimesliceTestThread::Finished()
+ {
+ return (KRequestPending!=iExitStatus.Int());
+ }
+
+void CTimesliceTestThread::Wait()
+ {
+ User::WaitForRequest(iExitStatus);
+ }
+
+TInt CTimesliceTestThread::ThreadFunc(TAny* aPtr)
+ {
+ CTimesliceTestThread& a = *(CTimesliceTestThread*)aPtr;
+ Driver.SetCurrentThreadCpu(a.iCpu);
+ Driver.SetCurrentThreadPriority(63);
+ Driver.SetCurrentThreadTimeslice(a.iSlice);
+ User::AfterHighRes(100000);
+ TUint id = a.iId;
+ TUint32 last_interval_begin = User::FastCounter();
+ TUint32 last_seen_time = User::FastCounter();
+ FOREVER
+ {
+ TUint32 nfc = User::FastCounter();
+ TUint32 delta = nfc - last_seen_time;
+ TUint32 interval_length = last_seen_time - last_interval_begin;
+ if (delta > a.iThresh || interval_length > a.iThresh2)
+ {
+ last_interval_begin = nfc;
+ TUint32 x = (id<<30) | (interval_length&0x3fffffffu);
+ TInt r = a.iBuf->TryPut(x);
+ if (r != KErrNone)
+ break;
+ }
+ last_seen_time = nfc;
+ }
+ return KErrNone;
+ }
+
+CircBuf* RunTimesliceTest(TInt aCpu, TInt aSlice, TInt aCount, TInt aInterfere = 0)
+ {
+ TUint32 oldaff = 0;
+ TUint32 interfereAffinity = 0;
+ TUint tellKernel = 0x80000000u;
+
+ CircBuf* buf = CircBuf::New(aCount);
+ test(buf != 0);
+ CTimesliceTestThread* t0 = CTimesliceTestThread::New(0, aCpu, aSlice, buf);
+ test(t0 != 0);
+ CTimesliceTestThread* t1 = CTimesliceTestThread::New(1, aCpu, aSlice, buf);
+ test(t1 != 0);
+
+ if (aInterfere)
+ {
+ if (aInterfere < 0)
+ {
+ tellKernel = 0;
+ }
+ TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
+ test(r>0);
+ interfereAffinity = (0x80000000 | ((0x1<<r)-1)) & ~0x2; // all except core 1
+ if (0x80000001 == interfereAffinity)
+ {
+ interfereAffinity = 0; // dual core system (not doing this fails affinity check later)
+ }
+
+ Driver.SetCurrentThreadCpu(interfereAffinity , &oldaff); // move away from core 1 (doesn't hurt though not much difference gained)
+ Driver.SetCurrentThreadPriority(63); // changing prescaler requires running on core 1 so priority needs to
+ } // match test threads
+
+
+ t0->Start();
+ t1->Start();
+ if (aInterfere)
+ {
+ TInt prescale = 1;
+ while (!t0->Finished() || !t1->Finished())
+ {
+ User::AfterHighRes(23000);
+ Driver.SetLocalTimerPrescaler((1u<<1)|tellKernel, prescale);
+ prescale++;
+ if (prescale > 4)
+ {
+ prescale = 0;
+ }
+ }
+ }
+
+ t0->Wait();
+ t1->Wait();
+
+ delete t0;
+ delete t1;
+ if (aInterfere)
+ {
+ TUint32 aff;
+ Driver.SetLocalTimerPrescaler((1u<<1)|0x80000000u, -1);
+ RThread().SetPriority(EPriorityNormal);
+ Driver.SetCurrentThreadCpu(oldaff,&aff);
+ test_Equal(aff,interfereAffinity);
+ }
+ return buf;
+ }
+
+TUint32 ticks_to_us(TUint32 aTicks, TUint32 aF)
+ {
+ TUint64 x = TUint64(aTicks) * TUint64(1000000);
+ TUint64 f64 = aF;
+ x += (f64>>1);
+ x /= f64;
+ return I64LOW(x);
+ }
+
+void DisplayBuffer(CircBuf* aBuf, TUint32 aSlice )
+ {
+ TUint32 f;
+ TInt r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)f);
+ test_KErrNone(r);
+ TUint32* p = (TUint32*)aBuf->iBufBase;
+ TInt c = aBuf->iSlotCount;
+ TInt i;
+ TInt lid = -1;
+ TUint32 min = ~0u;
+ TUint32 max = 0;
+ TUint32 totivus = 0;
+ TBool firstchg = ETrue;
+ for (i=0; i<c; ++i)
+ {
+ TUint32 x = p[i];
+ TUint32 id = x>>30;
+ TUint32 iv = (x<<2)>>2;
+ TUint32 ivus = ticks_to_us(iv,f);
+ if (lid >= 0)
+ {
+ if (lid == (TInt)id)
+ totivus += ivus;
+ else
+ {
+ if (!firstchg)
+ {
+ if (totivus < min)
+ min = totivus;
+ if (totivus > max)
+ max = totivus;
+ }
+ else
+ firstchg = EFalse;
+ totivus = ivus;
+ }
+ }
+ lid = (TInt)id;
+ test.Printf(_L("ID: %1d IV: %10d (=%10dus) TIV %10dus\n"), id, iv, ivus, totivus);
+ }
+
+ if (aSlice > 0)
+ {
+ // check timeslices where within acceptable ranges
+ TUint32 sliceError = KSliceDeltaPercent*aSlice/100;
+ test_Compare(max,<,aSlice+sliceError);
+ test_Compare(min,>,aSlice-sliceError);
+ }
+ test.Printf(_L("RANGE %d-%dus (%dus)\n"), min, max, max-min);
+ }
+
+void TT()
+ {
+ test.Printf(_L("Timeslicing test ...\n"));
+ CircBuf* b = RunTimesliceTest(1, 50000, 100);
+ test.Next(_L("Baseline - expecting normal"));
+ DisplayBuffer(b,50000u);
+ delete b;
+
+ Driver.SetLocalTimerPrescaler(1u<<1, 1);
+ b = RunTimesliceTest(1, 50000, 100);
+ test.Next(_L("expecting double"));
+ DisplayBuffer(b,100000u);
+ delete b;
+
+ Driver.SetLocalTimerPrescaler(1u<<1|0x80000000u, 1);
+ test.Next(_L("expecting normal again"));
+ b = RunTimesliceTest(1, 50000, 100);
+ DisplayBuffer(b,50000u);
+ delete b;
+
+ test.Next(_L("expecting half"));
+ Driver.SetLocalTimerPrescaler(1u<<1, -1);
+ b = RunTimesliceTest(1, 50000, 100);
+ DisplayBuffer(b,25000u);
+ delete b;
+
+ Driver.SetLocalTimerPrescaler(1u<<1|0x80000000u, -1);
+ test.Next(_L("expecting normal again"));
+ b = RunTimesliceTest(1, 50000, 100);
+ DisplayBuffer(b,50000u);
+ delete b;
+
+ b = RunTimesliceTest(1, 50000, 200 ,-1);
+ test.Next(_L("expecting random"));
+ DisplayBuffer(b,0u); // timeslices should be fairly random on this run
+
+ b = RunTimesliceTest(1, 50000, 200 ,1);
+ test.Next(_L("expecting normal again"));
+ DisplayBuffer(b,50000u);
+ delete b;
+ }
+
+struct SGTRecord
+ {
+ TUint64 iTSInterval;
+ TUint64 iGTInterval;
+ };
+
+
+SGTRecord* RunGTTest(TInt aCount, TInt aWait)
+ {
+ TUint64 lastgt,lastts,gt,ts;
+
+ SGTRecord* res = new SGTRecord[aCount];
+ test(res!=0);
+
+
+ TInt r = Driver.ReadGlobalTimerAndTimestamp(lastgt,lastts);
+ test_Equal(r,KErrNone);
+
+ for (TInt i = 0; i < aCount; i++)
+ {
+ User::AfterHighRes(aWait);
+
+ TInt r = Driver.ReadGlobalTimerAndTimestamp(gt,ts);
+ test_Equal(r,KErrNone);
+ res[i].iGTInterval = gt-lastgt;
+ lastgt = gt;
+ res[i].iTSInterval = ts-lastts;
+ lastts = ts;
+ }
+
+ return res;
+ }
+
+void DisplayGTResults(SGTRecord* aRec, TInt aCount, TUint32 aFreq, TUint64 aExpectedTSInterval, TUint64 aExpectedGTInterval)
+ {
+ SGTRecord max = { 0ul , 0ul };
+ SGTRecord min = { KMaxTUint64 , KMaxTUint64 };
+
+ TUint64 errgt = (aExpectedGTInterval*KTimeStampDeltaPercent)/100;
+ TUint64 errts = (aExpectedTSInterval*KTimeStampDeltaPercent)/100;
+
+
+ for (TInt i = 0 ; i < aCount; i++)
+ {
+ test.Printf(_L("gt interval : %Lu (gtticks) %Lu (us)\n"),
+ aRec[i].iGTInterval,
+ aRec[i].iTSInterval*1000000u/TUint64(aFreq));
+
+ if (max.iTSInterval < aRec[i].iTSInterval)
+ {
+ max.iTSInterval = aRec[i].iTSInterval;
+ }
+ if (max.iGTInterval < aRec[i].iGTInterval)
+ {
+ max.iGTInterval = aRec[i].iGTInterval;
+ }
+
+ if (min.iTSInterval > aRec[i].iTSInterval)
+ {
+ min.iTSInterval = aRec[i].iTSInterval;
+ }
+ if (min.iGTInterval > aRec[i].iGTInterval)
+ {
+ min.iGTInterval = aRec[i].iGTInterval;
+ }
+ }
+
+ test.Printf(_L("RANGE Global Timer %Lu-%Lu ticks (%Lu ticks)\n"),
+ min.iGTInterval, max.iGTInterval, max.iGTInterval-min.iGTInterval);
+
+ test.Printf(_L("RANGE Timestamp %Lu-%Lu us (%Lu us)\n"),
+ (1000000u*min.iGTInterval)/TUint64(aFreq), (1000000u*max.iGTInterval)/TUint64(aFreq),
+ (1000000u*max.iGTInterval)/TUint64(aFreq) - (1000000u*min.iGTInterval)/TUint64(aFreq));
+
+ if (errts)
+ {
+ test_Compare(max.iTSInterval,<,aExpectedTSInterval+errts);
+ test_Compare(min.iTSInterval,>,aExpectedTSInterval);
+ }
+
+ if (errgt)
+ {
+ test_Compare(max.iGTInterval,<,aExpectedGTInterval+errgt);
+ test_Compare(min.iGTInterval,>,aExpectedGTInterval);
+ }
+
+ }
+
+void GTT()
+ {
+ test.Printf(_L("Global timer tests ...\n"));
+ TUint64 gt,ts;
+
+ TInt r = Driver.ReadGlobalTimerAndTimestamp(gt,ts);
+ if (KErrNotSupported == r )
+ {
+ test.Printf(_L("Global timer not supported in this plaform, skipping GT tests\n"));
+ return;
+ }
+
+ TUint32 f;
+ r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)f);
+ test_KErrNone(r);
+ TInt wait = 100000; // 100ms
+ TInt count = 10;
+
+ TUint64 expectedTs = (TUint64(f)*TUint64(wait))/1000000u;
+ TUint64 expectedGtOrig = expectedTs;
+
+ SGTRecord* rec;
+ for (TInt i = 0; i < 10; i++)
+ {
+ TUint64 expectedGt = expectedGtOrig/(i+1);
+ r = Driver.SetGlobalTimerPrescaler(i);
+ test_KErrNone(r);
+ rec = RunGTTest(count, wait);
+ test.Printf(_L("expectedTS %Lu expectedGT %Lu\n"),expectedTs,expectedGt);
+ DisplayGTResults(rec,count, f, expectedTs , expectedGt);
+ delete rec;
+ }
+
+ r = Driver.SetGlobalTimerPrescaler(-1); // back to default
+ test_KErrNone(r);
+ }
+
+void RunTests()
+ {
+ TestRatios();
+ if (Driver.FrqChgTestPresent()!=KErrNone)
+ {
+ test.Printf(_L("Frequency Change not supported on this platform\n"));
+ return;
+ }
+ TT();
+ GTT();
+ }
+
+GLDEF_C TInt E32Main()
+ {
+ test.Title();
+ test.Start(_L("Testing"));
+ TInt r = User::LoadLogicalDevice(KLddName);
+ if (r==KErrNotFound)
+ {
+ test.Printf(_L("Test not supported on this platform\n"));
+ }
+ else
+ {
+ if (r!=KErrNone)
+ {
+ test_Equal(KErrAlreadyExists, r);
+ }
+ r = Driver.Open();
+ test_KErrNone(r);
+ RunTests();
+ Driver.Close();
+ }
+
+ test.End();
+ r = User::FreeLogicalDevice(KLddName);
+ test_KErrNone(r);
+ return KErrNone;
+ }