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__ |