mingw-w64/mingw-w64-crt/crt/tlsthrd.c

159 lines
3.6 KiB
C

/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD 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>
extern void __cdecl __MINGW_NOTHROW _fpreset (void);
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 __UNUSED_PARAM(hDllHandle),
DWORD reason,
LPVOID __UNUSED_PARAM(reserved))
{
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_key_t volatile *keyp, *t;
for (keyp = key_dtor_list; keyp; )
{
t = keyp->next;
free((void *)keyp);
keyp = t;
}
key_dtor_list = NULL;
__mingwthr_cs_init = 0;
DeleteCriticalSection (&__mingwthr_cs);
}
break;
case DLL_THREAD_ATTACH:
_fpreset();
break;
case DLL_THREAD_DETACH:
__mingwthr_run_key_dtors();
break;
}
return TRUE;
}