--- /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);
+ }
+}
+
+
+
+