push 9eb9af089d68d39110a91889d3a673043db63c4b
[wine/hacks.git] / dlls / kernel32 / tests / thread.c
blobb3580a182bee950d116b3c7a66f0ec08be915894
1 /*
2 * Unit test suite for directory functions.
4 * Copyright 2002 Geoffrey Hausheer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 /* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
22 #define _WIN32_WINNT 0x0500
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "wine/test.h"
29 #include <windef.h>
30 #include <winbase.h>
31 #include <winnt.h>
32 #include <winerror.h>
34 /* Specify the number of simultaneous threads to test */
35 #define NUM_THREADS 4
36 /* Specify whether to test the extended priorities for Win2k/XP */
37 #define USE_EXTENDED_PRIORITIES 0
38 /* Specify whether to test the stack allocation in CreateThread */
39 #define CHECK_STACK 0
41 /* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
42 CreateThread. So far I have been unable to make this work, and
43 I am in doubt as to how portable it is. Also, according to MSDN,
44 you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
45 Anyhow, the check is currently commented out
47 #if CHECK_STACK
48 # ifdef __try
49 # define __TRY __try
50 # define __EXCEPT __except
51 # define __ENDTRY
52 # else
53 # include "wine/exception.h"
54 # endif
55 #endif
57 typedef BOOL (WINAPI *GetThreadPriorityBoost_t)(HANDLE,PBOOL);
58 static GetThreadPriorityBoost_t pGetThreadPriorityBoost=NULL;
60 typedef HANDLE (WINAPI *OpenThread_t)(DWORD,BOOL,DWORD);
61 static OpenThread_t pOpenThread=NULL;
63 typedef BOOL (WINAPI *QueueUserWorkItem_t)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
64 static QueueUserWorkItem_t pQueueUserWorkItem=NULL;
66 typedef DWORD (WINAPI *SetThreadIdealProcessor_t)(HANDLE,DWORD);
67 static SetThreadIdealProcessor_t pSetThreadIdealProcessor=NULL;
69 typedef BOOL (WINAPI *SetThreadPriorityBoost_t)(HANDLE,BOOL);
70 static SetThreadPriorityBoost_t pSetThreadPriorityBoost=NULL;
72 typedef BOOL (WINAPI *RegisterWaitForSingleObject_t)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
73 static RegisterWaitForSingleObject_t pRegisterWaitForSingleObject=NULL;
75 typedef BOOL (WINAPI *UnregisterWait_t)(HANDLE);
76 static UnregisterWait_t pUnregisterWait=NULL;
78 static HANDLE create_target_process(const char *arg)
80 char **argv;
81 char cmdline[MAX_PATH];
82 PROCESS_INFORMATION pi;
83 STARTUPINFO si = { 0 };
84 si.cb = sizeof(si);
86 winetest_get_mainargs( &argv );
87 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
88 ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
89 &si, &pi) != 0, "error: %u\n", GetLastError());
90 ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
91 return pi.hProcess;
94 /* Functions not tested yet:
95 AttachThreadInput
96 SetThreadContext
97 SwitchToThread
99 In addition there are no checks that the inheritance works properly in
100 CreateThread
103 /* Functions to ensure that from a group of threads, only one executes
104 certain chunks of code at a time, and we know which one is executing
105 it. It basically makes multithreaded execution linear, which defeats
106 the purpose of multiple threads, but makes testing easy. */
107 static HANDLE start_event, stop_event;
108 static LONG num_synced;
110 static void init_thread_sync_helpers(void)
112 start_event = CreateEvent(NULL, TRUE, FALSE, NULL);
113 ok(start_event != NULL, "CreateEvent failed\n");
114 stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
115 ok(stop_event != NULL, "CreateEvent failed\n");
116 num_synced = -1;
119 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
121 LONG num = InterlockedIncrement(&num_synced);
122 assert(-1 <= num && num <= 1);
123 if (num == 1)
125 ResetEvent( stop_event );
126 SetEvent( start_event );
128 else
130 DWORD ret = WaitForSingleObject(start_event, 10000);
131 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
133 return sync_id == my_id;
136 static void resync_after_run(void)
138 LONG num = InterlockedDecrement(&num_synced);
139 assert(-1 <= num && num <= 1);
140 if (num == -1)
142 ResetEvent( start_event );
143 SetEvent( stop_event );
145 else
147 DWORD ret = WaitForSingleObject(stop_event, 10000);
148 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
152 static void cleanup_thread_sync_helpers(void)
154 CloseHandle(start_event);
155 CloseHandle(stop_event);
158 DWORD tlsIndex;
160 typedef struct {
161 int threadnum;
162 HANDLE *event;
163 DWORD *threadmem;
164 } t1Struct;
166 /* WinME supports OpenThread but doesn't know about access restrictions so
167 we require them to be either completely ignored or always obeyed.
169 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
170 #define obey_ar(x) \
171 (obeying_ars == 0 \
172 ? ((x) \
173 ? (obeying_ars = +1) \
174 : ((obeying_ars = -1), \
175 trace("not restricted, assuming consistent behaviour\n"))) \
176 : (obeying_ars < 0) \
177 ? ok(!(x), "access restrictions obeyed\n") \
178 : ok( (x), "access restrictions not obeyed\n"))
180 /* Basic test that simultaneous threads can access shared memory,
181 that the thread local storage routines work correctly, and that
182 threads actually run concurrently
184 static DWORD WINAPI threadFunc1(LPVOID p)
186 t1Struct *tstruct = (t1Struct *)p;
187 int i;
188 /* write our thread # into shared memory */
189 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
190 ok(TlsSetValue(tlsIndex,(LPVOID)(tstruct->threadnum+1))!=0,
191 "TlsSetValue failed\n");
192 /* The threads synchronize before terminating. This is done by
193 Signaling an event, and waiting for all events to occur
195 SetEvent(tstruct->event[tstruct->threadnum]);
196 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
197 /* Double check that all threads really did run by validating that
198 they have all written to the shared memory. There should be no race
199 here, since all threads were synchronized after the write.*/
200 for(i=0;i<NUM_THREADS;i++) {
201 while(tstruct->threadmem[i]==0) ;
204 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
205 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
207 /* Check that no one changed our tls memory */
208 ok((int)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
209 "TlsGetValue failed\n");
210 return NUM_THREADS+tstruct->threadnum;
213 static DWORD WINAPI threadFunc2(LPVOID p)
215 return 99;
218 static DWORD WINAPI threadFunc3(LPVOID p)
220 HANDLE thread;
221 thread=GetCurrentThread();
222 SuspendThread(thread);
223 return 99;
226 static DWORD WINAPI threadFunc4(LPVOID p)
228 HANDLE event = (HANDLE)p;
229 if(event != NULL) {
230 SetEvent(event);
232 Sleep(99000);
233 return 0;
236 #if CHECK_STACK
237 static DWORD WINAPI threadFunc5(LPVOID p)
239 DWORD *exitCode = (DWORD *)p;
240 SYSTEM_INFO sysInfo;
241 sysInfo.dwPageSize=0;
242 GetSystemInfo(&sysInfo);
243 *exitCode=0;
244 __TRY
246 alloca(2*sysInfo.dwPageSize);
248 __EXCEPT(1) {
249 *exitCode=1;
251 __ENDTRY
252 return 0;
254 #endif
256 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
258 SetEvent((HANDLE) p);
259 return 0;
262 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
264 CloseHandle((HANDLE) p);
265 return 0;
268 static void create_function_addr_events(HANDLE events[2])
270 char buffer[256];
272 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
273 events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
275 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
276 events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
279 /* check CreateRemoteThread */
280 static VOID test_CreateRemoteThread(void)
282 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
283 DWORD tid, ret, exitcode;
284 HANDLE hAddrEvents[2];
286 hProcess = create_target_process("sleep");
287 ok(hProcess != NULL, "Can't start process\n");
289 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
290 * address as in the child process */
291 create_function_addr_events(hAddrEvents);
292 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
293 if (ret == WAIT_TIMEOUT)
295 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
296 return;
299 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
300 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
301 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
302 0, FALSE, DUPLICATE_SAME_ACCESS);
303 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
305 /* create suspended remote thread with entry point SetEvent() */
306 SetLastError(0xdeadbeef);
307 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
308 hRemoteEvent, CREATE_SUSPENDED, &tid);
309 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
311 skip("CreateRemoteThread is not implemented\n");
312 goto cleanup;
314 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
315 ok(tid != 0, "null tid\n");
316 ret = SuspendThread(hThread);
317 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
318 ret = ResumeThread(hThread);
319 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
321 /* thread still suspended, so wait times out */
322 ret = WaitForSingleObject(hEvent, 100);
323 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
325 ret = ResumeThread(hThread);
326 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
328 /* wait that doesn't time out */
329 ret = WaitForSingleObject(hEvent, 100);
330 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
332 /* wait for thread end */
333 ret = WaitForSingleObject(hThread, 100);
334 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
335 CloseHandle(hThread);
337 /* create and wait for remote thread with entry point CloseHandle() */
338 hThread = CreateRemoteThread(hProcess, NULL, 0,
339 threadFunc_CloseHandle,
340 hRemoteEvent, 0, &tid);
341 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
342 ret = WaitForSingleObject(hThread, 100);
343 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
344 CloseHandle(hThread);
346 /* create remote thread with entry point SetEvent() */
347 hThread = CreateRemoteThread(hProcess, NULL, 0,
348 threadFunc_SetEvent,
349 hRemoteEvent, 0, &tid);
350 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
352 /* closed handle, so wait times out */
353 ret = WaitForSingleObject(hEvent, 100);
354 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
356 /* check that remote SetEvent() failed */
357 ret = GetExitCodeThread(hThread, &exitcode);
358 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
359 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
360 CloseHandle(hThread);
362 cleanup:
363 TerminateProcess(hProcess, 0);
364 CloseHandle(hEvent);
365 CloseHandle(hProcess);
368 /* Check basic functionality of CreateThread and Tls* functions */
369 static VOID test_CreateThread_basic(void)
371 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
372 DWORD threadid[NUM_THREADS],curthreadId;
373 DWORD threadmem[NUM_THREADS];
374 DWORD exitCode;
375 t1Struct tstruct[NUM_THREADS];
376 int error;
377 DWORD i,j;
378 DWORD GLE, ret;
379 DWORD tid;
381 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
382 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
384 /* Retrieve current Thread ID for later comparisons */
385 curthreadId=GetCurrentThreadId();
386 /* Allocate some local storage */
387 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
388 /* Create events for thread synchronization */
389 for(i=0;i<NUM_THREADS;i++) {
390 threadmem[i]=0;
391 /* Note that it doesn't matter what type of event we choose here. This
392 test isn't trying to thoroughly test events
394 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
395 tstruct[i].threadnum=i;
396 tstruct[i].threadmem=threadmem;
397 tstruct[i].event=event;
400 /* Test that passing arguments to threads works okay */
401 for(i=0;i<NUM_THREADS;i++) {
402 thread[i] = CreateThread(NULL,0,threadFunc1,
403 &tstruct[i],0,&threadid[i]);
404 ok(thread[i]!=NULL,"Create Thread failed\n");
406 /* Test that the threads actually complete */
407 for(i=0;i<NUM_THREADS;i++) {
408 error=WaitForSingleObject(thread[i],5000);
409 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
410 if(error!=WAIT_OBJECT_0) {
411 TerminateThread(thread[i],i+NUM_THREADS);
413 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
414 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
416 /* Test that each thread executed in its parent's address space
417 (it was able to change threadmem and pass that change back to its parent)
418 and that each thread id was independent). Note that we prove that the
419 threads actually execute concurrently by having them block on each other
420 in threadFunc1
422 for(i=0;i<NUM_THREADS;i++) {
423 error=0;
424 for(j=i+1;j<NUM_THREADS;j++) {
425 if (threadmem[i]==threadmem[j]) {
426 error=1;
429 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
430 "Thread did not execute successfully\n");
431 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
433 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
435 /* Test how passing NULL as a pointer to threadid works */
436 SetLastError(0xFACEaBAD);
437 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
438 GLE = GetLastError();
439 if (thread[0]) { /* NT */
440 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
441 ret = WaitForSingleObject(thread[0],100);
442 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
443 ret = GetExitCodeThread(thread[0],&exitCode);
444 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
445 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
446 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
448 else { /* 9x */
449 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
453 /* Check that using the CREATE_SUSPENDED flag works */
454 static VOID test_CreateThread_suspended(void)
456 HANDLE thread;
457 DWORD threadId;
458 DWORD suspend_count;
459 int error;
461 thread = CreateThread(NULL,0,threadFunc2,NULL,
462 CREATE_SUSPENDED,&threadId);
463 ok(thread!=NULL,"Create Thread failed\n");
464 /* Check that the thread is suspended */
465 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
466 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
467 /* Check that resume thread didn't actually start the thread. I can't think
468 of a better way of checking this than just waiting. I am not sure if this
469 will work on slow computers.
471 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
472 "ResumeThread should not have actually started the thread\n");
473 /* Now actually resume the thread and make sure that it actually completes*/
474 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
475 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
476 "Thread did not resume\n");
477 if(error!=WAIT_OBJECT_0) {
478 TerminateThread(thread,1);
481 suspend_count = SuspendThread(thread);
482 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
484 suspend_count = ResumeThread(thread);
485 ok(suspend_count == 0 ||
486 broken(suspend_count == -1), /* win9x */
487 "ResumeThread returned %d, expected 0\n", suspend_count);
489 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
492 /* Check that SuspendThread and ResumeThread work */
493 static VOID test_SuspendThread(void)
495 HANDLE thread,access_thread;
496 DWORD threadId,exitCode,error;
497 int i;
499 thread = CreateThread(NULL,0,threadFunc3,NULL,
500 0,&threadId);
501 ok(thread!=NULL,"Create Thread failed\n");
502 /* Check that the thread is suspended */
503 /* Note that this is a polling method, and there is a race between
504 SuspendThread being called (in the child, and the loop below timing out,
505 so the test could fail on a heavily loaded or slow computer.
507 error=0;
508 for(i=0;error==0 && i<100;i++) {
509 error=SuspendThread(thread);
510 ResumeThread(thread);
511 if(error==0) {
512 Sleep(50);
513 i++;
516 ok(error==1,"SuspendThread did not work\n");
517 /* check that access restrictions are obeyed */
518 if (pOpenThread) {
519 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
520 0,threadId);
521 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
522 if (access_thread!=NULL) {
523 obey_ar(SuspendThread(access_thread)==~0U);
524 obey_ar(ResumeThread(access_thread)==~0U);
525 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
528 /* Double check that the thread really is suspended */
529 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
530 "Thread did not really suspend\n");
531 /* Resume the thread, and make sure it actually completes */
532 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
533 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
534 "Thread did not resume\n");
535 if(error!=WAIT_OBJECT_0) {
536 TerminateThread(thread,1);
538 /* Trying to suspend a terminated thread should fail */
539 error=SuspendThread(thread);
540 ok(error==~0U, "wrong return code: %d\n", error);
541 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
543 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
546 /* Check that TerminateThread works properly
548 static VOID test_TerminateThread(void)
550 HANDLE thread,access_thread,event;
551 DWORD threadId,exitCode;
552 event=CreateEventA(NULL,TRUE,FALSE,NULL);
553 thread = CreateThread(NULL,0,threadFunc4,
554 (LPVOID)event, 0,&threadId);
555 ok(thread!=NULL,"Create Thread failed\n");
556 /* TerminateThread has a race condition in Wine. If the thread is terminated
557 before it starts, it leaves a process behind. Therefore, we wait for the
558 thread to signal that it has started. There is no easy way to force the
559 race to occur, so we don't try to find it.
561 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
562 "TerminateThread didn't work\n");
563 /* check that access restrictions are obeyed */
564 if (pOpenThread) {
565 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
566 0,threadId);
567 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
568 if (access_thread!=NULL) {
569 obey_ar(TerminateThread(access_thread,99)==0);
570 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
573 /* terminate a job and make sure it terminates */
574 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
575 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
576 "TerminateThread didn't work\n");
577 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
578 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
579 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
580 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
583 /* Check if CreateThread obeys the specified stack size. This code does
584 not work properly, and is currently disabled
586 static VOID test_CreateThread_stack(void)
588 #if CHECK_STACK
589 /* The only way I know of to test the stack size is to use alloca
590 and __try/__except. However, this is probably not portable,
591 and I couldn't get it to work under Wine anyhow. However, here
592 is the code which should allow for testing that CreateThread
593 respects the stack-size limit
595 HANDLE thread;
596 DWORD threadId,exitCode;
598 SYSTEM_INFO sysInfo;
599 sysInfo.dwPageSize=0;
600 GetSystemInfo(&sysInfo);
601 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
602 thread = CreateThread(NULL,sysInfo.dwPageSize,
603 threadFunc5,&exitCode,
604 0,&threadId);
605 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
606 "TerminateThread didn't work\n");
607 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
608 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
609 #endif
612 /* Check whether setting/retrieving thread priorities works */
613 static VOID test_thread_priority(void)
615 HANDLE curthread,access_thread;
616 DWORD curthreadId,exitCode;
617 int min_priority=-2,max_priority=2;
618 BOOL disabled,rc;
619 int i;
621 curthread=GetCurrentThread();
622 curthreadId=GetCurrentThreadId();
623 /* Check thread priority */
624 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
625 is -2 to 2. However, even on a real Win2k system, using thread
626 priorities beyond the -2 to 2 range does not work. If you want to try
627 anyway, enable USE_EXTENDED_PRIORITIES
629 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
630 "GetThreadPriority Failed\n");
632 if (pOpenThread) {
633 /* check that access control is obeyed */
634 access_thread=pOpenThread(THREAD_ALL_ACCESS &
635 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
636 0,curthreadId);
637 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
638 if (access_thread!=NULL) {
639 obey_ar(SetThreadPriority(access_thread,1)==0);
640 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
641 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
642 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
645 #if USE_EXTENDED_PRIORITIES
646 min_priority=-7; max_priority=6;
647 #endif
648 for(i=min_priority;i<=max_priority;i++) {
649 ok(SetThreadPriority(curthread,i)!=0,
650 "SetThreadPriority Failed for priority: %d\n",i);
651 ok(GetThreadPriority(curthread)==i,
652 "GetThreadPriority Failed for priority: %d\n",i);
654 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
655 "SetThreadPriority Failed\n");
656 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
657 "GetThreadPriority Failed\n");
658 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
659 "SetThreadPriority Failed\n");
660 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
661 "GetThreadPriority Failed\n");
662 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
664 /* Check that the thread priority is not changed if SetThreadPriority
665 is called with a value outside of the max/min range */
666 SetThreadPriority(curthread,min_priority);
667 SetLastError(0xdeadbeef);
668 rc = SetThreadPriority(curthread,min_priority-1);
670 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
671 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
672 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
673 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
674 GetLastError());
675 ok(GetThreadPriority(curthread)==min_priority,
676 "GetThreadPriority didn't return min_priority\n");
678 SetThreadPriority(curthread,max_priority);
679 SetLastError(0xdeadbeef);
680 rc = SetThreadPriority(curthread,max_priority+1);
682 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
683 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
684 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
685 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
686 GetLastError());
687 ok(GetThreadPriority(curthread)==max_priority,
688 "GetThreadPriority didn't return max_priority\n");
690 /* Check thread priority boost */
691 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
692 return; /* Win9x */
694 SetLastError(0xdeadbeef);
695 rc=pGetThreadPriorityBoost(curthread,&disabled);
696 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
697 return; /* WinME */
699 todo_wine
700 ok(rc!=0,"error=%d\n",GetLastError());
702 if (pOpenThread) {
703 /* check that access control is obeyed */
704 access_thread=pOpenThread(THREAD_ALL_ACCESS &
705 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
706 0,curthreadId);
707 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
708 if (access_thread!=NULL) {
709 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
710 obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
711 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
715 todo_wine {
716 rc = pSetThreadPriorityBoost(curthread,1);
717 ok( rc != 0, "error=%d\n",GetLastError());
718 rc=pGetThreadPriorityBoost(curthread,&disabled);
719 ok(rc!=0 && disabled==1,
720 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
722 rc = pSetThreadPriorityBoost(curthread,0);
723 ok( rc != 0, "error=%d\n",GetLastError());
724 rc=pGetThreadPriorityBoost(curthread,&disabled);
725 ok(rc!=0 && disabled==0,
726 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
730 /* check the GetThreadTimes function */
731 static VOID test_GetThreadTimes(void)
733 HANDLE thread,access_thread=NULL;
734 FILETIME creationTime,exitTime,kernelTime,userTime;
735 DWORD threadId;
736 int error;
738 thread = CreateThread(NULL,0,threadFunc2,NULL,
739 CREATE_SUSPENDED,&threadId);
741 ok(thread!=NULL,"Create Thread failed\n");
742 /* check that access control is obeyed */
743 if (pOpenThread) {
744 access_thread=pOpenThread(THREAD_ALL_ACCESS &
745 (~THREAD_QUERY_INFORMATION), 0,threadId);
746 ok(access_thread!=NULL,
747 "OpenThread returned an invalid handle\n");
749 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
750 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
751 "ResumeThread didn't work\n");
752 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
753 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
754 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
755 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
756 /* GetThreadTimes should set all of the parameters passed to it */
757 error=GetThreadTimes(thread,&creationTime,&exitTime,
758 &kernelTime,&userTime);
759 if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
760 ok(error!=0,"GetThreadTimes failed\n");
761 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
762 "creationTime was invalid\n");
763 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
764 "exitTime was invalid\n");
765 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
766 "kernelTimewas invalid\n");
767 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
768 "userTime was invalid\n");
769 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
770 if(access_thread!=NULL)
772 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
773 &kernelTime,&userTime);
774 obey_ar(error==0);
777 if(access_thread!=NULL) {
778 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
782 /* Check the processor affinity functions */
783 /* NOTE: These functions should also be checked that they obey access control
785 static VOID test_thread_processor(void)
787 HANDLE curthread,curproc;
788 DWORD_PTR processMask,systemMask;
789 SYSTEM_INFO sysInfo;
790 int error=0;
792 sysInfo.dwNumberOfProcessors=0;
793 GetSystemInfo(&sysInfo);
794 ok(sysInfo.dwNumberOfProcessors>0,
795 "GetSystemInfo failed to return a valid # of processors\n");
796 /* Use the current Thread/process for all tests */
797 curthread=GetCurrentThread();
798 ok(curthread!=NULL,"GetCurrentThread failed\n");
799 curproc=GetCurrentProcess();
800 ok(curproc!=NULL,"GetCurrentProcess failed\n");
801 /* Check the Affinity Mask functions */
802 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
803 "GetProcessAffinityMask failed\n");
804 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
805 "SetThreadAffinityMask failed\n");
806 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
807 "SetThreadAffinityMask passed for an illegal processor\n");
808 /* NOTE: This only works on WinNT/2000/XP) */
809 if (pSetThreadIdealProcessor) {
810 todo_wine {
811 SetLastError(0);
812 error=pSetThreadIdealProcessor(curthread,0);
813 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
814 ok(error!=-1, "SetThreadIdealProcessor failed\n");
817 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
818 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
819 ok(error==-1,
820 "SetThreadIdealProcessor succeeded with an illegal processor #\n");
821 todo_wine {
822 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
823 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
829 static VOID test_GetThreadExitCode(void)
831 DWORD exitCode, threadid;
832 DWORD GLE, ret;
833 HANDLE thread;
835 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
836 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
837 GLE = GetLastError();
838 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
840 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
841 ret = WaitForSingleObject(thread,100);
842 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
843 ret = GetExitCodeThread(thread,&exitCode);
844 ok(ret==exitCode || ret==1,
845 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
846 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
847 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
850 #ifdef __i386__
852 static int test_value = 0;
853 static HANDLE event;
855 static void WINAPI set_test_val( int val )
857 test_value += val;
860 static DWORD WINAPI threadFunc6(LPVOID p)
862 SetEvent( event );
863 Sleep( 1000 );
864 test_value *= (int)p;
865 return 0;
868 static void test_SetThreadContext(void)
870 CONTEXT ctx;
871 int *stack;
872 HANDLE thread;
873 DWORD threadid;
874 DWORD prevcount;
875 BOOL ret;
877 SetLastError(0xdeadbeef);
878 event = CreateEvent( NULL, TRUE, FALSE, NULL );
879 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
880 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
881 if (!thread)
883 trace("Thread creation failed, skipping rest of test\n");
884 return;
886 WaitForSingleObject( event, INFINITE );
887 SuspendThread( thread );
888 CloseHandle( event );
890 ctx.ContextFlags = CONTEXT_FULL;
891 SetLastError(0xdeadbeef);
892 ret = GetThreadContext( thread, &ctx );
893 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
895 if (ret)
897 /* simulate a call to set_test_val(10) */
898 stack = (int *)ctx.Esp;
899 stack[-1] = 10;
900 stack[-2] = ctx.Eip;
901 ctx.Esp -= 2 * sizeof(int *);
902 ctx.Eip = (DWORD)set_test_val;
903 SetLastError(0xdeadbeef);
904 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
907 SetLastError(0xdeadbeef);
908 prevcount = ResumeThread( thread );
909 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
910 prevcount, GetLastError() );
912 WaitForSingleObject( thread, INFINITE );
913 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
916 #endif /* __i386__ */
918 static HANDLE finish_event;
919 static LONG times_executed;
921 static DWORD CALLBACK work_function(void *p)
923 LONG executed = InterlockedIncrement(&times_executed);
925 if (executed == 100)
926 SetEvent(finish_event);
927 return 0;
930 static void test_QueueUserWorkItem(void)
932 int i;
933 DWORD wait_result;
934 DWORD before, after;
936 /* QueueUserWorkItem not present on win9x */
937 if (!pQueueUserWorkItem) return;
939 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
941 before = GetTickCount();
943 for (i = 0; i < 100; i++)
945 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
946 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
949 wait_result = WaitForSingleObject(finish_event, 10000);
951 after = GetTickCount();
952 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
953 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
955 ok(times_executed == 100, "didn't execute all of the work items\n");
958 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
960 HANDLE event = p;
961 SetEvent(event);
962 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
965 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
967 HANDLE event = p;
968 SetEvent(event);
969 ok(TimerOrWaitFired, "wait should have timed out\n");
972 static void test_RegisterWaitForSingleObject(void)
974 BOOL ret;
975 HANDLE wait_handle;
976 HANDLE handle;
977 HANDLE complete_event;
979 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
981 skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
982 return;
985 /* test signaled case */
987 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
988 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
990 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
991 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
993 WaitForSingleObject(complete_event, INFINITE);
994 /* give worker thread chance to complete */
995 Sleep(100);
997 ret = pUnregisterWait(wait_handle);
998 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1000 /* test cancel case */
1002 ResetEvent(handle);
1004 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1005 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1007 ret = pUnregisterWait(wait_handle);
1008 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1010 /* test timeout case */
1012 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1013 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1015 WaitForSingleObject(complete_event, INFINITE);
1016 /* give worker thread chance to complete */
1017 Sleep(100);
1019 ret = pUnregisterWait(wait_handle);
1020 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1023 static DWORD TLS_main;
1024 static DWORD TLS_index0, TLS_index1;
1026 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1028 /* We should NOT inherit the TLS values from our parent or from the
1029 main thread. */
1030 LPVOID val;
1032 val = TlsGetValue(TLS_main);
1033 ok(val == NULL, "TLS inheritance failed\n");
1035 val = TlsGetValue(TLS_index0);
1036 ok(val == NULL, "TLS inheritance failed\n");
1038 val = TlsGetValue(TLS_index1);
1039 ok(val == NULL, "TLS inheritance failed\n");
1041 return 0;
1044 /* Basic TLS usage test. Make sure we can create slots and the values we
1045 store in them are separate among threads. Also test TLS value
1046 inheritance with TLS_InheritanceProc. */
1047 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1049 LONG id = (LONG) p;
1050 LPVOID val;
1051 BOOL ret;
1053 if (sync_threads_and_run_one(0, id))
1055 TLS_index0 = TlsAlloc();
1056 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1058 resync_after_run();
1060 if (sync_threads_and_run_one(1, id))
1062 TLS_index1 = TlsAlloc();
1063 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1065 /* Slot indices should be different even if created in different
1066 threads. */
1067 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1069 /* Both slots should be initialized to NULL */
1070 val = TlsGetValue(TLS_index0);
1071 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1072 ok(val == NULL, "TLS slot not initialized correctly\n");
1074 val = TlsGetValue(TLS_index1);
1075 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1076 ok(val == NULL, "TLS slot not initialized correctly\n");
1078 resync_after_run();
1080 if (sync_threads_and_run_one(0, id))
1082 val = TlsGetValue(TLS_index0);
1083 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1084 ok(val == NULL, "TLS slot not initialized correctly\n");
1086 val = TlsGetValue(TLS_index1);
1087 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1088 ok(val == NULL, "TLS slot not initialized correctly\n");
1090 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1091 ok(ret, "TlsSetValue failed\n");
1093 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1094 ok(ret, "TlsSetValue failed\n");
1096 val = TlsGetValue(TLS_index0);
1097 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1098 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1100 val = TlsGetValue(TLS_index1);
1101 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1102 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1104 resync_after_run();
1106 if (sync_threads_and_run_one(1, id))
1108 val = TlsGetValue(TLS_index0);
1109 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1110 ok(val == NULL, "TLS slot not initialized correctly\n");
1112 val = TlsGetValue(TLS_index1);
1113 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1114 ok(val == NULL, "TLS slot not initialized correctly\n");
1116 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1117 ok(ret, "TlsSetValue failed\n");
1119 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1120 ok(ret, "TlsSetValue failed\n");
1122 val = TlsGetValue(TLS_index0);
1123 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1124 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1126 val = TlsGetValue(TLS_index1);
1127 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1128 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1130 resync_after_run();
1132 if (sync_threads_and_run_one(0, id))
1134 HANDLE thread;
1135 DWORD waitret, tid;
1137 val = TlsGetValue(TLS_index0);
1138 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1139 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1141 val = TlsGetValue(TLS_index1);
1142 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1143 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1145 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1146 ok(thread != NULL, "CreateThread failed\n");
1147 waitret = WaitForSingleObject(thread, 60000);
1148 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1149 CloseHandle(thread);
1151 ret = TlsFree(TLS_index0);
1152 ok(ret, "TlsFree failed\n");
1154 resync_after_run();
1156 if (sync_threads_and_run_one(1, id))
1158 ret = TlsFree(TLS_index1);
1159 ok(ret, "TlsFree failed\n");
1161 resync_after_run();
1163 return 0;
1166 static void test_TLS(void)
1168 HANDLE threads[2];
1169 LONG i;
1170 DWORD ret;
1171 BOOL suc;
1173 init_thread_sync_helpers();
1175 /* Allocate a TLS slot in the main thread to test for inheritance. */
1176 TLS_main = TlsAlloc();
1177 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1178 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1179 ok(suc, "TlsSetValue failed\n");
1181 for (i = 0; i < 2; ++i)
1183 DWORD tid;
1185 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1186 ok(threads[i] != NULL, "CreateThread failed\n");
1189 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1190 ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
1192 for (i = 0; i < 2; ++i)
1193 CloseHandle(threads[i]);
1195 suc = TlsFree(TLS_main);
1196 ok(suc, "TlsFree failed\n");
1197 cleanup_thread_sync_helpers();
1200 START_TEST(thread)
1202 HINSTANCE lib;
1203 int argc;
1204 char **argv;
1205 argc = winetest_get_mainargs( &argv );
1206 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1207 so that the compile passes
1209 lib=GetModuleHandleA("kernel32.dll");
1210 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1211 pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
1212 pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
1213 pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem");
1214 pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
1215 pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
1216 pRegisterWaitForSingleObject=(RegisterWaitForSingleObject_t)GetProcAddress(lib,"RegisterWaitForSingleObject");
1217 pUnregisterWait=(UnregisterWait_t)GetProcAddress(lib,"UnregisterWait");
1219 if (argc >= 3)
1221 if (!strcmp(argv[2], "sleep"))
1223 HANDLE hAddrEvents[2];
1224 create_function_addr_events(hAddrEvents);
1225 SetEvent(hAddrEvents[0]);
1226 SetEvent(hAddrEvents[1]);
1227 Sleep(5000); /* spawned process runs for at most 5 seconds */
1228 return;
1230 while (1)
1232 HANDLE hThread;
1233 DWORD tid;
1234 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1235 ok(hThread != NULL, "CreateThread failed, error %u\n",
1236 GetLastError());
1237 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1238 "Thread did not exit in time\n");
1239 if (hThread == NULL) break;
1240 CloseHandle(hThread);
1242 return;
1245 test_CreateRemoteThread();
1246 test_CreateThread_basic();
1247 test_CreateThread_suspended();
1248 test_SuspendThread();
1249 test_TerminateThread();
1250 test_CreateThread_stack();
1251 test_thread_priority();
1252 test_GetThreadTimes();
1253 test_thread_processor();
1254 test_GetThreadExitCode();
1255 #ifdef __i386__
1256 test_SetThreadContext();
1257 #endif
1258 test_QueueUserWorkItem();
1259 test_RegisterWaitForSingleObject();
1260 test_TLS();