diff -r 000000000000 -r a41df078684a kernel/eka/include/kernel/kernel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/include/kernel/kernel.h Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,2968 @@ +// Copyright (c) 1994-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\kernel\kernel.h +// Public header for device drivers +// +// 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 __K32STD_H__ +#define __K32STD_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class DObject; +class DObjectCon; +class DThread; +class DCodeSeg; +class DProcess; +class DLibrary; +class DMutex; +class DSemaphore; +class DChunk; +class DShPool; +class DShBuf; + + +/** Data type for physical addresses +@publishedPartner +@released +*/ +typedef TUint32 TPhysAddr; + + +/** +A constant representing an invalid physical address. +@publishedPartner +@released +*/ +const TPhysAddr KPhysAddrInvalid=0xFFFFFFFFu; + + +/** @internalComponent */ +_LIT(KLitKernExec, "KERN-EXEC"); + +/******************************************** + * HAL entry array + ********************************************/ + +/** @internalTechnology */ +const TInt KMaxHalGroups=32; + + + + +/** +@publishedPartner +@released + +Defines the signature for a HAL handler function. +*/ +typedef TInt (*THalFunc)(TAny*,TInt,TAny*,TAny*); + +/** @internalTechnology */ +const TInt KMaxHalEntries=8; + +/** @internalTechnology */ +struct SHalEntry + { + THalFunc iFunction; + TAny* iPtr; + }; + +/** @internalTechnology */ +struct SHalEntry2 : public SHalEntry + { + SHalEntry* iExtendedEntries; + }; + +/******************************************** + * Exports from layer 1 of the kernel + ********************************************/ +class TThreadMessage; +class DObjectCon; +class DPowerModel; +class TSuperPage; +class TMachineConfig; + +/******************************************** + * Thread creation info block + ********************************************/ + +/** +@publishedPartner +@released + +Defines a set of thread types. +*/ +enum TThreadType + { + /** The thread is the initial thread + @internalComponent + */ + EThreadInitial, + + /** The thread runs in supervisor mode */ + EThreadSupervisor, + + /** The thread runs in supervisor mode and has no handles array */ + EThreadMinimalSupervisor, + + /** The thread runs in user mode */ + EThreadUser, + + /** The thread is the initial thread on a non-boot processor (SMP only) + @internalComponent + */ + EThreadAPInitial, + }; + +/******************************************** + * Kernel Mutex Ordering + ********************************************/ +const TUint8 KMutexOrdNone = 0xff; /**< @internalComponent */ +const TUint8 KMutexOrdUser = 0xfe; /**< @internalComponent */ + +/** +Mutex order value for general purpose use. This value is higher than any used internally +by the kernel, therefore there are no mutex ordering restrictions that limit which kernel +functions may be called whilst a mutex of this order is held. +@see Kern::MutexCreate() +@publishedPartner +@released +*/ +const TUint8 KMutexOrdGeneral7 = 0xf7; + +/** +Mutex order value for general purpose use. This value is higher than any used internally +by the kernel, therefore there are no mutex ordering restrictions that limit which kernel +functions may be called whilst a mutex of this order is held. +@see Kern::MutexCreate() +@publishedPartner +@released +*/ +const TUint8 KMutexOrdGeneral6 = 0xf6; + +/** +Mutex order value for general purpose use. This value is higher than any used internally +by the kernel, therefore there are no mutex ordering restrictions that limit which kernel +functions may be called whilst a mutex of this order is held. +@see Kern::MutexCreate() +@publishedPartner +@released +*/ +const TUint8 KMutexOrdGeneral5 = 0xf5; + +/** +Mutex order value for general purpose use. This value is higher than any used internally +by the kernel, therefore there are no mutex ordering restrictions that limit which kernel +functions may be called whilst a mutex of this order is held. +@see Kern::MutexCreate() +@publishedPartner +@released +*/ +const TUint8 KMutexOrdGeneral4 = 0xf4; + +/** +Mutex order value for general purpose use. This value is higher than any used internally +by the kernel, therefore there are no mutex ordering restrictions that limit which kernel +functions may be called whilst a mutex of this order is held. +@see Kern::MutexCreate() +@publishedPartner +@released +*/ +const TUint8 KMutexOrdGeneral3 = 0xf3; + +/** +Mutex order value for general purpose use. This value is higher than any used internally +by the kernel, therefore there are no mutex ordering restrictions that limit which kernel +functions may be called whilst a mutex of this order is held. +@see Kern::MutexCreate() +@publishedPartner +@released +*/ +const TUint8 KMutexOrdGeneral2 = 0xf2; + +/** +Mutex order value for general purpose use. This value is higher than any used internally +by the kernel, therefore there are no mutex ordering restrictions that limit which kernel +functions may be called whilst a mutex of this order is held. +@see Kern::MutexCreate() +@publishedPartner +@released +*/ +const TUint8 KMutexOrdGeneral1 = 0xf1; + +/** +Mutex order value for general purpose use. This value is higher than any used internally +by the kernel, therefore there are no mutex ordering restrictions that limit which kernel +functions may be called whilst a mutex of this order is held. +@see Kern::MutexCreate() +@publishedPartner +@released +*/ +const TUint8 KMutexOrdGeneral0 = 0xf0; + + +const TUint8 KMutexOrdRamDrive = KMutexOrdGeneral7; /**< @internalComponent */ +const TUint8 KMutexOrdShPool = 0x68; /**< @internalComponent */ +const TUint8 KMutexOrdCodeSegLock = 0x60; /**< @internalComponent */ +const TUint8 KMutexOrdPubSub2 = 0x5e; /**< @internalComponent */ + +/** +@internalComponent +@prototype +*/ +const TUint8 KMutexOrdPageIn = 0x5c; + +const TUint8 KMutexOrdRamDefrag = 0x59; /**< @internalComponent */ +const TUint8 KMutexOrdPowerMgr = 0x58; /**< @internalComponent */ +const TUint8 KMutexOrdPubSub = 0x50; /**< @internalComponent */ +const TUint8 KMutexOrdProcessLock = 0x48; /**< @internalComponent */ +const TUint8 KMutexOrdDebug = 0x47; /**< @internalComponent */ +const TUint8 KMutexOrdTimer = 0x40; /**< @internalComponent */ +const TUint8 KMutexOrdObjectCon2 = 0x38; /**< @internalComponent */ // servers +const TUint8 KMutexOrdHandle = 0x30; /**< @internalComponent */ +const TUint8 KMutexOrdObjectCon = 0x28; /**< @internalComponent */ +const TUint8 KMutexOrdMachineConfig = 0x20; /**< @internalComponent */ +const TUint8 KMutexOrdHwChunk = 0x10; /**< @internalComponent */ +const TUint8 KMutexOrdKernelHeap = 0x08; /**< @internalComponent */ +const TUint8 KMutexOrdRamAlloc = 0x04; /**< @internalComponent */ +#if defined(__MEMMODEL_FLEXIBLE__) +const TUint8 KMutexOrdSyncPhysMem = 0x03; /**< @internalComponent */ +#endif +const TUint8 KMutexOrdPageOut = 0x02; /**< @internalComponent */ +const TUint8 KMutexOrdResourceManager = 0x01; /**< @internalComponent */ + + +/******************************************** + * Kernel Extension Priority Ordering + ********************************************/ + +/** +@internalComponent +@prototype 9.5 +*/ +const TUint8 KExtensionMaximumPriority = 0xff; + +/** +@internalComponent +@prototype 9.5 +*/ +const TUint8 KExtensionStandardPriority = 0; + + +/** +Defines a function type that implements a polling operation. + +A function of this type takes a single TAny* type argument, and returns +a TBool type, and is passed as an argument to Kern::PollingWait(). + +@see Kern::PollingWait() + +@publishedPartner +@released +*/ +typedef TBool (*TPollFunction)(TAny*); + + + + +/** +Structure used to specify parameters to Kern::ChunkCreate() +@see Kern::ChunkCreate() +@publishedPartner +@released +*/ +class TChunkCreateInfo + { +public: + /** + Enumeration representing the type of chunk to be created. + */ + enum TType + { + /** + A chunk which may only be opened by one user side process at a time. + Chunks of this type are slightly more efficient than the + ESharedKernelMultiple type when used on the Moving Memory Model. + */ + ESharedKernelSingle = 9, + + /** + A chunk which may be opened by any number of user side processes. + */ + ESharedKernelMultiple = 10, + }; + + /** + The chunk type to be created. + @see TChunkCreateInfo::TType + */ + TType iType; + + /** + The size of linear address space to reserve for this chunk. + */ + TInt iMaxSize; + + /** + Caching attributes for the chunks memory. + + This is a value constructed from the TMappingAttributes values. + E.g. EMapAttrFullyBlocking (no caching) or EMapAttrCachedMax (full caching). + + Note that if the MMU doesn't support the requested attributes then a lesser + cached attribute will be used. The actual value used is returned in aMapAttr of + Kern::ChunkCreate() + + @see TMappingAttributes + */ + TUint32 iMapAttr; + + /** + Set to true if the chunk is to own its committed memory. In which case all + memory committed to the chunk will come from the system's free pool and will be + returned there when the chunk is destroyed. + */ + TUint8 iOwnsMemory; + + /** + @internalComponent + Reserved for future expansion. + */ + TInt8 iSpare8[3]; + + /** + Pointer to a DFC which will be queued on destruction of chunk. + */ + TDfc* iDestroyedDfc; + + /** + @internalComponent + Reserved for future expansion. + */ + TInt32 iSpare32[2]; +public: + /** + Constructor which zeros all member data. + */ + inline TChunkCreateInfo() + { memset(this,0,sizeof(*this)); } + }; + + + +/** +Generic kernel hook function. +@internalComponent +*/ +typedef TInt (*TKernelHookFn)(); + +/** +Available kernel hooks. +@internalComponent +*/ +enum TKernelHookType + { + EHookTrace, + EHookNanoWait, + EHookInitialTime, + + ENumKernelHooks + }; + + +/* +Specifies the origin of the log when calling trace handler hook. +@publishedPartner +@released +*/ +enum TTraceSource + { + /** + User side tracing + @see User::DebugPrint + */ + EUserTrace, + /** + Kernel tracing + @see Kern::Print + */ + EKernelTrace, + /** + Platform security tracing + */ + EPlatSecTrace, + }; + +/* +Trace handler hook +@param aText Debug log. The content of the descriptor resides in kernel memory. +@param aTraceType Identifies the origin of the debug log. +@see TTraceHandlerType +@return Specifies whether the log is processed or not. + If ETrue, the log is processed. Kernel will drop the log (it won't be passed to trace port - UART) + If EFalse, the log is not processed. Kernel will pass the log to the trace port, as well. +@publishedPartner +@released +*/ +typedef TBool (*TTraceHandler)(const TDesC8& /*aText*/, TTraceSource /*aTraceSource*/); + + +/** +Defines the prototype of the kernel hook for the Kern::NanoWait implementation. +@see Kern::NanoWait +@see Kern::SetNanoWaitHandler +@publishedPartner +@released +*/ +typedef void (*TNanoWaitHandler)(TUint32 aInterval); + + +/** +Defines the prototype of the kernel hook to get the initial system time. + +The hook is called during boot to get the inital system time. It should attempt +to read the time from the hardware RTC. If the contents of the RTC are invalid +it should return KErrCorrupt. + +@return The time in seconds from 00:00:00 01-01-2000, or one of the +system-wide error codes. + +@see Kern::SetInitialTimeHandler +@see P::InitSystemTime +@publishedPartner +@released +*/ +typedef TInt (*TInitialTimeHandler)(); + + +/** +A thread's realtime state. + +Some non-realtime behaviour can be detected by the kernel. When it does so, action is taken +depending on the thread state: + +- ERealtimeStateOff - no action. +- ERealtimeStateOn - the the thread will be panicked with KERN-EXEC 61 (EIllegalFunctionForRealtimeThread). +- ERealtimeStateWarn - no action. However, if the kernel trace flag KREALTIME is enabled + then tracing will be emitted as if the thread state was ERealtimeStateOn. + +@publishedPartner +@released +*/ +enum TThreadRealtimeState + { + ERealtimeStateOff, /**< Thread is not realtime */ + ERealtimeStateOn, /**< Thread is realtime */ + ERealtimeStateWarn /**< Thread is realtime but doesn't want this enforced */ + }; + + +/** +A DFC queue intended to be created and destroyed as needed. + +This class extends the TDfcQue class with a destroy method. + +@publishedPartner +@released +*/ +class TDynamicDfcQue : public TDfcQue + { +public: + TDynamicDfcQue(); + IMPORT_C void Destroy(); + IMPORT_C void SetRealtimeState(TThreadRealtimeState aNewState); +private: + TDfc iKillDfc; + }; + + +/** +An object representing an asynchronous request from a user thread, containing a TRequestStatus +pointer. + +It can be queued for completion when the thread next returns to user-mode, to move the impact of any +page faults from the thread posting the completion to the thread that made the request. + +@publishedPartner +@released +*/ +class TClientRequest : public TUserModeCallback + { +public: + IMPORT_C TInt SetStatus(TRequestStatus*); + IMPORT_C void Reset(); + IMPORT_C TRequestStatus* StatusPtr(); + IMPORT_C TBool IsReady(); +public: + void Close(); +protected: + enum TState + { + EFree, + EReady, + EInUse, + EClosing, + EBad + }; + TClientRequest(TUserModeCallbackFunc aCallback = CallbackFunc); + ~TClientRequest(); + TState State(); + static TState GetState(T_UintPtr aStatus); + TBool StartComplete(DThread* aThread, TInt aReason); + void EndComplete(DThread* aThread); + static void CallbackFunc(TAny* aData, TUserModeCallbackReason aReason); +private: + static TDfc DeadClientCleanupDfc; + static void DoDeadClientCleanup(TAny*); +private: + T_UintPtr MakeFree(); +public: + volatile T_UintPtr iStatus; // holds TRequestStatus pointer and state flag bits + TInt iResult; + friend class Kern; + friend class K; + }; + + +/** +Base classs for TClientDataRequest. + +@internalTechnology +*/ +class TClientDataRequestBase : public TClientRequest + { +public: + /** + Set the destination in the client's address space where the data will be copied to when the + request is completed. + @publishedPartner + @released + */ + inline void SetDestPtr(TAny* aPtr) { iDestPtr = aPtr; } /**< */ + /** + Get the destination address in the client's address space. + @publishedPartner + @released + */ + inline TAny* DestPtr() { return iDestPtr; } + /** + Get the local address of the buffer where the structure data will be held until it is copied to + the client. + @publishedPartner + @released + */ + inline TUint8* Buffer() { return (TUint8*)this + _ALIGN_UP(sizeof(*this), 8); } +protected: + TClientDataRequestBase(TInt aBufferSize); + ~TClientDataRequestBase() { } // call Close(), don't delete + static void CallbackFunc(TAny* aData, TUserModeCallbackReason aReason); +public: + TInt iSize; + TAny* iDestPtr; + friend class Kern; + }; + +/** +An object representing an asynchronous request from a user thread that involves copying a small +fixed-size structure to the client. It contains a TRequestStatus pointer and a buffer to hold the +structure. + +It can be queued for completion when the thread next returns to user-mode, to move the impact of any +page faults from the thread posting the completion to the thread that made the request. + +@publishedPartner +@released +*/ +template +class TClientDataRequest : public TClientDataRequestBase + { +public: + T& Data() { return *(T*)Buffer(); } +private: + TClientDataRequest(); + ~TClientDataRequest(); // call Close(), don't delete + }; + +/** +Base classs for TClientDataRequest2. + +@prototype +@internalTechnology +*/ +class TClientDataRequestBase2 : public TClientRequest + { +public: + inline void SetDestPtr1(TAny* aPtr) { iDestPtr1 = aPtr; } + inline TAny* DestPtr1() { return iDestPtr1; } + inline TUint8* Buffer1() { return (TUint8*)this + _ALIGN_UP(sizeof(*this), 8); } + inline void SetDestPtr2(TAny* aPtr) { iDestPtr2 = aPtr; } + inline TAny* DestPtr2() { return iDestPtr2; } + inline TUint8* Buffer2() { return Buffer1() + _ALIGN_UP(iSize1, 8); } +protected: + TClientDataRequestBase2(TInt aBufferSize1, TInt aBufferSize2); + ~TClientDataRequestBase2() { } // call Close(), don't delete + static void CallbackFunc(TAny* aData, TUserModeCallbackReason aReason); +public: + TInt iSize1; + TAny* iDestPtr1; + TInt iSize2; + TAny* iDestPtr2; + friend class Kern; + }; + +/** +An object representing an asynchronous request from a user thread that involves copying two small +fixed-size structures to the client. It contains a TRequestStatus pointer and two buffer to hold +the structures. + +It can be queued for completion when the thread next returns to user-mode, to move the impact of any +page faults from the thread posting the completion to the thread that made the request. + +@prototype +@internalTechnology +*/ +template +class TClientDataRequest2 : public TClientDataRequestBase2 + { +public: + T1& Data1() { return *(T1*)Buffer1(); } + T2& Data2() { return *(T2*)Buffer2(); } +private: + TClientDataRequest2(); + ~TClientDataRequest2(); // call Close(), don't delete + }; + +/** +A parsed descriptor header. + +This has the same internal structure as TRawDesHeader but the header data is stored in a parsed +representation. + +@see TRawDesHeader. + +@prototype +@internalTechnology +*/ +class TDesHeader + { +public: + enum { KConstMaxLength = (TUint)KErrBadDescriptor }; + inline TDesHeader(); + /// Set the contents of this object + inline void Set(TUint32 aTypeAndLength, TLinAddr aDataPtr, TUint aMaxLength = KConstMaxLength); + /// Reset the object to its initial un-set state + inline void Unset(); + /// Determine whether this object has been set to a valid descriptor header + inline TBool IsSet() const; + /// Set both type and length fields in one operation + inline void SetTypeAndLength(TUint32 aTypeAndLength); + // Accessors + inline const TUint32& TypeAndLength() const; + inline TDesType Type() const; + inline TInt Length() const; + inline TBool IsWriteable() const; + inline TInt MaxLength() const; + inline TLinAddr DataPtr() const; +private: + enum { KUnsetFlag = 0xffffffff }; + TUint32 iData[3]; + }; + +inline TDesHeader::TDesHeader() + { + iData[0] = (TUint32)KUnsetFlag; + } + +inline void TDesHeader::Set(TUint32 aTypeAndLength, TLinAddr aDataPtr, TUint aMaxLength) + { + iData[0] = aTypeAndLength; + iData[1] = aMaxLength; + iData[2] = aDataPtr; + } + +inline void TDesHeader::Unset() + { + iData[0] = (TUint32)KUnsetFlag; + } + +inline TBool TDesHeader::IsSet() const + { + return iData[0] != KUnsetFlag; + } + +inline void TDesHeader::SetTypeAndLength(TUint32 aTypeAndLength) + { + iData[0] = aTypeAndLength; + } + +inline const TUint32& TDesHeader::TypeAndLength() const + { + return iData[0]; + } + +inline TDesType TDesHeader::Type() const + { + return (TDesType)(iData[0] >> KShiftDesType); + } + +inline TInt TDesHeader::Length() const + { + return (TInt)(iData[0] & KMaskDesLength); + } + +inline TBool TDesHeader::IsWriteable() const + { + return iData[1] != KConstMaxLength; + } + +inline TInt TDesHeader::MaxLength() const + { + return (TInt)iData[1]; + } + +inline TLinAddr TDesHeader::DataPtr() const + { + return (TLinAddr)iData[2]; + } + +/** +An object representing a client buffer that resides in user-side memory. + +TClientBuffer objects can be used to specify memory to pin using Kern::PinVirtualMemory +@see, and can be read and written using Kern::ThreadBufRead and Kern::ThreadBufWrite. + +@see TClientBufferRequest +@see Kern::PinVirtualMemory +@see Kern::UnpinVirtualMemory +@see Kern::ThreadBufRead +@see Kern::ThreadBufWrite + +@publishedPartner +@released +*/ +class TClientBuffer + { +public: + IMPORT_C TClientBuffer(); + IMPORT_C TInt SetFromDescriptor(TAny* aDesPtr, DThread* aClientThread = NULL); + IMPORT_C void SetFromBuffer(TLinAddr aStartAddr, TInt aLength, TBool aWriteable); + IMPORT_C TBool IsSet() const; + IMPORT_C void Reset(); + IMPORT_C TBool IsWriteable() const; + IMPORT_C TInt Length() const; + IMPORT_C TInt MaxLength() const; + IMPORT_C TInt UpdateDescriptorLength(DThread* aClientThread = NULL); +public: + TAny* DesPtr() const; + TAny* DataPtr() const; +private: + enum TFlags + { + EIsBuffer = 1 + }; +private: + TUint32 iPtr; + TDesHeader iHeader; + friend class Kern; + }; + +class TVirtualPinObject; +class TPhysicalPinObject; +class TShPool; +class TShBuf; + +/** +An object representing a device driver request that involves writing data to one or more user-side +buffers. + +It handles pinning of the buffers when the request is set up, so that the memory can be accessed in +kernel thread context. + +It can be queued for completion when the thread next returns to user-mode. Any writeable +descriptors have their lengths written back to the client at the same time as the completion value. + +The following operations can only be called from client thread context: + + StartSetup + AddBuffer + EndSetup + +These operations can be called from any thread context: + + Kern::QueueRequestComplete + +@publishedPartner +@released +*/ +class TClientBufferRequest : private TClientRequest + { +public: + enum TFlags + { + /** A flag indicating that buffers should have their virtual memory pinned. */ + EPinVirtual = 1 + }; + IMPORT_C TInt StartSetup(TRequestStatus* aStatus); + IMPORT_C TInt AddBuffer(TClientBuffer*& aBufOut, TAny* aDesPtr); + IMPORT_C TInt AddBuffer(TClientBuffer*& aBufOut, TLinAddr aStartAddr, TInt aLength, TBool aWriteable = EFalse); + IMPORT_C void EndSetup(); + IMPORT_C void Reset(); + inline TInt Setup(TClientBuffer*& aBufOut, TRequestStatus* aStatus, TAny* aDesPtr); + inline TInt Setup(TClientBuffer*& aBufOut, TRequestStatus* aStatus, TLinAddr aStartAddr, TInt aLength, TBool aWriteable = EFalse); + inline TBool IsReady(); +private: + struct SBufferData : public SDblQueLink + { + TClientBuffer iBuffer; + TVirtualPinObject* iPinObject; + }; + TClientBufferRequest(TUint aFlags); + ~TClientBufferRequest(); // call Close(), don't delete + TInt Construct(TInt aMaxBuffers); + void Close(); + TInt AllocateBufferData(); + SBufferData* StartAddBuffer(); + TInt EndAddBuffer(TClientBuffer*& aBufOut, SBufferData* aBuf); + void QueueComplete(DThread* aThread, TInt aReason); + static void CallbackFunc(TAny* aData, TUserModeCallbackReason aReason); +private: + TUint iFlags; + DThread* iSetupThread; + SDblQue iBufferList; + static NFastMutex Lock; + friend class Kern; + }; + +inline TInt TClientBufferRequest::Setup(TClientBuffer*& aBufOut, TRequestStatus* aStatus, TAny* aDesPtr) + { + TInt r = StartSetup(aStatus); + if (r == KErrNone) + r = AddBuffer(aBufOut, aDesPtr); + if (r == KErrNone) + EndSetup(); + return r; + } + +inline TInt TClientBufferRequest::Setup(TClientBuffer*& aBufOut, TRequestStatus* aStatus, TLinAddr aStartAddr, TInt aLength, TBool aWriteable) + { + TInt r = StartSetup(aStatus); + if (r == KErrNone) + r = AddBuffer(aBufOut, aStartAddr, aLength, aWriteable); + if (r == KErrNone) + EndSetup(); + return r; + } + +inline TBool TClientBufferRequest::IsReady() + { + return TClientRequest::IsReady(); + } + +class DPagingDevice; +class DLogicalDevice; +class DPhysicalDevice; +class TShPoolCreateInfo; + +class Kern +/** +Kernel utility functions + +@publishedPartner +@released +*/ + { +public: + /** + Bit values to be used with the aMode parameter of Kern::SetSytemTime() to + specify the mode of operation of Kern::SetSytemTime(). + */ + enum TTimeSetMode + { + ETimeSet_SetHwRtc = 1, /**< Set HW as well as SW RTC */ + ETimeSet_LocalTime = 2, /**< The Kern::SetSytemTime() parameter aTime is specified in local time rather than UTC */ + ETimeSet_SyncNotify = 4, /**< Synchronously trigger change notifiers*/ + ETimeSet_AsyncNotify = 8, /**< Asynchronously trigger change notifiers*/ + ETimeSet_Secure = 16 /**< Set the secure clock (implies ETimeSet_SetHwRtc)*/ + }; +public: + IMPORT_C static void Printf(const char* aFmt, ...); + IMPORT_C static TInt AddHalEntry(TInt aId, THalFunc aFunc, TAny* aPtr); + IMPORT_C static TInt AddHalEntry(TInt aId, THalFunc aFunc, TAny* aPtr, TInt aDeviceNumber); + IMPORT_C static TInt RemoveHalEntry(TInt aId); + IMPORT_C static TInt RemoveHalEntry(TInt aId, TInt aDeviceNumber); + IMPORT_C static SHalEntry* FindHalEntry(TInt aId); + IMPORT_C static SHalEntry* FindHalEntry(TInt aId, TInt aDeviceNumber); + IMPORT_C static void SafeClose(DObject*& aObj, TAny* aPtr); + IMPORT_C static TInt ValidateName(const TDesC& aName); + IMPORT_C static TInt ValidateFullName(const TDesC& aName); + IMPORT_C static TBool PowerGood(); + IMPORT_C static void NotifyChanges(TUint aChangesMask); + IMPORT_C static void NotifyThreadDeath(DThread* aDeadThread); /**< @internalComponent */ + IMPORT_C static void AsyncNotifyChanges(TUint aChangesMask); + IMPORT_C static void InfoCopy(TDes8& aDest, const TDesC8& aSrc); + IMPORT_C static void InfoCopy(TDes8& aDest, const TUint8* aPtr, TInt aLength); + IMPORT_C static void RequestComplete(DThread* aThread, TRequestStatus*& aStatus, TInt aReason); + IMPORT_C static void RequestComplete(TRequestStatus*& aStatus, TInt aReason); + IMPORT_C static void QueueRequestComplete(DThread* aThread, TClientRequest* aRequest, TInt aReason); + IMPORT_C static TInt CreateClientRequest(TClientRequest*& aRequestPtr); + + template inline static TInt CreateClientDataRequest(TClientDataRequest*& aRequestPtr) + { + TInt r = Kern::CreateClientDataRequestBase((TClientDataRequestBase*&)aRequestPtr, sizeof(T)); + if (r == KErrNone) + new (aRequestPtr->Buffer()) T; + return r; + } + + template inline static TInt CreateClientDataRequest2(TClientDataRequest2*& aRequestPtr) + { + TInt r = Kern::CreateClientDataRequestBase2((TClientDataRequestBase2*&)aRequestPtr, sizeof(T1), sizeof(T2)); + if (r == KErrNone) + { + new (aRequestPtr->Buffer1()) T1; + new (aRequestPtr->Buffer2()) T2; + } + return r; + } + + IMPORT_C static void DestroyClientRequest(TClientRequest*& aRequestPtr); + template inline static void DestroyClientRequest(TClientDataRequest*& aRequestPtr) + { DestroyClientRequest((TClientRequest*&)aRequestPtr); } /**< @prototype */ + template inline static void DestroyClientRequest(TClientDataRequest2*& aRequestPtr) + { DestroyClientRequest((TClientRequest*&)aRequestPtr); } /**< @prototype */ + IMPORT_C static TInt CreateClientBufferRequest(TClientBufferRequest*& aRequestPtr, TUint aInitialBuffers, TUint aFlags); + IMPORT_C static void DestroyClientBufferRequest(TClientBufferRequest*& aRequestPtr); + IMPORT_C static void QueueBufferRequestComplete(DThread* aThread, TClientBufferRequest* aRequest, TInt aReason); + IMPORT_C static TDfcQue* DfcQue0(); + IMPORT_C static TDfcQue* DfcQue1(); + IMPORT_C static TDfcQue* TimerDfcQ(); + IMPORT_C static TDfcQue* SvMsgQue(); + IMPORT_C static DObjectCon* const *Containers(); /**< @internalComponent */ + IMPORT_C static SDblQue* CodeSegList(); + IMPORT_C static DMutex* CodeSegLock(); + IMPORT_C static DPowerModel* PowerModel(); + IMPORT_C static TInt SetThreadPriority(TInt aPriority, DThread* aThread=NULL); + IMPORT_C static void SetRealtimeState(TThreadRealtimeState aNewState); + IMPORT_C static DObject* ObjectFromHandle(DThread* aThread, TInt aHandle, TInt aType); + IMPORT_C static DObject* ObjectFromHandle(DThread* aThread, TInt aHandle, TInt aType, TUint& aAttr); + IMPORT_C static DThread* ThreadFromId(TUint aId); + IMPORT_C static DProcess* ProcessFromId(TUint aId); + IMPORT_C static void ThreadSuspend(DThread& aThread, TInt aCount); + IMPORT_C static void ThreadResume(DThread& aThread); + IMPORT_C static TInt MutexWait(DMutex& aMutex); + IMPORT_C static void MutexSignal(DMutex& aMutex); + IMPORT_C static TInt MutexCreate(DMutex*& aMutex, const TDesC& aName, TUint aOrder); + IMPORT_C static TInt SemaphoreWait(DSemaphore& aSem, TInt aNTicks=0); + IMPORT_C static void SemaphoreSignal(DSemaphore& aSem); + IMPORT_C static TInt SemaphoreCreate(DSemaphore*& aSem, const TDesC& aName, TInt aInitialCount); + IMPORT_C static TInt ThreadCreate(SThreadCreateInfo& aInfo); + IMPORT_C static TInt DfcQInit(TDfcQue* aDfcQ, TInt aPriority, const TDesC* aName=NULL); + IMPORT_C static TInt DfcQCreate(TDfcQue*& aDfcQ, TInt aPriority, const TDesC* aName=NULL); + IMPORT_C static TInt DynamicDfcQCreate(TDynamicDfcQue*& aDfcQ, TInt aPriority, const TDesC& aBaseName); + IMPORT_C static TInt ProcessCreate(DProcess*& aProcess, TProcessCreateInfo& aInfo, HBuf*& aCommand, TInt* aHandle); /**< @internalComponent */ + IMPORT_C static TSupplyStatus MachinePowerStatus(); + IMPORT_C static void AppendFormat(TDes8& aDes, const char* aFmt, VA_LIST aList); + IMPORT_C static TSuperPage& SuperPage(); + IMPORT_C static TMachineConfig& MachineConfig(); + IMPORT_C static TUint32 Random(); + IMPORT_C static void RandomSalt(TUint32 aBit); + IMPORT_C static void WaitForRequest(TRequestStatus& aStatus); /**< @internalTechnology */ + IMPORT_C static TAny* Alloc(TInt aSize); + IMPORT_C static TAny* AllocZ(TInt aSize); + IMPORT_C static void Free(TAny* aPtr); + IMPORT_C static void AsyncFree(TAny* aPtr); + IMPORT_C static TAny* ReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0); + IMPORT_C static TInt SafeReAlloc(TAny*& aPtr, TInt aOldSize, TInt aNewSize); + IMPORT_C static void ValidateHeap(); + IMPORT_C static void PanicCurrentThread(const TDesC& aCategory, TInt aReason); + IMPORT_C static TBool QueryVersionSupported(const TVersion& aCurrent,const TVersion& aRequested); + IMPORT_C static TTimeK SystemTimeSecure(); + IMPORT_C static TTimeK SystemTime(); + IMPORT_C static TInt SetSystemTime(const TTimeK& aTime, TUint aMode); + IMPORT_C static TInt HalFunction(TInt aGroup, TInt aFunction, TAny* a1, TAny* a2); + IMPORT_C static TInt HalFunction(TInt aGroup, TInt aFunction, TAny* a1, TAny* a2, TInt aDeviceNumber); + IMPORT_C static TInt AddEvent(const TRawEvent& aEvent); + IMPORT_C static TInt AddEvent(const TRawEvent& aEvent, TBool aResetUserActivity); + IMPORT_C static void Exit(TInt aReason); + IMPORT_C static TInt TickPeriod(); + IMPORT_C static void KUDesGet(TDes8& aDest, const TDesC8& aSrc); + IMPORT_C static void KUDesPut(TDes8& aDest, const TDesC8& aSrc); + IMPORT_C static const TUint8* KUDesInfo(const TDesC8& aSrc, TInt& aLength, TInt& aMaxLength); + IMPORT_C static void KUDesSetLength(TDes8& aDes, TInt aLength); + IMPORT_C static TInt ThreadDesRead(DThread* aThread, const TAny* aSrc, TDes8& aDest, TInt aOffset, TInt aMode); + IMPORT_C static TInt ThreadRawRead(DThread* aThread, const TAny* aSrc, TAny* aDest, TInt aSize); + IMPORT_C static TInt ThreadDesWrite(DThread* aThread, TAny* aDest, const TDesC8& aSrc, TInt aOffset, TInt aMode, DThread* aOrigThread); + IMPORT_C static TInt ThreadRawWrite(DThread* aThread, TAny* aDest, const TAny* aSrc, TInt aSize, DThread* aOrigThread=NULL); + inline static TInt ThreadDesRead(DThread* aThread, const TAny* aSrc, TDes8& aDest, TInt aOffset); + inline static TInt ThreadDesWrite(DThread* aThread, TAny* aDest, const TDesC8& aSrc, TInt aOffset, DThread* aOrigThread=NULL); + IMPORT_C static TInt ThreadBufRead(DThread* aThread, const TClientBuffer* aSrc, TDes8& aDest, TInt aOffset, TInt aMode); + IMPORT_C static TInt ThreadBufWrite(DThread* aThread, TClientBuffer* aDest, const TDesC8& aSrc, TInt aOffset, TInt aMode, DThread* aOrigThread); + IMPORT_C static TInt ThreadGetDesLength(DThread* aThread, const TAny* aDes); + IMPORT_C static TInt ThreadGetDesMaxLength(DThread* aThread, const TAny* aDes); + IMPORT_C static TInt ThreadGetDesInfo(DThread* aThread, const TAny* aDes, TInt& aLength, TInt& aMaxLength, TUint8*& aPtr, TBool aWriteable); + IMPORT_C static void ThreadKill(DThread* aThread, TExitType aType, TInt aReason, const TDesC& aCategory); + IMPORT_C static TAny* KUSafeRead(const TAny* aSrc, TAny* aDest, TInt aSize); /**< @internalTechnology */ + IMPORT_C static TAny* SafeRead(const TAny* aSrc, TAny* aDest, TInt aSize); /**< @internalTechnology */ + IMPORT_C static TAny* KUSafeWrite(TAny* aDest, const TAny* aSrc, TInt aSize); /**< @internalTechnology */ + IMPORT_C static TAny* SafeWrite(TAny* aDest, const TAny* aSrc, TInt aSize); /**< @internalTechnology */ + IMPORT_C static TInt KUSafeInc(TInt& aValue); /**< @internalTechnology */ + IMPORT_C static TInt KUSafeDec(TInt& aValue); /**< @internalTechnology */ + IMPORT_C static DThread& CurrentThread(); + IMPORT_C static DProcess& CurrentProcess(); + IMPORT_C static TThreadMessage& Message(); + IMPORT_C static TInt FreeRamInBytes(); + IMPORT_C static void Fault(const char* aCat, TInt aFault); + IMPORT_C static TBool ColdStart(); + IMPORT_C static void NanoWait(TUint32 aInterval); + IMPORT_C static TUint32 TickCount(); + IMPORT_C static TInt PollingWait(TPollFunction aFunction, TAny* aPtr, TInt aPollPeriodMs, TInt aMaxPoll); + IMPORT_C static TUint32 RoundToPageSize(TUint32 aSize); + IMPORT_C static TUint32 RoundToChunkSize(TUint32 aSize); + IMPORT_C static void Restart(TInt aMode); /**< @internalTechnology */ + IMPORT_C static void AccessCode(); + IMPORT_C static void EndAccessCode(); + IMPORT_C static DThread* NThreadToDThread(NThread* aNThread); + IMPORT_C static TInt PrepareMemoryForDMA(DThread* aThread, TAny* aAddress, TInt aSize, TPhysAddr* aPageList); /**< @internalComponent */ + IMPORT_C static TInt ReleaseMemoryFromDMA(DThread* aThread, TAny* aAddress, TInt aSize, TPhysAddr* aPageList);/**< @internalComponent */ + +#ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__ + /** + Checks whether the process that owns the current thread has the specified capability. + + When a check fails the action taken is determined by the system wide Platform Security + configuration. If PlatSecDiagnostics is ON, then a diagnostic message is emitted. + If PlatSecEnforcement is OFF, then this function will return True even though the + check failed. + + @param aCapability The capability to be tested. + @param aDiagnosticText A string that will be emitted along with any diagnostic message + that may be issued if the test finds the capability is not present. + This string must be enclosed in the __PLATSEC_DIAGNOSTIC_STRING macro + which enables it to be easily removed from the system. + + @return True if the current thread's process has the capability, False otherwise. + */ + inline static TBool CurrentThreadHasCapability(TCapability aCapability, const char* aDiagnosticText=0) + { return DoCurrentThreadHasCapability(aCapability, aDiagnosticText); } +#else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__ + // Only available to NULL arguments + /** + Checks whether the process that owns the current thread has the specified capability. + + When a check fails the action taken is determined by the system wide Platform Security + configuration. If PlatSecDiagnostics is ON, then a diagnostic message is emitted. + If PlatSecEnforcement is OFF, then this function will return True even though the + check failed. + + @param aCapability The capability to be tested. + + @return True if the current thread's process has the capability, False otherwise. + */ + inline static TBool CurrentThreadHasCapability(TCapability aCapability, OnlyCreateWithNull /*aDiagnosticText*/=NULL) + { return DoCurrentThreadHasCapability(aCapability); } +#endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__ + + IMPORT_C static TVendorId ThreadVendorId(DThread* aThread); + IMPORT_C static TVendorId ProcessVendorId(DProcess* aProcess); + IMPORT_C static TSecureId ThreadSecureId(DThread* aThread); + IMPORT_C static TSecureId ProcessSecureId(DProcess* aProcess); + + IMPORT_C static DCodeSeg* CodeSegFromAddress(TLinAddr aAddr, DProcess* aProcess); + IMPORT_C static void CodeSegGetMemoryInfo(DCodeSeg& aCodeSeg, TModuleMemoryInfo& aInfo, DProcess* aProcess); + IMPORT_C static TInt MakeHandleAndOpen(DThread* aThread, DObject* aObject); + IMPORT_C static TInt CloseHandle(DThread* aThread, TInt aHandle); + IMPORT_C static TInt ChunkCreate(const TChunkCreateInfo& aInfo, DChunk*& aChunk, TLinAddr& aKernAddr, TUint32& iMapAttr); + IMPORT_C static TInt ChunkCommit(DChunk* aChunk, TInt aOffset, TInt aSize); + IMPORT_C static TInt ChunkCommitContiguous(DChunk* aChunk, TInt aOffset, TInt aSize, TUint32& aPhysicalAddress); + IMPORT_C static TInt ChunkCommitPhysical(DChunk* aChunk, TInt aOffset, TInt aSize, TUint32 aPhysicalAddress); + IMPORT_C static TInt ChunkCommitPhysical(DChunk* aChunk, TInt aOffset, TInt aSize, const TUint32* aPhysicalAddressList); + IMPORT_C static TInt ChunkClose(DChunk* aChunk); + IMPORT_C static DChunk* OpenSharedChunk(DThread* aThread, const TAny* aAddress, TBool aWrite, TInt& aOffset); + IMPORT_C static DChunk* OpenSharedChunk(DThread* aThread, TInt aChunkHandle, TBool aWrite); + IMPORT_C static TInt ChunkAddress(DChunk* aChunk, TInt aOffset, TInt aSize, TLinAddr& aKernelAddress); + IMPORT_C static TInt ChunkPhysicalAddress(DChunk* aChunk, TInt aOffset, TInt aSize, TLinAddr& aKernelAddress, TUint32& aMapAttr, TUint32& aPhysicalAddress, TUint32* aPhysicalPageList=NULL); + IMPORT_C static TUint8* ChunkUserBase(DChunk* aChunk, DThread* aThread); + + /** + Enumeration indicating the behaviour of text trace messages. + @publishedPartner + @released + */ + enum TTextTraceMode + { + /** Traces are sent to the serial port if not already handled by other means. */ + ESerialOutDefault = 0, + /** Traces are never sent to the serial port. */ + ESerialOutNever = 1, + /** Traces are always sent to the serial port. */ + ESerialOutAlways = 2, + /** Mask for serial port mode values. */ + ESerialOutMask = 3 + }; + IMPORT_C static TUint SetTextTraceMode(TUint aMode, TUint aMask); + IMPORT_C static TTraceHandler SetTraceHandler(TTraceHandler aHandler); + inline static TNanoWaitHandler SetNanoWaitHandler(TNanoWaitHandler aHandler); + inline static TInitialTimeHandler SetInitialTimeHandler(TInitialTimeHandler aHandler); + + /** + Install the specified paging device. + @param aDevice The device. + @return KErrNone or standard error code. + @post The devices DPagingDevice::iDeviceId has been set. + @internalTechnology + */ + IMPORT_C static TInt InstallPagingDevice(DPagingDevice* aDevice); + IMPORT_C static TInt InstallLogicalDevice(DLogicalDevice* aDevice); /**< @internalTechnology */ + IMPORT_C static TInt InstallPhysicalDevice(DPhysicalDevice* aDevice); /**< @internalTechnology */ + + IMPORT_C static TInt CreateVirtualPinObject(TVirtualPinObject*& aPinObject); // prototype + IMPORT_C static TInt PinVirtualMemory(TVirtualPinObject* aPinObject, TLinAddr aStart, TUint aSize, DThread* aThread=NULL); // prototype + IMPORT_C static TInt PinVirtualMemory(TVirtualPinObject* aPinObject, const TClientBuffer& aDes, DThread* aThread=NULL); // prototype + IMPORT_C static TInt CreateAndPinVirtualMemory(TVirtualPinObject*& aPinObject, TLinAddr aStart, TUint aSize); //prototype + IMPORT_C static void UnpinVirtualMemory(TVirtualPinObject* aPinObject); // prototype + IMPORT_C static void DestroyVirtualPinObject(TVirtualPinObject*& aPinObject); // prototype + + IMPORT_C static TInt CreatePhysicalPinObject(TPhysicalPinObject*& aPinObject); // prototype + IMPORT_C static TInt PinPhysicalMemory(TPhysicalPinObject* aPinObject, TLinAddr aStart, TUint aSize, TBool aReadOnly, TPhysAddr& aAddress, TPhysAddr* aPages, TUint32& aMapAttr, TUint& aColour, DThread* aThread=NULL); + IMPORT_C static TInt UnpinPhysicalMemory(TPhysicalPinObject* aPinObject); // prototype + IMPORT_C static TInt DestroyPhysicalPinObject(TPhysicalPinObject*& aPinObject); // prototype + + + IMPORT_C static TInt ShPoolCreate(TShPool*& aPool, TShPoolCreateInfo& aInfo, TBool aMap, TUint aFlags); + IMPORT_C static TInt ShPoolOpen(TShPool*& aPool, DThread* aThread, TInt aHandle, TBool aMap, TUint aFlags); + IMPORT_C static TInt ShPoolClose(TShPool* aPool); + IMPORT_C static TInt ShPoolMakeHandleAndOpen(TShPool* aPool, DThread* aThread, TUint aAttr); + IMPORT_C static TInt ShPoolSetBufferWindow(TShPool* aPool, TInt aWindowSize); + IMPORT_C static TInt ShPoolAlloc(TShPool* aPool, TShBuf*& aBuf, TUint aFlags); + IMPORT_C static void ShPoolGetInfo(TShPool* aPool, TShPoolInfo& aInfo); + IMPORT_C static TUint ShPoolBufSize(TShPool* aPool); + IMPORT_C static TUint ShPoolFreeCount(TShPool* aPool); + IMPORT_C static TInt ShBufOpen(TShBuf*& aBuf, DThread* aThread, TInt aHandle); + IMPORT_C static TInt ShBufClose(TShBuf* aBuf); + IMPORT_C static TInt ShBufMakeHandleAndOpen(TShBuf* aBuf, DThread* aThread); + IMPORT_C static void ShBufCopyFrom(TShBuf* aBuf, const TDesC8& aSrc, TUint aOffset); + IMPORT_C static TUint8* ShBufPtr(TShBuf* aBuf); + IMPORT_C static TUint ShBufSize(TShBuf* aBuf); + IMPORT_C static TInt ShBufPin(TShBuf* aBuf, TPhysicalPinObject* aPinObject, TBool aReadOnly, TPhysAddr& Address, TPhysAddr* aPages, TUint32& aMapAttr, TUint& aColour); + + +private: + IMPORT_C static TBool DoCurrentThreadHasCapability(TCapability aCapability, const char* aDiagnosticText); + IMPORT_C static TBool DoCurrentThreadHasCapability(TCapability aCapability); + IMPORT_C static TKernelHookFn SetHook(TKernelHookType aType, TKernelHookFn aFunction, TBool aAllowOveride=EFalse); + IMPORT_C static TInt CreateClientDataRequestBase(TClientDataRequestBase*& aRequestPtr, TInt aSize); /**< @internalTechnology */ + IMPORT_C static TInt CreateClientDataRequestBase2(TClientDataRequestBase2*& aRequestPtr, TInt aSize1, TInt aSize2); /**< @internalTechnology */ + friend class DThread; + }; + + + +/** +Reads an 8-bit descriptor from the specified thread's address space, enforcing +checks on validity of source and destination if necessary. + +It is used especially by device drivers to transfer data from a user thread. +aDes might be accessed with user permission validation. + +@param aThread The thread from whose address space data is to be read. +@param aSrc Pointer to a source descriptor in the specified thread's address + space. This must not be NULL. +@param aDest Target descriptor +@param aOffset Offset in aSrc from where to start reading data. + +@return KErrNone, if sucessful; KErrBadDescriptor, if aPtr or aDes is an + invalid decriptor; KErrArgument if anOffset is negative; KErrDied if aThread + is dead. +*/ +inline TInt Kern::ThreadDesRead(DThread* aThread, const TAny* aSrc, TDes8& aDest, TInt aOffset) + { return ThreadDesRead(aThread,aSrc,aDest,aOffset,KChunkShiftBy0); } + + + + +/** +Writes an 8-bit descriptor to the specified thread's address space, enforcing +checks on validity of source and destination if necessary. + +It is used especially by device drivers to transfer data to a user thread. +aDes might be accessed with user permission validation. + +@param aThread The thread into whose address space data is to be written. +@param aDest Pointer to a target descriptor in the specified thread's address + space. It must not be NULL +@param aSrc Source descriptor +@param aOffset Offset in aDest to start writing data to. +@param aOrigThread The thread on behalf of which this operation is performed (eg client of device driver). + +@return KErrNone, if sucessful; KErrBadDescriptor, if aPtr or aDes is an + invalid decriptor; KErrArgument if anOffset is negative; KErrDied if aThread + is dead. +*/ +inline TInt Kern::ThreadDesWrite(DThread* aThread, TAny* aDest, const TDesC8& aSrc, TInt aOffset, DThread* aOrigThread) + { return ThreadDesWrite(aThread,aDest,aSrc,aOffset,KChunkShiftBy0,aOrigThread); } + + +/** +Register the function used to implement Kern::NanoWait. + +This should be called from the variant to supply an accurate implementation for Kern::NanoWait. + +@return The previous implemention. + +@see Kern::NanoWait + +@publishedPartner +@released +*/ +inline TNanoWaitHandler Kern::SetNanoWaitHandler(TNanoWaitHandler aHandler) + { + return (TNanoWaitHandler) SetHook(EHookNanoWait, (TKernelHookFn)aHandler, ETrue); + } + + + +/** +Register the function used to read the initial system time. + +This may be called from the variant to override the default behaviour. If so it +should be called in phase 1 of initialisation. + +@return The previous implemention. + +@publishedPartner +@released +*/ +inline TInitialTimeHandler Kern::SetInitialTimeHandler(TInitialTimeHandler aHandler) + { + return (TInitialTimeHandler) SetHook(EHookInitialTime, (TKernelHookFn)aHandler, ETrue); + } + + + +struct SMiscNotifierQ; +class TMiscNotifierMgr; +class DObject : public DBase +/** +Base class for reference-counted kernel side objects. + +@publishedPartner +@released +*/ +// NOTE: Any changes to the structure of this class should be duplicated in class DMonObject + { +public: + + /** + Defines a set of bit values that are returned from calls + to DObject::Close(), or by an overriding implementation of Close() provided + by a derived class. + + The values describe the state of the object on return from Close(). + */ + enum TCloseReturn + { + + /** + If set, indicates that the object has been deleted. + */ + EObjectDeleted=1, + + /** + If set, indicates that the last reference + from a user process has been removed. + + Note that this only applies to DLibrary objects. + */ + EObjectUnmapped=2, + }; + + /** @internalComponent */ + enum TObjectProtection + { + ELocal=0, // Private + EProtected, + EGlobal, // Public + }; + + /** @internalComponent */ + enum TObjectFlags + { + EObjectExtraReference = (1<<0), + EObjectDeferKernelCodesegCleanup = (1<<1) + }; + +public: + /** @internalComponent */ + inline TInt Inc() { return __e32_atomic_tas_ord32(&iAccessCount, 1, 1, 0); } + + /** @internalComponent */ + inline TInt Dec() { return __e32_atomic_tas_ord32(&iAccessCount, 1, -1, 0); } + + IMPORT_C DObject(); + IMPORT_C ~DObject(); + + /** + Opens this kernel side reference-counted object. + + Opening a reference-counted object increments its reference count + by one. The increment operation is done atomically. + + @return KErrNone, if the increment operation succeeds; + KErrGeneral, if the reference count value is either zero + or negative before performing the increment operation; + the reference count is initialised to 1 on construction + of the object, and can never be less than 1. + */ + inline TInt Open() { return(Inc()?KErrNone:KErrGeneral); } + IMPORT_C void CheckedOpen(); + IMPORT_C virtual TInt Close(TAny* aPtr); + IMPORT_C virtual TInt RequestUserHandle(DThread* aThread, TOwnerType aType); + IMPORT_C virtual TInt RequestUserHandle(DThread* aThread, TOwnerType aType, TUint aAttr); + IMPORT_C virtual TInt AddToProcess(DProcess* aProcess); + IMPORT_C virtual TInt AddToProcess(DProcess* aProcess, TUint aAttr); + IMPORT_C TInt AsyncClose(); + IMPORT_C virtual void DoAppendName(TDes& aName); + IMPORT_C void DoAppendFullName(TDes& aFullName); + IMPORT_C void Name(TDes& aName); + IMPORT_C void AppendName(TDes& aName); + IMPORT_C void FullName(TDes& aFullName); + IMPORT_C void AppendFullName(TDes& aFullName); + IMPORT_C TInt SetName(const TDesC* aName); + IMPORT_C TInt SetOwner(DObject* aOwner); + IMPORT_C void TraceAppendName(TDes8& aName, TBool aLock); + IMPORT_C void TraceAppendFullName(TDes8& aFullName, TBool aLock); + inline DObject* Owner(); + inline TInt AccessCount(); + inline TInt UniqueID(); + inline HBuf* NameBuf(); + inline void SetProtection(TObjectProtection aProtection); + inline TUint Protection(); + void BaseName(TDes& aName); + inline TUint64 ObjectId() const; /**< @internalComponent */ +public: + /** @internalComponent */ + TInt iAccessCount; // must be first + + /** @internalComponent */ + DObject* iOwner; + + /** A TObjectType value with one added + @internalComponent */ + TUint8 iContainerID; + + /** A TObjectProtection value + @internalComponent */ + TUint8 iProtection; + + /** Bit field made of values from TObjectFlags + @internalComponent */ + TUint8 iObjectFlags; + + /** @internalComponent */ + TUint8 iNotQLow; + + /** @internalComponent */ + HBuf* iName; + + /** A unique ID. + @internalComponent */ + TUint64 iObjectId; + + /** @internalComponent */ +// SMiscNotifierQ* iNotifierQ; + +public: + static NFastMutex Lock; +private: + inline SMiscNotifierQ* NotifierQ() const; /**< @internalComponent */ + inline void SetNotifierQ(SMiscNotifierQ*); /**< @internalComponent */ + inline TBool HasNotifierQ() const; /**< @internalComponent */ +private: + static TUint64 NextObjectId; + + friend class DObjectCon; + friend class RObjectIx; + friend class Monitor; + friend class Debugger; + friend void Kern::AppendFormat(TDes8&, const char*, VA_LIST); + friend class K; + friend struct SMiscNotifierQ; + friend class TMiscNotifierMgr; + }; + +/** +Gets the number of open references to +this reference-counted kernel side object. + +@return The number of open references. +*/ +inline TInt DObject::AccessCount() + { return iAccessCount; } + +/** +Gets a pointer to the kernel-side reference counted object +that owns this kernel side reference-counted object. + +@return A pointer to the owning reference-counted object. + This is NULL, if there is no owner. +*/ +inline DObject* DObject::Owner() + { return iOwner; } + +/** @internalComponent */ +inline HBuf* DObject::NameBuf() + { return iName; } + +/** @internalComponent */ +inline TInt DObject::UniqueID() + {return(iContainerID);} + +/** @internalComponent */ +inline TUint DObject::Protection() + {return (TUint8)iProtection;} + +/** @internalComponent */ +inline void DObject::SetProtection(TObjectProtection aProtection) + {iProtection=(TUint8)aProtection;} + +/******************************************** + * Device driver base classes + ********************************************/ + +/** +@publishedPartner +@released + +If set, it indicates that the use of units is valid. + +@see DLogicalDevice::iParsemask +*/ +const TUint KDeviceAllowUnit=0x01; + + + + +/** +@publishedPartner +@released + +If set, then an LDD requires a PDD. + +@see DLogicalDevice::iParsemask +*/ +const TUint KDeviceAllowPhysicalDevice=0x02; + + + + +/** +@publishedPartner +@released + +If set, it indicates that the use of additional information is allowed. + +@see DLogicalDevice::iParsemask +*/ +const TUint KDeviceAllowInfo=0x04; + + + + +/** +@publishedPartner +@released + +Combines all of: KDeviceAllowUnit, KDeviceAllowPhysicalDevice and KDeviceAllowInfo. + +@see DLogicalDevice::iParsemask +*/ +const TUint KDeviceAllowAll=(KDeviceAllowUnit|KDeviceAllowPhysicalDevice|KDeviceAllowInfo); + + + + +/** +@publishedPartner +@released + +A flag bit that can set in the aMode parameter passed to the +Kern::ThreadDesWrite(DThread* ,TAny*, const TDesC8&, TInt, TInt aMode, DThread*); +variant. + +It ensures that the length of data copied to the target descriptor is +truncated, if necesary, to prevent the maximum length of that target descriptor +from being exceeded. + +@see Kern::ThreadDesWrite() +*/ +const TInt KTruncateToMaxLength=(TInt)0x40000000; + + + + +/** +@publishedPartner +@released + +Used internally by Symbian OS. +*/ +const TInt KCheckLocalAddress=(TInt)0x20000000; + + + + +/** +@internalTechnology +@prototype + +A flag bit that can set in the aMode parameter passed to the +Kern::ThreadDesWrite(DThread* ,TAny*, const TDesC8&, TInt, TInt aMode, DThread*); +variant. + +It indicates that the descriptor header should not be updated to reflect the new length. + +@see Kern::ThreadDesWrite() +*/ +const TInt KDoNotUpdateDesLength=(TInt)0x10000000; + +class DLogicalDevice; +class DPhysicalDevice; + + + + +/** +@publishedPartner +@released + +The abstract base class for a logical channel. +*/ +class DLogicalChannelBase : public DObject + { +public: + IMPORT_C virtual ~DLogicalChannelBase(); +public: + /** + Handles a client request in the client context. + + The function is called from within the kernel, but the implementation + must be provided by external code. + */ + virtual TInt Request(TInt aReqNo, TAny* a1, TAny* a2)=0; + IMPORT_C virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer); +public: + DLogicalDevice* iDevice; + DPhysicalDevice* iPhysicalDevice; + DBase* iPdd; + }; + + + + +/** +@publishedPartner +@released + +The abstract base class for an LDD factory object. +*/ +class DLogicalDevice : public DObject + { +public: + IMPORT_C virtual ~DLogicalDevice(); + IMPORT_C virtual TBool QueryVersionSupported(const TVersion& aVer) const; + IMPORT_C virtual TBool IsAvailable(TInt aUnit, const TDesC* aDriver, const TDesC8* aInfo) const; + TInt ChannelCreate(DLogicalChannelBase*& pC, TChannelCreateInfo& aInfo); + TInt FindPhysicalDevice(DLogicalChannelBase* aChannel, TChannelCreateInfo& aInfo); + + + /** + Second stage constructor for derived objects. + This must at least set a name for the driver object. + + @return KErrNone or standard error code. + */ + virtual TInt Install()=0; + + + /** + Gets the driver's capabilities. + + This is called in the response to an RDevice::GetCaps() request. + + @param aDes A user-side descriptor into which capabilities information is to be wriiten. + */ + virtual void GetCaps(TDes8& aDes) const =0; + + + /** + Called by the kernel's device driver framework to create a Logical Channel. + This is called in the context of the user thread (client) which requested the creation of a Logical Channel + (e.g. through a call to RBusLogicalChannel::DoCreate). + The thread is in a critical section. + + @param aChannel Set to point to the created Logical Channel + + @return KErrNone or standard error code. + */ + virtual TInt Create(DLogicalChannelBase*& aChannel)=0; + + +public: + /** + The version of this factory object. + + This is used to check that an LDD and PDD are compatible. + Typically, this is set by the constructor of a derived class. + */ + TVersion iVersion; + + + /** + A bitmask that indicates device properties. + + This can take the following values: + KDeviceAllowUnit + KDeviceAllowPhysicalDevice + KDeviceAllowInfo + KDeviceAllowAll + + Typically, this is set by the constructor of a derived class. + + @see RBusLogicalChannel::DoCreate() + @see KDeviceAllowUnit + @see KDeviceAllowPhysicalDevice + @see KDeviceAllowInfo + @see KDeviceAllowAll + */ + TUint iParseMask; + + + /** + Indicates which units are valid. + + If units are allowed, i.e. the KDeviceAllowUnit bit is set in iParseMask, + then this mask indicates which of the units (from 0 to 31) are valid. + + The DPhysicalDevice object associated with the PDD has a similar mask, + and both masks are used to indicate which units the LDD-PDD pair + can handle. + + Typically, this is set by the constructor of a derived class. + + @see KDeviceAllowUnit + */ + TUint iUnitsMask; + + + /** + Pointer to the DCodeSeg object which contains the executable code + for this LDD. + */ + DCodeSeg* iCodeSeg; + + + /** + Number of DLogicalChannelBase objects currently in existence which + have been created from this LDD. + */ + TInt iOpenChannels; + }; + +/** @internalComponent */ +typedef DLogicalDevice* (*TLogicalDeviceNew)(); + + + + +/** +@publishedPartner +@released + +The abstract base class for a PDD factory object. +*/ +class DPhysicalDevice : public DObject + { +public: + enum TInfoFunction + { + EPriority=0, + + /** if implemented (i.e. Info(EMediaDriverPersistent) returns KErrNone) implies the media driver + created by this DPhysicalDevice will not be unloaded when the peripheral bus is powered down */ + EMediaDriverPersistent=1, + }; +public: + IMPORT_C virtual ~DPhysicalDevice(); + IMPORT_C virtual TBool QueryVersionSupported(const TVersion& aVer) const; + IMPORT_C virtual TBool IsAvailable(TInt aUnit, const TDesC8* aInfo) const; + + /** + Second stage constructor for derived objects. + This must at least set a name for the driver object. + + @return KErrNone or standard error code. + */ + virtual TInt Install() =0; + + /** + Returns the drivers capabilities. This is not used by the Symbian OS device driver framework + but may be useful for the LDD to use. + + @param aDes Descriptor to write capabilities information into + */ + virtual void GetCaps(TDes8& aDes) const =0; + + /** + Called by the kernel's device driver framework to create a Physical Channel. + This is called in the context of the user thread (client) which requested the creation of a Logical Channel + (E.g. through a call to RBusLogicalChannel::DoCreate) + The thread is in a critical section. + + @param aChannel Set to point to the created Physical Channel + @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate + @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate + @param aVer The version number of the Logical Channel which will use this Physical Channel + + @return KErrNone or standard error code. + */ + virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer) =0; + + /** + Called by the kernel's device driver framework to check if this PDD is suitable for use with a Logical Channel. + This is called in the context of the user thread (client) which requested the creation of a Logical Channel + (E.g. through a call to RBusLogicalChannel::DoCreate) + The thread is in a critical section. + + @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate + @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate + @param aVer The version number of the Logical Channel which will use this Physical Channel + + @return KErrNone or standard error code. + */ + virtual TInt Validate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer) =0; + IMPORT_C virtual TInt Info(TInt aFunction, TAny* a1); +public: + TVersion iVersion; + TUint iUnitsMask; + DCodeSeg* iCodeSeg; + }; + + + + +/** @internalComponent */ +typedef DPhysicalDevice* (*TPhysicalDeviceNew)(); + +// Utility stuff for PDD finding + +/** @internalTechnology */ +struct SPhysicalDeviceEntry + { + TInt iPriority; + DPhysicalDevice* iPhysicalDevice; + }; + +/** @internalTechnology */ +class RPhysicalDeviceArray : public RArray + { +public: + IMPORT_C RPhysicalDeviceArray(); + IMPORT_C void Close(); + IMPORT_C TInt GetDriverList(const TDesC& aMatch, TInt aUnit, const TDesC8* aInfo, const TVersion& aVersion); + }; + +/******************************************** + * Kernel-side messages and message queues. + ********************************************/ +class TMessageQue; + + + + +/** +@publishedPartner +@released + +The base class for a kernel side message. + +This is a means of communication between Symbian OS threads +executing kernel-side code. +*/ +class TMessageBase : public SDblQueLink + { +public: + /** @internalComponent */ + enum TState {EFree,EDelivered,EAccepted}; +public: + TMessageBase() : iState(EFree), iQueue(NULL) {} + IMPORT_C void Send(TMessageQue* aQ); + IMPORT_C TInt SendReceive(TMessageQue* aQ); + IMPORT_C void Forward(TMessageQue* aQ, TBool aReceiveNext); + IMPORT_C void Complete(TInt aResult, TBool aReceiveNext); + IMPORT_C void Cancel(); /**< @internalComponent */ + IMPORT_C void PanicClient(const TDesC& aCategory, TInt aReason); +public: + IMPORT_C DThread* Client(); +public: + TUint8 iState; /**< @internalComponent */ + TMessageQue* iQueue; /**< @internalComponent */ + NFastSemaphore iSem; /**< @internalComponent */ + TInt iValue; /**< @internalComponent */ // msg id/return code + }; + + + + +/** +@publishedPartner +@released + +A queue for kernel-side messages. + +Objects of this type consist of a DFC plus a doubly-linked list +of received messages. +*/ +class TMessageQue : private TDfc + { +public: + IMPORT_C TMessageQue(TDfcFn aFunction, TAny* aPtr, TDfcQue* aDfcQ, TInt aPriority); + IMPORT_C void Receive(); + IMPORT_C TMessageBase* Poll(); + IMPORT_C TMessageBase* Last(); + IMPORT_C void CompleteAll(TInt aResult); + using TDfc::SetDfcQ; +public: + inline static void Lock() {NKern::FMWait(&MsgLock);} /**< @internalComponent */ + inline static void Unlock() {NKern::FMSignal(&MsgLock);} /**< @internalComponent */ + inline void UnlockAndKick() {Enque(&MsgLock);} /**< @internalComponent */ +public: + SDblQue iQ; /**< @internalComponent */ + TBool iReady; /**< @internalComponent */ + TMessageBase* iMessage; /**< @internalComponent */ + static NFastMutex MsgLock; /**< @internalComponent */ + friend class TMessageBase; + }; + + + + +/** +@publishedPartner +@released + +Synchronous kernel-side messages. + +There is one per thread, and the thread always blocks while the message is outstanding. +The iPtr field of a DFC points to the message. +*/ +class TThreadMessage : public TMessageBase + { +public: + /** + Returns argument 0 as an integer. + */ + inline TInt Int0() const {return (TInt)iArg[0];} + + /** + Returns argument 1 as an integer. + */ + inline TInt Int1() const {return (TInt)iArg[1];} + + /** + Returns argument 2 as an integer. + */ + inline TInt Int2() const {return (TInt)iArg[2];} + + /** + Returns argument 3 as an integer. + */ + inline TInt Int3() const {return (TInt)iArg[3];} + + /** + Returns argument 0 as a pointer type. + */ + inline TAny* Ptr0() const {return iArg[0];} + + /** + Returns argument 1 as a pointer type. + */ + inline TAny* Ptr1() const {return iArg[1];} + + /** + Returns argument 2 as a pointer type. + */ + inline TAny* Ptr2() const {return iArg[2];} + + /** + Returns argument 3 as a pointer type. + */ + inline TAny* Ptr3() const {return iArg[3];} +public: + /** + Message arguments. + */ + TAny* iArg[10]; // message arguments + }; + + + + +/** +@publishedPartner +@released + +An abstract class for a logical channel that provides a framework in which +user-side client requests are executed in the context of +a single kernel-side thread. +*/ +class DLogicalChannel : public DLogicalChannelBase + { +public: + enum { + /** + Defines the smallest request number that Request() accepts. + Smaller request numbers will raise a panic. + */ + EMinRequestId=(TInt)0xc0000000, + + /** + The value of the close message sent to the device driver thread + by Close(). + */ + ECloseMsg=(TInt)0x80000000}; +public: + IMPORT_C DLogicalChannel(); + IMPORT_C virtual ~DLogicalChannel(); + IMPORT_C virtual TInt Close(TAny*); + IMPORT_C virtual TInt Request(TInt aReqNo, TAny* a1, TAny* a2); + IMPORT_C virtual TInt SendMsg(TMessageBase* aMsg); + + /** + Processes a message for this logical channel. + This function is called in the context of a DFC thread. + + @param aMsg The message to process. + The iValue member of this distinguishes the message type: + iValue==ECloseMsg, channel close message + iValue==KMaxTInt, a 'DoCancel' message + iValue>=0, a 'DoControl' message with function number equal to iValue + iValue<0, a 'DoRequest' message with function number equal to ~iValue + */ + IMPORT_C virtual void HandleMsg(TMessageBase* aMsg)=0; + IMPORT_C void SetDfcQ(TDfcQue* aDfcQ); +public: + static void MsgQFunc(TAny* aPtr); +public: + TDfcQue* iDfcQ; + TMessageQue iMsgQ; + }; + + + + +/******************************************** + * Timers based on the system tick + ********************************************/ + +/** +@publishedPartner +@released + +Defines the signature for a tick timer callback function. +*/ +typedef void (*TTickCallBack)(TAny* aPtr); + + + + +/** +@publishedPartner +@released + +Relative timer with the resolution of one Symbian OS tick (generally 1/64 second). + +Tick timers are general purpose interval timers which are used where there +is no need for high resolution or great accuracy. They correspond to the +timing functions available to user side code on EKA1 (User::After, +RTimer::After, RTimer::Lock). + +@see User::After() +@see RTimer::After() +@see RTimer::Lock() +*/ +class TTickLink : public SDeltaQueLink + { +public: + IMPORT_C TTickLink(); + IMPORT_C void Periodic(TInt aPeriod, TTickCallBack aCallBack, TAny* aPtr); + IMPORT_C void OneShot(TInt aTime, TTickCallBack aCallBack, TAny* aPtr); + IMPORT_C void Lock(TInt aTicks, TTickCallBack aCallBack, TAny* aPtr); + IMPORT_C void Cancel(); + void DoCancel(); + TInt GetNextLock(TTimerLockSpec aMark, TInt &aTickCount) const; +public: + TInt iPeriod; /**< @internalComponent */ + TAny *iPtr; /**< @internalComponent */ + TTickCallBack iCallBack; /**< @internalComponent */ + Int64 iLastLock; /**< @internalComponent */ + }; + + + + +/** +@publishedPartner +@released + +Defines the signature for a second timer callback function. + +@see TSecondLink +*/ +typedef void (*TSecondCallBack)(TAny* aPtr); + + + + +/** +@publishedPartner +@released + +Absolute timer with a resolution of 1 second. + +Second timers are used when an event needs to occur at a specific date and +time of day, rather than after a specified interval. They have a resolution of +1 second. + +They are typically used for user alarms, and, if necessary, will power up +the system at the expiry time. +*/ +class TSecondLink : public SDblQueLink + { +public: + IMPORT_C TSecondLink(); + IMPORT_C TInt At(const TTimeK& aUTCTime, TSecondCallBack aCallBack, TAny* aPtr); + IMPORT_C void Cancel(); +public: + Int64 iTime; /**< @internalComponent */ + TAny* iPtr; /**< @internalComponent */ + TSecondCallBack iCallBack; /**< @internalComponent */ + }; + + + + +/** +@publishedPartner +@released + +Defines the signature for an inactivity timer callback function. + +@see TInactivityLink +*/ +typedef void (*TInactivityCallBack)(TAny*); + + + + +/** +@publishedPartner +@released + +Inactivity timer. + +Inactivity timers are used to detect a specified period of user inactivity, +for example to enable device auto power down or screen saver functionality. +*/ +class TInactivityLink : public SDblQueLink + { +public: + IMPORT_C TInactivityLink(); + IMPORT_C TInt Start(TInt aSeconds, TInactivityCallBack aCallBack, TAny* aPtr); + IMPORT_C void Cancel(); +public: + TUint32 iTime; /**< @internalComponent */ // expiry time in ticks + TAny* iPtr; /**< @internalComponent */ + TInactivityCallBack iCallBack; /**< @internalComponent */ + }; + +/******************************************** + * Internal RAM drive + ********************************************/ + +/** + @internalTechnology +*/ +class TInternalRamDrive + { +public: + static TInt Create(); + IMPORT_C static TLinAddr Base(); + IMPORT_C static TInt Size(); + IMPORT_C static TInt MaxSize(); + IMPORT_C static TInt Adjust(TInt aNewSize); + IMPORT_C static void Lock(); + IMPORT_C static void Unlock(); + IMPORT_C static void Wait(); + IMPORT_C static void Signal(); +public: + static DMutex* Mutex; + friend class Monitor; + }; + +/********************************************/ + +/** List of all supported events. + + By default, all events, except the explicitly mentioned ones, are sent only + if the kernel is built with __DEBUGGER_SUPPORT__ defined. + + This event set may be extended in the future, so clients should handle + unknown events gracefully. + + @see DKernelEventHandler + @publishedPartner + @released +*/ +enum TKernelEvent + { + /** + Event delivered when a user-side software exception occurs. + This event is always sent. + The following conditions are true: + - a1 contains a TExcType instance. + - The current thread is the thread taking the exception. + */ + EEventSwExc, + + /** + Event delivered when a hardware exception occurs. + This event is always sent. + The following conditions are true: + - a1 points to the CPU-specific structure stored on the + stack where the processor state has been saved. For ARM, + the structure is TArmExcInfo. + - The current thread is the thread taking the exception. + On exit, use DKernelEventHandler::EExcHandled to indicate event + handled. + */ + EEventHwExc, + + /** + Event delivered when a process is created (i.e. during a call to + RProcess::Create or Kern::ProcessCreate()). + The following conditions are true: + - a1 points to the process being created. + - a2 points to the creator thread (which may not be the current thread). + In some case the creator thread can not be reliably determined and a2 + will be set to NULL. + - The process being created is partly constructed (no threads and no chunks yet). + */ + EEventAddProcess, + + /** + Event delivered after a process attribute change. Currently this applies + only to process renaming and address space change (chunk addition/removal) + but may be extended in the future. + The following conditions are true: + - a1 points to the process being modified. + - The process lock may be held + */ + EEventUpdateProcess, + + /** + Event delivered when a process terminates. + The following conditions are true: + - a1 points to the process being terminated. + - The current thread is the kernel server thread. + - The process is partly destructed so its resources should be accessed + only after checking they still exist. + */ + EEventRemoveProcess, + + /** + Event delivered when a user or kernel thread is created (i.e. during a call + to RProcess::Create(), RThread::Create() or Kern::ThreadCreate()). + The following conditions are true: + - a1 points to the thread being created. + - a2 points to the creator thread (which may not be the current thread). + - The thread being created is fully constructed but has not executed any code yet. + */ + EEventAddThread, + + /** + Event delivered when a user or kernel thread is scheduled for the first time. + The following conditions are true: + - a1 points to the thread being scheduled. + - The current thread is the thread being scheduled. + - The thread has not executed any code yet. + */ + EEventStartThread, + + /** + Event delivered after a thread attribute change. Currently this applies + only to thread renaming but may be extended in the future. + a1 points to the thread being modified. + */ + EEventUpdateThread, + + /** + Event delivered when a user or kernel thread terminates. + This event is always sent. + The following conditions are true: + - a1 points to the thread being terminated. + - The current thread is the thread being terminated. + - The current thread is in the ECSExitInProgress state, + and so can not be suspended. + - The thread's address space can be inspected. + */ + EEventKillThread, + + /** + Event delivered when a user or kernel thread is about to be closed. + The following conditions are true: + - a1 points to the thread being terminated. + - The current thread is the supervisor thread. + - The thread is partly destructed so its resources should be accessed + only after checking if they still exist. + */ + EEventRemoveThread, + + /** + Event delivered when a chunk is created. + The following conditions are true: + - a1 points to the chunk being created. + */ + EEventNewChunk, + + /** + Event delivered when physical memory is committed to/decommitted from a + chunk. + The following conditions are true: + - a1 points to the chunk being modified. + */ + EEventUpdateChunk, + + /** + Event delivered when a chunk is deleted. + The following conditions are true: + - a1 points to the chunk being deleted. + */ + EEventDeleteChunk, + + /** + Event delivered when a user-side DLL is explicitly loaded. + The following conditions are true: + - a1 points to the DLibrary instance being loaded. + - a2 points to the creator thread. + - DLibrary::iMapCount is equals to 1 if the DLL is loaded for the first + time into the creator thread's address space. + - If the DLL is loaded for the first time, its global c'tors (if any) + haven't been called yet. + - The DLL and all its dependencies have been mapped. + - The system-wide mutex DCodeSeg::CodeSegLock is held. + */ + EEventAddLibrary, + + /** + Event delivered when a previously explicitly loaded user-side DLL is + closed or unloaded (i.e. call to RLibrary::Close()). + The following conditions are true: + - a1 points to the DLibrary instance being unloaded. + - DLibrary::iMapCount is equals to 0 if the DLL is about to be unloaded. + - If the DLL is about to be unloaded, its global d'tors have been called + but it is still mapped (and so are its dependencies). + - The current thread may be the kernel server. + - The system-wide mutex DCodeSeg::CodeSegLock is held. + */ + EEventRemoveLibrary, + + /** + Event delivered when a LDD is loaded. + The following conditions are true: + - a1 points to the LDD's code segment (DCodeSeg instance). + - The current thread is the loader thread. + - The LDD factory function has not been called yet. + */ + EEventLoadLdd, + + /** + Event delivered when a LDD is unloaded. + The following conditions are true: + - a1 points to the LDD's code segment (DCodeSeg instance). + - The current thread is the loader thread. + */ + EEventUnloadLdd, + + /** + Event delivered when a PDD is loaded. + The following conditions are true: + - a1 points to the PDD's code segment (DCodeSeg instance). + - The current thread is the loader thread. + - The PDD factory function has not been called yet. + */ + EEventLoadPdd, + + /** + Event delivered when a PDD is unloaded. + The following conditions are true: + - a1 points to the PDD's code segment (DCodeSeg instance). + - The current thread is the loader thread. + */ + EEventUnloadPdd, + + /** + Event delivered when RDebug::Print is called in user-side code. + The following conditions are true: + - a1 points to the user-side buffer containing the unicode string + for printing. The characters can not be accessed directly. The + string must copied instead using kumemget() and, as the event + is delivered in thread critical section, the call to kumemget() + must be protected with XTRAP. + - a2 is a TInt which holds the length in characters of the string + for printing. As this is a unicode string, the size of the + user-side buffer is twice the length. + - The current thread is the user-side client. + On exit use DKernelEventHandler::ETraceHandled to indicate event handled. + */ + EEventUserTrace, + + /** + Event delivered when a code segment is mapped into a process. + The following conditions are true: + - a1 points to the code segment. + - a2 points to the process. + - The system-wide mutex DCodeSeg::CodeSegLock is held. + */ + EEventAddCodeSeg, + + /** + Event delivered when a code segment is unmapped from a process. + The following conditions are true: + - a1 points to the code segment. + - a2 points to the process. + - The system-wide mutex DCodeSeg::CodeSegLock is held. + */ + EEventRemoveCodeSeg, + + /** + Event delivered when a process is created (i.e. during a call to + RProcess::Create or Kern::ProcessCreate()). + The following conditions are true: + - a1 points to the process. + - The process being created is fully constructed. + */ + EEventLoadedProcess, + + /** + Event delivered when a process is being released, before its code segment, + stack chunk, etc. are unmapped. + The following conditions are true: + - a1 points to the process. + - The process being released is fully constructed. + */ + EEventUnloadingProcess, + + /** + Must be last + */ + EEventLimit + }; + +/** Access-counted event handler callback. + + The kernel maintains a queue of event handlers which are called in turn + when various events (thread creation, hardware exception, ...) occur. + + Typical clients would be drivers or kernel extensions implementing kernel + debug agents or profilers. This class could also be used to extend the + instruction set (by trapping undefined instructions). + + An access count needs to be maintained because handlers can not be dequeued + and destructed while one or more threads are executing some code inside the + callback. The access count, initially set to 1, is incremented every time + a thread enters the callback and decremented every time a thread exits the + callback. + + Consequently: + + - Client code should use Close() instead the operator delete to destroy the + event handler. + + - If the client is a LDD, the lifetime of the event handler may exceed that + of the logical channel and its user-side client thread. Therefore, the + callback should not refer to data stored in the channel and any + asynchronous request to be completed in the callback should be cancelled by + the channel destructor. + + If the client is a RAM-loaded LDD (or PDD), it is possible for the DLL to + be unloaded while the handler is still in use. This would result in an + exception. To avoid this, the handler must open a reference to the + DLogicalDevice (or DPhysicalDevice) and close it in its d'tor. + + @publishedPartner + @released +*/ +class DKernelEventHandler : public DBase + { +public: + /** Values used to select where to insert the handler in the queue */ + enum TAddPolicy + { + EAppend, /**< Append at end of queue */ + }; + + /** Bitmask returned by callback function */ + enum TReturnCode + { + /** Run next handler if set, ignore remaining handlers if cleared */ + ERunNext = 1, + /** Available for EEventUserTrace only. Ignore trace statement if set. */ + ETraceHandled = 0x40000000, + /** Available for hardware exceptions only. Do not panic thread if set. */ + EExcHandled = (TInt)0x80000000, + }; + + /** Pointer to C callback function called when an event occurs. + aEvent designates what event is dispatched. a1 and a2 are event-specific. + aPrivateData is specified when the handler is created, typically a pointer + to the event handler. + The function is always called in thread critical section. + @see TReturnCode + */ + typedef TUint (*TCallback)(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aPrivateData); +public: + // external interface + IMPORT_C static TBool DebugSupportEnabled(); + IMPORT_C DKernelEventHandler(TCallback aCb, TAny* aPrivateData); + IMPORT_C TInt Add(TAddPolicy aPolicy = EAppend); + IMPORT_C TInt Close(); + inline TBool IsQueued() const; +public: + // kernel internal interface + static TUint Dispatch(TKernelEvent aEvent, TAny* a1, TAny* a2); +private: + static SDblQue HandlersQ; +private: + TInt iAccessCount; + SDblQueLink iLink; + TCallback iCb; + TAny* iPrivateData; + }; + +/** Returns whether or not the handler has been queued. */ +inline TBool DKernelEventHandler::IsQueued() const + { + return iLink.iNext != NULL; + } + + +/******************************************** + * Persistent Machine Configuration + ********************************************/ + +/** + @internalTechnology +*/ +class TMachineConfig + { +public: + TInt iLogSize; + TInt iLogMaxSize; + SLocaleData iLocale; + TInt iXtalError; + + /** The last time set by the user */ + TTimeK LastSetTime; + + /** The accumulated RTC correction due to crystal errors */ + TInt TheRTCCorrection; + }; + +/****************************************************************************** + * Macros for typical extensions/device drivers/ASSPs + ******************************************************************************/ +#ifndef __WINS__ +/** +@internalComponent +@prototype 9.5 + +Defines the entry point for an extension that specifies a priority +Priorities are used to sequence calls to the entry point (KModuleEntryReasonExtensionInit1) +and may be used to ensure that extensions with higher priority are started before +ones with lower priority. When the priority of 2 extensions is the same, the order +they are started is the order they appear in the ROM header extension list. +The maximum priority is 255. Priority 0 is the lowest priority (standard extension). +@note This feature is not available for the emulator. +*/ +#define DECLARE_EXTENSION_WITH_PRIORITY(priority) \ + GLREF_C TInt InitExtension(); \ + TInt KernelModuleEntry(TInt aReason) \ + { \ + if (aReason==KModuleEntryReasonExtensionInit0) \ + return priority; \ + if (aReason!=KModuleEntryReasonExtensionInit1) \ + return KErrArgument; \ + return InitExtension(); \ + } \ + GLDEF_C TInt InitExtension() + + +/** +@publishedPartner +@released + +Defines the entry point for a standard extension +*/ +#define DECLARE_STANDARD_EXTENSION() DECLARE_EXTENSION_WITH_PRIORITY(KExtensionStandardPriority) + +#else +/** +@publishedPartner +@released + +Defines the entry point for a standard extension +*/ +#define DECLARE_STANDARD_EXTENSION() \ + GLREF_C TInt InitExtension(); \ + TInt KernelModuleEntry(TInt aReason) \ + { \ + if (aReason==KModuleEntryReasonExtensionInit0) \ + return KErrNone; \ + if (aReason!=KModuleEntryReasonExtensionInit1) \ + return KErrArgument; \ + return InitExtension(); \ + } \ + GLDEF_C TInt InitExtension() + +#endif + +/** +@publishedPartner +@released + +Defines the entry point for a standard logical device driver (LDD), +and declares the ordinal 1 export function for creating the LDD factory object +*/ +#define DECLARE_STANDARD_LDD() \ + TInt KernelModuleEntry(TInt) \ + { return KErrNone; } \ + EXPORT_C DLogicalDevice* CreateLogicalDevice() + + + + +/** +@publishedPartner +@released + +Defines the entry point for a standard physical device driver (PDD), +and declares the ordinal 1 export function for creating the PDD factory object. +*/ +#define DECLARE_STANDARD_PDD() \ + TInt KernelModuleEntry(TInt) \ + { return KErrNone; } \ + EXPORT_C DPhysicalDevice* CreatePhysicalDevice() + + + + +/** +@publishedPartner +@released + +Defines the entry point for a standard logical device driver (LDD) +that is also an extension, and declares the ordinal 1 export function +for creating the LDD factory object +*/ +#define DECLARE_EXTENSION_LDD() \ + EXPORT_C DLogicalDevice* CreateLogicalDevice() + + + + +/** +@publishedPartner +@released + +Defines the entry point for a standard physical device driver (PDD) +that is also an extension, and declares the ordinal 1 export function +for creating the PDD factory object +*/ +#define DECLARE_EXTENSION_PDD() \ + EXPORT_C DPhysicalDevice* CreatePhysicalDevice() + + + + +/** +@publishedPartner +@released + +Generates a stub entry point function and the AsicInitialise() function that +causes static constructors to be called. + +ASSP DLLs require static constructors to be called at the same time as +the variant is initialised. +*/ +#define DECLARE_STANDARD_ASSP() \ + extern "C" { GLREF_C TInt _E32Dll(TInt); } \ + GLDEF_C TInt KernelModuleEntry(TInt aReason) \ + { return (aReason==KModuleEntryReasonExtensionInit1) \ + ?KErrNone:KErrGeneral; } \ + EXPORT_C void AsicInitialise() \ + { _E32Dll(KModuleEntryReasonExtensionInit1); } + + +/** +@internalComponent +*/ +#define __VARIANT_SUPPORTS_ADDITIONAL_INTERFACE_BLOCK__(x) \ + __Variant_Flags__ |= (x) + +/** +@internalTechnology +@prototype +Used to indicate that a variant supports the nanokernel interface block +*/ +#define __VARIANT_SUPPORTS_NANOKERNEL_INTERFACE_BLOCK__() \ + __VARIANT_SUPPORTS_ADDITIONAL_INTERFACE_BLOCK__(1) + + +class DemandPaging; + +/** +Memory locking on demand paging systems. + +This class is not thread safe. I.e. Only one method should be executed at any time +for a given instance of an object. + +@internalTechnology +@prototype +*/ +class DDemandPagingLock : public DBase + { +public: + IMPORT_C DDemandPagingLock(); + + /** + Unlock and Free the memory associated with this object + */ + inline ~DDemandPagingLock() { Free(); } + + /** + Reserve memory so that this object can be used for locking up to + the specified number of bytes. + + @param aSize Maximum number of bytes to be locked. + + @return KErrNone or standard error code. + */ + IMPORT_C TInt Alloc(TInt aSize); + + /** + Unlock any memory locked by this object, then free the memory reserved with + Alloc(). This returns the object to the same state it was at immediately after + construction. + */ + IMPORT_C void Free(); + + /** + Ensure all pages in the given region are present and lock them so that they will + not be paged out. If the region contained no demand paged memory, then no action + is performed. + + This function may not be called again until the previous memory has been + unlocked. + + @param aThread The thread in whoes process the memory lies. + @param aStart The address of the first byte of memory to be locked. + @param aSize The number of bytes to lock. + + @return 1 (one) if any memory was locked. 0 (KErrNone) if memory + did not need locking because it is not demand paged. Otherwise + KErrBadDescriptor to indicate that the memory region was not + valid. + + @pre Alloc must have been used to reserve sufficient RAM. + */ + IMPORT_C TInt Lock(DThread* aThread, TLinAddr aStart, TInt aSize); + + /** + Unlock the memory region which was previousely locked with Lock. + This may be called even if memory wasn't previousely locked. + */ + inline void Unlock() { if(iLockedPageCount) DoUnlock(); } + +private: + IMPORT_C void DoUnlock(); +private: + DemandPaging* iThePager; + TInt iReservedPageCount; + TInt iLockedPageCount; + TLinAddr iLockedStart; + DProcess* iProcess; + TPhysAddr* iPages; + TAny* iPinMapping; + TInt iMaxPageCount; + + friend class DemandPaging; + }; + + + +class DPagingRequestPool; + +/** +Base class for Paging Devices. +A Paging Device provides the paging system with access to storage media which holds +data being demand paged. +@internalTechnology +@prototype +*/ +class DPagingDevice : public DBase + { +public: + /** The type of device this represents. */ + enum TType + { + ERom = 1<<0, /**< Paged ROM device type. */ + ECode = 1<<1, /**< Code paging device type. */ + EData = 1<<2 /**< Data paging device type. */ + }; + + enum TSpecialDrives + { + EDriveRomPaging = -1, /**< Special drive number to indicate rom paging. */ + EDriveDataPaging = -2, /**< Special drive number to indicate data paging. */ + }; + + /** + Called by the paging system to read data from the media represented by this + device. + + @param aBuffer The location where the read data should be stored. + @param aOffset The offset from the media start, in read units, from where + data should be read. + @param aSize The number of read units to be read. + + @param aDrvNumber The drive number for code paging or a member of TSpecialDrives for rom or data + paging. + + @return KErrNone or standard error code. + */ + virtual TInt Read(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize, TInt aDrvNumber) = 0; + + /** + Called by the paging system to write data to the media represented by this device. + + This is only used in the implementation of data paging to write to the swap partition. + + @param aBuffer The location of the data to write. + @param aOffset The offset from the media start, in read units, to where data should be written. + @param aSize The number of read units to write. + @param aBackground If set, this indicates that the request should not count as making the device busy. + + @return KErrNone or standard error code. + */ + inline virtual TInt Write(TThreadMessage* aReq,TLinAddr aBuffer,TUint aOffset,TUint aSize,TBool aBackground); + + /** + Called by the paging system to notify the media driver that data that was previously written is + now no longer needed. + + This is only used in the implementation of data paging when data in the swap partition is no + longer needed. + + @param aOffset The offset from the media start, in read units, to where data was written. + @param aSize The size in read units. + + @return KErrNone or standard error code. + */ + inline virtual TInt DeleteNotify(TThreadMessage* aReq,TUint aOffset,TUint aSize); + + /** + Called by the paging device to notify the kernel that the device has just become idle and is not + currently processing any requests. + + This is used by the kernel to work out when to clean pages in the background. + + Note that write requests made by calling the DPagingDevice::Write() with the aBackground flag + set do not count towards the device being busy. + */ + IMPORT_C void NotifyIdle(); + + /** + Called by the paging device to notify the kernel that the device has just become busy and is + currently processing requests. + + This is used by the kernel to work out when to clean pages in the background. + + Note that write requests made by calling the DPagingDevice::Write() with the aBackground flag + set do not count towards the device being busy. + */ + IMPORT_C void NotifyBusy(); + +public: + /** The type of device this represents. */ + TUint32 iType; + + /** The local drives supported for code paging. + This is a bitmask containing one bit set for each local drive supported, where the bit set + is 1 << the local drive number. If this device does not support code paging, this should be + zero. */ + TUint32 iDrivesSupported; + + /** Zero terminated string representing the name of the device. + (Only used for debug tracing purposes.) */ + const char* iName; + + /** Log2 of the read unit size. A read unit is the number of bytes which + the device can optimally read from the underlying media. + E.g. for small block NAND, a read unit would be equal to the page size, + 512 bytes, therefore iReadUnitShift would be set to 9. */ + TInt iReadUnitShift; + + /** The value the device should use to identify itself. + This value is set by Kern::InstallPagingDevice(). + The purpose of this Id is to distinguish multiple Code Paging devices. */ + TInt iDeviceId; + + /** For data paging only, the size of the swap partition supported by this device, in read units. + + If data paging is not supported, or has been disabled by the media driver, this should be + zero. + */ + TInt iSwapSize; + + /** The pool of DPagingRequest objects used to issue requests for this device. + This is setup and used internally by the kernel. + */ + DPagingRequestPool* iRequestPool; + + /** Reserved for future use. + */ + TInt iSpare[4]; + }; + +inline TInt DPagingDevice::Write(TThreadMessage*,TLinAddr,TUint,TUint,TBool) + { + // Default implementation, may be overriden by dervied classes + return KErrNotSupported; + } + +inline TInt DPagingDevice::DeleteNotify(TThreadMessage*,TUint,TUint) + { + // Default implementation, may be overriden by dervied classes + return KErrNotSupported; + } + +extern "C" { extern TInt __Variant_Flags__; } + +/******************************************** + * Shareable Data Buffers + ********************************************/ +/** + Pool create info + + @publishedPartner + @prototype +*/ +class TMappingAttributes2; + +#include + +class TShPoolCreateInfo + { +public: + /** + Enumeration type to say that the shared pool is to be backed with memory supplied by the kernel. + */ + enum TShPoolPageAlignedBuffers + { + EPageAlignedBuffer = EShPoolPageAlignedBuffer, + }; + + /** + Enumeration type to say that the shared pool is to be backed with memory supplied by the kernel. + */ + enum TShPoolNonPageAlignedBuffers + { + ENonPageAlignedBuffer = EShPoolNonPageAlignedBuffer, + }; + + /** + Enumeration type to say that the shared pool is to be mapped onto device memory. + */ + enum TShPoolMemoryDevice + { + EDevice = EShPoolPhysicalMemoryPool, + }; + + IMPORT_C TShPoolCreateInfo(TShPoolPageAlignedBuffers aFlag, TUint aBufSize, TUint aInitialBufs); + IMPORT_C TShPoolCreateInfo(TShPoolNonPageAlignedBuffers aFlag, TUint aBufSize, TUint aInitialBufs, TUint aAlignment); + + IMPORT_C TShPoolCreateInfo(TShPoolMemoryDevice aFlag, TUint aBufSize, TUint aInitialBufs, TUint aAlignment, TUint aPages, TPhysAddr* aPhysicalAddressList); + + IMPORT_C TShPoolCreateInfo(TShPoolMemoryDevice aFlag, TUint aBufSize, TUint aInitialBufs, TUint aAlignment, TUint aPages, TPhysAddr aPhysicalAddress); + + IMPORT_C TInt SetSizingAttributes(TUint aMaxBufs, TUint aMinFreeBufs, TUint aGrowByBufs, TUint aShrinkByBufs); + IMPORT_C TInt SetExclusive(); + IMPORT_C TInt SetContiguous(); + IMPORT_C TInt SetGuardPages(); + +private: + friend class ExecHandler; + friend class DShPool; + friend class DMemModelShPool; + friend class DMemModelAlignedShPool; + friend class DMemModelNonAlignedShPool; + friend class DMemModelProcess; + friend class DWin32ShPool; + friend class DWin32AlignedShPool; + friend class DWin32NonAlignedShPool; + friend class DWin32Process; + friend class DShBufTestDrvChannel; + + inline TShPoolCreateInfo() ///< default constructor + { + memclr(this, sizeof(TShPoolCreateInfo)); + }; + + TShPoolInfo iInfo; + + union PhysAddr + { + TPhysAddr* iPhysAddrList; ///< physical addresses for hardware + TPhysAddr iPhysAddr; ///< physical address for hardware + } iPhysAddr; + + TUint iPages; ///< number of pages to commit +}; + +#endif //__K32STD_H__