First public contribution.
1 // Copyright (c) 2008-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\nkern\d_crazyints.cpp
17 // kernel-side test (driver) for Crazy-Interrupts functionality
22 #include <kernel/kern_priv.h>
23 #include "d_crazyints.h"
26 const TInt KMaxNumChannels = 1; // we only support one client at the time
28 _LIT(KLddRootName,"d_crazyints");
29 _LIT(KIntTestThreadName,"InterruptsTest");
32 DDeviceIntsTest::DDeviceIntsTest()
35 iUnitsMask = 0; // No info, no PDD, no Units
36 iVersion = TVersion(KIntTestMajorVersionNumber,
37 KIntTestMinorVersionNumber, KIntTestBuildVersionNumber);
40 DDeviceIntsTest::~DDeviceIntsTest()
44 // Install the device driver.
45 TInt DDeviceIntsTest::Install()
47 return (SetName(&KLddRootName));
50 void DDeviceIntsTest::GetCaps(TDes8& aDes) const
52 TPckgBuf<TCapsProxyClient> b;
53 b().version = TVersion(KIntTestMajorVersionNumber, KIntTestMinorVersionNumber, KIntTestBuildVersionNumber);
54 Kern::InfoCopy(aDes, b);
57 // Create a channel on the device.
58 TInt DDeviceIntsTest::Create(DLogicalChannelBase*& aChannel)
60 if (iOpenChannels >= KMaxNumChannels)
63 aChannel = new DChannIntsTest;
64 return aChannel ? KErrNone : KErrNoMemory;
67 DChannIntsTest::DChannIntsTest()
69 : iTimer(Handler, this)
72 iClient = &Kern::CurrentThread();
73 // Increase the DThread's ref count so that it does not close without us
74 ((DObject*)iClient)->Open();
77 DChannIntsTest::~DChannIntsTest()
80 // decrement the DThread's reference count
81 Kern::SafeClose((DObject*&) iClient, NULL);
84 TInt DChannIntsTest::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
86 TInt r = Kern::DynamicDfcQCreate(iDfcQue, KIntTestThreadPriority, KIntTestThreadName);
96 return KErrNotSupported;
100 void DChannIntsTest::HandleMsg(TMessageBase* aMsg)
102 TThreadMessage& m = *(TThreadMessage*) aMsg;
107 iMsgQ.iMessage->Complete(KErrNone, EFalse);
110 else if (id == KMaxTInt)
112 m.Complete(KErrNone, ETrue);
118 TRequestStatus* pS = (TRequestStatus*) m.Ptr0();
119 TInt r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
122 Kern::RequestComplete(iClient, pS, r);
124 m.Complete(KErrNone, ETrue);
128 TInt r = DoControl(id, m.Ptr0(), m.Ptr1());
129 m.Complete(r, ETrue);
134 TBool DChannIntsTest::CrazyInterruptsEnabled()
136 // check, if crazy-interrupts are enabled..
137 TSuperPage& sp = Kern::SuperPage();
138 return (sp.KernelConfigFlags() & EKernelConfigSMPCrazyInterrupts);
141 // Isr handler - it will check, if previously was run on the same core..
142 void DChannIntsTest::Handler (TAny *aParam)
144 __KTRACE_OPT(KTESTFAST,Kern::Printf("Handler\n"));
145 DChannIntsTest *a = (DChannIntsTest*) aParam;
147 // clear the flag for the core that we're now executing..
148 TUint curr_core = NKern::CurrentCpu();
149 a->iStatus &= ~(1u << curr_core);
151 // decrement the counter..and kick the timer again - as required..
152 TInt cnt = __e32_atomic_add_acq32(&a->iRunCount, ~(0u));
154 a->iTimer.Again(KTimerWaitValue);
157 // This test checks if the timer handler run in ISR context executes on all available
158 // CPU cores when crazy interrupts are enabled.
159 TInt DChannIntsTest::TestCrazyInts()
161 __KTRACE_OPT(KTESTFAST,Kern::Printf("TestCrazyInts"));
163 if(!CrazyInterruptsEnabled())
164 return KErrNotSupported;
166 // Check how many CPUs we have in the system -and set corresponding flags in
167 // iStatus. As an indication, that ISRs are run on a different cores all these flags
168 // should be cleared in the Handler.
170 for(TInt i = 0; i < NKern::NumberOfCpus(); ++i)
176 // Kick-off a Timer to run it's handler in a ISR context..
177 iRunCount = KNumOfTimes;
178 iTimer.OneShot(KTimerWaitValue);
180 //busy wait until it all completes..
181 while (__e32_atomic_load_acq32(&iRunCount) > 0)
186 if((iStatus ^ status) == 1)
188 // we must be running on the single core version, whilst the kernel flag is set
189 // this might happen, if the Kernel (nkern) was not compiled with SMP_CRAZY_INTERRUPTS defined
190 // check, if variant.mmh for this platform contains: macro SMP_CRAZY_INTERRUPTS
191 Kern::Printf("Interrupts running only on CPU0 and EKernelConfigSMPCrazyInterrupts flag is set \n\r is this - wrong configuration? ", iStatus);
194 Kern::Printf("ISR was not executed on all CPUs..(%x)", iStatus);
203 // to handle synchronous requests from the client
204 TInt DChannIntsTest::DoControl(TInt aId, TAny* a1, TAny* a2)
209 case RBusIntTestClient::ETestCrazyInts:
214 r = KErrNotSupported;
221 __KTRACE_OPT(KTESTFAST,Kern::Printf("DChannIntsTest::DoControl():Unrecognized value for aId=0x%x\n", aId));
229 // to handle asynchronous requests from the client
230 TInt DChannIntsTest::DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2)
232 __KTRACE_OPT(KTESTFAST,Kern::Printf("DChannIntsTest::DoRequest(aId=0x%x, aStatus=0x%x, a1=0x%x, a2=0x%x\n",
233 aId, aStatus, a1, a2));
240 __KTRACE_OPT(KTESTFAST,Kern::Printf("DChannIntsTest::DoRequest(): unrecognized value for aId=0x%x\n", aId));
249 DECLARE_STANDARD_LDD()
251 return new DDeviceIntsTest;