• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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
pthread_win32_process_attach_np()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
pthread_win32_process_detach_np()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
pthread_win32_thread_attach_np()192 pthread_win32_thread_attach_np ()
193 {
194   return TRUE;
195 }
196 
197 BOOL
pthread_win32_thread_detach_np()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
pthread_win32_test_features_np(int feature_mask)253 pthread_win32_test_features_np (int feature_mask)
254 {
255   return ((ptw32_features & feature_mask) == feature_mask);
256 }
257