mingw-tls.c: New file.

2009-05-30  Kai Tietz  <kai.tietz@onevision.com>

        * 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__.

From-SVN: r148000
This commit is contained in:
Kai Tietz 2009-05-30 09:05:56 +00:00 committed by Kai Tietz
parent ec5c6f4a5f
commit a1bda0d7e8
4 changed files with 245 additions and 5 deletions

View File

@ -1,3 +1,11 @@
2009-05-30 Kai Tietz <kai.tietz@onevision.com>
* 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 <ghazi@caip.rutgers.edu>
* configure.ac: Add MPC support.

233
gcc/config/i386/mingw-tls.c Normal file
View File

@ -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
<http://www.gnu.org/licenses/>. */
/* This part is based on the implementation of Mumit Khan <khan@nanotech.wisc.edu>
* provided to mingw under public domain and ported for libgcc by Kai Tietz.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <stdlib.h>
/* 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

View File

@ -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

View File

@ -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