Update contrib.
1 // Copyright (c) 1998-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\include\nkern\nk_priv.h
16 // WARNING: This file contains some APIs which are internal and are subject
17 // to change without notice. Such APIs should therefore not be used
18 // outside the Kernel and Hardware Services package.
26 /********************************************
28 ********************************************/
33 inline TBool TDfc::TestAndSetQueued()
34 { return __e32_atomic_swp_ord8(&iSpare3, 1); }
36 /********************************************
38 ********************************************/
40 class TUserModeCallback;
46 Base class for a nanokernel thread.
48 class NThreadBase : public TPriListLink
52 Defines the possible states of a nanokernel thread.
57 The thread is eligible for execution.
59 Threads in this state are linked into the ready list.
60 The highest priority READY thread is the one that will run, unless it
61 is blocked on a fast mutex.
66 The thread is explicitly suspended (rather than blocking on
72 The thread is blocked waiting for a fast semaphore to be signalled.
77 The thread is blocked waiting for a specific time period to elapse.
82 The thread is blocked on a wait object implemented in a layer above
85 In practice, this means that it is blocked on a Symbian OS
91 The thread has terminated and will not execute again.
96 The thread is a DFC-handling thread and it is blocked waiting for
102 Not a thread state, but defines the maximum number of states.
111 Defines a set of values that, when passed to a nanokernel state handler,
112 indicates which operation is being performed on the thread.
114 Every thread that can use a new type of wait object, must have a nanokernel
115 state handler installed to handle operations on that thread while it is
116 waiting on that wait object.
118 A wait handler has the signature:
120 void StateHandler(NThread* aThread, TInt aOp, TInt aParam);
123 where aOp is one of these enum values.
125 The state handler is always called with preemption disabled.
127 enum NThreadOperation
130 Indicates that the thread is suspended while not in a critical section,
131 and not holding a fast mutex.
133 StateHandler() is called in whichever context
134 NThreadBase::Suspend() is called from.
136 Note that the third parameter passed to StateHandler() contains
137 the requested suspension count.
142 Indicates that the thread is being resumed while suspended, and
143 the last suspension has been removed.
145 StateHandler() is called in whichever context
146 NThreadBase::Resume() is called from.
151 Indicates that the thread has all suspensions cancelled while
154 Statehandler() is called in whichever context
155 NThreadBase::ForceResume() is called from.
160 Indicates that the thread is being released from its wait.
162 Statehandler() is called in whichever context
163 NThreadBase::Release() is called from.
168 Indicates that the thread's priority is being changed.
170 StateHandler() is called in whichever context
171 NThreadBase::SetPriority() is called from.
176 Indicates that the thread has called NKern::ThreadLeaveCS() with
177 an unknown NThreadBase::iCsFunction that is negative, but not equal
178 to NThreadBase::ECsExitPending.
180 Note that NThreadBase::iCsFunction is internal to Symbian OS.
185 Indicates that the thread's wait timeout has expired, and no timeout
186 handler has been defined for that thread.
188 StateHandler() is called in the context of the nanokernel
189 timer thread, DfcThread1.
194 enum NThreadCSFunction
200 enum NThreadTimeoutOp
208 TInt Create(SNThreadCreateInfo& anInfo, TBool aInitial);
209 IMPORT_C void CheckSuspendThenReady();
210 IMPORT_C void Ready();
213 IMPORT_C TBool Suspend(TInt aCount);
214 IMPORT_C TBool Resume();
215 IMPORT_C TBool ForceResume();
216 IMPORT_C void Release(TInt aReturnCode);
217 IMPORT_C void RequestSignal();
218 IMPORT_C void SetPriority(TInt aPriority);
219 void SetEntry(NThreadFunction aFunction);
220 IMPORT_C void Kill();
223 // hooks for platform-specific code
227 static void TimerExpired(TAny* aPtr);
228 inline void UnknownState(TInt aOp, TInt aParam)
229 { (*iHandlers->iStateHandler)((NThread*)this,aOp,aParam); }
231 /** @internalComponent */
232 inline TUint8 Attributes()
235 /** @internalComponent */
236 inline TUint8 SetAttributes(TUint8 aNewAtt)
237 { return __e32_atomic_swp_ord8(&iSpare2, aNewAtt); }
239 /** @internalComponent */
240 inline TUint8 ModifyAttributes(TUint8 aClearMask, TUint8 aSetMask)
241 { return __e32_atomic_axo_ord8(&iSpare2, (TUint8)~(aClearMask|aSetMask), aSetMask); }
243 /** @internalComponent */
244 inline void SetAddressSpace(TAny* a)
247 inline void SetReturnValue(TInt aValue)
248 { iReturnValue=aValue; }
249 inline void SetExtraContext(TAny* a, TInt aSize)
250 { iExtraContext = a; iExtraContextSize = aSize; }
252 /** @internalComponent */
253 void CallUserModeCallbacks();
255 // TUint8 iNState; // use iSpare1 for state
256 // TUint8 i_ThrdAttr; /**< @internalComponent */ // use iSpare2 for attributes
257 // TUint8 iUserContextType; // use iSpare3
258 NFastMutex* iHeldFastMutex; /**< @internalComponent */ // fast mutex held by this thread
259 NFastMutex* iWaitFastMutex; /**< @internalComponent */ // fast mutex on which this thread is blocked
260 TAny* iAddressSpace; /**< @internalComponent */
261 TInt iTime; // time remaining
262 TInt iTimeslice; // timeslice for this thread
263 NFastSemaphore iRequestSemaphore; /**< @internalComponent */
264 TAny* iWaitObj; // object on which this thread is waiting
265 TInt iSuspendCount; /**< @internalComponent */ // -how many times we have been suspended
266 TInt iCsCount; /**< @internalComponent */ // critical section count
267 TInt iCsFunction; /**< @internalComponent */ // what to do on leaving CS: +n=suspend n times, 0=nothing, -1=exit
268 NTimer iTimer; /**< @internalComponent */
270 TLinAddr iStackBase; /**< @internalComponent */
271 TInt iStackSize; /**< @internalComponent */
272 const SNThreadHandlers* iHandlers; /**< @internalComponent */ // additional thread event handlers
273 const SFastExecTable* iFastExecTable; /**< @internalComponent */
274 const SSlowExecEntry* iSlowExecTable; /**< @internalComponent */ // points to first entry iEntries[0]
275 TLinAddr iSavedSP; /**< @internalComponent */
276 TAny* iExtraContext; /**< @internalComponent */ // parent FPSCR value (iExtraContextSize == -1), coprocessor context (iExtraContextSize > 0) or NULL
277 TInt iExtraContextSize; /**< @internalComponent */ // +ve=dynamically allocated, 0=none, -1=iExtraContext stores parent FPSCR value
278 TUint iLastStartTime; /**< @internalComponent */ // last start of execution timestamp
279 TUint64 iTotalCpuTime; /**< @internalComponent */ // total time spent running, in hi-res timer ticks
280 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.
281 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.
282 TUserModeCallback* volatile iUserModeCallbacks; /**< @internalComponent */ // Head of singly-linked list of callbacks
283 TUint32 iSpare7; /**< @internalComponent */ // spare to allow growth while preserving BC
284 TUint32 iSpare8; /**< @internalComponent */ // spare to allow growth while preserving BC
287 __ASSERT_COMPILE(!(_FOFF(NThreadBase,iTotalCpuTime)&7));
289 #ifdef __INCLUDE_NTHREADBASE_DEFINES__
290 #define iNState iSpare1
291 #define i_ThrdAttr iSpare2
292 #define iUserContextType iSpare3
295 #define i_NThread_BasePri iPriority
297 /********************************************
299 ********************************************/
304 class TScheduler : public TPriListBase
308 void Remove(NThreadBase* aThread);
309 void RotateReadyList(TInt aPriority);
311 static void Reschedule();
312 static void YieldTo(NThreadBase* aThread);
313 void TimesliceTick();
314 IMPORT_C static TScheduler* Ptr();
315 inline void SetProcessHandler(TLinAddr aHandler) {iProcessHandler=aHandler;}
317 SDblQueLink* iExtraQueues[KNumPriorities-1];
319 TUint8 iRescheduleNeededFlag;
320 TUint8 iDfcPendingFlag;
323 TLinAddr iMonitorExceptionHandler;
324 TLinAddr iProcessHandler;
325 TLinAddr iRescheduleHook;
328 NThreadBase* iCurrentThread;
336 TUint32 iEmiDfcTrigger;
343 TUint8 iCpuUsageFilter;
344 TUint8 iFastMutexFilter;
345 BTrace::THandler iBTraceHandler;
348 TUint32 iIdleGenerationCount;
354 GLREF_D TScheduler TheScheduler;
359 inline void RescheduleNeeded()
360 {TheScheduler.iRescheduleNeededFlag=TRUE;}
367 inline NThread* NCurrentThread()
368 { return (NThread*)TheScheduler.iCurrentThread; }
374 #define __NK_ASSERT_UNLOCKED __NK_ASSERT_DEBUG(TheScheduler.iKernCSLocked==0)
379 #define __NK_ASSERT_LOCKED __NK_ASSERT_DEBUG(TheScheduler.iKernCSLocked!=0)
386 #define __ASSERT_NO_FAST_MUTEX { \
387 NThread* nt=NKern::CurrentThread(); \
388 __NK_ASSERT_DEBUG(!nt->iHeldFastMutex); \
395 #define __ASSERT_FAST_MUTEX(m) { \
396 NThread* nt=NKern::CurrentThread(); \
397 __NK_ASSERT_DEBUG(nt->iHeldFastMutex==(m) && (m)->iHoldingThread==nt); \
404 #define __ASSERT_SYSTEM_LOCK { \
405 NThread* nt=NKern::CurrentThread(); \
406 NFastMutex& m=TScheduler::Ptr()->iLock; \
407 __NK_ASSERT_DEBUG(nt->iHeldFastMutex==&m && m.iHoldingThread==nt); \
410 #define __ASSERT_NOT_ISR __NK_ASSERT_DEBUG(NKern::CurrentContext()!=NKern::EInterrupt)
413 #define __ASSERT_NO_FAST_MUTEX
414 #define __ASSERT_FAST_MUTEX(m)
415 #define __ASSERT_SYSTEM_LOCK
416 #define __ASSERT_NOT_ISR
419 /********************************************
421 ********************************************/
431 typedef void (*TDebugFn)(TAny* aPtr, TInt aPos); /**< @internalComponent */
432 enum { ETimerQMask=31, ENumTimerQueues=32 }; /**< @internalComponent */ // these are not easily modifiable
434 /** @internalComponent */
442 static void Init1(TInt aTickPeriod);
443 static void Init3(TDfcQue* aDfcQ);
444 IMPORT_C static TAny* TimerAddress();
445 IMPORT_C void Tick();
446 IMPORT_C static TInt IdleTime();
447 IMPORT_C static void Advance(TInt aTicks);
449 static void DfcFn(TAny* aPtr);
451 void Add(NTimer* aTimer);
452 void AddFinal(NTimer* aTimer);
454 STimerQ iTickQ[ENumTimerQueues]; /**< @internalComponent */ // NOTE: the order of member data is important
455 TUint32 iPresent; /**< @internalComponent */ // The assembler code relies on it
456 TUint32 iMsCount; /**< @internalComponent */
457 SDblQue iHoldingQ; /**< @internalComponent */
458 SDblQue iOrderedQ; /**< @internalComponent */
459 SDblQue iCompletedQ; /**< @internalComponent */
460 TDfc iDfc; /**< @internalComponent */
461 TUint8 iTransferringCancelled; /**< @internalComponent */
462 TUint8 iCriticalCancelled; /**< @internalComponent */
463 TUint8 iPad1; /**< @internalComponent */
464 TUint8 iPad2; /**< @internalComponent */
465 TDebugFn iDebugFn; /**< @internalComponent */
466 TAny* iDebugPtr; /**< @internalComponent */
467 TInt iTickPeriod; /**< @internalComponent */ // in microseconds
469 This member is intended for use by ASSP/variant interrupt code as a convenient
470 location to store rounding error information where hardware interrupts are not
471 exactly one millisecond. The Symbian kernel does not make any use of this member.
478 GLREF_D NTimerQ TheTimerQ;
483 inline TUint32 NTickCount()
484 {return TheTimerQ.iMsCount;}
489 inline TInt NTickPeriod()
490 {return TheTimerQ.iTickPeriod;}
497 extern void NKCrashHandler(TInt aPhase, const TAny* a0, TInt a1);
502 extern TUint32 CrashState;
506 #define __ACQUIRE_BTRACE_LOCK()
507 #define __RELEASE_BTRACE_LOCK()
512 TBool InterruptsStatus(TBool aRequest);
514 //declarations for the checking of kernel preconditions
519 PRECOND_FUNCTION_CALLER is needed for __ASSERT_WITH_MESSAGE_ALWAYS(),
520 so is outside the #ifdef _DEBUG.
522 #ifndef PRECOND_FUNCTION_CALLER
523 #define PRECOND_FUNCTION_CALLER 0
531 #define MASK_NO_FAST_MUTEX 0x1
532 #define MASK_CRITICAL 0x2
533 #define MASK_NO_CRITICAL 0x4
534 #define MASK_KERNEL_LOCKED 0x8
535 #define MASK_KERNEL_UNLOCKED 0x10
536 #define MASK_KERNEL_LOCKED_ONCE 0x20
537 #define MASK_INTERRUPTS_ENABLED 0x40
538 #define MASK_INTERRUPTS_DISABLED 0x80
539 #define MASK_SYSTEM_LOCKED 0x100
540 #define MASK_NOT_ISR 0x400
541 #define MASK_NOT_IDFC 0x800
542 #define MASK_NOT_THREAD 0x1000
543 #define MASK_NO_CRITICAL_IF_USER 0x2000
544 #define MASK_THREAD_STANDARD ( MASK_NO_FAST_MUTEX | MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC )
545 #define MASK_THREAD_CRITICAL ( MASK_THREAD_STANDARD | MASK_CRITICAL )
546 #define MASK_ALWAYS_FAIL 0x4000
547 #define MASK_NO_RESCHED 0x8000
549 #if defined(__STANDALONE_NANOKERNEL__) || (!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__))
550 #define CHECK_PRECONDITIONS(mask,function)
551 #define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function)
557 extern "C" TInt CheckPreconditions(TUint32 aConditionMask, const char* aFunction, TLinAddr aAddr);
561 #define CHECK_PRECONDITIONS(mask,function) CheckPreconditions(mask,function,PRECOND_FUNCTION_CALLER)
563 #ifdef __KERNEL_APIS_CONTEXT_CHECKS_FAULT__
568 #define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function) \
569 __ASSERT_DEBUG( (cond), ( \
570 DEBUGPRINT("Assertion failed: %s\nFunction: %s; called from: %08x\n",message,function,PRECOND_FUNCTION_CALLER),\
571 NKFault(function, 0)))
573 #else//!__KERNEL_APIS_CONTEXT_CHECKS_FAULT__
577 #define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function) \
578 __ASSERT_DEBUG( (cond), \
579 DEBUGPRINT("Assertion failed: %s\nFunction: %s; called from: %08x\n",message,function,PRECOND_FUNCTION_CALLER))
582 #endif//__KERNEL_APIS_CONTEXT_CHECKS_FAULT__
583 #endif//(!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__))
587 #define CHECK_PRECONDITIONS(mask,function)
588 #define __ASSERT_WITH_MESSAGE_DEBUG(cond,message,function)
592 #if (!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__))
593 #define __ASSERT_WITH_MESSAGE_ALWAYS(cond,message,function)
595 #ifdef __KERNEL_APIS_CONTEXT_CHECKS_FAULT__
599 #define __ASSERT_WITH_MESSAGE_ALWAYS(cond,message,function) \
600 __ASSERT_ALWAYS( (cond), ( \
601 DEBUGPRINT("Assertion failed: %s\nFunction: %s; called from: %08x\n",message,function,PRECOND_FUNCTION_CALLER),\
602 NKFault(function, 0)))
607 #define __ASSERT_WITH_MESSAGE_ALWAYS(cond,message,function) \
608 __ASSERT_ALWAYS( (cond), \
609 DEBUGPRINT("Assertion failed: %s\nFunction: %s; called from: %08x\n",message,function,PRECOND_FUNCTION_CALLER))
610 #endif//__KERNEL_APIS_CONTEXT_CHECKS_FAULT__
611 #endif//(!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__))