--- /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 <kernel/kern_priv.h>
+#include "d_emitest.h"
+#include "d_emitest_dev.h"
+#include <kernel/emi.h>
+
+//
+// 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);
+ }