]> pd.if.org Git - pdclib/blob - platform/win32/functions/threads/tss_create.c
dos2unix
[pdclib] / platform / win32 / functions / threads / tss_create.c
1 #ifndef REGTEST
2 #include <threads.h>
3 #include <stdbool.h>
4 #include <windows.h>
5
6 /* Pull in TLS support */
7 extern char _tls_used[];
8
9 struct _PDCLIB_tss * _PDCLIB_tss_first = NULL;
10
11 int tss_create( tss_t *key, tss_dtor_t dtor )
12 {
13     *key = malloc( sizeof *key );
14     if( !*key ) {
15         return thrd_nomem;
16     }
17
18     (*key)->_Key = TlsAlloc();
19     if((*key)->_Key == TLS_OUT_OF_INDEXES) {
20         return thrd_error;
21     }
22     (*key)->_Destructor = dtor;
23     (*key)->_Next = _PDCLIB_tss_first;
24
25     // TODO: make this atomic (& validate no other TLS blocks have been 
26     // simultaneously allocated)
27     _PDCLIB_tss_first = *key;
28
29     return thrd_success;
30 }
31
32 static void NTAPI runTlsDestructors( void * image, DWORD reason, PVOID pv )
33 {
34     if( reason == DLL_THREAD_DETACH ) {
35         for(unsigned i = 0; i < TSS_DTOR_ITERATIONS; i++) {
36             struct _PDCLIB_tss * tss = _PDCLIB_tss_first;
37             bool destructorsRan = false;
38             while( tss ) {
39                 void * val = TlsGetValue( tss->_Key );
40                 if( val ) {
41                     TlsSetValue( tss->_Key, NULL );
42                     if( tss->_Destructor ) {
43                         tss->_Destructor( val );
44                         destructorsRan = true;
45                     }
46                 }
47
48                 tss = tss->_Next;
49             }
50             if(!destructorsRan) break;
51         }
52     }
53 }
54
55 #ifdef __GNUC__
56 __attribute__((__section__(".CRT$XLC")))
57 #else
58 __declspec(allocate(".CRT$XLC")) 
59 #endif
60 PIMAGE_TLS_CALLBACK _PDCLIB_runTlsDestructors = runTlsDestructors;
61
62 #endif
63
64 #ifdef TEST
65 #include "_PDCLIB_test.h"
66
67 /* Tested in tss_get.c */
68 int main( void )
69 {
70     return TEST_RESULTS;
71 }
72
73 #endif