kerneltest/e32test/nkernsa/nkutils.cpp
changeset 43 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 43:96e5fb8b040d
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\nkernsa\nkutils.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <nktest/nkutils.h>
       
    19 
       
    20 extern TDfcQue* CleanupDfcQ;
       
    21 
       
    22 class NThreadX : public NThread
       
    23 	{
       
    24 public:
       
    25 	NThreadX();
       
    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);
       
    30 public:
       
    31 	TDfc iKillDfc;
       
    32 	TExitFunc iExitFunc;
       
    33 	TAny* iExitParam;
       
    34 	};
       
    35 
       
    36 extern const SNThreadHandlers ThreadHandlers =
       
    37 	{
       
    38 	&NThreadX::ExitHandler,
       
    39 	NTHREAD_DEFAULT_STATE_HANDLER,
       
    40 	&NThreadX::ExceptionHandler,
       
    41 	0
       
    42 	};
       
    43 
       
    44 NThreadX::NThreadX()
       
    45 	: iKillDfc(&KillDfcFn, this, 1), iExitFunc(0)
       
    46 	{
       
    47 	}
       
    48 
       
    49 void NThreadX::KillDfcFn(TAny* a)
       
    50 	{
       
    51 	NThreadX* t = (NThreadX*)a;
       
    52 	TExitFunc f = t->iExitFunc;
       
    53 	TAny* p = t->iExitParam;
       
    54 	if (f)
       
    55 		(*f)(p, t, 1);
       
    56 #ifdef __SMP__
       
    57 	free((TAny*)t->iNThreadBaseSpare8);
       
    58 #else
       
    59 	free((TAny*)t->iSpare8);
       
    60 #endif
       
    61 	free((TAny*)t->iStackBase);
       
    62 	free(t);
       
    63 	if (f)
       
    64 		(*f)(p, t, 2);
       
    65 	}
       
    66 
       
    67 TDfc* NThreadX::ExitHandler(NThread* aT)
       
    68 	{
       
    69 	NThreadX* t = (NThreadX*)aT;
       
    70 	if (t->iExitFunc)
       
    71 		(*t->iExitFunc)(t->iExitParam, t, 0);
       
    72 	return &t->iKillDfc;
       
    73 	}
       
    74 
       
    75 extern "C" void ExcFault(TAny*);
       
    76 void NThreadX::ExceptionHandler(TAny* aPtr, NThread*)
       
    77 	{
       
    78 	NKern::DisableAllInterrupts();
       
    79 	ExcFault(aPtr);
       
    80 	}
       
    81 
       
    82 extern "C" unsigned int strlen(const char*);
       
    83 
       
    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)
       
    85 	{
       
    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));
       
    94 
       
    95 	SNThreadCreateInfo info;
       
    96 
       
    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;
       
   108 #ifdef __SMP__
       
   109 	info.iCpuAffinity = aCpuAffinity;
       
   110 	info.iGroup = aGroup;
       
   111 #endif
       
   112 
       
   113 	TInt r = NKern::ThreadCreate(t, info);
       
   114 	__NK_ASSERT_ALWAYS(r==KErrNone);
       
   115 #ifdef __SMP__
       
   116 	t->iNThreadBaseSpare8 = (TUint32)namebuf;
       
   117 #else
       
   118 	t->iSpare8 = (TUint32)namebuf;
       
   119 #endif
       
   120 	t->iKillDfc.SetDfcQ(CleanupDfcQ);
       
   121 	t->iExitFunc = aExitFunc;
       
   122 	t->iExitParam = aExitParam;
       
   123 	if (aResume)
       
   124 		NKern::ThreadResume(t);
       
   125 	return t;
       
   126 	}
       
   127 
       
   128 void NThreadX::SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC)
       
   129 	{
       
   130 	NFastSemaphore* s = (NFastSemaphore*)aP;
       
   131 	(void)aT;
       
   132 	if (aC==EAfterFree)
       
   133 		NKern::FSSignal(s);
       
   134 	}
       
   135 
       
   136 NThread* CreateThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
       
   137 	{
       
   138 	return CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
       
   139 	}
       
   140 
       
   141 NThread* CreateUnresumedThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
       
   142 	{
       
   143 	return CreateThread(aName, aFunc, aPri, aParams, aPSize, FALSE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
       
   144 	}
       
   145 
       
   146 void CreateThreadAndWaitForExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, TUint32 aCpuAffinity, NThreadGroup* aGroup)
       
   147 	{
       
   148 	NFastSemaphore s(0);
       
   149 	CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, &s, aCpuAffinity, aGroup);
       
   150 	NKern::FSWait(&s);
       
   151 	}
       
   152 
       
   153 TDfcQue* CreateDfcQ(const char* aName, TInt aPri, TUint32 aCpuAffinity, NThreadGroup* aGroup)
       
   154 	{
       
   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);
       
   160 	q->iThread = t;
       
   161 	NKern::ThreadResume(t);
       
   162 	return q;
       
   163 	}
       
   164 
       
   165 void killDfcFn(TAny* aPtr)
       
   166 	{
       
   167 	TDfcQue* q = (TDfcQue*)aPtr;
       
   168 	delete q;
       
   169 	NKern::Exit();
       
   170 	}
       
   171 
       
   172 void DestroyDfcQ(TDfcQue* aQ)
       
   173 	{
       
   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;
       
   179 	killDfc.Enque();
       
   180 	NKern::FSWait(&exitSem);
       
   181 	}
       
   182 
       
   183 #ifdef __SMP__
       
   184 class NKTest
       
   185 	{
       
   186 public:
       
   187 	static TInt FSWait(NFastSemaphore* aS, TUint32 aTimeout);
       
   188 	};
       
   189 
       
   190 TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
       
   191 	{
       
   192 	return NKTest::FSWait(aS, aTimeout);
       
   193 	}
       
   194 
       
   195 TInt NKTest::FSWait(NFastSemaphore* aS, TUint32 aTimeout)
       
   196 	{
       
   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
       
   201 	else
       
   202 		RescheduleNeeded();				// have to wait
       
   203 	NKern::PreemptionPoint();
       
   204 	TInt r = pC->iWaitState.iWtC.iRetVal;
       
   205 	NKern::Unlock();
       
   206 	return r;
       
   207 	}
       
   208 #else
       
   209 TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
       
   210 	{
       
   211 	NThreadBase* pC = NKern::LockC();
       
   212 	if (--aS->iCount < 0)
       
   213 		{
       
   214 		NKern::NanoBlock(aTimeout, NThreadBase::EWaitFastSemaphore, aS);
       
   215 		}
       
   216 	NKern::PreemptionPoint();
       
   217 	TInt r = pC->iReturnValue;
       
   218 	if (r == KErrNone)
       
   219 		pC->Release(KErrNone);	// cancel the timer on normal completion
       
   220 	NKern::Unlock();
       
   221 	return r;
       
   222 	}
       
   223 #endif
       
   224 
       
   225 void FMWaitFull(NFastMutex* aMutex)
       
   226 	{
       
   227 	NKern::Lock();
       
   228 	aMutex->Wait();
       
   229 	NKern::Unlock();
       
   230 	}
       
   231 
       
   232 void FMSignalFull(NFastMutex* aMutex)
       
   233 	{
       
   234 	NKern::Lock();
       
   235 	aMutex->Signal();
       
   236 	NKern::Unlock();
       
   237 	}
       
   238 
       
   239 void WaitForRequest(NRequestStatus& aStatus)
       
   240 	{
       
   241 	TInt n = -1;
       
   242 	do	{
       
   243 		++n;
       
   244 		NKern::WaitForAnyRequest();
       
   245 		} while (aStatus == KRequestPending);
       
   246 	if (n > 0)
       
   247 		NKern::ThreadRequestSignal(0, n);
       
   248 	}
       
   249 
       
   250 
       
   251 extern "C" {
       
   252 void SpinWait(TUint32 aTicks)
       
   253 	{
       
   254 	TUint32 tc = NKern::TickCount() + aTicks;
       
   255 	TUint32 x;
       
   256 	do	{
       
   257 		x = NKern::TickCount();
       
   258 		} while (TInt(x-tc)<0);
       
   259 	}
       
   260 }
       
   261 
       
   262 
       
   263 
       
   264