1*c87b03e5Sespie /* Implementation of W32-specific threads compatibility routines for
2*c87b03e5Sespie libgcc2. */
3*c87b03e5Sespie
4*c87b03e5Sespie /* Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
5*c87b03e5Sespie Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
6*c87b03e5Sespie Modified and moved to separate file by Danny Smith
7*c87b03e5Sespie <dannysmith@users.sourceforge.net>.
8*c87b03e5Sespie
9*c87b03e5Sespie This file is part of GCC.
10*c87b03e5Sespie
11*c87b03e5Sespie GCC is free software; you can redistribute it and/or modify it under
12*c87b03e5Sespie the terms of the GNU General Public License as published by the Free
13*c87b03e5Sespie Software Foundation; either version 2, or (at your option) any later
14*c87b03e5Sespie version.
15*c87b03e5Sespie
16*c87b03e5Sespie GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17*c87b03e5Sespie WARRANTY; without even the implied warranty of MERCHANTABILITY or
18*c87b03e5Sespie FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19*c87b03e5Sespie for more details.
20*c87b03e5Sespie
21*c87b03e5Sespie You should have received a copy of the GNU General Public License
22*c87b03e5Sespie along with GCC; see the file COPYING. If not, write to the Free
23*c87b03e5Sespie Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24*c87b03e5Sespie 02111-1307, USA. */
25*c87b03e5Sespie
26*c87b03e5Sespie /* As a special exception, if you link this library with other files,
27*c87b03e5Sespie some of which are compiled with GCC, to produce an executable,
28*c87b03e5Sespie this library does not by itself cause the resulting executable
29*c87b03e5Sespie to be covered by the GNU General Public License.
30*c87b03e5Sespie This exception does not however invalidate any other reasons why
31*c87b03e5Sespie the executable file might be covered by the GNU General Public License. */
32*c87b03e5Sespie
33*c87b03e5Sespie
34*c87b03e5Sespie #ifndef __GTHREAD_HIDE_WIN32API
35*c87b03e5Sespie # define __GTHREAD_HIDE_WIN32API 1
36*c87b03e5Sespie #endif
37*c87b03e5Sespie #include <gthr-win32.h>
38*c87b03e5Sespie #include <windows.h>
39*c87b03e5Sespie
40*c87b03e5Sespie /* Windows32 threads specific definitions. The windows32 threading model
41*c87b03e5Sespie does not map well into pthread-inspired gcc's threading model, and so
42*c87b03e5Sespie there are caveats one needs to be aware of.
43*c87b03e5Sespie
44*c87b03e5Sespie 1. The destructor supplied to __gthread_key_create is ignored for
45*c87b03e5Sespie generic x86-win32 ports. This will certainly cause memory leaks
46*c87b03e5Sespie due to unreclaimed eh contexts (sizeof (eh_context) is at least
47*c87b03e5Sespie 24 bytes for x86 currently).
48*c87b03e5Sespie
49*c87b03e5Sespie This memory leak may be significant for long-running applications
50*c87b03e5Sespie that make heavy use of C++ EH.
51*c87b03e5Sespie
52*c87b03e5Sespie However, Mingw runtime (version 0.3 or newer) provides a mechanism
53*c87b03e5Sespie to emulate pthreads key dtors; the runtime provides a special DLL,
54*c87b03e5Sespie linked in if -mthreads option is specified, that runs the dtors in
55*c87b03e5Sespie the reverse order of registration when each thread exits. If
56*c87b03e5Sespie -mthreads option is not given, a stub is linked in instead of the
57*c87b03e5Sespie DLL, which results in memory leak. Other x86-win32 ports can use
58*c87b03e5Sespie the same technique of course to avoid the leak.
59*c87b03e5Sespie
60*c87b03e5Sespie 2. The error codes returned are non-POSIX like, and cast into ints.
61*c87b03e5Sespie This may cause incorrect error return due to truncation values on
62*c87b03e5Sespie hw where sizeof (DWORD) > sizeof (int).
63*c87b03e5Sespie
64*c87b03e5Sespie 3. We might consider using Critical Sections instead of Windows32
65*c87b03e5Sespie mutexes for better performance, but emulating __gthread_mutex_trylock
66*c87b03e5Sespie interface becomes more complicated (Win9x does not support
67*c87b03e5Sespie TryEnterCriticalSectioni, while NT does).
68*c87b03e5Sespie
69*c87b03e5Sespie The basic framework should work well enough. In the long term, GCC
70*c87b03e5Sespie needs to use Structured Exception Handling on Windows32. */
71*c87b03e5Sespie
72*c87b03e5Sespie int
__gthr_win32_once(__gthread_once_t * once,void (* func)(void))73*c87b03e5Sespie __gthr_win32_once (__gthread_once_t *once, void (*func) (void))
74*c87b03e5Sespie {
75*c87b03e5Sespie if (once == NULL || func == NULL)
76*c87b03e5Sespie return EINVAL;
77*c87b03e5Sespie
78*c87b03e5Sespie if (! once->done)
79*c87b03e5Sespie {
80*c87b03e5Sespie if (InterlockedIncrement (&(once->started)) == 0)
81*c87b03e5Sespie {
82*c87b03e5Sespie (*func) ();
83*c87b03e5Sespie once->done = TRUE;
84*c87b03e5Sespie }
85*c87b03e5Sespie else
86*c87b03e5Sespie {
87*c87b03e5Sespie /* Another thread is currently executing the code, so wait for it
88*c87b03e5Sespie to finish; yield the CPU in the meantime. If performance
89*c87b03e5Sespie does become an issue, the solution is to use an Event that
90*c87b03e5Sespie we wait on here (and set above), but that implies a place to
91*c87b03e5Sespie create the event before this routine is called. */
92*c87b03e5Sespie while (! once->done)
93*c87b03e5Sespie Sleep (0);
94*c87b03e5Sespie }
95*c87b03e5Sespie }
96*c87b03e5Sespie return 0;
97*c87b03e5Sespie }
98*c87b03e5Sespie
99*c87b03e5Sespie /* Windows32 thread local keys don't support destructors; this leads to
100*c87b03e5Sespie leaks, especially in threaded applications making extensive use of
101*c87b03e5Sespie C++ EH. Mingw uses a thread-support DLL to work-around this problem. */
102*c87b03e5Sespie
103*c87b03e5Sespie int
__gthr_win32_key_create(__gthread_key_t * key,void (* dtor)(void *))104*c87b03e5Sespie __gthr_win32_key_create (__gthread_key_t *key, void (*dtor) (void *))
105*c87b03e5Sespie {
106*c87b03e5Sespie int status = 0;
107*c87b03e5Sespie DWORD tls_index = TlsAlloc ();
108*c87b03e5Sespie if (tls_index != 0xFFFFFFFF)
109*c87b03e5Sespie {
110*c87b03e5Sespie *key = tls_index;
111*c87b03e5Sespie #ifdef MINGW32_SUPPORTS_MT_EH
112*c87b03e5Sespie /* Mingw runtime will run the dtors in reverse order for each thread
113*c87b03e5Sespie when the thread exits. */
114*c87b03e5Sespie status = __mingwthr_key_dtor (*key, dtor);
115*c87b03e5Sespie #endif
116*c87b03e5Sespie }
117*c87b03e5Sespie else
118*c87b03e5Sespie status = (int) GetLastError ();
119*c87b03e5Sespie return status;
120*c87b03e5Sespie }
121*c87b03e5Sespie
122*c87b03e5Sespie int
__gthr_win32_key_delete(__gthread_key_t key)123*c87b03e5Sespie __gthr_win32_key_delete (__gthread_key_t key)
124*c87b03e5Sespie {
125*c87b03e5Sespie return (TlsFree (key) != 0) ? 0 : (int) GetLastError ();
126*c87b03e5Sespie }
127*c87b03e5Sespie
128*c87b03e5Sespie void *
__gthr_win32_getspecific(__gthread_key_t key)129*c87b03e5Sespie __gthr_win32_getspecific (__gthread_key_t key)
130*c87b03e5Sespie {
131*c87b03e5Sespie DWORD lasterror;
132*c87b03e5Sespie void *ptr;
133*c87b03e5Sespie lasterror = GetLastError();
134*c87b03e5Sespie ptr = TlsGetValue(key);
135*c87b03e5Sespie SetLastError( lasterror );
136*c87b03e5Sespie return ptr;
137*c87b03e5Sespie }
138*c87b03e5Sespie
139*c87b03e5Sespie int
__gthr_win32_setspecific(__gthread_key_t key,const void * ptr)140*c87b03e5Sespie __gthr_win32_setspecific (__gthread_key_t key, const void *ptr)
141*c87b03e5Sespie {
142*c87b03e5Sespie return (TlsSetValue (key, (void*) ptr) != 0) ? 0 : (int) GetLastError ();
143*c87b03e5Sespie }
144*c87b03e5Sespie
145*c87b03e5Sespie void
__gthr_win32_mutex_init_function(__gthread_mutex_t * mutex)146*c87b03e5Sespie __gthr_win32_mutex_init_function (__gthread_mutex_t *mutex)
147*c87b03e5Sespie {
148*c87b03e5Sespie /* Create unnamed mutex with default security attr and no initial owner. */
149*c87b03e5Sespie *mutex = CreateMutex (NULL, 0, NULL);
150*c87b03e5Sespie }
151*c87b03e5Sespie
152*c87b03e5Sespie int
__gthr_win32_mutex_lock(__gthread_mutex_t * mutex)153*c87b03e5Sespie __gthr_win32_mutex_lock (__gthread_mutex_t *mutex)
154*c87b03e5Sespie {
155*c87b03e5Sespie if (WaitForSingleObject (*mutex, INFINITE) == WAIT_OBJECT_0)
156*c87b03e5Sespie return 0;
157*c87b03e5Sespie else
158*c87b03e5Sespie return 1;
159*c87b03e5Sespie }
160*c87b03e5Sespie
161*c87b03e5Sespie int
__gthr_win32_mutex_trylock(__gthread_mutex_t * mutex)162*c87b03e5Sespie __gthr_win32_mutex_trylock (__gthread_mutex_t *mutex)
163*c87b03e5Sespie {
164*c87b03e5Sespie if (WaitForSingleObject (*mutex, 0) == WAIT_OBJECT_0)
165*c87b03e5Sespie return 0;
166*c87b03e5Sespie else
167*c87b03e5Sespie return 1;
168*c87b03e5Sespie }
169*c87b03e5Sespie
170*c87b03e5Sespie int
__gthr_win32_mutex_unlock(__gthread_mutex_t * mutex)171*c87b03e5Sespie __gthr_win32_mutex_unlock (__gthread_mutex_t *mutex)
172*c87b03e5Sespie {
173*c87b03e5Sespie return (ReleaseMutex (*mutex) != 0) ? 0 : 1;
174*c87b03e5Sespie }
175