push e8d2f3f1a5d20911a70f6477421a6c3dacf00760
[wine/hacks.git] / dlls / kernel32 / tests / thread.c
blobff9dad281007975c866950f333791f2207f7b666
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 all_synced;
108 static LONG num_syncing_threads, num_synced;
110 static void init_thread_sync_helpers(LONG num_threads)
112 all_synced = CreateEvent(NULL, FALSE, FALSE, NULL);
113 ok(all_synced != NULL, "CreateEvent failed\n");
114 num_syncing_threads = num_threads;
115 num_synced = 0;
118 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
120 LONG num = InterlockedIncrement(&num_synced);
121 assert(0 < num && num <= num_syncing_threads);
122 if (num == num_syncing_threads)
123 /* FIXME: MSDN claims PulseEvent is unreliable. For a test this isn't
124 so important, but we could use condition variables with more effort.
125 The given approach is clearer, though. */
126 PulseEvent(all_synced);
127 else
129 DWORD ret = WaitForSingleObject(all_synced, 60000);
130 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
132 return sync_id == my_id;
135 static void resync_after_run(void)
137 LONG num = InterlockedDecrement(&num_synced);
138 assert(0 <= num && num < num_syncing_threads);
139 if (num == 0)
140 PulseEvent(all_synced);
141 else
143 DWORD ret = WaitForSingleObject(all_synced, 60000);
144 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
148 static void cleanup_thread_sync_helpers(void)
150 CloseHandle(all_synced);
151 all_synced = NULL;
154 DWORD tlsIndex;
156 typedef struct {
157 int threadnum;
158 HANDLE *event;
159 DWORD *threadmem;
160 } t1Struct;
162 /* WinME supports OpenThread but doesn't know about access restrictions so
163 we require them to be either completely ignored or always obeyed.
165 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
166 #define obey_ar(x) \
167 (obeying_ars == 0 \
168 ? ((x) \
169 ? (obeying_ars = +1) \
170 : ((obeying_ars = -1), \
171 trace("not restricted, assuming consistent behaviour\n"))) \
172 : (obeying_ars < 0) \
173 ? ok(!(x), "access restrictions obeyed\n") \
174 : ok( (x), "access restrictions not obeyed\n"))
176 /* Basic test that simultaneous threads can access shared memory,
177 that the thread local storage routines work correctly, and that
178 threads actually run concurrently
180 static DWORD WINAPI threadFunc1(LPVOID p)
182 t1Struct *tstruct = (t1Struct *)p;
183 int i;
184 /* write our thread # into shared memory */
185 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
186 ok(TlsSetValue(tlsIndex,(LPVOID)(tstruct->threadnum+1))!=0,
187 "TlsSetValue failed\n");
188 /* The threads synchronize before terminating. This is done by
189 Signaling an event, and waiting for all events to occur
191 SetEvent(tstruct->event[tstruct->threadnum]);
192 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
193 /* Double check that all threads really did run by validating that
194 they have all written to the shared memory. There should be no race
195 here, since all threads were synchronized after the write.*/
196 for(i=0;i<NUM_THREADS;i++) {
197 while(tstruct->threadmem[i]==0) ;
200 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
201 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
203 /* Check that no one changed our tls memory */
204 ok((int)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
205 "TlsGetValue failed\n");
206 return NUM_THREADS+tstruct->threadnum;
209 static DWORD WINAPI threadFunc2(LPVOID p)
211 return 99;
214 static DWORD WINAPI threadFunc3(LPVOID p)
216 HANDLE thread;
217 thread=GetCurrentThread();
218 SuspendThread(thread);
219 return 99;
222 static DWORD WINAPI threadFunc4(LPVOID p)
224 HANDLE event = (HANDLE)p;
225 if(event != NULL) {
226 SetEvent(event);
228 Sleep(99000);
229 return 0;
232 #if CHECK_STACK
233 static DWORD WINAPI threadFunc5(LPVOID p)
235 DWORD *exitCode = (DWORD *)p;
236 SYSTEM_INFO sysInfo;
237 sysInfo.dwPageSize=0;
238 GetSystemInfo(&sysInfo);
239 *exitCode=0;
240 __TRY
242 alloca(2*sysInfo.dwPageSize);
244 __EXCEPT(1) {
245 *exitCode=1;
247 __ENDTRY
248 return 0;
250 #endif
252 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
254 SetEvent((HANDLE) p);
255 return 0;
258 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
260 CloseHandle((HANDLE) p);
261 return 0;
264 static void create_function_addr_events(HANDLE events[2])
266 char buffer[256];
268 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
269 events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
271 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
272 events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
275 /* check CreateRemoteThread */
276 static VOID test_CreateRemoteThread(void)
278 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
279 DWORD tid, ret, exitcode;
280 HANDLE hAddrEvents[2];
282 hProcess = create_target_process("sleep");
283 ok(hProcess != NULL, "Can't start process\n");
285 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
286 * address as in the child process */
287 create_function_addr_events(hAddrEvents);
288 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
289 if (ret == WAIT_TIMEOUT)
291 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
292 return;
295 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
296 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
297 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
298 0, FALSE, DUPLICATE_SAME_ACCESS);
299 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
301 /* create suspended remote thread with entry point SetEvent() */
302 SetLastError(0xdeadbeef);
303 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
304 hRemoteEvent, CREATE_SUSPENDED, &tid);
305 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
307 skip("CreateRemoteThread is not implemented\n");
308 goto cleanup;
310 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
311 ok(tid != 0, "null tid\n");
312 ret = SuspendThread(hThread);
313 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
314 ret = ResumeThread(hThread);
315 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
317 /* thread still suspended, so wait times out */
318 ret = WaitForSingleObject(hEvent, 100);
319 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
321 ret = ResumeThread(hThread);
322 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
324 /* wait that doesn't time out */
325 ret = WaitForSingleObject(hEvent, 100);
326 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
328 /* wait for thread end */
329 ret = WaitForSingleObject(hThread, 100);
330 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
331 CloseHandle(hThread);
333 /* create and wait for remote thread with entry point CloseHandle() */
334 hThread = CreateRemoteThread(hProcess, NULL, 0,
335 threadFunc_CloseHandle,
336 hRemoteEvent, 0, &tid);
337 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
338 ret = WaitForSingleObject(hThread, 100);
339 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
340 CloseHandle(hThread);
342 /* create remote thread with entry point SetEvent() */
343 hThread = CreateRemoteThread(hProcess, NULL, 0,
344 threadFunc_SetEvent,
345 hRemoteEvent, 0, &tid);
346 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
348 /* closed handle, so wait times out */
349 ret = WaitForSingleObject(hEvent, 100);
350 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
352 /* check that remote SetEvent() failed */
353 ret = GetExitCodeThread(hThread, &exitcode);
354 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
355 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
356 CloseHandle(hThread);
358 cleanup:
359 TerminateProcess(hProcess, 0);
360 CloseHandle(hEvent);
361 CloseHandle(hProcess);
364 /* Check basic functionality of CreateThread and Tls* functions */
365 static VOID test_CreateThread_basic(void)
367 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
368 DWORD threadid[NUM_THREADS],curthreadId;
369 DWORD threadmem[NUM_THREADS];
370 DWORD exitCode;
371 t1Struct tstruct[NUM_THREADS];
372 int error;
373 DWORD i,j;
374 DWORD GLE, ret;
375 DWORD tid;
377 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
378 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
380 /* Retrieve current Thread ID for later comparisons */
381 curthreadId=GetCurrentThreadId();
382 /* Allocate some local storage */
383 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
384 /* Create events for thread synchronization */
385 for(i=0;i<NUM_THREADS;i++) {
386 threadmem[i]=0;
387 /* Note that it doesn't matter what type of event we choose here. This
388 test isn't trying to thoroughly test events
390 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
391 tstruct[i].threadnum=i;
392 tstruct[i].threadmem=threadmem;
393 tstruct[i].event=event;
396 /* Test that passing arguments to threads works okay */
397 for(i=0;i<NUM_THREADS;i++) {
398 thread[i] = CreateThread(NULL,0,threadFunc1,
399 &tstruct[i],0,&threadid[i]);
400 ok(thread[i]!=NULL,"Create Thread failed\n");
402 /* Test that the threads actually complete */
403 for(i=0;i<NUM_THREADS;i++) {
404 error=WaitForSingleObject(thread[i],5000);
405 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
406 if(error!=WAIT_OBJECT_0) {
407 TerminateThread(thread[i],i+NUM_THREADS);
409 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
410 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
412 /* Test that each thread executed in its parent's address space
413 (it was able to change threadmem and pass that change back to its parent)
414 and that each thread id was independent). Note that we prove that the
415 threads actually execute concurrently by having them block on each other
416 in threadFunc1
418 for(i=0;i<NUM_THREADS;i++) {
419 error=0;
420 for(j=i+1;j<NUM_THREADS;j++) {
421 if (threadmem[i]==threadmem[j]) {
422 error=1;
425 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
426 "Thread did not execute successfully\n");
427 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
429 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
431 /* Test how passing NULL as a pointer to threadid works */
432 SetLastError(0xFACEaBAD);
433 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
434 GLE = GetLastError();
435 if (thread[0]) { /* NT */
436 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
437 ret = WaitForSingleObject(thread[0],100);
438 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
439 ret = GetExitCodeThread(thread[0],&exitCode);
440 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
441 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
442 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
444 else { /* 9x */
445 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
449 /* Check that using the CREATE_SUSPENDED flag works */
450 static VOID test_CreateThread_suspended(void)
452 HANDLE thread;
453 DWORD threadId;
454 DWORD suspend_count;
455 int error;
457 thread = CreateThread(NULL,0,threadFunc2,NULL,
458 CREATE_SUSPENDED,&threadId);
459 ok(thread!=NULL,"Create Thread failed\n");
460 /* Check that the thread is suspended */
461 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
462 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
463 /* Check that resume thread didn't actually start the thread. I can't think
464 of a better way of checking this than just waiting. I am not sure if this
465 will work on slow computers.
467 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
468 "ResumeThread should not have actually started the thread\n");
469 /* Now actually resume the thread and make sure that it actually completes*/
470 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
471 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
472 "Thread did not resume\n");
473 if(error!=WAIT_OBJECT_0) {
474 TerminateThread(thread,1);
477 suspend_count = SuspendThread(thread);
478 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
480 suspend_count = ResumeThread(thread);
481 ok(suspend_count == 0 ||
482 broken(suspend_count == -1), /* win9x */
483 "ResumeThread returned %d, expected 0\n", suspend_count);
485 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
488 /* Check that SuspendThread and ResumeThread work */
489 static VOID test_SuspendThread(void)
491 HANDLE thread,access_thread;
492 DWORD threadId,exitCode,error;
493 int i;
495 thread = CreateThread(NULL,0,threadFunc3,NULL,
496 0,&threadId);
497 ok(thread!=NULL,"Create Thread failed\n");
498 /* Check that the thread is suspended */
499 /* Note that this is a polling method, and there is a race between
500 SuspendThread being called (in the child, and the loop below timing out,
501 so the test could fail on a heavily loaded or slow computer.
503 error=0;
504 for(i=0;error==0 && i<100;i++) {
505 error=SuspendThread(thread);
506 ResumeThread(thread);
507 if(error==0) {
508 Sleep(50);
509 i++;
512 ok(error==1,"SuspendThread did not work\n");
513 /* check that access restrictions are obeyed */
514 if (pOpenThread) {
515 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
516 0,threadId);
517 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
518 if (access_thread!=NULL) {
519 obey_ar(SuspendThread(access_thread)==~0U);
520 obey_ar(ResumeThread(access_thread)==~0U);
521 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
524 /* Double check that the thread really is suspended */
525 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
526 "Thread did not really suspend\n");
527 /* Resume the thread, and make sure it actually completes */
528 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
529 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
530 "Thread did not resume\n");
531 if(error!=WAIT_OBJECT_0) {
532 TerminateThread(thread,1);
534 /* Trying to suspend a terminated thread should fail */
535 error=SuspendThread(thread);
536 ok(error==~0U, "wrong return code: %d\n", error);
537 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
539 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
542 /* Check that TerminateThread works properly
544 static VOID test_TerminateThread(void)
546 HANDLE thread,access_thread,event;
547 DWORD threadId,exitCode;
548 event=CreateEventA(NULL,TRUE,FALSE,NULL);
549 thread = CreateThread(NULL,0,threadFunc4,
550 (LPVOID)event, 0,&threadId);
551 ok(thread!=NULL,"Create Thread failed\n");
552 /* TerminateThread has a race condition in Wine. If the thread is terminated
553 before it starts, it leaves a process behind. Therefore, we wait for the
554 thread to signal that it has started. There is no easy way to force the
555 race to occur, so we don't try to find it.
557 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
558 "TerminateThread didn't work\n");
559 /* check that access restrictions are obeyed */
560 if (pOpenThread) {
561 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
562 0,threadId);
563 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
564 if (access_thread!=NULL) {
565 obey_ar(TerminateThread(access_thread,99)==0);
566 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
569 /* terminate a job and make sure it terminates */
570 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
571 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
572 "TerminateThread didn't work\n");
573 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
574 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
575 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
576 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
579 /* Check if CreateThread obeys the specified stack size. This code does
580 not work properly, and is currently disabled
582 static VOID test_CreateThread_stack(void)
584 #if CHECK_STACK
585 /* The only way I know of to test the stack size is to use alloca
586 and __try/__except. However, this is probably not portable,
587 and I couldn't get it to work under Wine anyhow. However, here
588 is the code which should allow for testing that CreateThread
589 respects the stack-size limit
591 HANDLE thread;
592 DWORD threadId,exitCode;
594 SYSTEM_INFO sysInfo;
595 sysInfo.dwPageSize=0;
596 GetSystemInfo(&sysInfo);
597 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
598 thread = CreateThread(NULL,sysInfo.dwPageSize,
599 threadFunc5,&exitCode,
600 0,&threadId);
601 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
602 "TerminateThread didn't work\n");
603 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
604 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
605 #endif
608 /* Check whether setting/retrieving thread priorities works */
609 static VOID test_thread_priority(void)
611 HANDLE curthread,access_thread;
612 DWORD curthreadId,exitCode;
613 int min_priority=-2,max_priority=2;
614 BOOL disabled,rc;
615 int i;
617 curthread=GetCurrentThread();
618 curthreadId=GetCurrentThreadId();
619 /* Check thread priority */
620 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
621 is -2 to 2. However, even on a real Win2k system, using thread
622 priorities beyond the -2 to 2 range does not work. If you want to try
623 anyway, enable USE_EXTENDED_PRIORITIES
625 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
626 "GetThreadPriority Failed\n");
628 if (pOpenThread) {
629 /* check that access control is obeyed */
630 access_thread=pOpenThread(THREAD_ALL_ACCESS &
631 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
632 0,curthreadId);
633 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
634 if (access_thread!=NULL) {
635 obey_ar(SetThreadPriority(access_thread,1)==0);
636 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
637 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
638 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
641 #if USE_EXTENDED_PRIORITIES
642 min_priority=-7; max_priority=6;
643 #endif
644 for(i=min_priority;i<=max_priority;i++) {
645 ok(SetThreadPriority(curthread,i)!=0,
646 "SetThreadPriority Failed for priority: %d\n",i);
647 ok(GetThreadPriority(curthread)==i,
648 "GetThreadPriority Failed for priority: %d\n",i);
650 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
651 "SetThreadPriority Failed\n");
652 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
653 "GetThreadPriority Failed\n");
654 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
655 "SetThreadPriority Failed\n");
656 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
657 "GetThreadPriority Failed\n");
658 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
660 /* Check that the thread priority is not changed if SetThreadPriority
661 is called with a value outside of the max/min range */
662 SetThreadPriority(curthread,min_priority);
663 SetLastError(0xdeadbeef);
664 rc = SetThreadPriority(curthread,min_priority-1);
666 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
667 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
668 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
669 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
670 GetLastError());
671 ok(GetThreadPriority(curthread)==min_priority,
672 "GetThreadPriority didn't return min_priority\n");
674 SetThreadPriority(curthread,max_priority);
675 SetLastError(0xdeadbeef);
676 rc = SetThreadPriority(curthread,max_priority+1);
678 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
679 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
680 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
681 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
682 GetLastError());
683 ok(GetThreadPriority(curthread)==max_priority,
684 "GetThreadPriority didn't return max_priority\n");
686 /* Check thread priority boost */
687 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
688 return; /* Win9x */
690 SetLastError(0xdeadbeef);
691 rc=pGetThreadPriorityBoost(curthread,&disabled);
692 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
693 return; /* WinME */
695 todo_wine
696 ok(rc!=0,"error=%d\n",GetLastError());
698 if (pOpenThread) {
699 /* check that access control is obeyed */
700 access_thread=pOpenThread(THREAD_ALL_ACCESS &
701 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
702 0,curthreadId);
703 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
704 if (access_thread!=NULL) {
705 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
706 obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
707 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
711 todo_wine {
712 rc = pSetThreadPriorityBoost(curthread,1);
713 ok( rc != 0, "error=%d\n",GetLastError());
714 rc=pGetThreadPriorityBoost(curthread,&disabled);
715 ok(rc!=0 && disabled==1,
716 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
718 rc = pSetThreadPriorityBoost(curthread,0);
719 ok( rc != 0, "error=%d\n",GetLastError());
720 rc=pGetThreadPriorityBoost(curthread,&disabled);
721 ok(rc!=0 && disabled==0,
722 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
726 /* check the GetThreadTimes function */
727 static VOID test_GetThreadTimes(void)
729 HANDLE thread,access_thread=NULL;
730 FILETIME creationTime,exitTime,kernelTime,userTime;
731 DWORD threadId;
732 int error;
734 thread = CreateThread(NULL,0,threadFunc2,NULL,
735 CREATE_SUSPENDED,&threadId);
737 ok(thread!=NULL,"Create Thread failed\n");
738 /* check that access control is obeyed */
739 if (pOpenThread) {
740 access_thread=pOpenThread(THREAD_ALL_ACCESS &
741 (~THREAD_QUERY_INFORMATION), 0,threadId);
742 ok(access_thread!=NULL,
743 "OpenThread returned an invalid handle\n");
745 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
746 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
747 "ResumeThread didn't work\n");
748 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
749 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
750 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
751 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
752 /* GetThreadTimes should set all of the parameters passed to it */
753 error=GetThreadTimes(thread,&creationTime,&exitTime,
754 &kernelTime,&userTime);
755 if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
756 ok(error!=0,"GetThreadTimes failed\n");
757 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
758 "creationTime was invalid\n");
759 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
760 "exitTime was invalid\n");
761 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
762 "kernelTimewas invalid\n");
763 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
764 "userTime was invalid\n");
765 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
766 if(access_thread!=NULL)
768 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
769 &kernelTime,&userTime);
770 obey_ar(error==0);
773 if(access_thread!=NULL) {
774 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
778 /* Check the processor affinity functions */
779 /* NOTE: These functions should also be checked that they obey access control
781 static VOID test_thread_processor(void)
783 HANDLE curthread,curproc;
784 DWORD_PTR processMask,systemMask;
785 SYSTEM_INFO sysInfo;
786 int error=0;
788 sysInfo.dwNumberOfProcessors=0;
789 GetSystemInfo(&sysInfo);
790 ok(sysInfo.dwNumberOfProcessors>0,
791 "GetSystemInfo failed to return a valid # of processors\n");
792 /* Use the current Thread/process for all tests */
793 curthread=GetCurrentThread();
794 ok(curthread!=NULL,"GetCurrentThread failed\n");
795 curproc=GetCurrentProcess();
796 ok(curproc!=NULL,"GetCurrentProcess failed\n");
797 /* Check the Affinity Mask functions */
798 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
799 "GetProcessAffinityMask failed\n");
800 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
801 "SetThreadAffinityMask failed\n");
802 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
803 "SetThreadAffinityMask passed for an illegal processor\n");
804 /* NOTE: This only works on WinNT/2000/XP) */
805 if (pSetThreadIdealProcessor) {
806 todo_wine {
807 SetLastError(0);
808 error=pSetThreadIdealProcessor(curthread,0);
809 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
810 ok(error!=-1, "SetThreadIdealProcessor failed\n");
813 if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
814 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
815 ok(error==-1,
816 "SetThreadIdealProcessor succeeded with an illegal processor #\n");
817 todo_wine {
818 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
819 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
825 static VOID test_GetThreadExitCode(void)
827 DWORD exitCode, threadid;
828 DWORD GLE, ret;
829 HANDLE thread;
831 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
832 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
833 GLE = GetLastError();
834 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
836 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
837 ret = WaitForSingleObject(thread,100);
838 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
839 ret = GetExitCodeThread(thread,&exitCode);
840 ok(ret==exitCode || ret==1,
841 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
842 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
843 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
846 #ifdef __i386__
848 static int test_value = 0;
849 static HANDLE event;
851 static void WINAPI set_test_val( int val )
853 test_value += val;
856 static DWORD WINAPI threadFunc6(LPVOID p)
858 SetEvent( event );
859 Sleep( 1000 );
860 test_value *= (int)p;
861 return 0;
864 static void test_SetThreadContext(void)
866 CONTEXT ctx;
867 int *stack;
868 HANDLE thread;
869 DWORD threadid;
870 DWORD prevcount;
871 BOOL ret;
873 SetLastError(0xdeadbeef);
874 event = CreateEvent( NULL, TRUE, FALSE, NULL );
875 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
876 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
877 if (!thread)
879 trace("Thread creation failed, skipping rest of test\n");
880 return;
882 WaitForSingleObject( event, INFINITE );
883 SuspendThread( thread );
884 CloseHandle( event );
886 ctx.ContextFlags = CONTEXT_FULL;
887 SetLastError(0xdeadbeef);
888 ret = GetThreadContext( thread, &ctx );
889 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
891 if (ret)
893 /* simulate a call to set_test_val(10) */
894 stack = (int *)ctx.Esp;
895 stack[-1] = 10;
896 stack[-2] = ctx.Eip;
897 ctx.Esp -= 2 * sizeof(int *);
898 ctx.Eip = (DWORD)set_test_val;
899 SetLastError(0xdeadbeef);
900 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
903 SetLastError(0xdeadbeef);
904 prevcount = ResumeThread( thread );
905 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
906 prevcount, GetLastError() );
908 WaitForSingleObject( thread, INFINITE );
909 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
912 #endif /* __i386__ */
914 static HANDLE finish_event;
915 static LONG times_executed;
917 static DWORD CALLBACK work_function(void *p)
919 LONG executed = InterlockedIncrement(&times_executed);
921 if (executed == 100)
922 SetEvent(finish_event);
923 return 0;
926 static void test_QueueUserWorkItem(void)
928 int i;
929 DWORD wait_result;
930 DWORD before, after;
932 /* QueueUserWorkItem not present on win9x */
933 if (!pQueueUserWorkItem) return;
935 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
937 before = GetTickCount();
939 for (i = 0; i < 100; i++)
941 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
942 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
945 wait_result = WaitForSingleObject(finish_event, 10000);
947 after = GetTickCount();
948 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
949 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
951 ok(times_executed == 100, "didn't execute all of the work items\n");
954 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
956 HANDLE event = p;
957 SetEvent(event);
958 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
961 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
963 HANDLE event = p;
964 SetEvent(event);
965 ok(TimerOrWaitFired, "wait should have timed out\n");
968 static void test_RegisterWaitForSingleObject(void)
970 BOOL ret;
971 HANDLE wait_handle;
972 HANDLE handle;
973 HANDLE complete_event;
975 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
977 skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
978 return;
981 /* test signaled case */
983 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
984 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
986 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
987 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
989 WaitForSingleObject(complete_event, INFINITE);
990 /* give worker thread chance to complete */
991 Sleep(100);
993 ret = pUnregisterWait(wait_handle);
994 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
996 /* test cancel case */
998 ResetEvent(handle);
1000 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1001 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1003 ret = pUnregisterWait(wait_handle);
1004 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1006 /* test timeout case */
1008 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1009 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1011 WaitForSingleObject(complete_event, INFINITE);
1012 /* give worker thread chance to complete */
1013 Sleep(100);
1015 ret = pUnregisterWait(wait_handle);
1016 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1019 static DWORD TLS_main;
1020 static DWORD TLS_index0, TLS_index1;
1022 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1024 /* We should NOT inherit the TLS values from our parent or from the
1025 main thread. */
1026 LPVOID val;
1028 val = TlsGetValue(TLS_main);
1029 ok(val == NULL, "TLS inheritance failed\n");
1031 val = TlsGetValue(TLS_index0);
1032 ok(val == NULL, "TLS inheritance failed\n");
1034 val = TlsGetValue(TLS_index1);
1035 ok(val == NULL, "TLS inheritance failed\n");
1037 return 0;
1040 /* Basic TLS usage test. Make sure we can create slots and the values we
1041 store in them are separate among threads. Also test TLS value
1042 inheritance with TLS_InheritanceProc. */
1043 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1045 LONG id = (LONG) p;
1046 LPVOID val;
1047 BOOL ret;
1049 if (sync_threads_and_run_one(0, id))
1051 TLS_index0 = TlsAlloc();
1052 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1054 resync_after_run();
1056 if (sync_threads_and_run_one(1, id))
1058 TLS_index1 = TlsAlloc();
1059 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1061 /* Slot indices should be different even if created in different
1062 threads. */
1063 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1065 /* Both slots should be initialized to NULL */
1066 val = TlsGetValue(TLS_index0);
1067 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1068 ok(val == NULL, "TLS slot not initialized correctly\n");
1070 val = TlsGetValue(TLS_index1);
1071 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1072 ok(val == NULL, "TLS slot not initialized correctly\n");
1074 resync_after_run();
1076 if (sync_threads_and_run_one(0, id))
1078 val = TlsGetValue(TLS_index0);
1079 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1080 ok(val == NULL, "TLS slot not initialized correctly\n");
1082 val = TlsGetValue(TLS_index1);
1083 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1084 ok(val == NULL, "TLS slot not initialized correctly\n");
1086 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1087 ok(ret, "TlsSetValue failed\n");
1089 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1090 ok(ret, "TlsSetValue failed\n");
1092 val = TlsGetValue(TLS_index0);
1093 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1094 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1096 val = TlsGetValue(TLS_index1);
1097 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1098 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1100 resync_after_run();
1102 if (sync_threads_and_run_one(1, id))
1104 val = TlsGetValue(TLS_index0);
1105 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1106 ok(val == NULL, "TLS slot not initialized correctly\n");
1108 val = TlsGetValue(TLS_index1);
1109 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1110 ok(val == NULL, "TLS slot not initialized correctly\n");
1112 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1113 ok(ret, "TlsSetValue failed\n");
1115 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1116 ok(ret, "TlsSetValue failed\n");
1118 val = TlsGetValue(TLS_index0);
1119 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1120 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1122 val = TlsGetValue(TLS_index1);
1123 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1124 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1126 resync_after_run();
1128 if (sync_threads_and_run_one(0, id))
1130 HANDLE thread;
1131 DWORD waitret, tid;
1133 val = TlsGetValue(TLS_index0);
1134 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1135 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1137 val = TlsGetValue(TLS_index1);
1138 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1139 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1141 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1142 ok(thread != NULL, "CreateThread failed\n");
1143 waitret = WaitForSingleObject(thread, 60000);
1144 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1145 CloseHandle(thread);
1147 ret = TlsFree(TLS_index0);
1148 ok(ret, "TlsFree failed\n");
1150 resync_after_run();
1152 if (sync_threads_and_run_one(1, id))
1154 ret = TlsFree(TLS_index1);
1155 ok(ret, "TlsFree failed\n");
1157 resync_after_run();
1159 return 0;
1162 static void test_TLS(void)
1164 HANDLE threads[2];
1165 LONG i;
1166 DWORD ret;
1167 BOOL suc;
1169 init_thread_sync_helpers(2);
1171 /* Allocate a TLS slot in the main thread to test for inheritance. */
1172 TLS_main = TlsAlloc();
1173 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1174 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1175 ok(suc, "TlsSetValue failed\n");
1177 for (i = 0; i < 2; ++i)
1179 DWORD tid;
1181 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1182 ok(threads[i] != NULL, "CreateThread failed\n");
1185 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1186 ok(ret == WAIT_OBJECT_0, "WaitForMultipleObjects failed\n");
1188 for (i = 0; i < 2; ++i)
1189 CloseHandle(threads[i]);
1191 suc = TlsFree(TLS_main);
1192 ok(suc, "TlsFree failed\n");
1193 cleanup_thread_sync_helpers();
1196 START_TEST(thread)
1198 HINSTANCE lib;
1199 int argc;
1200 char **argv;
1201 argc = winetest_get_mainargs( &argv );
1202 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1203 so that the compile passes
1205 lib=GetModuleHandleA("kernel32.dll");
1206 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1207 pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
1208 pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
1209 pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem");
1210 pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
1211 pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
1212 pRegisterWaitForSingleObject=(RegisterWaitForSingleObject_t)GetProcAddress(lib,"RegisterWaitForSingleObject");
1213 pUnregisterWait=(UnregisterWait_t)GetProcAddress(lib,"UnregisterWait");
1215 if (argc >= 3)
1217 if (!strcmp(argv[2], "sleep"))
1219 HANDLE hAddrEvents[2];
1220 create_function_addr_events(hAddrEvents);
1221 SetEvent(hAddrEvents[0]);
1222 SetEvent(hAddrEvents[1]);
1223 Sleep(5000); /* spawned process runs for at most 5 seconds */
1224 return;
1226 while (1)
1228 HANDLE hThread;
1229 DWORD tid;
1230 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1231 ok(hThread != NULL, "CreateThread failed, error %u\n",
1232 GetLastError());
1233 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1234 "Thread did not exit in time\n");
1235 if (hThread == NULL) break;
1236 CloseHandle(hThread);
1238 return;
1241 test_CreateRemoteThread();
1242 test_CreateThread_basic();
1243 test_CreateThread_suspended();
1244 test_SuspendThread();
1245 test_TerminateThread();
1246 test_CreateThread_stack();
1247 test_thread_priority();
1248 test_GetThreadTimes();
1249 test_thread_processor();
1250 test_GetThreadExitCode();
1251 #ifdef __i386__
1252 test_SetThreadContext();
1253 #endif
1254 test_QueueUserWorkItem();
1255 test_RegisterWaitForSingleObject();
1256 test_TLS();