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: test4.c (threading/tls)
8**
9** Purpose: Test to ensure that upon key creation, the value NULL
10** is associated with the new key in all active threads.
11** Upon thread creation, the value NULL is associated
12** with all defined keys in the new thread.
13**
14** Dependencies: PAL_Initialize
15** PAL_Terminate
16** LocalAlloc
17** LocalFree
18**
19
20**
21**===========================================================================*/
22#include <palsuite.h>
23
24#define NUM_OF_THREADS 10
25
26DWORD dwTlsIndex; /* TLS index */
27
28/**
29 * ThreadFunc
30 *
31 * Thread function that checks that NULL is associated with the tls index
32 */
33DWORD PALAPI ThreadFunc(VOID)
34{
35 LPVOID lpvData;
36 DWORD dwError;
37
38 /* Retrieve a data pointer for the current thread.
39 The return value should be NULL since no data has been
40 set in the index */
41 lpvData = TlsGetValue(dwTlsIndex);
42
43 if ( (lpvData != NULL) &&
44 ((dwError = GetLastError()) == NO_ERROR) )
45 {/*ERROR */
46 Fail("TlsGetValue(%d) returned data "
47 "even if no data was associated with the index\n",
48 dwTlsIndex);
49 }
50
51 return PASS;
52}
53
54/**
55 * main
56 *
57 * executable entry point
58 */
59INT __cdecl main( INT argc, CHAR **argv )
60{
61 DWORD IDThread;
62 LPVOID lpvData;
63 DWORD dwError;
64 HANDLE hThread[NUM_OF_THREADS];
65 int i;
66
67 /*PAL initialization */
68 if( (PAL_Initialize(argc, argv)) != 0 )
69 {
70 return FAIL;
71 }
72
73 /*Allocate a TLS index. */
74 if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
75 {/*ERROR*/
76 DWORD dwError = GetLastError();
77 Fail("TlsAlloc() returned error %d\n",
78 dwError);
79 }
80
81 /*Check that the value associated with the tls index is NULL*/
82 lpvData = TlsGetValue(dwTlsIndex);
83
84 if ( (lpvData != NULL) &&
85 ((dwError = GetLastError()) == NO_ERROR) )
86 {/*ERROR */
87 Fail("TlsGetValue(%d) returned non-null data "
88 "even if no data was associated with the index\n",
89 dwTlsIndex);
90 }
91
92 /*Create multiple threads.*/
93 for (i = 0; i < NUM_OF_THREADS; i++)
94 {
95 hThread[i] = CreateThread(NULL, /* no security attributes*/
96 0, /* use default stack size */
97 (LPTHREAD_START_ROUTINE) ThreadFunc, /* thread function */
98 NULL, /* no thread function argument */
99 0, /* use default creation flags */
100 &IDThread); /* returns thread identifier */
101
102 /* Check the return value for success. */
103 if (hThread[i] == NULL)
104 {/* ERROR */
105 DWORD dwError = GetLastError();
106 Fail("Unexpected CreateThread error %d\n",
107 dwError);
108 }
109 }
110
111 /* Wait for all threads to finish */
112 for (i = 0; i < NUM_OF_THREADS; i++)
113 {
114 DWORD dwRet;
115
116 dwRet = WaitForSingleObject(hThread[i], INFINITE);
117
118 if( dwRet == WAIT_FAILED )
119 {/* ERROR */
120 DWORD dwError = GetLastError();
121 Fail("Unexpected WaitForSingleObject error %d\n",
122 dwError);
123 }
124 }
125
126 /* Release the TLS index */
127 if( TlsFree( dwTlsIndex ) == 0 )
128 {/* ERROR */
129 DWORD dwError = GetLastError();
130 Fail("TlsFree() returned 0 with error %d\n",
131 dwError);
132 }
133
134 PAL_Terminate();
135 return PASS;
136}
137
138