summaryrefslogtreecommitdiffstats
path: root/src/H5.c
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1998-11-21 03:36:51 (GMT)
committerRobb Matzke <matzke@llnl.gov>1998-11-21 03:36:51 (GMT)
commit7488c6366e878651f6bb8dc94f05eb69cd0df83b (patch)
treec2ba0295a0bec1b350fa3d4fa291b46ac75e271f /src/H5.c
parent6345a417a3930b32ec9e5fc087e0aeb20a94aed7 (diff)
downloadhdf5-7488c6366e878651f6bb8dc94f05eb69cd0df83b.zip
hdf5-7488c6366e878651f6bb8dc94f05eb69cd0df83b.tar.gz
hdf5-7488c6366e878651f6bb8dc94f05eb69cd0df83b.tar.bz2
[svn-r936] Changes since 19981119
---------------------- ./src/H5.c ./src/H5A.c ./src/H5AC.c ./src/H5B.c ./src/H5D.c ./src/H5E.c ./src/H5F.c ./src/H5Farray.c ./src/H5Fcore.c ./src/H5Ffamily.c ./src/H5Fistore.c ./src/H5Flow.c ./src/H5Fmpio.c ./src/H5Fsec2.c ./src/H5Fsplit.c ./src/H5Fstdio.c ./src/H5G.c ./src/H5Gent.c ./src/H5Gnode.c ./src/H5Gstab.c ./src/H5HG.c ./src/H5HL.c ./src/H5I.c ./src/H5Iprivate.h ./src/H5MF.c ./src/H5MM.c ./src/H5O.c ./src/H5Oattr.c ./src/H5Ocomp.c ./src/H5Ocont.c ./src/H5Odtype.c ./src/H5Oefl.c ./src/H5Ofill.c ./src/H5Olayout.c ./src/H5Omtime.c ./src/H5Oname.c ./src/H5Osdspace.c ./src/H5Oshared.c ./src/H5Ostab.c ./src/H5P.c ./src/H5R.c ./src/H5RA.c ./src/H5S.c ./src/H5Sall.c ./src/H5Shyper.c ./src/H5Smpio.c ./src/H5Snone.c ./src/H5Spoint.c ./src/H5Sselect.c ./src/H5T.c ./src/H5TB.c ./src/H5Tbit.c ./src/H5Tconv.c ./src/H5V.c ./src/H5Z.c ./src/H5detect.c ./src/H5private.h Most of these changes are because the `interface_initialize_g' variable change from hbool_t to int. It's a one line change. Changed the way the library is closed so we have more control over the order the interfaces are shut down. Instead of registering an atexit() function for every interface in some haphazard order we just register one: H5_term_library() which then calls the H5*_term_interface() functions in a well-defined order. If the library is closed and then reopened repeatedly by calling H5close() and H5open() in a loop we only add one copy of the library termination functions with atexit(). Termination is a two-step process in order to help detect programming errors that would cause an infinite loop caused by the termination of one interface waking up some other previously terminated interface. The first step terminates the interface and *marks it as unusable*. After all interfaces are terminated then we mark them all as usable again. The FUNC_ENTER() macro has been modified to return failure or to dump core (depending on whether NDEBUG is defined) if we try to call an interface while it's shutting down. ./src/H5.c The H5dont_atexit() function returns failure if it's called more than once or if it's called too late. However, the error stack is not automatically printed on failure because the library might not be initialized yet ./test/chunk.c ./test/flush1.c ./test/flush2.c ./test/iopipe.c ./test/overhead.c ./test/ragged.c Changed the extra cast for Win32 so we do floating point division again -- it was just confusion about precedence and associativity of casting and the C coercion rules. Removed extra carriage returns inserted by broken operating system. ./src/H5Ffamily.c Fixed an bug where H5F_fam_write() lowered the EOF marker for one of the family members causing H5F_fam_read() to read zeros. ./test/h5test.h [NEW] ./test/h5test.c [NEW] ./test/Makefile.in ./test/bittests.c ./test/cmpd_dset.c ./test/dsets.c ./test/dtypes.c ./test/extend.c ./test/external.c Support library for test files. This isn't done yet but Katie's contractions are ~10 minutes apart so I figured I better back this stuff up just in case I'm not here next week... Eventually all test files will understand HDF5_DRIVER to name the low level file driver and parameters so we can easily test various drivers. They will also understand HDF5_PREFIX to prepend to the beginning of file names which is necessary for testing ROMIO with various drivers. Also, the cleanup function will know how to use the file name prefix and will understand different file driver naming schemes like file families. I'm not sure they'll understand the `gsf:' type prefixes yet. Note, the external test is completely commented out because I'm in the middle of modifying it. It will still compile and run but it doesn't test anything at the moment.
Diffstat (limited to 'src/H5.c')
-rw-r--r--src/H5.c329
1 files changed, 119 insertions, 210 deletions
diff --git a/src/H5.c b/src/H5.c
index 42d19dc..f97409d 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -16,26 +16,6 @@ static char RcsId[] = "@(#)$Revision$";
/* $Id$ */
-/*LINTLIBRARY */
-/*+
- FILE
- hdf5.c
- HDF library support routines
-
- EXPORTED ROUTINES
- H5dont_atexit -- Indicate that an 'atexit' routine is _not_ to be installed
- H5get_libversion -- Check the version of the library
-
- LIBRARY-SCOPED ROUTINES
- H5_init_library -- initialize the HDF5 library
- H5_term_library -- shut-down the HDF5 library
- H5_init_thread -- initialize thread-specific information
-
- LOCAL ROUTINES
- H5_init_interface -- initialize the H5 interface
- + */
-
-
/* private headers */
#include <H5private.h> /*library */
#include <H5ACprivate.h> /*cache */
@@ -44,7 +24,7 @@ static char RcsId[] = "@(#)$Revision$";
#include <H5Iprivate.h> /*atoms */
#include <H5MMprivate.h> /*memory management */
#include <H5Pprivate.h> /*property lists */
-#include <H5Rpublic.h> /* References */
+#include <H5Rpublic.h> /*references */
#include <H5Sprivate.h> /*data spaces */
#include <H5Tprivate.h> /*data types */
#include <H5Zprivate.h> /*filters */
@@ -55,22 +35,13 @@ FILE *fdopen(int fd, const char *mode);
#define PABLO_MASK H5_mask
hbool_t library_initialize_g = FALSE;
-hbool_t thread_initialize_g = FALSE;
-hbool_t install_atexit_g = TRUE;
+hbool_t dont_atexit_g = FALSE;
H5_debug_t H5_debug_g; /*debugging info */
static void H5_debug_mask(const char*);
-typedef struct H5_exit {
- void (*func) (void); /* Interface function to call during exit */
- struct H5_exit *next; /* Pointer to next node with exit function */
-} H5_exit_t;
-
-H5_exit_t *lib_exit_head; /* Pointer to the head of the list of 'atexit' functions */
-
/* Interface initialization */
-static hbool_t interface_initialize_g = FALSE;
-#define INTERFACE_INIT H5_init_interface
-static herr_t H5_init_interface(void);
+static intn interface_initialize_g = 0;
+#define INTERFACE_INIT NULL
/*--------------------------------------------------------------------------
NAME
@@ -112,13 +83,17 @@ H5_init_library(void)
H5_debug_g.pkg[H5_PKG_V].name = "v";
H5_debug_g.pkg[H5_PKG_Z].name = "z";
- /* Install atexit() library cleanup routine */
- if (install_atexit_g == TRUE &&
- HDatexit(&H5_term_library) != 0) {
- HRETURN_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL,
- "unable to register atexit function");
+ /*
+ * Install atexit() library cleanup routine unless the H5dont_atexit()
+ * has been called. Once we add something to the atexit() list it stays
+ * there permanently, so we set dont_atexit_g after we add it to prevent
+ * adding it again later if the library is cosed and reopened.
+ */
+ if (!dont_atexit_g) {
+ atexit(H5_term_library);
+ dont_atexit_g = TRUE;
}
-
+
/*
* Initialize interfaces that might not be able to initialize themselves
* soon enough.
@@ -135,187 +110,113 @@ H5_init_library(void)
FUNC_LEAVE(SUCCEED);
}
-/*--------------------------------------------------------------------------
- NAME
- H5_add_exit
- PURPOSE
- Add an exit routine to the list of routines to call during 'atexit'
- USAGE
- herr_t H5_add_exit(func)
- void (*func)(void); IN: Function pointer of routine to add to chain
-
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- Pre-pend the new function to the list of function to call during the exit
- process. These routines are responsible for free'ing static buffers, etc.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- Don't make assumptions about the environment during the exit procedure...
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5_add_exit(void (*func)(void))
-{
- H5_exit_t *new_exit;
-
- FUNC_ENTER_INIT(H5_add_exit, NULL, FAIL);
-
- assert(func);
-
- if (NULL==(new_exit = H5MM_calloc(sizeof(H5_exit_t)))) {
- HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,
- "memory allocation failed");
- }
-
- new_exit->func = func;
- new_exit->next = lib_exit_head;
- lib_exit_head = new_exit;
-
- FUNC_LEAVE(SUCCEED);
-} /* end H5_add_exit() */
-
-/*--------------------------------------------------------------------------
- NAME
- H5_term_library
- PURPOSE
- Terminate various static buffers and shutdown the library.
- USAGE
- void H5_term_library()
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- Walk through the shutdown routines for the various interfaces and
- terminate them all.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- Should only ever be called by the "atexit" function, or real power-users.
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------
+ * Function: H5_term_library
+ *
+ * Purpose: Terminate interfaces in a well-defined order due to
+ * dependencies among the interfaces, then terminate
+ * library-specific data.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 20, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
void
H5_term_library(void)
{
- H5_exit_t *temp;
-
- temp = lib_exit_head;
- while (lib_exit_head != NULL) {
- (*lib_exit_head->func) ();
- lib_exit_head = lib_exit_head->next;
- HDfree(temp);
- temp = lib_exit_head;
- } /* end while */
-} /* end H5_term_library() */
-
-/*--------------------------------------------------------------------------
-NAME
- H5_init_thread -- Initialize thread-specific information
-USAGE
- void H5_init_thread()
-
-RETURNS
- Non-negative on success/Negative on failure
-DESCRIPTION
- Initializes any thread-specific data or routines.
-
---------------------------------------------------------------------------*/
-herr_t
-H5_init_thread(void)
-{
- FUNC_ENTER_INIT(H5_init_thread, NULL, FAIL);
-
- /* Add the "thread termination" routine to the exit chain */
- if (H5_add_exit(&H5_term_thread)<0)
- HRETURN_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL,
- "unable to set thread atexit function");
-
- FUNC_LEAVE(SUCCEED);
-} /* H5_init_thread */
-
-/*--------------------------------------------------------------------------
- NAME
- H5_term_thread
- PURPOSE
- Terminate various thread-specific objects
- USAGE
- void H5_term_thread()
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- Release the error stack and any other thread-specific resources allocated
- on a "per thread" basis.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- Can't report errors...
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-void
-H5_term_thread(void)
-{/*void*/}
+ /* Don't do anything if the library is already closed */
+ if (!library_initialize_g) return;
-/*--------------------------------------------------------------------------
-NAME
- H5_init_interface -- Initialize interface-specific information
-USAGE
- herr_t H5_init_interface()
-
-RETURNS
- Non-negative on success/Negative on failure
-DESCRIPTION
- Initializes any interface-specific data or routines.
+ /*
+ * Close interfaces in a well-defined order based on dependencies. The
+ * goal is that closing one interface doesn't reopen another that was
+ * just closed. In order to help us track down dependencies that we
+ * didn't know about, we close the interfaces in a two step process. The
+ * first step does the real work and makes the interface unusable. The
+ * second step doesn't do any work but makes it possible to reopen the
+ * interface later.
+ */
---------------------------------------------------------------------------*/
-static herr_t
-H5_init_interface(void)
-{
- FUNC_ENTER(H5_init_interface, FAIL);
+ /* Function What depends on it? */
+ /*------------------------- ------------------------------- */
+ H5D_term_interface(-1); /* */
+ H5TB_term_interface(-1); /* */
+ H5Z_term_interface(-1); /* */
+ H5A_term_interface(-1); /* */
+ H5RA_term_interface(-1); /* */
+ H5F_term_interface(-1); /* T */
+ H5G_term_interface(-1); /* */
+ H5R_term_interface(-1); /* */
+ H5S_term_interface(-1); /* */
+ H5T_native_close(-1); /* D RA */
+ H5T_term_interface(-1); /* D RA */
+ H5P_term_interface(-1); /* D */
+ H5I_term_interface(-1); /* A D F G P RA S T TB Z */
+ /*------------------------- --------------------------------- */
- FUNC_LEAVE(SUCCEED);
-} /* H5_init_interface */
+ /*
+ * Finalize the closing by calling all the functions again but with an
+ * argument of zero. This allows the interface to be reopened later.
+ */
+ H5A_term_interface(0);
+ H5D_term_interface(0);
+ H5F_term_interface(0);
+ H5G_term_interface(0);
+ H5I_term_interface(0);
+ H5P_term_interface(0);
+ H5RA_term_interface(0);
+ H5R_term_interface(0);
+ H5S_term_interface(0);
+ H5TB_term_interface(0);
+ H5T_native_close(0);
+ H5T_term_interface(0);
+ H5Z_term_interface(0);
+
+ /* Mark library as closed */
+ library_initialize_g = FALSE;
+}
-/*--------------------------------------------------------------------------
- NAME
- H5dont_atexit
- PURPOSE
- Indicates to the library that an 'atexit()' routine is _not_ to be installed
- USAGE
- herr_t H5dont_atexit(void)
- RETURNS
- Non-negative on success/Negative on failure
- DESCRIPTION
- This routine indicates to the library that an 'atexit()' cleanip routine
- should not be installed. The major (only?) purpose for this is in
- situations where the library is dynamically linked into an application and
- is un-linked from the application before 'exit()' gets callled. In those
- situations, a routine installed with 'atexit()' would jump to a routine
- which was no longer in memory, causing errors.
- In order to be effective, this routine _must_ be called before any other
- HDF function calls, and must be called each time the library is loaded/
- linked into the application. (the first time and after it's been un-loaded)
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- If this routine is used, certain memory buffers will not be de-allocated,
- although in theory a user could call HPend on their own...
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------
+ * Function: H5dont_atexit
+ *
+ * Purpose: Indicates that the library is not to clean up after itself
+ * when the application exits by calling exit() or returning
+ * from main(). This function must be called before any other
+ * HDF5 function or constant is used or it will have no effect.
+ *
+ * If this function is used then certain memory buffers will not
+ * be de-allocated nor will open files be flushed automatically.
+ * The application may still call H5close() explicitly to
+ * accomplish these things.
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative if this function is called more than
+ * once or if it is called too late.
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 20, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
herr_t
H5dont_atexit(void)
{
-#ifdef DONT_DO_THIS
- FUNC_ENTER_INIT(H5dont_atexit, NULL, FAIL);
-#endif /* DONT_DO_THIS */
-
- if (install_atexit_g == TRUE)
- install_atexit_g = FALSE;
-
-#ifdef DONT_DO_THIS
- FUNC_LEAVE(SUCCEED);
-#else /* DONT_DO_THIS */
+ /* FUNC_ENTER_INIT() should not be called */
+ H5_trace(FALSE, "H5dont_atexit", "");
+ if (dont_atexit_g) return FAIL;
+ dont_atexit_g = TRUE;
+ H5_trace(TRUE, NULL, "e", SUCCEED);
return(SUCCEED);
-#endif /* DONT_DO_THIS */
}
@@ -531,7 +432,7 @@ H5close (void)
* thing just to release it all right away. It is safe to call this
* function for an uninitialized library.
*/
- H5_term_library ();
+ H5_term_library();
return SUCCEED;
}
@@ -1138,6 +1039,12 @@ H5_bandwidth(char *buf/*out*/, double nbytes, double nseconds)
* Note: The TYPE string is meant to be terse and is generated by a
* separate perl script.
*
+ * WARNING: DO NOT CALL ANY HDF5 FUNCTION THAT CALLS FUNC_ENTER(). DOING
+ * SO MAY CAUSE H5_trace() TO BE INVOKED RECURSIVELY OR MAY
+ * CAUSE LIBRARY INITIALIZATIONS THAT ARE NOT DESIRED. DO NOT
+ * USE THE H5T_*_* CONSTANTS SINCE THEY CALL H5_open() WHICH
+ * INVOKES FUNC_ENTER().
+ *
* Return: void
*
* Programmer: Robb Matzke
@@ -1159,6 +1066,8 @@ H5_trace (hbool_t returning, const char *func, const char *type, ...)
void *vp = NULL;
FILE *out = H5_debug_g.trace;
+ /* FUNC_ENTER() should not be called */
+
if (!out) return; /*tracing is off*/
va_start (ap, type);