sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\include\nkern\nk_priv.h sl@0: // sl@0: // WARNING: This file contains some APIs which are internal and are subject sl@0: // to change without notice. Such APIs should therefore not be used sl@0: // outside the Kernel and Hardware Services package. sl@0: // sl@0: sl@0: #ifndef __NK_PRIV_H__ sl@0: #define __NK_PRIV_H__ sl@0: #include sl@0: #include sl@0: sl@0: /******************************************** sl@0: * DFCs sl@0: ********************************************/ sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: inline TBool TDfc::TestAndSetQueued() sl@0: { return __e32_atomic_swp_ord8(&iSpare3, 1); } sl@0: sl@0: /******************************************** sl@0: * Thread sl@0: ********************************************/ sl@0: sl@0: class TUserModeCallback; sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @released sl@0: sl@0: Base class for a nanokernel thread. sl@0: */ sl@0: class NThreadBase : public TPriListLink sl@0: { sl@0: public: sl@0: /** sl@0: Defines the possible states of a nanokernel thread. sl@0: */ sl@0: enum NThreadState sl@0: { sl@0: /** sl@0: The thread is eligible for execution. sl@0: sl@0: Threads in this state are linked into the ready list. sl@0: The highest priority READY thread is the one that will run, unless it sl@0: is blocked on a fast mutex. sl@0: */ sl@0: EReady, sl@0: sl@0: /** sl@0: The thread is explicitly suspended (rather than blocking on sl@0: a wait object). sl@0: */ sl@0: ESuspended, sl@0: sl@0: /** sl@0: The thread is blocked waiting for a fast semaphore to be signalled. sl@0: */ sl@0: EWaitFastSemaphore, sl@0: sl@0: /** sl@0: The thread is blocked waiting for a specific time period to elapse. sl@0: */ sl@0: ESleep, sl@0: sl@0: /** sl@0: The thread is blocked on a wait object implemented in a layer above sl@0: the nanokernel. sl@0: sl@0: In practice, this means that it is blocked on a Symbian OS sl@0: semaphore or mutex. sl@0: */ sl@0: EBlocked, sl@0: sl@0: /** sl@0: The thread has terminated and will not execute again. sl@0: */ sl@0: EDead, sl@0: sl@0: /** sl@0: The thread is a DFC-handling thread and it is blocked waiting for sl@0: the DFC to be queued. sl@0: */ sl@0: EWaitDfc, sl@0: sl@0: /** sl@0: Not a thread state, but defines the maximum number of states. sl@0: */ sl@0: ENumNStates sl@0: }; sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Defines a set of values that, when passed to a nanokernel state handler, sl@0: indicates which operation is being performed on the thread. sl@0: sl@0: Every thread that can use a new type of wait object, must have a nanokernel sl@0: state handler installed to handle operations on that thread while it is sl@0: waiting on that wait object. sl@0: sl@0: A wait handler has the signature: sl@0: @code sl@0: void StateHandler(NThread* aThread, TInt aOp, TInt aParam); sl@0: @endcode sl@0: sl@0: where aOp is one of these enum values. sl@0: sl@0: The state handler is always called with preemption disabled. sl@0: */ sl@0: enum NThreadOperation sl@0: { sl@0: /** sl@0: Indicates that the thread is suspended while not in a critical section, sl@0: and not holding a fast mutex. sl@0: sl@0: StateHandler() is called in whichever context sl@0: NThreadBase::Suspend() is called from. sl@0: sl@0: Note that the third parameter passed to StateHandler() contains sl@0: the requested suspension count. sl@0: */ sl@0: ESuspend=0, sl@0: sl@0: /** sl@0: Indicates that the thread is being resumed while suspended, and sl@0: the last suspension has been removed. sl@0: sl@0: StateHandler() is called in whichever context sl@0: NThreadBase::Resume() is called from. sl@0: */ sl@0: EResume=1, sl@0: sl@0: /** sl@0: Indicates that the thread has all suspensions cancelled while sl@0: actually suspended. sl@0: sl@0: Statehandler() is called in whichever context sl@0: NThreadBase::ForceResume() is called from. sl@0: */ sl@0: EForceResume=2, sl@0: sl@0: /** sl@0: Indicates that the thread is being released from its wait. sl@0: sl@0: Statehandler() is called in whichever context sl@0: NThreadBase::Release() is called from. sl@0: */ sl@0: ERelease=3, sl@0: sl@0: /** sl@0: Indicates that the thread's priority is being changed. sl@0: sl@0: StateHandler() is called in whichever context sl@0: NThreadBase::SetPriority() is called from. sl@0: */ sl@0: EChangePriority=4, sl@0: sl@0: /** sl@0: Indicates that the thread has called NKern::ThreadLeaveCS() with sl@0: an unknown NThreadBase::iCsFunction that is negative, but not equal sl@0: to NThreadBase::ECsExitPending. sl@0: sl@0: Note that NThreadBase::iCsFunction is internal to Symbian OS. sl@0: */ sl@0: ELeaveCS=5, sl@0: sl@0: /** sl@0: Indicates that the thread's wait timeout has expired, and no timeout sl@0: handler has been defined for that thread. sl@0: sl@0: StateHandler() is called in the context of the nanokernel sl@0: timer thread, DfcThread1. sl@0: */ sl@0: ETimeout=6, sl@0: }; sl@0: sl@0: enum NThreadCSFunction sl@0: { sl@0: ECSExitPending=-1, sl@0: ECSExitInProgress=-2 sl@0: }; sl@0: sl@0: enum NThreadTimeoutOp sl@0: { sl@0: ETimeoutPreamble=0, sl@0: ETimeoutPostamble=1, sl@0: ETimeoutSpurious=2, sl@0: }; sl@0: public: sl@0: NThreadBase(); sl@0: TInt Create(SNThreadCreateInfo& anInfo, TBool aInitial); sl@0: IMPORT_C void CheckSuspendThenReady(); sl@0: IMPORT_C void Ready(); sl@0: void DoReady(); sl@0: void DoCsFunction(); sl@0: IMPORT_C TBool Suspend(TInt aCount); sl@0: IMPORT_C TBool Resume(); sl@0: IMPORT_C TBool ForceResume(); sl@0: IMPORT_C void Release(TInt aReturnCode); sl@0: IMPORT_C void RequestSignal(); sl@0: IMPORT_C void SetPriority(TInt aPriority); sl@0: void SetEntry(NThreadFunction aFunction); sl@0: IMPORT_C void Kill(); sl@0: void Exit(); sl@0: void ForceExit(); sl@0: // hooks for platform-specific code sl@0: void OnKill(); sl@0: void OnExit(); sl@0: public: sl@0: static void TimerExpired(TAny* aPtr); sl@0: inline void UnknownState(TInt aOp, TInt aParam) sl@0: { (*iHandlers->iStateHandler)((NThread*)this,aOp,aParam); } sl@0: sl@0: /** @internalComponent */ sl@0: inline TUint8 Attributes() sl@0: { return iSpare2; } sl@0: sl@0: /** @internalComponent */ sl@0: inline TUint8 SetAttributes(TUint8 aNewAtt) sl@0: { return __e32_atomic_swp_ord8(&iSpare2, aNewAtt); } sl@0: sl@0: /** @internalComponent */ sl@0: inline TUint8 ModifyAttributes(TUint8 aClearMask, TUint8 aSetMask) sl@0: { return __e32_atomic_axo_ord8(&iSpare2, (TUint8)~(aClearMask|aSetMask), aSetMask); } sl@0: sl@0: /** @internalComponent */ sl@0: inline void SetAddressSpace(TAny* a) sl@0: { iAddressSpace=a; } sl@0: sl@0: inline void SetReturnValue(TInt aValue) sl@0: { iReturnValue=aValue; } sl@0: inline void SetExtraContext(TAny* a, TInt aSize) sl@0: { iExtraContext = a; iExtraContextSize = aSize; } sl@0: sl@0: /** @internalComponent */ sl@0: void CallUserModeCallbacks(); sl@0: public: sl@0: // TUint8 iNState; // use iSpare1 for state sl@0: // TUint8 i_ThrdAttr; /**< @internalComponent */ // use iSpare2 for attributes sl@0: // TUint8 iUserContextType; // use iSpare3 sl@0: NFastMutex* iHeldFastMutex; /**< @internalComponent */ // fast mutex held by this thread sl@0: NFastMutex* iWaitFastMutex; /**< @internalComponent */ // fast mutex on which this thread is blocked sl@0: TAny* iAddressSpace; /**< @internalComponent */ sl@0: TInt iTime; // time remaining sl@0: TInt iTimeslice; // timeslice for this thread sl@0: NFastSemaphore iRequestSemaphore; /**< @internalComponent */ sl@0: TAny* iWaitObj; // object on which this thread is waiting sl@0: TInt iSuspendCount; /**< @internalComponent */ // -how many times we have been suspended sl@0: TInt iCsCount; /**< @internalComponent */ // critical section count sl@0: TInt iCsFunction; /**< @internalComponent */ // what to do on leaving CS: +n=suspend n times, 0=nothing, -1=exit sl@0: NTimer iTimer; /**< @internalComponent */ sl@0: TInt iReturnValue; sl@0: TLinAddr iStackBase; /**< @internalComponent */ sl@0: TInt iStackSize; /**< @internalComponent */ sl@0: const SNThreadHandlers* iHandlers; /**< @internalComponent */ // additional thread event handlers sl@0: const SFastExecTable* iFastExecTable; /**< @internalComponent */ sl@0: const SSlowExecEntry* iSlowExecTable; /**< @internalComponent */ // points to first entry iEntries[0] sl@0: TLinAddr iSavedSP; /**< @internalComponent */ sl@0: TAny* iExtraContext; /**< @internalComponent */ // parent FPSCR value (iExtraContextSize == -1), coprocessor context (iExtraContextSize > 0) or NULL sl@0: TInt iExtraContextSize; /**< @internalComponent */ // +ve=dynamically allocated, 0=none, -1=iExtraContext stores parent FPSCR value sl@0: TUint iLastStartTime; /**< @internalComponent */ // last start of execution timestamp sl@0: TUint64 iTotalCpuTime; /**< @internalComponent */ // total time spent running, in hi-res timer ticks sl@0: 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. sl@0: 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. sl@0: TUserModeCallback* volatile iUserModeCallbacks; /**< @internalComponent */ // Head of singly-linked list of callbacks sl@0: TUint32 iSpare7; /**< @internalComponent */ // spare to allow growth while preserving BC sl@0: TUint32 iSpare8; /**< @internalComponent */ // spare to allow growth while preserving BC sl@0: }; sl@0: sl@0: __ASSERT_COMPILE(!(_FOFF(NThreadBase,iTotalCpuTime)&7)); sl@0: sl@0: #ifdef __INCLUDE_NTHREADBASE_DEFINES__ sl@0: #define iNState iSpare1 sl@0: #define i_ThrdAttr iSpare2 sl@0: #define iUserContextType iSpare3 sl@0: #endif sl@0: sl@0: #define i_NThread_BasePri iPriority sl@0: sl@0: /******************************************** sl@0: * Scheduler sl@0: ********************************************/ sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: class TScheduler : public TPriListBase sl@0: { sl@0: public: sl@0: TScheduler(); sl@0: void Remove(NThreadBase* aThread); sl@0: void RotateReadyList(TInt aPriority); sl@0: void QueueDfcs(); sl@0: static void Reschedule(); sl@0: static void YieldTo(NThreadBase* aThread); sl@0: void TimesliceTick(); sl@0: IMPORT_C static TScheduler* Ptr(); sl@0: inline void SetProcessHandler(TLinAddr aHandler) {iProcessHandler=aHandler;} sl@0: private: sl@0: SDblQueLink* iExtraQueues[KNumPriorities-1]; sl@0: public: sl@0: TUint8 iRescheduleNeededFlag; sl@0: TUint8 iDfcPendingFlag; sl@0: TInt iKernCSLocked; sl@0: SDblQue iDfcs; sl@0: TLinAddr iMonitorExceptionHandler; sl@0: TLinAddr iProcessHandler; sl@0: TLinAddr iRescheduleHook; sl@0: TUint8 iInIDFC; sl@0: NFastMutex iLock; sl@0: NThreadBase* iCurrentThread; sl@0: TAny* iAddressSpace; sl@0: TAny* iExtras[16]; sl@0: // For EMI support sl@0: NThread* iSigma; sl@0: TDfc* iEmiDfc; sl@0: TUint32 iEmiMask; sl@0: TUint32 iEmiState; sl@0: TUint32 iEmiDfcTrigger; sl@0: TBool iLogging; sl@0: TAny* iBufferStart; sl@0: TAny* iBufferEnd; sl@0: TAny* iBufferTail; sl@0: TAny* iBufferHead; sl@0: // For BTrace suport sl@0: TUint8 iCpuUsageFilter; sl@0: TUint8 iFastMutexFilter; sl@0: BTrace::THandler iBTraceHandler; sl@0: // Idle notification sl@0: SDblQue iIdleDfcs; sl@0: TUint32 iIdleGenerationCount; sl@0: // Delayed threads sl@0: SDblQue iDelayedQ; sl@0: TDfc iDelayDfc; sl@0: }; sl@0: sl@0: GLREF_D TScheduler TheScheduler; sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: inline void RescheduleNeeded() sl@0: {TheScheduler.iRescheduleNeededFlag=TRUE;} sl@0: sl@0: #include sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: inline NThread* NCurrentThread() sl@0: { return (NThread*)TheScheduler.iCurrentThread; } sl@0: sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define __NK_ASSERT_UNLOCKED __NK_ASSERT_DEBUG(TheScheduler.iKernCSLocked==0) sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define __NK_ASSERT_LOCKED __NK_ASSERT_DEBUG(TheScheduler.iKernCSLocked!=0) sl@0: sl@0: #ifdef _DEBUG sl@0: /** sl@0: @publishedPartner sl@0: @released sl@0: */ sl@0: #define __ASSERT_NO_FAST_MUTEX { \ sl@0: NThread* nt=NKern::CurrentThread(); \ sl@0: __NK_ASSERT_DEBUG(!nt->iHeldFastMutex); \ sl@0: } sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @released sl@0: */ sl@0: #define __ASSERT_FAST_MUTEX(m) { \ sl@0: NThread* nt=NKern::CurrentThread(); \ sl@0: __NK_ASSERT_DEBUG(nt->iHeldFastMutex==(m) && (m)->iHoldingThread==nt); \ sl@0: } sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @released sl@0: */ sl@0: #define __ASSERT_SYSTEM_LOCK { \ sl@0: NThread* nt=NKern::CurrentThread(); \ sl@0: NFastMutex& m=TScheduler::Ptr()->iLock; \ sl@0: __NK_ASSERT_DEBUG(nt->iHeldFastMutex==&m && m.iHoldingThread==nt); \ sl@0: } sl@0: sl@0: #define __ASSERT_NOT_ISR __NK_ASSERT_DEBUG(NKern::CurrentContext()!=NKern::EInterrupt) sl@0: sl@0: #else sl@0: #define __ASSERT_NO_FAST_MUTEX sl@0: #define __ASSERT_FAST_MUTEX(m) sl@0: #define __ASSERT_SYSTEM_LOCK sl@0: #define __ASSERT_NOT_ISR sl@0: #endif sl@0: sl@0: /******************************************** sl@0: * System timer queue sl@0: ********************************************/ sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @released sl@0: */ sl@0: class NTimerQ sl@0: { sl@0: friend class NTimer; sl@0: public: sl@0: typedef void (*TDebugFn)(TAny* aPtr, TInt aPos); /**< @internalComponent */ sl@0: enum { ETimerQMask=31, ENumTimerQueues=32 }; /**< @internalComponent */ // these are not easily modifiable sl@0: sl@0: /** @internalComponent */ sl@0: struct STimerQ sl@0: { sl@0: SDblQue iIntQ; sl@0: SDblQue iDfcQ; sl@0: }; sl@0: public: sl@0: NTimerQ(); sl@0: static void Init1(TInt aTickPeriod); sl@0: static void Init3(TDfcQue* aDfcQ); sl@0: IMPORT_C static TAny* TimerAddress(); sl@0: IMPORT_C void Tick(); sl@0: IMPORT_C static TInt IdleTime(); sl@0: IMPORT_C static void Advance(TInt aTicks); sl@0: private: sl@0: static void DfcFn(TAny* aPtr); sl@0: void Dfc(); sl@0: void Add(NTimer* aTimer); sl@0: void AddFinal(NTimer* aTimer); sl@0: public: sl@0: STimerQ iTickQ[ENumTimerQueues]; /**< @internalComponent */ // NOTE: the order of member data is important sl@0: TUint32 iPresent; /**< @internalComponent */ // The assembler code relies on it sl@0: TUint32 iMsCount; /**< @internalComponent */ sl@0: SDblQue iHoldingQ; /**< @internalComponent */ sl@0: SDblQue iOrderedQ; /**< @internalComponent */ sl@0: SDblQue iCompletedQ; /**< @internalComponent */ sl@0: TDfc iDfc; /**< @internalComponent */ sl@0: TUint8 iTransferringCancelled; /**< @internalComponent */ sl@0: TUint8 iCriticalCancelled; /**< @internalComponent */ sl@0: TUint8 iPad1; /**< @internalComponent */ sl@0: TUint8 iPad2; /**< @internalComponent */ sl@0: TDebugFn iDebugFn; /**< @internalComponent */ sl@0: TAny* iDebugPtr; /**< @internalComponent */ sl@0: TInt iTickPeriod; /**< @internalComponent */ // in microseconds sl@0: /** sl@0: This member is intended for use by ASSP/variant interrupt code as a convenient sl@0: location to store rounding error information where hardware interrupts are not sl@0: exactly one millisecond. The Symbian kernel does not make any use of this member. sl@0: @publishedPartner sl@0: @released sl@0: */ sl@0: TInt iRounding; sl@0: }; sl@0: sl@0: GLREF_D NTimerQ TheTimerQ; sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: inline TUint32 NTickCount() sl@0: {return TheTimerQ.iMsCount;} sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: inline TInt NTickPeriod() sl@0: {return TheTimerQ.iTickPeriod;} sl@0: sl@0: sl@0: extern "C" { sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: extern void NKCrashHandler(TInt aPhase, const TAny* a0, TInt a1); sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: extern TUint32 CrashState; sl@0: } sl@0: sl@0: sl@0: #define __ACQUIRE_BTRACE_LOCK() sl@0: #define __RELEASE_BTRACE_LOCK() sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: TBool InterruptsStatus(TBool aRequest); sl@0: sl@0: //declarations for the checking of kernel preconditions sl@0: sl@0: /** sl@0: @internalComponent sl@0: sl@0: PRECOND_FUNCTION_CALLER is needed for __ASSERT_WITH_MESSAGE_ALWAYS(), sl@0: so is outside the #ifdef _DEBUG. sl@0: */ sl@0: #ifndef PRECOND_FUNCTION_CALLER sl@0: #define PRECOND_FUNCTION_CALLER 0 sl@0: #endif sl@0: sl@0: #ifdef _DEBUG sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define MASK_NO_FAST_MUTEX 0x1 sl@0: #define MASK_CRITICAL 0x2 sl@0: #define MASK_NO_CRITICAL 0x4 sl@0: #define MASK_KERNEL_LOCKED 0x8 sl@0: #define MASK_KERNEL_UNLOCKED 0x10 sl@0: #define MASK_KERNEL_LOCKED_ONCE 0x20 sl@0: #define MASK_INTERRUPTS_ENABLED 0x40 sl@0: #define MASK_INTERRUPTS_DISABLED 0x80 sl@0: #define MASK_SYSTEM_LOCKED 0x100 sl@0: #define MASK_NOT_ISR 0x400 sl@0: #define MASK_NOT_IDFC 0x800 sl@0: #define MASK_NOT_THREAD 0x1000 sl@0: #define MASK_NO_CRITICAL_IF_USER 0x2000 sl@0: #define MASK_THREAD_STANDARD ( MASK_NO_FAST_MUTEX | MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC ) sl@0: #define MASK_THREAD_CRITICAL ( MASK_THREAD_STANDARD | MASK_CRITICAL ) sl@0: #define MASK_ALWAYS_FAIL 0x4000 sl@0: #define MASK_NO_RESCHED 0x8000 sl@0: sl@0: #if defined(__STANDALONE_NANOKERNEL__) || (!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__)) sl@0: #define CHECK_PRECONDITIONS(mask,function) sl@0: #define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function) sl@0: sl@0: #else sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: extern "C" TInt CheckPreconditions(TUint32 aConditionMask, const char* aFunction, TLinAddr aAddr); sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define CHECK_PRECONDITIONS(mask,function) CheckPreconditions(mask,function,PRECOND_FUNCTION_CALLER) sl@0: sl@0: #ifdef __KERNEL_APIS_CONTEXT_CHECKS_FAULT__ sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function) \ sl@0: __ASSERT_DEBUG( (cond), ( \ sl@0: DEBUGPRINT("Assertion failed: %s\nFunction: %s; called from: %08x\n",message,function,PRECOND_FUNCTION_CALLER),\ sl@0: NKFault(function, 0))) sl@0: sl@0: #else//!__KERNEL_APIS_CONTEXT_CHECKS_FAULT__ sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function) \ sl@0: __ASSERT_DEBUG( (cond), \ sl@0: DEBUGPRINT("Assertion failed: %s\nFunction: %s; called from: %08x\n",message,function,PRECOND_FUNCTION_CALLER)) sl@0: sl@0: sl@0: #endif//__KERNEL_APIS_CONTEXT_CHECKS_FAULT__ sl@0: #endif//(!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__)) sl@0: sl@0: #else//if !DEBUG sl@0: sl@0: #define CHECK_PRECONDITIONS(mask,function) sl@0: #define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function) sl@0: sl@0: #endif//_DEBUG sl@0: sl@0: #if (!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__)) sl@0: #define __ASSERT_WITH_MESSAGE_ALWAYS(cond,message,function) sl@0: #else sl@0: #ifdef __KERNEL_APIS_CONTEXT_CHECKS_FAULT__ sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define __ASSERT_WITH_MESSAGE_ALWAYS(cond,message,function) \ sl@0: __ASSERT_ALWAYS( (cond), ( \ sl@0: DEBUGPRINT("Assertion failed: %s\nFunction: %s; called from: %08x\n",message,function,PRECOND_FUNCTION_CALLER),\ sl@0: NKFault(function, 0))) sl@0: #else sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define __ASSERT_WITH_MESSAGE_ALWAYS(cond,message,function) \ sl@0: __ASSERT_ALWAYS( (cond), \ sl@0: DEBUGPRINT("Assertion failed: %s\nFunction: %s; called from: %08x\n",message,function,PRECOND_FUNCTION_CALLER)) sl@0: #endif//__KERNEL_APIS_CONTEXT_CHECKS_FAULT__ sl@0: #endif//(!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__)) sl@0: sl@0: #endif