📄 thread.c
字号:
thread to signal that it has started. There is no easy way to force the
race to occur, so we don't try to find it.
*/
ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
"TerminateThread didn't work\n");
/* check that access restrictions are obeyed */
if (pOpenThread) {
access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
0,threadId);
ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
if (access_thread!=NULL) {
obey_ar(TerminateThread(access_thread,99)==0);
ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
}
}
/* terminate a job and make sure it terminates */
ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
"TerminateThread didn't work\n");
ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
"TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
ok(exitCode==99, "TerminateThread returned invalid exit code\n");
ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
}
/* Check if CreateThread obeys the specified stack size. This code does
not work properly, and is currently disabled
*/
static VOID test_CreateThread_stack(void)
{
#if CHECK_STACK
/* The only way I know of to test the stack size is to use alloca
and __try/__except. However, this is probably not portable,
and I couldn't get it to work under Wine anyhow. However, here
is the code which should allow for testing that CreateThread
respects the stack-size limit
*/
HANDLE thread;
DWORD threadId,exitCode;
SYSTEM_INFO sysInfo;
sysInfo.dwPageSize=0;
GetSystemInfo(&sysInfo);
ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
thread = CreateThread(NULL,sysInfo.dwPageSize,
threadFunc5,&exitCode,
0,&threadId);
ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
"TerminateThread didn't work\n");
ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
#endif
}
/* Check whether setting/retrieving thread priorities works */
static VOID test_thread_priority(void)
{
HANDLE curthread,access_thread;
DWORD curthreadId,exitCode;
int min_priority=-2,max_priority=2;
BOOL disabled,rc;
int i;
curthread=GetCurrentThread();
curthreadId=GetCurrentThreadId();
/* Check thread priority */
/* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
is -2 to 2. However, even on a real Win2k system, using thread
priorities beyond the -2 to 2 range does not work. If you want to try
anyway, enable USE_EXTENDED_PRIORITIES
*/
ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
"GetThreadPriority Failed\n");
if (pOpenThread) {
/* check that access control is obeyed */
access_thread=pOpenThread(THREAD_ALL_ACCESS &
(~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
0,curthreadId);
ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
if (access_thread!=NULL) {
obey_ar(SetThreadPriority(access_thread,1)==0);
obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
ok(CloseHandle(access_thread),"Error Closing thread handle\n");
}
#if USE_EXTENDED_PRIORITIES
min_priority=-7; max_priority=6;
#endif
}
for(i=min_priority;i<=max_priority;i++) {
ok(SetThreadPriority(curthread,i)!=0,
"SetThreadPriority Failed for priority: %d\n",i);
ok(GetThreadPriority(curthread)==i,
"GetThreadPriority Failed for priority: %d\n",i);
}
ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
"SetThreadPriority Failed\n");
ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
"GetThreadPriority Failed\n");
ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
"SetThreadPriority Failed\n");
ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
"GetThreadPriority Failed\n");
ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
/* Check thread priority boost */
if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
return; /* Win9x */
SetLastError(0xdeadbeef);
rc=pGetThreadPriorityBoost(curthread,&disabled);
if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
return; /* WinME */
/* check that access control is obeyed */
access_thread=pOpenThread(THREAD_ALL_ACCESS &
(~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
0,curthreadId);
ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
if (access_thread!=NULL) {
obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
ok(CloseHandle(access_thread),"Error Closing thread handle\n");
}
todo_wine {
ok(rc!=0,"error=%ld\n",GetLastError());
rc = pSetThreadPriorityBoost(curthread,1);
ok( rc != 0, "error=%ld\n",GetLastError());
rc=pGetThreadPriorityBoost(curthread,&disabled);
ok(rc!=0 && disabled==1,
"rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
rc = pSetThreadPriorityBoost(curthread,0);
ok( rc != 0, "error=%ld\n",GetLastError());
rc=pGetThreadPriorityBoost(curthread,&disabled);
ok(rc!=0 && disabled==0,
"rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
}
}
/* check the GetThreadTimes function */
static VOID test_GetThreadTimes(void)
{
HANDLE thread,access_thread=NULL;
FILETIME creationTime,exitTime,kernelTime,userTime;
DWORD threadId;
int error;
thread = CreateThread(NULL,0,threadFunc2,NULL,
CREATE_SUSPENDED,&threadId);
ok(thread!=NULL,"Create Thread failed\n");
/* check that access control is obeyed */
if (pOpenThread) {
access_thread=pOpenThread(THREAD_ALL_ACCESS &
(~THREAD_QUERY_INFORMATION), 0,threadId);
ok(access_thread!=NULL,
"OpenThread returned an invalid handle\n");
}
ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
"ResumeThread didn't work\n");
creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
/* GetThreadTimes should set all of the parameters passed to it */
error=GetThreadTimes(thread,&creationTime,&exitTime,
&kernelTime,&userTime);
if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
ok(error!=0,"GetThreadTimes failed\n");
ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
"creationTime was invalid\n");
ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
"exitTime was invalid\n");
ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
"kernelTimewas invalid\n");
ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
"userTime was invalid\n");
ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
if(access_thread!=NULL)
{
error=GetThreadTimes(access_thread,&creationTime,&exitTime,
&kernelTime,&userTime);
obey_ar(error==0);
}
}
if(access_thread!=NULL) {
ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
}
}
/* Check the processor affinity functions */
/* NOTE: These functions should also be checked that they obey access control
*/
static VOID test_thread_processor(void)
{
HANDLE curthread,curproc;
DWORD processMask,systemMask;
SYSTEM_INFO sysInfo;
int error=0;
sysInfo.dwNumberOfProcessors=0;
GetSystemInfo(&sysInfo);
ok(sysInfo.dwNumberOfProcessors>0,
"GetSystemInfo failed to return a valid # of processors\n");
/* Use the current Thread/process for all tests */
curthread=GetCurrentThread();
ok(curthread!=NULL,"GetCurrentThread failed\n");
curproc=GetCurrentProcess();
ok(curproc!=NULL,"GetCurrentProcess failed\n");
/* Check the Affinity Mask functions */
ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
"GetProcessAffinityMask failed\n");
ok(SetThreadAffinityMask(curthread,processMask)==processMask,
"SetThreadAffinityMask failed\n");
ok(SetThreadAffinityMask(curthread,processMask+1)==0,
"SetThreadAffinityMask passed for an illegal processor\n");
/* NOTE: This only works on WinNT/2000/XP) */
if (pSetThreadIdealProcessor) {
todo_wine {
SetLastError(0);
error=pSetThreadIdealProcessor(curthread,0);
if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
ok(error!=-1, "SetThreadIdealProcessor failed\n");
}
}
if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
ok(error==-1,
"SetThreadIdealProcessor succeeded with an illegal processor #\n");
todo_wine {
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
}
}
}
}
static VOID test_GetThreadExitCode(void)
{
DWORD exitCode, threadid;
DWORD GLE, ret;
HANDLE thread;
ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
ok(ret==0, "GetExitCodeThread returned non zero value: %ld\n", ret);
GLE = GetLastError();
ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %ld (expected 6)\n", GLE);
thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
ret = WaitForSingleObject(thread,100);
ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
ret = GetExitCodeThread(thread,&exitCode);
ok(ret==exitCode || ret==1,
"GetExitCodeThread returned %ld (expected 1 or %ld)\n", ret, exitCode);
ok(exitCode==99, "threadFunc2 exited with code %ld (expected 99)\n", exitCode);
ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
}
#ifdef __i386__
static int test_value = 0;
static HANDLE event;
static void WINAPI set_test_val( int val )
{
test_value += val;
}
static DWORD WINAPI threadFunc6(LPVOID p)
{
SetEvent( event );
Sleep( 1000 );
test_value *= (int)p;
return 0;
}
static void test_SetThreadContext(void)
{
CONTEXT ctx;
int *stack;
HANDLE thread;
DWORD threadid;
DWORD prevcount;
SetLastError(0xdeadbeef);
event = CreateEvent( NULL, TRUE, FALSE, NULL );
thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
ok( thread != NULL, "CreateThread failed : (%ld)\n", GetLastError() );
if (!thread)
{
trace("Thread creation failed, skipping rest of test\n");
return;
}
WaitForSingleObject( event, INFINITE );
SuspendThread( thread );
CloseHandle( event );
ctx.ContextFlags = CONTEXT_FULL;
SetLastError(0xdeadbeef);
ok( GetThreadContext( thread, &ctx ), "GetThreadContext failed : (%ld)\n", GetLastError() );
/* simulate a call to set_test_val(10) */
stack = (int *)ctx.Esp;
stack[-1] = 10;
stack[-2] = ctx.Eip;
ctx.Esp -= 2 * sizeof(int *);
ctx.Eip = (DWORD)set_test_val;
SetLastError(0xdeadbeef);
ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%ld)\n", GetLastError() );
SetLastError(0xdeadbeef);
prevcount = ResumeThread( thread );
ok ( prevcount == 1, "Previous suspend count (%ld) instead of 1, last error : (%ld)\n",
prevcount, GetLastError() );
WaitForSingleObject( thread, INFINITE );
ok( test_value == 20, "test_value %d instead of 20\n", test_value );
}
#endif /* __i386__ */
START_TEST(thread)
{
HINSTANCE lib;
/* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
so that the compile passes
*/
lib=GetModuleHandleA("kernel32.dll");
ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
test_CreateThread_basic();
test_CreateThread_suspended();
test_SuspendThread();
test_TerminateThread();
test_CreateThread_stack();
test_thread_priority();
test_GetThreadTimes();
test_thread_processor();
test_GetThreadExitCode();
#ifdef __i386__
test_SetThreadContext();
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -