First public contribution.
1 // Copyright (c) 2005-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\emi\d_emitest.cpp
18 #include <kernel/kern_priv.h>
19 #include "d_emitest.h"
20 #include "d_emitest_dev.h"
21 #include <kernel/emi.h>
28 Standard export function for LDDs. This creates a DLogicalDevice derived object,
29 in this case, our DEMITestFactory
31 DECLARE_STANDARD_LDD()
33 return new DEMITestFactory;
36 DEMITestFactory::DEMITestFactory()
40 DEMITestFactory::~DEMITestFactory()
45 Second stage constructor for DEMITestFactory.
46 This must at least set a name for the driver object.
48 @return KErrNone or standard error code.
50 TInt DEMITestFactory::Install()
52 return SetName(&KEMITestName);
56 Return the drivers capabilities.
57 Called in the response to an RDevice::GetCaps() request.
58 The thread is in a critical section.
60 @param aDes Descriptor to write capabilities information into
62 void DEMITestFactory::GetCaps(TDes8&) const
67 Called by the kernel's device driver framework to create a Logical Channel.
68 This is called in the context of the user thread (client) which requested the creation of a Logical Channel
69 (E.g. through a call to RBusLogicalChannel::DoCreate)
70 The thread is in a critical section.
72 @param aChannel Set to point to the created Logical Channel
74 @return KErrNone or standard error code.
76 TInt DEMITestFactory::Create(DLogicalChannelBase*& aChannel)
78 aChannel=new DEMITestChannel;
90 DEMITestChannel::DEMITestChannel()
91 : iTagMaskDFC(TagMaskDFC,NULL,1)
93 // Get pointer to client threads DThread object
94 iClient=&Kern::CurrentThread();
95 // Open a reference on client thread so it's control block can't dissapear until
96 // this driver has finished with it.
97 ((DObject*)iClient)->Open();
100 DEMITestChannel::~DEMITestChannel()
102 // Stop EMI, incase it wannt stopped manually.
103 EMI::TaskEventLogging(EFalse,0,NULL,NULL);
106 // Close our reference on the client thread
107 Kern::SafeClose((DObject*&)iClient,NULL);
111 Second stage constructor called by the kernel's device driver framework.
112 This is called in the context of the user thread (client) which requested the creation of a Logical Channel
113 (E.g. through a call to RBusLogicalChannel::DoCreate)
114 The thread is in a critical section.
116 @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
117 @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
118 @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate
120 @return KErrNone or standard error code.
122 TInt DEMITestChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion&)
124 iTagMaskDFC.SetDfcQ(Kern::DfcQue0());
131 TInt MyThreadStartMonitor(NThread* aNThread)
133 TTaskEventRecord rec;
135 rec.iPrevious=((TInt*) aNThread)+1; // This stops the event getting killed on thread exit.
136 // This means there is no garantee the thread will still exist when
137 // the record is read. This is only safe here as the test code never
138 // attempts to derefrance this pointer.
139 EMI::AddTaskEvent(rec);
144 void MyThreadExitMonitor(NThread* aNThread)
146 TTaskEventRecord rec;
148 rec.iPrevious=aNThread;
149 EMI::AddTaskEvent(rec);
155 0: No monitors called.
156 -1: Wrong Exit monitor callled.
157 -2: Exit call before StartMonitor
158 -3: Jibberish VEMs value. (or anything ending 5-9)
159 -4: Exit called multiple times, 1st time ok.
160 <-9: Exit called multiple times. See last digit for status 1st time.
161 Stops couting after -1000, where its clearly very sick!
165 TInt SoakStartMonitor1(NThread* aNThread)
167 EMI::SetThreadVemsData(aNThread,(TAny*)1000);
171 TInt SoakStartMonitor2(NThread* aNThread)
173 EMI::SetThreadVemsData(aNThread,(TAny*)2000);
179 inline void SoakExitMonitor(NThread* aNThread, TInt aOwner)
181 TInt val = (TInt) EMI::GetThreadVemsData(aNThread);
185 TInt notOwner = (aOwner==1000?2000:1000);
188 EMI::SetThreadVemsData(aNThread,(TAny*)1);
189 else if (val==notOwner)
190 EMI::SetThreadVemsData(aNThread,(TAny*)-1);
192 EMI::SetThreadVemsData(aNThread,(TAny*)-2);
194 EMI::SetThreadVemsData(aNThread,(TAny*)-4);
196 EMI::SetThreadVemsData(aNThread,(TAny*)-3);
201 EMI::SetThreadVemsData(aNThread,(TAny*)(val-10));
203 EMI::SetThreadVemsData(aNThread,(TAny*)val);
207 void SoakExitMonitor1(NThread* aNThread)
209 SoakExitMonitor(aNThread,1000);
211 void SoakExitMonitor2(NThread* aNThread)
213 SoakExitMonitor(aNThread,2000);
217 Process synchronous requests
219 TInt DEMITestChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
221 TInt r=KErrNotSupported;
222 TTaskEventRecord rec;
226 case REMITest::ETaskEventLogging:
229 NKern::ThreadEnterCS();
231 TMonitors mon = (TMonitors) ((TInt)a1 >> 1);
232 TBool logging = (TBool) ((TInt)a1 & 1);
236 case ENone: r = EMI::TaskEventLogging(logging,(TInt) a2,NULL,NULL);
238 case ENormal: r = EMI::TaskEventLogging(logging,(TInt) a2,&MyThreadStartMonitor,&MyThreadExitMonitor);
240 case EStressFirst:r = EMI::TaskEventLogging(logging,(TInt) a2,SoakStartMonitor1,SoakExitMonitor1);
242 case EStressSecond:r = EMI::TaskEventLogging(logging,(TInt) a2,SoakStartMonitor2,SoakExitMonitor2);
244 NKern::ThreadLeaveCS();
247 case REMITest::EGetTaskEvent:
248 r = (TInt) EMI::GetTaskEvent(rec);
250 kumemput(a1,&rec,sizeof(TTaskEventRecord));
252 case REMITest::EAddTaskEvent:
253 kumemget(&rec,a1,sizeof(TTaskEventRecord));
254 return (TInt) EMI::AddTaskEvent(rec);
255 case REMITest::EGetIdleThread:
256 return (TInt) EMI::GetIdleThread();
257 case REMITest::EGetSigmaThread:
258 return (TInt) EMI::GetSigmaThread();
259 case REMITest::ESetVEMSData:
260 EMI::SetThreadVemsData((NThread*) a1,a2);
262 case REMITest::EGetVEMSData:
263 return (TInt) EMI::GetThreadVemsData((NThread*) a1);
264 case REMITest::ESetThreadLoggable:
265 EMI::SetThreadLoggable((NThread*) a1,(TBool) a2);
267 case REMITest::EGetThreadLoggable:
268 return (TInt) EMI::GetThreadLoggable((NThread*) a1);
269 case REMITest::ESetThreadTag:
270 EMI::SetThreadTag((NThread*) a1,(TUint32) a2);
272 case REMITest::EGetThreadTag:
273 return (TInt) EMI::GetThreadTag((NThread*) a1);
274 case REMITest::ESetMask:
275 EMI::SetMask((TInt) a1);
277 case REMITest::EGetMask:
278 return EMI::GetMask();
279 case REMITest::ESetDFC:
280 EMI::SetDfc(&iTagMaskDFC, 0);
282 case REMITest::ESetState:
283 EMI::SetState((TInt) a1);
285 case REMITest::EGetState:
286 return EMI::GetState();
287 case REMITest::EGetNThread:
293 myThread = (DThread* ) Kern::CurrentThread().ObjectFromHandle((TInt)a1,EThread);
294 myNThread= (TInt) (myThread==NULL?NULL:&myThread->iNThread);
295 NKern::UnlockSystem();
298 case REMITest::EAfterIdle:
299 EMI::AfterIdle((TInt) a1);
303 return KErrNotSupported;
308 DFC callback which gets triggered when the EMI tag anded with thread mask is true.
309 Sets EMI state to be the value returned from GetDfcTriggerTag.
311 void DEMITestChannel::TagMaskDFC(TAny*)
313 EMI::SetState(EMI::GetDfcTriggerTag());