diff options
author | John Mainzer <mainzer@hdfgroup.org> | 2005-06-24 06:30:29 (GMT) |
---|---|---|
committer | John Mainzer <mainzer@hdfgroup.org> | 2005-06-24 06:30:29 (GMT) |
commit | 7f8e3460261851cdad1e344d8929d2817e3149ad (patch) | |
tree | 760d0e8dd581c4d4245a7e8acf51254f0c29d1ad /src/H5C.c | |
parent | 2ab6b12b552e9260e2e76640a788b5a3744c6a9f (diff) | |
download | hdf5-7f8e3460261851cdad1e344d8929d2817e3149ad.zip hdf5-7f8e3460261851cdad1e344d8929d2817e3149ad.tar.gz hdf5-7f8e3460261851cdad1e344d8929d2817e3149ad.tar.bz2 |
[svn-r10978] Purpose:
Interim checkin of code changes moving management of the is_dirty flag
into the cache code.
Description:
Prior to this checkin, management of the is_dirty flag was handled
above the level of the metadata cache. This can no longer be allowed,
as it introduces a race condition in the proposed fix for a cache
coherency bug in PHDF5.
Solution:
Move management fo the is_dirty flag to the cache code proper.
Entries are now marked as dirty via a flag on the unprotect call.
Platforms tested:
h5committested
Misc. update:
Diffstat (limited to 'src/H5C.c')
-rw-r--r-- | src/H5C.c | 315 |
1 files changed, 233 insertions, 82 deletions
@@ -1437,88 +1437,107 @@ if ( ( (cache_ptr) == NULL ) || \ * dirty LRU lists, and the other not. Yet another attempt * at optimization. * + * JRM - 6/23/05 + * Added the was_dirty parameter. It is possible that + * the entry was clean when it was renamed -- if so it + * it is in the clean LRU regardless of the current + * value of the is_dirty field. + * + * At present, all renamed entries are forced to be + * dirty. This macro is a bit more general that that, + * to allow it to function correctly should that policy + * be relaxed in the future. + * *------------------------------------------------------------------------- */ #if H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS -#define H5C__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list, and re-insert it at the head. */ \ - \ - H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* move the entry to the head of either the clean or dirty LRU list \ - * as appropriate. \ - */ \ - \ - if ( (entry_ptr)->is_dirty ) { \ - \ - H5C__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - \ - H5C__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ - (cache_ptr)->dLRU_tail_ptr, \ - (cache_ptr)->dLRU_list_len, \ - (cache_ptr)->dLRU_list_size, (fail_val)) \ - \ - } else { \ - \ - H5C__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - \ - H5C__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ - (cache_ptr)->cLRU_tail_ptr, \ - (cache_ptr)->cLRU_list_len, \ - (cache_ptr)->cLRU_list_size, (fail_val)) \ - } \ - \ - /* End modified LRU specific code. */ \ - \ +#define H5C__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list, and re-insert it at the head. */ \ + \ + H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* remove the entry from either the clean or dirty LUR list as \ + * indicated by the was_dirty parameter \ + */ \ + if ( was_dirty ) { \ + \ + H5C__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + \ + } else { \ + \ + H5C__AUX_DLL_REMOVE((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ + /* insert the entry at the head of either the clean or dirty LRU list \ + * as appropriate. \ + */ \ + \ + if ( (entry_ptr)->is_dirty ) { \ + \ + H5C__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->dLRU_head_ptr, \ + (cache_ptr)->dLRU_tail_ptr, \ + (cache_ptr)->dLRU_list_len, \ + (cache_ptr)->dLRU_list_size, (fail_val)) \ + \ + } else { \ + \ + H5C__AUX_DLL_PREPEND((entry_ptr), (cache_ptr)->cLRU_head_ptr, \ + (cache_ptr)->cLRU_tail_ptr, \ + (cache_ptr)->cLRU_list_len, \ + (cache_ptr)->cLRU_list_size, (fail_val)) \ + } \ + \ + /* End modified LRU specific code. */ \ + \ } /* H5C__UPDATE_RP_FOR_RENAME */ #else /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ -#define H5C__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, fail_val) \ -{ \ - HDassert( (cache_ptr) ); \ - HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ - HDassert( (entry_ptr) ); \ - HDassert( !((entry_ptr)->is_protected) ); \ - HDassert( (entry_ptr)->size > 0 ); \ - \ - /* modified LRU specific code */ \ - \ - /* remove the entry from the LRU list, and re-insert it at the head. */ \ - \ - H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ - (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ - (cache_ptr)->LRU_list_size, (fail_val)) \ - \ - /* End modified LRU specific code. */ \ - \ +#define H5C__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, fail_val) \ +{ \ + HDassert( (cache_ptr) ); \ + HDassert( (cache_ptr)->magic == H5C__H5C_T_MAGIC ); \ + HDassert( (entry_ptr) ); \ + HDassert( !((entry_ptr)->is_protected) ); \ + HDassert( (entry_ptr)->size > 0 ); \ + \ + /* modified LRU specific code */ \ + \ + /* remove the entry from the LRU list, and re-insert it at the head. */ \ + \ + H5C__DLL_REMOVE((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + H5C__DLL_PREPEND((entry_ptr), (cache_ptr)->LRU_head_ptr, \ + (cache_ptr)->LRU_tail_ptr, (cache_ptr)->LRU_list_len, \ + (cache_ptr)->LRU_list_size, (fail_val)) \ + \ + /* End modified LRU specific code. */ \ + \ } /* H5C__UPDATE_RP_FOR_RENAME */ #endif /* H5C_MAINTAIN_CLEAN_AND_DIRTY_LRU_LISTS */ @@ -2821,6 +2840,11 @@ done: * H5C__SET_FLUSH_MARKER_FLAG. Note that this flag is * ignored unless the new entry is dirty. * + * JRM -- 6/6/05 + * Added code to force all inserted entries to be dirty. + * This is part of a set of changes moving management of the + * is_dirty field of H5C_cache_entry_t into the H5C code. + * *------------------------------------------------------------------------- */ @@ -2860,6 +2884,9 @@ H5C_insert_entry(H5F_t * f, entry_ptr->addr = addr; entry_ptr->type = type; + /* newly inserted entries are assumed to be dirty */ + entry_ptr->is_dirty = TRUE; + if ( (type->size)(f, thing, &(entry_ptr->size)) < 0 ) { HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, \ @@ -2979,6 +3006,10 @@ H5C_insert_entry(H5F_t * f, H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL) + /* New entries are presumed to be dirty, so this if statement is + * unnecessary. Rework it once the rest of the code changes are + * in and tested. -- JRM + */ if ( entry_ptr->is_dirty ) { entry_ptr->flush_marker = set_flush_marker; @@ -3017,6 +3048,12 @@ done: * JRM -- 7/21/04 * Updated function for the addition of the hash table. * + * JRM -- 6/6/05 + * Updated function to force all renamed entries to be + * dirty. This is part of a series of code modifications + * moving management of the is_dirty field of + * H5C_cache_entry_t into the H5C code. + * *------------------------------------------------------------------------- */ @@ -3027,6 +3064,7 @@ H5C_rename_entry(H5C_t * cache_ptr, haddr_t new_addr) { herr_t ret_value = SUCCEED; /* Return value */ + hbool_t was_dirty; H5C_cache_entry_t * entry_ptr = NULL; H5C_cache_entry_t * test_entry_ptr = NULL; @@ -3063,12 +3101,13 @@ H5C_rename_entry(H5C_t * cache_ptr, HGOTO_ERROR(H5E_CACHE, H5E_CANTRENAME, FAIL, \ "New address already in use?.") + } } /* If we get this far, we have work to do. Remove *entry_ptr from * the hash table (and skip list if necessary), change its address to the - * new address, and then re-insert. + * new address, mark it as dirty (if it isn't already) and then re-insert. * * Update the replacement policy for a hit to avoid an eviction before * the renamed entry is touched. Update stats for a rename. @@ -3076,6 +3115,7 @@ H5C_rename_entry(H5C_t * cache_ptr, * Note that we do not check the size of the cache, or evict anything. * Since this is a simple re-name, cache size should be unaffected. */ + H5C__DELETE_FROM_INDEX(cache_ptr, entry_ptr) if ( entry_ptr->in_slist ) { @@ -3086,15 +3126,21 @@ H5C_rename_entry(H5C_t * cache_ptr, } entry_ptr->addr = new_addr; + was_dirty = entry_ptr->is_dirty; + entry_ptr->is_dirty = TRUE; H5C__INSERT_IN_INDEX(cache_ptr, entry_ptr, FAIL) + /* remove this if statement once this set of mods + * is up and running. -- JRM + */ + if ( entry_ptr->is_dirty ) { H5C__INSERT_ENTRY_IN_SLIST(cache_ptr, entry_ptr) } - H5C__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, FAIL) + H5C__UPDATE_RP_FOR_RENAME(cache_ptr, entry_ptr, was_dirty, FAIL) H5C__UPDATE_STATS_FOR_RENAME(cache_ptr, entry_ptr) @@ -3162,14 +3208,14 @@ done: */ void * -H5C_protect(H5F_t * f, - hid_t primary_dxpl_id, - hid_t secondary_dxpl_id, - H5C_t * cache_ptr, +H5C_protect(H5F_t * f, + hid_t primary_dxpl_id, + hid_t secondary_dxpl_id, + H5C_t * cache_ptr, const H5C_class_t * type, - haddr_t addr, - const void * udata1, - void * udata2) + haddr_t addr, + const void * udata1, + void * udata2) { hbool_t hit = FALSE; hbool_t first_flush = TRUE; @@ -4124,6 +4170,12 @@ H5C_stats__reset(H5C_t * cache_ptr) * once the flush_marker field of an entry is set, the * only way it can be reset is by being flushed. * + * JRM -- 6/3/05 + * Added the dirtied parameter and supporting code. This + * is part of an effort to move management of the is_dirty + * field into the cache code. This has become necessary + * to repair a cache coherency bug in PHDF5. + * *------------------------------------------------------------------------- */ herr_t @@ -4134,6 +4186,7 @@ H5C_unprotect(H5F_t * f, const H5C_class_t * type, haddr_t addr, void * thing, + hbool_t dirtied, unsigned int flags) { hbool_t deleted; @@ -4167,6 +4220,9 @@ H5C_unprotect(H5F_t * f, "Entry already unprotected??") } + /* mark the entry as dirty if appropriate */ + entry_ptr->is_dirty = ( (entry_ptr->is_dirty) || dirtied ); + H5C__UPDATE_RP_FOR_UNPROTECT(cache_ptr, entry_ptr, FAIL) entry_ptr->is_protected = FALSE; @@ -5761,6 +5817,101 @@ H5C_flush_single_entry(H5F_t * f, */ if ( destroy ) { /* AKA eviction */ +#if 0 /* JRM */ + /* This test code may come in handy -- lets keep it for a while */ + { + if ( entry_ptr->is_dirty ) + { + if ( cache_ptr->dLRU_head_ptr == NULL ) + HDfprintf(stdout,"cache_ptr->dLRU_head_ptr == NULL.\n"); + + if ( cache_ptr->dLRU_tail_ptr == NULL ) + HDfprintf(stdout,"cache_ptr->dLRU_tail_ptr == NULL.\n"); + + if ( cache_ptr->dLRU_list_len <= 0 ) + HDfprintf(stdout,"cache_ptr->dLRU_list_len <= 0.\n"); + + if ( cache_ptr->dLRU_list_size <= 0 ) + HDfprintf(stdout,"cache_ptr->dLRU_list_size <= 0.\n"); + + if ( cache_ptr->dLRU_list_size < entry_ptr->size ) + HDfprintf(stdout, + "cache_ptr->dLRU_list_size < entry_ptr->size.\n"); + + if ( ( (cache_ptr->dLRU_list_size) == entry_ptr->size ) && + ( ! ( (cache_ptr->dLRU_list_len) == 1 ) ) ) + HDfprintf(stdout, + "dLRU_list_size == size && dLRU_list_len != 1\n"); + + if ( ( entry_ptr->aux_prev == NULL ) && + ( cache_ptr->dLRU_head_ptr != entry_ptr ) ) + HDfprintf(stdout, "entry_ptr->aux_prev == NULL && dLRU_head_ptr != entry_ptr\n"); + + if ( ( entry_ptr->aux_next == NULL ) && + ( cache_ptr->dLRU_tail_ptr != entry_ptr ) ) + HDfprintf(stdout, "entry_ptr->aux_next == NULL && dLRU_tail_ptr != entry_ptr\n"); + + if ( ( cache_ptr->dLRU_list_len == 1 ) && + ( ! ( ( cache_ptr->dLRU_head_ptr == entry_ptr ) && + ( cache_ptr->dLRU_tail_ptr == entry_ptr ) && + ( entry_ptr->aux_next == NULL ) && + ( entry_ptr->aux_prev == NULL ) && + ( cache_ptr->dLRU_list_size == entry_ptr->size ) + ) + ) + ) + { + HDfprintf(stdout, "single entry dlru sanity check fails\n"); + } + + } + else + { + if ( cache_ptr->cLRU_head_ptr == NULL ) + HDfprintf(stdout,"cache_ptr->cLRU_head_ptr == NULL.\n"); + + if ( cache_ptr->cLRU_tail_ptr == NULL ) + HDfprintf(stdout,"cache_ptr->cLRU_tail_ptr == NULL.\n"); + + if ( cache_ptr->cLRU_list_len <= 0 ) + HDfprintf(stdout,"cache_ptr->cLRU_list_len <= 0.\n"); + + if ( cache_ptr->cLRU_list_size <= 0 ) + HDfprintf(stdout,"cache_ptr->cLRU_list_size <= 0.\n"); + + if ( cache_ptr->cLRU_list_size < entry_ptr->size ) + HDfprintf(stdout, + "cache_ptr->cLRU_list_size < entry_ptr->size.\n"); + + if ( ( (cache_ptr->cLRU_list_size) == entry_ptr->size ) && + ( ! ( (cache_ptr->cLRU_list_len) == 1 ) ) ) + HDfprintf(stdout, + "cLRU_list_size == size && cLRU_list_len != 1\n"); + + if ( ( entry_ptr->aux_prev == NULL ) && + ( cache_ptr->cLRU_head_ptr != entry_ptr ) ) + HDfprintf(stdout, "entry_ptr->aux_prev == NULL && cLRU_head_ptr != entry_ptr\n"); + + if ( ( entry_ptr->aux_next == NULL ) && + ( cache_ptr->cLRU_tail_ptr != entry_ptr ) ) + HDfprintf(stdout, "entry_ptr->aux_next == NULL && cLRU_tail_ptr != entry_ptr\n"); + + if ( ( cache_ptr->cLRU_list_len == 1 ) && + ( ! ( ( cache_ptr->cLRU_head_ptr == entry_ptr ) && + ( cache_ptr->cLRU_tail_ptr == entry_ptr ) && + ( entry_ptr->aux_next == NULL ) && + ( entry_ptr->aux_prev == NULL ) && + ( cache_ptr->cLRU_list_size == entry_ptr->size ) + ) + ) + ) + { + HDfprintf(stdout, "single entry clru sanity check fails\n"); + } + } + } +#endif /* JRM */ + H5C__UPDATE_RP_FOR_EVICTION(cache_ptr, entry_ptr, FAIL) } else { |