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
38static 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 */
46DWORD 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 */
79INT __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