diff options
author | Dana Robinson <derobins@hdfgroup.org> | 2014-04-11 19:04:54 (GMT) |
---|---|---|
committer | Dana Robinson <derobins@hdfgroup.org> | 2014-04-11 19:04:54 (GMT) |
commit | f466a5d298885c4d3dd813c0e6c8db9319cade50 (patch) | |
tree | 770e2cec48a2a6497ad1e0ce6175b5ec6d4424e4 /src/H5TS.c | |
parent | 17a1f1a5976b98db1788200f0b015694f85cb008 (diff) | |
download | hdf5-f466a5d298885c4d3dd813c0e6c8db9319cade50.zip hdf5-f466a5d298885c4d3dd813c0e6c8db9319cade50.tar.gz hdf5-f466a5d298885c4d3dd813c0e6c8db9319cade50.tar.bz2 |
[svn-r25018] Purpose:
Merged r24893, r24961, r24965 from trunk.
Fix for thread-local storage resource leaks on Windows with Win32 threads.
Prohibits thread-safe + C++/Fortran/static library in CMake.
Tested on:
64-bit Windows 7 w/ Visual Studio 2012
Diffstat (limited to 'src/H5TS.c')
-rw-r--r-- | src/H5TS.c | 225 |
1 files changed, 161 insertions, 64 deletions
@@ -56,8 +56,6 @@ H5TS_key_t H5TS_cancel_key_g; * PROGRAMMER: Quincey Koziol * February 7, 2003 * - * MODIFICATIONS: - * *-------------------------------------------------------------------------- */ static void @@ -68,39 +66,9 @@ H5TS_key_destructor(void *key_val) HDfree(key_val); } -#ifdef H5_HAVE_WIN_THREADS -/*-------------------------------------------------------------------------- - * NAME - * H5TS_win32_first_thread_init - * - * USAGE - * H5TS_win32_first_thread_init() - * - * RETURNS - * - * DESCRIPTION - * Special function on windows needed to call the H5TS_first_thread_init - * function. - * - * PROGRAMMER: Mike McGreevy - * September 1, 2010 - * - * MODIFICATIONS: - * - *-------------------------------------------------------------------------- - */ -BOOL CALLBACK -H5TS_win32_first_thread_init(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContex) -{ - InitializeCriticalSection ( &H5_g.init_lock.CriticalSection ); - H5TS_errstk_key_g = TlsAlloc(); - H5TS_funcstk_key_g = TlsAlloc(); - H5TS_cancel_key_g = TlsAlloc(); +#ifndef H5_HAVE_WIN_THREADS - return TRUE; -} /* H5TS_win32_first_thread_init() */ -#else /* H5_HAVE_WIN_THREADS */ /*-------------------------------------------------------------------------- * NAME * H5TS_pthread_first_thread_init @@ -118,8 +86,6 @@ H5TS_win32_first_thread_init(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpCont * PROGRAMMER: Chee Wai LEE * May 2, 2000 * - * MODIFICATIONS: - * *-------------------------------------------------------------------------- */ void @@ -149,6 +115,7 @@ H5TS_pthread_first_thread_init(void) } #endif /* H5_HAVE_WIN_THREADS */ + /*-------------------------------------------------------------------------- * NAME * H5TS_mutex_lock @@ -167,11 +134,6 @@ H5TS_pthread_first_thread_init(void) * PROGRAMMER: Chee Wai LEE * May 2, 2000 * - * MODIFICATIONS: - * - * 19 May 2000, Bill Wendling - * Changed (*foo). form of accessing structure members to the -> form. - * *-------------------------------------------------------------------------- */ herr_t @@ -203,6 +165,7 @@ H5TS_mutex_lock(H5TS_mutex_t *mutex) #endif /* H5_HAVE_WIN_THREADS */ } + /*-------------------------------------------------------------------------- * NAME * H5TS_mutex_unlock @@ -221,12 +184,6 @@ H5TS_mutex_lock(H5TS_mutex_t *mutex) * PROGRAMMER: Chee Wai LEE * May 2, 2000 * - * MODIFICATIONS: - * - * 19 May 2000, Bill Wendling - * Changed (*foo). form of accessing structure members to the -> form. - * Also gave the function a return value. - * *-------------------------------------------------------------------------- */ herr_t @@ -258,6 +215,7 @@ H5TS_mutex_unlock(H5TS_mutex_t *mutex) #endif /* H5_HAVE_WIN_THREADS */ } /* H5TS_mutex_unlock */ + /*-------------------------------------------------------------------------- * NAME * H5TS_cancel_count_inc @@ -280,12 +238,6 @@ H5TS_mutex_unlock(H5TS_mutex_t *mutex) * PROGRAMMER: Chee Wai LEE * May 2, 2000 * - * MODIFICATIONS: - * - * 19 May 2000, Bill Wendling - * Changed function to return a value. Also changed the malloc() call to - * the H5MM_malloc() call and checked the returned pointer. - * *-------------------------------------------------------------------------- */ herr_t @@ -328,6 +280,7 @@ H5TS_cancel_count_inc(void) #endif /* H5_HAVE_WIN_THREADS */ } + /*-------------------------------------------------------------------------- * NAME * H5TS_cancel_count_dec @@ -348,11 +301,6 @@ H5TS_cancel_count_inc(void) * PROGRAMMER: Chee Wai LEE * May 2, 2000 * - * MODIFICATIONS: - * - * 19 May 2000, Bill Wendling - * Changed so that function returns a value. May be of limited usefulness. - * *-------------------------------------------------------------------------- */ herr_t @@ -377,6 +325,154 @@ H5TS_cancel_count_dec(void) } +#ifdef H5_HAVE_WIN_THREADS +/*-------------------------------------------------------------------------- + * NAME + * H5TS_win32_process_enter + * + * RETURNS + * SUCCEED/FAIL + * + * DESCRIPTION + * Per-process setup on Windows when using Win32 threads. + * + *-------------------------------------------------------------------------- + */ +H5_DLL BOOL CALLBACK +H5TS_win32_process_enter(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContex) +{ + BOOL ret_value = TRUE; + + /* Initialize the critical section (can't fail) */ + InitializeCriticalSection(&H5_g.init_lock.CriticalSection); + + /* Set up thread local storage */ + if(TLS_OUT_OF_INDEXES == (H5TS_errstk_key_g = TlsAlloc())) + ret_value = FALSE; + +#ifdef H5_HAVE_CODESTACK + if(TLS_OUT_OF_INDEXES == (H5TS_funcstk_key_g = TlsAlloc())) + ret_value = FALSE; +#endif /* H5_HAVE_CODESTACK */ + + return ret_value; +} /* H5TS_win32_process_enter() */ +#endif /* H5_HAVE_WIN_THREADS */ + + +#ifdef H5_HAVE_WIN_THREADS +/*-------------------------------------------------------------------------- + * NAME + * H5TS_win32_thread_enter + * + * RETURNS + * SUCCEED/FAIL + * + * DESCRIPTION + * Per-thread setup on Windows when using Win32 threads. + * + *-------------------------------------------------------------------------- + */ +herr_t +H5TS_win32_thread_enter(void) +{ + herr_t ret_value = SUCCEED; + + /* Currently a placeholder function. TLS setup is performed + * elsewhere in the library. + * + * WARNING: Do NOT use C standard library functions here. + * CRT functions are not allowed in DllMain, which is where this code + * is used. + */ + + return ret_value; +} /* H5TS_win32_thread_enter() */ +#endif /* H5_HAVE_WIN_THREADS */ + + +#ifdef H5_HAVE_WIN_THREADS +/*-------------------------------------------------------------------------- + * NAME + * H5TS_win32_process_exit + * + * RETURNS + * SUCCEED/FAIL + * + * DESCRIPTION + * Per-process cleanup on Windows when using Win32 threads. + * + *-------------------------------------------------------------------------- + */ +void +H5TS_win32_process_exit(void) +{ + + /* Windows uses a different thread local storage mechanism which does + * not support auto-freeing like pthreads' keys. + * + * This function is currently registered via atexit() and is called + * AFTER H5_term_library(). + */ + + /* Clean up critical section resources (can't fail) */ + DeleteCriticalSection(&H5_g.init_lock.CriticalSection); + + /* Clean up per-process thread local storage */ + TlsFree(H5TS_errstk_key_g); + +#ifdef H5_HAVE_CODESTACK + TlsFree(H5TS_funcstk_key_g); +#endif /* H5_HAVE_CODESTACK */ + + return; +} /* H5TS_win32_process_exit() */ +#endif /* H5_HAVE_WIN_THREADS */ + + +#ifdef H5_HAVE_WIN_THREADS +/*-------------------------------------------------------------------------- + * NAME + * H5TS_win32_thread_exit + * + * RETURNS + * SUCCEED/FAIL + * + * DESCRIPTION + * Per-thread cleanup on Windows when using Win32 threads. + * + *-------------------------------------------------------------------------- + */ +herr_t +H5TS_win32_thread_exit(void) +{ + LPVOID lpvData; + herr_t ret_value = SUCCEED; + + /* Windows uses a different thread local storage mechanism which does + * not support auto-freeing like pthreads' keys. + * + * WARNING: Do NOT use C standard library functions here. + * CRT functions are not allowed in DllMain, which is where this code + * is used. + */ + + /* Clean up per-thread thread local storage */ + lpvData = TlsGetValue(H5TS_errstk_key_g); + if(lpvData) + LocalFree((HLOCAL)lpvData); + +#ifdef H5_HAVE_CODESTACK + lpvData = TlsGetValue(H5TS_funcstk_key_g); + if(lpvData) + LocalFree((HLOCAL)lpvData); +#endif /* H5_HAVE_CODESTACK */ + + return ret_value; +} /* H5TS_win32_thread_exit() */ +#endif /* H5_HAVE_WIN_THREADS */ + + /*-------------------------------------------------------------------------- * NAME * H5TS_create_thread @@ -399,16 +495,17 @@ H5TS_create_thread(void *func, H5TS_attr_t *attr, void *udata) #ifdef H5_HAVE_WIN_THREADS - /* When calling C runtime functions, you have to use _beginthread or + /* When calling C runtime functions, you should use _beginthread or * _beginthreadex instead of CreateThread. Threads created with - * CreateThread risk being killed in low-memory situations. - * We use _beginthread instead of _begintheadex because the latter - * requires a stdcall function (and we don't need the more advanced - * features it exposes). + * CreateThread risk being killed in low-memory situations. Since we + * only create threads in our test code, this is unlikely to be an issue + * and we'll use the easier-to-deal-with CreateThread for now. * - * NOTE: No error checks here! ret_value will be -1L on errors. + * NOTE: _beginthread() auto-recycles its handle when execution completes + * so you can't wait on it, making it unsuitable for the existing + * test code. */ - ret_value = _beginthread(func, 0 /* stack size */, udata); + ret_value = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, udata, 0, NULL); #else /* H5_HAVE_WIN_THREADS */ |