os/kernelhwsrv/kernel/eka/include/nkernsmp/dfcs.h
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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