First public contribution.
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\nkernsa\nkutils.cpp
18 #include <nktest/nkutils.h>
20 extern TDfcQue* CleanupDfcQ;
22 class NThreadX : public NThread
26 static void KillDfcFn(TAny*);
27 static TDfc* ExitHandler(NThread* aThread);
28 static void ExceptionHandler(TAny* aPtr, NThread* aThread);
29 static void SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC);
36 extern const SNThreadHandlers ThreadHandlers =
38 &NThreadX::ExitHandler,
39 NTHREAD_DEFAULT_STATE_HANDLER,
40 &NThreadX::ExceptionHandler,
45 : iKillDfc(&KillDfcFn, this, 1), iExitFunc(0)
49 void NThreadX::KillDfcFn(TAny* a)
51 NThreadX* t = (NThreadX*)a;
52 TExitFunc f = t->iExitFunc;
53 TAny* p = t->iExitParam;
57 free((TAny*)t->iNThreadBaseSpare8);
59 free((TAny*)t->iSpare8);
61 free((TAny*)t->iStackBase);
67 TDfc* NThreadX::ExitHandler(NThread* aT)
69 NThreadX* t = (NThreadX*)aT;
71 (*t->iExitFunc)(t->iExitParam, t, 0);
75 extern "C" void ExcFault(TAny*);
76 void NThreadX::ExceptionHandler(TAny* aPtr, NThread*)
78 NKern::DisableAllInterrupts();
82 extern "C" unsigned int strlen(const char*);
84 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)
86 __KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateThread %s pri %d", aName, aPri));
87 TInt nlen = (TInt)strlen(aName);
88 NThreadX* t = new NThreadX;
89 TAny* stack = malloc(KStackSize);
90 memset(stack, 0xee, KStackSize);
91 TAny* namebuf = malloc(nlen+1);
92 memcpy(namebuf, aName, nlen+1);
93 __KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateThread -> thread at %08x stack %08x", t, stack));
95 SNThreadCreateInfo info;
97 info.iFunction = aFunc;
98 info.iStackBase = stack;
99 info.iStackSize = KStackSize;
100 info.iPriority = aPri;
101 info.iTimeslice = aTimeslice;
102 info.iAttributes = 0;
103 info.iHandlers = &ThreadHandlers;
104 info.iFastExecTable = 0;
105 info.iSlowExecTable = 0;
106 info.iParameterBlock = (const TUint32*)aParams;
107 info.iParameterBlockSize = aPSize;
109 info.iCpuAffinity = aCpuAffinity;
110 info.iGroup = aGroup;
113 TInt r = NKern::ThreadCreate(t, info);
114 __NK_ASSERT_ALWAYS(r==KErrNone);
116 t->iNThreadBaseSpare8 = (TUint32)namebuf;
118 t->iSpare8 = (TUint32)namebuf;
120 t->iKillDfc.SetDfcQ(CleanupDfcQ);
121 t->iExitFunc = aExitFunc;
122 t->iExitParam = aExitParam;
124 NKern::ThreadResume(t);
128 void NThreadX::SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC)
130 NFastSemaphore* s = (NFastSemaphore*)aP;
136 NThread* CreateThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
138 return CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
141 NThread* CreateUnresumedThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
143 return CreateThread(aName, aFunc, aPri, aParams, aPSize, FALSE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
146 void CreateThreadAndWaitForExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, TUint32 aCpuAffinity, NThreadGroup* aGroup)
149 CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, &s, aCpuAffinity, aGroup);
153 TDfcQue* CreateDfcQ(const char* aName, TInt aPri, TUint32 aCpuAffinity, NThreadGroup* aGroup)
155 __KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateDfcQ %s pri %d cpu %08x", aName, aPri, aCpuAffinity));
156 __KTRACE_OPT(KTHREAD,DEBUGPRINT("NKern::CurrentThread() = %08x\n", NKern::CurrentThread()));
157 TDfcQue* q = new TDfcQue;
158 __KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateDfcQ -> %08x", q));
159 NThread* t = CreateThread(aName, &TDfcQue::ThreadFunction, aPri, q, 0, FALSE, KTimeslice, 0, 0, aCpuAffinity, aGroup);
161 NKern::ThreadResume(t);
165 void killDfcFn(TAny* aPtr)
167 TDfcQue* q = (TDfcQue*)aPtr;
172 void DestroyDfcQ(TDfcQue* aQ)
174 NFastSemaphore exitSem(0);
175 TDfc killDfc(&killDfcFn, aQ, aQ, 0);
176 NThreadX* t = (NThreadX*)aQ->iThread;
177 t->iExitFunc = &NThreadX::SignalSemaphoreOnExit;
178 t->iExitParam = &exitSem;
180 NKern::FSWait(&exitSem);
187 static TInt FSWait(NFastSemaphore* aS, TUint32 aTimeout);
190 TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
192 return NKTest::FSWait(aS, aTimeout);
195 TInt NKTest::FSWait(NFastSemaphore* aS, TUint32 aTimeout)
197 NThreadBase* pC = NKern::LockC();
198 pC->iWaitState.SetUpWait(NThreadBase::EWaitFastSemaphore, 0, aS, aTimeout);
199 if (aS->Dec(pC)) // full barrier
200 pC->iWaitState.CancelWait(); // don't have to wait
202 RescheduleNeeded(); // have to wait
203 NKern::PreemptionPoint();
204 TInt r = pC->iWaitState.iWtC.iRetVal;
209 TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
211 NThreadBase* pC = NKern::LockC();
212 if (--aS->iCount < 0)
214 NKern::NanoBlock(aTimeout, NThreadBase::EWaitFastSemaphore, aS);
216 NKern::PreemptionPoint();
217 TInt r = pC->iReturnValue;
219 pC->Release(KErrNone); // cancel the timer on normal completion
225 void FMWaitFull(NFastMutex* aMutex)
232 void FMSignalFull(NFastMutex* aMutex)
239 void WaitForRequest(NRequestStatus& aStatus)
244 NKern::WaitForAnyRequest();
245 } while (aStatus == KRequestPending);
247 NKern::ThreadRequestSignal(0, n);
252 void SpinWait(TUint32 aTicks)
254 TUint32 tc = NKern::TickCount() + aTicks;
257 x = NKern::TickCount();
258 } while (TInt(x-tc)<0);