--- /dev/null
+#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