diff -r 000000000000 -r a41df078684a kernel/eka/include/nkernsmp/nk_priv.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/include/nkernsmp/nk_priv.h Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,871 @@ +// Copyright (c) 2007-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: +// e32\include\nkernsmp\nk_priv.h +// +// WARNING: This file contains some APIs which are internal and are subject +// to change without notice. Such APIs should therefore not be used +// outside the Kernel and Hardware Services package. +// + +#ifndef __NK_PRIV_H__ +#define __NK_PRIV_H__ +#include +#include + +#define __USE_BTRACE_LOCK__ + +class Monitor; + +/******************************************** + * Schedulable = thread or thread group + ********************************************/ + +/** +@publishedPartner +@prototype + +Base class for a nanokernel thread or group +*/ +class NThreadGroup; +class NSchedulable : public TPriListLink + { +public: + enum + { + EReadyGroup=1, + EReadyCpuMask=0x7f, + EReadyOffset=0x80, + }; + + enum NReadyFlags + { + ENewTimeslice=1, + EPreferSameCpu=2, + EUnPause=4, + }; + + enum NEventState + { + EEventCountShift=16u, + EEventCountMask=0xffff0000u, + EEventCountInc=0x10000u, + EEventCpuShift=0u, + EEventCpuMask=0x1fu, + EThreadCpuShift=8u, + EThreadCpuMask=0x1f00u, + EDeferredReady=0x4000u, + EEventParent=0x8000u, + }; +public: + NSchedulable(); + void AcqSLock(); + void RelSLock(); + void LAcqSLock(); + void RelSLockU(); + void ReadyT(TUint aMode); // make ready, assumes lock held + TInt BeginTiedEvent(); + void EndTiedEvent(); + TInt AddTiedEvent(NEventHandler* aEvent); + TBool TiedEventReadyInterlock(TInt aCpu); + void UnPauseT(); // decrement pause count and make ready if necessary + static void DeferredReadyIDfcFn(TAny*); + void DetachTiedEvents(); +public: + inline TBool IsGroup() {return !iParent;} + inline TBool IsLoneThread() {return iParent==this;} + inline TBool IsGroupThread() {return iParent && iParent!=this;} +public: +// TUint8 iReady; /**< @internalComponent */ // flag indicating thread on ready list = cpu number | EReadyOffset +// TUint8 iCurrent; /**< @internalComponent */ // flag indicating thread is running +// TUint8 iLastCpu; /**< @internalComponent */ // CPU on which this thread last ran + TUint8 iPauseCount; /**< @internalComponent */ // count of externally requested pauses extending a voluntary wait + TUint8 iSuspended; /**< @internalComponent */ // flag indicating active external suspend (Not used for groups) + TUint8 iNSchedulableSpare1; /**< @internalComponent */ + TUint8 iNSchedulableSpare2; /**< @internalComponent */ + + TUint8 iCpuChange; /**< @internalComponent */ // flag showing CPU migration outstanding + TUint8 iStopping; /**< @internalComponent */ // thread is exiting, thread group is being destroyed + TUint16 iFreezeCpu; /**< @internalComponent */ // flag set if CPU frozen - count for groups + NSchedulable* iParent; /**< @internalComponent */ // Pointer to group containing thread, =this for normal thread, =0 for group + + TUint32 iCpuAffinity; /**< @internalComponent */ + volatile TUint32 iEventState; /**< @internalComponent */ // bits 16-31=count, 0-4=event CPU, 5-9=thread CPU, 10=defer, 11=parent + + TSpinLock iSSpinLock; /**< @internalComponent */ + + SDblQue iEvents; /**< @internalComponent */ // doubly-linked list of tied events + + TUint32 i_IDfcMem[sizeof(TDfc)/sizeof(TUint32)]; /**< @internalComponent */ // IDFC used to make thread ready after last tied event completes +// TDfc iDeferredReadyIDfc; /**< @internalComponent */ // IDFC used to make thread ready after last tied event completes + + union + { + TUint64 iRunCount64; + TUint32 iRunCount32[2]; + }; + union + { + TUint64 iTotalCpuTime64; /**< @internalComponent */ // total time spent running, in hi-res timer ticks + TUint32 iTotalCpuTime32[2]; /**< @internalComponent */ // total time spent running, in hi-res timer ticks + }; + }; + +__ASSERT_COMPILE(!(_FOFF(NSchedulable,iSSpinLock)&7)); +__ASSERT_COMPILE(!(_FOFF(NSchedulable,iRunCount64)&7)); +__ASSERT_COMPILE(!(_FOFF(NSchedulable,iTotalCpuTime64)&7)); +__ASSERT_COMPILE(!(sizeof(NSchedulable)&7)); + + +/** +@internalComponent +*/ +inline TBool TDfc::IsValid() + { + if (iHType < KNumDfcPriorities) + return TRUE; + if (iHType != EEventHandlerIDFC) + return FALSE; + return !iTied || !iTied->iStopping; + } + +/******************************************** + * Thread + ********************************************/ + +/** +@internalComponent +*/ +class NThreadWaitState + { +private: + enum TWtStFlags + { + EWtStWaitPending =0x01u, // thread is about to wait + EWtStWaitActive =0x02u, // thread is actually blocked + EWtStTimeout =0x04u, // timeout is active on this wait + EWtStObstructed =0x08u, // wait is due to obstruction (e.g. mutex) rather than lack of work to do + EWtStDead =0x80u, // thread is dead + }; +private: + NThreadWaitState(); + void SetUpWait(TUint aType, TUint aFlags, TAny* aWaitObj); + void SetUpWait(TUint aType, TUint aFlags, TAny* aWaitObj, TUint32 aTimeout); + void SetDead(TDfc* aKillDfc); + void CancelWait(); + TInt DoWait(); + static void TimerExpired(TAny*); + TInt UnBlockT(TUint aType, TAny* aWaitObj, TInt aReturnValue); + TUint32 ReleaseT(TAny*& aWaitObj, TInt aReturnValue); + void CancelTimerT(); +private: + inline NThreadBase* Thread(); + inline TBool WaitPending() + { return iWtC.iWtStFlags & (EWtStWaitPending|EWtStDead); } + inline TBool ThreadIsBlocked() + { return iWtC.iWtStFlags & (EWtStWaitActive|EWtStDead); } + inline TBool ThreadIsDead() + { return iWtC.iWtStFlags & EWtStDead; } +private: + struct S + { + volatile TUint8 iWtStFlags; + volatile TUint8 iWtObjType; + volatile TUint8 iWtStSpare1; + volatile TUint8 iWtStSpare2; + union + { + TAny* volatile iWtObj; + volatile TInt iRetVal; + TDfc* volatile iKillDfc; + }; + }; + union + { + S iWtC; + volatile TUint32 iWtSt32[2]; + volatile TUint64 iWtSt64; + }; + NTimer iTimer; +private: + friend class NSchedulable; + friend class NThreadBase; + friend class NThread; + friend class TScheduler; + friend class TSubScheduler; + friend class TDfc; + friend class TDfcQue; + friend class NFastSemaphore; + friend class NFastMutex; + friend class NTimer; + friend class NTimerQ; + friend class NKern; + friend class Monitor; + friend class NKTest; + }; + +/** +@publishedPartner +@prototype + +Base class for a nanokernel thread. +*/ +class TSubScheduler; +class NThreadBase : public NSchedulable + { +public: + /** + Defines the possible types of wait object + */ + enum NThreadWaitType + { + EWaitNone, + EWaitFastSemaphore, + EWaitFastMutex, + EWaitSleep, + EWaitBlocked, + EWaitDfc, + + ENumWaitTypes + }; + + + /** + @internalComponent + */ + enum NThreadCSFunction + { + ECSExitPending=-1, + ECSExitInProgress=-2, + ECSDivertPending=-3, + }; + + /** + @internalComponent + */ + enum NThreadTimeoutOp + { + ETimeoutPreamble=0, + ETimeoutPostamble=1, + ETimeoutSpurious=2, + }; +public: + NThreadBase(); + TInt Create(SNThreadCreateInfo& anInfo, TBool aInitial); + void UnReadyT(); + TBool SuspendOrKill(TInt aCount); + TBool DoSuspendOrKillT(TInt aCount, TSubScheduler* aS); + TBool CancelTimerT(); + void DoReleaseT(TInt aReturnCode, TUint aMode); + TBool CheckFastMutexDefer(); + void DoCsFunctionT(); + TBool Resume(TBool aForce); + IMPORT_C TBool Suspend(TInt aCount); /**< @internalComponent */ + IMPORT_C TBool Resume(); /**< @internalComponent */ + IMPORT_C TBool ForceResume(); /**< @internalComponent */ + IMPORT_C void Release(TInt aReturnCode, TUint aMode); /**< @internalComponent */ + IMPORT_C void RequestSignal(); /**< @internalComponent */ + IMPORT_C void SetPriority(TInt aPriority); /**< @internalComponent */ + void SetMutexPriority(NFastMutex* aMutex); + void LoseInheritedPriorityT(); + void ChangeReadyThreadPriority(); + TUint32 SetCpuAffinity(TUint32 aAffinity); + TBool TiedEventLeaveInterlock(); + TBool TiedEventJoinInterlock(); + IMPORT_C void Kill(); /**< @internalComponent */ + void Exit(); + // hooks for platform-specific code + void OnKill(); + void OnExit(); +public: + static void TimerExpired(TAny* aPtr); + + /** @internalComponent */ + inline void UnknownState(TInt aOp, TInt aParam) + { (*iHandlers->iStateHandler)((NThread*)this,aOp,aParam); } + + /** @internalComponent */ + inline TUint8 Attributes() + { return i_ThrdAttr; } + + /** @internalComponent */ + inline TUint8 SetAttributes(TUint8 aNewAtt) + { return __e32_atomic_swp_ord8(&i_ThrdAttr, aNewAtt); } + + /** @internalComponent */ + inline TUint8 ModifyAttributes(TUint8 aClearMask, TUint8 aSetMask) + { return __e32_atomic_axo_ord8(&i_ThrdAttr, (TUint8)~(aClearMask|aSetMask), aSetMask); } + + /** @internalComponent */ + inline void SetAddressSpace(TAny* a) + { iAddressSpace=a; } + + /** @internalComponent */ + inline void SetExtraContext(TAny* a, TInt aSize) + { iExtraContext = a; iExtraContextSize = aSize; } + + /** @internalTechnology */ + inline TBool IsDead() + { return iWaitState.ThreadIsDead(); } +public: + TPriListLink iWaitLink; /**< @internalComponent */ // used to link thread into a wait queue +// TUint8 iBasePri; /**< @internalComponent */ // priority with no fast mutex held +// TUint8 iMutexPri; /**< @internalComponent */ // priority from held fast mutex +// TUint8 iInitial; /**< @internalComponent */ // TRUE if this is an initial thread + TUint8 iLinkedObjType; + TUint8 i_ThrdAttr; /**< @internalComponent */ + TUint8 iNThreadBaseSpare10; + TUint8 iFastMutexDefer; /**< @internalComponent */ + + NFastSemaphore iRequestSemaphore; /**< @internalComponent */ + + TInt iTime; /**< @internalComponent */ // time remaining, 0 if expired + TInt iTimeslice; /**< @internalComponent */ // timeslice for this thread, -ve = no timeslicing + + TLinAddr iSavedSP; /**< @internalComponent */ + TAny* iAddressSpace; /**< @internalComponent */ + + NFastMutex* volatile iHeldFastMutex; /**< @internalComponent */ // fast mutex held by this thread + TUserModeCallback* volatile iUserModeCallbacks; /**< @internalComponent */ // Head of singly-linked list of callbacks + TAny* volatile iLinkedObj; /**< @internalComponent */ // object to which this thread is linked + NThreadGroup* iNewParent; /**< @internalComponent */ // group to join + + const SFastExecTable* iFastExecTable; /**< @internalComponent */ + const SSlowExecEntry* iSlowExecTable; /**< @internalComponent */ // points to first entry iEntries[0] + + volatile TInt iCsCount; /**< @internalComponent */ // critical section count + volatile TInt iCsFunction; /**< @internalComponent */ // what to do on leaving CS: +n=suspend n times, 0=nothing, -1=exit + + NThreadWaitState iWaitState; /**< @internalComponent */ + + const SNThreadHandlers* iHandlers; /**< @internalComponent */ // additional thread event handlers + TInt iSuspendCount; /**< @internalComponent */ // -how many times we have been suspended + + TLinAddr iStackBase; /**< @internalComponent */ + TInt iStackSize; /**< @internalComponent */ + + TAny* iExtraContext; /**< @internalComponent */ // parent FPSCR value (iExtraContextSize == -1), coprocessor context (iExtraContextSize > 0) or NULL + TInt iExtraContextSize; /**< @internalComponent */ // +ve=dynamically allocated, 0=none, -1=iExtraContext stores parent FPSCR value + + TUint32 iNThreadBaseSpare6; /**< @internalComponent */ // spare to allow growth while preserving BC + TUint32 iNThreadBaseSpare7; /**< @internalComponent */ // spare to allow growth while preserving BC + TUint32 iNThreadBaseSpare8; /**< @internalComponent */ // spare to allow growth while preserving BC + TUint32 iNThreadBaseSpare9; /**< @internalComponent */ // spare to allow growth while preserving BC + + // For EMI support - HOPEFULLY THIS CAN DIE + TUint32 iTag; /**< @internalComponent */ // User defined set of bits which is ANDed with a mask when the thread is scheduled, and indicates if a DFC should be scheduled. + TAny* iVemsData; /**< @internalComponent */ // This pointer can be used by any VEMS to store any data associated with the thread. This data must be clean up before the Thread Exit Monitor completes. + }; + +__ASSERT_COMPILE(!(_FOFF(NThreadBase,iWaitLink)&7)); +__ASSERT_COMPILE(!(sizeof(NThreadBase)&7)); + +#ifdef __INCLUDE_NTHREADBASE_DEFINES__ +#define iReady iSpare1 /**< @internalComponent */ +#define iCurrent iSpare2 /**< @internalComponent */ +#define iLastCpu iSpare3 /**< @internalComponent */ + +#define iBasePri iWaitLink.iSpare1 /**< @internalComponent */ +#define iMutexPri iWaitLink.iSpare2 /**< @internalComponent */ +#define i_NThread_Initial iWaitLink.iSpare3 /**< @internalComponent */ + +#endif + +/** @internalComponent */ +#define i_NThread_BasePri iWaitLink.iSpare1 + +/** @internalComponent */ +#define NTHREADBASE_CPU_AFFINITY_MASK 0x80000000 + +/** @internalComponent */ +inline NThreadBase* NThreadWaitState::Thread() + { return _LOFF(this, NThreadBase, iWaitState); } + +/******************************************** + * Thread group + ********************************************/ + +/** +@publishedPartner +@prototype + +Base class for a nanokernel thread or group +*/ +class NThreadGroup : public NSchedulable + { +public: + NThreadGroup(); +public: + TInt iThreadCount; /**< @internalComponent */ + TPriList iNThreadList; /**< @internalComponent */ + }; + +/******************************************** + * Scheduler + ********************************************/ + +/** +@internalComponent +*/ +class TScheduler; +class NThread; +class NIrqHandler; +class TSubScheduler : public TPriListBase + { +public: + TSubScheduler(); + void QueueDfcs(); + void RotateReadyList(TInt aPriority); + NThread* SelectNextThread(); + TBool QueueEvent(NEventHandler* aEvent); + void QueueEventAndKick(NEventHandler* aEvent); + void SaveTimesliceTimer(NThreadBase* aThread); + void UpdateThreadTimes(NThreadBase* aOld, NThreadBase* aNew); +private: + SDblQueLink* iExtraQueues[KNumPriorities-1]; +public: + TSpinLock iExIDfcLock; // lock to protect exogenous IDFC queue + + SDblQue iExIDfcs; // list of pending exogenous IDFCs (i.e. ones punted over from another CPU) + + SDblQue iDfcs; // normal IDFC/DFC pending queue (only accessed by this CPU) + + TDfc* volatile iCurrentIDFC; // pointer to IDFC currently running on this CPU + NThread* iCurrentThread; // the thread currently running on this CPU + + TUint32 iCpuNum; + TUint32 iCpuMask; + + TSpinLock iReadyListLock; + + volatile TUint8 iRescheduleNeededFlag; // TRUE if a thread reschedule is pending + TUint8 iSubSchedulerSBZ1; // always zero + volatile TUint8 iDfcPendingFlag; // TRUE if a normal IDFC is pending + volatile TUint8 iExIDfcPendingFlag; // TRUE if an exogenous IDFC is pending + TInt iKernLockCount; // how many times the current CPU has locked the kernel + + TUint8 iInIDFC; // TRUE if IDFCs are currently being run on this CPU + volatile TUint8 iEventHandlersPending; // TRUE if an event handler is pending on this CPU + TUint8 iSubSchedulerSpare4; + TUint8 iSubSchedulerSpare5; + TAny* iAddressSpace; + + TUint32 iReschedIPIs; + TScheduler* iScheduler; + + union + { + TUint64 iLastTimestamp64; // NKern::Timestamp() value at last reschedule or timestamp sync + TUint32 iLastTimestamp32[2]; + }; + union + { + TUint64 iReschedCount64; + TUint32 iReschedCount32[2]; + }; + + TAny* iExtras[24]; // Space for platform-specific extras + + TGenericIPI* iNextIPI; // next generic IPI to run on this CPU + NThread* iInitialThread; // Initial (idle) thread on this CPU + + TSpinLock iEventHandlerLock; // lock to protect event handler queue + + SDblQue iEventHandlers; // queue of pending event handlers on this CPU + + TUint64 iSpinLockOrderCheck; // bitmask showing which spinlock orders currently held + + TUint32 iSubSchedulerPadding[8]; + }; + +__ASSERT_COMPILE(!(_FOFF(TSubScheduler,iExIDfcLock)&7)); +__ASSERT_COMPILE(!(_FOFF(TSubScheduler,iEventHandlerLock)&7)); +__ASSERT_COMPILE(!(_FOFF(TSubScheduler,iReadyListLock)&7)); +__ASSERT_COMPILE(!(_FOFF(TSubScheduler,iLastTimestamp64)&7)); +__ASSERT_COMPILE(!(_FOFF(TSubScheduler,iReschedCount64)&7)); +__ASSERT_COMPILE(sizeof(TSubScheduler)==512); // make it a nice power of 2 size for easy indexing + +/** +@internalComponent +*/ +class TScheduler + { +public: + TScheduler(); + static void Reschedule(); + IMPORT_C static TScheduler* Ptr(); + inline void SetProcessHandler(TLinAddr aHandler) {iProcessHandler=aHandler;} +public: + TLinAddr iMonitorExceptionHandler; + TLinAddr iProcessHandler; + + TLinAddr iRescheduleHook; + TUint32 iActiveCpus1; // bit n set if CPU n is accepting unlocked threads + + TUint32 iActiveCpus2; // bit n set if CPU n is accepting generic IPIs + TInt iNumCpus; // number of CPUs under the kernel's control + + TSubScheduler* iSub[KMaxCpus]; // one subscheduler per CPU + + TAny* iExtras[24]; // Space for platform-specific extras + + NFastMutex iLock; // the 'system lock' fast mutex + + TSpinLock iIdleSpinLock; // lock to protect list of DFCs to be run on idle + + SDblQue iIdleDfcs; // list of DFCs to run when all CPUs go idle + + TUint32 iCpusNotIdle; // bitmask - Bit n set => CPU n is not idle + TUint8 iIdleGeneration; // Toggles between 0 and 1 each time iIdleDfcs list is spilled to a CPU IDFC queue + TUint8 iIdleSpillCpu; // Which CPU last spilled the iIdleDfcs list to its IDFC queue + TUint8 iTSchedulerSpare1; + TUint8 iTSchedulerSpare2; + + TUint32 iIdleGenerationCount; // Incremented each time iIdleDfcs list is spilled to a CPU IDFC queue + TUint32 i_Scheduler_Padding[3]; + + // For EMI support - HOPEFULLY THIS CAN DIE + NThread* iSigma; + TDfc* iEmiDfc; + TUint32 iEmiMask; + TUint32 iEmiState; + TUint32 iEmiDfcTrigger; + TBool iLogging; + TAny* iBufferStart; + TAny* iBufferEnd; + TAny* iBufferTail; + TAny* iBufferHead; + }; + +__ASSERT_COMPILE(!(_FOFF(TScheduler,iIdleSpinLock)&7)); +__ASSERT_COMPILE(sizeof(TScheduler)==512); + +extern TScheduler TheScheduler; +extern TSubScheduler TheSubSchedulers[KMaxCpus]; + +#ifdef __USE_BTRACE_LOCK__ +extern TSpinLock BTraceLock; + +#define __ACQUIRE_BTRACE_LOCK() TInt _btrace_irq = BTraceLock.LockIrqSave() +#define __RELEASE_BTRACE_LOCK() BTraceLock.UnlockIrqRestore(_btrace_irq) + +#else + +#define __ACQUIRE_BTRACE_LOCK() +#define __RELEASE_BTRACE_LOCK() + +#endif + +/** +@internalComponent +*/ +extern "C" TSubScheduler& SubScheduler(); + +/** +@internalComponent +*/ +extern "C" void send_resched_ipis(TUint32 aMask); + +/** +@internalComponent +*/ +extern "C" void send_resched_ipi(TInt aCpu); + +/** +@internalComponent +*/ +extern "C" void send_resched_ipi_and_wait(TInt aCpu); + + +#include + +/** +Call with kernel locked + +@internalComponent +*/ +inline void RescheduleNeeded() + { SubScheduler().iRescheduleNeededFlag = 1; } + + +/** +@internalComponent +*/ +#define NCurrentThread() NKern::CurrentThread() + +/** Optimised current thread function which can only be called from places where + CPU migration is not possible - i.e. with interrupts disabled or preemption + disabled. + +@internalComponent +*/ +extern "C" NThread* NCurrentThreadL(); + +/** @internalComponent */ +inline TBool CheckCpuAgainstAffinity(TInt aCpu, TUint32 aAffinity) + { + if (aAffinity & NTHREADBASE_CPU_AFFINITY_MASK) + return aAffinity & (1<HeldByCurrentThread()); + +/** +@publishedPartner +@released +*/ +#define __ASSERT_SYSTEM_LOCK __NK_ASSERT_DEBUG(TScheduler::Ptr()->iLock.HeldByCurrentThread()); + +#define __ASSERT_NOT_ISR __NK_ASSERT_DEBUG(NKern::CurrentContext()!=NKern::EInterrupt) + +#else +#define __ASSERT_NO_FAST_MUTEX +#define __ASSERT_FAST_MUTEX(m) +#define __ASSERT_SYSTEM_LOCK +#define __ASSERT_NOT_ISR +#endif + +/******************************************** + * System timer queue + ********************************************/ + +/** +@publishedPartner +@prototype +*/ +class NTimerQ + { + friend class NTimer; +public: + typedef void (*TDebugFn)(TAny* aPtr, TInt aPos); /**< @internalComponent */ + enum { ETimerQMask=31, ENumTimerQueues=32 }; /**< @internalComponent */ // these are not easily modifiable + + /** @internalComponent */ + struct STimerQ + { + SDblQue iIntQ; + SDblQue iDfcQ; + }; +public: + NTimerQ(); + static void Init1(TInt aTickPeriod); + static void Init3(TDfcQue* aDfcQ); + IMPORT_C static TAny* TimerAddress(); + IMPORT_C void Tick(); + IMPORT_C static TInt IdleTime(); + IMPORT_C static void Advance(TInt aTicks); +private: + static void DfcFn(TAny* aPtr); + void Dfc(); + void Add(NTimer* aTimer); + void AddFinal(NTimer* aTimer); +public: + STimerQ iTickQ[ENumTimerQueues]; /**< @internalComponent */ // NOTE: the order of member data is important + TUint32 iPresent; /**< @internalComponent */ // The assembler code relies on it + TUint32 iMsCount; /**< @internalComponent */ + SDblQue iHoldingQ; /**< @internalComponent */ + SDblQue iOrderedQ; /**< @internalComponent */ + SDblQue iCompletedQ; /**< @internalComponent */ + TDfc iDfc; /**< @internalComponent */ + TUint8 iTransferringCancelled; /**< @internalComponent */ + TUint8 iCriticalCancelled; /**< @internalComponent */ + TUint8 iPad1; /**< @internalComponent */ + TUint8 iPad2; /**< @internalComponent */ + TDebugFn iDebugFn; /**< @internalComponent */ + TAny* iDebugPtr; /**< @internalComponent */ + TInt iTickPeriod; /**< @internalComponent */ // in microseconds + + /** + This member is intended for use by ASSP/variant interrupt code as a convenient + location to store rounding error information where hardware interrupts are not + exactly one millisecond. The Symbian kernel does not make any use of this member. + @publishedPartner + @prototype + */ + TInt iRounding; + TInt iDfcCompleteCount; /**< @internalComponent */ + TSpinLock iTimerSpinLock; /**< @internalComponent */ + }; + +__ASSERT_COMPILE(!(_FOFF(NTimerQ,iTimerSpinLock)&7)); + + +GLREF_D NTimerQ TheTimerQ; + +/** +@internalComponent +*/ +inline TUint32 NTickCount() + {return TheTimerQ.iMsCount;} + +/** +@internalComponent +*/ +inline TInt NTickPeriod() + {return TheTimerQ.iTickPeriod;} + + +extern "C" { +/** +@internalComponent +*/ +extern void NKCrashHandler(TInt aPhase, const TAny* a0, TInt a1); + +/** +@internalComponent +*/ +extern TUint32 CrashState; +} + + +/** +@internalComponent +*/ +class TGenIPIList : public SDblQue + { +public: + TGenIPIList(); +public: + TSpinLock iGenIPILock; + }; + +/** +@internalComponent +*/ +class TCancelIPI : public TGenericIPI + { +public: + void Send(TDfc* aDfc, TInt aCpu); + static void Isr(TGenericIPI*); +public: + TDfc* volatile iDfc; + }; + + +/** +@internalComponent +*/ +TBool InterruptsStatus(TBool aRequest); + + +//declarations for the checking of kernel preconditions +#ifdef _DEBUG + +/** +@internalComponent +*/ +#define MASK_NO_FAST_MUTEX 0x1 +#define MASK_CRITICAL 0x2 +#define MASK_NO_CRITICAL 0x4 +#define MASK_KERNEL_LOCKED 0x8 +#define MASK_KERNEL_UNLOCKED 0x10 +#define MASK_KERNEL_LOCKED_ONCE 0x20 +#define MASK_INTERRUPTS_ENABLED 0x40 +#define MASK_INTERRUPTS_DISABLED 0x80 +#define MASK_SYSTEM_LOCKED 0x100 +#define MASK_NOT_ISR 0x400 +#define MASK_NOT_IDFC 0x800 +#define MASK_NOT_THREAD 0x1000 +#define MASK_NO_CRITICAL_IF_USER 0x2000 +#define MASK_THREAD_STANDARD ( MASK_NO_FAST_MUTEX | MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC ) +#define MASK_THREAD_CRITICAL ( MASK_THREAD_STANDARD | MASK_CRITICAL ) +#define MASK_ALWAYS_FAIL 0x4000 +#define MASK_NO_RESCHED 0x8000 + +#if defined(__STANDALONE_NANOKERNEL__) || (!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__)) +#define CHECK_PRECONDITIONS(mask,function) +#define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function) + +#else +/** +@internalComponent +*/ +extern "C" TInt CheckPreconditions(TUint32 aConditionMask, const char* aFunction, TLinAddr aAddr); +/** +@internalComponent +*/ +#define CHECK_PRECONDITIONS(mask,function) CheckPreconditions(mask,function,0) + +#ifdef __KERNEL_APIS_CONTEXT_CHECKS_FAULT__ + +/** +@internalComponent +*/ +#define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function) \ + __ASSERT_DEBUG( (cond), ( \ + DEBUGPRINT("Assertion failed: %s\nFunction: %s\n",message,function),\ + NKFault(function, 0))) + +#else//!__KERNEL_APIS_CONTEXT_CHECKS_FAULT__ +/** +@internalComponent +*/ +#define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function) \ + __ASSERT_DEBUG( (cond), \ + DEBUGPRINT("Assertion failed: %s\nFunction: %s\n",message,function)) + + +#endif//__KERNEL_APIS_CONTEXT_CHECKS_FAULT__ +#endif//(!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__)) + +#else//if !DEBUG + +#define CHECK_PRECONDITIONS(mask,function) +#define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function ) + +#endif//_DEBUG + +#if (!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__)) +#define __ASSERT_WITH_MESSAGE_ALWAYS(cond,message,function ) +#else +#ifdef __KERNEL_APIS_CONTEXT_CHECKS_FAULT__ +/** +@internalComponent +*/ +#define __ASSERT_WITH_MESSAGE_ALWAYS(cond,message,function) \ + __ASSERT_ALWAYS( (cond), ( \ + DEBUGPRINT("Assertion failed: %s\nFunction: %s\n",message,function),\ + NKFault(function, 0))) +#else +/** +@internalComponent +*/ +#define __ASSERT_WITH_MESSAGE_ALWAYS(cond,message,function) \ + __ASSERT_ALWAYS( (cond), \ + DEBUGPRINT("Assertion failed: %s\nFunction: %s\n",message,function)) +#endif//__KERNEL_APIS_CONTEXT_CHECKS_FAULT__ +#endif//(!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__)) + +#endif