kerneltest/e32test/nkern/d_implicit.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:26:05 +0100
branchRCL_3
changeset 29 743008598095
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 1997-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\nkern\d_implicit.cpp
// LDD for testing nanokernel implicit system lock
// 
//

#define __INCLUDE_NTHREADBASE_DEFINES__

#include "platform.h"
#include "nk_priv.h"
#include "d_implicit.h"

#ifndef __SMP__
#include "../misc/prbs.h"

const TInt KMajorVersionNumber=0;
const TInt KMinorVersionNumber=1;
const TInt KBuildVersionNumber=1;

const TInt KStackSize=1024;

inline NThreadBase::NThreadBase()
	{
	}

class DImpSysTestFactory : public DLogicalDevice
//
// Implicit system lock test LDD factory
//
	{
public:
	DImpSysTestFactory();
	virtual TInt Install();						//overriding pure virtual
	virtual void GetCaps(TDes8& aDes) const;	//overriding pure virtual
	virtual TInt Create(DLogicalChannelBase*& aChannel);	//overriding pure virtual
	};

class DImpSysTest : public DLogicalChannelBase
//
// Implicit system lock test LDD channel
//
	{
public:
	DImpSysTest();
protected:
	virtual TInt Request(TInt aReqNo, TAny* a1, TAny* a2);
	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
public:
	TInt CreateThread(TInt);
	TInt Start(TInt aTest);
	TInt Stop(SStats& aStats);
	static void Thread1(TAny*);
	static void Thread2(TAny*);
	static void Thread3(TAny*);
public:
	TInt iFailCount;
	TInt iCount1;
	TInt iCount2;
	TInt iCount3;
	TInt iTestNum;
	NFastMutex iMutex;
	NThread iThread1;	// holds fast mutex, imp sys
	NThread iThread2;	// holds system lock, not imp sys
	NThread iThread3;	// random stuff
	TUint32 iStack1[KStackSize/sizeof(TUint32)];
	TUint32 iStack2[KStackSize/sizeof(TUint32)];
	TUint32 iStack3[KStackSize/sizeof(TUint32)];
	};

TInt DImpSysTest::CreateThread(TInt a)
	{
	SNThreadCreateInfo info;
	info.iStackSize=KStackSize;
	info.iPriority=(a==3)?16:12;
	info.iTimeslice=-1;
	info.iAttributes=(TUint8)((a==1)?KThreadAttImplicitSystemLock:0);
	info.iHandlers=NULL;
	info.iFastExecTable=NULL;
	info.iSlowExecTable=NULL;
	info.iParameterBlock=(const TUint32*)this;
	info.iParameterBlockSize=0;

	NThread* pT=NULL;
	switch (a)
		{
		case 1:
			pT=&iThread1;
			info.iFunction=&Thread1;
			info.iStackBase=iStack1;
			break;
		case 2:
			pT=&iThread2;
			info.iFunction=&Thread2;
			info.iStackBase=iStack2;
			break;
		case 3:
			pT=&iThread3;
			info.iFunction=&Thread3;
			info.iStackBase=iStack3;
			break;
		default:
			return KErrArgument;
		}

	return NKern::ThreadCreate(pT,info);
	}

void DImpSysTest::Thread1(TAny* aPtr)
	{
	DImpSysTest& d=*(DImpSysTest*)aPtr;
	TScheduler* pS=TScheduler::Ptr();
	NFastMutex& m=pS->iLock;
	TUint seed[2];
	seed[0]=1;
	seed[1]=0;
	FOREVER
		{
		NKern::FMWait(&d.iMutex);
		Kern::NanoWait(1300000);	// spin for 1.3ms
		TInt c = NKern::CurrentContext();
		__NK_ASSERT_ALWAYS(c == NKern::EThread);
		NKern::FMSignal(&d.iMutex);
		if (m.iHoldingThread)
			++d.iFailCount;
		TInt x=Random(seed)&3;
		if (x)
			NKern::Sleep(x);
		++d.iCount1;
		}
	}

void DImpSysTest::Thread2(TAny* aPtr)
	{
	DImpSysTest& d=*(DImpSysTest*)aPtr;
	TUint seed[2];
	seed[0]=2;
	seed[1]=0;
	FOREVER
		{
		TInt c = NKern::CurrentContext();
		__NK_ASSERT_ALWAYS(c == NKern::EThread);
		NKern::LockSystem();
		Kern::NanoWait(1100000);	// spin for 1.1ms
		NKern::UnlockSystem();
		TInt x=Random(seed)&3;
		if (x)
			NKern::Sleep(x);
		++d.iCount2;
		}
	}

