kerneltest/e32test/nkernsa/nkutils.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/nkernsa/nkutils.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,264 @@
+// Copyright (c) 2006-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\nkernsa\nkutils.cpp
+// 
+//
+
+#include <nktest/nkutils.h>
+
+extern TDfcQue* CleanupDfcQ;
+
+class NThreadX : public NThread
+	{
+public:
+	NThreadX();
+	static void KillDfcFn(TAny*);
+	static TDfc* ExitHandler(NThread* aThread);
+	static void ExceptionHandler(TAny* aPtr, NThread* aThread);
+	static void SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC);
+public:
+	TDfc iKillDfc;
+	TExitFunc iExitFunc;
+	TAny* iExitParam;
+	};
+
+extern const SNThreadHandlers ThreadHandlers =
+	{
+	&NThreadX::ExitHandler,
+	NTHREAD_DEFAULT_STATE_HANDLER,
+	&NThreadX::ExceptionHandler,
+	0
+	};
+
+NThreadX::NThreadX()
+	: iKillDfc(&KillDfcFn, this, 1), iExitFunc(0)
+	{
+	}
+
+void NThreadX::KillDfcFn(TAny* a)
+	{
+	NThreadX* t = (NThreadX*)a;
+	TExitFunc f = t->iExitFunc;
+	TAny* p = t->iExitParam;
+	if (f)
+		(*f)(p, t, 1);
+#ifdef __SMP__
+	free((TAny*)t->iNThreadBaseSpare8);
+#else
+	free((TAny*)t->iSpare8);
+#endif
+	free((TAny*)t->iStackBase);
+	free(t);
+	if (f)
+		(*f)(p, t, 2);
+	}
+
+TDfc* NThreadX::ExitHandler(NThread* aT)
+	{
+	NThreadX* t = (NThreadX*)aT;
+	if (t->iExitFunc)
+		(*t->iExitFunc)(t->iExitParam, t, 0);
+	return &t->iKillDfc;
+	}
+
+extern "C" void ExcFault(TAny*);
+void NThreadX::ExceptionHandler(TAny* aPtr, NThread*)
+	{
+	NKern::DisableAllInterrupts();
+	ExcFault(aPtr);
+	}
+
+extern "C" unsigned int strlen(const char*);
+
+NThread* CreateThread(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TBool aResume, TInt aTimeslice, TExitFunc aExitFunc, TAny* aExitParam, TUint32 aCpuAffinity, NThreadGroup* aGroup)
+	{
+	__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateThread %s pri %d", aName, aPri));
+	TInt nlen = (TInt)strlen(aName);
+	NThreadX* t = new NThreadX;
+	TAny* stack = malloc(KStackSize);
+	memset(stack, 0xee, KStackSize);
+	TAny* namebuf = malloc(nlen+1);
+	memcpy(namebuf, aName, nlen+1);
+	__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateThread -> thread at %08x stack %08x", t, stack));
+
+	SNThreadCreateInfo info;
+
+	info.iFunction = aFunc;
+	info.iStackBase = stack;
+	info.iStackSize = KStackSize;
+	info.iPriority = aPri;
+	info.iTimeslice = aTimeslice;
+	info.iAttributes = 0;
+	info.iHandlers = &ThreadHandlers;
+	info.iFastExecTable = 0;
+	info.iSlowExecTable = 0;
+	info.iParameterBlock = (const TUint32*)aParams;
+	info.iParameterBlockSize = aPSize;
+#ifdef __SMP__
+	info.iCpuAffinity = aCpuAffinity;
+	info.iGroup = aGroup;
+#endif
+
+	TInt r = NKern::ThreadCreate(t, info);
+	__NK_ASSERT_ALWAYS(r==KErrNone);
+#ifdef __SMP__
+	t->iNThreadBaseSpare8 = (TUint32)namebuf;
+#else
+	t->iSpare8 = (TUint32)namebuf;
+#endif
+	t->iKillDfc.SetDfcQ(CleanupDfcQ);
+	t->iExitFunc = aExitFunc;
+	t->iExitParam = aExitParam;
+	if (aResume)
+		NKern::ThreadResume(t);
+	return t;
+	}
+
+void NThreadX::SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC)
+	{
+	NFastSemaphore* s = (NFastSemaphore*)aP;
+	(void)aT;
+	if (aC==EAfterFree)
+		NKern::FSSignal(s);
+	}
+
+NThread* CreateThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
+	{
+	return CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
+	}
+
+NThread* CreateUnresumedThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
+	{
+	return CreateThread(aName, aFunc, aPri, aParams, aPSize, FALSE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
+	}
+
+void CreateThreadAndWaitForExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, TUint32 aCpuAffinity, NThreadGroup* aGroup)
+	{
+	NFastSemaphore s(0);
+	CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, &s, aCpuAffinity, aGroup);
+	NKern::FSWait(&s);
+	}
+
+TDfcQue* CreateDfcQ(const char* aName, TInt aPri, TUint32 aCpuAffinity, NThreadGroup* aGroup)
+	{
+	__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateDfcQ %s pri %d cpu %08x", aName, aPri, aCpuAffinity));
+	__KTRACE_OPT(KTHREAD,DEBUGPRINT("NKern::CurrentThread() = %08x\n", NKern::CurrentThread()));
+	TDfcQue* q = new TDfcQue;
+	__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateDfcQ -> %08x", q));
+	NThread* t = CreateThread(aName, &TDfcQue::ThreadFunction, aPri, q, 0, FALSE, KTimeslice, 0, 0, aCpuAffinity, aGroup);
+	q->iThread = t;
+	NKern::ThreadResume(t);
+	return q;
+	}
+
+void killDfcFn(TAny* aPtr)
+	{
+	TDfcQue* q = (TDfcQue*)aPtr;
+	delete q;
+	NKern::Exit();
+	}
+
+void DestroyDfcQ(TDfcQue* aQ)
+	{
+	NFastSemaphore exitSem(0);
+	TDfc killDfc(&killDfcFn, aQ, aQ, 0);
+	NThreadX* t = (NThreadX*)aQ->iThread;
+	t->iExitFunc = &NThreadX::SignalSemaphoreOnExit;
+	t->iExitParam = &exitSem;
+	killDfc.Enque();
+	NKern::FSWait(&exitSem);
+	}
+
+#ifdef __SMP__
+class NKTest
+	{
+public:
+	static TInt FSWait(NFastSemaphore* aS, TUint32 aTimeout);
+	};
+
+TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
+	{
+	return NKTest::FSWait(aS, aTimeout);
+	}
+
+TInt NKTest::FSWait(NFastSemaphore* aS, TUint32 aTimeout)
+	{
+	NThreadBase* pC = NKern::LockC();
+	pC->iWaitState.SetUpWait(NThreadBase::EWaitFastSemaphore, 0, aS, aTimeout);
+	if (aS->Dec(pC))					// full barrier
+		pC->iWaitState.CancelWait();	// don't have to wait
+	else
+		RescheduleNeeded();				// have to wait
+	NKern::PreemptionPoint();
+	TInt r = pC->iWaitState.iWtC.iRetVal;
+	NKern::Unlock();
+	return r;
+	}
+#else
+TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
+	{
+	NThreadBase* pC = NKern::LockC();
+	if (--aS->iCount < 0)
+		{
+		NKern::NanoBlock(aTimeout, NThreadBase::EWaitFastSemaphore, aS);
+		}
+	NKern::PreemptionPoint();
+	TInt r = pC->iReturnValue;
+	if (r == KErrNone)
+		pC->Release(KErrNone);	// cancel the timer on normal completion
+	NKern::Unlock();
+	return r;
+	}
+#endif
+
+void FMWaitFull(NFastMutex* aMutex)
+	{
+	NKern::Lock();
+	aMutex->Wait();
+	NKern::Unlock();
+	}
+
+void FMSignalFull(NFastMutex* aMutex)
+	{
+	NKern::Lock();
+	aMutex->Signal();
+	NKern::Unlock();
+	}
+
+void WaitForRequest(NRequestStatus& aStatus)
+	{
+	TInt n = -1;
+	do	{
+		++n;
+		NKern::WaitForAnyRequest();
+		} while (aStatus == KRequestPending);
+	if (n > 0)
+		NKern::ThreadRequestSignal(0, n);
+	}
+
+
+extern "C" {
+void SpinWait(TUint32 aTicks)
+	{
+	TUint32 tc = NKern::TickCount() + aTicks;
+	TUint32 x;
+	do	{
+		x = NKern::TickCount();
+		} while (TInt(x-tc)<0);
+	}
+}
+
+
+
+