os/kernelhwsrv/kerneltest/e32test/nkernsa/nkutils.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
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".
     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