| 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: tls.c | 
|---|
| 8 | ** | 
|---|
| 9 | ** Purpose: Test to ensure TlsAlloc, TlsGetValue, TlsSetValue | 
|---|
| 10 | **          and TlsFree are working properly together. | 
|---|
| 11 | ** | 
|---|
| 12 | ** Dependencies: PAL_Initialize | 
|---|
| 13 | **               Fail | 
|---|
| 14 | **               Sleep | 
|---|
| 15 | **               LocalAlloc | 
|---|
| 16 | **               LocalFree | 
|---|
| 17 | **               WaitForSingleObject | 
|---|
| 18 | **               CreateThread | 
|---|
| 19 | **               GetLastError | 
|---|
| 20 | ** | 
|---|
| 21 |  | 
|---|
| 22 | ** | 
|---|
| 23 | **===========================================================================*/ | 
|---|
| 24 | #include <palsuite.h> | 
|---|
| 25 |  | 
|---|
| 26 | #define NUM_OF_THREADS 10 | 
|---|
| 27 |  | 
|---|
| 28 | DWORD dwTlsIndex; /* TLS index */ | 
|---|
| 29 |  | 
|---|
| 30 | /** | 
|---|
| 31 | * CommonFunction | 
|---|
| 32 | * | 
|---|
| 33 | * Helper function that calls TlsGetValue | 
|---|
| 34 | */ | 
|---|
| 35 | VOID CommonFunction(VOID) | 
|---|
| 36 | { | 
|---|
| 37 | LPVOID lpvData; | 
|---|
| 38 | DWORD dwError; | 
|---|
| 39 |  | 
|---|
| 40 | /* Retrieve a data pointer for the current thread. */ | 
|---|
| 41 | lpvData = TlsGetValue(dwTlsIndex); | 
|---|
| 42 |  | 
|---|
| 43 | if ( (lpvData == 0) && | 
|---|
| 44 | ((dwError = GetLastError()) != NO_ERROR) ) | 
|---|
| 45 | {/*ERROR */ | 
|---|
| 46 | Fail( "TlsGetValue(%d) returned 0 with error %d\n", | 
|---|
| 47 | dwTlsIndex, | 
|---|
| 48 | dwError); | 
|---|
| 49 | } | 
|---|
| 50 |  | 
|---|
| 51 | Sleep(5000); | 
|---|
| 52 | } | 
|---|
| 53 |  | 
|---|
| 54 | /** | 
|---|
| 55 | * ThreadFunc | 
|---|
| 56 | * | 
|---|
| 57 | * Thread function that stores a value in the thread's tls slot | 
|---|
| 58 | * for the predefined tls index | 
|---|
| 59 | */ | 
|---|
| 60 | DWORD PALAPI ThreadFunc(LPVOID lpThreadParameter) | 
|---|
| 61 | { | 
|---|
| 62 | LPVOID lpvData; | 
|---|
| 63 | DWORD dwError; | 
|---|
| 64 |  | 
|---|
| 65 | /* Initialize the TLS index for this thread.*/ | 
|---|
| 66 | lpvData = (LPVOID) LocalAlloc(0, 256); | 
|---|
| 67 |  | 
|---|
| 68 | if( lpvData == NULL ) | 
|---|
| 69 | {/*ERROR */ | 
|---|
| 70 | dwError = GetLastError(); | 
|---|
| 71 | Fail( "Unexpected LocalAlloc(0, 256) failure with error %d\n", | 
|---|
| 72 | dwError); | 
|---|
| 73 | } | 
|---|
| 74 |  | 
|---|
| 75 |  | 
|---|
| 76 | if ( TlsSetValue(dwTlsIndex, lpvData) == 0 ) | 
|---|
| 77 | {/*ERROR */ | 
|---|
| 78 | dwError = GetLastError(); | 
|---|
| 79 | Fail( "TlsSetValue(%d, %x) returned 0 with error %d\n", | 
|---|
| 80 | dwTlsIndex, | 
|---|
| 81 | lpvData, | 
|---|
| 82 | dwError); | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | CommonFunction(); | 
|---|
| 86 |  | 
|---|
| 87 | /* Release the dynamic memory. */ | 
|---|
| 88 | lpvData = TlsGetValue(dwTlsIndex); | 
|---|
| 89 |  | 
|---|
| 90 | if ( (lpvData == 0) && | 
|---|
| 91 | ((dwError = GetLastError()) != NO_ERROR) ) | 
|---|
| 92 | {/*ERROR */ | 
|---|
| 93 | Fail( "TlsGetValue(%d) returned 0 with error %d\n", | 
|---|
| 94 | dwTlsIndex, | 
|---|
| 95 | dwError); | 
|---|
| 96 | } | 
|---|
| 97 | else | 
|---|
| 98 | { | 
|---|
| 99 | if( LocalFree((HLOCAL) lpvData) != NULL ) | 
|---|
| 100 | { | 
|---|
| 101 | dwError = GetLastError(); | 
|---|
| 102 | Fail( "Unexpected LocalFree(%x) failure with error %d\n", | 
|---|
| 103 | lpvData, | 
|---|
| 104 | dwError); | 
|---|
| 105 | } | 
|---|
| 106 | } | 
|---|
| 107 |  | 
|---|
| 108 | return PASS; | 
|---|
| 109 | } | 
|---|
| 110 |  | 
|---|
| 111 | /** | 
|---|
| 112 | * main | 
|---|
| 113 | * | 
|---|
| 114 | * executable entry point | 
|---|
| 115 | */ | 
|---|
| 116 | INT __cdecl main( INT argc, CHAR **argv ) | 
|---|
| 117 | { | 
|---|
| 118 | DWORD IDThread; | 
|---|
| 119 | HANDLE hThread[NUM_OF_THREADS]; | 
|---|
| 120 | int i; | 
|---|
| 121 |  | 
|---|
| 122 | /*PAL initialization */ | 
|---|
| 123 | if( (PAL_Initialize(argc, argv)) != 0 ) | 
|---|
| 124 | { | 
|---|
| 125 | return FAIL; | 
|---|
| 126 | } | 
|---|
| 127 |  | 
|---|
| 128 | /*Allocate a TLS index. */ | 
|---|
| 129 | if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) | 
|---|
| 130 | {/*RROR*/ | 
|---|
| 131 | DWORD dwError = GetLastError(); | 
|---|
| 132 | Fail( "TlsAlloc() returned error %d\n", | 
|---|
| 133 | dwError); | 
|---|
| 134 | } | 
|---|
| 135 |  | 
|---|
| 136 | /*Create multiple threads.*/ | 
|---|
| 137 |  | 
|---|
| 138 | for (i = 0; i < NUM_OF_THREADS; i++) | 
|---|
| 139 | { | 
|---|
| 140 | hThread[i] = CreateThread(NULL,       /* no security attributes*/ | 
|---|
| 141 | 0,          /* use default stack size */ | 
|---|
| 142 | ThreadFunc, /* thread function */ | 
|---|
| 143 | NULL,       /* no thread function argument */ | 
|---|
| 144 | 0,          /* use default creation flags */ | 
|---|
| 145 | &IDThread); /* returns thread identifier */ | 
|---|
| 146 |  | 
|---|
| 147 | /* Check the return value for success. */ | 
|---|
| 148 | if (hThread[i] == NULL) | 
|---|
| 149 | {/* ERROR */ | 
|---|
| 150 | DWORD dwError = GetLastError(); | 
|---|
| 151 | Fail( "Unexpected CreateThread error %d\n", | 
|---|
| 152 | dwError); | 
|---|
| 153 | } | 
|---|
| 154 | } | 
|---|
| 155 |  | 
|---|
| 156 | /* Wait for all threads to finish */ | 
|---|
| 157 | for (i = 0; i < NUM_OF_THREADS; i++) | 
|---|
| 158 | { | 
|---|
| 159 | DWORD dwRet; | 
|---|
| 160 |  | 
|---|
| 161 | dwRet = WaitForSingleObject(hThread[i], INFINITE); | 
|---|
| 162 |  | 
|---|
| 163 | if( dwRet == WAIT_FAILED ) | 
|---|
| 164 | {/* ERROR */ | 
|---|
| 165 | DWORD dwError = GetLastError(); | 
|---|
| 166 | Fail( "Unexpected WaitForSingleObject error %d\n", | 
|---|
| 167 | dwError); | 
|---|
| 168 | } | 
|---|
| 169 | } | 
|---|
| 170 |  | 
|---|
| 171 | /* Release the TLS index */ | 
|---|
| 172 | if( TlsFree( dwTlsIndex ) == 0 ) | 
|---|
| 173 | {/* ERROR */ | 
|---|
| 174 | DWORD dwError = GetLastError(); | 
|---|
| 175 | Fail( "TlsFree() returned 0 with error %d\n", | 
|---|
| 176 | dwError); | 
|---|
| 177 | } | 
|---|
| 178 |  | 
|---|
| 179 | PAL_Terminate(); | 
|---|
| 180 | return PASS; | 
|---|
| 181 | } | 
|---|
| 182 |  | 
|---|
| 183 |  | 
|---|