diff -r 000000000000 -r a41df078684a kerneltest/e32test/emi/d_emitest.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/emi/d_emitest.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,315 @@ +// Copyright (c) 2005-2009 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\emi\d_emitest.cpp +// +// + +#include +#include "d_emitest.h" +#include "d_emitest_dev.h" +#include + +// +// DEMITestFactory +// + +/* + Standard export function for LDDs. This creates a DLogicalDevice derived object, + in this case, our DEMITestFactory +*/ +DECLARE_STANDARD_LDD() + { + return new DEMITestFactory; + } + +DEMITestFactory::DEMITestFactory() + { + } + +DEMITestFactory::~DEMITestFactory() + { + } + +/* + Second stage constructor for DEMITestFactory. + This must at least set a name for the driver object. + + @return KErrNone or standard error code. +*/ +TInt DEMITestFactory::Install() + { + return SetName(&KEMITestName); + } + +/* + Return the drivers capabilities. + Called in the response to an RDevice::GetCaps() request. + The thread is in a critical section. + + @param aDes Descriptor to write capabilities information into +*/ +void DEMITestFactory::GetCaps(TDes8&) const + { + } + +/* + Called by the kernel's device driver framework to create a Logical Channel. + This is called in the context of the user thread (client) which requested the creation of a Logical Channel + (E.g. through a call to RBusLogicalChannel::DoCreate) + The thread is in a critical section. + + @param aChannel Set to point to the created Logical Channel + + @return KErrNone or standard error code. +*/ +TInt DEMITestFactory::Create(DLogicalChannelBase*& aChannel) + { + aChannel=new DEMITestChannel; + if(!aChannel) + return KErrNoMemory; + + return KErrNone; + } + + +// +// Logical Channel +// + +DEMITestChannel::DEMITestChannel() +: iTagMaskDFC(TagMaskDFC,NULL,1) + { + // Get pointer to client threads DThread object + iClient=&Kern::CurrentThread(); + // Open a reference on client thread so it's control block can't dissapear until + // this driver has finished with it. + ((DObject*)iClient)->Open(); + } + +DEMITestChannel::~DEMITestChannel() + { + // Stop EMI, incase it wannt stopped manually. + EMI::TaskEventLogging(EFalse,0,NULL,NULL); + EMI::SetMask(0); + + // Close our reference on the client thread + Kern::SafeClose((DObject*&)iClient,NULL); + } + +/* + Second stage constructor called by the kernel's device driver framework. + This is called in the context of the user thread (client) which requested the creation of a Logical Channel + (E.g. through a call to RBusLogicalChannel::DoCreate) + The thread is in a critical section. + + @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate + @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate + @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate + + @return KErrNone or standard error code. +*/ +TInt DEMITestChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion&) + { + iTagMaskDFC.SetDfcQ(Kern::DfcQue0()); + return KErrNone; + } + +/* + Normal test monitors +*/ +TInt MyThreadStartMonitor(NThread* aNThread) + { + TTaskEventRecord rec; + rec.iType=128; + rec.iPrevious=((TInt*) aNThread)+1; // This stops the event getting killed on thread exit. + // This means there is no garantee the thread will still exist when + // the record is read. This is only safe here as the test code never + // attempts to derefrance this pointer. + EMI::AddTaskEvent(rec); + return 0; + } + + +void MyThreadExitMonitor(NThread* aNThread) + { + TTaskEventRecord rec; + rec.iType=129; + rec.iPrevious=aNThread; + EMI::AddTaskEvent(rec); + } +/* + Stress test monitors + + Vems = 1: Passed. + 0: No monitors called. + -1: Wrong Exit monitor callled. + -2: Exit call before StartMonitor + -3: Jibberish VEMs value. (or anything ending 5-9) + -4: Exit called multiple times, 1st time ok. + <-9: Exit called multiple times. See last digit for status 1st time. + Stops couting after -1000, where its clearly very sick! +*/ + + +TInt SoakStartMonitor1(NThread* aNThread) + { + EMI::SetThreadVemsData(aNThread,(TAny*)1000); + return 0; + } + +TInt SoakStartMonitor2(NThread* aNThread) + { + EMI::SetThreadVemsData(aNThread,(TAny*)2000); + return 0; + } + + + +inline void SoakExitMonitor(NThread* aNThread, TInt aOwner) + { + TInt val = (TInt) EMI::GetThreadVemsData(aNThread); + + if (val>-1) + { + TInt notOwner = (aOwner==1000?2000:1000); + + if (val==aOwner) + EMI::SetThreadVemsData(aNThread,(TAny*)1); + else if (val==notOwner) + EMI::SetThreadVemsData(aNThread,(TAny*)-1); + else if (val==0) + EMI::SetThreadVemsData(aNThread,(TAny*)-2); + else if (val==1) + EMI::SetThreadVemsData(aNThread,(TAny*)-4); + else + EMI::SetThreadVemsData(aNThread,(TAny*)-3); + } + else + { + if (val>-1000) + EMI::SetThreadVemsData(aNThread,(TAny*)(val-10)); + else + EMI::SetThreadVemsData(aNThread,(TAny*)val); + } + } + +void SoakExitMonitor1(NThread* aNThread) + { + SoakExitMonitor(aNThread,1000); + } +void SoakExitMonitor2(NThread* aNThread) + { + SoakExitMonitor(aNThread,2000); + } + +/* + Process synchronous requests +*/ +TInt DEMITestChannel::Request(TInt aFunction, TAny* a1, TAny* a2) + { + TInt r=KErrNotSupported; + TTaskEventRecord rec; + + switch (aFunction) + { + case REMITest::ETaskEventLogging: + { + + NKern::ThreadEnterCS(); + + TMonitors mon = (TMonitors) ((TInt)a1 >> 1); + TBool logging = (TBool) ((TInt)a1 & 1); + + switch (mon) + { + case ENone: r = EMI::TaskEventLogging(logging,(TInt) a2,NULL,NULL); + break; + case ENormal: r = EMI::TaskEventLogging(logging,(TInt) a2,&MyThreadStartMonitor,&MyThreadExitMonitor); + break; + case EStressFirst:r = EMI::TaskEventLogging(logging,(TInt) a2,SoakStartMonitor1,SoakExitMonitor1); + break; + case EStressSecond:r = EMI::TaskEventLogging(logging,(TInt) a2,SoakStartMonitor2,SoakExitMonitor2); + } + NKern::ThreadLeaveCS(); + return r; + } + case REMITest::EGetTaskEvent: + r = (TInt) EMI::GetTaskEvent(rec); + if (r) + kumemput(a1,&rec,sizeof(TTaskEventRecord)); + return r; + case REMITest::EAddTaskEvent: + kumemget(&rec,a1,sizeof(TTaskEventRecord)); + return (TInt) EMI::AddTaskEvent(rec); + case REMITest::EGetIdleThread: + return (TInt) EMI::GetIdleThread(); + case REMITest::EGetSigmaThread: + return (TInt) EMI::GetSigmaThread(); + case REMITest::ESetVEMSData: + EMI::SetThreadVemsData((NThread*) a1,a2); + return KErrNone; + case REMITest::EGetVEMSData: + return (TInt) EMI::GetThreadVemsData((NThread*) a1); + case REMITest::ESetThreadLoggable: + EMI::SetThreadLoggable((NThread*) a1,(TBool) a2); + return KErrNone; + case REMITest::EGetThreadLoggable: + return (TInt) EMI::GetThreadLoggable((NThread*) a1); + case REMITest::ESetThreadTag: + EMI::SetThreadTag((NThread*) a1,(TUint32) a2); + return KErrNone; + case REMITest::EGetThreadTag: + return (TInt) EMI::GetThreadTag((NThread*) a1); + case REMITest::ESetMask: + EMI::SetMask((TInt) a1); + return KErrNone; + case REMITest::EGetMask: + return EMI::GetMask(); + case REMITest::ESetDFC: + EMI::SetDfc(&iTagMaskDFC, 0); + return KErrNone; + case REMITest::ESetState: + EMI::SetState((TInt) a1); + return KErrNone; + case REMITest::EGetState: + return EMI::GetState(); + case REMITest::EGetNThread: + { + DThread* myThread; + TInt myNThread; + NKern::LockSystem(); + + myThread = (DThread* ) Kern::CurrentThread().ObjectFromHandle((TInt)a1,EThread); + myNThread= (TInt) (myThread==NULL?NULL:&myThread->iNThread); + NKern::UnlockSystem(); + return myNThread; + } + case REMITest::EAfterIdle: + EMI::AfterIdle((TInt) a1); + return KErrNone; + + default: + return KErrNotSupported; + } + } + +/* + DFC callback which gets triggered when the EMI tag anded with thread mask is true. + Sets EMI state to be the value returned from GetDfcTriggerTag. +*/ +void DEMITestChannel::TagMaskDFC(TAny*) + { + EMI::SetState(EMI::GetDfcTriggerTag()); + EMI::SetMask(0); + }