Windows: Manage thread local storage manually in dlfcn_w32
This commit is contained in:
@@ -36,17 +36,75 @@
|
||||
|
||||
#define ERR_STR_LEN 256
|
||||
|
||||
__declspec(thread) static char err_str[ERR_STR_LEN];
|
||||
static volatile DWORD dlfcn_tls = TLS_OUT_OF_INDEXES;
|
||||
|
||||
static void set_error(const char * e) {
|
||||
StringCbCopy(err_str, sizeof(err_str), e);
|
||||
static DWORD get_tl_error_slot(void)
|
||||
{
|
||||
if (dlfcn_tls == TLS_OUT_OF_INDEXES) {
|
||||
DWORD slot = TlsAlloc();
|
||||
DWORD old_slot;
|
||||
|
||||
if (slot == TLS_OUT_OF_INDEXES)
|
||||
return dlfcn_tls;
|
||||
|
||||
if ((old_slot = InterlockedCompareExchange(&dlfcn_tls, slot,
|
||||
TLS_OUT_OF_INDEXES)) !=
|
||||
TLS_OUT_OF_INDEXES) {
|
||||
|
||||
/* Lost a race */
|
||||
TlsFree(slot);
|
||||
return old_slot;
|
||||
} else {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
||||
return dlfcn_tls;
|
||||
}
|
||||
|
||||
static void set_error(const char * e)
|
||||
{
|
||||
char * s;
|
||||
char * old_s;
|
||||
size_t len;
|
||||
|
||||
DWORD slot = get_tl_error_slot();
|
||||
|
||||
if (slot == TLS_OUT_OF_INDEXES)
|
||||
return;
|
||||
|
||||
len = strlen(e) * sizeof(char) + sizeof(char);
|
||||
s = LocalAlloc(LMEM_FIXED, len);
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
old_s = (char *) TlsGetValue(slot);
|
||||
TlsSetValue(slot, (LPVOID) s);
|
||||
|
||||
if (old_s != NULL)
|
||||
LocalFree(old_s);
|
||||
}
|
||||
|
||||
static void set_error_from_last(void) {
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
DWORD slot = get_tl_error_slot();
|
||||
char * s = NULL;
|
||||
char * old_s;
|
||||
|
||||
if (slot == TLS_OUT_OF_INDEXES)
|
||||
return;
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
0, GetLastError(), 0,
|
||||
err_str, sizeof(err_str)/sizeof(err_str[0]),
|
||||
(LPTSTR) &s, 0,
|
||||
NULL);
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
old_s = (char *) TlsGetValue(slot);
|
||||
TlsSetValue(slot, (LPVOID) s);
|
||||
|
||||
if (old_s != NULL)
|
||||
LocalFree(old_s);
|
||||
}
|
||||
|
||||
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
|
||||
@@ -64,7 +122,12 @@ dlclose(void * vhm)
|
||||
ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
|
||||
dlerror(void)
|
||||
{
|
||||
return err_str;
|
||||
DWORD slot = get_tl_error_slot();
|
||||
|
||||
if (slot == TLS_OUT_OF_INDEXES)
|
||||
return NULL;
|
||||
|
||||
return (char *) TlsGetValue(slot);
|
||||
}
|
||||
|
||||
ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL
|
||||
|
Reference in New Issue
Block a user