This source file includes following definitions.
- do_init_self_key
- init_self_key
- get_current_thread_handle
- glwthread_thread_self
- wrapper_func
- glwthread_thread_create
- glwthread_thread_join
- glwthread_thread_detach
- glwthread_thread_exit
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 #include <config.h>
  21 
  22 
  23 #include "windows-thread.h"
  24 
  25 #include <errno.h>
  26 #include <process.h>
  27 #include <stdlib.h>
  28 
  29 #include "windows-once.h"
  30 #include "windows-tls.h"
  31 
  32 
  33 
  34 static DWORD self_key = (DWORD)-1;
  35 
  36 
  37 static void
  38 do_init_self_key (void)
     
  39 {
  40   self_key = TlsAlloc ();
  41   
  42   if (self_key == (DWORD)-1)
  43     abort ();
  44 }
  45 
  46 
  47 static void
  48 init_self_key (void)
     
  49 {
  50   static glwthread_once_t once = GLWTHREAD_ONCE_INIT;
  51   glwthread_once (&once, do_init_self_key);
  52 }
  53 
  54 
  55 
  56 struct glwthread_thread_struct
  57 {
  58   
  59   HANDLE volatile handle;
  60   CRITICAL_SECTION handle_lock;
  61   
  62   BOOL volatile detached;
  63   void * volatile result;
  64   
  65   void * (*func) (void *);
  66   void *arg;
  67 };
  68 
  69 
  70 static HANDLE
  71 get_current_thread_handle (void)
     
  72 {
  73   HANDLE this_handle;
  74 
  75   
  76 
  77   if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
  78                         GetCurrentProcess (), &this_handle,
  79                         0, FALSE, DUPLICATE_SAME_ACCESS))
  80     abort ();
  81   return this_handle;
  82 }
  83 
  84 glwthread_thread_t
  85 glwthread_thread_self (void)
     
  86 {
  87   glwthread_thread_t thread;
  88 
  89   if (self_key == (DWORD)-1)
  90     init_self_key ();
  91   thread = TlsGetValue (self_key);
  92   if (thread == NULL)
  93     {
  94       
  95 
  96       for (;;)
  97         {
  98           thread =
  99             (struct glwthread_thread_struct *)
 100             malloc (sizeof (struct glwthread_thread_struct));
 101           if (thread != NULL)
 102             break;
 103           
 104 
 105           Sleep (1);
 106         }
 107 
 108       thread->handle = get_current_thread_handle ();
 109       InitializeCriticalSection (&thread->handle_lock);
 110       thread->detached = FALSE; 
 111       thread->result = NULL; 
 112       TlsSetValue (self_key, thread);
 113     }
 114   return thread;
 115 }
 116 
 117 
 118 
 119 static unsigned int WINAPI
 120 wrapper_func (void *varg)
     
 121 {
 122   struct glwthread_thread_struct *thread =
 123     (struct glwthread_thread_struct *) varg;
 124 
 125   EnterCriticalSection (&thread->handle_lock);
 126   
 127 
 128   if (thread->handle == NULL)
 129     thread->handle = get_current_thread_handle ();
 130   LeaveCriticalSection (&thread->handle_lock);
 131 
 132   if (self_key == (DWORD)-1)
 133     init_self_key ();
 134   TlsSetValue (self_key, thread);
 135 
 136   
 137 
 138   thread->result = thread->func (thread->arg);
 139 
 140   
 141   glwthread_tls_process_destructors ();
 142 
 143   if (thread->detached)
 144     {
 145       
 146       DeleteCriticalSection (&thread->handle_lock);
 147       CloseHandle (thread->handle);
 148       free (thread);
 149     }
 150 
 151   return 0;
 152 }
 153 
 154 int
 155 glwthread_thread_create (glwthread_thread_t *threadp, unsigned int attr,
     
 156                          void * (*func) (void *), void *arg)
 157 {
 158   struct glwthread_thread_struct *thread =
 159     (struct glwthread_thread_struct *)
 160     malloc (sizeof (struct glwthread_thread_struct));
 161   if (thread == NULL)
 162     return ENOMEM;
 163   thread->handle = NULL;
 164   InitializeCriticalSection (&thread->handle_lock);
 165   thread->detached = (attr & GLWTHREAD_ATTR_DETACHED ? TRUE : FALSE);
 166   thread->result = NULL; 
 167   thread->func = func;
 168   thread->arg = arg;
 169 
 170   {
 171     unsigned int thread_id;
 172     HANDLE thread_handle;
 173 
 174     thread_handle = (HANDLE)
 175       _beginthreadex (NULL, 100000, wrapper_func, thread, 0, &thread_id);
 176       
 177     if (thread_handle == NULL)
 178       {
 179         DeleteCriticalSection (&thread->handle_lock);
 180         free (thread);
 181         return EAGAIN;
 182       }
 183 
 184     EnterCriticalSection (&thread->handle_lock);
 185     if (thread->handle == NULL)
 186       thread->handle = thread_handle;
 187     else
 188       
 189       CloseHandle (thread_handle);
 190     LeaveCriticalSection (&thread->handle_lock);
 191 
 192     *threadp = thread;
 193     return 0;
 194   }
 195 }
 196 
 197 int
 198 glwthread_thread_join (glwthread_thread_t thread, void **retvalp)
     
 199 {
 200   if (thread == NULL)
 201     return EINVAL;
 202 
 203   if (thread == glwthread_thread_self ())
 204     return EDEADLK;
 205 
 206   if (thread->detached)
 207     return EINVAL;
 208 
 209   if (WaitForSingleObject (thread->handle, INFINITE) == WAIT_FAILED)
 210     return EINVAL;
 211 
 212   if (retvalp != NULL)
 213     *retvalp = thread->result;
 214 
 215   DeleteCriticalSection (&thread->handle_lock);
 216   CloseHandle (thread->handle);
 217   free (thread);
 218 
 219   return 0;
 220 }
 221 
 222 int
 223 glwthread_thread_detach (glwthread_thread_t thread)
     
 224 {
 225   if (thread == NULL)
 226     return EINVAL;
 227 
 228   if (thread->detached)
 229     return EINVAL;
 230 
 231   thread->detached = TRUE;
 232   return 0;
 233 }
 234 
 235 void
 236 glwthread_thread_exit (void *retval)
     
 237 {
 238   glwthread_thread_t thread = glwthread_thread_self ();
 239   thread->result = retval;
 240   glwthread_tls_process_destructors ();
 241   _endthreadex (0); 
 242   abort ();
 243 }