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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\include\nkernsmp\dfcs.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.
35 /********************************************
36 * Delayed function call queue
37 ********************************************/
43 The number of DFC priorities the system has, which range from 0
44 to KNumDfcPriorities - 1.
46 const TInt KNumDfcPriorities=8;
52 The highest priority level for a DFC, which is equal to KNumDfcPriorities + 1.
54 const TInt KMaxDfcPriority=KNumDfcPriorities-1;
63 Each DFC queue is associated with a thread.
67 class TDfcQue : public TPriList<TDfc,KNumDfcPriorities>
72 inline TBool IsEmpty(); /**< @internalComponent */
73 static void ThreadFunction(TAny* aDfcQ);
75 NThreadBase* iThread; /**< @internalComponent */
81 inline TBool TDfcQue::IsEmpty()
82 { return (iPresent[0]==0); }
84 /********************************************
85 * Delayed function call
86 ********************************************/
92 The function type that can be set to run as a DFC or IDFC.
96 typedef NEventFn TDfcFn;
102 Defines a Deferred Function Call (DFC) or Immediate Deferred Function Call (IDFC).
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.
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.
121 class TDfc : public NEventHandler
123 // iPriority<KNumDfcPriorities => DFC, otherwise IDFC
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
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).
141 // For IDFC iHType = EEventHandlerIDFC
142 // For DFC iHType = priority (0 to 7) and iTied points to TDfcQue (since DFCs can't be tied)
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
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
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 */
167 inline TBool IsValid(); /**< @internalComponent */
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 */
180 friend class TSubScheduler;
181 friend class TCancelIPI;
182 friend class TDfcQue;
190 Used to find out if the DFC/IDFC is queued on either the pending or final DFC queue.
192 @return TRUE if the DFC/IDFC is queued, otherwise FALSE.
195 inline TBool TDfc::Queued()
196 { TUint32 state = i8816.iHState16; return state && (state&0xE0)!=0xC0; }
202 Determines if the object represents an IDFC rather than a DFC.
204 @return TRUE if this represents an IDFC, otherwise FALSE.
206 inline TBool TDfc::IsIDFC()
207 { return iHType == EEventHandlerIDFC; }
213 Determines if the object represents a DFC rather than an IDFC.
215 @return TRUE if this represents a DFC, otherwise FALSE.
217 inline TBool TDfc::IsDFC()
218 { return iHType < KNumDfcPriorities; }
225 Sets the DFC queue that the DFC is to added to and executed by.
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
233 The DFC queue that the DFC is to be added to and executed by.
236 inline void TDfc::SetDfcQ(TDfcQue* aDfcQ)
243 Sets the function that is run when the DFC/IDFC is scheduled.
247 The function that the DFC/IDFC runs when it is scheduled.
250 inline void TDfc::SetFunction(TDfcFn aDfcFn)
256 inline void TDfc::SetPriority(TInt aPriority)
257 { iHState = (TUint8)aPriority; }
259 #ifdef __INCLUDE_TDFC_DEFINES__
263 #define iDfcState (i8816.iHState16)
268 #define DFC_STATE(p) ((p)->i8816.iHState16)
272 /********************************************
273 * Kernel-side asynchronous request,
274 * based on DFC queueing
275 ********************************************/
280 class TAsyncRequest : protected TDfc
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()
291 IMPORT_C TAsyncRequest(TDfcFn aFunction, TDfcQue* aDfcQ, TInt aPriority);
293 TAny* iCompletionObject;
294 volatile TBool iCancel;