diff options
author | John Mainzer <mainzer@hdfgroup.org> | 2006-05-24 07:36:28 (GMT) |
---|---|---|
committer | John Mainzer <mainzer@hdfgroup.org> | 2006-05-24 07:36:28 (GMT) |
commit | a415cc6b17269c893704b3410a764b1c5d3d812e (patch) | |
tree | 36c29aba9c7b776bec0a65999d796d389bec9090 /src | |
parent | 5f4234fabfe2ee0c07d74776d36352a8daf49e31 (diff) | |
download | hdf5-a415cc6b17269c893704b3410a764b1c5d3d812e.zip hdf5-a415cc6b17269c893704b3410a764b1c5d3d812e.tar.gz hdf5-a415cc6b17269c893704b3410a764b1c5d3d812e.tar.bz2 |
[svn-r12374] Purpose:
1) Check in potential fix to unreproduceable bug in t_cache observed on
Cobalt
2) Check in code supporting added pinned entry features in the metadata
cache.
Description:
1) Elena encountered a bug in t_cache when running on Cobalt. On
investigation I found a potential race condition in t_cache that
could explain her observation.
2) Quincey requested additions to the metadata cache allowing renaming
of pinned entryies, and marking of pinned or protected entries as
dirty.
Solution:
1) Modified t_cache.c to prevent the potential race condition. Elena
was unable to reproduce the bug on Cobalt, so we don't know if my
fix actually addressed the problem.
2) Added code supporting the requested functions. The changes were
relatively trivial, but required substantial new test code.
Platforms tested:
h5committest, serial test on heping, parallel test on phoenix.
Misc. update:
Diffstat (limited to 'src')
-rw-r--r-- | src/H5AC.c | 160 | ||||
-rw-r--r-- | src/H5ACpkg.h | 14 | ||||
-rw-r--r-- | src/H5ACprivate.h | 4 | ||||
-rw-r--r-- | src/H5C.c | 97 | ||||
-rw-r--r-- | src/H5Cprivate.h | 19 |
5 files changed, 289 insertions, 5 deletions
@@ -465,6 +465,10 @@ H5AC_term_interface(void) * Added code to set the prefix if required. * * JRM - 1/20/06 + * + * Added code to initialize the new write_done field. + * + * JRM - 5/11/06 * *------------------------------------------------------------------------- */ @@ -568,6 +572,7 @@ H5AC_create(const H5F_t *f, aux_ptr->d_slist_len = 0; aux_ptr->c_slist_ptr = NULL; aux_ptr->c_slist_len = 0; + aux_ptr->write_done = NULL; sprintf(prefix, "%d:", mpi_rank); } @@ -863,6 +868,9 @@ done: * bug in PHDF5. See the header comments on the H5AC_aux_t * structure for details. * + * JRM -- 5/11/06 + * Added call to the write_done callback. + * *------------------------------------------------------------------------- */ herr_t @@ -936,6 +944,12 @@ H5AC_flush(H5F_t *f, hid_t dxpl_id, unsigned flags) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush.") } + + if ( aux_ptr->write_done != NULL ) { + + (aux_ptr->write_done)(); + } + } /* end if ( aux_ptr->mpi_rank == 0 ) */ status = H5AC_propagate_flushed_and_still_clean_entries_list(f, @@ -1199,9 +1213,6 @@ done: * If the entry has changed size, the function updates * data structures for the size change. * - * If the entry is not already dirty, the function places - * the entry on the skip list. - * * Return: Non-negative on success/Negative on failure * * Programmer: John Mainzer @@ -1260,7 +1271,7 @@ H5AC_mark_pinned_entry_dirty(H5F_t * f, if ( result < 0 ) { - HGOTO_ERROR(H5E_CACHE, H5E_CANTUNPROTECT, FAIL, \ + HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \ "H5AC_log_dirtied_entry() failed.") } } @@ -1285,6 +1296,82 @@ done: /*------------------------------------------------------------------------- + * Function: H5AC_mark_pinned_or_protected_entry_dirty + * + * Purpose: Mark a pinned or protected entry as dirty. The target + * entry MUST be either pinned, protected, or both. + * + * Unlike H5AC_mark_pinned_entry_dirty(), this function does + * not support size changes. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/16/06 + * + * Modifications: + * + * None + * + *------------------------------------------------------------------------- + */ +herr_t +H5AC_mark_pinned_or_protected_entry_dirty(H5F_t * f, + void * thing) +{ + H5C_t * cache_ptr = f->shared->cache; +#ifdef H5_HAVE_PARALLEL + H5AC_info_t * info_ptr; +#endif /* H5_HAVE_PARALLEL */ + herr_t result; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5AC_mark_pinned_or_protected_entry_dirty, FAIL) + +#ifdef H5_HAVE_PARALLEL + + HDassert( cache_ptr ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + HDassert( thing ); + + info_ptr = (H5AC_info_t *)thing; + + if ( ( info_ptr->is_dirty == FALSE ) && + ( ! ( info_ptr->is_protected ) ) && + ( info_ptr->is_pinned ) && + ( NULL != cache_ptr->aux_ptr) ) { + + result = H5AC_log_dirtied_entry(cache_ptr, + info_ptr, + info_ptr->addr, + FALSE, + 0); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \ + "H5AC_log_dirtied_entry() failed.") + } + } +#endif /* H5_HAVE_PARALLEL */ + + result = H5C_mark_pinned_or_protected_entry_dirty(cache_ptr, thing); + + if ( result < 0 ) { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \ + "H5C_mark_pinned_entry_dirty() failed.") + + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5AC_mark_pinned_entry_dirty() */ + + +/*------------------------------------------------------------------------- * Function: H5AC_rename * * Purpose: Use this function to notify the cache that an object's @@ -1664,6 +1751,11 @@ done: * as it can effect dirty byte creation counts, thereby * throwing the caches out of sync in the PHDF5 case. * + * JRM - 5/16/06 + * Added code to use the new dirtied field in + * H5C_cache_entry_t in the test to see if the entry has + * been dirtied. + * *------------------------------------------------------------------------- */ herr_t @@ -1691,7 +1783,8 @@ H5AC_unprotect(H5F_t *f, hid_t dxpl_id, const H5AC_class_t *type, haddr_t addr, HDassert( ((H5AC_info_t *)thing)->addr == addr ); HDassert( ((H5AC_info_t *)thing)->type == type ); - dirtied = ((flags & H5AC__DIRTIED_FLAG) == H5AC__DIRTIED_FLAG ); + dirtied = ( ( (flags & H5AC__DIRTIED_FLAG) == H5AC__DIRTIED_FLAG ) || + ( ((H5AC_info_t *)thing)->dirtied ) ); if ( dirtied ) { @@ -1783,6 +1876,55 @@ done: /*------------------------------------------------------------------------- + * Function: HA5C_set_write_done_callback + * + * Purpose: Set the value of the write_done callback. This callback + * is used to improve performance of the parallel test bed + * for the cache. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/11/06 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +#ifdef H5_HAVE_PARALLEL +herr_t +H5AC_set_write_done_callback(H5C_t * cache_ptr, + void (* write_done)(void)) +{ + herr_t ret_value = SUCCEED; /* Return value */ + H5AC_aux_t * aux_ptr = NULL; + + FUNC_ENTER_NOAPI(H5AC_set_write_done_callback, FAIL) + + /* This would normally be an assert, but we need to use an HGOTO_ERROR + * call to shut up the compiler. + */ + if ( ( ! cache_ptr ) || ( cache_ptr->magic != H5C__H5C_T_MAGIC ) ) { + + HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "Bad cache_ptr") + } + + aux_ptr = cache_ptr->aux_ptr; + + HDassert( aux_ptr != NULL ); + HDassert( aux_ptr->magic == H5AC__H5AC_AUX_T_MAGIC ); + + aux_ptr->write_done = write_done; + +done: + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5AC_set_write_done_callback() */ +#endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- * Function: H5AC_stats * * Purpose: Prints statistics about the cache. @@ -3410,6 +3552,9 @@ done: * * Modifications: * + * JRM -- 5/11/06 + * Added code to call the write_done callback. + * *------------------------------------------------------------------------- */ @@ -3476,6 +3621,11 @@ H5AC_propagate_flushed_and_still_clean_entries_list(H5F_t * f, "H5C_flush_to_min_clean() failed.") } + if ( aux_ptr->write_done != NULL ) { + + (aux_ptr->write_done)(); + } + if ( H5AC_broadcast_clean_list(cache_ptr) < 0 ) { HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, \ diff --git a/src/H5ACpkg.h b/src/H5ACpkg.h index 903eca3..e31f245 100644 --- a/src/H5ACpkg.h +++ b/src/H5ACpkg.h @@ -263,6 +263,18 @@ * contain the value 0 on all processes other than process 0. * It exists primarily for sanity checking. * + * write_done: In the parallel test bed, it is necessary to ensure that + * all writes to the server process from cache 0 complete + * before it enters the barrier call with the other caches. + * + * The write_done callback allows t_cache to do this without + * requiring an ACK on each write. Since these ACKs greatly + * increase the run time on some platforms, this is a + * significant optimization. + * + * This field must be set to NULL when the callback is not + * needed. + * ****************************************************************************/ #ifdef H5_HAVE_PARALLEL @@ -308,6 +320,8 @@ typedef struct H5AC_aux_t int32_t c_slist_len; + void (* write_done)(void); + } H5AC_aux_t; /* struct H5AC_aux_t */ #endif /* H5_HAVE_PARALLEL */ diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 6638be4..6dcd88c 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -261,10 +261,14 @@ H5_DLL herr_t H5AC_mark_pinned_entry_dirty(H5F_t * f, void * thing, hbool_t size_changed, size_t new_size); +H5_DLL herr_t H5AC_mark_pinned_or_protected_entry_dirty(H5F_t * f, + void * thing); H5_DLL herr_t H5AC_rename(H5F_t *f, const H5AC_class_t *type, haddr_t old_addr, haddr_t new_addr); H5_DLL herr_t H5AC_dest(H5F_t *f, hid_t dxpl_id); +H5_DLL herr_t H5AC_set_write_done_callback(H5C_t * cache_ptr, + void (* write_done)(void)); H5_DLL herr_t H5AC_stats(const H5F_t *f); H5_DLL herr_t H5AC_get_cache_auto_resize_config(H5AC_t * cache_ptr, @@ -2607,6 +2607,7 @@ H5C_create(size_t max_cache_size, ((cache_ptr->epoch_markers)[i]).size = (size_t)0; ((cache_ptr->epoch_markers)[i]).type = &epoch_marker_class; ((cache_ptr->epoch_markers)[i]).is_dirty = FALSE; + ((cache_ptr->epoch_markers)[i]).dirtied = FALSE; ((cache_ptr->epoch_markers)[i]).is_protected = FALSE; ((cache_ptr->epoch_markers)[i]).is_pinned = FALSE; ((cache_ptr->epoch_markers)[i]).in_slist = FALSE; @@ -3732,6 +3733,10 @@ done: * Added initialization for the new is_pinned field of the * H5C_cache_entry_t structure. * + * JRM -- 5/3/06 + * Added initialization for the new dirtied field of the + * H5C_cache_entry_t structure. + * *------------------------------------------------------------------------- */ @@ -3789,6 +3794,9 @@ H5C_insert_entry(H5F_t * f, /* newly inserted entries are assumed to be dirty */ entry_ptr->is_dirty = TRUE; + /* not protected, so can't be dirtied */ + entry_ptr->dirtied = FALSE; + if ( (type->size)(f, thing, &(entry_ptr->size)) < 0 ) { HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, \ @@ -4364,6 +4372,79 @@ done: /*------------------------------------------------------------------------- + * Function: H5C_mark_pinned_or_protected_entry_dirty + * + * Purpose: Mark a pinned or protected entry as dirty. The target entry + * MUST be either pinned or protected, and MAY be both. + * + * At present, this funtion does not support size change. + * + * In the protected case, this call is the functional + * equivalent of setting the H5C__DIRTIED_FLAG on an unprotect + * call. + * + * In the pinned but not protected case, if the entry is not + * already dirty, the function places function marks the entry + * dirty and places it on the skip list. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/15/06 + * + * Modifications: + * + * None + * + *------------------------------------------------------------------------- + */ +herr_t +H5C_mark_pinned_or_protected_entry_dirty(H5C_t * cache_ptr, + void * thing) +{ + herr_t ret_value = SUCCEED; /* Return value */ + H5C_cache_entry_t * entry_ptr; + + FUNC_ENTER_NOAPI(H5C_mark_pinned_or_protected_entry_dirty, FAIL) + + HDassert( cache_ptr ); + HDassert( cache_ptr->magic == H5C__H5C_T_MAGIC ); + HDassert( thing ); + + entry_ptr = (H5C_cache_entry_t *)thing; + + if ( entry_ptr->is_protected ) { + + /* set the dirtied flag */ + entry_ptr->dirtied = TRUE; + + } else if ( entry_ptr->is_pinned ) { + + /* mark the entry as dirty if it isn't already */ + entry_ptr->is_dirty = TRUE; + + + if ( ! (entry_ptr->in_slist) ) { + + H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr) + } + + H5C__UPDATE_STATS_FOR_DIRTY_PIN(cache_ptr, entry_ptr) + + } else { + + HGOTO_ERROR(H5E_CACHE, H5E_CANTMARKDIRTY, FAIL, \ + "Entry is neither pinned nor protected??") + } + +done: + + FUNC_LEAVE_NOAPI(ret_value) + +} /* H5C_mark_pinned_or_protected_entry_dirty() */ + + +/*------------------------------------------------------------------------- * * Function: H5C_rename_entry * @@ -4621,6 +4702,10 @@ done: * JRM -- 10/22/05 * Hand optimizations. * + * JRM -- 5/3/06 + * Added code to set the new dirtied field in + * H5C_cache_entry_t to FALSE prior to return. + * *------------------------------------------------------------------------- */ @@ -4791,6 +4876,8 @@ H5C_protect(H5F_t * f, entry_ptr->is_protected = TRUE; + entry_ptr->dirtied = FALSE; + ret_value = thing; H5C__UPDATE_CACHE_HIT_RATE_STATS(cache_ptr, hit) @@ -5857,6 +5944,11 @@ done: * Unpdated function to pin and unpin entries as directed via * the new H5C__PIN_ENTRY_FLAG and H5C__UNPIN_ENTRY_FLAG flags. * + * JRM -- 5/3/06 + * Added code to make use of the new dirtied field in + * H5C_cache_entry_t. If this field is TRUE, it is the + * equivalent of setting the H5C__DIRTIED_FLAG. + * *------------------------------------------------------------------------- */ herr_t @@ -5910,6 +6002,11 @@ H5C_unprotect(H5F_t * f, HDassert( entry_ptr->addr == addr ); HDassert( entry_ptr->type == type ); + /* also set the dirtied variable if the dirtied field is set in + * the entry. + */ + dirtied |= entry_ptr->dirtied; + #if H5C_DO_EXTREME_SANITY_CHECKS if ( H5C_validate_lru_list(cache_ptr) < 0 ) { diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 43a93b3..bdcf501 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -234,6 +234,21 @@ typedef herr_t (*H5C_log_flush_func_t)(H5C_t * cache_ptr, * modules using the cache. These still clear the * is_dirty field as before. -- JRM 7/5/05 * + * dirtied: Boolean flag used to indicate that the entry has been + * dirtied while protected. + * + * This field is set to FALSE in the protect call, and may + * be set to TRUE by the + * H5C_mark_pinned_or_protected_entry_dirty() + * call at an time prior to the unprotect call. + * + * The H5C_mark_pinned_or_protected_entry_dirty() call exists + * as a convenience function for the fractal heap code which + * may not know if an entry is protected or pinned, but knows + * that is either protected or pinned. The dirtied field was + * added as in the parallel case, it is necessary to know + * whether a protected entry was dirty prior to the protect call. + * * is_protected: Boolean flag indicating whether this entry is protected * (or locked, to use more conventional terms). When it is * protected, the entry cannot be flushed or accessed until @@ -401,6 +416,7 @@ typedef struct H5C_cache_entry_t size_t size; const H5C_class_t * type; hbool_t is_dirty; + hbool_t dirtied; hbool_t is_protected; hbool_t is_pinned; hbool_t in_slist; @@ -835,6 +851,9 @@ H5_DLL herr_t H5C_mark_pinned_entry_dirty(H5C_t * cache_ptr, hbool_t size_changed, size_t new_size); +H5_DLL herr_t H5C_mark_pinned_or_protected_entry_dirty(H5C_t * cache_ptr, + void * thing); + H5_DLL herr_t H5C_rename_entry(H5C_t * cache_ptr, const H5C_class_t * type, haddr_t old_addr, |