1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*============================================================================= |
6 | ** |
7 | ** Source: test2.c |
8 | ** |
9 | ** Dependencies: PAL_Initialize |
10 | ** PAL_Terminate |
11 | ** Fail |
12 | ** CreateThread |
13 | ** SetThreadPriority |
14 | ** GetThreadPriority |
15 | ** ResumeThread |
16 | ** WaitForSingleObject |
17 | ** GetLastError |
18 | ** |
19 | ** Purpose: |
20 | ** |
21 | ** Test to ensure proper operation of the GetCurrentThread() |
22 | ** API. The test launches a thread in suspended mode, and sets |
23 | ** its priority to a non-default value using the handle returned |
24 | ** by CreateThread(). The new thread calls GetCurrentThred() to |
25 | ** retrieve a handle to itself, and calls GetThreadPriority() |
26 | ** to verify that its priority matches what it was set to on |
27 | ** the main execution thread. |
28 | ** |
29 | |
30 | ** |
31 | **===========================================================================*/ |
32 | #include <palsuite.h> |
33 | |
34 | |
35 | /* we store the return code from the child thread here because */ |
36 | /* we're missing the GetExitCodeThread() API */ |
37 | |
38 | static int g_priority = 0; |
39 | |
40 | /** |
41 | * ThreadFunc |
42 | * |
43 | * Thread function that calls GetCurrentThread() to get a pseudo-handle |
44 | * to itself, then checks its priority and exits with that value. |
45 | */ |
46 | DWORD PALAPI ThreadFunc( LPVOID param ) |
47 | { |
48 | int priority; |
49 | HANDLE hThread; |
50 | |
51 | /* call GetCurrentThread() to get a pseudo-handle to */ |
52 | /* the current thread */ |
53 | hThread = GetCurrentThread(); |
54 | if( hThread == NULL ) |
55 | { |
56 | Fail( "GetCurrentThread() call failed\n" ); |
57 | } |
58 | |
59 | |
60 | /* get the current thread priority */ |
61 | priority = GetThreadPriority( hThread ); |
62 | if( priority == THREAD_PRIORITY_ERROR_RETURN ) |
63 | { |
64 | /* GetThreadPriority call failed */ |
65 | Fail( "ERROR:%lu:GetThreadPriority() call failed\n" , GetLastError() ); |
66 | } |
67 | |
68 | /* store this globally because we don't have GetExitCodeThread() */ |
69 | g_priority = priority; |
70 | return (DWORD)priority; |
71 | } |
72 | |
73 | |
74 | /** |
75 | * main |
76 | * |
77 | * executable entry point |
78 | */ |
79 | INT __cdecl main( INT argc, CHAR **argv ) |
80 | { |
81 | HANDLE hThread = NULL; |
82 | DWORD IDThread; |
83 | DWORD dwRet; |
84 | |
85 | SIZE_T i = 0; |
86 | |
87 | /* PAL initialization */ |
88 | if( (PAL_Initialize(argc, argv)) != 0 ) |
89 | { |
90 | return( FAIL ); |
91 | } |
92 | |
93 | #if !HAVE_SCHED_OTHER_ASSIGNABLE |
94 | /* Defining thread priority for SCHED_OTHER is implementation defined. |
95 | Some platforms like NetBSD cannot reassign it as they are dynamic. |
96 | */ |
97 | printf("paltest_getcurrentthread_test2 has been disabled on this platform\n" ); |
98 | #else |
99 | /* Create multiple threads. */ |
100 | hThread = CreateThread( NULL, /* no security attributes */ |
101 | 0, /* use default stack size */ |
102 | (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */ |
103 | (LPVOID) i, /* pass thread index as */ |
104 | /* function argument */ |
105 | CREATE_SUSPENDED, /* create suspended */ |
106 | &IDThread ); /* returns thread identifier */ |
107 | |
108 | /* Check the return value for success. */ |
109 | if( hThread == NULL ) |
110 | { |
111 | /* ERROR */ |
112 | Fail( "ERROR:%lu:CreateThread failed\n" , GetLastError() ); |
113 | } |
114 | |
115 | /* set the thread priority of the new thread to the highest value */ |
116 | if( ! SetThreadPriority( hThread, THREAD_PRIORITY_TIME_CRITICAL) ) |
117 | { |
118 | Fail( "ERROR:%lu:SetThreadPriority() call failed\n" , GetLastError() ); |
119 | } |
120 | |
121 | /* let the child thread run now */ |
122 | ResumeThread( hThread ); |
123 | |
124 | |
125 | /* wait for the thread to finish */ |
126 | dwRet = WaitForSingleObject( hThread, INFINITE ); |
127 | if( dwRet == WAIT_FAILED ) |
128 | { |
129 | /* ERROR */ |
130 | Fail( "ERROR:%lu:WaitForSingleObject call failed\n" , GetLastError() ); |
131 | } |
132 | |
133 | /* validate the thread's exit code */ |
134 | if( g_priority != THREAD_PRIORITY_TIME_CRITICAL ) |
135 | { |
136 | /* ERROR */ |
137 | Fail( "FAIL:Unexpected thread priority %d returned, expected %d\n" , |
138 | g_priority, THREAD_PRIORITY_TIME_CRITICAL ); |
139 | } |
140 | #endif |
141 | |
142 | PAL_Terminate(); |
143 | return PASS; |
144 | } |
145 | |