void DImpSysTest::Thread3(TAny* aPtr)
	{
	DImpSysTest& d=*(DImpSysTest*)aPtr;
	TUint seed[2];
	seed[0]=3;
	seed[1]=0;
	if (d.iTestNum==RImpSysTest::ETestPriority)
		{
		FOREVER
			{
			TInt c = NKern::CurrentContext();
			__NK_ASSERT_ALWAYS(c == NKern::EThread);
			TInt x=Random(seed)&15;
			NKern::Sleep(x+1);
			x=Random(seed)&1;
			TInt p=10+Random(seed)&3;
			if (x)
				NKern::ThreadSetPriority(&d.iThread1,p);
			else
				NKern::ThreadSetPriority(&d.iThread2,p);
			++d.iCount3;
			}
		}
	else if (d.iTestNum==RImpSysTest::ETestRoundRobin)
		{
		FOREVER
			{
			TInt c = NKern::CurrentContext();
			__NK_ASSERT_ALWAYS(c == NKern::EThread);
			TInt x=Random(seed)&15;
			NKern::Sleep(x+1);
			NKern::RotateReadyList(12);
			++d.iCount3;
			}
		}
	else if (d.iTestNum==RImpSysTest::ETestDummy)
		{
		FOREVER
			{
			TInt c = NKern::CurrentContext();
			__NK_ASSERT_ALWAYS(c == NKern::EThread);
			TInt x=Random(seed)&15;
			NKern::Sleep(x+1);
			x=Random(seed)&255;
			TInt p=10+Random(seed)&3;
			if (x<85)
				{
				NKern::LockSystem();
				NKern::ThreadSetPriority(&d.iThread1,p);
				NKern::UnlockSystem();
				}
			else if (x<170)
				{
				NKern::LockSystem();
				NKern::ThreadSetPriority(&d.iThread2,p);
				NKern::UnlockSystem();
				}
			else
				{
				NKern::FMWait(&d.iMutex);
				NKern::FMSignal(&d.iMutex);
				}
			++d.iCount3;
			}
		}
	}

TInt DImpSysTest::Start(TInt aTest)
	{
	if (iTestNum>=0)
		return KErrInUse;
	iTestNum=aTest;
	iFailCount=0;
	iCount1=0;
	iCount2=0;
	iCount3=0;
	new (&iMutex) NFastMutex;
	TInt r=CreateThread(1);
	if (r==KErrNone)
		r=CreateThread(2);
	if (r==KErrNone)
		r=CreateThread(3);
	if (r==KErrNone)
		{
		NKern::ThreadResume(&iThread3);
		NKern::ThreadResume(&iThread1);
		NKern::ThreadResume(&iThread2);
		}
	if (r!=KErrNone)
		iTestNum=-1;
	return r;
	}


TInt DImpSysTest::Stop(SStats& a)
	{
	NKern::ThreadKill(&iThread1);
	NKern::ThreadKill(&iThread2);
	NKern::ThreadKill(&iThread3);
	NKern::ThreadSetPriority(&iThread1,16);
	NKern::ThreadSetPriority(&iThread2,16);
	NKern::ThreadSetPriority(&iThread3,16);
	while (iThread1.iNState!=NThread::EDead || iThread2.iNState!=NThread::EDead || iThread3.iNState!=NThread::EDead)
		NKern::Sleep(10);
	TInt size=3*(sizeof(NThread)+KStackSize)+sizeof(NFastMutex);
	memset(&iMutex,0xbb,size);
	a.iFailCount=iFailCount;
	a.iCount1=iCount1;
	a.iCount2=iCount2;
	a.iCount3=iCount3;
	iTestNum=-1;
	return KErrNone;
	}

DImpSysTestFactory::DImpSysTestFactory()
//
// Constructor
//
    {
    iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
    //iParseMask=0;//No units, no info, no PDD
    //iUnitsMask=0;//Only one thing
    }

TInt DImpSysTestFactory::Create(DLogicalChannelBase*& aChannel)
//
// Create a new DImpSysTest on this logical device
//
    {
	aChannel=new DImpSysTest;
    return aChannel?KErrNone:KErrNoMemory;
    }

TInt DImpSysTestFactory::Install()
//
// Install the LDD - overriding pure virtual
//
    {
    return SetName(&KLddName);
    }

void DImpSysTestFactory::GetCaps(TDes8& aDes) const
//
// Get capabilities - overriding pure virtual
//
    {
    TCapsImpSysTestV01 b;
    b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
    Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
    }

DImpSysTest::DImpSysTest()
//
// Constructor
//
	: iTestNum(-1)
    {
    }

TInt DImpSysTest::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
//
// Create channel
//
    {

    if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
    	return KErrNotSupported;
	return KErrNone;
	}

TInt DImpSysTest::Request(TInt aReqNo, TAny* a1, TAny*)
	{
	SStats s;
	TInt r=KErrNotSupported;
	switch (aReqNo)
		{
		case RImpSysTest::EControlStart:
			r=Start((TInt)a1);
			break;
		case RImpSysTest::EControlStop:
			{
			r=Stop(s);
			kumemput32(a1,&s,sizeof(s));
			}
			break;
		default:
			break;
		}
	return r;
	}

#endif


DECLARE_STANDARD_LDD()
	{
#ifdef __SMP__
	return 0;	// not used on SMP
#else
    return new DImpSysTestFactory;
#endif
    }