Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32test\nkernsa\nkutils.cpp
//
//
#include <nktest/nkutils.h>
extern TDfcQue* CleanupDfcQ;
class NThreadX : public NThread
{
public:
NThreadX();
static void KillDfcFn(TAny*);
static TDfc* ExitHandler(NThread* aThread);
static void ExceptionHandler(TAny* aPtr, NThread* aThread);
static void SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC);
public:
TDfc iKillDfc;
TExitFunc iExitFunc;
TAny* iExitParam;
};
extern const SNThreadHandlers ThreadHandlers =
{
&NThreadX::ExitHandler,
NTHREAD_DEFAULT_STATE_HANDLER,
&NThreadX::ExceptionHandler,
0
};
NThreadX::NThreadX()
: iKillDfc(&KillDfcFn, this, 1), iExitFunc(0)
{
}
void NThreadX::KillDfcFn(TAny* a)
{
NThreadX* t = (NThreadX*)a;
TExitFunc f = t->iExitFunc;
TAny* p = t->iExitParam;
if (f)
(*f)(p, t, 1);
#ifdef __SMP__
free((TAny*)t->iNThreadBaseSpare8);
#else
free((TAny*)t->iSpare8);
#endif
free((TAny*)t->iStackBase);
free(t);
if (f)
(*f)(p, t, 2);
}
TDfc* NThreadX::ExitHandler(NThread* aT)
{
NThreadX* t = (NThreadX*)aT;
if (t->iExitFunc)
(*t->iExitFunc)(t->iExitParam, t, 0);
return &t->iKillDfc;
}
extern "C" void ExcFault(TAny*);
void NThreadX::ExceptionHandler(TAny* aPtr, NThread*)
{
NKern::DisableAllInterrupts();
ExcFault(aPtr);
}
extern "C" unsigned int strlen(const char*);
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)
{
__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateThread %s pri %d", aName, aPri));
TInt nlen = (TInt)strlen(aName);
NThreadX* t = new NThreadX;
TAny* stack = malloc(KStackSize);
memset(stack, 0xee, KStackSize);
TAny* namebuf = malloc(nlen+1);
memcpy(namebuf, aName, nlen+1);
__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateThread -> thread at %08x stack %08x", t, stack));
SNThreadCreateInfo info;
info.iFunction = aFunc;
info.iStackBase = stack;
info.iStackSize = KStackSize;
info.iPriority = aPri;
info.iTimeslice = aTimeslice;
info.iAttributes = 0;
info.iHandlers = &ThreadHandlers;
info.iFastExecTable = 0;
info.iSlowExecTable = 0;
info.iParameterBlock = (const TUint32*)aParams;
info.iParameterBlockSize = aPSize;
#ifdef __SMP__
info.iCpuAffinity = aCpuAffinity;
info.iGroup = aGroup;
#endif
TInt r = NKern::ThreadCreate(t, info);
__NK_ASSERT_ALWAYS(r==KErrNone);
#ifdef __SMP__
t->iNThreadBaseSpare8 = (TUint32)namebuf;
#else
t->iSpare8 = (TUint32)namebuf;
#endif
t->iKillDfc.SetDfcQ(CleanupDfcQ);
t->iExitFunc = aExitFunc;
t->iExitParam = aExitParam;
if (aResume)
NKern::ThreadResume(t);
return t;
}
void NThreadX::SignalSemaphoreOnExit(TAny* aP, NThread* aT, TInt aC)
{
NFastSemaphore* s = (NFastSemaphore*)aP;
(void)aT;
if (aC==EAfterFree)
NKern::FSSignal(s);
}
NThread* CreateThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
{
return CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
}
NThread* CreateUnresumedThreadSignalOnExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, NFastSemaphore* aExitSem, TUint32 aCpuAffinity, NThreadGroup* aGroup)
{
return CreateThread(aName, aFunc, aPri, aParams, aPSize, FALSE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, aExitSem, aCpuAffinity, aGroup);
}
void CreateThreadAndWaitForExit(const char* aName, NThreadFunction aFunc, TInt aPri, const TAny* aParams, TInt aPSize, TInt aTimeslice, TUint32 aCpuAffinity, NThreadGroup* aGroup)
{
NFastSemaphore s(0);
CreateThread(aName, aFunc, aPri, aParams, aPSize, TRUE, aTimeslice, &NThreadX::SignalSemaphoreOnExit, &s, aCpuAffinity, aGroup);
NKern::FSWait(&s);
}
TDfcQue* CreateDfcQ(const char* aName, TInt aPri, TUint32 aCpuAffinity, NThreadGroup* aGroup)
{
__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateDfcQ %s pri %d cpu %08x", aName, aPri, aCpuAffinity));
__KTRACE_OPT(KTHREAD,DEBUGPRINT("NKern::CurrentThread() = %08x\n", NKern::CurrentThread()));
TDfcQue* q = new TDfcQue;
__KTRACE_OPT(KTHREAD,DEBUGPRINT("CreateDfcQ -> %08x", q));
NThread* t = CreateThread(aName, &TDfcQue::ThreadFunction, aPri, q, 0, FALSE, KTimeslice, 0, 0, aCpuAffinity, aGroup);
q->iThread = t;
NKern::ThreadResume(t);
return q;
}
void killDfcFn(TAny* aPtr)
{
TDfcQue* q = (TDfcQue*)aPtr;
delete q;
NKern::Exit();
}
void DestroyDfcQ(TDfcQue* aQ)
{
NFastSemaphore exitSem(0);
TDfc killDfc(&killDfcFn, aQ, aQ, 0);
NThreadX* t = (NThreadX*)aQ->iThread;
t->iExitFunc = &NThreadX::SignalSemaphoreOnExit;
t->iExitParam = &exitSem;
killDfc.Enque();
NKern::FSWait(&exitSem);
}
#ifdef __SMP__
class NKTest
{
public:
static TInt FSWait(NFastSemaphore* aS, TUint32 aTimeout);
};
TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
{
return NKTest::FSWait(aS, aTimeout);
}
TInt NKTest::FSWait(NFastSemaphore* aS, TUint32 aTimeout)
{
NThreadBase* pC = NKern::LockC();
pC->iWaitState.SetUpWait(NThreadBase::EWaitFastSemaphore, 0, aS, aTimeout);
if (aS->Dec(pC)) // full barrier
pC->iWaitState.CancelWait(); // don't have to wait
else
RescheduleNeeded(); // have to wait
NKern::PreemptionPoint();
TInt r = pC->iWaitState.iWtC.iRetVal;
NKern::Unlock();
return r;
}
#else
TInt WaitWithTimeout(NFastSemaphore* aS, TUint32 aTimeout)
{
NThreadBase* pC = NKern::LockC();
if (--aS->iCount < 0)
{
NKern::NanoBlock(aTimeout, NThreadBase::EWaitFastSemaphore, aS);
}
NKern::PreemptionPoint();
TInt r = pC->iReturnValue;
if (r == KErrNone)
pC->Release(KErrNone); // cancel the timer on normal completion
NKern::Unlock();
return r;
}
#endif
void FMWaitFull(NFastMutex* aMutex)
{
NKern::Lock();
aMutex->Wait();
NKern::Unlock();
}
void FMSignalFull(NFastMutex* aMutex)
{
NKern::Lock();
aMutex->Signal();
NKern::Unlock();
}
void WaitForRequest(NRequestStatus& aStatus)
{
TInt n = -1;
do {
++n;
NKern::WaitForAnyRequest();
} while (aStatus == KRequestPending);
if (n > 0)
NKern::ThreadRequestSignal(0, n);
}
extern "C" {
void SpinWait(TUint32 aTicks)
{
TUint32 tc = NKern::TickCount() + aTicks;
TUint32 x;
do {
x = NKern::TickCount();
} while (TInt(x-tc)<0);
}
}