summaryrefslogtreecommitdiffstats
path: root/src/H5TS.c
diff options
context:
space:
mode:
authorDana Robinson <derobins@hdfgroup.org>2014-04-11 19:04:54 (GMT)
committerDana Robinson <derobins@hdfgroup.org>2014-04-11 19:04:54 (GMT)
commitf466a5d298885c4d3dd813c0e6c8db9319cade50 (patch)
tree770e2cec48a2a6497ad1e0ce6175b5ec6d4424e4 /src/H5TS.c
parent17a1f1a5976b98db1788200f0b015694f85cb008 (diff)
downloadhdf5-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.c225
1 files changed, 161 insertions, 64 deletions
diff --git a/src/H5TS.c b/src/H5TS.c
index 8b75ab2..3c7e4f4 100644
--- a/src/H5TS.c
+++ b/src/H5TS.c
@@ -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 */