diff -r 000000000000 -r 96e5fb8b040d kerneltest/e32test/nkernsa/nkutils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/nkernsa/nkutils.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -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 + +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); + } +} + + + +