kernel/eka/include/nkern/win32/nk_plat.h
changeset 273 6a75fa55495f
parent 0 a41df078684a
equal deleted inserted replaced
271:dc268b18d709 273:6a75fa55495f
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     1 // Copyright (c) 1998-2010 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
    10 //
    10 //
    11 // Contributors:
    11 // Contributors:
    12 //
    12 //
    13 // Description:
    13 // Description:
    14 // e32\include\nkern\win32\nk_plat.h
    14 // e32\include\nkern\win32\nk_plat.h
    15 // 
    15 //
    16 // WARNING: This file contains some APIs which are internal and are subject
    16 // WARNING: This file contains some APIs which are internal and are subject
    17 //          to change without notice. Such APIs should therefore not be used
    17 //          to change without notice. Such APIs should therefore not be used
    18 //          outside the Kernel and Hardware Services package.
    18 //          outside the Kernel and Hardware Services package.
    19 //
    19 //
    20 
    20 
    21 /**
    21 /**
    22  @file
    22  @file
    23  @internalComponent
    23  @internalComponent
    24 */
    24 */
    25 
    25 
    26 #ifndef __NK_WIN32_H__
    26 #ifndef	__NK_WIN32_H__
    27 #define __NK_WIN32_H__
    27 #define	__NK_WIN32_H__
    28 
    28 
    29 #define _CRTIMP			// we want to use the win32 static runtime library
    29 #define	_CRTIMP			// we want to use the win32 static runtime library
    30 
    30 
    31 #define WIN32_LEAN_AND_MEAN
    31 #define	WIN32_LEAN_AND_MEAN
    32 #define _WIN32_WINNT 0x0400
    32 #define	_WIN32_WINNT	0x0400
    33 #include <windows.h>
    33 #include <windows.h>
    34 
    34 
    35 typedef void (*TExcHandler)(TAny*,TAny*);
    35 typedef void (*TExcHandler)(TAny*, TAny*);
    36 
    36 
    37 struct TWin32ExcInfo
    37 struct TWin32ExcInfo
    38 	{
    38 	{
    39 	enum {EExcInKernel = 0x1};
    39 	enum { EExcInKernel = 0x1 };
    40 public:
    40 public:
    41 	TExcHandler iHandler;
    41 	TExcHandler iHandler;
    42 	TAny* iParam[2];
    42 	TAny* iParam[2];
    43 	TUint iFlags;
    43 	TUint iFlags;
    44 	// ExcType, iExcId, iFaultAddress, iEax, iEcx, iEdx, iEbx, iEsp, iEbp, iEsi, iEdi,
    44 	// ExcType, iExcId, iFaultAddress, iEax, iEcx, iEdx, iEbx, iEsp, iEbp, iEsi, iEdi,
    65 	};
    65 	};
    66 
    66 
    67 enum TEmulThreadType
    67 enum TEmulThreadType
    68 	{
    68 	{
    69 	EThreadEvent,	// an 'interrupt' thread, interacts with Win32 events
    69 	EThreadEvent,	// an 'interrupt' thread, interacts with Win32 events
    70 	EThreadNKern	// a nKern thread, identified by a NThread control block
    70 	EThreadNKern	// an nKern thread, identified by an NThread control block
    71 	};
    71 	};
    72 
    72 
    73 class NThread : public NThreadBase
    73 class NThread : public NThreadBase
    74 	{
    74 	{
    75 public:
    75 public:
    76 	typedef void (*TDivert)();
    76 	typedef void (*TDivert)();
    77 	enum TWakeup {ERelease,EResume,EResumeLocked,EIdle,EEscaped,EResumeDiverted};
    77 	enum TWakeup { ERelease, EResume, EResumeLocked, EIdle, EEscaped, EResumeDiverted };
    78 	enum TSelectCpu {ECpuAll=-1,ECpuSingle=-2};
    78 	enum TSelectCpu { ECpuAll = -1, ECpuSingle = -2 };
       
    79 
    79 public:
    80 public:
    80 	TInt Create(SNThreadCreateInfo& aInfo, TBool aInitial);
    81 	TInt Create(SNThreadCreateInfo& aInfo, TBool aInitial);
    81 	void Stillborn();
    82 	void Stillborn();
    82 	void DoForceExit();
    83 	void DoForceExit();
    83 //
    84 
    84 	IMPORT_C static void Idle();
    85 	IMPORT_C static void Idle();
    85 	IMPORT_C static void SetProperties(TBool aTrace, TInt aCpu);
    86 	IMPORT_C static void SetProperties(TBool aTrace, TInt aCpu);
    86 	TBool WakeUp();
    87 	TBool WakeUp();
    87 	TBool IsSafeToPreempt();
    88 	TBool IsSafeToPreempt();
    88 	void Divert(TDivert aDivert);
    89 	void Divert(TDivert aDivert);
    89 	void ApplyDiversion();
    90 	void ApplyDiversion();
    90 
    91 
    91 private:
    92 private:
    92 	static DWORD WINAPI StartThread(LPVOID aParam);
    93 	static DWORD WINAPI StartThread(LPVOID aParam);
    93 //
    94 
    94 	static void ExitSync();
    95 	static void ExitSync();
    95 	static void ExitAsync();
    96 	static void ExitAsync();
    96 //
    97 
    97 	static void Exception();
    98 	static void Exception();
    98 	static LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* aExc);
    99 	static LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* aExc);
    99 
   100 
   100 public:
   101 public:
   101 	static void Diverted();
   102 	static void Diverted();
   103 	static DWORD ExceptionHandler(EXCEPTION_RECORD* aException, CONTEXT* aContext);
   104 	static DWORD ExceptionHandler(EXCEPTION_RECORD* aException, CONTEXT* aContext);
   104 
   105 
   105 public:
   106 public:
   106 	HANDLE iWinThread;
   107 	HANDLE iWinThread;
   107 	DWORD iWinThreadId;
   108 	DWORD iWinThreadId;
   108 	HANDLE iScheduleLock;	// event used for scheduling interlock
   109 	HANDLE iScheduleLock;		// event used for scheduling interlock
   109 	TBool iDiverted;		// flag to indicate that the thread is being diverted
   110 	volatile TInt iInKernel;	// flag to indicate if the thread is running 'in' the kernel
   110 	TDivert iDivert;		// function to invoke after reschedule, may be null
   111 	TWakeup iWakeup;			// indicates how to wake up the thread
   111 	TAny* iDivertReturn;    // return address from diversion
   112 	TBool iDiverting;			// flag to indicate that the thread is being diverted
   112 	TInt iInKernel;			// flag to indicate if the thread is running 'in' the kernel
   113 	TDivert iDivertFn;			// function to invoke after reschedule, may be null
   113 	TWakeup iWakeup;		// indicates how to wake up the thread
   114 	TAny* iDivertReturn;    	// return address from diversion
   114 	TLinAddr iUserStackBase;
   115 	TLinAddr iUserStackBase;
   115 	};
   116 	};
   116 
   117 
   117 IMPORT_C HANDLE CreateWin32Thread(TEmulThreadType aType, LPTHREAD_START_ROUTINE aThreadFunc, LPVOID aPtr, TBool aRun);
   118 IMPORT_C HANDLE CreateWin32Thread(TEmulThreadType aType, LPTHREAD_START_ROUTINE aThreadFunc, LPVOID aPtr, TBool aRun);
   118 IMPORT_C void StartOfInterrupt();
       
   119 IMPORT_C void EndOfInterrupt();
       
   120 
   119 
   121 void SchedulerInit(NThread& aInit);
   120 void SchedulerInit(NThread& aInit);
   122 void SchedulerRegister(NThread& aSelf);
   121 void SchedulerRegister(NThread& aSelf);
   123 NThread* SchedulerThread();
       
   124 NThread& CheckedCurrentThread();
       
   125 void SchedulerLock();
   122 void SchedulerLock();
   126 void SchedulerUnlock();
   123 void SchedulerUnlock();
   127 void SchedulerEscape();
   124 void SchedulerEscape();
   128 void SchedulerReenter();
   125 void SchedulerReenter();
       
   126 NThread* RunningThread();
       
   127 NThread& CheckedCurrentThread();
       
   128 
       
   129 void EnterKernel(TBool aDiversion = FALSE);
       
   130 void LeaveKernel();
       
   131 IMPORT_C void StartOfInterrupt();
       
   132 IMPORT_C void EndOfInterrupt();
       
   133 
   129 void Win32FindNonPreemptibleFunctions();
   134 void Win32FindNonPreemptibleFunctions();
   130 
   135 
   131 inline void EnterKernel(TBool aCheck=TRUE)
       
   132 	{
       
   133 	if (++CheckedCurrentThread().iInKernel==1 && aCheck)
       
   134 		{
       
   135 		NThread& t = CheckedCurrentThread();
       
   136 		__NK_ASSERT_ALWAYS(t.iCsCount==0);
       
   137 		__NK_ASSERT_ALWAYS(t.iHeldFastMutex==0);
       
   138 		__NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked==0);
       
   139 		}
       
   140 	}
       
   141 
       
   142 void LeaveKernel();
       
   143 
       
   144 IMPORT_C TInt __fastcall Dispatch(TInt aFunction, TInt* aArgs);
   136 IMPORT_C TInt __fastcall Dispatch(TInt aFunction, TInt* aArgs);
   145 
   137 
   146 typedef TInt (__cdecl *TExecHandler)(TInt,TInt,TInt,TInt);
   138 typedef TInt (__cdecl* TExecHandler)(TInt, TInt, TInt, TInt);
   147 typedef void (__cdecl *TPreprocessHandler)(TInt*,TUint32);
   139 typedef void (__cdecl* TPreprocessHandler)(TInt*, TUint32);
   148 
   140 
   149 // Emulator nKern scheduling data
   141 // Emulator nKern scheduling data
   150 class Win32Interrupt
   142 class Win32Interrupt
   151 	{
   143 	{
   152 public:
   144 public:
   153 	void Init();
   145 	void Init();
   154 	TInt Mask();
   146 	void BeginInterrupt();
   155 	void Restore(TInt aLevel);
   147 	void EndInterrupt();
   156 	void Begin();
   148 	TInt MaskInterrupts(TBool aPreempt);
   157 	void End();
   149 	void RestoreInterruptMask(TInt aLevel);
       
   150 	void ForceReschedule();
       
   151 
   158 	inline TBool InInterrupt() const
   152 	inline TBool InInterrupt() const
   159 		{return iInterrupted!=0;}	
   153 		{
   160 	void ForceReschedule();
   154 		return iInterrupted != 0;
       
   155 		}
   161 	inline TBool InterruptsStatus(TBool aRequest) const
   156 	inline TBool InterruptsStatus(TBool aRequest) const
   162 	{return aRequest?(iLevel==0):(iLevel!=0);}
   157 		{
       
   158 		return aRequest ? (iLevel == 0) : (iLevel != 0);
       
   159 		}
       
   160 
   163 private:
   161 private:
   164 	static void Reschedule(TAny*);
   162 	static void SchedulerThreadFunction(TAny*);
       
   163 
   165 private:
   164 private:
   166 	TInt iLock;
   165 	CRITICAL_SECTION iCS;			// protects data below
   167 	HANDLE iQ;
   166 	HANDLE iQ;						// semaphore to wait on
   168 	DWORD iOwner;
   167 
   169 	TInt iLevel;
   168 	DWORD iOwner;					// controller of the mask
       
   169 	TInt iLevel;					// owner's recursion count
       
   170 	TInt iWaiting;					// number of waiters
       
   171 
   170 	TBool iRescheduleOnExit;
   172 	TBool iRescheduleOnExit;
   171 	NThread* iInterrupted;
   173 	NThread* iInterrupted;			// the thread preempted by Begin()
   172 	NThread iScheduler;
   174 	NThread iScheduler;				// the dedicated scheduler thread
   173 	};
   175 	};
   174 
   176 
   175 extern TBool Win32AtomicSOAW;	// flag to indicate availability of SignalObjectAndWait() API
   177 extern TBool Win32AtomicSOAW;		// flag to indicate availability of SignalObjectAndWait() API
   176 extern TBool Win32TraceThreadId;
   178 extern TBool Win32TraceThreadId;
   177 extern TInt Win32SingleCpu;
   179 extern TInt Win32SingleCpu;
   178 extern Win32Interrupt Interrupt;
   180 extern Win32Interrupt Interrupt;
   179 
   181 
   180 // Emulator nKern exception data
   182 // Emulator nKern exception data
   182 extern TAny* Win32ExcDataAddress;
   184 extern TAny* Win32ExcDataAddress;
   183 extern TUint Win32ExcCode;
   185 extern TUint Win32ExcCode;
   184 
   186 
   185 void FastCounterInit();
   187 void FastCounterInit();
   186 
   188 
   187 #endif
   189 // Wrappers round Win32 thread control & synchronisation functions ...
       
   190 inline void CheckedSuspendThread(HANDLE aWinThread)
       
   191 	{
       
   192 	TInt suspLevel = (TInt)SuspendThread(aWinThread);
       
   193 	__NK_ASSERT_ALWAYS(suspLevel >= 0);
       
   194 	}
       
   195 
       
   196 inline void CheckedResumeThread(HANDLE aWinThread, BOOL once = EFalse)
       
   197 	{
       
   198 	TInt suspLevel = (TInt)ResumeThread(aWinThread);
       
   199 	__NK_ASSERT_ALWAYS(once ? suspLevel == 1 : suspLevel > 0);				// check thread was previously suspended
       
   200 	}
       
   201 
       
   202 inline void CheckedGetThreadContext(HANDLE aWinThread, CONTEXT* aContext)
       
   203 	{
       
   204 	DWORD r = GetThreadContext(aWinThread, aContext);
       
   205 	__NK_ASSERT_ALWAYS(r != 0);
       
   206 	}
       
   207 
       
   208 inline void CheckedSetThreadContext(HANDLE aWinThread, CONTEXT* aContext)
       
   209 	{
       
   210 	DWORD r = SetThreadContext(aWinThread, aContext);
       
   211 	__NK_ASSERT_ALWAYS(r != 0);
       
   212 	}
       
   213 
       
   214 inline void CheckedSetThreadPriority(HANDLE aWinThread, TInt aPriority)
       
   215 	{
       
   216 	DWORD r = SetThreadPriority(aWinThread, aPriority);
       
   217 	__NK_ASSERT_ALWAYS(r != 0);
       
   218 	}
       
   219 
       
   220 inline void CheckedWaitForSingleObject(HANDLE aWaitObject)
       
   221 	{
       
   222 	DWORD r = WaitForSingleObject(aWaitObject, INFINITE);
       
   223 	__NK_ASSERT_ALWAYS(r == WAIT_OBJECT_0);
       
   224 	}
       
   225 
       
   226 inline void CheckedSignalObjectAndWait(HANDLE aToWake, HANDLE aToWaitOn)
       
   227 	{
       
   228 	DWORD r = SignalObjectAndWait(aToWake, aToWaitOn, INFINITE, FALSE);
       
   229 	__NK_ASSERT_ALWAYS(r == WAIT_OBJECT_0);
       
   230 	}
       
   231 
       
   232 inline void CheckedSetEvent(HANDLE aWaitObject)
       
   233 	{
       
   234 	DWORD r = SetEvent(aWaitObject);
       
   235 	__NK_ASSERT_ALWAYS(r != 0);
       
   236 	}
       
   237 
       
   238 inline void CheckedReleaseSemaphore(HANDLE aSemaphore)
       
   239 	{
       
   240 	DWORD r = ReleaseSemaphore(aSemaphore, 1, NULL);
       
   241 	__NK_ASSERT_ALWAYS(r != 0);
       
   242 	}
       
   243 
       
   244 
       
   245 #endif	// __NK_WIN32_H__