gthr-win32.c revision 146895
1163953Srrs/* Implementation of W32-specific threads compatibility routines for 2169382Srrs libgcc2. */ 3235828Stuexen 4235828Stuexen/* Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation, Inc. 5163953Srrs Contributed by Mumit Khan <khan@xraylith.wisc.edu>. 6163953Srrs Modified and moved to separate file by Danny Smith 7163953Srrs <dannysmith@users.sourceforge.net>. 8163953Srrs 9163953SrrsThis file is part of GCC. 10228653Stuexen 11163953SrrsGCC is free software; you can redistribute it and/or modify it under 12163953Srrsthe terms of the GNU General Public License as published by the Free 13163953SrrsSoftware Foundation; either version 2, or (at your option) any later 14228653Stuexenversion. 15163953Srrs 16163953SrrsGCC is distributed in the hope that it will be useful, but WITHOUT ANY 17163953SrrsWARRANTY; without even the implied warranty of MERCHANTABILITY or 18163953SrrsFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19163953Srrsfor more details. 20163953Srrs 21163953SrrsYou should have received a copy of the GNU General Public License 22163953Srrsalong with GCC; see the file COPYING. If not, write to the Free 23163953SrrsSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 24163953Srrs02111-1307, USA. */ 25163953Srrs 26163953Srrs/* As a special exception, if you link this library with other files, 27163953Srrs some of which are compiled with GCC, to produce an executable, 28163953Srrs this library does not by itself cause the resulting executable 29163953Srrs to be covered by the GNU General Public License. 30163953Srrs This exception does not however invalidate any other reasons why 31163953Srrs the executable file might be covered by the GNU General Public License. */ 32163953Srrs 33163953Srrs 34163953Srrs#include <windows.h> 35163953Srrs#ifndef __GTHREAD_HIDE_WIN32API 36163953Srrs# define __GTHREAD_HIDE_WIN32API 1 37163953Srrs#endif 38163953Srrs#undef __GTHREAD_I486_INLINE_LOCK_PRIMITIVES 39163953Srrs#define __GTHREAD_I486_INLINE_LOCK_PRIMITIVES 40163953Srrs#include <gthr-win32.h> 41163953Srrs 42163953Srrs/* Windows32 threads specific definitions. The windows32 threading model 43163953Srrs does not map well into pthread-inspired gcc's threading model, and so 44163953Srrs there are caveats one needs to be aware of. 45163953Srrs 46163953Srrs 1. The destructor supplied to __gthread_key_create is ignored for 47169208Srrs generic x86-win32 ports. This will certainly cause memory leaks 48163953Srrs due to unreclaimed eh contexts (sizeof (eh_context) is at least 49167598Srrs 24 bytes for x86 currently). 50163953Srrs 51170091Srrs This memory leak may be significant for long-running applications 52170091Srrs that make heavy use of C++ EH. 53170091Srrs 54170091Srrs However, Mingw runtime (version 0.3 or newer) provides a mechanism 55170091Srrs to emulate pthreads key dtors; the runtime provides a special DLL, 56170091Srrs linked in if -mthreads option is specified, that runs the dtors in 57170091Srrs the reverse order of registration when each thread exits. If 58170091Srrs -mthreads option is not given, a stub is linked in instead of the 59170091Srrs DLL, which results in memory leak. Other x86-win32 ports can use 60170091Srrs the same technique of course to avoid the leak. 61170091Srrs 62170091Srrs 2. The error codes returned are non-POSIX like, and cast into ints. 63170091Srrs This may cause incorrect error return due to truncation values on 64170091Srrs hw where sizeof (DWORD) > sizeof (int). 65170091Srrs 66170091Srrs 3. We are currently using a special mutex instead of the Critical 67170091Srrs Sections, since Win9x does not support TryEnterCriticalSection 68170091Srrs (while NT does). 69170091Srrs 70170091Srrs The basic framework should work well enough. In the long term, GCC 71218211Srrs needs to use Structured Exception Handling on Windows32. */ 72170091Srrs 73208160Srrsint 74208160Srrs__gthr_win32_once (__gthread_once_t *once, void (*func) (void)) 75208160Srrs{ 76208160Srrs if (once == NULL || func == NULL) 77167598Srrs return EINVAL; 78167598Srrs 79163953Srrs if (! once->done) 80208160Srrs { 81163953Srrs if (InterlockedIncrement (&(once->started)) == 0) 82163953Srrs { 83167598Srrs (*func) (); 84228653Stuexen once->done = TRUE; 85163953Srrs } 86167598Srrs else 87225676Stuexen { 88228653Stuexen /* Another thread is currently executing the code, so wait for it 89208160Srrs to finish; yield the CPU in the meantime. If performance 90208160Srrs does become an issue, the solution is to use an Event that 91175751Srrs we wait on here (and set above), but that implies a place to 92167598Srrs create the event before this routine is called. */ 93163953Srrs while (! once->done) 94163953Srrs Sleep (0); 95163953Srrs } 96167598Srrs } 97167598Srrs return 0; 98163953Srrs} 99258221Stuexen 100208160Srrs/* Windows32 thread local keys don't support destructors; this leads to 101208160Srrs leaks, especially in threaded applications making extensive use of 102208160Srrs C++ EH. Mingw uses a thread-support DLL to work-around this problem. */ 103258765Stuexen 104258765Stuexenint 105258765Stuexen__gthr_win32_key_create (__gthread_key_t *key, void (*dtor) (void *)) 106208160Srrs{ 107258221Stuexen int status = 0; 108208160Srrs DWORD tls_index = TlsAlloc (); 109208160Srrs if (tls_index != 0xFFFFFFFF) 110167598Srrs { 111167598Srrs *key = tls_index; 112167598Srrs#ifdef MINGW32_SUPPORTS_MT_EH 113163953Srrs /* Mingw runtime will run the dtors in reverse order for each thread 114163953Srrs when the thread exits. */ 115178251Srrs status = __mingwthr_key_dtor (*key, dtor); 116180387Srrs#endif 117167598Srrs } 118167598Srrs else 119163953Srrs status = (int) GetLastError (); 120167598Srrs return status; 121163953Srrs} 122167598Srrs 123167598Srrsint 124197288Srrs__gthr_win32_key_delete (__gthread_key_t key) 125167598Srrs{ 126167598Srrs return (TlsFree (key) != 0) ? 0 : (int) GetLastError (); 127167598Srrs} 128167598Srrs 129167598Srrsvoid * 130163953Srrs__gthr_win32_getspecific (__gthread_key_t key) 131163953Srrs{ 132167598Srrs DWORD lasterror; 133163953Srrs void *ptr; 134167598Srrs lasterror = GetLastError(); 135167598Srrs ptr = TlsGetValue(key); 136167598Srrs SetLastError( lasterror ); 137167598Srrs return ptr; 138167598Srrs} 139163953Srrs 140167598Srrsint 141163953Srrs__gthr_win32_setspecific (__gthread_key_t key, const void *ptr) 142163953Srrs{ 143163953Srrs return (TlsSetValue (key, (void*) ptr) != 0) ? 0 : (int) GetLastError (); 144180387Srrs} 145163953Srrs 146163953Srrsvoid 147167598Srrs__gthr_win32_mutex_init_function (__gthread_mutex_t *mutex) 148239035Stuexen{ 149163953Srrs mutex->counter = -1; 150167598Srrs mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL); 151163953Srrs} 152167598Srrs 153239035Stuexenint 154167598Srrs__gthr_win32_mutex_lock (__gthread_mutex_t *mutex) 155167598Srrs{ 156167598Srrs if (InterlockedIncrement (&mutex->counter) == 0 || 157167598Srrs WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0) 158167598Srrs return 0; 159167598Srrs else 160167598Srrs { 161167598Srrs /* WaitForSingleObject returns WAIT_FAILED, and we can only do 162167598Srrs some best-effort cleanup here. */ 163167598Srrs InterlockedDecrement (&mutex->counter); 164167598Srrs return 1; 165167598Srrs } 166167598Srrs} 167167598Srrs 168172091Srrsint 169167598Srrs__gthr_win32_mutex_trylock (__gthread_mutex_t *mutex) 170167598Srrs{ 171167598Srrs if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0) 172179783Srrs return 0; 173196610Stuexen else 174232724Stuexen return 1; 175167598Srrs} 176167598Srrs 177167598Srrsint 178232866Srrs__gthr_win32_mutex_unlock (__gthread_mutex_t *mutex) 179167598Srrs{ 180167598Srrs if (InterlockedDecrement (&mutex->counter) >= 0) 181167598Srrs return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1; 182167598Srrs else 183167598Srrs return 0; 184163953Srrs} 185163953Srrs