kerneltest/e32test/emi/d_emitest.cpp
changeset 0 a41df078684a
--- /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);
+	}