kernel/eka/include/nkern/nk_priv.h
changeset 0 a41df078684a
child 8 538db54a451d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/include/nkern/nk_priv.h	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,603 @@
+// Copyright (c) 1998-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\nkern\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 <cpudefs.h>
+#include <nkern.h>
+
+/********************************************
+ * DFCs
+ ********************************************/
+
+/**
+@internalComponent
+*/
+inline TBool TDfc::TestAndSetQueued()
+	{ return __e32_atomic_swp_ord8(&iSpare3, 1); }
+
+/********************************************
+ * Thread
+ ********************************************/
+
+class TUserModeCallback;
+
+/**
+@publishedPartner
+@released
+
+Base class for a nanokernel thread.
+*/
+class NThreadBase : public TPriListLink
+	{
+public:
+    /**
+    Defines the possible states of a nanokernel thread.
+    */
+	enum NThreadState
+		{
+		/**
+		The thread is eligible for execution.
+		
+		Threads in this state are linked into the ready list.
+		The highest priority READY thread is the one that will run, unless it
+		is blocked on a fast mutex.
+		*/
+		EReady,
+		
+		/**
+		The thread is explicitly suspended (rather than blocking on
+		a wait object).
+		*/
+		ESuspended,
+		
+		/**
+		The thread is blocked waiting for a fast semaphore to be signalled.
+		*/
+		EWaitFastSemaphore,
+		
+		/**
+		The thread is blocked waiting for a specific time period to elapse.
+		*/
+		ESleep,
+		
+		/**
+		The thread is blocked on a wait object implemented in a layer above
+		the nanokernel.
+		
+		In practice, this means that it is blocked on a Symbian OS
+		semaphore or mutex.
+		*/
+		EBlocked,
+		
+		/**
+		The thread has terminated and will not execute again.
+		*/
+		EDead,
+		
+		/**
+		The thread is a DFC-handling thread and it is blocked waiting for
+		the DFC to be queued.
+		*/
+		EWaitDfc,
+		
+		/**
+		Not a thread state, but defines the maximum number of states.
+		*/
+		ENumNStates
+		};
+
+
+
+
+    /**
+    Defines a set of values that, when passed to a nanokernel state handler,
+    indicates which operation is being performed on the thread.
+    
+    Every thread that can use a new type of wait object, must have a nanokernel
+    state handler installed to handle operations on that thread while it is
+    waiting on that wait object.
+    
+    A wait handler has the signature:
+    @code
+    void StateHandler(NThread* aThread, TInt aOp, TInt aParam);
+    @endcode
+    
+    where aOp is one of these enum values.
+    
+    The state handler is always called with preemption disabled.
+    */
+	enum NThreadOperation
+		{
+		/**
+		Indicates that the thread is suspended while not in a critical section,
+		and not holding a fast mutex.
+		
+		StateHandler() is called in whichever context
+		NThreadBase::Suspend() is called from.
+		
+		Note that the third parameter passed to StateHandler() contains
+		the requested suspension count.
+		*/
+		ESuspend=0,
+		
+		/**
+		Indicates that the thread is being resumed while suspended, and
+		the last suspension has been removed.
+		
+		StateHandler() is called in whichever context
+		NThreadBase::Resume() is called from.
+		*/
+		EResume=1,
+		
+		/**
+		Indicates that the thread has all suspensions cancelled while
+		actually suspended.
+		
+		Statehandler() is called in whichever context
+		NThreadBase::ForceResume() is called from.
+		*/
+		EForceResume=2,
+		
+		/**
+		Indicates that the thread is being released from its wait.
+		
+		Statehandler() is called in whichever context
+		NThreadBase::Release() is called from.
+		*/
+		ERelease=3,
+		
+		/**
+		Indicates that the thread's priority is being changed.
+		
+		StateHandler() is called in whichever context
+		NThreadBase::SetPriority() is called from.
+		*/
+		EChangePriority=4,
+		
+		/**
+		Indicates that the thread has called NKern::ThreadLeaveCS() with
+		an unknown NThreadBase::iCsFunction that is negative, but not equal
+		to NThreadBase::ECsExitPending.
+		
+		Note that NThreadBase::iCsFunction is internal to Symbian OS.
+		*/
+		ELeaveCS=5,
+		
+		/**
+		Indicates that the thread's wait timeout has expired, and no timeout
+		handler has been defined for that thread.
+	    
+	    StateHandler() is called in the context of the nanokernel
+	    timer thread, DfcThread1.
+	    */
+		ETimeout=6,
+		};
+		
+	enum NThreadCSFunction
+		{
+		ECSExitPending=-1,
+		ECSExitInProgress=-2
+		};
+
+	enum NThreadTimeoutOp
+		{
+		ETimeoutPreamble=0,
+		ETimeoutPostamble=1,
+		ETimeoutSpurious=2,
+		};
+public:
+	NThreadBase();
+	TInt Create(SNThreadCreateInfo& anInfo,	TBool aInitial);
+	IMPORT_C void CheckSuspendThenReady();
+	IMPORT_C void Ready();
+	void DoReady();
+	void DoCsFunction();
+	IMPORT_C TBool Suspend(TInt aCount);
+	IMPORT_C TBool Resume();
+	IMPORT_C TBool ForceResume();
+	IMPORT_C void Release(TInt aReturnCode);
+	IMPORT_C void RequestSignal();
+	IMPORT_C void SetPriority(TInt aPriority);
+	void SetEntry(NThreadFunction aFunction);
+	IMPORT_C void Kill();
+	void Exit();
+	void ForceExit();
+	// hooks for platform-specific code
+	void OnKill(); 
+	void OnExit();
+public:
+	static void TimerExpired(TAny* aPtr);
+	inline void UnknownState(TInt aOp, TInt aParam)
+		{ (*iHandlers->iStateHandler)((NThread*)this,aOp,aParam); }
+
+	/** @internalComponent */
+	inline TUint8 Attributes()
+		{ return iSpare2; }
+
+	/** @internalComponent */
+	inline TUint8 SetAttributes(TUint8 aNewAtt)
+		{ return __e32_atomic_swp_ord8(&iSpare2, aNewAtt); }
+
+	/** @internalComponent */
+	inline TUint8 ModifyAttributes(TUint8 aClearMask, TUint8 aSetMask)
+		{ return __e32_atomic_axo_ord8(&iSpare2, (TUint8)~(aClearMask|aSetMask), aSetMask); }
+
+	/** @internalComponent */
+	inline void SetAddressSpace(TAny* a)
+		{ iAddressSpace=a; }
+
+	inline void SetReturnValue(TInt aValue)
+		{ iReturnValue=aValue; }
+	inline void SetExtraContext(TAny* a, TInt aSize)
+		{ iExtraContext = a; iExtraContextSize = aSize; }
+
+	/** @internalComponent */
+	void CallUserModeCallbacks();
+public:
+//	TUint8 iNState;														// use iSpare1 for state
+//	TUint8 i_ThrdAttr;						/**< @internalComponent */	// use iSpare2 for attributes
+//	TUint8 iUserContextType;											// use iSpare3
+	NFastMutex* iHeldFastMutex;				/**< @internalComponent */	// fast mutex held by this thread
+	NFastMutex* iWaitFastMutex;				/**< @internalComponent */	// fast mutex on which this thread is blocked
+	TAny* iAddressSpace;					/**< @internalComponent */
+	TInt iTime;															// time remaining
+	TInt iTimeslice;													// timeslice for this thread
+	NFastSemaphore iRequestSemaphore;		/**< @internalComponent */
+	TAny* iWaitObj;														// object on which this thread is waiting
+	TInt iSuspendCount;						/**< @internalComponent */	// -how many times we have been suspended
+	TInt iCsCount;							/**< @internalComponent */	// critical section count
+	TInt iCsFunction;						/**< @internalComponent */	// what to do on leaving CS: +n=suspend n times, 0=nothing, -1=exit
+	NTimer iTimer;							/**< @internalComponent */
+	TInt iReturnValue;
+	TLinAddr iStackBase;					/**< @internalComponent */
+	TInt iStackSize;						/**< @internalComponent */
+	const SNThreadHandlers* iHandlers;		/**< @internalComponent */	// additional thread event handlers
+	const SFastExecTable* iFastExecTable;	/**< @internalComponent */
+	const SSlowExecEntry* iSlowExecTable;	/**< @internalComponent */	// points to first entry iEntries[0]
+	TLinAddr iSavedSP;						/**< @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
+	TUint iLastStartTime;					/**< @internalComponent */	// last start of execution timestamp
+	TUint64 iTotalCpuTime;					/**< @internalComponent */	// total time spent running, in hi-res timer ticks
+	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.
+	TUserModeCallback* volatile iUserModeCallbacks;	/**< @internalComponent */	// Head of singly-linked list of callbacks
+	TUint32 iSpare7;						/**< @internalComponent */	// spare to allow growth while preserving BC
+	TUint32 iSpare8;						/**< @internalComponent */	// spare to allow growth while preserving BC
+	};
+
+__ASSERT_COMPILE(!(_FOFF(NThreadBase,iTotalCpuTime)&7));
+
+#ifdef __INCLUDE_NTHREADBASE_DEFINES__
+#define iNState				iSpare1
+#define	i_ThrdAttr			iSpare2
+#define iUserContextType	iSpare3
+#endif
+
+#define	i_NThread_BasePri	iPriority
+
+/********************************************
+ * Scheduler
+ ********************************************/
+
+/**
+@internalComponent
+*/
+class TScheduler : public TPriListBase
+	{
+public:
+	TScheduler();
+	void Remove(NThreadBase* aThread);
+	void RotateReadyList(TInt aPriority);
+	void QueueDfcs();
+	static void Reschedule();
+	static void YieldTo(NThreadBase* aThread);
+	void TimesliceTick();
+	IMPORT_C static TScheduler* Ptr();
+	inline void SetProcessHandler(TLinAddr aHandler) {iProcessHandler=aHandler;}
+private:
+	SDblQueLink* iExtraQueues[KNumPriorities-1];
+public:
+	TUint8 iRescheduleNeededFlag;
+	TUint8 iDfcPendingFlag;
+	TInt iKernCSLocked;
+	SDblQue iDfcs;
+	TLinAddr iMonitorExceptionHandler;
+	TLinAddr iProcessHandler;
+	TLinAddr iRescheduleHook;
+	TUint8 iInIDFC;
+	NFastMutex iLock;
+	NThreadBase* iCurrentThread;
+	TAny* iAddressSpace;
+	TAny* iExtras[16];
+	// For EMI support
+	NThread* iSigma;	
+	TDfc* iEmiDfc;
+	TUint32 iEmiMask;
+	TUint32 iEmiState;
+	TUint32 iEmiDfcTrigger;
+	TBool iLogging;
+	TAny* iBufferStart;
+	TAny* iBufferEnd;
+	TAny* iBufferTail;
+	TAny* iBufferHead;
+	// For BTrace suport
+	TUint8 iCpuUsageFilter;
+	TUint8 iFastMutexFilter;
+	BTrace::THandler iBTraceHandler;
+	// Idle notification
+	SDblQue iIdleDfcs;
+	TUint32 iIdleGenerationCount;
+	// Delayed threads
+	SDblQue iDelayedQ;
+	TDfc iDelayDfc;
+	};
+
+GLREF_D TScheduler TheScheduler;
+
+/**
+@internalComponent
+*/
+inline void RescheduleNeeded()
+	{TheScheduler.iRescheduleNeededFlag=TRUE;}
+
+#include <nk_plat.h>
+
+/**
+@internalComponent
+*/
+inline NThread* NCurrentThread()
+	{ return (NThread*)TheScheduler.iCurrentThread; }
+
+
+/**
+@internalComponent
+*/
+#define __NK_ASSERT_UNLOCKED	__NK_ASSERT_DEBUG(TheScheduler.iKernCSLocked==0)
+
+/**
+@internalComponent
+*/
+#define __NK_ASSERT_LOCKED		__NK_ASSERT_DEBUG(TheScheduler.iKernCSLocked!=0)
+
+#ifdef _DEBUG
+/**
+@publishedPartner
+@released
+*/
+#define __ASSERT_NO_FAST_MUTEX	{	\
+								NThread* nt=NKern::CurrentThread();	\
+								__NK_ASSERT_DEBUG(!nt->iHeldFastMutex); \
+								}
+
+/**
+@publishedPartner
+@released
+*/
+#define __ASSERT_FAST_MUTEX(m)	{	\
+								NThread* nt=NKern::CurrentThread();	\
+								__NK_ASSERT_DEBUG(nt->iHeldFastMutex==(m) && (m)->iHoldingThread==nt); \
+								}
+
+/**
+@publishedPartner
+@released
+*/
+#define __ASSERT_SYSTEM_LOCK	{	\
+								NThread* nt=NKern::CurrentThread();	\
+								NFastMutex& m=TScheduler::Ptr()->iLock; \
+								__NK_ASSERT_DEBUG(nt->iHeldFastMutex==&m && m.iHoldingThread==nt); \
+								}
+
+#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
+@released
+*/
+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
+	@released
+	*/
+	TInt iRounding;
+	};
+
+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;
+}
+
+
+#define	__ACQUIRE_BTRACE_LOCK()
+#define	__RELEASE_BTRACE_LOCK()
+
+/**
+@internalComponent
+*/
+TBool InterruptsStatus(TBool aRequest);
+
+
+//declarations for the checking of kernel precoditions
+#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