summaryrefslogtreecommitdiffstats
path: root/winsup/mingw/tlsthrd.c
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/mingw/tlsthrd.c')
-rw-r--r--winsup/mingw/tlsthrd.c148
1 files changed, 148 insertions, 0 deletions
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;
+}
+