2 * Unit test suite for thread 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
28 #include "wine/test.h"
34 /* Specify the number of simultaneous threads to test */
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 */
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
50 # define __EXCEPT __except
53 # include "wine/exception.h"
57 static BOOL (WINAPI *pGetThreadPriorityBoost)(HANDLE,PBOOL);
58 static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
59 static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
60 static DWORD (WINAPI *pSetThreadIdealProcessor)(HANDLE,DWORD);
61 static BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL);
62 static BOOL (WINAPI *pRegisterWaitForSingleObject)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
63 static BOOL (WINAPI *pUnregisterWait)(HANDLE);
64 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
66 static HANDLE create_target_process(const char *arg)
69 char cmdline[MAX_PATH];
70 PROCESS_INFORMATION pi;
71 STARTUPINFO si = { 0 };
74 winetest_get_mainargs( &argv );
75 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
76 ok(CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
77 &si, &pi) != 0, "error: %u\n", GetLastError());
78 ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
82 /* Functions not tested yet:
87 In addition there are no checks that the inheritance works properly in
91 /* Functions to ensure that from a group of threads, only one executes
92 certain chunks of code at a time, and we know which one is executing
93 it. It basically makes multithreaded execution linear, which defeats
94 the purpose of multiple threads, but makes testing easy. */
95 static HANDLE start_event, stop_event;
96 static LONG num_synced;
98 static void init_thread_sync_helpers(void)
100 start_event = CreateEvent(NULL, TRUE, FALSE, NULL);
101 ok(start_event != NULL, "CreateEvent failed\n");
102 stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
103 ok(stop_event != NULL, "CreateEvent failed\n");
107 static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id)
109 LONG num = InterlockedIncrement(&num_synced);
110 assert(-1 <= num && num <= 1);
113 ResetEvent( stop_event );
114 SetEvent( start_event );
118 DWORD ret = WaitForSingleObject(start_event, 10000);
119 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed %x\n",ret);
121 return sync_id == my_id;
124 static void resync_after_run(void)
126 LONG num = InterlockedDecrement(&num_synced);
127 assert(-1 <= num && num <= 1);
130 ResetEvent( start_event );
131 SetEvent( stop_event );
135 DWORD ret = WaitForSingleObject(stop_event, 10000);
136 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
140 static void cleanup_thread_sync_helpers(void)
142 CloseHandle(start_event);
143 CloseHandle(stop_event);
154 /* WinME supports OpenThread but doesn't know about access restrictions so
155 we require them to be either completely ignored or always obeyed.
157 INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
161 ? (obeying_ars = +1) \
162 : ((obeying_ars = -1), \
163 trace("not restricted, assuming consistent behaviour\n"))) \
164 : (obeying_ars < 0) \
165 ? ok(!(x), "access restrictions obeyed\n") \
166 : ok( (x), "access restrictions not obeyed\n"))
168 /* Basic test that simultaneous threads can access shared memory,
169 that the thread local storage routines work correctly, and that
170 threads actually run concurrently
172 static DWORD WINAPI threadFunc1(LPVOID p)
174 t1Struct *tstruct = p;
176 /* write our thread # into shared memory */
177 tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
178 ok(TlsSetValue(tlsIndex,(LPVOID)(INT_PTR)(tstruct->threadnum+1))!=0,
179 "TlsSetValue failed\n");
180 /* The threads synchronize before terminating. This is done by
181 Signaling an event, and waiting for all events to occur
183 SetEvent(tstruct->event[tstruct->threadnum]);
184 WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
185 /* Double check that all threads really did run by validating that
186 they have all written to the shared memory. There should be no race
187 here, since all threads were synchronized after the write.*/
188 for(i=0;i<NUM_THREADS;i++) {
189 while(tstruct->threadmem[i]==0) ;
192 /* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
193 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
195 /* Check that no one changed our tls memory */
196 ok((INT_PTR)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
197 "TlsGetValue failed\n");
198 return NUM_THREADS+tstruct->threadnum;
201 static DWORD WINAPI threadFunc2(LPVOID p)
206 static DWORD WINAPI threadFunc3(LPVOID p)
209 thread=GetCurrentThread();
210 SuspendThread(thread);
214 static DWORD WINAPI threadFunc4(LPVOID p)
225 static DWORD WINAPI threadFunc5(LPVOID p)
229 sysInfo.dwPageSize=0;
230 GetSystemInfo(&sysInfo);
234 alloca(2*sysInfo.dwPageSize);
244 static DWORD WINAPI threadFunc_SetEvent(LPVOID p)
250 static DWORD WINAPI threadFunc_CloseHandle(LPVOID p)
256 static void create_function_addr_events(HANDLE events[2])
260 sprintf(buffer, "threadFunc_SetEvent %p", threadFunc_SetEvent);
261 events[0] = CreateEvent(NULL, FALSE, FALSE, buffer);
263 sprintf(buffer, "threadFunc_CloseHandle %p", threadFunc_CloseHandle);
264 events[1] = CreateEvent(NULL, FALSE, FALSE, buffer);
267 /* check CreateRemoteThread */
268 static VOID test_CreateRemoteThread(void)
270 HANDLE hProcess, hThread, hEvent, hRemoteEvent;
271 DWORD tid, ret, exitcode;
272 HANDLE hAddrEvents[2];
274 hProcess = create_target_process("sleep");
275 ok(hProcess != NULL, "Can't start process\n");
277 /* ensure threadFunc_SetEvent & threadFunc_CloseHandle are the same
278 * address as in the child process */
279 create_function_addr_events(hAddrEvents);
280 ret = WaitForMultipleObjects(2, hAddrEvents, TRUE, 5000);
281 if (ret == WAIT_TIMEOUT)
283 skip("child process wasn't mapped at same address, so can't do CreateRemoteThread tests.\n");
287 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
288 ok(hEvent != NULL, "Can't create event, err=%u\n", GetLastError());
289 ret = DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hRemoteEvent,
290 0, FALSE, DUPLICATE_SAME_ACCESS);
291 ok(ret != 0, "DuplicateHandle failed, err=%u\n", GetLastError());
293 /* create suspended remote thread with entry point SetEvent() */
294 SetLastError(0xdeadbeef);
295 hThread = CreateRemoteThread(hProcess, NULL, 0, threadFunc_SetEvent,
296 hRemoteEvent, CREATE_SUSPENDED, &tid);
297 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
299 win_skip("CreateRemoteThread is not implemented\n");
302 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
303 ok(tid != 0, "null tid\n");
304 ret = SuspendThread(hThread);
305 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
306 ret = ResumeThread(hThread);
307 ok(ret == 2, "ret=%u, err=%u\n", ret, GetLastError());
309 /* thread still suspended, so wait times out */
310 ret = WaitForSingleObject(hEvent, 100);
311 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
313 ret = ResumeThread(hThread);
314 ok(ret == 1, "ret=%u, err=%u\n", ret, GetLastError());
316 /* wait that doesn't time out */
317 ret = WaitForSingleObject(hEvent, 100);
318 ok(ret == WAIT_OBJECT_0, "object not signaled, ret=%u\n", ret);
320 /* wait for thread end */
321 ret = WaitForSingleObject(hThread, 100);
322 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
323 CloseHandle(hThread);
325 /* create and wait for remote thread with entry point CloseHandle() */
326 hThread = CreateRemoteThread(hProcess, NULL, 0,
327 threadFunc_CloseHandle,
328 hRemoteEvent, 0, &tid);
329 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
330 ret = WaitForSingleObject(hThread, 100);
331 ok(ret == WAIT_OBJECT_0, "waiting for thread failed, ret=%u\n", ret);
332 CloseHandle(hThread);
334 /* create remote thread with entry point SetEvent() */
335 hThread = CreateRemoteThread(hProcess, NULL, 0,
337 hRemoteEvent, 0, &tid);
338 ok(hThread != NULL, "CreateRemoteThread failed, err=%u\n", GetLastError());
340 /* closed handle, so wait times out */
341 ret = WaitForSingleObject(hEvent, 100);
342 ok(ret == WAIT_TIMEOUT, "wait did not time out, ret=%u\n", ret);
344 /* check that remote SetEvent() failed */
345 ret = GetExitCodeThread(hThread, &exitcode);
346 ok(ret != 0, "GetExitCodeThread failed, err=%u\n", GetLastError());
347 if (ret) ok(exitcode == 0, "SetEvent succeeded, expected to fail\n");
348 CloseHandle(hThread);
351 TerminateProcess(hProcess, 0);
353 CloseHandle(hProcess);
356 /* Check basic functionality of CreateThread and Tls* functions */
357 static VOID test_CreateThread_basic(void)
359 HANDLE thread[NUM_THREADS],event[NUM_THREADS];
360 DWORD threadid[NUM_THREADS],curthreadId;
361 DWORD threadmem[NUM_THREADS];
363 t1Struct tstruct[NUM_THREADS];
369 /* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
370 ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
372 /* Retrieve current Thread ID for later comparisons */
373 curthreadId=GetCurrentThreadId();
374 /* Allocate some local storage */
375 ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
376 /* Create events for thread synchronization */
377 for(i=0;i<NUM_THREADS;i++) {
379 /* Note that it doesn't matter what type of event we choose here. This
380 test isn't trying to thoroughly test events
382 event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
383 tstruct[i].threadnum=i;
384 tstruct[i].threadmem=threadmem;
385 tstruct[i].event=event;
388 /* Test that passing arguments to threads works okay */
389 for(i=0;i<NUM_THREADS;i++) {
390 thread[i] = CreateThread(NULL,0,threadFunc1,
391 &tstruct[i],0,&threadid[i]);
392 ok(thread[i]!=NULL,"Create Thread failed\n");
394 /* Test that the threads actually complete */
395 for(i=0;i<NUM_THREADS;i++) {
396 error=WaitForSingleObject(thread[i],5000);
397 ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
398 if(error!=WAIT_OBJECT_0) {
399 TerminateThread(thread[i],i+NUM_THREADS);
401 ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
402 ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
404 /* Test that each thread executed in its parent's address space
405 (it was able to change threadmem and pass that change back to its parent)
406 and that each thread id was independent). Note that we prove that the
407 threads actually execute concurrently by having them block on each other
410 for(i=0;i<NUM_THREADS;i++) {
412 for(j=i+1;j<NUM_THREADS;j++) {
413 if (threadmem[i]==threadmem[j]) {
417 ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
418 "Thread did not execute successfully\n");
419 ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
421 ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
423 /* Test how passing NULL as a pointer to threadid works */
424 SetLastError(0xFACEaBAD);
425 thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,&tid);
426 GLE = GetLastError();
427 if (thread[0]) { /* NT */
428 ok(GLE==0xFACEaBAD, "CreateThread set last error to %d, expected 4207848365\n", GLE);
429 ret = WaitForSingleObject(thread[0],100);
430 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
431 ret = GetExitCodeThread(thread[0],&exitCode);
432 ok(ret!=0, "GetExitCodeThread returned %d (expected nonzero)\n", ret);
433 ok(exitCode==99, "threadFunc2 exited with code: %d (expected 99)\n", exitCode);
434 ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
437 ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %d, expected 87\n", GLE);
441 /* Check that using the CREATE_SUSPENDED flag works */
442 static VOID test_CreateThread_suspended(void)
449 thread = CreateThread(NULL,0,threadFunc2,NULL,
450 CREATE_SUSPENDED,&threadId);
451 ok(thread!=NULL,"Create Thread failed\n");
452 /* Check that the thread is suspended */
453 ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
454 ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
455 /* Check that resume thread didn't actually start the thread. I can't think
456 of a better way of checking this than just waiting. I am not sure if this
457 will work on slow computers.
459 ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
460 "ResumeThread should not have actually started the thread\n");
461 /* Now actually resume the thread and make sure that it actually completes*/
462 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
463 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
464 "Thread did not resume\n");
465 if(error!=WAIT_OBJECT_0) {
466 TerminateThread(thread,1);
469 suspend_count = SuspendThread(thread);
470 ok(suspend_count == -1, "SuspendThread returned %d, expected -1\n", suspend_count);
472 suspend_count = ResumeThread(thread);
473 ok(suspend_count == 0 ||
474 broken(suspend_count == -1), /* win9x */
475 "ResumeThread returned %d, expected 0\n", suspend_count);
477 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
480 /* Check that SuspendThread and ResumeThread work */
481 static VOID test_SuspendThread(void)
483 HANDLE thread,access_thread;
484 DWORD threadId,exitCode,error;
487 thread = CreateThread(NULL,0,threadFunc3,NULL,
489 ok(thread!=NULL,"Create Thread failed\n");
490 /* Check that the thread is suspended */
491 /* Note that this is a polling method, and there is a race between
492 SuspendThread being called (in the child, and the loop below timing out,
493 so the test could fail on a heavily loaded or slow computer.
496 for(i=0;error==0 && i<100;i++) {
497 error=SuspendThread(thread);
498 ResumeThread(thread);
504 ok(error==1,"SuspendThread did not work\n");
505 /* check that access restrictions are obeyed */
507 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
509 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
510 if (access_thread!=NULL) {
511 obey_ar(SuspendThread(access_thread)==~0U);
512 obey_ar(ResumeThread(access_thread)==~0U);
513 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
516 /* Double check that the thread really is suspended */
517 ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
518 "Thread did not really suspend\n");
519 /* Resume the thread, and make sure it actually completes */
520 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
521 ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
522 "Thread did not resume\n");
523 if(error!=WAIT_OBJECT_0) {
524 TerminateThread(thread,1);
526 /* Trying to suspend a terminated thread should fail */
527 error=SuspendThread(thread);
528 ok(error==~0U, "wrong return code: %d\n", error);
529 ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %d\n", GetLastError());
531 ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
534 /* Check that TerminateThread works properly
536 static VOID test_TerminateThread(void)
538 HANDLE thread,access_thread,event;
539 DWORD threadId,exitCode;
540 event=CreateEventA(NULL,TRUE,FALSE,NULL);
541 thread = CreateThread(NULL,0,threadFunc4,event,0,&threadId);
542 ok(thread!=NULL,"Create Thread failed\n");
543 /* TerminateThread has a race condition in Wine. If the thread is terminated
544 before it starts, it leaves a process behind. Therefore, we wait for the
545 thread to signal that it has started. There is no easy way to force the
546 race to occur, so we don't try to find it.
548 ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
549 "TerminateThread didn't work\n");
550 /* check that access restrictions are obeyed */
552 access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
554 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
555 if (access_thread!=NULL) {
556 obey_ar(TerminateThread(access_thread,99)==0);
557 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
560 /* terminate a job and make sure it terminates */
561 ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
562 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
563 "TerminateThread didn't work\n");
564 ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
565 "TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
566 ok(exitCode==99, "TerminateThread returned invalid exit code\n");
567 ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
570 /* Check if CreateThread obeys the specified stack size. This code does
571 not work properly, and is currently disabled
573 static VOID test_CreateThread_stack(void)
576 /* The only way I know of to test the stack size is to use alloca
577 and __try/__except. However, this is probably not portable,
578 and I couldn't get it to work under Wine anyhow. However, here
579 is the code which should allow for testing that CreateThread
580 respects the stack-size limit
583 DWORD threadId,exitCode;
586 sysInfo.dwPageSize=0;
587 GetSystemInfo(&sysInfo);
588 ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
589 thread = CreateThread(NULL,sysInfo.dwPageSize,
590 threadFunc5,&exitCode,
592 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
593 "TerminateThread didn't work\n");
594 ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
595 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
599 /* Check whether setting/retrieving thread priorities works */
600 static VOID test_thread_priority(void)
602 HANDLE curthread,access_thread;
603 DWORD curthreadId,exitCode;
604 int min_priority=-2,max_priority=2;
608 curthread=GetCurrentThread();
609 curthreadId=GetCurrentThreadId();
610 /* Check thread priority */
611 /* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
612 is -2 to 2. However, even on a real Win2k system, using thread
613 priorities beyond the -2 to 2 range does not work. If you want to try
614 anyway, enable USE_EXTENDED_PRIORITIES
616 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
617 "GetThreadPriority Failed\n");
620 /* check that access control is obeyed */
621 access_thread=pOpenThread(THREAD_ALL_ACCESS &
622 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
624 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
625 if (access_thread!=NULL) {
626 obey_ar(SetThreadPriority(access_thread,1)==0);
627 obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
628 obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
629 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
632 #if USE_EXTENDED_PRIORITIES
633 min_priority=-7; max_priority=6;
635 for(i=min_priority;i<=max_priority;i++) {
636 ok(SetThreadPriority(curthread,i)!=0,
637 "SetThreadPriority Failed for priority: %d\n",i);
638 ok(GetThreadPriority(curthread)==i,
639 "GetThreadPriority Failed for priority: %d\n",i);
641 ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
642 "SetThreadPriority Failed\n");
643 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
644 "GetThreadPriority Failed\n");
645 ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
646 "SetThreadPriority Failed\n");
647 ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
648 "GetThreadPriority Failed\n");
649 ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
651 /* Check that the thread priority is not changed if SetThreadPriority
652 is called with a value outside of the max/min range */
653 SetThreadPriority(curthread,min_priority);
654 SetLastError(0xdeadbeef);
655 rc = SetThreadPriority(curthread,min_priority-1);
657 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
658 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
659 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
660 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
662 ok(GetThreadPriority(curthread)==min_priority,
663 "GetThreadPriority didn't return min_priority\n");
665 SetThreadPriority(curthread,max_priority);
666 SetLastError(0xdeadbeef);
667 rc = SetThreadPriority(curthread,max_priority+1);
669 ok(rc == FALSE, "SetThreadPriority passed with a bad argument\n");
670 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
671 GetLastError() == ERROR_INVALID_PRIORITY /* Win9x */,
672 "SetThreadPriority error %d, expected ERROR_INVALID_PARAMETER or ERROR_INVALID_PRIORITY\n",
674 ok(GetThreadPriority(curthread)==max_priority,
675 "GetThreadPriority didn't return max_priority\n");
677 /* Check thread priority boost */
678 if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
681 SetLastError(0xdeadbeef);
682 rc=pGetThreadPriorityBoost(curthread,&disabled);
683 if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
685 win_skip("GetThreadPriorityBoost is not implemented on WinME\n");
689 ok(rc!=0,"error=%d\n",GetLastError());
692 /* check that access control is obeyed */
693 access_thread=pOpenThread(THREAD_ALL_ACCESS &
694 (~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
696 ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
697 if (access_thread!=NULL) {
698 obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
699 todo_wine obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
700 ok(CloseHandle(access_thread),"Error Closing thread handle\n");
705 rc = pSetThreadPriorityBoost(curthread,1);
706 ok( rc != 0, "error=%d\n",GetLastError());
707 rc=pGetThreadPriorityBoost(curthread,&disabled);
708 ok(rc!=0 && disabled==1,
709 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
711 rc = pSetThreadPriorityBoost(curthread,0);
712 ok( rc != 0, "error=%d\n",GetLastError());
714 rc=pGetThreadPriorityBoost(curthread,&disabled);
715 ok(rc!=0 && disabled==0,
716 "rc=%d error=%d disabled=%d\n",rc,GetLastError(),disabled);
719 /* check the GetThreadTimes function */
720 static VOID test_GetThreadTimes(void)
722 HANDLE thread,access_thread=NULL;
723 FILETIME creationTime,exitTime,kernelTime,userTime;
727 thread = CreateThread(NULL,0,threadFunc2,NULL,
728 CREATE_SUSPENDED,&threadId);
730 ok(thread!=NULL,"Create Thread failed\n");
731 /* check that access control is obeyed */
733 access_thread=pOpenThread(THREAD_ALL_ACCESS &
734 (~THREAD_QUERY_INFORMATION), 0,threadId);
735 ok(access_thread!=NULL,
736 "OpenThread returned an invalid handle\n");
738 ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
739 ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
740 "ResumeThread didn't work\n");
741 creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
742 exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
743 kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
744 userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
745 /* GetThreadTimes should set all of the parameters passed to it */
746 error=GetThreadTimes(thread,&creationTime,&exitTime,
747 &kernelTime,&userTime);
749 if (error == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
750 win_skip("GetThreadTimes is not implemented\n");
752 ok(error!=0,"GetThreadTimes failed\n");
753 ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
754 "creationTime was invalid\n");
755 ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
756 "exitTime was invalid\n");
757 ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
758 "kernelTimewas invalid\n");
759 ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
760 "userTime was invalid\n");
761 ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
762 if(access_thread!=NULL)
764 error=GetThreadTimes(access_thread,&creationTime,&exitTime,
765 &kernelTime,&userTime);
769 if(access_thread!=NULL) {
770 ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
774 /* Check the processor affinity functions */
775 /* NOTE: These functions should also be checked that they obey access control
777 static VOID test_thread_processor(void)
779 HANDLE curthread,curproc;
780 DWORD_PTR processMask,systemMask;
785 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
787 sysInfo.dwNumberOfProcessors=0;
788 GetSystemInfo(&sysInfo);
789 ok(sysInfo.dwNumberOfProcessors>0,
790 "GetSystemInfo failed to return a valid # of processors\n");
791 /* Use the current Thread/process for all tests */
792 curthread=GetCurrentThread();
793 ok(curthread!=NULL,"GetCurrentThread failed\n");
794 curproc=GetCurrentProcess();
795 ok(curproc!=NULL,"GetCurrentProcess failed\n");
796 /* Check the Affinity Mask functions */
797 ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
798 "GetProcessAffinityMask failed\n");
799 ok(SetThreadAffinityMask(curthread,processMask)==processMask,
800 "SetThreadAffinityMask failed\n");
801 ok(SetThreadAffinityMask(curthread,processMask+1)==0,
802 "SetThreadAffinityMask passed for an illegal processor\n");
803 /* NOTE: This only works on WinNT/2000/XP) */
804 if (pSetThreadIdealProcessor) {
805 SetLastError(0xdeadbeef);
806 error=pSetThreadIdealProcessor(curthread,0);
807 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
809 win_skip("SetThreadIdealProcessor is not implemented\n");
812 ok(error!=-1, "SetThreadIdealProcessor failed\n");
816 SetLastError(0xdeadbeef);
817 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
819 ok(error!=-1, "SetThreadIdealProcessor failed for %u on Wow64\n", MAXIMUM_PROCESSORS+1);
821 SetLastError(0xdeadbeef);
822 error=pSetThreadIdealProcessor(curthread,65);
823 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
824 ok(GetLastError()==ERROR_INVALID_PARAMETER,
825 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
829 SetLastError(0xdeadbeef);
830 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
831 ok(error==-1, "SetThreadIdealProcessor succeeded with an illegal processor #\n");
832 ok(GetLastError()==ERROR_INVALID_PARAMETER,
833 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
836 error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
837 ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
841 static VOID test_GetThreadExitCode(void)
843 DWORD exitCode, threadid;
847 ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
848 ok(ret==0, "GetExitCodeThread returned non zero value: %d\n", ret);
849 GLE = GetLastError();
850 ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %d (expected 6)\n", GLE);
852 thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
853 ret = WaitForSingleObject(thread,100);
854 ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
855 ret = GetExitCodeThread(thread,&exitCode);
856 ok(ret==exitCode || ret==1,
857 "GetExitCodeThread returned %d (expected 1 or %d)\n", ret, exitCode);
858 ok(exitCode==99, "threadFunc2 exited with code %d (expected 99)\n", exitCode);
859 ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
864 static int test_value = 0;
867 static void WINAPI set_test_val( int val )
872 static DWORD WINAPI threadFunc6(LPVOID p)
876 test_value *= (int)p;
880 static void test_SetThreadContext(void)
889 SetLastError(0xdeadbeef);
890 event = CreateEvent( NULL, TRUE, FALSE, NULL );
891 thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
892 ok( thread != NULL, "CreateThread failed : (%d)\n", GetLastError() );
895 trace("Thread creation failed, skipping rest of test\n");
898 WaitForSingleObject( event, INFINITE );
899 SuspendThread( thread );
900 CloseHandle( event );
902 ctx.ContextFlags = CONTEXT_FULL;
903 SetLastError(0xdeadbeef);
904 ret = GetThreadContext( thread, &ctx );
905 ok( ret, "GetThreadContext failed : (%u)\n", GetLastError() );
909 /* simulate a call to set_test_val(10) */
910 stack = (int *)ctx.Esp;
913 ctx.Esp -= 2 * sizeof(int *);
914 ctx.Eip = (DWORD)set_test_val;
915 SetLastError(0xdeadbeef);
916 ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%d)\n", GetLastError() );
919 SetLastError(0xdeadbeef);
920 prevcount = ResumeThread( thread );
921 ok ( prevcount == 1, "Previous suspend count (%d) instead of 1, last error : (%d)\n",
922 prevcount, GetLastError() );
924 WaitForSingleObject( thread, INFINITE );
925 ok( test_value == 20, "test_value %d instead of 20\n", test_value );
928 #endif /* __i386__ */
930 static HANDLE finish_event;
931 static LONG times_executed;
933 static DWORD CALLBACK work_function(void *p)
935 LONG executed = InterlockedIncrement(×_executed);
938 SetEvent(finish_event);
942 static void test_QueueUserWorkItem(void)
948 /* QueueUserWorkItem not present on win9x */
949 if (!pQueueUserWorkItem) return;
951 finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
953 before = GetTickCount();
955 for (i = 0; i < 100; i++)
957 BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
958 ok(ret, "QueueUserWorkItem failed with error %d\n", GetLastError());
961 wait_result = WaitForSingleObject(finish_event, 10000);
963 after = GetTickCount();
964 trace("100 QueueUserWorkItem calls took %dms\n", after - before);
965 ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%x\n", wait_result);
967 ok(times_executed == 100, "didn't execute all of the work items\n");
970 static void CALLBACK signaled_function(PVOID p, BOOLEAN TimerOrWaitFired)
974 ok(!TimerOrWaitFired, "wait shouldn't have timed out\n");
977 static void CALLBACK timeout_function(PVOID p, BOOLEAN TimerOrWaitFired)
981 ok(TimerOrWaitFired, "wait should have timed out\n");
984 static void test_RegisterWaitForSingleObject(void)
989 HANDLE complete_event;
991 if (!pRegisterWaitForSingleObject || !pUnregisterWait)
993 win_skip("RegisterWaitForSingleObject or UnregisterWait not implemented\n");
997 /* test signaled case */
999 handle = CreateEvent(NULL, TRUE, TRUE, NULL);
1000 complete_event = CreateEvent(NULL, FALSE, FALSE, NULL);
1002 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1003 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1005 WaitForSingleObject(complete_event, INFINITE);
1006 /* give worker thread chance to complete */
1009 ret = pUnregisterWait(wait_handle);
1010 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1012 /* test cancel case */
1016 ret = pRegisterWaitForSingleObject(&wait_handle, handle, signaled_function, complete_event, INFINITE, WT_EXECUTEONLYONCE);
1017 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1019 ret = pUnregisterWait(wait_handle);
1020 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1022 /* test timeout case */
1024 ret = pRegisterWaitForSingleObject(&wait_handle, handle, timeout_function, complete_event, 0, WT_EXECUTEONLYONCE);
1025 ok(ret, "RegisterWaitForSingleObject failed with error %d\n", GetLastError());
1027 WaitForSingleObject(complete_event, INFINITE);
1028 /* give worker thread chance to complete */
1031 ret = pUnregisterWait(wait_handle);
1032 ok(ret, "UnregisterWait failed with error %d\n", GetLastError());
1035 static DWORD TLS_main;
1036 static DWORD TLS_index0, TLS_index1;
1038 static DWORD WINAPI TLS_InheritanceProc(LPVOID p)
1040 /* We should NOT inherit the TLS values from our parent or from the
1044 val = TlsGetValue(TLS_main);
1045 ok(val == NULL, "TLS inheritance failed\n");
1047 val = TlsGetValue(TLS_index0);
1048 ok(val == NULL, "TLS inheritance failed\n");
1050 val = TlsGetValue(TLS_index1);
1051 ok(val == NULL, "TLS inheritance failed\n");
1056 /* Basic TLS usage test. Make sure we can create slots and the values we
1057 store in them are separate among threads. Also test TLS value
1058 inheritance with TLS_InheritanceProc. */
1059 static DWORD WINAPI TLS_ThreadProc(LPVOID p)
1061 LONG_PTR id = (LONG_PTR) p;
1065 if (sync_threads_and_run_one(0, id))
1067 TLS_index0 = TlsAlloc();
1068 ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1072 if (sync_threads_and_run_one(1, id))
1074 TLS_index1 = TlsAlloc();
1075 ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1077 /* Slot indices should be different even if created in different
1079 ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n");
1081 /* Both slots should be initialized to NULL */
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");
1092 if (sync_threads_and_run_one(0, id))
1094 val = TlsGetValue(TLS_index0);
1095 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1096 ok(val == NULL, "TLS slot not initialized correctly\n");
1098 val = TlsGetValue(TLS_index1);
1099 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1100 ok(val == NULL, "TLS slot not initialized correctly\n");
1102 ret = TlsSetValue(TLS_index0, (LPVOID) 1);
1103 ok(ret, "TlsSetValue failed\n");
1105 ret = TlsSetValue(TLS_index1, (LPVOID) 2);
1106 ok(ret, "TlsSetValue failed\n");
1108 val = TlsGetValue(TLS_index0);
1109 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1110 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1112 val = TlsGetValue(TLS_index1);
1113 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1114 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1118 if (sync_threads_and_run_one(1, id))
1120 val = TlsGetValue(TLS_index0);
1121 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1122 ok(val == NULL, "TLS slot not initialized correctly\n");
1124 val = TlsGetValue(TLS_index1);
1125 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1126 ok(val == NULL, "TLS slot not initialized correctly\n");
1128 ret = TlsSetValue(TLS_index0, (LPVOID) 3);
1129 ok(ret, "TlsSetValue failed\n");
1131 ret = TlsSetValue(TLS_index1, (LPVOID) 4);
1132 ok(ret, "TlsSetValue failed\n");
1134 val = TlsGetValue(TLS_index0);
1135 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1136 ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n");
1138 val = TlsGetValue(TLS_index1);
1139 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1140 ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n");
1144 if (sync_threads_and_run_one(0, id))
1149 val = TlsGetValue(TLS_index0);
1150 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1151 ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n");
1153 val = TlsGetValue(TLS_index1);
1154 ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n");
1155 ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n");
1157 thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, &tid);
1158 ok(thread != NULL, "CreateThread failed\n");
1159 waitret = WaitForSingleObject(thread, 60000);
1160 ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
1161 CloseHandle(thread);
1163 ret = TlsFree(TLS_index0);
1164 ok(ret, "TlsFree failed\n");
1168 if (sync_threads_and_run_one(1, id))
1170 ret = TlsFree(TLS_index1);
1171 ok(ret, "TlsFree failed\n");
1178 static void test_TLS(void)
1185 init_thread_sync_helpers();
1187 /* Allocate a TLS slot in the main thread to test for inheritance. */
1188 TLS_main = TlsAlloc();
1189 ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n");
1190 suc = TlsSetValue(TLS_main, (LPVOID) 4114);
1191 ok(suc, "TlsSetValue failed\n");
1193 for (i = 0; i < 2; ++i)
1197 threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, &tid);
1198 ok(threads[i] != NULL, "CreateThread failed\n");
1201 ret = WaitForMultipleObjects(2, threads, TRUE, 60000);
1202 ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0+1 /* nt4 */, "WaitForMultipleObjects failed %u\n",ret);
1204 for (i = 0; i < 2; ++i)
1205 CloseHandle(threads[i]);
1207 suc = TlsFree(TLS_main);
1208 ok(suc, "TlsFree failed\n");
1209 cleanup_thread_sync_helpers();
1217 argc = winetest_get_mainargs( &argv );
1218 /* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
1219 so that the compile passes
1221 lib=GetModuleHandleA("kernel32.dll");
1222 ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
1223 pGetThreadPriorityBoost=(void *)GetProcAddress(lib,"GetThreadPriorityBoost");
1224 pOpenThread=(void *)GetProcAddress(lib,"OpenThread");
1225 pQueueUserWorkItem=(void *)GetProcAddress(lib,"QueueUserWorkItem");
1226 pSetThreadIdealProcessor=(void *)GetProcAddress(lib,"SetThreadIdealProcessor");
1227 pSetThreadPriorityBoost=(void *)GetProcAddress(lib,"SetThreadPriorityBoost");
1228 pRegisterWaitForSingleObject=(void *)GetProcAddress(lib,"RegisterWaitForSingleObject");
1229 pUnregisterWait=(void *)GetProcAddress(lib,"UnregisterWait");
1230 pIsWow64Process=(void *)GetProcAddress(lib,"IsWow64Process");
1234 if (!strcmp(argv[2], "sleep"))
1236 HANDLE hAddrEvents[2];
1237 create_function_addr_events(hAddrEvents);
1238 SetEvent(hAddrEvents[0]);
1239 SetEvent(hAddrEvents[1]);
1240 Sleep(5000); /* spawned process runs for at most 5 seconds */
1247 hThread = CreateThread(NULL, 0, threadFunc2, NULL, 0, &tid);
1248 ok(hThread != NULL, "CreateThread failed, error %u\n",
1250 ok(WaitForSingleObject(hThread, 200) == WAIT_OBJECT_0,
1251 "Thread did not exit in time\n");
1252 if (hThread == NULL) break;
1253 CloseHandle(hThread);
1258 test_CreateRemoteThread();
1259 test_CreateThread_basic();
1260 test_CreateThread_suspended();
1261 test_SuspendThread();
1262 test_TerminateThread();
1263 test_CreateThread_stack();
1264 test_thread_priority();
1265 test_GetThreadTimes();
1266 test_thread_processor();
1267 test_GetThreadExitCode();
1269 test_SetThreadContext();
1271 test_QueueUserWorkItem();
1272 test_RegisterWaitForSingleObject();