Home | History | Annotate | Line # | Download | only in i386
gthr-win32-thread.c revision 1.1
      1  1.1  mrg /* Implementation of threads compatibility routines for libgcc2.  */
      2  1.1  mrg 
      3  1.1  mrg /* Copyright (C) 1999-2024 Free Software Foundation, Inc.
      4  1.1  mrg 
      5  1.1  mrg This file is part of GCC.
      6  1.1  mrg 
      7  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      8  1.1  mrg the terms of the GNU General Public License as published by the Free
      9  1.1  mrg Software Foundation; either version 3, or (at your option) any later
     10  1.1  mrg version.
     11  1.1  mrg 
     12  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     13  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  1.1  mrg for more details.
     16  1.1  mrg 
     17  1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     18  1.1  mrg permissions described in the GCC Runtime Library Exception, version
     19  1.1  mrg 3.1, as published by the Free Software Foundation.
     20  1.1  mrg 
     21  1.1  mrg You should have received a copy of the GNU General Public License and
     22  1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     23  1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24  1.1  mrg <http://www.gnu.org/licenses/>.  */
     25  1.1  mrg 
     26  1.1  mrg /* This module is separate from the rest of the implementation because only
     27  1.1  mrg    one copy of it ought to be linked.  */
     28  1.1  mrg 
     29  1.1  mrg /* The implementation strategy for the c++0x thread support is as follows.
     30  1.1  mrg 
     31  1.1  mrg    A GNU thread is represented by a Win32 HANDLE that is obtained when the
     32  1.1  mrg    Win32 thread is created, except of course for the initial thread.  This
     33  1.1  mrg    Win32 HANDLE is stored in a descriptor keyed from TLS memory for every
     34  1.1  mrg    thread, so the self routine can return it instead of having to duplicate
     35  1.1  mrg    the pseudo-handle returned by GetCurrentThread each time it is invoked.
     36  1.1  mrg    For the initial thread, this Win32 HANDLE is created during the first
     37  1.1  mrg    call to the self routine using the aforementioned technique.
     38  1.1  mrg 
     39  1.1  mrg    Note that the equal routine compares the identifier of threads instead
     40  1.1  mrg    of their Win32 HANDLE, which will give the correct positive answer even
     41  1.1  mrg    in the case where distinct Win32 HANDLEs have been created for the same
     42  1.1  mrg    thread by multiple instances of libgcc included in the link.  */
     43  1.1  mrg 
     44  1.1  mrg #include "gthr-win32.h"
     45  1.1  mrg 
     46  1.1  mrg /* The thread descriptor keyed from TLS memory.  */
     47  1.1  mrg struct __gthr_win32_thr_desc
     48  1.1  mrg {
     49  1.1  mrg   void *(*func) (void*);
     50  1.1  mrg   void *args;
     51  1.1  mrg   HANDLE h;
     52  1.1  mrg };
     53  1.1  mrg 
     54  1.1  mrg /* The TLS key used by one instance of the library.  */
     55  1.1  mrg static __gthread_key_t __gthr_win32_tls = TLS_OUT_OF_INDEXES;
     56  1.1  mrg 
     57  1.1  mrg /* The initialization device for the TLS key.  */
     58  1.1  mrg static __gthread_once_t __gthr_win32_tls_once = __GTHREAD_ONCE_INIT;
     59  1.1  mrg 
     60  1.1  mrg /* Initialize the TLS key.  */
     61  1.1  mrg 
     62  1.1  mrg static void
     63  1.1  mrg __gthr_win32_tls_init (void)
     64  1.1  mrg {
     65  1.1  mrg   if (__gthread_key_create (&__gthr_win32_tls, free))
     66  1.1  mrg     abort ();
     67  1.1  mrg }
     68  1.1  mrg 
     69  1.1  mrg /* Wrapper routine around thread functions.  */
     70  1.1  mrg 
     71  1.1  mrg static DWORD
     72  1.1  mrg __gthr_win32_thread_wrapper (void *args)
     73  1.1  mrg {
     74  1.1  mrg   struct __gthr_win32_thr_desc *td = (struct __gthr_win32_thr_desc *) args;
     75  1.1  mrg 
     76  1.1  mrg   __gthread_setspecific (__gthr_win32_tls, td);
     77  1.1  mrg 
     78  1.1  mrg   DWORD exit_code = (DWORD) (ULONG_PTR) (*td->func) (td->args);
     79  1.1  mrg 
     80  1.1  mrg   ExitThread (exit_code);
     81  1.1  mrg   return exit_code;
     82  1.1  mrg }
     83  1.1  mrg 
     84  1.1  mrg /* Implement the __gthread_create routine.  */
     85  1.1  mrg 
     86  1.1  mrg int
     87  1.1  mrg __gthr_win32_create (__gthread_t *thr, void *(*func) (void*), void *args)
     88  1.1  mrg {
     89  1.1  mrg   struct __gthr_win32_thr_desc *td;
     90  1.1  mrg 
     91  1.1  mrg   __gthread_once (&__gthr_win32_tls_once, __gthr_win32_tls_init);
     92  1.1  mrg 
     93  1.1  mrg   td = malloc (sizeof (struct __gthr_win32_thr_desc));
     94  1.1  mrg   td->func = func;
     95  1.1  mrg   td->args = args;
     96  1.1  mrg   td->h = CreateThread (NULL, 0,
     97  1.1  mrg 			(LPTHREAD_START_ROUTINE) __gthr_win32_thread_wrapper,
     98  1.1  mrg 			(LPVOID) td, CREATE_SUSPENDED, NULL);
     99  1.1  mrg   if (td->h)
    100  1.1  mrg     {
    101  1.1  mrg       ResumeThread (td->h);
    102  1.1  mrg       *thr = (__gthread_t) td->h;
    103  1.1  mrg       return 0;
    104  1.1  mrg     }
    105  1.1  mrg   else
    106  1.1  mrg     {
    107  1.1  mrg       free (td);
    108  1.1  mrg       return (int) GetLastError ();
    109  1.1  mrg     }
    110  1.1  mrg }
    111  1.1  mrg 
    112  1.1  mrg /* Implement the __gthread_join routine.  */
    113  1.1  mrg 
    114  1.1  mrg int
    115  1.1  mrg __gthr_win32_join (__gthread_t thr, void **value_ptr)
    116  1.1  mrg {
    117  1.1  mrg   int status = 0;
    118  1.1  mrg 
    119  1.1  mrg   if (GetThreadId ((HANDLE) thr) == GetCurrentThreadId ())
    120  1.1  mrg     return 1;
    121  1.1  mrg 
    122  1.1  mrg   if (WaitForSingleObject ((HANDLE) thr, INFINITE) == WAIT_OBJECT_0)
    123  1.1  mrg     {
    124  1.1  mrg       if (value_ptr)
    125  1.1  mrg 	{
    126  1.1  mrg 	  DWORD exit_code;
    127  1.1  mrg 	  if (GetExitCodeThread ((HANDLE) thr, &exit_code))
    128  1.1  mrg 	    *value_ptr = (void *) (ULONG_PTR) exit_code;
    129  1.1  mrg 	  else
    130  1.1  mrg 	    status = (int) GetLastError ();
    131  1.1  mrg 	}
    132  1.1  mrg     }
    133  1.1  mrg   else
    134  1.1  mrg     status = (int) GetLastError ();
    135  1.1  mrg 
    136  1.1  mrg   CloseHandle ((HANDLE) thr);
    137  1.1  mrg   return status;
    138  1.1  mrg }
    139  1.1  mrg 
    140  1.1  mrg /* Implement the __gthread_self routine.  */
    141  1.1  mrg 
    142  1.1  mrg __gthread_t
    143  1.1  mrg __gthr_win32_self (void)
    144  1.1  mrg {
    145  1.1  mrg   struct __gthr_win32_thr_desc *td;
    146  1.1  mrg 
    147  1.1  mrg   __gthread_once (&__gthr_win32_tls_once, __gthr_win32_tls_init);
    148  1.1  mrg 
    149  1.1  mrg   if (!(td = __gthread_getspecific (__gthr_win32_tls)))
    150  1.1  mrg     {
    151  1.1  mrg       HANDLE proc = GetCurrentProcess ();
    152  1.1  mrg       td = malloc (sizeof (struct __gthr_win32_thr_desc));
    153  1.1  mrg       td->func = NULL;
    154  1.1  mrg       td->args = NULL;
    155  1.1  mrg       if (!DuplicateHandle (proc, GetCurrentThread(), proc, &td->h, 0, FALSE,
    156  1.1  mrg 			    DUPLICATE_SAME_ACCESS))
    157  1.1  mrg 	abort ();
    158  1.1  mrg       __gthread_setspecific (__gthr_win32_tls, td);
    159  1.1  mrg     }
    160  1.1  mrg 
    161  1.1  mrg   return td->h;
    162  1.1  mrg }
    163