source: trunk/src/kernel32/hmthread.cpp@ 9949

Last change on this file since 9949 was 9949, checked in by sandervl, 22 years ago

* empty log message *

File size: 16.1 KB
Line 
1/* $Id: hmthread.cpp,v 1.19 2003-03-27 15:27:37 sandervl Exp $ */
2
3/*
4 * Project Odin Software License can be found in LICENSE.TXT
5 *
6 * Win32 thread handle class
7 *
8 *
9 * TODO: Handle is not destroyed when thread terminates (or else GetExitCodeThread won't work)
10 * Create thread token during thread creation??
11 * Fix for WaitForSingleObject when thread is already terminated, but
12 * WaitForMultipleObjects can still fail!
13 * WaitForSingle/MultipleObjects needs to be rewritten! (not using
14 * Open32)
15 *
16 ************************************************************************************
17 * NOTE: If we ever decide to allocate our own stack, then we MUST use VirtualAlloc!!!!
18 * (alignment reasons)
19 ************************************************************************************
20 *
21 * Copyright 2000 Sander van Leeuwen (sandervl@xs4all.nl)
22 *
23 */
24#include <os2win.h>
25#include <stdlib.h>
26#include <string.h>
27#include <misc.h>
28#include <wprocess.h>
29
30#include <HandleManager.H>
31#include "HMThread.h"
32#include "oslibthread.h"
33
34#include <win\thread.h>
35#include "thread.h"
36#include "asmutil.h"
37#include "winexebase.h"
38
39#define DBG_LOCALLOG DBG_hmthread
40#include "dbglocal.h"
41
42
43typedef struct {
44 HANDLE hDupThread; //original thread handle if duplicated
45 DWORD dwState; //THREAD_ALIVE, THREAD_TERMINATED
46} OBJ_THREAD;
47
48#define GET_THREADHANDLE(hThread) (threadobj && threadobj->hDupThread) ? threadobj->hDupThread : hThread
49
50//******************************************************************************
51//******************************************************************************
52HANDLE HMDeviceThreadClass::CreateThread(PHMHANDLEDATA pHMHandleData,
53 LPSECURITY_ATTRIBUTES lpsa,
54 DWORD cbStack,
55 LPTHREAD_START_ROUTINE lpStartAddr,
56 LPVOID lpvThreadParm,
57 DWORD fdwCreate,
58 LPDWORD lpIDThread,
59 BOOL fFirstThread)
60{
61 Win32Thread *winthread;
62 DWORD threadid;
63 HANDLE hThread = pHMHandleData->hHMHandle;
64
65 if(lpIDThread == NULL) {
66 lpIDThread = &threadid;
67 }
68 pHMHandleData->dwInternalType = HMTYPE_THREAD;
69 OBJ_THREAD *threadobj = (OBJ_THREAD *)malloc(sizeof(OBJ_THREAD));
70 if(threadobj == 0) {
71 DebugInt3();
72 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
73 return(0);
74 }
75 threadobj->hDupThread = 0; //not a duplicate
76 threadobj->dwState = THREAD_ALIVE;
77 pHMHandleData->dwUserData = (DWORD)threadobj;
78
79 //SvL: This doesn't really create a thread, but only sets up the
80 // handle of thread 0
81 if(fFirstThread) {
82 pHMHandleData->hHMHandle = O32_GetCurrentThread(); //return Open32 handle of thread
83 return pHMHandleData->hHMHandle;
84 }
85 winthread = new Win32Thread(lpStartAddr, lpvThreadParm, fdwCreate, hThread);
86
87 if(winthread == 0) {
88 DebugInt3();
89 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
90 return(0);
91 }
92 // @@@PH Note: with debug code enabled, ODIN might request more stack space!
93 //SvL: Also need more stack in release build (RealPlayer 7 sometimes runs
94 // out of stack
95 if (cbStack > 0) {
96 cbStack <<= 1; // double stack
97 }
98 else {
99 cbStack = (WinExe) ? WinExe->getDefaultStackSize() : 0x100000; // per default 1MB stack per thread
100 }
101 dprintf(("Thread stack size 0x%x", cbStack));
102
103 //************************************************************************************
104 //NOTE: If we ever decide to allocate our own stack, then we MUST use VirtualAlloc!!!!
105 // (alignment reasons)
106 //************************************************************************************
107 pHMHandleData->hHMHandle = O32_CreateThread(lpsa, cbStack, winthread->GetOS2Callback(),
108 (LPVOID)winthread, fdwCreate, lpIDThread);
109
110 if(pHMHandleData->hHMHandle == 0) {
111 dprintf(("Thread creation failed!!"));
112 DebugInt3();
113 }
114
115 *lpIDThread = MAKE_THREADID(O32_GetCurrentProcessId(), *lpIDThread);
116
117 TEB *teb = GetTEBFromThreadHandle(hThread);
118 if(teb) {
119 //store thread id in TEB
120 teb->o.odin.threadId = *lpIDThread;
121 teb->o.odin.dwSuspend = (fdwCreate & CREATE_SUSPENDED) ? 1 : 0;
122 }
123 else DebugInt3();
124
125 dprintf(("CreateThread created %08x, id %x", pHMHandleData->hHMHandle, *lpIDThread));
126
127 return pHMHandleData->hHMHandle;
128}
129/*****************************************************************************
130 * Name : HMDeviceFileClass::DuplicateHandle
131 * Purpose :
132 * Parameters:
133 * various parameters as required
134 * Variables :
135 * Result :
136 * Remark : DUPLICATE_CLOSE_SOURCE flag handled in HMDuplicateHandle
137 *
138 * Status : partially implemented
139 *
140 * Author : SvL
141 *****************************************************************************/
142BOOL HMDeviceThreadClass::DuplicateHandle(HANDLE srchandle, PHMHANDLEDATA pHMHandleData,
143 HANDLE srcprocess,
144 PHMHANDLEDATA pHMSrcHandle,
145 HANDLE destprocess,
146 PHANDLE desthandle,
147 DWORD fdwAccess,
148 BOOL fInherit,
149 DWORD fdwOptions,
150 DWORD fdwOdinOptions)
151{
152 BOOL ret;
153 OBJ_THREAD *threadsrc = (OBJ_THREAD *)pHMSrcHandle->dwUserData;
154
155 dprintf(("KERNEL32:HMDeviceThreadClass::DuplicateHandle (%08x,%08x,%08x,%08x,%08x)",
156 pHMHandleData, srcprocess, pHMSrcHandle->hHMHandle, destprocess, desthandle));
157
158 if(destprocess != srcprocess)
159 {
160 dprintf(("ERROR: DuplicateHandle; different processes not supported!!"));
161 SetLastError(ERROR_INVALID_HANDLE); //??
162 return FALSE;
163 }
164 ret = O32_DuplicateHandle(srcprocess, pHMSrcHandle->hHMHandle, destprocess, desthandle, fdwAccess, fInherit, fdwOptions);
165
166 if(ret == TRUE) {
167 OBJ_THREAD *threaddest = (OBJ_THREAD *)malloc(sizeof(OBJ_THREAD));
168 if(threaddest == NULL) {
169 O32_CloseHandle(*desthandle);
170 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
171 return FALSE;
172 }
173 threaddest->hDupThread = 0;
174 threaddest->dwState = THREAD_ALIVE;
175 pHMHandleData->dwUserData = (DWORD)threaddest;
176
177 if(threadsrc) {
178 threaddest->hDupThread = (threadsrc->hDupThread) ? threadsrc->hDupThread : srchandle;
179 threaddest->dwState = threadsrc->dwState;
180 }
181
182 pHMHandleData->hHMHandle = *desthandle;
183 return TRUE;
184 }
185 else return FALSE;
186}
187//******************************************************************************
188//******************************************************************************
189DWORD HMDeviceThreadClass::SuspendThread(HANDLE hThread, PHMHANDLEDATA pHMHandleData)
190{
191 DWORD dwSuspend;
192 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
193
194 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread));
195 if(teb) {
196 teb->o.odin.dwSuspend++;
197 dprintf(("SuspendThread %08xh): count %d", pHMHandleData->hHMHandle, teb->o.odin.dwSuspend));
198 }
199 dwSuspend = O32_SuspendThread(pHMHandleData->hHMHandle);
200 if(dwSuspend == -1) {
201 teb->o.odin.dwSuspend--;
202 dprintf(("!ERROR!: SuspendThread FAILED"));
203 }
204 return dwSuspend;
205}
206//******************************************************************************
207//******************************************************************************
208DWORD HMDeviceThreadClass::ResumeThread(HANDLE hThread, PHMHANDLEDATA pHMHandleData)
209{
210 DWORD dwSuspend;
211 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
212
213 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread));
214 if(teb) {
215 teb->o.odin.dwSuspend--;
216 dprintf(("ResumeThread (%08xh) : count %d", pHMHandleData->hHMHandle, teb->o.odin.dwSuspend));
217 }
218 dwSuspend = O32_ResumeThread(pHMHandleData->hHMHandle);
219 if(dwSuspend == -1) {
220 teb->o.odin.dwSuspend++;
221 dprintf(("!ERROR!: ResumeThread FAILED"));
222 }
223 return dwSuspend;
224}
225//******************************************************************************
226//******************************************************************************
227INT HMDeviceThreadClass::GetThreadPriority(HANDLE hThread, PHMHANDLEDATA pHMHandleData)
228{
229 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
230
231 dprintf(("GetThreadPriority(%08xh)\n", pHMHandleData->hHMHandle));
232
233 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread));
234 if(teb == NULL) {
235 dprintf(("!WARNING!: TEB not found!!"));
236 SetLastError(ERROR_INVALID_HANDLE);
237 return THREAD_PRIORITY_ERROR_RETURN;
238 }
239 return teb->delta_priority;
240}
241//******************************************************************************
242//******************************************************************************
243BOOL HMDeviceThreadClass::SetThreadPriority(HANDLE hThread, PHMHANDLEDATA pHMHandleData, int priority)
244{
245 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
246
247 dprintf(("SetThreadPriority (%08xh,%08xh)", pHMHandleData->hHMHandle, priority));
248
249 TEB *teb = GetTEBFromThreadHandle(GET_THREADHANDLE(hThread));
250 if(teb == NULL) {
251 dprintf(("!WARNING!: TEB not found!!"));
252 SetLastError(ERROR_INVALID_HANDLE);
253 return FALSE;
254 }
255 DWORD ret = OSLibDosSetPriority(ODIN_TO_OS2_THREADID(teb->o.odin.threadId), priority);
256 if(ret == ERROR_SUCCESS) {
257 teb->delta_priority = priority;
258 return TRUE;
259 }
260 else {
261 dprintf(("DosSetPriority failed with rc %d", ret));
262 return FALSE;
263 }
264}
265//******************************************************************************
266//TODO: Implement this??
267//******************************************************************************
268BOOL HMDeviceThreadClass::GetThreadContext(HANDLE hThread, PHMHANDLEDATA pHMHandleData, PCONTEXT lpContext)
269{
270 dprintf(("GetThreadContext NOT IMPLEMENTED!! (TRUE)\n"));
271 memset(lpContext, 0, sizeof(CONTEXT));
272
273 /* make up some plausible values for segment registers */
274 lpContext->SegCs = getCS();
275 lpContext->SegDs = getDS();
276 lpContext->SegSs = getSS();
277 lpContext->SegEs = getES();
278 lpContext->SegGs = getGS();
279 lpContext->SegFs = GetFS();
280
281 return TRUE;
282}
283//******************************************************************************
284//TODO: Implement this??
285//******************************************************************************
286BOOL HMDeviceThreadClass::SetThreadContext(HANDLE hThread, PHMHANDLEDATA pHMHandleData, const CONTEXT *lpContext)
287{
288 dprintf(("SetThreadContext NOT IMPLEMENTED!!\n"));
289
290 return FALSE;
291}
292/*****************************************************************************
293 * Name : BOOL GetThreadTimes
294 * Purpose : The GetThreadTimes function obtains timing information about a specified thread.
295 * Parameters: HANDLE hThread specifies the thread of interest
296 * LPFILETIME lpCreationTime when the thread was created
297 * LPFILETIME lpExitTime when the thread exited
298 * LPFILETIME lpKernelTime time the thread has spent in kernel mode
299 * LPFILETIME lpUserTime time the thread has spent in user mode
300 * Variables :
301 * Result : TRUE / FALSE
302 * Remark :
303 * Status : UNTESTED STUB
304 *
305 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
306 *****************************************************************************/
307
308BOOL HMDeviceThreadClass::GetThreadTimes(HANDLE hThread,
309 PHMHANDLEDATA pHMHandleData,
310 LPFILETIME lpCreationTime,
311 LPFILETIME lpExitTime,
312 LPFILETIME lpKernelTime,
313 LPFILETIME lpUserTime)
314{
315 dprintf(("Kernel32: GetThreadTimes(%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n",
316 hThread,
317 lpCreationTime,
318 lpExitTime,
319 lpKernelTime,
320 lpUserTime));
321
322 return (FALSE);
323}
324//******************************************************************************
325//******************************************************************************
326BOOL HMDeviceThreadClass::TerminateThread(HANDLE hThread, PHMHANDLEDATA pHMHandleData, DWORD exitcode)
327{
328 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
329
330 dprintf(("TerminateThread (%08xh,%08xh)\n",
331 pHMHandleData->hHMHandle,
332 exitcode));
333
334 if(threadobj) {
335 threadobj->dwState = THREAD_TERMINATED;
336 }
337 else DebugInt3();
338 return O32_TerminateThread(pHMHandleData->hHMHandle, exitcode);
339}
340//******************************************************************************
341//******************************************************************************
342BOOL HMDeviceThreadClass::SetThreadTerminated(HANDLE hThread, PHMHANDLEDATA pHMHandleData)
343{
344 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
345
346 if(threadobj) {
347 threadobj->dwState = THREAD_TERMINATED;
348 }
349 else DebugInt3();
350
351 return TRUE;
352}
353//******************************************************************************
354//******************************************************************************
355BOOL HMDeviceThreadClass::GetExitCodeThread(HANDLE hThread, PHMHANDLEDATA pHMHandleData, LPDWORD lpExitCode)
356{
357 dprintf(("GetExitCodeThread (%08xh,%08xh)\n",
358 pHMHandleData->hHMHandle,
359 lpExitCode));
360
361#if 0
362 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
363
364 if(threadobj && threadobj->dwState == THREAD_ALIVE) {
365 lpExitCode == STILL_ALIVE;
366 return TRUE;
367 }
368 else DebugInt3();
369#endif
370 return O32_GetExitCodeThread(pHMHandleData->hHMHandle, lpExitCode);
371}
372//******************************************************************************
373//******************************************************************************
374BOOL HMDeviceThreadClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
375{
376 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
377
378 dprintf(("HMThread::CloseHandle %08x", pHMHandleData->hHMHandle));
379
380 if(threadobj) {
381 pHMHandleData->dwUserData = 0;
382 free(threadobj);
383 }
384 return O32_CloseHandle(pHMHandleData->hHMHandle);
385}
386//******************************************************************************
387//******************************************************************************
388DWORD HMDeviceThreadClass::WaitForSingleObject(PHMHANDLEDATA pHMHandleData,
389 DWORD dwTimeout)
390{
391 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
392
393 dprintf(("HMThread::WaitForSingleObject (%08xh,%08xh)\n",
394 pHMHandleData->hHMHandle,
395 dwTimeout));
396
397 //This doesn't work very well in Open32 (object's state never signaled)
398 if(threadobj && threadobj->dwState == THREAD_TERMINATED) {
399 return WAIT_OBJECT_0;
400 }
401 return HMDeviceOpen32Class::WaitForSingleObject(pHMHandleData, dwTimeout);
402}
403//******************************************************************************
404//******************************************************************************
405DWORD HMDeviceThreadClass::WaitForSingleObjectEx(PHMHANDLEDATA pHMHandleData,
406 DWORD dwTimeout,
407 BOOL fAlertable)
408{
409 OBJ_THREAD *threadobj = (OBJ_THREAD *)pHMHandleData->dwUserData;
410
411 //This doesn't work very well in Open32 (object's state never signaled)
412 if(threadobj && threadobj->dwState == THREAD_TERMINATED) {
413 return WAIT_OBJECT_0;
414 }
415 return HMDeviceOpen32Class::WaitForSingleObjectEx(pHMHandleData, dwTimeout, fAlertable);
416}
417//******************************************************************************
418//******************************************************************************
Note: See TracBrowser for help on using the repository browser.