os/kernelhwsrv/kerneltest/e32test/nkernsa/nkutils.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32test\nkernsa\nkutils.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include <nktest/nkutils.h>
sl@0
    19
sl@0
    20
extern TDfcQue* CleanupDfcQ;
sl@0
    21
sl@0
    22
class NThreadX : public NThread
sl@0
    23
	{
sl@0
    24
public:
sl@0
    25
	NThreadX();
sl@0
    26
	static void KillDfcFn(TAny*);
sl@0
    27
	static TDfc* ExitHandler(NThread* aThread);
sl@0
    28
	static void ExceptionHandler(TAny* aPtr, NThread* aThread);
sl@0
    29
	static void SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC);
sl@0
    30
public:
sl@0
    31
	TDfc iKillDfc;
sl@0
    32
	TExitFunc iExitFunc;
sl@0
    33
	TAny* iExitParam;
sl@0
    34
	};
sl@0
    35
sl@0
    36
extern const SNThreadHandlers ThreadHandlers =
sl@0
    37
	{
sl@0
    38
	&NThreadX::ExitHandler,
sl@0
    39
	NTHREAD_DEFAULT_STATE_HANDLER,
sl@0
    40
	&NThreadX::ExceptionHandler,
sl@0
    41
	0
sl@0
    42
	};
sl@0
    43
sl@0
    44
NThreadX::NThreadX()
sl@0
    45
	: iKillDfc(&KillDfcFn, this, 1), iExitFunc(0)
sl@0
    46
	{
sl@0
    47
	}
sl@0
    48
sl@0
    49
void NThreadX::KillDfcFn(TAny* a)
sl@0
    50
	{
sl@0
    51
	NThreadX* t = (NThreadX*)a;
sl@0
    52
	TExitFunc f = t->iExitFunc;
sl@0
    53
	TAny* p = t->iExitParam;
sl@0
    54
	if (f)
sl@0
    55
		(*f)(p, t, 1);
sl@0
    56
#ifdef __SMP__
sl@0
    57
	free((TAny*)t->iNThreadBaseSpare8);
sl@0
    58
#else
sl@0
    59
	free((TAny*)t->iSpare8);
sl@0
    60
#endif
sl@0
    61
	free((TAny*)t->iStackBase);
sl@0
    62
	free(t);
sl@0
    63
	if (f)
sl@0
    64
		(*f)(p, t, 2);
sl@0
    65
	}
sl@0
    66
sl@0
    67
TDfc* NThreadX::ExitHandler(NThread* aT)
sl@0
    68
	{
sl@0
    69
	NThreadX* t = (NThreadX*)aT;
sl@0
    70
	if (t->iExitFunc)
sl@0
    71
		(*t->iExitFunc)(t->iExitParam, t, 0);
sl@0
    72
	return &t->iKillDfc;
sl@0
    73
	}
sl@0
    74
sl@0
    75
extern "C" void ExcFault(TAny*);
sl@0
    76
void NThreadX::ExceptionHandler(TAny* aPtr, NThread*)
sl@0
    77
	{
sl@0
    78
	NKern::DisableAllInterrupts();
sl@0
    79
	ExcFault(aPtr);
sl@0
    80
	}
sl@0
    81
sl@0
    82
extern "C" unsigned int strlen(const char*);
sl@0
    83
sl@0
    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)
