diff -r 000000000000 -r 96e5fb8b040d kernel/eka/include/nkernsmp/dfcs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/include/nkernsmp/dfcs.h Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,299 @@ +// Copyright (c) 2007-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\nkernsmp\dfcs.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 __DFCS_H__ +#define __DFCS_H__ + +#include +#include + +class NTimer; +class NThreadBase; +class NThread; +class NFastSemaphore; +class NFastMutex; +class TSubScheduler; +class TCancelIPI; + +/******************************************** + * Delayed function call queue + ********************************************/ + +/** +@publishedPartner +@released + +The number of DFC priorities the system has, which range from 0 +to KNumDfcPriorities - 1. +*/ +const TInt KNumDfcPriorities=8; + +/** +@publishedPartner +@released + +The highest priority level for a DFC, which is equal to KNumDfcPriorities + 1. +*/ +const TInt KMaxDfcPriority=KNumDfcPriorities-1; + +class TDfc; +/** +@publishedPartner +@prototype + +Defines a DFC queue. + +Each DFC queue is associated with a thread. + +@see TDfc +*/ +class TDfcQue : public TPriList + { +public: + IMPORT_C TDfcQue(); + + inline TBool IsEmpty(); /**< @internalComponent */ + static void ThreadFunction(TAny* aDfcQ); +public: + NThreadBase* iThread; /**< @internalComponent */ + }; + +/** +@internalComponent +*/ +inline TBool TDfcQue::IsEmpty() + { return (iPresent[0]==0); } + +/******************************************** + * Delayed function call + ********************************************/ + +/** +@publishedPartner +@released + +The function type that can be set to run as a DFC or IDFC. + +@see TDfc +*/ +typedef NEventFn TDfcFn; + +/** +@publishedPartner +@prototype + +Defines a Deferred Function Call (DFC) or Immediate Deferred Function Call (IDFC). + +A DFC is a kernel object that specifies a function to be run in a thread, +which is processing a DFC queue. A DFC is added to a DFC queue that is +associated with a given thread, where it is cooperatively scheduled with other +DFCs on that queue. Queued DFCs are run in order of their priority, followed +by the order they where queued. When the DFC gets to run, the function is run +kernel side, and no other DFC in this queue will get to run until it +completes. A DFC can be queued from any context. + +An IDFC is run as soon as the scheduler is next run, which is during the IRQ +postamble if queued from an ISR; when the currently-running IDFC completes if +queued from an IDFC; or when the kernel is next unlocked if queued from thread +context. Unlike a DFC, the IDFC is not run from a thread context, and its +execution time must be much smaller. For these reasons, IDFCs are rarely used +directly, but are used for implementation of the kernel and RTOS personality +layers. An important use of IDFCs is in the implementation of queuing DFCs from +an ISR context. IDFCs are run with interrupts enabled but the kernel locked. +*/ +class TDfc : public NEventHandler + { + // iPriority DFC, otherwise IDFC + // + // iHState2 = 0 normally + // = Bit n is set if CPU n is waiting to cancel this DFC + // iHState1 = 0 if not on any list + // = 100nnnnn if on CPU n endogenous IDFC/DFC queue + // = 101nnnnn if on CPU n exogenous IDFC queue + // = 110nnnnn if running on CPU n + // = 111nnnnn if running on CPU n and a second execution is also pending (Add() was called while running) + // = 011nnnnn if running on CPU n and a second idle queue is also pending (QueueOnIdle() was called while running) + // = 0010000g if idle DFC generation g (could be either on idle queue or CPU endogenous IDFC/DFC queue) + // = 00000001 if on final DFC queue + // iHState1 and iHState2 are accessed together as a single 16 bit iDfcState + // + // iHState0 is set to 0 when a DFC/IDFC is added to a CPUs endogenous IDFC + // queue or to the idle queue. It is set to 1 if and when BeginTiedEvent() + // is subsequently called (thus only for tied IDFCs). + // + // For IDFC iHType = EEventHandlerIDFC + // For DFC iHType = priority (0 to 7) and iTied points to TDfcQue (since DFCs can't be tied) + // +public: + IMPORT_C TDfc(TDfcFn aFunction, TAny* aPtr); // create IDFC + IMPORT_C TDfc(NSchedulable* aTied, TDfcFn aFunction, TAny* aPtr); // create IDFC tied to a thread or group + IMPORT_C TDfc(TDfcFn aFunction, TAny* aPtr, TInt aPriority); // create DFC, queue to be set later + IMPORT_C TDfc(TDfcFn aFunction, TAny* aPtr, TDfcQue* aDfcQ, TInt aPriority); // create DFC + IMPORT_C ~TDfc(); + IMPORT_C TBool Add(); // call from ISR or IDFC or thread with kernel locked + IMPORT_C TBool Cancel(); // call from anywhere except ISR + IMPORT_C TBool Enque(); // call from thread + IMPORT_C TBool Enque(NFastMutex* aMutex); // call from thread, signal fast mutex (anti-thrash) + IMPORT_C TBool DoEnque(); // call from IDFC or thread with kernel locked + IMPORT_C TBool RawAdd(); // same as Add() but without checks for 'correct' usage or other instrumentation + IMPORT_C TBool QueueOnIdle(); // queue the DFC to be run when the system goes idle + IMPORT_C TInt SetTied(NSchedulable* aTied); // tie an IDFC to a thread or group + IMPORT_C NThreadBase* Thread(); // thread on which DFC runs, NULL for IDFC +public: + inline TBool Queued(); + inline TBool IsIDFC(); + inline TBool IsDFC(); + inline void SetDfcQ(TDfcQue* aDfcQ); + inline void SetFunction(TDfcFn aDfcFn); + inline void SetPriority(TInt aPriority); /**< @internalComponent */ +private: + inline TBool IsValid(); /**< @internalComponent */ +private: + TUint32 AddStateChange(); /**< @internalComponent */ + TUint32 MoveToFinalQStateChange(); /**< @internalComponent */ + TUint32 TransferIDFCStateChange(TInt aCpu); /**< @internalComponent */ + TUint32 RunIDFCStateChange(); /**< @internalComponent */ + TUint32 EndIDFCStateChange(TSubScheduler*); /**< @internalComponent */ + TUint32 EndIDFCStateChange2(); /**< @internalComponent */ + TUint32 CancelInitialStateChange(); /**< @internalComponent */ + TUint32 CancelFinalStateChange(); /**< @internalComponent */ + TUint32 QueueOnIdleStateChange(); /**< @internalComponent */ + void ResetState(); /**< @internalComponent */ + + friend class TSubScheduler; + friend class TCancelIPI; + friend class TDfcQue; + friend class NTimer; + }; + +/** +@publishedPartner +@prototype + +Used to find out if the DFC/IDFC is queued on either the pending or final DFC queue. + +@return TRUE if the DFC/IDFC is queued, otherwise FALSE. + +*/ +inline TBool TDfc::Queued() + { TUint32 state = i8816.iHState16; return state && (state&0xE0)!=0xC0; } + +/** +@publishedPartner +@prototype + +Determines if the object represents an IDFC rather than a DFC. + +@return TRUE if this represents an IDFC, otherwise FALSE. +*/ +inline TBool TDfc::IsIDFC() + { return iHType == EEventHandlerIDFC; } + +/** +@publishedPartner +@prototype + +Determines if the object represents a DFC rather than an IDFC. + +@return TRUE if this represents a DFC, otherwise FALSE. +*/ +inline TBool TDfc::IsDFC() + { return iHType < KNumDfcPriorities; } + + +/** +@publishedPartner +@prototype + +Sets the DFC queue that the DFC is to added to and executed by. + +Note that this function should only be used in the initialisation of the DFC, +when it is not on any queue. This function does not move the DFC from one +queue to another. + +@param aDfcQ + + The DFC queue that the DFC is to be added to and executed by. + +*/ +inline void TDfc::SetDfcQ(TDfcQue* aDfcQ) + { iDfcQ = aDfcQ; } + +/** +@publishedPartner +@prototype + +Sets the function that is run when the DFC/IDFC is scheduled. + +@param aDfcFn + + The function that the DFC/IDFC runs when it is scheduled. + +*/ +inline void TDfc::SetFunction(TDfcFn aDfcFn) + { iFn = aDfcFn; } + +/** +@internalComponent +*/ +inline void TDfc::SetPriority(TInt aPriority) + { iHState = (TUint8)aPriority; } + +#ifdef __INCLUDE_TDFC_DEFINES__ +/** +@internalComponent +*/ +#define iDfcState (i8816.iHState16) + +/** +@internalComponent +*/ +#define DFC_STATE(p) ((p)->i8816.iHState16) +#endif + + +/******************************************** + * Kernel-side asynchronous request, + * based on DFC queueing + ********************************************/ + +/** +@internalComponent +*/ +class TAsyncRequest : protected TDfc + { +public: + IMPORT_C void Send(TDfc* aCompletionDfc); + IMPORT_C void Send(NFastSemaphore* aCompletionSemaphore); + IMPORT_C TInt SendReceive(); + IMPORT_C void Cancel(); + IMPORT_C void Complete(TInt aResult); + inline TBool PollForCancel() + { return iCancel; } +protected: + IMPORT_C TAsyncRequest(TDfcFn aFunction, TDfcQue* aDfcQ, TInt aPriority); +protected: + TAny* iCompletionObject; + volatile TBool iCancel; + TInt iResult; + }; + + +#endif