sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\include\nkernsmp\nkern.h sl@0: // sl@0: // WARNING: This file contains some APIs which are internal and are subject sl@0: // to change without notice. Such APIs should therefore not be used sl@0: // outside the Kernel and Hardware Services package. sl@0: // sl@0: sl@0: #ifndef __NKERN_H__ sl@0: #define __NKERN_H__ sl@0: sl@0: #ifdef __STANDALONE_NANOKERNEL__ sl@0: #undef __IN_KERNEL__ sl@0: #define __IN_KERNEL__ sl@0: #endif sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: extern "C" { sl@0: /** @internalComponent */ sl@0: IMPORT_C void NKFault(const char* file, TInt line); sl@0: /** @internalComponent */ sl@0: void NKIdle(TInt aStage); sl@0: } sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @released sl@0: */ sl@0: #define FAULT() NKFault(__FILE__,__LINE__) sl@0: sl@0: #ifdef _DEBUG sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @released sl@0: */ sl@0: #define __NK_ASSERT_DEBUG(c) ((void) ((c)||(FAULT(),0)) ) sl@0: sl@0: #else sl@0: sl@0: #define __NK_ASSERT_DEBUG(c) sl@0: sl@0: #endif sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @released sl@0: */ sl@0: #define __NK_ASSERT_ALWAYS(c) ((void) ((c)||(FAULT(),0)) ) sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @released sl@0: */ sl@0: const TInt KNumPriorities=64; sl@0: sl@0: const TInt KMaxCpus=8; sl@0: sl@0: class NSchedulable; sl@0: class NThread; sl@0: class NThreadGroup; sl@0: sl@0: sl@0: /** Spin lock sl@0: sl@0: Used for protecting a code fragment against both interrupts and concurrent sl@0: execution on another processor. sl@0: sl@0: List of spin locks in the nanokernel, in deadlock-prevention order: sl@0: A NEventHandler::TiedLock (preemption) sl@0: B NFastMutex spin locks (preemption) sl@0: C Thread spin locks (preemption) sl@0: D Thread group spin locks (preemption) sl@0: E Per-CPU ready list lock (preemption) sl@0: sl@0: a Idle DFC list lock (interrupts) sl@0: b Per-CPU exogenous IDFC queue lock (interrupts) sl@0: c NTimerQ spin lock (interrupts) sl@0: d Generic IPI list locks (interrupts) sl@0: e NIrq spin locks (interrupts) sl@0: f Per-CPU event handler list lock (interrupts) sl@0: z BTrace lock (interrupts) sl@0: sl@0: z must be minimum since BTrace can appear anywhere sl@0: sl@0: interrupt-disabling spinlocks must be lower than preemption-disabling ones sl@0: sl@0: Nestings which actually occur are: sl@0: A > C sl@0: B > C > D > E sl@0: c > f sl@0: Nothing (except possibly z) nested inside a, b, d, f sl@0: e is held while calling HW-poking functions (which might use other spinlocks) sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: class TSpinLock sl@0: { sl@0: public: sl@0: enum TOrder sl@0: { sl@0: // Bit 7 of order clear for locks used with interrupts disabled sl@0: EOrderGenericIrqLow0 =0x00u, // Device driver spin locks, low range sl@0: EOrderGenericIrqLow1 =0x01u, // Device driver spin locks, low range sl@0: EOrderGenericIrqLow2 =0x02u, // Device driver spin locks, low range sl@0: EOrderGenericIrqLow3 =0x03u, // Device driver spin locks, low range sl@0: EOrderBTrace =0x04u, // BTrace lock sl@0: EOrderEventHandlerList =0x07u, // Per-CPU event handler list lock sl@0: EOrderCacheMaintenance =0x08u, // CacheMaintenance (for PL310) sl@0: EOrderNIrq =0x0Au, // NIrq lock sl@0: EOrderGenericIPIList =0x0Du, // Generic IPI list lock sl@0: EOrderNTimerQ =0x10u, // Nanokernel timer queue lock sl@0: EOrderExIDfcQ =0x13u, // Per-CPU exogenous IDFC queue list lock sl@0: EOrderIdleDFCList =0x16u, // Idle DFC list lock sl@0: EOrderGenericIrqHigh0 =0x18u, // Device driver spin locks, high range sl@0: EOrderGenericIrqHigh1 =0x19u, // Device driver spin locks, high range sl@0: EOrderGenericIrqHigh2 =0x1Au, // Device driver spin locks, high range sl@0: EOrderGenericIrqHigh3 =0x1Bu, // Device driver spin locks, high range sl@0: sl@0: // Bit 7 of order set for locks used with interrupts enabled, preemption disabled sl@0: EOrderGenericPreLow0 =0x80u, // Device driver spin locks, low range sl@0: EOrderGenericPreLow1 =0x81u, // Device driver spin locks, low range sl@0: EOrderReadyList =0x88u, // Per-CPU ready list lock sl@0: EOrderThreadGroup =0x90u, // Thread group locks sl@0: EOrderThread =0x91u, // Thread locks sl@0: EOrderFastMutex =0x98u, // Fast mutex locks sl@0: EOrderEventHandlerTied =0x9Cu, // Event handler tied lock sl@0: EOrderGenericPreHigh0 =0x9Eu, // Device driver spin locks, high range sl@0: EOrderGenericPreHigh1 =0x9Fu, // Device driver spin locks, high range sl@0: sl@0: EOrderNone =0xFFu // No order check required (e.g. for dynamic ordering) sl@0: }; sl@0: public: sl@0: IMPORT_C TSpinLock(TUint aOrder); sl@0: IMPORT_C void LockIrq(); /**< @internalComponent disable interrupts and acquire the lock */ sl@0: IMPORT_C void UnlockIrq(); /**< @internalComponent release the lock and enable interrupts */ sl@0: IMPORT_C TBool FlashIrq(); /**< @internalComponent if someone else is waiting for the lock, UnlockIrq() then LockIrq() */ sl@0: IMPORT_C void LockOnly(); /**< @internalComponent acquire the lock, assuming interrupts/preemption already disabled */ sl@0: IMPORT_C void UnlockOnly(); /**< @internalComponent release the lock, don't change interrupt/preemption state */ sl@0: IMPORT_C TBool FlashOnly(); /**< @internalComponent if someone else is waiting for the lock, UnlockOnly() then LockOnly() */ sl@0: IMPORT_C TInt LockIrqSave(); /**< @internalComponent remember original interrupt state then disable interrupts and acquire the lock */ sl@0: IMPORT_C void UnlockIrqRestore(TInt); /**< @internalComponent release the lock then restore original interrupt state */ sl@0: IMPORT_C TBool FlashIrqRestore(TInt); /**< @internalComponent if someone else is waiting for the lock, UnlockIrqRestore() then LockIrq() */ sl@0: IMPORT_C TBool FlashPreempt(); /**< @internalComponent if someone else is waiting for the lock, UnlockOnly(); NKern::PreemptionPoint(); LockOnly(); */ sl@0: private: sl@0: volatile TUint64 iLock; sl@0: }; sl@0: sl@0: sl@0: /** Macro to disable interrupts and acquire the lock. sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_LOCK_IRQ(lock) ((lock).LockIrq()) sl@0: sl@0: /** Macro to release the lock and enable interrupts. sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_UNLOCK_IRQ(lock) (lock).UnlockIrq() sl@0: sl@0: /** Macro to see if someone else is waiting for the lock, enabling IRQs sl@0: then disabling IRQs again. sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_FLASH_IRQ(lock) (lock).FlashIrq() sl@0: sl@0: /** Macro to remember original interrupt state then disable interrupts sl@0: and acquire the lock. sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_LOCK_IRQSAVE(lock) ((lock).LockIrqSave()) sl@0: sl@0: /** Macro to release the lock then restore original interrupt state to that sl@0: supplied. sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_UNLOCK_IRQRESTORE(lock,irq) (lock).UnlockIrqRestore(irq) sl@0: sl@0: /** Macro to see if someone else is waiting for the lock, enabling IRQs to sl@0: the original state supplied then disabling IRQs again. sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_FLASH_IRQRESTORE(lock,irq) (lock).FlashIrqRestore(irq) sl@0: sl@0: /** Macro to acquire the lock. This assumes the caller has already disabled sl@0: interrupts/preemption. sl@0: sl@0: If interrupts/preemption is not disabled a run-time assert will occur sl@0: This is to protect against unsafe code that might lead to same core sl@0: deadlock. sl@0: sl@0: In device driver code it is safer to use __SPIN_LOCK_IRQSAVE() instead, sl@0: although not as efficient should interrupts aleady be disabled for the sl@0: duration the lock is held. sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_LOCK(lock) ((lock).LockOnly()) sl@0: sl@0: /** Macro to release the lock, don't change interrupt/preemption state. sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_UNLOCK(lock) (lock).UnlockOnly() sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define __SPIN_FLASH(lock) (lock).FlashOnly() sl@0: sl@0: /** Macro to see if someone else is waiting for the lock, enabling preemption sl@0: then disabling it again. sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_FLASH_PREEMPT(lock) (lock).FlashPreempt() sl@0: sl@0: sl@0: /** Read/Write Spin lock sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: class TRWSpinLock sl@0: { sl@0: public: sl@0: IMPORT_C TRWSpinLock(TUint aOrder); // Uses same order space as TSpinLock sl@0: sl@0: IMPORT_C void LockIrqR(); /**< @internalComponent disable interrupts and acquire read lock */ sl@0: IMPORT_C void UnlockIrqR(); /**< @internalComponent release read lock and enable interrupts */ sl@0: IMPORT_C TBool FlashIrqR(); /**< @internalComponent if someone else is waiting for write lock, UnlockIrqR() then LockIrqR() */ sl@0: IMPORT_C void LockIrqW(); /**< @internalComponent disable interrupts and acquire write lock */ sl@0: IMPORT_C void UnlockIrqW(); /**< @internalComponent release write lock and enable interrupts */ sl@0: IMPORT_C TBool FlashIrqW(); /**< @internalComponent if someone else is waiting for the lock, UnlockIrqW() then LockIrqW() */ sl@0: IMPORT_C void LockOnlyR(); /**< @internalComponent acquire read lock, assuming interrupts/preemption already disabled */ sl@0: IMPORT_C void UnlockOnlyR(); /**< @internalComponent release read lock, don't change interrupt/preemption state */ sl@0: IMPORT_C TBool FlashOnlyR(); /**< @internalComponent if someone else is waiting for write lock, UnlockOnlyR() then LockOnlyR() */ sl@0: IMPORT_C void LockOnlyW(); /**< @internalComponent acquire write lock, assuming interrupts/preemption already disabled */ sl@0: IMPORT_C void UnlockOnlyW(); /**< @internalComponent release write lock, don't change interrupt/preemption state */ sl@0: IMPORT_C TBool FlashOnlyW(); /**< @internalComponent if someone else is waiting for the lock, UnlockOnlyW() then LockOnlyW() */ sl@0: IMPORT_C TInt LockIrqSaveR(); /**< @internalComponent disable interrupts and acquire read lock, return original interrupt state */ sl@0: IMPORT_C void UnlockIrqRestoreR(TInt); /**< @internalComponent release read lock and reset original interrupt state */ sl@0: IMPORT_C TBool FlashIrqRestoreR(TInt); /**< @internalComponent if someone else is waiting for write lock, UnlockIrqRestoreR() then LockIrqR() */ sl@0: IMPORT_C TInt LockIrqSaveW(); /**< @internalComponent disable interrupts and acquire write lock, return original interrupt state */ sl@0: IMPORT_C void UnlockIrqRestoreW(TInt); /**< @internalComponent release write lock and reset original interrupt state */ sl@0: IMPORT_C TBool FlashIrqRestoreW(TInt); /**< @internalComponent if someone else is waiting for the lock, UnlockIrqRestoreW() then LockIrqW() */ sl@0: IMPORT_C TBool FlashPreemptR(); /**< @internalComponent if someone else is waiting for write lock, UnlockOnlyR(); NKern::PreemptionPoint(); LockOnlyR(); */ sl@0: IMPORT_C TBool FlashPreemptW(); /**< @internalComponent if someone else is waiting for the lock, UnlockOnlyW(); NKern::PreemptionPoint(); LockOnlyW(); */ sl@0: private: sl@0: volatile TUint64 iLock; sl@0: }; sl@0: sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_LOCK_IRQ_R(lock) (lock).LockIrqR() sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_UNLOCK_IRQ_R(lock) (lock).UnlockIrqR() sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_FLASH_IRQ_R(lock) ((lock).FlashIrqR()) sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_LOCK_IRQ_W(lock) (lock).LockIrqW() sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_UNLOCK_IRQ_W(lock) (lock).UnlockIrqW() sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_FLASH_IRQ_W(lock) ((lock).FlashIrqW()) sl@0: sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_LOCK_R(lock) (lock).LockOnlyR() sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_UNLOCK_R(lock) (lock).UnlockOnlyR() sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define __SPIN_FLASH_R(lock) ((lock).FlashOnlyR()) sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_LOCK_W(lock) (lock).LockOnlyW() sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_UNLOCK_W(lock) (lock).UnlockOnlyW() sl@0: sl@0: /** sl@0: @internalComponent sl@0: */ sl@0: #define __SPIN_FLASH_W(lock) ((lock).FlashOnlyW()) sl@0: sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_LOCK_IRQSAVE_R(lock) (lock).LockIrqSaveR() sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_UNLOCK_IRQRESTORE_R(lock,irq) (lock).UnlockIrqRestoreR(irq) sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_FLASH_IRQRESTORE_R(lock,irq) ((lock).FlashIrqRestoreR(irq)) sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_LOCK_IRQSAVE_W(lock) (lock).LockIrqSaveW() sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_UNLOCK_IRQRESTORE_W(lock,irq) (lock).UnlockIrqRestoreW(irq) sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_FLASH_IRQRESTORE_W(lock,irq) ((lock).FlashIrqRestoreW(irq)) sl@0: sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_FLASH_PREEMPT_R(lock) ((lock).FlashPreemptR()) sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: #define __SPIN_FLASH_PREEMPT_W(lock) ((lock).FlashPreemptW()) sl@0: sl@0: sl@0: #ifdef _DEBUG sl@0: #define __INCLUDE_SPIN_LOCK_CHECKS__ sl@0: #endif sl@0: sl@0: sl@0: /** Nanokernel fast semaphore sl@0: sl@0: A light-weight semaphore class that only supports a single waiting thread, sl@0: suitable for the Symbian OS thread I/O semaphore. sl@0: sl@0: Initialising a NFastSemaphore involves two steps: sl@0: sl@0: - Constructing the semaphore sl@0: - Setting the semaphore owning thread (the one allowed to wait on it) sl@0: sl@0: For example, creating one for the current thread to wait on: sl@0: sl@0: @code sl@0: NFastSemaphore sem; sl@0: sem.iOwningThread = NKern::CurrentThread(); sl@0: @endcode sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: class NFastSemaphore sl@0: { sl@0: public: sl@0: inline NFastSemaphore(); sl@0: inline NFastSemaphore(NThreadBase* aThread); sl@0: IMPORT_C void SetOwner(NThreadBase* aThread); sl@0: IMPORT_C void Wait(); sl@0: IMPORT_C void Signal(); sl@0: IMPORT_C void SignalN(TInt aCount); sl@0: IMPORT_C void Reset(); sl@0: void WaitCancel(); sl@0: sl@0: TInt Dec(NThreadBase* aThread); // does mb() if >0 sl@0: NThreadBase* Inc(TInt aCount); // does mb() sl@0: NThreadBase* DoReset(); // does mb() sl@0: public: sl@0: /** If >=0 the semaphore count sl@0: If <0, (thread>>2)|0x80000000 sl@0: @internalComponent sl@0: */ sl@0: TInt iCount; sl@0: sl@0: /** The thread allowed to wait on the semaphore sl@0: @internalComponent sl@0: */ sl@0: NThreadBase* iOwningThread; sl@0: }; sl@0: sl@0: /** Create a fast semaphore sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: inline NFastSemaphore::NFastSemaphore() sl@0: : iCount(0), iOwningThread(NULL) sl@0: {} sl@0: sl@0: /** Nanokernel fast mutex sl@0: sl@0: A light-weight priority-inheritance mutex that can be used if the following sl@0: conditions apply: sl@0: sl@0: - Threads that hold the mutex never block. sl@0: - The mutex is never acquired in a nested fashion sl@0: sl@0: If either of these conditions is not met, a DMutex object is more appropriate. sl@0: sl@0: @publishedPartner sl@0: @prototype sl@0: */ sl@0: class NFastMutex sl@0: { sl@0: public: sl@0: IMPORT_C NFastMutex(); sl@0: IMPORT_C void Wait(); sl@0: IMPORT_C void Signal(); sl@0: IMPORT_C TBool HeldByCurrentThread(); sl@0: private: sl@0: void DoWaitL(); sl@0: void DoSignalL(); sl@0: sl@0: friend class NKern; sl@0: public: sl@0: /** @internalComponent sl@0: sl@0: If mutex is free and no-one is waiting, iHoldingThread=0 sl@0: If mutex is held and no-one is waiting, iHoldingThread points to holding thread sl@0: If mutex is free but threads are waiting, iHoldingThread=1 sl@0: If mutex is held and threads are waiting, iHoldingThread points to holding thread but with bit 0 set sl@0: */ sl@0: NThreadBase* iHoldingThread; sl@0: sl@0: TUint32 i_NFastMutex_Pad1; /**< @internalComponent */ sl@0: sl@0: /** @internalComponent sl@0: sl@0: Spin lock to protect mutex sl@0: */ sl@0: TSpinLock iMutexLock; sl@0: sl@0: /** @internalComponent sl@0: sl@0: List of NThreads which are waiting for the mutex. The threads are linked via sl@0: their iWaitLink members. sl@0: */ sl@0: TPriList iWaitQ; sl@0: }; sl@0: sl@0: __ASSERT_COMPILE(!(_FOFF(NFastMutex,iMutexLock)&7)); sl@0: sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: sl@0: The type of the callback function used by the nanokernel timer. sl@0: sl@0: @see NTimer sl@0: */ sl@0: typedef NEventFn NTimerFn; sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @prototype sl@0: sl@0: A basic relative timer provided by the nanokernel. sl@0: sl@0: It can generate either a one-shot interrupt or periodic interrupts. sl@0: sl@0: A timeout handler is called when the timer expires, either: sl@0: - from the timer ISR - if the timer is queued via OneShot(TInt aTime) or OneShot(TInt aTime, TBool EFalse), or sl@0: - from the nanokernel timer dfc1 thread - if the timer is queued via OneShot(TInt aTime, TBool ETrue) call, or sl@0: - from any other dfc thread that provided DFC belongs to - if the timer is queued via OneShot(TInt aTime, TDfc& aDfc) call. sl@0: Call-back mechanism cannot be changed in the life time of a timer. sl@0: sl@0: These timer objects may be manipulated from any context. sl@0: The timers are driven from a periodic system tick interrupt, sl@0: usually a 1ms period. sl@0: sl@0: @see NTimerFn sl@0: */ sl@0: class NTimerQ; sl@0: class NTimer : public NEventHandler sl@0: { sl@0: public: sl@0: /** sl@0: Default constructor. sl@0: */ sl@0: inline NTimer() sl@0: { sl@0: iHType = EEventHandlerNTimer; sl@0: i8888.iHState1 = EIdle; sl@0: } sl@0: /** sl@0: Constructor taking a callback function and a pointer to be passed sl@0: to the callback function. sl@0: sl@0: @param aFunction The callback function. sl@0: @param aPtr A pointer to be passed to the callback function sl@0: when called. sl@0: */ sl@0: inline NTimer(NTimerFn aFunction, TAny* aPtr) sl@0: { sl@0: iPtr = aPtr; sl@0: iFn = aFunction; sl@0: iHType = EEventHandlerNTimer; sl@0: i8888.iHState1 = EIdle; sl@0: } sl@0: IMPORT_C NTimer(NSchedulable* aTied, NTimerFn aFunction, TAny* aPtr); sl@0: IMPORT_C NTimer(TDfcFn aFunction, TAny* aPtr, TInt aPriority); // create DFC, queue to be set later sl@0: IMPORT_C NTimer(TDfcFn aFunction, TAny* aPtr, TDfcQue* aDfcQ, TInt aPriority); // create DFC sl@0: IMPORT_C void SetDfcQ(TDfcQue* aDfcQ); sl@0: IMPORT_C ~NTimer(); sl@0: IMPORT_C TInt SetTied(NSchedulable* aTied); sl@0: IMPORT_C TInt OneShot(TInt aTime); sl@0: IMPORT_C TInt OneShot(TInt aTime, TBool aDfc); sl@0: IMPORT_C TInt OneShot(TInt aTime, TDfc& aDfc); sl@0: IMPORT_C TInt Again(TInt aTime); sl@0: IMPORT_C TBool Cancel(); sl@0: IMPORT_C TBool IsPending(); sl@0: private: sl@0: enum { ECancelDestroy=1 }; sl@0: private: sl@0: inline TBool IsNormal() sl@0: { return iHType==EEventHandlerNTimer; } sl@0: inline TBool IsMutating() sl@0: { return iHType sl@0: #endif