1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/nkernsa/nkutils.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,264 @@
1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\nkernsa\nkutils.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include <nktest/nkutils.h>
1.22 +
1.23 +extern TDfcQue* CleanupDfcQ;
1.24 +
1.25 +class NThreadX : public NThread
1.26 + {
1.27 +public:
1.28 + NThreadX();
1.29 + static void KillDfcFn(TAny*);
1.30 + static TDfc* ExitHandler(NThread* aThread);
1.31 + static void ExceptionHandler(TAny* aPtr, NThread* aThread);
1.32 + static void SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC);
1.33 +public:
1.34 + TDfc iKillDfc;
1.35 + TExitFunc iExitFunc;
1.36 + TAny* iExitParam;
1.37 + };
1.38 +
1.39 +extern const SNThreadHandlers ThreadHandlers =
1.40 + {
1.41 + &NThreadX::ExitHandler,
1.42 + NTHREAD_DEFAULT_STATE_HANDLER,
1.43 + &NThreadX::ExceptionHandler,
1.44 + 0
1.45 + };
1.46 +
1.47 +NThreadX::NThreadX()
1.48 + : iKillDfc(&KillDfcFn, this, 1), iExitFunc(0)
1.49 + {
1.50 + }
1.51 +
1.52 +void NThreadX::KillDfcFn(TAny* a)
1.53 + {
1.54 + NThreadX* t = (NThreadX*)a;
1.55 + TExitFunc f = t->iExitFunc;
1.56 + TAny* p = t->iExitParam;
1.57 + if (f)
1.58 + (*f)(p, t, 1);
1.59 +#ifdef __SMP__
1.60 + free((TAny*)t->iNThreadBaseSpare8);
1.61 +#else
1.62 + free((TAny*)t->iSpare8);
1.63 +#endif
1.64 + free((TAny*)t->iStackBase);
1.65 + free(t);
1.66 + if (f)
1.67 + (*f)(p, t, 2);
1.68 + }
1.69 +
1.70 +TDfc* NThreadX::ExitHandler(NThread* aT)
1.71 + {
1.72 + NThreadX* t = (NThreadX*)aT;
1.73 + if (t->iExitFunc)
1.74 + (*t->iExitFunc)(t->iExitParam, t, 0);
1.75 + return &t->iKillDfc;
1.76 + }
1.77 +
1.78 +extern "C" void ExcFault(TAny*);
1.79 +void NThreadX::ExceptionHandler(TAny* aPtr, NThread*)
1.80 + {
1.81 + NKern::DisableAllInterrupts();
1.82 + ExcFault(aPtr);
1.83 + }
1.84 +
1.85 +extern "C" unsigned int strlen(const char*);
1.86 +
1.87 +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)
1.88 + {
1.89 + __KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateThread %s pri %d", aName, aPri));
1.90 + TInt nlen = (TInt)strlen(aName);
1.91 + NThreadX* t = new NThreadX;
1.92 + TAny* stack = malloc(KStackSize);
1.93 + memset(stack, 0xee, KStackSize);
1.94 + TAny* namebuf = malloc(nlen+1);
1.95 + memcpy(namebuf, aName, nlen+1);
1.96 + __KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateThread -> thread at %08x stack %08x", t, stack));
1.97 +
1.98 + SNThreadCreateInfo info;
1.99 +
1.100 + info.iFunction = aFunc;
1.101 + info.iStackBase = stack;
1.102 + info.iStackSize = KStackSize;
1.103 + info.iPriority = aPri;
1.104 + info.iTimeslice = aTimeslice;
1.105 + info.iAttributes = 0;
1.106 + info.iHandlers = &ThreadHandlers;
1.107 + info.iFastExecTable = 0;
1.108 + info.iSlowExecTable = 0;
1.109 + info.iParameterBlock = (const TUint32*)aParams;
1.110 + info.iParameterBlockSize = aPSize;
1.111 +#ifdef __SMP__
1.112 + info.iCpuAffinity = aCpuAffinity;
1.113 + info.iGroup = aGroup;
1.114 +#endif
1.115 +
1.116 + TInt r = NKern::ThreadCreate(t, info);
1.117 + __NK_ASSERT_ALWAYS(r==KErrNone);
1.118 +#ifdef __SMP__
1.119 + t->iNThreadBaseSpare8 = (TUint32)namebuf;
1.120 +#else
1.121 + t->iSpare8 = (TUint32)namebuf;
1.122 +#endif
1.123 + t->iKillDfc.SetDfcQ(CleanupDfcQ);
1.124 + t->iExitFunc = aExitFunc;
1.125 + t->iExitParam = aExitParam;
1.126 + if (aResume)
1.127 + NKern::ThreadResume(t);
1.128 + return t;
1.129 + }
1.130 +
1.131 +void NThreadX::SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC)
1.132 + {
1.133 + NFastSemaphore* s = (NFastSemaphore*)aP;
1.134 + (void)aT;
1.135 + if (aC==EAfterFree)
1.136 + NKern::FSSignal(s);
1.137 + }
1.138 +
1.139 +NThread* CreateThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
1.140 + {
1.141 + return CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
1.142 + }
1.143 +
1.144 +NThread* CreateUnresumedThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
1.145 + {
1.146 + return CreateThread(aName, aFunc, aPri, aParams, aPSize, FALSE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
1.147 + }
1.148 +
1.149 +void CreateThreadAndWaitForExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, TUint32 aCpuAffinity, NThreadGroup* aGroup)
1.150 + {
1.151 + NFastSemaphore s(0);
1.152 + CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, &s, aCpuAffinity, aGroup);
1.153 + NKern::FSWait(&s);
1.154 + }
1.155 +
1.156 +TDfcQue* CreateDfcQ(const char* aName, TInt aPri, TUint32 aCpuAffinity, NThreadGroup* aGroup)
1.157 + {
1.158 + __KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateDfcQ %s pri %d cpu %08x", aName, aPri, aCpuAffinity));
1.159 + __KTRACE_OPT(KTHREAD,DEBUGPRINT("NKern::CurrentThread() = %08x\n", NKern::CurrentThread()));
1.160 + TDfcQue* q = new TDfcQue;
1.161 + __KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateDfcQ -> %08x", q));
1.162 + NThread* t = CreateThread(aName, &TDfcQue::ThreadFunction, aPri, q, 0, FALSE, KTimeslice, 0, 0, aCpuAffinity, aGroup);
1.163 + q->iThread = t;
1.164 + NKern::ThreadResume(t);
1.165 + return q;
1.166 + }
1.167 +
1.168 +void killDfcFn(TAny* aPtr)
1.169 + {
1.170 + TDfcQue* q = (TDfcQue*)aPtr;
1.171 + delete q;
1.172 + NKern::Exit();
1.173 + }
1.174 +
1.175 +void DestroyDfcQ(TDfcQue* aQ)
1.176 + {
1.177 + NFastSemaphore exitSem(0);
1.178 + TDfc killDfc(&killDfcFn, aQ, aQ, 0);
1.179 + NThreadX* t = (NThreadX*)aQ->iThread;
1.180 + t->iExitFunc = &NThreadX::SignalSemaphoreOnExit;
1.181 + t->iExitParam = &exitSem;
1.182 + killDfc.Enque();
1.183 + NKern::FSWait(&exitSem);
1.184 + }
1.185 +
1.186 +#ifdef __SMP__
1.187 +class NKTest
1.188 + {
1.189 +public:
1.190 + static TInt FSWait(NFastSemaphore* aS, TUint32 aTimeout);
1.191 + };
1.192 +
1.193 +TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
1.194 + {
1.195 + return NKTest::FSWait(aS, aTimeout);
1.196 + }
1.197 +
1.198 +TInt NKTest::FSWait(NFastSemaphore* aS, TUint32 aTimeout)
1.199 + {
1.200 + NThreadBase* pC = NKern::LockC();
1.201 + pC->iWaitState.SetUpWait(NThreadBase::EWaitFastSemaphore, 0, aS, aTimeout);
1.202 + if (aS->Dec(pC)) // full barrier
1.203 + pC->iWaitState.CancelWait(); // don't have to wait
1.204 + else
1.205 + RescheduleNeeded(); // have to wait
1.206 + NKern::PreemptionPoint();
1.207 + TInt r = pC->iWaitState.iWtC.iRetVal;
1.208 + NKern::Unlock();
1.209 + return r;
1.210 + }
1.211 +#else
1.212 +TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
1.213 + {
1.214 + NThreadBase* pC = NKern::LockC();
1.215 + if (--aS->iCount < 0)
1.216 + {
1.217 + NKern::NanoBlock(aTimeout, NThreadBase::EWaitFastSemaphore, aS);
1.218 + }
1.219 + NKern::PreemptionPoint();
1.220 + TInt r = pC->iReturnValue;
1.221 + if (r == KErrNone)
1.222 + pC->Release(KErrNone); // cancel the timer on normal completion
1.223 + NKern::Unlock();
1.224 + return r;
1.225 + }
1.226 +#endif
1.227 +
1.228 +void FMWaitFull(NFastMutex* aMutex)
1.229 + {
1.230 + NKern::Lock();
1.231 + aMutex->Wait();
1.232 + NKern::Unlock();
1.233 + }
1.234 +
1.235 +void FMSignalFull(NFastMutex* aMutex)
1.236 + {
1.237 + NKern::Lock();
1.238 + aMutex->Signal();
1.239 + NKern::Unlock();
1.240 + }
1.241 +
1.242 +void WaitForRequest(NRequestStatus& aStatus)
1.243 + {
1.244 + TInt n = -1;
1.245 + do {
1.246 + ++n;
1.247 + NKern::WaitForAnyRequest();
1.248 + } while (aStatus == KRequestPending);
1.249 + if (n > 0)
1.250 + NKern::ThreadRequestSignal(0, n);
1.251 + }
1.252 +
1.253 +
1.254 +extern "C" {
1.255 +void SpinWait(TUint32 aTicks)
1.256 + {
1.257 + TUint32 tc = NKern::TickCount() + aTicks;
1.258 + TUint32 x;
1.259 + do {
1.260 + x = NKern::TickCount();
1.261 + } while (TInt(x-tc)<0);
1.262 + }
1.263 +}
1.264 +
1.265 +
1.266 +
1.267 +