diff -r dc268b18d709 -r 6a75fa55495f kernel/eka/include/nkern/win32/nk_plat.h --- a/kernel/eka/include/nkern/win32/nk_plat.h Wed Sep 22 10:53:45 2010 +0100 +++ b/kernel/eka/include/nkern/win32/nk_plat.h Mon Sep 27 10:52:00 2010 +0100 @@ -1,4 +1,4 @@ -// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 1998-2010 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" @@ -12,7 +12,7 @@ // // Description: // e32\include\nkern\win32\nk_plat.h -// +// // WARNING: This file contains some APIs which are internal and are subject // to change without notice. Such APIs should therefore not be used // outside the Kernel and Hardware Services package. @@ -23,20 +23,20 @@ @internalComponent */ -#ifndef __NK_WIN32_H__ -#define __NK_WIN32_H__ +#ifndef __NK_WIN32_H__ +#define __NK_WIN32_H__ -#define _CRTIMP // we want to use the win32 static runtime library +#define _CRTIMP // we want to use the win32 static runtime library -#define WIN32_LEAN_AND_MEAN -#define _WIN32_WINNT 0x0400 +#define WIN32_LEAN_AND_MEAN +#define _WIN32_WINNT 0x0400 #include -typedef void (*TExcHandler)(TAny*,TAny*); +typedef void (*TExcHandler)(TAny*, TAny*); struct TWin32ExcInfo { - enum {EExcInKernel = 0x1}; + enum { EExcInKernel = 0x1 }; public: TExcHandler iHandler; TAny* iParam[2]; @@ -67,20 +67,21 @@ enum TEmulThreadType { EThreadEvent, // an 'interrupt' thread, interacts with Win32 events - EThreadNKern // a nKern thread, identified by a NThread control block + EThreadNKern // an nKern thread, identified by an NThread control block }; class NThread : public NThreadBase { public: typedef void (*TDivert)(); - enum TWakeup {ERelease,EResume,EResumeLocked,EIdle,EEscaped,EResumeDiverted}; - enum TSelectCpu {ECpuAll=-1,ECpuSingle=-2}; + enum TWakeup { ERelease, EResume, EResumeLocked, EIdle, EEscaped, EResumeDiverted }; + enum TSelectCpu { ECpuAll = -1, ECpuSingle = -2 }; + public: TInt Create(SNThreadCreateInfo& aInfo, TBool aInitial); void Stillborn(); void DoForceExit(); -// + IMPORT_C static void Idle(); IMPORT_C static void SetProperties(TBool aTrace, TInt aCpu); TBool WakeUp(); @@ -90,10 +91,10 @@ private: static DWORD WINAPI StartThread(LPVOID aParam); -// + static void ExitSync(); static void ExitAsync(); -// + static void Exception(); static LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* aExc); @@ -105,74 +106,75 @@ public: HANDLE iWinThread; DWORD iWinThreadId; - HANDLE iScheduleLock; // event used for scheduling interlock - TBool iDiverted; // flag to indicate that the thread is being diverted - TDivert iDivert; // function to invoke after reschedule, may be null - TAny* iDivertReturn; // return address from diversion - TInt iInKernel; // flag to indicate if the thread is running 'in' the kernel - TWakeup iWakeup; // indicates how to wake up the thread + HANDLE iScheduleLock; // event used for scheduling interlock + volatile TInt iInKernel; // flag to indicate if the thread is running 'in' the kernel + TWakeup iWakeup; // indicates how to wake up the thread + TBool iDiverting; // flag to indicate that the thread is being diverted + TDivert iDivertFn; // function to invoke after reschedule, may be null + TAny* iDivertReturn; // return address from diversion TLinAddr iUserStackBase; }; IMPORT_C HANDLE CreateWin32Thread(TEmulThreadType aType, LPTHREAD_START_ROUTINE aThreadFunc, LPVOID aPtr, TBool aRun); -IMPORT_C void StartOfInterrupt(); -IMPORT_C void EndOfInterrupt(); void SchedulerInit(NThread& aInit); void SchedulerRegister(NThread& aSelf); -NThread* SchedulerThread(); -NThread& CheckedCurrentThread(); void SchedulerLock(); void SchedulerUnlock(); void SchedulerEscape(); void SchedulerReenter(); -void Win32FindNonPreemptibleFunctions(); +NThread* RunningThread(); +NThread& CheckedCurrentThread(); -inline void EnterKernel(TBool aCheck=TRUE) - { - if (++CheckedCurrentThread().iInKernel==1 && aCheck) - { - NThread& t = CheckedCurrentThread(); - __NK_ASSERT_ALWAYS(t.iCsCount==0); - __NK_ASSERT_ALWAYS(t.iHeldFastMutex==0); - __NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked==0); - } - } +void EnterKernel(TBool aDiversion = FALSE); +void LeaveKernel(); +IMPORT_C void StartOfInterrupt(); +IMPORT_C void EndOfInterrupt(); -void LeaveKernel(); +void Win32FindNonPreemptibleFunctions(); IMPORT_C TInt __fastcall Dispatch(TInt aFunction, TInt* aArgs); -typedef TInt (__cdecl *TExecHandler)(TInt,TInt,TInt,TInt); -typedef void (__cdecl *TPreprocessHandler)(TInt*,TUint32); +typedef TInt (__cdecl* TExecHandler)(TInt, TInt, TInt, TInt); +typedef void (__cdecl* TPreprocessHandler)(TInt*, TUint32); // Emulator nKern scheduling data class Win32Interrupt { public: void Init(); - TInt Mask(); - void Restore(TInt aLevel); - void Begin(); - void End(); + void BeginInterrupt(); + void EndInterrupt(); + TInt MaskInterrupts(TBool aPreempt); + void RestoreInterruptMask(TInt aLevel); + void ForceReschedule(); + inline TBool InInterrupt() const - {return iInterrupted!=0;} - void ForceReschedule(); + { + return iInterrupted != 0; + } inline TBool InterruptsStatus(TBool aRequest) const - {return aRequest?(iLevel==0):(iLevel!=0);} + { + return aRequest ? (iLevel == 0) : (iLevel != 0); + } + private: - static void Reschedule(TAny*); + static void SchedulerThreadFunction(TAny*); + private: - TInt iLock; - HANDLE iQ; - DWORD iOwner; - TInt iLevel; + CRITICAL_SECTION iCS; // protects data below + HANDLE iQ; // semaphore to wait on + + DWORD iOwner; // controller of the mask + TInt iLevel; // owner's recursion count + TInt iWaiting; // number of waiters + TBool iRescheduleOnExit; - NThread* iInterrupted; - NThread iScheduler; + NThread* iInterrupted; // the thread preempted by Begin() + NThread iScheduler; // the dedicated scheduler thread }; -extern TBool Win32AtomicSOAW; // flag to indicate availability of SignalObjectAndWait() API +extern TBool Win32AtomicSOAW; // flag to indicate availability of SignalObjectAndWait() API extern TBool Win32TraceThreadId; extern TInt Win32SingleCpu; extern Win32Interrupt Interrupt; @@ -184,4 +186,60 @@ void FastCounterInit(); -#endif +// Wrappers round Win32 thread control & synchronisation functions ... +inline void CheckedSuspendThread(HANDLE aWinThread) + { + TInt suspLevel = (TInt)SuspendThread(aWinThread); + __NK_ASSERT_ALWAYS(suspLevel >= 0); + } + +inline void CheckedResumeThread(HANDLE aWinThread, BOOL once = EFalse) + { + TInt suspLevel = (TInt)ResumeThread(aWinThread); + __NK_ASSERT_ALWAYS(once ? suspLevel == 1 : suspLevel > 0); // check thread was previously suspended + } + +inline void CheckedGetThreadContext(HANDLE aWinThread, CONTEXT* aContext) + { + DWORD r = GetThreadContext(aWinThread, aContext); + __NK_ASSERT_ALWAYS(r != 0); + } + +inline void CheckedSetThreadContext(HANDLE aWinThread, CONTEXT* aContext) + { + DWORD r = SetThreadContext(aWinThread, aContext); + __NK_ASSERT_ALWAYS(r != 0); + } + +inline void CheckedSetThreadPriority(HANDLE aWinThread, TInt aPriority) + { + DWORD r = SetThreadPriority(aWinThread, aPriority); + __NK_ASSERT_ALWAYS(r != 0); + } + +inline void CheckedWaitForSingleObject(HANDLE aWaitObject) + { + DWORD r = WaitForSingleObject(aWaitObject, INFINITE); + __NK_ASSERT_ALWAYS(r == WAIT_OBJECT_0); + } + +inline void CheckedSignalObjectAndWait(HANDLE aToWake, HANDLE aToWaitOn) + { + DWORD r = SignalObjectAndWait(aToWake, aToWaitOn, INFINITE, FALSE); + __NK_ASSERT_ALWAYS(r == WAIT_OBJECT_0); + } + +inline void CheckedSetEvent(HANDLE aWaitObject) + { + DWORD r = SetEvent(aWaitObject); + __NK_ASSERT_ALWAYS(r != 0); + } + +inline void CheckedReleaseSemaphore(HANDLE aSemaphore) + { + DWORD r = ReleaseSemaphore(aSemaphore, 1, NULL); + __NK_ASSERT_ALWAYS(r != 0); + } + + +#endif // __NK_WIN32_H__