diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 17c0715dc5b3..6c28aeb3be21 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2009-05-30 Kai Tietz + + * config/i386/mingw-tls.c: New file. + * config/i386/t-gthr-win32 (LIB2FUNCS_EXTRA): Add + mingw-tls.c file. + * gthr-win32.h (MINGW32_SUPPORTS_MT_EH): Define + it for targets defining _WIN32 but not __CYGWIN__. + 2009-05-29 Kaveh R. Ghazi * configure.ac: Add MPC support. diff --git a/gcc/config/i386/mingw-tls.c b/gcc/config/i386/mingw-tls.c new file mode 100644 index 000000000000..7a5c7758b2ea --- /dev/null +++ b/gcc/config/i386/mingw-tls.c @@ -0,0 +1,233 @@ +/* Catch and clean up data allocated in TLS. + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2009 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +/* This part is based on the implementation of Mumit Khan + * provided to mingw under public domain and ported for libgcc by Kai Tietz. + */ + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include + +/* The list of threads active with key/dtor pairs. */ +typedef struct __mingwthr_key { + DWORD key; + void (*dtor) (void *); + struct __mingwthr_key *next; +} __mingwthr_key_t; + +#if defined(_WIN32) && !defined(__CYGWIN__) + +/* Possibly we could define this here for none MT too and avoid use of + mingwthrd.a at all, but well ... */ +#ifdef SHARED +__declspec(dllexport) +int _CRT_MT = 1; +#else +#if 0 +int _CRT_MT = 0; +#endif +#endif + +/* Static functions for libgcc. */ +#ifndef SHARED + +int __mingwthr_key_dtor (DWORD,void (*dtor)(void *)); +int __mingwthr_remove_key_dtor (DWORD); + + +int +__mingwthr_key_dtor (DWORD key __attribute__ ((__unused__)), + void (*dtor) (void *) __attribute__ ((__unused__))) +{ + return 0; +} + +int +__mingwthr_remove_key_dtor (DWORD key __attribute__ ((__unused__))) +{ + return 0; +} + +#else +/* Shared functions for libgcc. */ + +/* Prototypes. */ +__declspec(dllexport) int __mingwthr_key_dtor (DWORD key, void (*) (void *)); +__declspec(dllexport) int __mingwthr_remove_key_dtor (DWORD); +BOOL APIENTRY DllMain (HANDLE, DWORD, LPVOID); + + +/* To protect the thread/key association data structure modifications. */ +static CRITICAL_SECTION __mingwthr_cs; +static __mingwthr_key_t *key_dtor_list; + +/* + * __mingwthr_key_add: + * + * Add key/dtor association for this thread. If the thread entry does not + * exist, create a new one and add to the head of the threads list; add + * the new assoc at the head of the keys list. + * + */ + +static int +___mingwthr_add_key_dtor (DWORD key, void (*dtor) (void *)) +{ + __mingwthr_key_t *new_key; + + new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t)); + if (new_key == NULL) + return -1; + + new_key->key = key; + new_key->dtor = dtor; + + EnterCriticalSection (&__mingwthr_cs); + + new_key->next = key_dtor_list; + key_dtor_list = new_key; + + LeaveCriticalSection (&__mingwthr_cs); + + return 0; +} + +static int +___mingwthr_remove_key_dtor (DWORD key) +{ + __mingwthr_key_t *prev_key; + __mingwthr_key_t *cur_key; + + EnterCriticalSection (&__mingwthr_cs); + + prev_key = NULL; + cur_key = key_dtor_list; + + while (cur_key != NULL) + { + if( cur_key->key == key ) + { + /* take key/dtor out of list */ + if (prev_key == NULL) + key_dtor_list = cur_key->next; + else + prev_key->next = cur_key->next; + + free (cur_key); + break; + } + + prev_key = cur_key; + cur_key = cur_key->next; + } + + LeaveCriticalSection (&__mingwthr_cs); + + return 0; +} + +/* + * __mingwthr_run_key_dtors (void): + * + * Callback from DllMain when thread detaches to clean up the key + * storage. + * + * Note that this does not delete the key itself, but just runs + * the dtor if the current value are both non-NULL. Note that the + * keys with NULL dtors are not added by __mingwthr_key_dtor, the + * only public interface, so we don't need to check. + * + */ + +static void +__mingwthr_run_key_dtors (void) +{ + __mingwthr_key_t *keyp; + + EnterCriticalSection (&__mingwthr_cs); + + for (keyp = key_dtor_list; keyp; ) + { + LPVOID value = TlsGetValue (keyp->key); + if (GetLastError () == ERROR_SUCCESS) + { + if (value) + (*keyp->dtor) (value); + } + keyp = keyp->next; + } + + LeaveCriticalSection (&__mingwthr_cs); +} + +/* + * __mingwthr_register_key_dtor (DWORD key, void (*dtor) (void *)) + * + * Public interface called by C++ exception handling mechanism in + * libgcc (cf: __gthread_key_create). + * + */ + +__declspec(dllexport) +int +__mingwthr_key_dtor (DWORD key, void (*dtor) (void *)) +{ + if (dtor) + return ___mingwthr_add_key_dtor (key, dtor); + + return 0; +} + +__declspec(dllexport) +int +__mingwthr_remove_key_dtor (DWORD key) +{ + return ___mingwthr_remove_key_dtor (key); +} + +BOOL APIENTRY +DllMain (HANDLE hDllHandle __attribute__ ((__unused__)), + DWORD reason /* Reason this function is being called. */, + LPVOID reserved __attribute__ ((__unused__))) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + InitializeCriticalSection (&__mingwthr_cs); + break; + + case DLL_PROCESS_DETACH: + __mingwthr_run_key_dtors (); + DeleteCriticalSection (&__mingwthr_cs); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + __mingwthr_run_key_dtors (); + break; + } + return TRUE; +} +#endif +#endif diff --git a/gcc/config/i386/t-gthr-win32 b/gcc/config/i386/t-gthr-win32 index 204a485bcd19..e3977ce6336c 100644 --- a/gcc/config/i386/t-gthr-win32 +++ b/gcc/config/i386/t-gthr-win32 @@ -1,3 +1,3 @@ # We hide calls to w32api needed for w32 thread support here: -LIB2FUNCS_EXTRA = $(srcdir)/config/i386/gthr-win32.c - +LIB2FUNCS_EXTRA = $(srcdir)/config/i386/gthr-win32.c \ + $(srcdir)/config/i386/mingw-tls.c diff --git a/gcc/gthr-win32.h b/gcc/gthr-win32.h index a4fd32b6a349..74ac6179c2c4 100644 --- a/gcc/gthr-win32.h +++ b/gcc/gthr-win32.h @@ -361,15 +361,14 @@ typedef struct { __gthread_recursive_mutex_init_function #define __GTHREAD_RECURSIVE_MUTEX_INIT_DEFAULT {-1, 0, 0, 0} -#if __MINGW32_MAJOR_VERSION >= 1 || \ - (__MINGW32_MAJOR_VERSION == 0 && __MINGW32_MINOR_VERSION > 2) +#if defined (_WIN32) && !defined(__CYGWIN__) #define MINGW32_SUPPORTS_MT_EH 1 /* Mingw runtime >= v0.3 provides a magic variable that is set to nonzero if -mthreads option was specified, or 0 otherwise. This is to get around the lack of weak symbols in PE-COFF. */ extern int _CRT_MT; extern int __mingwthr_key_dtor (unsigned long, void (*) (void *)); -#endif /* __MINGW32__ version */ +#endif /* _WIN32 && !__CYGWIN__ */ /* The Windows95 kernel does not export InterlockedCompareExchange. This provides a substitute. When building apps that reference