00001 /* Implementation of W32-specific threads compatibility routines for 00002 libgcc2. */ 00003 00004 /* Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. 00005 Contributed by Mumit Khan <khan@xraylith.wisc.edu>. 00006 Modified and moved to separate file by Danny Smith 00007 <dannysmith@users.sourceforge.net>. 00008 00009 This file is part of GCC. 00010 00011 GCC is free software; you can redistribute it and/or modify it under 00012 the terms of the GNU General Public License as published by the Free 00013 Software Foundation; either version 2, or (at your option) any later 00014 version. 00015 00016 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 00017 WARRANTY; without even the implied warranty of MERCHANTABILITY or 00018 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00019 for more details. 00020 00021 You should have received a copy of the GNU General Public License 00022 along with GCC; see the file COPYING. If not, write to the Free 00023 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 00024 02111-1307, USA. */ 00025 00026 /* As a special exception, if you link this library with other files, 00027 some of which are compiled with GCC, to produce an executable, 00028 this library does not by itself cause the resulting executable 00029 to be covered by the GNU General Public License. 00030 This exception does not however invalidate any other reasons why 00031 the executable file might be covered by the GNU General Public License. */ 00032 00033 00034 #ifndef __GTHREAD_HIDE_WIN32API 00035 # define __GTHREAD_HIDE_WIN32API 1 00036 #endif 00037 #include <gthr-win32.h> 00038 #include <windows.h> 00039 00040 /* Windows32 threads specific definitions. The windows32 threading model 00041 does not map well into pthread-inspired gcc's threading model, and so 00042 there are caveats one needs to be aware of. 00043 00044 1. The destructor supplied to __gthread_key_create is ignored for 00045 generic x86-win32 ports. This will certainly cause memory leaks 00046 due to unreclaimed eh contexts (sizeof (eh_context) is at least 00047 24 bytes for x86 currently). 00048 00049 This memory leak may be significant for long-running applications 00050 that make heavy use of C++ EH. 00051 00052 However, Mingw runtime (version 0.3 or newer) provides a mechanism 00053 to emulate pthreads key dtors; the runtime provides a special DLL, 00054 linked in if -mthreads option is specified, that runs the dtors in 00055 the reverse order of registration when each thread exits. If 00056 -mthreads option is not given, a stub is linked in instead of the 00057 DLL, which results in memory leak. Other x86-win32 ports can use 00058 the same technique of course to avoid the leak. 00059 00060 2. The error codes returned are non-POSIX like, and cast into ints. 00061 This may cause incorrect error return due to truncation values on 00062 hw where sizeof (DWORD) > sizeof (int). 00063 00064 3. We might consider using Critical Sections instead of Windows32 00065 mutexes for better performance, but emulating __gthread_mutex_trylock 00066 interface becomes more complicated (Win9x does not support 00067 TryEnterCriticalSectioni, while NT does). 00068 00069 The basic framework should work well enough. In the long term, GCC 00070 needs to use Structured Exception Handling on Windows32. */ 00071 00072 int 00073 __gthr_win32_once (__gthread_once_t *once, void (*func) (void)) 00074 { 00075 if (once == NULL || func == NULL) 00076 return EINVAL; 00077 00078 if (! once->done) 00079 { 00080 if (InterlockedIncrement (&(once->started)) == 0) 00081 { 00082 (*func) (); 00083 once->done = TRUE; 00084 } 00085 else 00086 { 00087 /* Another thread is currently executing the code, so wait for it 00088 to finish; yield the CPU in the meantime. If performance 00089 does become an issue, the solution is to use an Event that 00090 we wait on here (and set above), but that implies a place to 00091 create the event before this routine is called. */ 00092 while (! once->done) 00093 Sleep (0); 00094 } 00095 } 00096 return 0; 00097 } 00098 00099 /* Windows32 thread local keys don't support destructors; this leads to 00100 leaks, especially in threaded applications making extensive use of 00101 C++ EH. Mingw uses a thread-support DLL to work-around this problem. */ 00102 00103 int 00104 __gthr_win32_key_create (__gthread_key_t *key, void (*dtor) (void *)) 00105 { 00106 int status = 0; 00107 DWORD tls_index = TlsAlloc (); 00108 if (tls_index != 0xFFFFFFFF) 00109 { 00110 *key = tls_index; 00111 #ifdef MINGW32_SUPPORTS_MT_EH 00112 /* Mingw runtime will run the dtors in reverse order for each thread 00113 when the thread exits. */ 00114 status = __mingwthr_key_dtor (*key, dtor); 00115 #endif 00116 } 00117 else 00118 status = (int) GetLastError (); 00119 return status; 00120 } 00121 00122 int 00123 __gthr_win32_key_delete (__gthread_key_t key) 00124 { 00125 return (TlsFree (key) != 0) ? 0 : (int) GetLastError (); 00126 } 00127 00128 void * 00129 __gthr_win32_getspecific (__gthread_key_t key) 00130 { 00131 DWORD lasterror; 00132 void *ptr; 00133 lasterror = GetLastError(); 00134 ptr = TlsGetValue(key); 00135 SetLastError( lasterror ); 00136 return ptr; 00137 } 00138 00139 int 00140 __gthr_win32_setspecific (__gthread_key_t key, const void *ptr) 00141 { 00142 return (TlsSetValue (key, (void*) ptr) != 0) ? 0 : (int) GetLastError (); 00143 } 00144 00145 void 00146 __gthr_win32_mutex_init_function (__gthread_mutex_t *mutex) 00147 { 00148 /* Create unnamed mutex with default security attr and no initial owner. */ 00149 *mutex = CreateMutex (NULL, 0, NULL); 00150 } 00151 00152 int 00153 __gthr_win32_mutex_lock (__gthread_mutex_t *mutex) 00154 { 00155 if (WaitForSingleObject (*mutex, INFINITE) == WAIT_OBJECT_0) 00156 return 0; 00157 else 00158 return 1; 00159 } 00160 00161 int 00162 __gthr_win32_mutex_trylock (__gthread_mutex_t *mutex) 00163 { 00164 if (WaitForSingleObject (*mutex, 0) == WAIT_OBJECT_0) 00165 return 0; 00166 else 00167 return 1; 00168 } 00169 00170 int 00171 __gthr_win32_mutex_unlock (__gthread_mutex_t *mutex) 00172 { 00173 return (ReleaseMutex (*mutex) != 0) ? 0 : 1; 00174 }
1.5.6