Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Sutcliffe <ir0nh34d@users.sourceforge.net>2010-01-26 01:58:03 +0300
committerChris Sutcliffe <ir0nh34d@users.sourceforge.net>2010-01-26 01:58:03 +0300
commitd359eb2e1fe2486bc8a7340b64f6c25387dd1585 (patch)
treefead62572254c03a9310417b1eb1dec6b762c340 /winsup/mingw
parent8944c6af484e4bbaf5c494649b09cf60dc70a5ac (diff)
2010-01-25 Kai Tietz <kai.tietz@onevision.com>
Implement TLS Callback. * tlsmcrt.c: New file. * tlsmthread.c: Ditto. * tlssup.c: Ditto. * tlsthrd.c: Ditto. * Makefile.in: Include new files. * crt1.c: Implement TLS Callback. * dllcrt1.c: Ditto. * mthr_stub.c: Remove.
Diffstat (limited to 'winsup/mingw')
-rw-r--r--winsup/mingw/ChangeLog13
-rw-r--r--winsup/mingw/Makefile.in14
-rw-r--r--winsup/mingw/crt1.c7
-rw-r--r--winsup/mingw/dllcrt1.c9
-rw-r--r--winsup/mingw/mthr_stub.c44
-rw-r--r--winsup/mingw/tlsmcrt.c13
-rw-r--r--winsup/mingw/tlsmthread.c59
-rw-r--r--winsup/mingw/tlssup.c213
-rw-r--r--winsup/mingw/tlsthrd.c148
9 files changed, 472 insertions, 48 deletions
diff --git a/winsup/mingw/ChangeLog b/winsup/mingw/ChangeLog
index 733d56e10..c83c8e38b 100644
--- a/winsup/mingw/ChangeLog
+++ b/winsup/mingw/ChangeLog
@@ -1,3 +1,16 @@
+2010-01-25 Kai Tietz <kai.tietz@onevision.com>
+
+ Implement TLS Callback.
+
+ * tlsmcrt.c: New file.
+ * tlsmthread.c: Ditto.
+ * tlssup.c: Ditto.
+ * tlsthrd.c: Ditto.
+ * Makefile.in: Include new files.
+ * crt1.c: Implement TLS Callback.
+ * dllcrt1.c: Ditto.
+ * mthr_stub.c: Remove.
+
2009-11-29 Chris Sutcliffe <ir0nh34d@users.sourceforge.net>
* include/_mingw.h: Increment version to 3.17.
diff --git a/winsup/mingw/Makefile.in b/winsup/mingw/Makefile.in
index 7a51a9f16..8f7358314 100644
--- a/winsup/mingw/Makefile.in
+++ b/winsup/mingw/Makefile.in
@@ -227,8 +227,9 @@ FLAGS_TO_PASS:=\
CRT0S = crt1.o dllcrt1.o crt2.o dllcrt2.o CRT_noglob.o crtmt.o crtst.o \
CRT_fp8.o CRT_fp10.o txtmode.o binmode.o
MINGW_OBJS = CRTglob.o CRTfmode.o CRTinit.o dllmain.o gccmain.o \
- main.o crtst.o mthr_stub.o CRT_fp10.o txtmode.o \
- pseudo-reloc.o pseudo-reloc-list.o cpu_features.o
+ main.o crtst.o CRT_fp10.o txtmode.o \
+ pseudo-reloc.o pseudo-reloc-list.o cpu_features.o \
+ tlsmcrt.o tlsmthread.o tlssup.o tlsthrd.o
MOLD_OBJS = isascii.o iscsym.o iscsymf.o toascii.o \
strcasecmp.o strncasecmp.o wcscmpi.o
@@ -247,6 +248,7 @@ LIBS = libcrtdll.a \
libmoldname80.a libmoldname80d.a \
libmoldname90.a libmoldname90d.a \
$(LIBM_A) \
+ libmingwthrd_old.a \
libmingwthrd.a
DLLS = $(THREAD_DLL_NAME)
@@ -260,7 +262,7 @@ Makefile.in README TODO config.guess config.sub configure configure.in \
aclocal.m4 crt1.c crtdll.def crtmt.c crtst.c dllcrt1.c dllmain.c \
gccmain.c init.c install-sh jamfile main.c mkinstalldirs \
moldname.def.in msvcrt.def.in ofmt_stub.s \
-mthr.c mthr_init.c mthr_stub.c readme.txt \
+mthr.c mthr_init.c tlsmcrt.c tlsmthread.c tlssup.c tlsthrd.c readme.txt \
isascii.c iscsym.c iscsymf.c toascii.c \
strcasecmp.c strncasecmp.c wcscmpi.c \
CRT_fp8.c CRT_fp10.c test_headers.c txtmode.c binmode.c pseudo-reloc.c \
@@ -290,7 +292,11 @@ libm.a: _libm_dummy.o
$(AR) rc $@ _libm_dummy.o
$(RANLIB) $@
-libmingwthrd.a: crtmt.o mingwthrd.def
+libmingwthrd.a: crtmt.o
+ $(AR) $(ARFLAGS) $@ crtmt.o
+ $(RANLIB) $@
+
+libmingwthrd_old.a: crtmt.o mingwthrd.def
$(DLLTOOL) $(DLLTOOL_FLAGS) --dllname $(THREAD_DLL_NAME) \
--def mingwthrd.def --output-lib $@
$(AR) $(ARFLAGS) $@ crtmt.o
diff --git a/winsup/mingw/crt1.c b/winsup/mingw/crt1.c
index ad3ed7147..104f6b783 100644
--- a/winsup/mingw/crt1.c
+++ b/winsup/mingw/crt1.c
@@ -34,6 +34,9 @@ extern void _pei386_runtime_relocator (void);
extern int main (int, char **, char **);
+/* TLS initialization hook. */
+extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
+
/*
* Must have the correct app type for MSVCRT.
*/
@@ -186,6 +189,10 @@ __mingw_CRTStartup (void)
{
int nRet;
+ /* Initialize TLS callback. */
+ if (__dyn_tls_init_callback != NULL)
+ __dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
+
/*
* Set up the top-level exception handler so that signal handling
* works as expected. The mapping between ANSI/POSIX signals and
diff --git a/winsup/mingw/dllcrt1.c b/winsup/mingw/dllcrt1.c
index dda8a24c7..ee03be3e6 100644
--- a/winsup/mingw/dllcrt1.c
+++ b/winsup/mingw/dllcrt1.c
@@ -14,6 +14,9 @@
#include <errno.h>
#include <windows.h>
+/* TLS initialization hook. */
+extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
+
/* Unlike normal crt1, I don't initialize the FPU, because the process
* should have done that already. I also don't set the file handle modes,
* because that would be rude. */
@@ -62,6 +65,12 @@ DllMainCRTStartup (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
*first_atexit = NULL;
next_atexit = first_atexit;
+ /* Initialize TLS callback. */
+ if (__dyn_tls_init_callback != NULL)
+ {
+ __dyn_tls_init_callback (hDll, DLL_THREAD_ATTACH, lpReserved);
+ }
+
/* Adust references to dllimported data (from other DLL's)
that have non-zero offsets. */
_pei386_runtime_relocator ();
diff --git a/winsup/mingw/mthr_stub.c b/winsup/mingw/mthr_stub.c
deleted file mode 100644
index e337b9a1c..000000000
--- a/winsup/mingw/mthr_stub.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * mthr_stub.c
- *
- * Implement Mingw thread-support stubs for single-threaded C++ apps.
- *
- * This file is used by if gcc is built with --enable-threads=win32 and
- * iff gcc does *NOT* use -mthreads option.
- *
- * The -mthreads implementation is in mthr.c.
- *
- * Created by Mumit Khan <khan@nanotech.wisc.edu>
- *
- */
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef WIN32_LEAN_AND_MEAN
-
-/*
- * __mingwthr_register_key_dtor (DWORD key, void (*dtor) (void *))
- *
- * Public interface called by C++ exception handling mechanism in
- * libgcc (cf: __gthread_key_create).
- * No-op versions.
- */
-
-int
-__mingwthr_key_dtor (DWORD key, void (*dtor) (void *))
-{
-#ifdef DEBUG
- printf ("%s: ignoring key: (%ld) / dtor: (%x)\n",
- __FUNCTION__, key, dtor);
-#endif
- return 0;
-}
-
-int
-__mingwthr_remove_key_dtor (DWORD key )
-{
-#ifdef DEBUG
- printf ("%s: ignoring key: (%ld)\n", __FUNCTION__, key );
-#endif
- return 0;
-}
diff --git a/winsup/mingw/tlsmcrt.c b/winsup/mingw/tlsmcrt.c
new file mode 100644
index 000000000..45bead291
--- /dev/null
+++ b/winsup/mingw/tlsmcrt.c
@@ -0,0 +1,13 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the w64 mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER within this package.
+ *
+ * Written by Kai Tietz <kai.tietz@onevision.com>
+ */
+
+/* We support TLS cleanup code in any case. If shared version of libgcc is used _CRT_MT has value 1,
+ otherwise
+ we do tls cleanup in runtime and _CRT_MT has value 2. */
+int _CRT_MT = 2;
+
diff --git a/winsup/mingw/tlsmthread.c b/winsup/mingw/tlsmthread.c
new file mode 100644
index 000000000..f30e70137
--- /dev/null
+++ b/winsup/mingw/tlsmthread.c
@@ -0,0 +1,59 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the w64 mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER within this package.
+ *
+ * Written by Kai Tietz <kai.tietz@onevision.com>
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <stdlib.h>
+
+int __mingwthr_key_dtor (DWORD key, void (*dtor)(void *));
+int __mingwthr_remove_key_dtor (DWORD key);
+
+extern int ___w64_mingwthr_remove_key_dtor (DWORD key);
+extern int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
+
+
+#ifndef _WIN64
+#define MINGWM10_DLL "mingwm10.dll"
+typedef int (*fMTRemoveKeyDtor)(DWORD key);
+typedef int (*fMTKeyDtor)(DWORD key, void (*dtor)(void *));
+extern fMTRemoveKeyDtor __mingw_gMTRemoveKeyDtor;
+extern fMTKeyDtor __mingw_gMTKeyDtor;
+extern int __mingw_usemthread_dll;
+#endif
+
+int
+__mingwthr_remove_key_dtor (DWORD key)
+{
+#ifndef _WIN64
+ if (!__mingw_usemthread_dll)
+#endif
+ return ___w64_mingwthr_remove_key_dtor (key);
+#ifndef _WIN64
+ if (__mingw_gMTRemoveKeyDtor)
+ return (*__mingw_gMTRemoveKeyDtor) (key);
+ return 0;
+#endif
+}
+
+int
+__mingwthr_key_dtor (DWORD key, void (*dtor)(void *))
+{
+ if (dtor)
+ {
+#ifndef _WIN64
+ if (!__mingw_usemthread_dll)
+#endif
+ return ___w64_mingwthr_add_key_dtor (key, dtor);
+#ifndef _WIN64
+ if (__mingw_gMTKeyDtor)
+ return (*__mingw_gMTKeyDtor) (key, dtor);
+#endif
+ }
+ return 0;
+}
diff --git a/winsup/mingw/tlssup.c b/winsup/mingw/tlssup.c
new file mode 100644
index 000000000..b101d1124
--- /dev/null
+++ b/winsup/mingw/tlssup.c
@@ -0,0 +1,213 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the w64 mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER within this package.
+ *
+ * Written by Kai Tietz <kai.tietz@onevision.com>
+ */
+
+#ifdef CRTDLL
+#undef CRTDLL
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include <memory.h>
+#include <malloc.h>
+
+#ifndef _CRTALLOC
+#define _CRTALLOC(x) __attribute__ ((section (x) ))
+#endif
+
+#ifndef __INTERNAL_FUNC_DEFINED
+#define __INTERNAL_FUNC_DEFINED
+ typedef void (__cdecl *_PVFV)(void);
+ typedef int (__cdecl *_PIFV)(void);
+ typedef void (__cdecl *_PVFI)(int);
+#endif
+
+extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
+
+#define FUNCS_PER_NODE 30
+
+typedef struct TlsDtorNode {
+ int count;
+ struct TlsDtorNode *next;
+ _PVFV funcs[FUNCS_PER_NODE];
+} TlsDtorNode;
+
+ULONG _tls_index = 0;
+
+/* TLS raw template data start and end. */
+_CRTALLOC(".tls$AAA") char _tls_start = 0;
+_CRTALLOC(".tls$ZZZ") char _tls_end = 0;
+
+_CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
+_CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
+
+#ifdef _WIN64
+_CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY64 _tls_used = {
+ (ULONGLONG) &_tls_start+1, (ULONGLONG) &_tls_end, (ULONGLONG) &_tls_index,
+ (ULONGLONG) (&__xl_a+1), (ULONG) 0, (ULONG) 0
+};
+#else
+_CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY _tls_used = {
+ (ULONG)(ULONG_PTR) &_tls_start+1, (ULONG)(ULONG_PTR) &_tls_end,
+ (ULONG)(ULONG_PTR) &_tls_index, (ULONG)(ULONG_PTR) (&__xl_a+1),
+ (ULONG) 0, (ULONG) 0
+};
+#endif
+
+#ifndef __CRT_THREAD
+#ifdef HAVE_ATTRIBUTE_THREAD
+#define __CRT_THREAD __declspec(thread)
+#else
+#define __CRT_THREAD __thread
+#endif
+#endif
+
+#define DISABLE_MS_TLS 1
+
+static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
+static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
+
+#if !defined (DISABLE_MS_TLS)
+static __CRT_THREAD TlsDtorNode *dtor_list;
+static __CRT_THREAD TlsDtorNode dtor_list_head;
+#endif
+
+extern int _CRT_MT;
+
+#ifndef _WIN64
+#define MINGWM10_DLL "mingwm10.dll"
+typedef int (*fMTRemoveKeyDtor)(DWORD key);
+typedef int (*fMTKeyDtor)(DWORD key, void (*dtor)(void *));
+fMTRemoveKeyDtor __mingw_gMTRemoveKeyDtor;
+fMTKeyDtor __mingw_gMTKeyDtor;
+int __mingw_usemthread_dll;
+static HANDLE __mingw_mthread_hdll;
+#endif
+
+BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
+
+BOOL WINAPI
+__dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
+{
+ _PVFV *pfunc;
+
+#ifndef _WIN64
+ if (_winmajor < 4)
+ {
+ __mingw_usemthread_dll = 1;
+ __mingw_mthread_hdll = LoadLibrary (MINGWM10_DLL);
+ if (__mingw_mthread_hdll != NULL)
+ {
+ __mingw_gMTRemoveKeyDtor = (fMTRemoveKeyDtor) GetProcAddress (__mingw_mthread_hdll, "__mingwthr_remove_key_dtor");
+ __mingw_gMTKeyDtor = (fMTKeyDtor) GetProcAddress (__mingw_mthread_hdll, "__mingwthr_key_dtor");
+ }
+ if (__mingw_mthread_hdll == NULL || !__mingw_gMTRemoveKeyDtor || !__mingw_gMTKeyDtor)
+ {
+ __mingw_gMTKeyDtor = NULL;
+ __mingw_gMTRemoveKeyDtor = NULL;
+ if (__mingw_mthread_hdll)
+ FreeLibrary (__mingw_mthread_hdll);
+ __mingw_mthread_hdll = NULL;
+ _CRT_MT = 0;
+ return TRUE;
+ }
+ _CRT_MT = 1;
+ return TRUE;
+ }
+#endif
+ /* We don't let us trick here. */
+ if (_CRT_MT != 2)
+ _CRT_MT = 2;
+
+ if (dwReason != DLL_THREAD_ATTACH)
+ {
+ if (dwReason == DLL_PROCESS_ATTACH)
+ __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
+ return TRUE;
+ }
+
+ for (pfunc = &__xd_a + 1; pfunc != &__xd_z; ++pfunc)
+ {
+ if (*pfunc != NULL)
+ (*pfunc)();
+ }
+ return TRUE;
+}
+
+const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init;
+_CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init;
+
+int __cdecl __tlregdtor (_PVFV);
+
+int __cdecl
+__tlregdtor (_PVFV func)
+{
+ if (!func)
+ return 0;
+#if !defined (DISABLE_MS_TLS)
+ if (dtor_list == NULL)
+ {
+ dtor_list = &dtor_list_head;
+ dtor_list_head.count = 0;
+ }
+ else if (dtor_list->count == FUNCS_PER_NODE)
+ {
+ TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
+ if (pnode == NULL)
+ return -1;
+ pnode->count = 0;
+ pnode->next = dtor_list;
+ dtor_list = pnode;
+
+ dtor_list->count = 0;
+ }
+ dtor_list->funcs[dtor_list->count++] = func;
+#endif
+ return 0;
+}
+
+static BOOL WINAPI
+__dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
+{
+#if !defined (DISABLE_MS_TLS)
+ TlsDtorNode *pnode, *pnext;
+ int i;
+#endif
+
+ if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
+ return TRUE;
+ /* As TLS variables are detroyed already by DLL_THREAD_DETACH
+ call, we have to avoid access on the possible DLL_PROCESS_DETACH
+ call the already destroyed TLS vars.
+ TODO: The used local thread based variables have to be handled
+ manually, so that we can control their lifetime here. */
+#if !defined (DISABLE_MS_TLS)
+ if (dwReason != DLL_PROCESS_DETACH)
+ {
+ for (pnode = dtor_list; pnode != NULL; pnode = pnext)
+ {
+ for (i = pnode->count - 1; i >= 0; --i)
+ {
+ if (pnode->funcs[i] != NULL)
+ (*pnode->funcs[i])();
+ }
+ pnext = pnode->next;
+ if (pnext != NULL)
+ free ((void *) pnode);
+ }
+ }
+#endif
+ __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
+ return TRUE;
+}
+
+_CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor;
+
+
+int mingw_initltsdrot_force = 0;
+int mingw_initltsdyn_force=0;
+int mingw_initltssuo_force = 0;
diff --git a/winsup/mingw/tlsthrd.c b/winsup/mingw/tlsthrd.c
new file mode 100644
index 000000000..a3758076d
--- /dev/null
+++ b/winsup/mingw/tlsthrd.c
@@ -0,0 +1,148 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the w64 mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER within this package.
+ *
+ * Written by Kai Tietz <kai.tietz@onevision.com>
+ *
+ * This file is used by if gcc is built with --enable-threads=win32.
+ *
+ * Based on version created by Mumit Khan <khan@nanotech.wisc.edu>
+ *
+ */
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <stdlib.h>
+
+WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
+int ___w64_mingwthr_remove_key_dtor (DWORD key);
+int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
+
+/* To protect the thread/key association data structure modifications. */
+static CRITICAL_SECTION __mingwthr_cs;
+static volatile int __mingwthr_cs_init = 0;
+
+typedef struct __mingwthr_key __mingwthr_key_t;
+
+/* The list of threads active with key/dtor pairs. */
+struct __mingwthr_key {
+ DWORD key;
+ void (*dtor)(void *);
+ __mingwthr_key_t volatile *next;
+};
+
+
+static __mingwthr_key_t volatile *key_dtor_list;
+
+int
+___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *))
+{
+ __mingwthr_key_t *new_key;
+
+ if (__mingwthr_cs_init == 0)
+ return 0;
+ 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;
+}
+
+int
+___w64_mingwthr_remove_key_dtor (DWORD key)
+{
+ __mingwthr_key_t volatile *prev_key;
+ __mingwthr_key_t volatile *cur_key;
+
+ if (__mingwthr_cs_init == 0)
+ return 0;
+
+ EnterCriticalSection (&__mingwthr_cs);
+
+ prev_key = NULL;
+ cur_key = key_dtor_list;
+
+ while (cur_key != NULL)
+ {
+ if ( cur_key->key == key)
+ {
+ if (prev_key == NULL)
+ key_dtor_list = cur_key->next;
+ else
+ prev_key->next = cur_key->next;
+
+ free ((void*)cur_key);
+ break;
+ }
+ prev_key = cur_key;
+ cur_key = cur_key->next;
+ }
+
+ LeaveCriticalSection (&__mingwthr_cs);
+ return 0;
+}
+
+static void
+__mingwthr_run_key_dtors (void)
+{
+ __mingwthr_key_t volatile *keyp;
+
+ if (__mingwthr_cs_init == 0)
+ return;
+ 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);
+}
+
+WINBOOL
+__mingw_TLScallback (HANDLE hDllHandle __attribute__ ((__unused__)),
+ DWORD reason,
+ LPVOID reserved __attribute__ ((__unused__)))
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ if (__mingwthr_cs_init == 0)
+ InitializeCriticalSection (&__mingwthr_cs);
+ __mingwthr_cs_init = 1;
+ break;
+ case DLL_PROCESS_DETACH:
+ __mingwthr_run_key_dtors();
+ if (__mingwthr_cs_init == 1)
+ {
+ __mingwthr_cs_init = 0;
+ DeleteCriticalSection (&__mingwthr_cs);
+ }
+ break;
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ __mingwthr_run_key_dtors();
+ break;
+ }
+ return TRUE;
+}
+