]> pd.if.org Git - pdclib/blobdiff - platform/win32/functions/threads/tss_create.c
win32: initial pass at thread support
[pdclib] / platform / win32 / functions / threads / tss_create.c
diff --git a/platform/win32/functions/threads/tss_create.c b/platform/win32/functions/threads/tss_create.c
new file mode 100644 (file)
index 0000000..af6da3f
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef REGTEST\r
+#include <threads.h>\r
+#include <stdbool.h>\r
+#include <windows.h>\r
+\r
+/* Pull in TLS support */\r
+extern char _tls_used[];\r
+\r
+struct _PDCLIB_tss * _PDCLIB_tss_first = NULL;\r
+\r
+int tss_create( tss_t *key, tss_dtor_t dtor )\r
+{\r
+    *key = malloc( sizeof *key );\r
+    if( !*key ) {\r
+        return thrd_nomem;\r
+    }\r
+\r
+    (*key)->_Key = TlsAlloc();\r
+    if((*key)->_Key == TLS_OUT_OF_INDEXES) {\r
+        return thrd_error;\r
+    }\r
+    (*key)->_Destructor = dtor;\r
+    (*key)->_Next = _PDCLIB_tss_first;\r
+\r
+    // TODO: make this atomic (& validate no other TLS blocks have been \r
+    // simultaneously allocated)\r
+    _PDCLIB_tss_first = *key;\r
+\r
+    return thrd_success;\r
+}\r
+\r
+static void NTAPI runTlsDestructors( void * image, DWORD reason, PVOID pv )\r
+{\r
+    if( reason == DLL_THREAD_DETACH ) {\r
+        for(unsigned i = 0; i < TSS_DTOR_ITERATIONS; i++) {\r
+            struct _PDCLIB_tss * tss = _PDCLIB_tss_first;\r
+            bool destructorsRan = false;\r
+            while( tss ) {\r
+                void * val = TlsGetValue( tss->_Key );\r
+                if( val ) {\r
+                    TlsSetValue( tss->_Key, NULL );\r
+                    if( tss->_Destructor ) {\r
+                        tss->_Destructor( val );\r
+                        destructorsRan = true;\r
+                    }\r
+                }\r
+\r
+                tss = tss->_Next;\r
+            }\r
+            if(!destructorsRan) break;\r
+        }\r
+    }\r
+}\r
+\r
+#ifdef __GNUC__\r
+__attribute__((__section__(".CRT$XLC")))\r
+#else\r
+__declspec(allocate(".CRT$XLC")) \r
+#endif\r
+PIMAGE_TLS_CALLBACK _PDCLIB_runTlsDestructors = runTlsDestructors;\r
+\r
+#endif\r
+\r
+#ifdef TEST\r
+#include <_PDCLIB_test.h>\r
+\r
+/* Tested in tss_get.c */\r
+int main( void )\r
+{\r
+    return TEST_RESULTS;\r
+}\r
+\r
+#endif
\ No newline at end of file