sl@0
    85
	{
sl@0
    86
	__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateThread %s pri %d", aName, aPri));
sl@0
    87
	TInt nlen = (TInt)strlen(aName);
sl@0
    88
	NThreadX* t = new NThreadX;
sl@0
    89
	TAny* stack = malloc(KStackSize);
sl@0
    90
	memset(stack, 0xee, KStackSize);
sl@0
    91
	TAny* namebuf = malloc(nlen+1);
sl@0
    92
	memcpy(namebuf, aName, nlen+1);
sl@0
    93
	__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateThread -> thread at %08x stack %08x", t, stack));
sl@0
    94
sl@0
    95
	SNThreadCreateInfo info;
sl@0
    96
sl@0
    97
	info.iFunction = aFunc;
sl@0
    98
	info.iStackBase = stack;
sl@0
    99
	info.iStackSize = KStackSize;
sl@0
   100
	info.iPriority = aPri;
sl@0
   101
	info.iTimeslice = aTimeslice;
sl@0
   102
	info.iAttributes = 0;
sl@0
   103
	info.iHandlers = &ThreadHandlers;
sl@0
   104
	info.iFastExecTable = 0;
sl@0
   105
	info.iSlowExecTable = 0;
sl@0
   106
	info.iParameterBlock = (const TUint32*)aParams;
sl@0
   107
	info.iParameterBlockSize = aPSize;
sl@0
   108
#ifdef __SMP__
sl@0
   109
	info.iCpuAffinity = aCpuAffinity;
sl@0
   110
	info.iGroup = aGroup;
sl@0
   111
#endif
sl@0
   112
sl@0
   113
	TInt r = NKern::ThreadCreate(t, info);
sl@0
   114
	__NK_ASSERT_ALWAYS(r==KErrNone);
sl@0
   115
#ifdef __SMP__
sl@0
   116
	t->iNThreadBaseSpare8 = (TUint32)namebuf;
sl@0
   117
#else
sl@0
   118
	t->iSpare8 = (TUint32)namebuf;
sl@0
   119
#endif
sl@0
   120
	t->iKillDfc.SetDfcQ(CleanupDfcQ);
sl@0
   121
	t->iExitFunc = aExitFunc;
sl@0
   122
	t->iExitParam = aExitParam;
sl@0
   123
	if (aResume)
sl@0
   124
		NKern::ThreadResume(t);
sl@0
   125
	return t;
sl@0
   126
	}
sl@0
   127
sl@0
   128
void NThreadX::SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC)
sl@0
   129
	{
sl@0
   130
	NFastSemaphore* s = (NFastSemaphore*)aP;
sl@0
   131
	(void)aT;
sl@0
   132
	if (aC==EAfterFree)
sl@0
   133
		NKern::FSSignal(s);
sl@0
   134
	}
sl@0
   135
sl@0
   136
NThread* CreateThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
sl@0
   137
	{
sl@0
   138
	return CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
sl@0
   139
	}
sl@0
   140
sl@0
   141
NThread* CreateUnresumedThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
sl@0
   142
	{
sl@0
   143
	return CreateThread(aName, aFunc, aPri, aParams, aPSize, FALSE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
sl@0
   144
	}
sl@0
   145
sl@0
   146
void CreateThreadAndWaitForExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, TUint32 aCpuAffinity, NThreadGroup* aGroup)
sl@0
   147
	{
sl@0
   148
	NFastSemaphore s(0);
sl@0
   149
	CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, &s, aCpuAffinity, aGroup);
sl@0
   150
	NKern::FSWait(&s);
sl@0
   151
	}
sl@0
   152
sl@0
   153
TDfcQue* CreateDfcQ(const char* aName, TInt aPri, TUint32 aCpuAffinity, NThreadGroup* aGroup)
sl@0
   154
	{
sl@0
   155
	__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateDfcQ %s pri %d cpu %08x", aName, aPri, aCpuAffinity));
sl@0
   156
	__KTRACE_OPT(KTHREAD,DEBUGPRINT("NKern::CurrentThread() = %08x\n", NKern::CurrentThread()));
sl@0
   157
	TDfcQue* q = new TDfcQue;
sl@0
   158
	__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateDfcQ -> %08x", q));
sl@0
   159
	NThread* t = CreateThread(aName, &TDfcQue::ThreadFunction, aPri, q, 0, FALSE, KTimeslice, 0, 0, aCpuAffinity, aGroup);
sl@0
   160
	q->iThread = t;
sl@0
   161
	NKern::ThreadResume(t);
sl@0
   162
	return q;
sl@0
   163
	}
sl@0
   164
sl@0
   165
void killDfcFn(TAny* aPtr)
sl@0
   166
	{
sl@0
   167
	TDfcQue* q = (TDfcQue*)aPtr;
sl@0
   168
	delete q;
sl@0
   169
	NKern::Exit();
sl@0
   170
	}
sl@0
   171
sl@0
   172
