summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2003-02-07 21:14:19 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2003-02-07 21:14:19 (GMT)
commit168d67dbd20923feef30fb76c6b569ef2e5add4a (patch)
tree2bcfd51c39665400804e92ac0fb13d42b2df96c3
parent4e8da9d2246a0bba1afb5c678346b2f1c4633c69 (diff)
downloadhdf5-168d67dbd20923feef30fb76c6b569ef2e5add4a.zip
hdf5-168d67dbd20923feef30fb76c6b569ef2e5add4a.tar.gz
hdf5-168d67dbd20923feef30fb76c6b569ef2e5add4a.tar.bz2
[svn-r6383] Purpose:
New feature for developers. Description: Added "function stack" tracing to library. This allows developers (there is no public API) to call H5FS_print within the library and get a listing of the functions traversed to reach that point in the library. Eventually, I may add support for reporting the parameters to each function also... Mainly for debugging parallel I/O programs, but I think it will come in handy in other cases also. The function stack tracking is controlled with a configure switch: --enable-funcstack, which defaults to enabled currently. When we branch for 1.6, we should change the default setting on the branch to be disabled. Also, added a destructor to the thread-specific keys when thread-safety is turned on in the library. Otherwise, they were leaking memory and causing difficult to debug errors in threaded programs (like the test/ttsafe test). Platforms tested: Tested h5committest {arabica (fortran), eirene (fortran, C++) modi4 (parallel, fortran)} FreeBSD 4.7 (sleipnir) w/thread-safety enabled. Misc. update: Updated MANIFEST with new files added (src/H5FS.c & src/H5FDprivate.h) Update release_docs/RELEASE with thread-safety bug fix.
-rw-r--r--MANIFEST2
-rwxr-xr-xconfigure37
-rw-r--r--configure.in25
-rw-r--r--release_docs/RELEASE.txt2
-rw-r--r--src/H5CS.c223
-rw-r--r--src/H5CSprivate.h40
-rw-r--r--src/H5FS.c223
-rw-r--r--src/H5FSprivate.h40
-rw-r--r--src/H5TS.c73
-rw-r--r--src/H5TSprivate.h1
-rw-r--r--src/H5config.h.in9
-rw-r--r--src/H5private.h53
-rw-r--r--src/Makefile.in17
-rw-r--r--test/bittests.c12
-rw-r--r--test/hyperslab.c12
-rw-r--r--test/ttsafe_cancel.c4
-rw-r--r--test/ttsafe_dcreate.c226
-rw-r--r--test/ttsafe_error.c3
18 files changed, 834 insertions, 168 deletions
diff --git a/MANIFEST b/MANIFEST
index dd9f3c8..cd8ea04 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -840,6 +840,8 @@
./src/H5FPprivate.h
./src/H5FPpublic.h
./src/H5FPserver.c
+./src/H5FS.c
+./src/H5FSprivate.h
./src/H5G.c
./src/H5Gent.c
./src/H5Gnode.c
diff --git a/configure b/configure
index 34ca1c4..c0a7674 100755
--- a/configure
+++ b/configure
@@ -1008,6 +1008,7 @@ Optional Features:
--enable-linux-lfs Enable support for large (64-bit) files on Linux.
[default=check]
--enable-threadsafe Enable thread safe capability
+ --enable-funcstack Enable the function stack tracing [default=yes]
--enable-hdf5v1_4 Compile the HDF5 v1.4 compatibility interface
[default=no]
--enable-stream-vfd Build the Stream Virtual File Driver [default=no]
@@ -4107,7 +4108,7 @@ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
case $host in
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 4110 "configure"' > conftest.$ac_ext
+ echo '#line 4111 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -4648,7 +4649,7 @@ chmod -w .
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
compiler_c_o=no
-if { (eval echo configure:4651: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+if { (eval echo configure:4652: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
if test -s out/conftest.err; then
@@ -6459,7 +6460,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 6462 "configure"
+#line 6463 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -6557,7 +6558,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 6560 "configure"
+#line 6561 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -27777,6 +27778,31 @@ _ACEOF
fi
+echo "$as_me:$LINENO: checking whether function stack tracking is enabled" >&5
+echo $ECHO_N "checking whether function stack tracking is enabled... $ECHO_C" >&6
+# Check whether --enable-funcstack or --disable-funcstack was given.
+if test "${enable_funcstack+set}" = set; then
+ enableval="$enable_funcstack"
+ FUNCSTACK=$enableval
+fi;
+
+case "X-$FUNCSTACK" in
+ X-|X-yes)
+ FUNCSTACK="yes"
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FUNCSTACK 1
+_ACEOF
+
+ ;;
+ *)
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ ;;
+esac
+
echo "$as_me:$LINENO: checking whether HDF5 v1.4 compatibility functions enabled" >&5
echo $ECHO_N "checking whether HDF5 v1.4 compatibility functions enabled... $ECHO_C" >&6
# Check whether --enable-hdf5v1_4 or --disable-hdf5v1_4 was given.
@@ -32010,5 +32036,8 @@ IF_ENABLED_DISABLED "$STREAM_VFD"
PRINT_N " Threadsafety"
IF_ENABLED_DISABLED "$THREADSAFE"
+PRINT_N " Function Stack Tracing"
+IF_ENABLED_DISABLED "$FUNCSTACK"
+
PRINT_N " Zlib-compression"
IF_YES_NO "$HAVE_ZLIB"
diff --git a/configure.in b/configure.in
index af929fe..8d689e0 100644
--- a/configure.in
+++ b/configure.in
@@ -1224,6 +1224,28 @@ if test "X$THREADSAFE" = "Xyes"; then
fi
dnl ----------------------------------------------------------------------
+dnl Check if they would like the function stack support compiled in
+dnl
+AC_MSG_CHECKING([whether function stack tracking is enabled])
+AC_ARG_ENABLE([funcstack],
+ [AC_HELP_STRING([--enable-funcstack],
+ [Enable the function stack
+ tracing [default=yes]])],
+ [FUNCSTACK=$enableval])
+
+case "X-$FUNCSTACK" in
+ X-|X-yes)
+ FUNCSTACK="yes"
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_FUNCSTACK], [1],
+ [Define if the function stack tracing code is to be compiled in])
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+esac
+
+dnl ----------------------------------------------------------------------
dnl Check if they would like the HDF5 v1.4 compatibility functions
dnl compiled in
dnl
@@ -2302,5 +2324,8 @@ IF_ENABLED_DISABLED "$STREAM_VFD"
PRINT_N " Threadsafety"
IF_ENABLED_DISABLED "$THREADSAFE"
+PRINT_N " Function Stack Tracing"
+IF_ENABLED_DISABLED "$FUNCSTACK"
+
PRINT_N " Zlib-compression"
IF_YES_NO "$HAVE_ZLIB"
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 4c0115b..38a5a75 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -35,6 +35,8 @@ Bug Fixes since HDF5-1.4.0
Library
-------
+ * Corrected memory/resource leaks in per-thread key information when
+ thread-safe operation was enabled. QAK - 2003/02/07
* H5Fopen without the H5F_ACC_CREAT flag should not succeed in creating
a new file with the 'core' VFL driver. QAK - 2003/01/24
* Allow opening objects with unknown object header messages.
diff --git a/src/H5CS.c b/src/H5CS.c
new file mode 100644
index 0000000..b523251
--- /dev/null
+++ b/src/H5CS.c
@@ -0,0 +1,223 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Provides internal function tracing in the form of a stack.
+ * The FUNC_ENTER() macro adds the function name to the function
+ * stack whenever a function is entered.
+ * As the functions return with FUNC_LEAVE,
+ * entries are removed from the stack.
+ *
+ * A function stack has a fixed maximum size. If this size is
+ * exceeded then the stack will be truncated and only the
+ * first called functions will have entries on the stack. This is
+ * expected to be a rare condition.
+ *
+ * Each thread has its own function stack, but since
+ * multi-threading has not been added to the library yet, this
+ * package maintains a single function stack. The function stack
+ * is statically allocated to reduce the complexity of handling
+ * errors within the H5FS package.
+ *
+ */
+#include "H5private.h" /* Generic Functions */
+#include "H5FSprivate.h" /* Private function stack routines */
+#include "H5MMprivate.h" /* Memory management functions */
+
+#ifdef H5_HAVE_FUNCSTACK
+
+#define PABLO_MASK H5FS_mask
+
+/* Interface initialization? */
+#define INTERFACE_INIT NULL
+
+#ifdef H5_HAVE_THREADSAFE
+/*
+ * The per-thread function stack. pthread_once() initializes a special
+ * key that will be used by all threads to create a stack specific to
+ * each thread individually. The association of stacks to threads will
+ * be handled by the pthread library.
+ *
+ * In order for this macro to work, H5FS_get_my_stack() must be preceeded
+ * by "H5FS_t *fstack =".
+ */
+static H5FS_t *H5FS_get_stack(void);
+#define H5FS_get_my_stack() H5FS_get_stack()
+#else /* H5_HAVE_THREADSAFE */
+/*
+ * The function stack. Eventually we'll have some sort of global table so each
+ * thread has it's own stack. The stacks will be created on demand when the
+ * thread first calls H5FS_push(). */
+H5FS_t H5FS_stack_g[1];
+#define H5FS_get_my_stack() (H5FS_stack_g+0)
+#endif /* H5_HAVE_THREADSAFE */
+
+
+#ifdef H5_HAVE_THREADSAFE
+/*-------------------------------------------------------------------------
+ * Function: H5FS_get_stack
+ *
+ * Purpose: Support function for H5FS_get_my_stack() to initialize and
+ * acquire per-thread function stack.
+ *
+ * Return: Success: function stack (H5FS_t *)
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * February 6, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5FS_t *
+H5FS_get_stack(void)
+{
+ H5FS_t *fstack;
+
+ FUNC_ENTER_NOAPI_NOFS(H5FS_get_stack);
+
+ fstack = pthread_getspecific(H5TS_funcstk_key_g);
+ if (!fstack) {
+ /* no associated value with current thread - create one */
+ fstack = (H5FS_t *)H5MM_malloc(sizeof(H5FS_t));
+ pthread_setspecific(H5TS_funcstk_key_g, (void *)fstack);
+ }
+
+ FUNC_LEAVE_NOAPI_NOFS(fstack);
+} /* end H5FS_get_stack() */
+#endif /* H5_HAVE_THREADSAFE */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_print
+ *
+ * Purpose: Prints the function stack in some default way.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * THursday, February 6, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_print(FILE *stream)
+{
+ H5FS_t *fstack = H5FS_get_my_stack (); /* Get the correct function stack */
+ const int indent = 2; /* Indention level */
+ int i; /* Local index ariable */
+
+ /* Don't push this function on the function stack... :-) */
+ FUNC_ENTER_NOAPI_NOFS(H5FS_print);
+
+ /* Sanity check */
+ assert(fstack);
+
+ /* Default to outputting information to stderr */
+ if (!stream)
+ stream = stderr;
+
+ HDfprintf (stream, "HDF5-DIAG: Function stack from %s ", H5_lib_vers_info_g);
+ /* try show the process or thread id in multiple processes cases*/
+#ifdef H5_HAVE_THREADSAFE
+ HDfprintf (stream, "thread %d.", (int)pthread_self());
+#else /* H5_HAVE_THREADSAFE */
+ HDfprintf (stream, "thread 0.");
+#endif /* H5_HAVE_THREADSAFE */
+ if (fstack && fstack->nused>0)
+ HDfprintf (stream, " Back trace follows.");
+ HDfputc ('\n', stream);
+
+ for (i=fstack->nused-1; i>=0; --i)
+ HDfprintf(stream, "%*s#%03d: Routine: %s\n", indent, "", i, fstack->slot[i]);
+
+ FUNC_LEAVE_NOAPI_NOFS(SUCCEED);
+} /* end H5FS_print() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_push
+ *
+ * Purpose: Pushes a new record onto function stack for the current
+ * thread.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, February 6, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_push(const char *func_name)
+{
+ H5FS_t *fstack = H5FS_get_my_stack ();
+
+ /* Don't push this function on the function stack... :-) */
+ FUNC_ENTER_NOAPI_NOFS(H5FS_push);
+
+ /* Sanity check */
+ assert (fstack);
+ assert (func_name);
+
+ /*
+ * Push the function if there's room. Otherwise just increment count
+ */
+ if (fstack->nused<H5FS_NSLOTS)
+ fstack->slot[fstack->nused] = func_name;
+ fstack->nused++;
+
+ FUNC_LEAVE_NOAPI_NOFS(SUCCEED);
+} /* end H5FS_push() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_pop
+ *
+ * Purpose: Pops a record off function stack for the current thread.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, February 6, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_pop(void)
+{
+ H5FS_t *fstack = H5FS_get_my_stack ();
+
+ /* Don't push this function on the function stack... :-) */
+ FUNC_ENTER_NOAPI_NOFS(H5FS_pop);
+
+ /* Sanity check */
+ assert (fstack);
+ assert (fstack->nused>0);
+
+ /* Pop the function. */
+ fstack->nused--;
+
+ FUNC_LEAVE_NOAPI_NOFS(SUCCEED);
+} /* end H5FS_pop() */
+
+#endif /* H5_HAVE_FUNCSTACK */
diff --git a/src/H5CSprivate.h b/src/H5CSprivate.h
new file mode 100644
index 0000000..6dba575
--- /dev/null
+++ b/src/H5CSprivate.h
@@ -0,0 +1,40 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Header file for function stacks, etc.
+ */
+#ifndef _H5FSprivate_H
+#define _H5FSprivate_H
+
+#ifdef NOT_YET
+#include "H5FSpublic.h"
+#endif /* NOT_YET */
+
+/* Private headers needed by this file */
+#include "H5private.h"
+
+#define H5FS_NSLOTS 32 /*number of slots in an function stack */
+
+/* A function stack */
+typedef struct H5FS_t {
+ int nused; /*num slots currently used in stack */
+ const char *slot[H5FS_NSLOTS]; /*array of function records */
+} H5FS_t;
+
+H5_DLL herr_t H5FS_push (const char *func_name);
+H5_DLL herr_t H5FS_pop (void);
+H5_DLL herr_t H5FS_print (FILE *stream);
+
+#endif /* _H5FSprivate_H */
diff --git a/src/H5FS.c b/src/H5FS.c
new file mode 100644
index 0000000..b523251
--- /dev/null
+++ b/src/H5FS.c
@@ -0,0 +1,223 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Purpose: Provides internal function tracing in the form of a stack.
+ * The FUNC_ENTER() macro adds the function name to the function
+ * stack whenever a function is entered.
+ * As the functions return with FUNC_LEAVE,
+ * entries are removed from the stack.
+ *
+ * A function stack has a fixed maximum size. If this size is
+ * exceeded then the stack will be truncated and only the
+ * first called functions will have entries on the stack. This is
+ * expected to be a rare condition.
+ *
+ * Each thread has its own function stack, but since
+ * multi-threading has not been added to the library yet, this
+ * package maintains a single function stack. The function stack
+ * is statically allocated to reduce the complexity of handling
+ * errors within the H5FS package.
+ *
+ */
+#include "H5private.h" /* Generic Functions */
+#include "H5FSprivate.h" /* Private function stack routines */
+#include "H5MMprivate.h" /* Memory management functions */
+
+#ifdef H5_HAVE_FUNCSTACK
+
+#define PABLO_MASK H5FS_mask
+
+/* Interface initialization? */
+#define INTERFACE_INIT NULL
+
+#ifdef H5_HAVE_THREADSAFE
+/*
+ * The per-thread function stack. pthread_once() initializes a special
+ * key that will be used by all threads to create a stack specific to
+ * each thread individually. The association of stacks to threads will
+ * be handled by the pthread library.
+ *
+ * In order for this macro to work, H5FS_get_my_stack() must be preceeded
+ * by "H5FS_t *fstack =".
+ */
+static H5FS_t *H5FS_get_stack(void);
+#define H5FS_get_my_stack() H5FS_get_stack()
+#else /* H5_HAVE_THREADSAFE */
+/*
+ * The function stack. Eventually we'll have some sort of global table so each
+ * thread has it's own stack. The stacks will be created on demand when the
+ * thread first calls H5FS_push(). */
+H5FS_t H5FS_stack_g[1];
+#define H5FS_get_my_stack() (H5FS_stack_g+0)
+#endif /* H5_HAVE_THREADSAFE */
+
+
+#ifdef H5_HAVE_THREADSAFE
+/*-------------------------------------------------------------------------
+ * Function: H5FS_get_stack
+ *
+ * Purpose: Support function for H5FS_get_my_stack() to initialize and
+ * acquire per-thread function stack.
+ *
+ * Return: Success: function stack (H5FS_t *)
+ *
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * February 6, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5FS_t *
+H5FS_get_stack(void)
+{
+ H5FS_t *fstack;
+
+ FUNC_ENTER_NOAPI_NOFS(H5FS_get_stack);
+
+ fstack = pthread_getspecific(H5TS_funcstk_key_g);
+ if (!fstack) {
+ /* no associated value with current thread - create one */
+ fstack = (H5FS_t *)H5MM_malloc(sizeof(H5FS_t));
+ pthread_setspecific(H5TS_funcstk_key_g, (void *)fstack);
+ }
+
+ FUNC_LEAVE_NOAPI_NOFS(fstack);
+} /* end H5FS_get_stack() */
+#endif /* H5_HAVE_THREADSAFE */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_print
+ *
+ * Purpose: Prints the function stack in some default way.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * THursday, February 6, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_print(FILE *stream)
+{
+ H5FS_t *fstack = H5FS_get_my_stack (); /* Get the correct function stack */
+ const int indent = 2; /* Indention level */
+ int i; /* Local index ariable */
+
+ /* Don't push this function on the function stack... :-) */
+ FUNC_ENTER_NOAPI_NOFS(H5FS_print);
+
+ /* Sanity check */
+ assert(fstack);
+
+ /* Default to outputting information to stderr */
+ if (!stream)
+ stream = stderr;
+
+ HDfprintf (stream, "HDF5-DIAG: Function stack from %s ", H5_lib_vers_info_g);
+ /* try show the process or thread id in multiple processes cases*/
+#ifdef H5_HAVE_THREADSAFE
+ HDfprintf (stream, "thread %d.", (int)pthread_self());
+#else /* H5_HAVE_THREADSAFE */
+ HDfprintf (stream, "thread 0.");
+#endif /* H5_HAVE_THREADSAFE */
+ if (fstack && fstack->nused>0)
+ HDfprintf (stream, " Back trace follows.");
+ HDfputc ('\n', stream);
+
+ for (i=fstack->nused-1; i>=0; --i)
+ HDfprintf(stream, "%*s#%03d: Routine: %s\n", indent, "", i, fstack->slot[i]);
+
+ FUNC_LEAVE_NOAPI_NOFS(SUCCEED);
+} /* end H5FS_print() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_push
+ *
+ * Purpose: Pushes a new record onto function stack for the current
+ * thread.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, February 6, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_push(const char *func_name)
+{
+ H5FS_t *fstack = H5FS_get_my_stack ();
+
+ /* Don't push this function on the function stack... :-) */
+ FUNC_ENTER_NOAPI_NOFS(H5FS_push);
+
+ /* Sanity check */
+ assert (fstack);
+ assert (func_name);
+
+ /*
+ * Push the function if there's room. Otherwise just increment count
+ */
+ if (fstack->nused<H5FS_NSLOTS)
+ fstack->slot[fstack->nused] = func_name;
+ fstack->nused++;
+
+ FUNC_LEAVE_NOAPI_NOFS(SUCCEED);
+} /* end H5FS_push() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FS_pop
+ *
+ * Purpose: Pops a record off function stack for the current thread.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, February 6, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_pop(void)
+{
+ H5FS_t *fstack = H5FS_get_my_stack ();
+
+ /* Don't push this function on the function stack... :-) */
+ FUNC_ENTER_NOAPI_NOFS(H5FS_pop);
+
+ /* Sanity check */
+ assert (fstack);
+ assert (fstack->nused>0);
+
+ /* Pop the function. */
+ fstack->nused--;
+
+ FUNC_LEAVE_NOAPI_NOFS(SUCCEED);
+} /* end H5FS_pop() */
+
+#endif /* H5_HAVE_FUNCSTACK */
diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h
new file mode 100644
index 0000000..6dba575
--- /dev/null
+++ b/src/H5FSprivate.h
@@ -0,0 +1,40 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Header file for function stacks, etc.
+ */
+#ifndef _H5FSprivate_H
+#define _H5FSprivate_H
+
+#ifdef NOT_YET
+#include "H5FSpublic.h"
+#endif /* NOT_YET */
+
+/* Private headers needed by this file */
+#include "H5private.h"
+
+#define H5FS_NSLOTS 32 /*number of slots in an function stack */
+
+/* A function stack */
+typedef struct H5FS_t {
+ int nused; /*num slots currently used in stack */
+ const char *slot[H5FS_NSLOTS]; /*array of function records */
+} H5FS_t;
+
+H5_DLL herr_t H5FS_push (const char *func_name);
+H5_DLL herr_t H5FS_pop (void);
+H5_DLL herr_t H5FS_print (FILE *stream);
+
+#endif /* _H5FSprivate_H */
diff --git a/src/H5TS.c b/src/H5TS.c
index ce3d5ef..c577ebc 100644
--- a/src/H5TS.c
+++ b/src/H5TS.c
@@ -30,6 +30,7 @@ typedef struct H5TS_cancel_struct {
/* Global variable definitions */
pthread_once_t H5TS_first_init_g = PTHREAD_ONCE_INIT;
pthread_key_t H5TS_errstk_key_g;
+pthread_key_t H5TS_funcstk_key_g;
pthread_key_t H5TS_cancel_key_g;
hbool_t H5TS_allow_concurrent_g = FALSE; /* concurrent APIs override this */
@@ -38,6 +39,36 @@ hbool_t H5TS_allow_concurrent_g = FALSE; /* concurrent APIs override this */
static void H5TS_mutex_init(H5TS_mutex_t *mutex);
#endif /* NOT_USED */
+
+/*--------------------------------------------------------------------------
+ * NAME
+ * H5TS_key_destructor
+ *
+ * USAGE
+ * H5TS_key_destructor()
+ *
+ * RETURNS
+ *
+ * DESCRIPTION
+ * Frees the memory for a key. Called by each thread as it exits.
+ * Currently all the thread-specific information for all keys are simple
+ * structures allocated with malloc, so we can free them all uniformly.
+ *
+ * PROGRAMMER: Quincey Koziol
+ * February 7, 2003
+ *
+ * MODIFICATIONS:
+ *
+ *--------------------------------------------------------------------------
+ */
+static void
+H5TS_key_destructor(void *key_val)
+{
+ /* Use HDfree here instead of H5MM_xfree(), to avoid calling the H5FS routines */
+ if(key_val!=NULL)
+ HDfree(key_val);
+}
+
/*--------------------------------------------------------------------------
* NAME
* H5TS_first_thread_init
@@ -73,46 +104,14 @@ H5TS_first_thread_init(void)
H5_g.init_lock.lock_count = 0;
/* initialize key for thread-specific error stacks */
- pthread_key_create(&H5TS_errstk_key_g, NULL);
+ pthread_key_create(&H5TS_errstk_key_g, H5TS_key_destructor);
- /* initialize key for thread cancellability mechanism */
- pthread_key_create(&H5TS_cancel_key_g, NULL);
-}
+ /* initialize key for thread-specific function stacks */
+ pthread_key_create(&H5TS_funcstk_key_g, H5TS_key_destructor);
-#ifdef NOT_USED
-/*--------------------------------------------------------------------------
- * NAME
- * H5TS_mutex_init
- *
- * USAGE
- * H5TS_mutex_init(&mutex_var)
- *
- * RETURNS
- *
- * DESCRIPTION
- * Recursive lock semantics for HDF5 (lock initialization) -
- * Multiple acquisition of a lock by a thread is permitted with a
- * corresponding unlock operation required.
- *
- * PROGRAMMER: Chee Wai LEE
- * May 2, 2000
- *
- * MODIFICATIONS:
- *
- * 19 May 2000, Bill Wendling
- * Changed (*foo). form of accessing structure members to the -> form.
- *
- *--------------------------------------------------------------------------
- */
-static void
-H5TS_mutex_init(H5TS_mutex_t *mutex)
-{
- H5_g.init_lock.owner_thread = NULL;
- pthread_mutex_init(&mutex->atomic_lock, NULL);
- pthread_cond_init(&mutex->cond_var, NULL);
- mutex->lock_count = 0;
+ /* initialize key for thread cancellability mechanism */
+ pthread_key_create(&H5TS_cancel_key_g, H5TS_key_destructor);
}
-#endif /* NOT_USED */
/*--------------------------------------------------------------------------
* NAME
diff --git a/src/H5TSprivate.h b/src/H5TSprivate.h
index c9a8c20..4ece8d6 100644
--- a/src/H5TSprivate.h
+++ b/src/H5TSprivate.h
@@ -34,6 +34,7 @@ typedef struct H5TS_mutex_struct {
/* Extern global variables */
extern pthread_once_t H5TS_first_init_g;
extern pthread_key_t H5TS_errstk_key_g;
+extern pthread_key_t H5TS_funcstk_key_g;
#if defined c_plusplus || defined __cplusplus
extern "C"
diff --git a/src/H5config.h.in b/src/H5config.h.in
index 1b7f58c..06928ff 100644
--- a/src/H5config.h.in
+++ b/src/H5config.h.in
@@ -21,15 +21,15 @@
/* Define to 1 if you have the <features.h> header file. */
#undef HAVE_FEATURES_H
+/* Define if support for Adler32 checksum is enabled */
+#undef HAVE_FILTER_ADLER32
+
/* Define if support for deflate filter is enabled */
#undef HAVE_FILTER_DEFLATE
/* Define if support for shuffle filter is enabled */
#undef HAVE_FILTER_SHUFFLE
-/* Define if support for Adler32 checksum filter is enabled */
-#undef HAVE_FILTER_ADLER32
-
/* Define to 1 if you have the `fork' function. */
#undef HAVE_FORK
@@ -39,6 +39,9 @@
/* Define to 1 if you have the `fseek64' function. */
#undef HAVE_FSEEK64
+/* Define if the function stack tracing code is to be compiled in */
+#undef HAVE_FUNCSTACK
+
/* Define if the compiler understand the __FUNCTION__ keyword */
#undef HAVE_FUNCTION
diff --git a/src/H5private.h b/src/H5private.h
index baff347..09e0f02 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -1091,6 +1091,18 @@ extern hbool_t H5_libinit_g; /* Has the library been initialized? */
#endif /* H5_HAVE_THREADSAFE */
+#ifdef H5_HAVE_FUNCSTACK
+
+/* Include required function stack header */
+#include "H5FSprivate.h"
+
+#define H5_PUSH_FUNC H5FS_push(FUNC)
+#define H5_POP_FUNC H5FS_pop()
+#else /* H5_HAVE_FUNCSTACK */
+#define H5_PUSH_FUNC /* void */
+#define H5_POP_FUNC /* void */
+#endif /* H5_HAVE_FUNCSTACK */
+
#ifdef H5_HAVE_MPE
extern hbool_t H5_MPEinit_g; /* Has the MPE Library been initialized? */
#endif
@@ -1149,6 +1161,7 @@ extern hbool_t H5_MPEinit_g; /* Has the MPE Library been initialized? */
FUNC_ENTER_API_VARS \
FUNC_ENTER_COMMON(func_name,H5_IS_API(FUNC)); \
FUNC_ENTER_API_THREADSAFE; \
+ H5_PUSH_FUNC; \
BEGIN_MPE_LOG(func_name); \
{
@@ -1159,7 +1172,7 @@ extern hbool_t H5_MPEinit_g; /* Has the MPE Library been initialized? */
{
/*
- * Use this macro for non-API functions which fall into two categories:
+ * Use this macro for non-API functions which fall into these categories:
* - static functions, since they must be called from a function in the
* interface, the library and interface must already be
* initialized.
@@ -1168,16 +1181,25 @@ extern hbool_t H5_MPEinit_g; /* Has the MPE Library been initialized? */
*/
#define FUNC_ENTER_NOINIT(func_name) { \
FUNC_ENTER_COMMON(func_name,!H5_IS_API(FUNC)); \
+ H5_PUSH_FUNC; \
+ {
+
+/*
+ * Use this macro for non-API functions which fall into these categories:
+ * - functions which shouldn't push their name on the function stack
+ * (so far, just the H5FS routines themselves)
+ */
+#define FUNC_ENTER_NOAPI_NOFS(func_name) { \
+ FUNC_ENTER_COMMON(func_name,!H5_IS_API(FUNC)); \
{
#define FUNC_ENTER_API_COMMON(func_name,interface_init_func,err) \
/* Initialize the library */ \
if (!(H5_INIT_GLOBAL)) { \
H5_INIT_GLOBAL = TRUE; \
- if (H5_init_library()<0) { \
+ if (H5_init_library()<0) \
HGOTO_ERROR (H5E_FUNC, H5E_CANTINIT, err, \
"library initialization failed"); \
- } \
} \
\
/* Initialize this interface or bust */ \
@@ -1190,7 +1212,11 @@ extern hbool_t H5_MPEinit_g; /* Has the MPE Library been initialized? */
"interface initialization failed"); \
} \
} \
- BEGIN_MPE_LOG(func_name)
+ \
+ /* Push the name of this function on the function stack */ \
+ H5_PUSH_FUNC; \
+ \
+ BEGIN_MPE_LOG(func_name)
#define FUNC_ENTER_NOAPI_INIT(func_name,interface_init_func,err) \
/* Initialize this interface or bust */ \
@@ -1202,7 +1228,10 @@ extern hbool_t H5_MPEinit_g; /* Has the MPE Library been initialized? */
HGOTO_ERROR (H5E_FUNC, H5E_CANTINIT, err, \
"interface initialization failed"); \
} \
- }
+ } \
+ \
+ /* Push the name of this function on the function stack */ \
+ H5_PUSH_FUNC;
/*-------------------------------------------------------------------------
* Purpose: Register function exit for code profiling. This should be
@@ -1223,6 +1252,7 @@ extern hbool_t H5_MPEinit_g; /* Has the MPE Library been initialized? */
FINISH_MPE_LOG; \
PABLO_TRACE_OFF (PABLO_MASK, pablo_func_id); \
H5TRACE_RETURN(ret_value); \
+ H5_POP_FUNC; \
H5_API_UNLOCK \
H5_API_SET_CANCEL \
return (ret_value); \
@@ -1231,17 +1261,30 @@ extern hbool_t H5_MPEinit_g; /* Has the MPE Library been initialized? */
#define FUNC_LEAVE_NOAPI(ret_value) \
PABLO_TRACE_OFF (PABLO_MASK, pablo_func_id); \
+ H5_POP_FUNC; \
return (ret_value); \
} /*end scope from end of FUNC_ENTER*/ \
} /*end scope from beginning of FUNC_ENTER*/
#define FUNC_LEAVE_NOAPI_VOID \
PABLO_TRACE_OFF (PABLO_MASK, pablo_func_id); \
+ H5_POP_FUNC; \
return; \
} /*end scope from end of FUNC_ENTER*/ \
} /*end scope from beginning of FUNC_ENTER*/
/*
+ * Use this macro for non-API functions which fall into these categories:
+ * - functions which didn't push their name on the function stack
+ * (so far, just the H5FS routines themselves)
+ */
+#define FUNC_LEAVE_NOAPI_NOFS(ret_value) \
+ PABLO_TRACE_OFF (PABLO_MASK, pablo_func_id); \
+ return (ret_value); \
+ } /*end scope from end of FUNC_ENTER*/ \
+} /*end scope from beginning of FUNC_ENTER*/
+
+/*
* The FUNC_ENTER() and FUNC_LEAVE() macros make calls to Pablo functions
* through one of these two sets of macros.
*/
diff --git a/src/Makefile.in b/src/Makefile.in
index a783909..db8c717 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -32,8 +32,8 @@ LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5D.c H5E.c H5F.c H5Farray.c H5Fcontig.c \
H5Fcompact.c H5Fistore.c H5Fseq.c H5FD.c H5FDcore.c H5FDfamily.c \
H5FDfphdf5.c H5FDgass.c H5FDlog.c H5FDmpio.c H5FDmpiposix.c \
H5FDmulti.c H5FDsec2.c H5FDsrb.c H5FDstdio.c H5FDstream.c H5FL.c \
- H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5G.c H5Gent.c H5Gnode.c \
- H5Gstab.c H5HG.c H5HL.c H5I.c H5MF.c H5MM.c H5O.c H5Oattr.c \
+ H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c H5G.c H5Gent.c \
+ H5Gnode.c H5Gstab.c H5HG.c H5HL.c H5I.c H5MF.c H5MM.c H5O.c H5Oattr.c \
H5Obogus.c H5Ocont.c H5Odtype.c H5Oefl.c H5Ofill.c H5Ofphdf5.c \
H5Olayout.c H5Omtime.c H5Oname.c H5Onull.c H5Opline.c H5Oplist.c \
H5Osdspace.c H5Oshared.c H5Ostab.c H5P.c H5Pdcpl.c H5Pdxpl.c \
@@ -58,13 +58,12 @@ PUB_HDR=H5public.h H5Apublic.h H5ACpublic.h H5Bpublic.h H5Dpublic.h \
## Other header files (not to be installed)...
PRIVATE_HDR=H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \
- H5Dprivate.h H5Eprivate.h H5Fprivate.h H5FDprivate.h \
- H5FLprivate.h H5FOprivate.h H5FPprivate.h H5Gprivate.h H5Gpkg.h \
- H5HGprivate.h H5HLprivate.h H5Iprivate.h H5MFprivate.h \
- H5MMprivate.h H5Oprivate.h H5Pprivate.h H5Ppkg.h H5Rprivate.h \
- H5RSprivate.h H5Sprivate.h H5STprivate.h H5Tprivate.h \
- H5TBprivate.h H5Tpkg.h H5TSprivate.h H5Vprivate.h H5Zprivate.h \
- H5config.h
+ H5Dprivate.h H5Eprivate.h H5Fprivate.h H5FDprivate.h H5FLprivate.h \
+ H5FOprivate.h H5FPprivate.h H5FSprivate.h H5Gprivate.h H5Gpkg.h \
+ H5HGprivate.h H5HLprivate.h H5Iprivate.h H5MFprivate.h H5MMprivate.h \
+ H5Oprivate.h H5Pprivate.h H5Ppkg.h H5Rprivate.h H5RSprivate.h \
+ H5Sprivate.h H5STprivate.h H5Tprivate.h H5TBprivate.h H5Tpkg.h \
+ H5TSprivate.h H5Vprivate.h H5Zprivate.h H5config.h
## Number format detection
## The LD_LIBRARY_PATH setting is a klutch.
diff --git a/test/bittests.c b/test/bittests.c
index a5af191..e1f01f9 100644
--- a/test/bittests.c
+++ b/test/bittests.c
@@ -513,6 +513,14 @@ main (void)
{
int nerrors=0;
+ /*
+ * Open the library explicitly for thread-safe builds, so per-thread
+ * things are initialized correctly.
+ */
+#ifdef H5_HAVE_THREADSAFE
+ H5open();
+#endif /* H5_HAVE_THREADSAFE */
+
nerrors += test_find ()<0?1:0;
nerrors += test_set ()<0?1:0;
nerrors += test_clear()<0?1:0;
@@ -524,5 +532,9 @@ main (void)
exit(1);
}
printf("All bit tests passed.\n");
+
+#ifdef H5_HAVE_THREADSAFE
+ H5close();
+#endif /* H5_HAVE_THREADSAFE */
return 0;
}
diff --git a/test/hyperslab.c b/test/hyperslab.c
index 2844ec6..aa43d96 100644
--- a/test/hyperslab.c
+++ b/test/hyperslab.c
@@ -1114,6 +1114,14 @@ main(int argc, char *argv[])
printf("\n");
/*
+ * Open the library explicitly for thread-safe builds, so per-thread
+ * things are initialized correctly.
+ */
+#ifdef H5_HAVE_THREADSAFE
+ H5open();
+#endif /* H5_HAVE_THREADSAFE */
+
+ /*
*------------------------------
* TEST HYPERSLAB FILL OPERATION
*------------------------------
@@ -1259,5 +1267,9 @@ main(int argc, char *argv[])
exit(1);
}
printf("All hyperslab tests passed.\n");
+
+#ifdef H5_HAVE_THREADSAFE
+ H5close();
+#endif /* H5_HAVE_THREADSAFE */
return 0;
}
diff --git a/test/ttsafe_cancel.c b/test/ttsafe_cancel.c
index 2d2ce3f..8e47d09 100644
--- a/test/ttsafe_cancel.c
+++ b/test/ttsafe_cancel.c
@@ -86,6 +86,9 @@ void tts_cancel(void)
H5Dclose(dataset);
H5Fclose(cancel_file);
+
+ /* Destroy the thread attribute */
+ pthread_attr_destroy(&attribute);
}
void *tts_cancel_thread(void *arg)
@@ -201,7 +204,6 @@ void tts_cancel_barrier(void)
void cleanup_cancel(void)
{
- H5close();
HDunlink(FILENAME);
}
diff --git a/test/ttsafe_dcreate.c b/test/ttsafe_dcreate.c
index ae4fdbc..d85dbe7 100644
--- a/test/ttsafe_dcreate.c
+++ b/test/ttsafe_dcreate.c
@@ -44,140 +44,148 @@ typedef struct thread_info {
} thread_info;
/*
+ * Set individual dataset names (rather than generated the names
+ * automatically)
+ */
+const char *dsetname[NUM_THREAD]={
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "ten",
+ "eleven",
+ "twelve",
+ "thirteen",
+ "fourteen",
+ "fifteen"
+};
+
+thread_info thread_out[NUM_THREAD];
+
+/*
**********************************************************************
* Thread safe test - multiple dataset creation
**********************************************************************
*/
void tts_dcreate(void)
{
- /* Pthread definitions */
- pthread_t threads[NUM_THREAD];
-
- /* HDF5 data definitions */
- hid_t file, dataset, datatype;
- int datavalue, i;
- thread_info *thread_out;
- const char *dsetname[NUM_THREAD];
- pthread_attr_t attribute;
-
- /* set pthread attribute to perform global scheduling */
- pthread_attr_init(&attribute);
- pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM);
-
- /*
- * Set individual dataset names (rather than generated the names
- * automatically)
- */
-
- for (i = 0; i < NUM_THREAD; i++)
- dsetname[i] = malloc(sizeof(char) * DATASETNAME_LENGTH);
-
- dsetname[0] = "zero";
- dsetname[1] = "one";
- dsetname[2] = "two";
- dsetname[3] = "three";
- dsetname[4] = "four";
- dsetname[5] = "five";
- dsetname[6] = "six";
- dsetname[7] = "seven";
- dsetname[8] = "eight";
- dsetname[9] = "nine";
- dsetname[10] = "ten";
- dsetname[11] = "eleven";
- dsetname[12] = "twelve";
- dsetname[13] = "thirteen";
- dsetname[14] = "fourteen";
- dsetname[15] = "fifteen";
-
- /*
- * Create a hdf5 file using H5F_ACC_TRUNC access, default file
- * creation plist and default file access plist
- */
- file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
-
- /* simultaneously create a large number of datasets within the file */
- for (i = 0; i < NUM_THREAD; i++) {
- thread_out = malloc(sizeof(thread_info));
- thread_out->id = i;
- thread_out->file = file;
- thread_out->dsetname = dsetname[i];
- pthread_create(&threads[i], NULL, tts_dcreate_creator, thread_out);
- }
-
- for (i = 0;i < NUM_THREAD; i++)
- pthread_join(threads[i], NULL);
-
- /* compare data to see if it is written correctly */
-
- /* define datatype for the data using native little endian integers */
- datatype = H5Tcopy(H5T_NATIVE_INT);
-
- for (i = 0; i < NUM_THREAD; i++) {
- if ((dataset = H5Dopen(file,dsetname[i])) < 0) {
- fprintf(stderr, "Dataset name not found - test failed\n");
- H5Fclose(file);
- num_errs++;
- return;
- } else {
- H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue);
-
- if (datavalue != i) {
- fprintf(stderr,
- "Wrong value read %d for dataset name %s - test failed\n",
- datavalue, dsetname[i]);
- H5Dclose(dataset);
- H5Fclose(file);
- num_errs++;
- return;
- }
-
- H5Dclose(dataset);
- }
- }
-
- /* close remaining resources */
- H5Fclose(file);
+ /* Pthread definitions */
+ pthread_t threads[NUM_THREAD];
+
+ /* HDF5 data definitions */
+ hid_t file, dataset;
+ int datavalue, i;
+ pthread_attr_t attribute;
+ int ret;
+
+ /* set pthread attribute to perform global scheduling */
+ ret=pthread_attr_init(&attribute);
+ assert(ret==0);
+ ret=pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM);
+/* Don't check return value on FreeBSD, since PTHREAD_SCOPE_SYSTEM is not
+ * currently supported in v4.7
+ */
+#ifndef __FreeBSD__
+ assert(ret==0);
+#endif /* __FreeBSD__ */
+
+ /*
+ * Create a hdf5 file using H5F_ACC_TRUNC access, default file
+ * creation plist and default file access plist
+ */
+ file = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ assert(file>=0);
+
+ /* simultaneously create a large number of datasets within the file */
+ for (i = 0; i < NUM_THREAD; i++) {
+ thread_out[i].id = i;
+ thread_out[i].file = file;
+ thread_out[i].dsetname = dsetname[i];
+ ret=pthread_create(&threads[i], NULL, tts_dcreate_creator, &thread_out[i]);
+ assert(ret==0);
+ }
+
+ for (i = 0;i < NUM_THREAD; i++) {
+ ret=pthread_join(threads[i], NULL);
+ assert(ret==0);
+ } /* end for */
+
+ /* compare data to see if it is written correctly */
+
+ for (i = 0; i < NUM_THREAD; i++) {
+ if ((dataset = H5Dopen(file,dsetname[i])) < 0) {
+ fprintf(stderr, "Dataset name not found - test failed\n");
+ H5Fclose(file);
+ num_errs++;
+ return;
+ } else {
+ ret=H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &datavalue);
+ assert(ret>=0);
+
+ if (datavalue != i) {
+ fprintf(stderr, "Wrong value read %d for dataset name %s - test failed\n",
+ datavalue, dsetname[i]);
+ H5Dclose(dataset);
+ H5Fclose(file);
+ num_errs++;
+ return;
+ }
+
+ ret=H5Dclose(dataset);
+ assert(ret>=0);
+ }
+ }
+
+ /* close remaining resources */
+ ret=H5Fclose(file);
+ assert(ret>=0);
+
+ /* Destroy the thread attribute */
+ ret=pthread_attr_destroy(&attribute);
+ assert(ret==0);
}
-void *tts_dcreate_creator(void *thread_data)
+void *tts_dcreate_creator(void *_thread_data)
{
- hid_t dataspace, datatype, dataset;
+ hid_t dataspace, dataset;
+ herr_t ret;
hsize_t dimsf[1]; /* dataset dimensions */
- struct thread_info {
- int id;
- hid_t file;
- char *dsetname;
- } thread_in;
+ struct thread_info thread_data;
- thread_in.dsetname = malloc(sizeof(char) * DATASETNAME_LENGTH);
- thread_in = *((struct thread_info *)thread_data);
+ memcpy(&thread_data,_thread_data,sizeof(struct thread_info));
/* define dataspace for dataset */
dimsf[0] = 1;
dataspace = H5Screate_simple(1,dimsf,NULL);
-
- /* define datatype for the data using native little endian integers */
- datatype = H5Tcopy(H5T_NATIVE_INT);
- H5Tset_order(datatype, H5T_ORDER_LE);
+ assert(dataspace>=0);
/* create a new dataset within the file */
- dataset = H5Dcreate(thread_in.file, thread_in.dsetname,
- datatype, dataspace, H5P_DEFAULT);
+ dataset = H5Dcreate(thread_data.file, thread_data.dsetname,
+ H5T_NATIVE_INT, dataspace, H5P_DEFAULT);
+ assert(dataset>=0);
/* initialize data for dataset and write value to dataset */
- H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
- H5P_DEFAULT, &thread_in.id);
+ ret=H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, &thread_data.id);
+ assert(ret>=0);
+
+ /* close dataset and dataspace resources */
+ ret=H5Dclose(dataset);
+ assert(ret>=0);
+ ret=H5Sclose(dataspace);
+ assert(ret>=0);
- /* close dataset, datatype and dataspace resources */
- H5Dclose(dataset);
- H5Tclose(datatype);
- H5Sclose(dataspace);
return NULL;
}
void cleanup_dcreate(void)
{
- H5close();
HDunlink(FILENAME);
}
#endif /*H5_HAVE_THREADSAFE*/
diff --git a/test/ttsafe_error.c b/test/ttsafe_error.c
index 54ffc4b..e911863 100644
--- a/test/ttsafe_error.c
+++ b/test/ttsafe_error.c
@@ -130,6 +130,9 @@ void tts_error(void)
/* turn our error stack handler off */
H5Eset_auto(old_error_cb, old_error_client_data);
+
+ /* Destroy the thread attribute */
+ pthread_attr_destroy(&attribute);
}
static