From d71dc9b022209480c2ddecdc8b1356ee02c69a55 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 22 May 2006 16:47:26 +0000 Subject: Fix TLS on Win32 to something a bit more safe and portable (compiler-wise). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@947 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/polyp/error.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/src/polyp/error.c b/src/polyp/error.c index 062b6f36..ee9ce51b 100644 --- a/src/polyp/error.c +++ b/src/polyp/error.c @@ -90,7 +90,78 @@ static void inittls(void) { #elif HAVE_WINDOWS_H -static __declspec(thread) char *tlsstr; +static DWORD tlsstr_key = TLS_OUT_OF_INDEXES; +static DWORD monitor_key = TLS_OUT_OF_INDEXES; + +static void inittls(void) { + HANDLE mutex; + char name[64]; + + sprintf(name, "polypaudio%d", (int)GetCurrentProcessId()); + + mutex = CreateMutex(NULL, FALSE, name); + if (!mutex) { + fprintf(stderr, __FILE__ ": CRITICAL: Unable to create named mutex (%d)\n", (int)GetLastError()); + exit(-1); + } + + WaitForSingleObject(mutex, INFINITE); + + if (tlsstr_key == TLS_OUT_OF_INDEXES) { + tlsstr_key = TlsAlloc(); + monitor_key = TlsAlloc(); + if ((tlsstr_key == TLS_OUT_OF_INDEXES) || (monitor_key == TLS_OUT_OF_INDEXES)) { + fprintf(stderr, __FILE__ ": CRITICAL: Unable to allocate TLS key (%d)\n", (int)GetLastError()); + exit(-1); + } + } + + ReleaseMutex(mutex); + + CloseHandle(mutex); +} + +/* + * This is incredibly brain dead, but this is necessary when dealing with + * the hell that is Win32. + */ +struct monitor_data { + HANDLE thread; + void *data; +}; + +static DWORD WINAPI monitor_thread(LPVOID param) { + struct monitor_data *data; + + data = (struct monitor_data*)param; + assert(data); + + WaitForSingleObject(data->thread, INFINITE); + + CloseHandle(data->thread); + pa_xfree(data->data); + pa_xfree(data); + + return 0; +} + +static void start_monitor(void) { + HANDLE thread; + struct monitor_data *data; + + data = pa_xnew(struct monitor_data, 1); + assert(data); + + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &data->thread, 0, FALSE, DUPLICATE_SAME_ACCESS); + + thread = CreateThread(NULL, 0, monitor_thread, data, 0, NULL); + assert(thread); + + TlsSetValue(monitor_key, data); + + CloseHandle(thread); +} #else @@ -112,6 +183,16 @@ char* pa_cstrerror(int errnum) { pthread_once(&cstrerror_once, inittls); tlsstr = pthread_getspecific(tlsstr_key); +#elif defined(HAVE_WINDOWS_H) + char *tlsstr; + struct monitor_data *data; + + inittls(); + + tlsstr = TlsGetValue(tlsstr_key); + if (!tlsstr) + start_monitor(); + data = TlsGetValue(monitor_key); #endif if (tlsstr) @@ -144,6 +225,9 @@ char* pa_cstrerror(int errnum) { #ifdef HAVE_PTHREAD pthread_setspecific(tlsstr_key, tlsstr); +#elif defined(HAVE_WINDOWS_H) + TlsSetValue(tlsstr_key, tlsstr); + data->data = tlsstr; #endif return tlsstr; -- cgit