void DestroyDfcQ(TDfcQue* aQ)
sl@0
   173
	{
sl@0
   174
	NFastSemaphore exitSem(0);
sl@0
   175
	TDfc killDfc(&killDfcFn, aQ, aQ, 0);
sl@0
   176
	NThreadX* t = (NThreadX*)aQ->iThread;
sl@0
   177
	t->iExitFunc = &NThreadX::SignalSemaphoreOnExit;
sl@0
   178
	t->iExitParam = &exitSem;
sl@0
   179
	killDfc.Enque();
sl@0
   180
	NKern::FSWait(&exitSem);
sl@0
   181
	}
sl@0
   182
sl@0
   183
#ifdef __SMP__
sl@0
   184
class NKTest
sl@0
   185
	{
sl@0
   186
public:
sl@0
   187
	static TInt FSWait(NFastSemaphore* aS, TUint32 aTimeout);
sl@0
   188
	};
sl@0
   189
sl@0
   190
TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
sl@0
   191
	{
sl@0
   192
	return NKTest::FSWait(aS, aTimeout);
sl@0
   193
	}
sl@0
   194
sl@0
   195
TInt NKTest::FSWait(NFastSemaphore* aS, TUint32 aTimeout)
sl@0
   196
	{
sl@0
   197
	NThreadBase* pC = NKern::LockC();
sl@0
   198
	pC->iWaitState.SetUpWait(NThreadBase::EWaitFastSemaphore, 0, aS, aTimeout);
sl@0
   199
	if (aS->Dec(pC))					// full barrier
sl@0
   200
		pC->iWaitState.CancelWait();	// don't have to wait
sl@0
   201
	else
sl@0
   202
		RescheduleNeeded();				// have to wait
sl@0
   203
	NKern::PreemptionPoint();
sl@0
   204
	TInt r = pC->iWaitState.iWtC.iRetVal;
sl@0
   205
	NKern::Unlock();
sl@0
   206
	return r;
sl@0
   207
	}
sl@0
   208
#else
sl@0
   209
TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
sl@0
   210
	{
sl@0
   211
	NThreadBase* pC = NKern::LockC();
sl@0
   212
	if (--aS->iCount < 0)
sl@0
   213
		{
sl@0
   214
		NKern::NanoBlock(aTimeout, NThreadBase::EWaitFastSemaphore, aS);
sl@0
   215
		}
sl@0
   216
	NKern::PreemptionPoint();
sl@0
   217
	TInt r = pC->iReturnValue;
sl@0
   218
	if (r == KErrNone)
sl@0
   219
		pC->Release(KErrNone);	// cancel the timer on normal completion
sl@0
   220
	NKern::Unlock();
sl@0
   221
	return r;
sl@0
   222
	}
sl@0
   223
#endif
sl@0
   224
sl@0
   225
void FMWaitFull(NFastMutex* aMutex)
sl@0
   226
	{
sl@0
   227
	NKern::Lock();
sl@0
   228
	aMutex->Wait();
sl@0
   229
	NKern::Unlock();
sl@0
   230
	}
sl@0
   231
sl@0
   232
void FMSignalFull(NFastMutex* aMutex)
sl@0
   233
	{
sl@0
   234
	NKern::Lock();
sl@0
   235
	aMutex->Signal();
sl@0
   236
	NKern::Unlock();
sl@0
   237
	}
sl@0
   238
sl@0
   239
void WaitForRequest(NRequestStatus& aStatus)
sl@0
   240
	{
sl@0
   241
	TInt n = -1;
sl@0
   242
	do	{
sl@0
   243
		++n;
sl@0
   244
		NKern::WaitForAnyRequest();
sl@0
   245
		} while (aStatus == KRequestPending);
sl@0
   246
	if (n > 0)
sl@0
   247
		NKern::ThreadRequestSignal(0, n);
sl@0
   248
	}
sl@0
   249
sl@0
   250
sl@0
   251
extern "C" {
sl@0
   252
void SpinWait(TUint32 aTicks)
sl@0
   253
	{
sl@0
   254
	TUint32 tc = NKern::TickCount() + aTicks;
sl@0
   255
	TUint32 x;
sl@0
   256
	do	{
sl@0
   257
		x = NKern::TickCount();
sl@0
   258
		} while (TInt(x-tc)<0);
sl@0
   259
	}
sl@0
   260
}
sl@0
   261
sl@0
   262
sl@0
   263
sl@0
   264