summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2004-07-09 02:06:29 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2004-07-09 02:06:29 (GMT)
commitfe76fb1b580aa99fa26ccb26da88ce7e16b35a84 (patch)
treeb90b9832ec612a2d7efead8c6bea6c767edc5b15 /src
parentd5c705a642a1ed06fa8dcaa25b61aa75687799d2 (diff)
downloadhdf5-fe76fb1b580aa99fa26ccb26da88ce7e16b35a84.zip
hdf5-fe76fb1b580aa99fa26ccb26da88ce7e16b35a84.tar.gz
hdf5-fe76fb1b580aa99fa26ccb26da88ce7e16b35a84.tar.bz2
[svn-r8844] Purpose:
Bug fix Description: The "shared" raw B-tree node can get freed before all the B-tree nodes had been flushed out to disk and released by the cache. Solution: Implement a simple reference counting wrapper for objects in the library and use it to hold the shared raw B-tree nodes so they aren't freed before all references to them in memory are released. Platforms tested: Solaris 2.7 (arabica) FreeBSD 4.10 (sleipnir) IRIX64 6.5 (modei4)
Diffstat (limited to 'src')
-rw-r--r--src/H5B.c10
-rw-r--r--src/H5Bpkg.h2
-rw-r--r--src/H5Distore.c44
-rw-r--r--src/H5F.c12
-rw-r--r--src/H5Fpkg.h3
-rw-r--r--src/H5Fprivate.h7
-rw-r--r--src/H5G.c5
-rw-r--r--src/H5Gnode.c46
-rw-r--r--src/H5Oprivate.h3
-rw-r--r--src/H5RC.c129
-rw-r--r--src/H5RCprivate.h62
-rw-r--r--src/Makefile.in8
12 files changed, 303 insertions, 28 deletions
diff --git a/src/H5B.c b/src/H5B.c
index 0da67bb..5529aea 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -241,8 +241,9 @@ H5B_create(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, void *udata,
bt->left = HADDR_UNDEF;
bt->right = HADDR_UNDEF;
bt->nchildren = 0;
- if((bt->raw_page=(type->get_page)(f, udata))==NULL)
+ if((bt->rc_page=(type->get_page)(f, udata))==NULL)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "can't retrieve B-tree node buffer")
+ bt->raw_page=H5RC_GET_OBJ(bt->rc_page);
if (NULL==(bt->native=H5FL_BLK_MALLOC(native_block,total_native_keysize)) ||
NULL==(bt->child=H5FL_SEQ_MALLOC(haddr_t,(size_t)(2*H5F_KVALUE(f,type)))) ||
NULL==(bt->nkey=H5FL_SEQ_MALLOC(voidp,(size_t)(2*H5F_KVALUE(f,type)+1))))
@@ -340,8 +341,9 @@ H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata)
NULL==(bt->child=H5FL_SEQ_MALLOC(haddr_t,(size_t)(2*H5F_KVALUE(f,type)))))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- if((bt->raw_page=(type->get_page)(f, udata))==NULL)
+ if((bt->rc_page=(type->get_page)(f, udata))==NULL)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "can't retrieve B-tree node buffer")
+ bt->raw_page=H5RC_GET_OBJ(bt->rc_page);
if (H5F_block_read(f, H5FD_MEM_BTREE, addr, size, dxpl_id, bt->raw_page)<0)
HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree node")
@@ -574,6 +576,7 @@ H5B_dest(H5F_t UNUSED *f, H5B_t *bt)
H5FL_SEQ_FREE(haddr_t,bt->child);
H5FL_SEQ_FREE(voidp,bt->nkey);
H5FL_BLK_FREE(native_block,bt->native);
+ H5RC_DEC(bt->rc_page);
H5FL_FREE(H5B_t,bt);
FUNC_LEAVE_NOAPI(SUCCEED)
@@ -2203,6 +2206,9 @@ H5B_copy(const H5F_t *f, const H5B_t *old_bt)
new_node->nkey[u] = NULL;
}
+ /* Increment the ref-count on the raw page */
+ H5RC_INC(new_node->rc_page);
+
/* Set return value */
ret_value=new_node;
diff --git a/src/H5Bpkg.h b/src/H5Bpkg.h
index 67b49db..67135cf 100644
--- a/src/H5Bpkg.h
+++ b/src/H5Bpkg.h
@@ -31,6 +31,7 @@
#include "H5Bprivate.h"
/* Other private headers needed by this file */
+#include "H5RCprivate.h" /* Reference counted object functions */
/**************************/
/* Package Private Macros */
@@ -54,6 +55,7 @@ struct H5B_t {
haddr_t left; /*address of left sibling */
haddr_t right; /*address of right sibling */
unsigned nchildren; /*number of child pointers */
+ H5RC_t *rc_page; /*ref-counted disk page */
uint8_t *raw_page; /*disk page (shared) */
uint8_t *native; /*array of keys in native format */
void **nkey; /*2k+1 key entries */
diff --git a/src/H5Distore.c b/src/H5Distore.c
index 0bab89d..09c025c 100644
--- a/src/H5Distore.c
+++ b/src/H5Distore.c
@@ -146,6 +146,7 @@ static haddr_t H5D_istore_get_addr(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *
const hssize_t offset[], H5D_istore_ud1_t *_udata);
static void *H5D_istore_chunk_alloc(size_t size, const H5O_pline_t *pline);
static void *H5D_istore_chunk_xfree(void *chk, const H5O_pline_t *pline);
+static herr_t H5D_istore_page_free (void *page);
/* B-tree iterator callbacks */
static int H5D_istore_iter_allocated(H5F_t *f, hid_t dxpl_id, void *left_key, haddr_t addr,
@@ -278,9 +279,13 @@ H5D_istore_get_page(H5F_t UNUSED *f, const void *_udata)
assert(udata);
assert(udata->mesg);
- assert(udata->mesg->u.chunk.raw_page);
+ assert(udata->mesg->u.chunk.rc_page);
- FUNC_LEAVE_NOAPI(udata->mesg->u.chunk.raw_page);
+ /* Increment reference count on B-tree node */
+ H5RC_INC(udata->mesg->u.chunk.rc_page);
+
+ /* Get the pointer to the ref-count object */
+ FUNC_LEAVE_NOAPI(udata->mesg->u.chunk.rc_page);
} /* end H5D_istore_get_page() */
@@ -898,6 +903,7 @@ H5D_istore_init (H5F_t *f, H5D_t *dset)
size_t sizeof_rkey; /* Single raw key size */
size_t size; /* Raw B-tree node size */
H5D_rdcc_t *rdcc = &(dset->cache.chunk);
+ void *page; /* Buffer for raw B-tree node */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5D_istore_init, FAIL);
@@ -919,9 +925,13 @@ H5D_istore_init (H5F_t *f, H5D_t *dset)
assert(sizeof_rkey);
size = H5B_nodesize(f, H5B_ISTORE, NULL, sizeof_rkey);
assert(size);
- if(NULL==(dset->layout.u.chunk.raw_page=H5FL_BLK_MALLOC(chunk_page,size)))
+ if(NULL==(page=H5FL_BLK_MALLOC(chunk_page,size)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree page")
+ /* Make page buffer reference counted */
+ if(NULL==(dset->layout.u.chunk.rc_page=H5RC_create(page,H5D_istore_page_free)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for page")
+
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5D_istore_init() */
@@ -1217,7 +1227,8 @@ H5D_istore_dest (H5F_t *f, hid_t dxpl_id, H5D_t *dset)
HDmemset (rdcc, 0, sizeof(H5D_rdcc_t));
/* Free the raw B-tree node buffer */
- H5FL_BLK_FREE(chunk_page,dset->layout.u.chunk.raw_page);
+ if(H5RC_DEC(dset->layout.u.chunk.rc_page)<0)
+ HGOTO_ERROR (H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page");
done:
FUNC_LEAVE_NOAPI(ret_value);
@@ -1225,6 +1236,31 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5D_istore_page_free
+ *
+ * Purpose: Free a B-tree node
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, July 8, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_istore_page_free (void *page)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_page_free)
+
+ H5FL_BLK_FREE(chunk_page,page);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5D_istore_page_free() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5D_istore_prune
*
* Purpose: Prune the cache by preempting some things until the cache has
diff --git a/src/H5F.c b/src/H5F.c
index 86f9019..de16b40 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1490,10 +1490,6 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id)
/* Create the file's "open object" information */
if(H5FO_create(f)<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object TBBT")
-
- /* Create information needed for group nodes */
- if(H5G_node_init(f)<0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create group node info")
} /* end else */
f->shared->nrefs++;
@@ -4472,7 +4468,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_raw_page
+ * Function: H5F_rc_page
*
* Purpose: Replaced a macro to retrieve the raw B-tree page value
* now that the generic properties are being used to store
@@ -4491,15 +4487,15 @@ done:
*
*-------------------------------------------------------------------------
*/
-void *H5F_raw_page(const H5F_t *f)
+H5RC_t *H5F_rc_page(const H5F_t *f)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_raw_page)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_rc_page)
assert(f);
assert(f->shared);
- FUNC_LEAVE_NOAPI(f->shared->raw_page)
+ FUNC_LEAVE_NOAPI(f->shared->rc_page)
} /* end H5F_raw_page() */
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 567ea39..318a8f1 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -37,6 +37,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5FOprivate.h" /* File objects */
#include "H5Gprivate.h" /* Groups */
+#include "H5RCprivate.h" /* Reference counted object functions */
/*
* Feature: Define this constant to be non-zero if you want to enable code
@@ -126,7 +127,7 @@ typedef struct H5F_file_t {
struct H5HG_heap_t **cwfs; /* Global heap cache */
H5FO_t *open_objs; /* Open objects in file */
H5F_close_degree_t fc_degree; /* File close behavior degree */
- void *raw_page; /* Pointer to raw B-tree node buffer */
+ H5RC_t *rc_page; /* Pointer to ref-counted raw B-tree node buffer */
} H5F_file_t;
/* A record of the mount table */
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index aace023..452b160 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -211,7 +211,7 @@ typedef struct H5F_t H5F_t;
/* Check for file driver feature enabled */
#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags&(FL))
/* B-tree node raw page */
-#define H5F_RAW_PAGE(F) ((F)->shared->raw_page)
+#define H5F_RC_PAGE(F) ((F)->shared->rc_page)
#else /* H5F_PACKAGE */
#define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F))
#define H5F_SIZEOF_SIZE(F) (H5F_sizeof_size(F))
@@ -221,7 +221,7 @@ typedef struct H5F_t H5F_t;
#define H5F_RDCC_NBYTES(F) (H5F_rdcc_nbytes(F))
#define H5F_RDCC_W0(F) (H5F_rdcc_w0(F))
#define H5F_HAS_FEATURE(F,FL) (H5F_has_feature(F,FL))
-#define H5F_RAW_PAGE(F) (H5F_raw_page(F))
+#define H5F_RC_PAGE(F) (H5F_rc_page(F))
#endif /* H5F_PACKAGE */
@@ -387,6 +387,7 @@ typedef struct H5F_t H5F_t;
/* Forward declarations for prototype arguments */
struct H5B_class_t;
+struct H5RC_t;
/* Private functions, not part of the publicly documented API */
H5_DLL herr_t H5F_init(void);
@@ -417,7 +418,7 @@ H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature);
H5_DLL size_t H5F_rdcc_nbytes(const H5F_t *f);
H5_DLL size_t H5F_rdcc_nelmts(const H5F_t *f);
H5_DLL double H5F_rdcc_w0(const H5F_t *f);
-H5_DLL void *H5F_raw_page(const H5F_t *f);
+H5_DLL struct H5RC_t *H5F_rc_page(const H5F_t *f);
/* Functions that operate on blocks of bytes wrt super block */
H5_DLL herr_t H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr,
diff --git a/src/H5G.c b/src/H5G.c
index ee3d5a4..27f43e8 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -1524,6 +1524,7 @@ done:
/* If we started with a NULL grp_ent and we copied something into it, free the entry information */
if(null_grp && group_copy)
H5G_free_ent_name(grp_ent);
+
FUNC_LEAVE_NOAPI(ret_value);
}
@@ -1661,6 +1662,10 @@ H5G_mkroot (H5F_t *f, hid_t dxpl_id, H5G_entry_t *ent)
if (f->shared->root_grp)
HGOTO_DONE(SUCCEED);
+ /* Create information needed for group nodes */
+ if(H5G_node_init(f)<0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group node info")
+
/*
* If there is no root object then create one. The root group always has
* a hard link count of one since it's pointed to by the boot block.
diff --git a/src/H5Gnode.c b/src/H5Gnode.c
index 1925ee5..1710270 100644
--- a/src/H5Gnode.c
+++ b/src/H5Gnode.c
@@ -64,6 +64,7 @@ typedef struct H5G_node_key_t {
/* PRIVATE PROTOTYPES */
static herr_t H5G_node_serialize(H5F_t *f, H5G_node_t *sym, size_t size, uint8_t *buf);
static size_t H5G_node_size(H5F_t *f);
+static herr_t H5G_node_page_free (void *page);
/* Metadata cache callbacks */
static H5G_node_t *H5G_node_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1,
@@ -196,7 +197,11 @@ H5G_node_get_page(H5F_t *f, const void UNUSED *_udata)
assert(f);
- FUNC_LEAVE_NOAPI(H5F_RAW_PAGE(f));
+ /* Increment reference count on B-tree node */
+ H5RC_INC(H5F_RC_PAGE(f));
+
+ /* Get the pointer to the ref-count object */
+ FUNC_LEAVE_NOAPI(H5F_RC_PAGE(f));
} /* end H5G_node_get_page() */
@@ -1722,8 +1727,9 @@ done:
herr_t
H5G_node_init(H5F_t *f)
{
- size_t sizeof_rkey; /* Single raw key size */
- size_t size; /* Raw B-tree node size */
+ size_t sizeof_rkey; /* Single raw key size */
+ size_t size; /* Raw B-tree node size */
+ void *page; /* Buffer for raw B-tree node */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5G_node_init, FAIL);
@@ -1736,9 +1742,13 @@ H5G_node_init(H5F_t *f)
assert(sizeof_rkey);
size = H5B_nodesize(f, H5B_SNODE, NULL, sizeof_rkey);
assert(size);
- if(NULL==(f->shared->raw_page=H5FL_BLK_MALLOC(grp_page,size)))
+ if(NULL==(page=H5FL_BLK_MALLOC(grp_page,size)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree page")
+ /* Make page buffer reference counted */
+ if(NULL==(f->shared->rc_page=H5RC_create(page,H5G_node_page_free)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for page")
+
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5G_node_init() */
@@ -1768,13 +1778,39 @@ H5G_node_close(const H5F_t *f)
assert(f);
/* Free the raw B-tree node buffer */
- H5FL_BLK_FREE(grp_page,f->shared->raw_page);
+ H5RC_DEC(f->shared->rc_page);
FUNC_LEAVE_NOAPI(SUCCEED);
} /* end H5G_node_close */
/*-------------------------------------------------------------------------
+ * Function: H5G_node_page_free
+ *
+ * Purpose: Free a B-tree node
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, July 8, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_node_page_free (void *page)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_page_free)
+
+ /* Free the raw B-tree node buffer */
+ H5FL_BLK_FREE(grp_page,page);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5G_node_page_free() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_node_debug
*
* Purpose: Prints debugging information about a symbol table node
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index b7d9b46..26bf5d8 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -37,6 +37,7 @@
/* Private headers needed by this file */
#include "H5private.h" /* Generic functions */
#include "H5HGprivate.h" /* Global heap functions */
+#include "H5RCprivate.h" /* Reference counted object functions */
#include "H5Tprivate.h" /* Datatype functions */
#include "H5Zprivate.h" /* I/O pipeline filters */
@@ -133,7 +134,7 @@ typedef struct H5O_layout_chunk_t {
unsigned ndims; /* Num dimensions in chunk */
size_t dim[H5O_LAYOUT_NDIMS]; /* Size of chunk in elements */
size_t size; /* Size of chunk in bytes */
- void *raw_page; /* Buffer for raw B-tree page */
+ H5RC_t *rc_page; /* Ref-counted buffer for raw B-tree page */
} H5O_layout_chunk_t;
typedef struct H5O_layout_compact_t {
diff --git a/src/H5RC.c b/src/H5RC.c
new file mode 100644
index 0000000..8ab1818
--- /dev/null
+++ b/src/H5RC.c
@@ -0,0 +1,129 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Reference counting buffer algorithms.
+ *
+ * These are used for various internal buffers which are shared.
+ *
+ */
+
+/* Pablo information */
+/* (Put before include files to avoid problems with inline functions) */
+#define PABLO_MASK H5RC_mask
+
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free lists */
+#include "H5RCprivate.h" /* Reference-counted buffers */
+
+/* Private typedefs & structs */
+
+/* Declare a free list to manage the H5RC_t struct */
+H5FL_DEFINE_STATIC(H5RC_t);
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5RC_create
+ PURPOSE
+ Create a reference counted object
+ USAGE
+ H5RC_t *H5RC_create(o,free)
+ const void *o; IN: Object to initialize ref-counted object with
+ H5RC_free_func_t free; IN: Function to call when ref-count drop to zero
+
+ RETURNS
+ Returns a pointer to a new ref-counted object on success, NULL on failure.
+ DESCRIPTION
+ Create a reference counted object. The object is not duplicated, it is
+ assumed to be owned by the reference counted object now and will be freed
+ with the 'free' function when the reference count drops to zero.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+H5RC_t *
+H5RC_create(void *o, H5RC_free_func_t free_func)
+{
+ H5RC_t *ret_value=NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5RC_create,NULL);
+
+ /* Sanity check */
+ HDassert(o);
+ HDassert(free_func);
+
+ /* Allocate ref-counted string structure */
+ if((ret_value=H5FL_MALLOC(H5RC_t))==NULL)
+ HGOTO_ERROR(H5E_RS,H5E_NOSPACE,NULL,"memory allocation failed");
+
+ /* Set the internal fields */
+ ret_value->o=o;
+ ret_value->n=1;
+ ret_value->free_func=free_func;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5RC_create() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5RC_decr
+ PURPOSE
+ Decrement the reference count for a ref-counted object
+ USAGE
+ herr_t H5RC_decr(rc)
+ H5RC_t *rc; IN: Ref-counted object to decrement count for
+
+ RETURNS
+ SUCCEED/FAIL
+ DESCRIPTION
+ Decrements the reference count for a ref-counted object, calling the
+ object's free function if ref-count drops to zero.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5RC_decr(H5RC_t *rc)
+{
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5RC_decr,FAIL);
+
+ /* Sanity check */
+ HDassert(rc);
+ HDassert(rc->o);
+ HDassert(rc->n>0);
+ HDassert(rc->free_func);
+
+ /* Decrement reference count */
+ rc->n--;
+
+ /* Check if we should delete this object now */
+ if(rc->n==0) {
+ if((rc->free_func)(rc->o)<0) {
+ H5FL_FREE(H5RC_t,rc);
+ HGOTO_ERROR(H5E_RS,H5E_CANTFREE,FAIL,"memory release failed");
+ } /* end if */
+ H5FL_FREE(H5RC_t,rc);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5RC_decr() */
+
diff --git a/src/H5RCprivate.h b/src/H5RCprivate.h
new file mode 100644
index 0000000..7f1dc3a
--- /dev/null
+++ b/src/H5RCprivate.h
@@ -0,0 +1,62 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * This file contains private information about the H5RC module
+ */
+#ifndef _H5RCprivate_H
+#define _H5RCprivate_H
+
+/**************************************/
+/* Public headers needed by this file */
+/**************************************/
+#ifdef LATER
+#include "H5RCpublic.h"
+#endif /* LATER */
+
+/***************************************/
+/* Private headers needed by this file */
+/***************************************/
+#include "H5private.h"
+
+/************/
+/* Typedefs */
+/************/
+
+/* Typedef for function to release object when reference count drops to zero */
+typedef herr_t (*H5RC_free_func_t)(void *o);
+
+/* Typedef for reference counted objects */
+typedef struct H5RC_t {
+ void *o; /* Object to be reference counted */
+ size_t n; /* Reference count of number of pointers sharing object */
+ H5RC_free_func_t free_func; /* Function to free object */
+} H5RC_t;
+
+/**********/
+/* Macros */
+/**********/
+#define H5RC_INC(rc) ((rc)->n++)
+#define H5RC_DEC(rc) (H5RC_decr(rc))
+#define H5RC_GET_OBJ(rc) ((rc)->o)
+
+/********************/
+/* Private routines */
+/********************/
+H5_DLL H5RC_t *H5RC_create(void *s, H5RC_free_func_t free_func);
+H5_DLL herr_t H5RC_decr(H5RC_t *rc);
+
+#endif /* _H5RSprivate_H */
+
+
diff --git a/src/Makefile.in b/src/Makefile.in
index dc59c33..4c05597 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -40,7 +40,7 @@ LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dcontig.c H5Dcompact.c H5Dio.c \
H5Obogus.c H5Ocont.c H5Odtype.c H5Oefl.c H5Ofill.c H5Olayout.c \
H5Omtime.c H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c \
H5Ostab.c H5P.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Ptest.c \
- H5R.c H5RS.c H5S.c H5Sall.c H5Shyper.c H5Smpio.c H5Snone.c \
+ H5R.c H5RC.c H5RS.c H5S.c H5Sall.c H5Shyper.c H5Smpio.c H5Snone.c \
H5Spoint.c H5Sselect.c H5Stest.c H5ST.c H5T.c H5Tarray.c H5Tbit.c \
H5Tcommit.c H5Tcompound.c H5Tconv.c H5Tcset.c H5Tenum.c H5Tfields.c \
H5Tfixed.c H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Topaque.c \
@@ -70,9 +70,9 @@ PRIVATE_HDR=H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \
H5FSprivate.h H5Gprivate.h H5Gpkg.h H5HGprivate.h H5HGpkg.h \
H5HLprivate.h H5HLpkg.h H5HPprivate.h H5Iprivate.h H5MFprivate.h \
H5MMprivate.h H5Oprivate.h H5Opkg.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 \
- H5Zpkg.h H5config.h
+ H5Rprivate.h H5RCprivate.h H5RSprivate.h H5Sprivate.h H5STprivate.h \
+ H5Tprivate.h H5TBprivate.h H5Tpkg.h H5TSprivate.h H5Vprivate.h \
+ H5Zprivate.h H5Zpkg.h H5config.h
## Error header generation
##