thread.c
来自「一个类似windows」· C语言 代码 · 共 591 行 · 第 1/2 页
C
591 行
}
/* Double check that the thread really is suspended */
ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
"Thread did not really suspend\n");
/* Resume the thread, and make sure it actually completes */
ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
"Thread did not resume\n");
if(error!=WAIT_OBJECT_0) {
TerminateThread(thread,1);
}
/* Trying to suspend a terminated thread should fail */
error=SuspendThread(thread);
ok(error==~0UL, "wrong return code: %ld\n", error);
ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %ld\n", GetLastError());
ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
}
/* Check that TerminateThread works properly
*/
static VOID test_TerminateThread(void)
{
HANDLE thread,access_thread,event;
DWORD threadId,exitCode;
event=CreateEventA(NULL,TRUE,FALSE,NULL);
thread = CreateThread(NULL,0,threadFunc4,
(LPVOID)event, 0,&threadId);
ok(thread!=NULL,"Create Thread failed\n");
/* Terminate thread has a race condition in Wine. If the thread is terminated
before it starts, it leaves a process behind. Therefore, we wait for the
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");
}
}
}
}
START_TEST(thread)
{
HINSTANCE lib;
/* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
so that the compile passes
*/
lib=LoadLibraryA("kernel32");
ok(lib!=NULL,"Couldn't load 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();
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?