Home | History | Annotate | Download | only in pthreads-win32
      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