1 /* 2 * pthread_win32_attach_detach_np.c 3 * 4 * Description: 5 * This translation unit implements non-portable thread functions. 6 * 7 * -------------------------------------------------------------------------- 8 * 9 * Pthreads-win32 - POSIX Threads Library for Win32 10 * Copyright(C) 1998 John E. Bossom 11 * Copyright(C) 1999,2005 Pthreads-win32 contributors 12 * 13 * Contact Email: rpj (at) callisto.canberra.edu.au 14 * 15 * The current list of contributors is contained 16 * in the file CONTRIBUTORS included with the source 17 * code distribution. The list can also be seen at the 18 * following World Wide Web location: 19 * http://sources.redhat.com/pthreads-win32/contributors.html 20 * 21 * This library is free software; you can redistribute it and/or 22 * modify it under the terms of the GNU Lesser General Public 23 * License as published by the Free Software Foundation; either 24 * version 2 of the License, or (at your option) any later version. 25 * 26 * This library is distributed in the hope that it will be useful, 27 * but WITHOUT ANY WARRANTY; without even the implied warranty of 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 29 * Lesser General Public License for more details. 30 * 31 * You should have received a copy of the GNU Lesser General Public 32 * License along with this library in the file COPYING.LIB; 33 * if not, write to the Free Software Foundation, Inc., 34 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 35 */ 36 37 #include "pthread.h" 38 #include "implement.h" 39 40 /* 41 * Handle to quserex.dll 42 */ 43 static HINSTANCE ptw32_h_quserex; 44 45 BOOL 46 pthread_win32_process_attach_np () 47 { 48 TCHAR QuserExDLLPathBuf[1024]; 49 BOOL result = TRUE; 50 51 result = ptw32_processInitialize (); 52 53 #if defined(_UWIN) 54 pthread_count++; 55 #endif 56 57 #if defined(__GNUC__) 58 ptw32_features = 0; 59 #else 60 /* 61 * This is obsolete now. 62 */ 63 ptw32_features = PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE; 64 #endif 65 66 /* 67 * Load QUSEREX.DLL and try to get address of QueueUserAPCEx. 68 * Because QUSEREX.DLL requires a driver to be installed we will 69 * assume the DLL is in the system directory. 70 * 71 * This should take care of any security issues. 72 */ 73 #if defined(__GNUC__) || _MSC_VER < 1400 74 if(GetSystemDirectory(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf))) 75 { 76 (void) strncat(QuserExDLLPathBuf, 77 "\\QUSEREX.DLL", 78 sizeof(QuserExDLLPathBuf) - strlen(QuserExDLLPathBuf) - 1); 79 ptw32_h_quserex = LoadLibrary(QuserExDLLPathBuf); 80 } 81 #else 82 /* strncat is secure - this is just to avoid a warning */ 83 if(GetSystemDirectory(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf)) && 84 0 == strncat_s(QuserExDLLPathBuf, sizeof(QuserExDLLPathBuf), "\\QUSEREX.DLL", 12)) 85 { 86 ptw32_h_quserex = LoadLibrary(QuserExDLLPathBuf); 87 } 88 #endif 89 90 if (ptw32_h_quserex != NULL) 91 { 92 ptw32_register_cancelation = (DWORD (*)(PAPCFUNC, HANDLE, DWORD)) 93 #if defined(NEED_UNICODE_CONSTS) 94 GetProcAddress (ptw32_h_quserex, 95 (const TCHAR *) TEXT ("QueueUserAPCEx")); 96 #else 97 GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx"); 98 #endif 99 } 100 101 if (NULL == ptw32_register_cancelation) 102 { 103 ptw32_register_cancelation = ptw32_RegisterCancelation; 104 105 if (ptw32_h_quserex != NULL) 106 { 107 (void) FreeLibrary (ptw32_h_quserex); 108 } 109 ptw32_h_quserex = 0; 110 } 111 else 112 { 113 /* Initialise QueueUserAPCEx */ 114 BOOL (*queue_user_apc_ex_init) (VOID); 115 116 queue_user_apc_ex_init = (BOOL (*)(VOID)) 117 #if defined(NEED_UNICODE_CONSTS) 118 GetProcAddress (ptw32_h_quserex, 119 (const TCHAR *) TEXT ("QueueUserAPCEx_Init")); 120 #else 121 GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Init"); 122 #endif 123 124 if (queue_user_apc_ex_init == NULL || !queue_user_apc_ex_init ()) 125 { 126 ptw32_register_cancelation = ptw32_RegisterCancelation; 127 128 (void) FreeLibrary (ptw32_h_quserex); 129 ptw32_h_quserex = 0; 130 } 131 } 132 133 if (ptw32_h_quserex) 134 { 135 ptw32_features |= PTW32_ALERTABLE_ASYNC_CANCEL; 136 } 137 138 return result; 139 } 140 141 142 BOOL 143 pthread_win32_process_detach_np () 144 { 145 if (ptw32_processInitialized) 146 { 147 ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); 148 149 if (sp != NULL) 150 { 151 /* 152 * Detached threads have their resources automatically 153 * cleaned up upon exit (others must be 'joined'). 154 */ 155 if (sp->detachState == PTHREAD_CREATE_DETACHED) 156 { 157 ptw32_threadDestroy (sp->ptHandle); 158 TlsSetValue (ptw32_selfThreadKey->key, NULL); 159 } 160 } 161 162 /* 163 * The DLL is being unmapped from the process's address space 164 */ 165 ptw32_processTerminate (); 166 167 if (ptw32_h_quserex) 168 { 169 /* Close QueueUserAPCEx */ 170 BOOL (*queue_user_apc_ex_fini) (VOID); 171 172 queue_user_apc_ex_fini = (BOOL (*)(VOID)) 173 #if defined(NEED_UNICODE_CONSTS) 174 GetProcAddress (ptw32_h_quserex, 175 (const TCHAR *) TEXT ("QueueUserAPCEx_Fini")); 176 #else 177 GetProcAddress (ptw32_h_quserex, (LPCSTR) "QueueUserAPCEx_Fini"); 178 #endif 179 180 if (queue_user_apc_ex_fini != NULL) 181 { 182 (void) queue_user_apc_ex_fini (); 183 } 184 (void) FreeLibrary (ptw32_h_quserex); 185 } 186 } 187 188 return TRUE; 189 } 190 191 BOOL 192 pthread_win32_thread_attach_np () 193 { 194 return TRUE; 195 } 196 197 BOOL 198 pthread_win32_thread_detach_np () 199 { 200 if (ptw32_processInitialized) 201 { 202 /* 203 * Don't use pthread_self() - to avoid creating an implicit POSIX thread handle 204 * unnecessarily. 205 */ 206 ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey); 207 208 if (sp != NULL) // otherwise Win32 thread with no implicit POSIX handle. 209 { 210 ptw32_mcs_local_node_t stateLock; 211 ptw32_callUserDestroyRoutines (sp->ptHandle); 212 213 ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); 214 sp->state = PThreadStateLast; 215 /* 216 * If the thread is joinable at this point then it MUST be joined 217 * or detached explicitly by the application. 218 */ 219 ptw32_mcs_lock_release (&stateLock); 220 221 /* 222 * Robust Mutexes 223 */ 224 while (sp->robustMxList != NULL) 225 { 226 pthread_mutex_t mx = sp->robustMxList->mx; 227 ptw32_robust_mutex_remove(&mx, sp); 228 (void) PTW32_INTERLOCKED_EXCHANGE_LONG( 229 (PTW32_INTERLOCKED_LONGPTR)&mx->robustNode->stateInconsistent, 230 (PTW32_INTERLOCKED_LONG)-1); 231 /* 232 * If there are no waiters then the next thread to block will 233 * sleep, wakeup immediately and then go back to sleep. 234 * See pthread_mutex_lock.c. 235 */ 236 SetEvent(mx->event); 237 } 238 239 240 if (sp->detachState == PTHREAD_CREATE_DETACHED) 241 { 242 ptw32_threadDestroy (sp->ptHandle); 243 244 TlsSetValue (ptw32_selfThreadKey->key, NULL); 245 } 246 } 247 } 248 249 return TRUE; 250 } 251 252 BOOL 253 pthread_win32_test_features_np (int feature_mask) 254 { 255 return ((ptw32_features & feature_mask) == feature_mask); 256 } 257