kernel/eka/include/nkernsmp/dfcs.h
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2007-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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\include\nkernsmp\dfcs.h
       
    15 // 
       
    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.
       
    19 //
       
    20 
       
    21 #ifndef __DFCS_H__
       
    22 #define __DFCS_H__
       
    23 
       
    24 #include <nklib.h>
       
    25 #include <nk_event.h>
       
    26 
       
    27 class NTimer;
       
    28 class NThreadBase;
       
    29 class NThread;
       
    30 class NFastSemaphore;
       
    31 class NFastMutex;
       
    32 class TSubScheduler;
       
    33 class TCancelIPI;
       
    34 
       
    35 /********************************************
       
    36  * Delayed function call queue
       
    37  ********************************************/
       
    38 
       
    39 /**
       
    40 @publishedPartner
       
    41 @released
       
    42 
       
    43 The number of DFC priorities the system has, which range from 0
       
    44 to KNumDfcPriorities - 1.
       
    45 */
       
    46 const TInt KNumDfcPriorities=8;
       
    47 
       
    48 /**
       
    49 @publishedPartner
       
    50 @released
       
    51 
       
    52 The highest priority level for a DFC, which is equal to KNumDfcPriorities + 1.
       
    53 */
       
    54 const TInt KMaxDfcPriority=KNumDfcPriorities-1;
       
    55 
       
    56 class TDfc;
       
    57 /**
       
    58 @publishedPartner
       
    59 @prototype
       
    60 
       
    61 Defines a DFC queue.
       
    62 
       
    63 Each DFC queue is associated with a thread.
       
    64 
       
    65 @see TDfc
       
    66 */
       
    67 class TDfcQue : public TPriList<TDfc,KNumDfcPriorities>
       
    68 	{
       
    69 public:
       
    70 	IMPORT_C TDfcQue();
       
    71 
       
    72 	inline TBool IsEmpty();		/**< @internalComponent */
       
    73 	static void ThreadFunction(TAny* aDfcQ);
       
    74 public:
       
    75 	NThreadBase* iThread;		/**< @internalComponent */
       
    76 	};
       
    77 
       
    78 /**
       
    79 @internalComponent
       
    80 */
       
    81 inline TBool TDfcQue::IsEmpty()
       
    82 	{ return (iPresent[0]==0); }
       
    83 
       
    84 /********************************************
       
    85  * Delayed function call
       
    86  ********************************************/
       
    87 
       
    88 /**
       
    89 @publishedPartner
       
    90 @released
       
    91 
       
    92 The function type that can be set to run as a DFC or IDFC.
       
    93 
       
    94 @see TDfc
       
    95 */
       
    96 typedef NEventFn TDfcFn;
       
    97 
       
    98 /**
       
    99 @publishedPartner
       
   100 @prototype
       
   101 
       
   102 Defines a Deferred Function Call (DFC) or Immediate Deferred Function Call (IDFC).
       
   103 
       
   104 A DFC is a kernel object that specifies a function to be run in a thread,
       
   105 which is processing a DFC queue. A DFC is added to a DFC queue that is 
       
   106 associated with a given thread, where it is cooperatively scheduled with other
       
   107 DFCs on that queue.  Queued DFCs are run in order of their priority, followed
       
   108 by the order they where queued.  When the DFC gets to run, the function is run
       
   109 kernel side, and no other DFC in this queue will get to run until it 
       
   110 completes. A DFC can be queued from any context.
       
   111 
       
   112 An IDFC is run as soon as the scheduler is next run, which is during the IRQ
       
   113 postamble if queued from an ISR; when the currently-running IDFC completes if
       
   114 queued from an IDFC; or when the kernel is next unlocked if queued from thread
       
   115 context.  Unlike a DFC, the IDFC is not run from a thread context, and its
       
   116 execution time must be much smaller.  For these reasons, IDFCs are rarely used
       
   117 directly, but are used for implementation of the kernel and RTOS personality
       
   118 layers.  An important use of IDFCs is in the implementation of queuing DFCs from
       
   119 an ISR context.  IDFCs are run with interrupts enabled but the kernel locked.
       
   120 */
       
   121 class TDfc : public NEventHandler
       
   122 	{
       
   123 	// iPriority<KNumDfcPriorities => DFC, otherwise IDFC
       
   124 	//
       
   125 	// iHState2	= 0 normally
       
   126 	//			= Bit n is set if CPU n is waiting to cancel this DFC
       
   127 	// iHState1	= 0 if not on any list
       
   128 	//			= 100nnnnn if on CPU n endogenous IDFC/DFC queue
       
   129 	//			= 101nnnnn if on CPU n exogenous IDFC queue
       
   130 	//			= 110nnnnn if running on CPU n
       
   131 	//			= 111nnnnn if running on CPU n and a second execution is also pending (Add() was called while running)
       
   132 	//			= 011nnnnn if running on CPU n and a second idle queue is also pending (QueueOnIdle() was called while running)
       
   133 	//			= 0010000g if idle DFC generation g (could be either on idle queue or CPU endogenous IDFC/DFC queue)
       
   134 	//			= 00000001 if on final DFC queue
       
   135 	// iHState1 and iHState2 are accessed together as a single 16 bit iDfcState
       
   136 	//
       
   137 	// iHState0 is set to 0 when a DFC/IDFC is added to a CPUs endogenous IDFC
       
   138 	// queue or to the idle queue. It is set to 1 if and when BeginTiedEvent()
       
   139 	// is subsequently called (thus only for tied IDFCs).
       
   140 	//
       
   141 	// For IDFC iHType = EEventHandlerIDFC
       
   142 	// For DFC iHType = priority (0 to 7) and iTied points to TDfcQue (since DFCs can't be tied)
       
   143 	//
       
   144 public:
       
   145 	IMPORT_C TDfc(TDfcFn aFunction, TAny* aPtr);									// create IDFC
       
   146 	IMPORT_C TDfc(NSchedulable* aTied, TDfcFn aFunction, TAny* aPtr);				// create IDFC tied to a thread or group
       
   147 	IMPORT_C TDfc(TDfcFn aFunction, TAny* aPtr, TInt aPriority);					// create DFC, queue to be set later
       
   148 	IMPORT_C TDfc(TDfcFn aFunction, TAny* aPtr, TDfcQue* aDfcQ, TInt aPriority);	// create DFC
       
   149 	IMPORT_C ~TDfc();
       
   150 	IMPORT_C TBool Add();						// call from ISR or IDFC or thread with kernel locked
       
   151 	IMPORT_C TBool Cancel();					// call from anywhere except ISR
       
   152 	IMPORT_C TBool Enque();						// call from thread
       
   153 	IMPORT_C TBool Enque(NFastMutex* aMutex);	// call from thread, signal fast mutex (anti-thrash)
       
   154 	IMPORT_C TBool DoEnque();					// call from IDFC or thread with kernel locked
       
   155 	IMPORT_C TBool RawAdd();					// same as Add() but without checks for 'correct' usage or other instrumentation
       
   156 	IMPORT_C TBool QueueOnIdle();				// queue the DFC to be run when the system goes idle
       
   157 	IMPORT_C TInt SetTied(NSchedulable* aTied);	// tie an IDFC to a thread or group
       
   158 	IMPORT_C NThreadBase* Thread();				// thread on which DFC runs, NULL for IDFC
       
   159 public:
       
   160 	inline TBool Queued();
       
   161 	inline TBool IsIDFC();
       
   162 	inline TBool IsDFC();
       
   163 	inline void SetDfcQ(TDfcQue* aDfcQ);
       
   164 	inline void SetFunction(TDfcFn aDfcFn);
       
   165 	inline void SetPriority(TInt aPriority);			/**< @internalComponent */
       
   166 private:
       
   167 	inline TBool IsValid();								/**< @internalComponent */
       
   168 private:
       
   169 	TUint32 AddStateChange();							/**< @internalComponent */
       
   170 	TUint32 MoveToFinalQStateChange();					/**< @internalComponent */
       
   171 	TUint32 TransferIDFCStateChange(TInt aCpu);			/**< @internalComponent */
       
   172 	TUint32 RunIDFCStateChange();						/**< @internalComponent */
       
   173 	TUint32 EndIDFCStateChange(TSubScheduler*);			/**< @internalComponent */
       
   174 	TUint32 EndIDFCStateChange2();						/**< @internalComponent */
       
   175 	TUint32 CancelInitialStateChange();					/**< @internalComponent */
       
   176 	TUint32 CancelFinalStateChange();					/**< @internalComponent */
       
   177 	TUint32 QueueOnIdleStateChange();					/**< @internalComponent */
       
   178 	void ResetState();									/**< @internalComponent */
       
   179 
       
   180 	friend class TSubScheduler;
       
   181 	friend class TCancelIPI;
       
   182 	friend class TDfcQue;
       
   183 	friend class NTimer;
       
   184 	};
       
   185 
       
   186 /**
       
   187 @publishedPartner
       
   188 @prototype
       
   189 
       
   190 Used to find out if the DFC/IDFC is queued on either the pending or final DFC queue.
       
   191 
       
   192 @return TRUE if the DFC/IDFC is queued, otherwise FALSE.
       
   193 
       
   194 */
       
   195 inline TBool TDfc::Queued()
       
   196 	{ TUint32 state = i8816.iHState16; return state && (state&0xE0)!=0xC0; }
       
   197 
       
   198 /**
       
   199 @publishedPartner
       
   200 @prototype
       
   201 
       
   202 Determines if the object represents an IDFC rather than a DFC.
       
   203 
       
   204 @return TRUE if this represents an IDFC, otherwise FALSE.
       
   205 */
       
   206 inline TBool TDfc::IsIDFC()
       
   207 	{ return iHType == EEventHandlerIDFC; }
       
   208 
       
   209 /**
       
   210 @publishedPartner
       
   211 @prototype
       
   212 
       
   213 Determines if the object represents a DFC rather than an IDFC.
       
   214 
       
   215 @return TRUE if this represents a DFC, otherwise FALSE.
       
   216 */
       
   217 inline TBool TDfc::IsDFC()
       
   218 	{ return iHType < KNumDfcPriorities; }
       
   219 
       
   220 
       
   221 /**
       
   222 @publishedPartner
       
   223 @prototype
       
   224 
       
   225 Sets the DFC queue that the DFC is to added to and executed by.
       
   226 
       
   227 Note that this function should only be used in the initialisation of the DFC, 
       
   228 when it is not on any queue.  This function does not move the DFC from one 
       
   229 queue to another.
       
   230 
       
   231 @param aDfcQ
       
   232 
       
   233 	The DFC queue that the DFC is to be added to and executed by.
       
   234 
       
   235 */
       
   236 inline void TDfc::SetDfcQ(TDfcQue* aDfcQ)
       
   237 	{ iDfcQ = aDfcQ; }
       
   238 
       
   239 /**
       
   240 @publishedPartner
       
   241 @prototype
       
   242 
       
   243 Sets the function that is run when the DFC/IDFC is scheduled.
       
   244 
       
   245 @param aDfcFn
       
   246 
       
   247 	The function that the DFC/IDFC runs when it is scheduled.
       
   248 
       
   249 */
       
   250 inline void TDfc::SetFunction(TDfcFn aDfcFn)
       
   251 	{ iFn = aDfcFn; }
       
   252 
       
   253 /**
       
   254 @internalComponent
       
   255 */
       
   256 inline void TDfc::SetPriority(TInt aPriority)
       
   257 	{ iHState = (TUint8)aPriority; }
       
   258 
       
   259 #ifdef __INCLUDE_TDFC_DEFINES__
       
   260 /**
       
   261 @internalComponent
       
   262 */
       
   263 #define	iDfcState		(i8816.iHState16)
       
   264 
       
   265 /**
       
   266 @internalComponent
       
   267 */
       
   268 #define DFC_STATE(p)	((p)->i8816.iHState16)
       
   269 #endif
       
   270 
       
   271 
       
   272 /********************************************
       
   273  * Kernel-side asynchronous request,
       
   274  * based on DFC queueing
       
   275  ********************************************/
       
   276 
       
   277 /**
       
   278 @internalComponent
       
   279 */
       
   280 class TAsyncRequest : protected TDfc
       
   281 	{
       
   282 public:
       
   283 	IMPORT_C void Send(TDfc* aCompletionDfc);
       
   284 	IMPORT_C void Send(NFastSemaphore* aCompletionSemaphore);
       
   285 	IMPORT_C TInt SendReceive();
       
   286 	IMPORT_C void Cancel();
       
   287 	IMPORT_C void Complete(TInt aResult);
       
   288 	inline TBool PollForCancel()
       
   289 		{ return iCancel; }
       
   290 protected:
       
   291 	IMPORT_C TAsyncRequest(TDfcFn aFunction, TDfcQue* aDfcQ, TInt aPriority);
       
   292 protected:
       
   293 	TAny*	iCompletionObject;
       
   294 	volatile TBool	iCancel;
       
   295 	TInt	iResult;
       
   296 	};
       
   297 
       
   298 
       
   299 #endif