Author: sewardj Date: 2007-10-04 01:26:24 +0100 (Thu, 04 Oct 2007) New Revision: 6935
Log: Rewrite the LAOG machinery for a third time, using a redundant bidirectional graph implementation based on WordFM and WordSet. This largely but not completely fixes the performance problems introduced by r6932. Modified: branches/THRCHECK/thrcheck/tc_main.c Modified: branches/THRCHECK/thrcheck/tc_main.c =================================================================== --- branches/THRCHECK/thrcheck/tc_main.c 2007-10-03 21:09:17 UTC (rev 6934) +++ branches/THRCHECK/thrcheck/tc_main.c 2007-10-04 00:26:24 UTC (rev 6935) @@ -320,8 +320,9 @@ static WordFM* map_locks = NULL; /* WordFM LockAddr Lock* */ /* The word-set universes for thread sets and lock sets. */ -static WordSetU* univ_tsets = NULL; -static WordSetU* univ_lsets = NULL; +static WordSetU* univ_tsets = NULL; /* sets of Thread* */ +static WordSetU* univ_lsets = NULL; /* sets of Lock* */ +static WordSetU* univ_laog = NULL; /* sets of Lock*, for LAOG */ /* never changed; we only care about its address. Is treated as if it was a standard userspace lock. Also we have a Lock* describing it @@ -610,7 +611,7 @@ The elements in lock sets are Lock*, casted to Word. */ -#define N_LSID_BITS 16 +#define N_LSID_BITS 17 #define N_LSID_MASK ((1 << (N_LSID_BITS)) - 1) #define N_LSID_SHIFT 0 @@ -1044,6 +1045,10 @@ univ_lsets = TC_(newWordSetU)( tc_zalloc, tc_free ); tl_assert(univ_lsets != NULL); + tl_assert(univ_laog == NULL); + univ_laog = TC_(newWordSetU)( tc_zalloc, tc_free ); + tl_assert(univ_laog != NULL); + /* Set up entries for the root thread */ // FIXME: this assumes that the first real ThreadId is 1 @@ -3926,94 +3931,161 @@ /*--- Lock acquisition order monitoring ---*/ /*--------------------------------------------------------------*/ -/* Indicates that .fst must always be acquired before .snd */ typedef struct { - Lock* fst; - Lock* snd; + WordSetID inns; /* in univ_laog */ + WordSetID outs; /* in univ_laog */ } - LockPair; + LAOGLinks; -static Word cmp_LockPair ( LockPair* lp1, LockPair* lp2 ) { - if (lp1->fst < lp2->fst) return -1; - if (lp1->fst > lp2->fst) return 1; - if (lp1->snd < lp2->snd) return -1; - if (lp1->snd > lp2->snd) return 1; - return 0; -} - /* lock order acquisition graph */ -static WordFM* laog = NULL; /* WordFM LockPair* void */ +static WordFM* laog = NULL; /* WordFM Lock* LAOGLinks* */ static void laog__show ( void ) { - LockPair* edge; + Word i, ws_size; + Word* ws_words; + Lock* me; + LAOGLinks* links; VG_(printf)("laog {\n"); TC_(initIterFM)( laog ); - edge = NULL; - while (TC_(nextIterFM)( laog, (Word*)&edge, NULL)) { - tl_assert(edge); - VG_(printf)(" %p -> %p\n", edge->fst, edge->snd); - edge = NULL; + me = NULL; + links = NULL; + while (TC_(nextIterFM)( laog, (Word*)&me, (Word*)&links )) { + tl_assert(me); + tl_assert(links); + VG_(printf)(" node %p:\n", me); + TC_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->inns ); + for (i = 0; i < ws_size; i++) + VG_(printf)(" inn %p\n", ws_words[i] ); + TC_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->outs ); + for (i = 0; i < ws_size; i++) + VG_(printf)(" out %p\n", ws_words[i] ); + me = NULL; + links = NULL; } TC_(doneIterFM)( laog ); VG_(printf)("}\n"); } static void laog__add_edge ( Lock* src, Lock* dst ) { - LockPair key; - key.fst = src; - key.snd = dst; - if (TC_(lookupFM)( laog, NULL, NULL, (Word)&key )) { - /* already present; do nothing */ + Word keyW; + LAOGLinks* links; + if (0) VG_(printf)("laog__add_edge %p %p\n", src, dst); + /* Update the out edges for src */ + keyW = 0; + links = NULL; + if (TC_(lookupFM)( laog, &keyW, (Word*)&links, (Word)src )) { + tl_assert(links); + tl_assert(keyW == (Word)src); + links->outs = TC_(addToWS)( univ_laog, links->outs, (Word)dst ); } else { - LockPair* nyu = tc_zalloc(sizeof(LockPair)); - tl_assert(nyu); - *nyu = key; - TC_(addToFM)( laog, (Word)nyu, (Word)0 ); + links = tc_zalloc(sizeof(LAOGLinks)); + links->inns = TC_(emptyWS)( univ_laog ); + links->outs = TC_(singletonWS)( univ_laog, (Word)dst ); + TC_(addToFM)( laog, (Word)src, (Word)links ); } + /* Update the in edges for dst */ + keyW = 0; + links = NULL; + if (TC_(lookupFM)( laog, &keyW, (Word*)&links, (Word)dst )) { + tl_assert(links); + tl_assert(keyW == (Word)dst); + links->inns = TC_(addToWS)( univ_laog, links->inns, (Word)src ); + } else { + links = tc_zalloc(sizeof(LAOGLinks)); + links->inns = TC_(singletonWS)( univ_laog, (Word)src ); + links->outs = TC_(emptyWS)( univ_laog ); + TC_(addToFM)( laog, (Word)dst, (Word)links ); + } } static void laog__del_edge ( Lock* src, Lock* dst ) { - Bool b; - LockPair key; - LockPair* old = NULL; - key.fst = src; - key.snd = dst; - b = TC_(delFromFM)( laog, (Word*)&old, NULL, (Word)&key ); - tl_assert(b); - tl_assert(old); - tc_free(old); + Word keyW; + LAOGLinks* links; + if (0) VG_(printf)("laog__del_edge %p %p\n", src, dst); + /* Update the out edges for src */ + keyW = 0; + links = NULL; + if (TC_(lookupFM)( laog, &keyW, (Word*)&links, (Word)src )) { + tl_assert(links); + tl_assert(keyW == (Word)src); + links->outs = TC_(delFromWS)( univ_laog, links->outs, (Word)dst ); + } + /* Update the in edges for dst */ + keyW = 0; + links = NULL; + if (TC_(lookupFM)( laog, &keyW, (Word*)&links, (Word)dst )) { + tl_assert(links); + tl_assert(keyW == (Word)dst); + links->inns = TC_(delFromWS)( univ_laog, links->inns, (Word)src ); + } } -static WordSetID /* in univ_lsets */ laog__step ( Lock* lk, Bool succs ) { - LockPair* edge; - WordSetID result; - result = TC_(emptyWS)( univ_lsets ); +static WordSetID /* in univ_laog */ laog__succs ( Lock* lk ) { + Word keyW; + LAOGLinks* links; + keyW = 0; + links = NULL; + if (TC_(lookupFM)( laog, &keyW, (Word*)&links, (Word)lk )) { + tl_assert(links); + tl_assert(keyW == (Word)lk); + return links->outs; + } else { + return TC_(emptyWS)( univ_laog ); + } +} + +static WordSetID /* in univ_laog */ laog__preds ( Lock* lk ) { + Word keyW; + LAOGLinks* links; + keyW = 0; + links = NULL; + if (TC_(lookupFM)( laog, &keyW, (Word*)&links, (Word)lk )) { + tl_assert(links); + tl_assert(keyW == (Word)lk); + return links->inns; + } else { + return TC_(emptyWS)( univ_laog ); + } +} + +static void laog__sanity_check ( void ) { + Word i, ws_size; + Word* ws_words; + Lock* me; + LAOGLinks* links; TC_(initIterFM)( laog ); - edge = NULL; - while (TC_(nextIterFM)( laog, (Word*)&edge, NULL)) { - tl_assert(edge); - if (succs) { - if (edge->fst == lk) - result = TC_(addToWS)( univ_lsets, result, (Word)edge->snd ); - } else { - if (edge->snd == lk) - result = TC_(addToWS)( univ_lsets, result, (Word)edge->fst ); + me = NULL; + links = NULL; +VG_(printf)("laog sanity check\n"); + while (TC_(nextIterFM)( laog, (Word*)&me, (Word*)&links )) { + tl_assert(me); + tl_assert(links); + TC_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->inns ); + for (i = 0; i < ws_size; i++) { + if ( ! TC_(elemWS)( univ_laog, + laog__succs( (Lock*)ws_words[i] ), + (Word)me )) + goto bad; } - edge = NULL; + TC_(getPayloadWS)( &ws_words, &ws_size, univ_laog, links->outs ); + for (i = 0; i < ws_size; i++) { + if ( ! TC_(elemWS)( univ_laog, + laog__preds( (Lock*)ws_words[i] ), + (Word)me )) + goto bad; + } + me = NULL; + links = NULL; } TC_(doneIterFM)( laog ); - return result; -} + return; -static WordSetID /* in univ_lsets */ laog__succs ( Lock* lk ) { - return laog__step( lk, True /* get successors of 'lk' */ ); + bad: + laog__show(); + tl_assert(0); } -static WordSetID /* in univ_lsets */ laog__preds ( Lock* lk ) { - return laog__step( lk, False /* get predecessors of 'lk' */ ); -} - static Bool laog__do_dfs_from_to ( Lock* src, Lock* dst ) { Bool ret; @@ -4024,7 +4096,7 @@ WordSetID succs; Word succs_size; Word* succs_words; - + //laog__sanity_check(); stack = VG_(newXA)( tc_zalloc, tc_free, sizeof(Lock*) ); visited = TC_(newFM)( tc_zalloc, tc_free, NULL/*unboxedcmp*/ ); @@ -4047,7 +4119,7 @@ TC_(addToFM)( visited, (Word)here, 0 ); succs = laog__succs( here ); - TC_(getPayloadWS)( &succs_words, &succs_size, univ_lsets, succs ); + TC_(getPayloadWS)( &succs_words, &succs_size, univ_laog, succs ); for (i = 0; i < succs_size; i++) (void) VG_(addToXA)( stack, &succs_words[i] ); } @@ -4073,12 +4145,12 @@ /* It may be that 'thr' already holds 'lk' and is recursively relocking in. In this case we just ignore the call. */ + /* NB: univ_lsets really is correct here */ if (TC_(elemWS)( univ_lsets, thr->locksetA, (Word)lk )) return; if (!laog) - laog = TC_(newFM)( tc_zalloc, tc_free, - (Word(*)(Word,Word)) cmp_LockPair ); + laog = TC_(newFM)( tc_zalloc, tc_free, NULL/*unboxedcmp*/ ); /* First, the check. Complain if there is any path in laog from lk to old for each old <- locks already held by thr. @@ -4115,11 +4187,11 @@ preds = laog__preds( lk ); succs = laog__succs( lk ); - TC_(getPayloadWS)( &preds_words, &preds_size, univ_lsets, preds ); + TC_(getPayloadWS)( &preds_words, &preds_size, univ_laog, preds ); for (i = 0; i < preds_size; i++) laog__del_edge( (Lock*)preds_words[i], lk ); - TC_(getPayloadWS)( &succs_words, &succs_size, univ_lsets, succs ); + TC_(getPayloadWS)( &succs_words, &succs_size, univ_laog, succs ); for (j = 0; j < succs_size; j++) laog__del_edge( lk, (Lock*)succs_words[j] ); @@ -4132,7 +4204,7 @@ } static void laog__handle_lock_deletions ( - WordSetID /* in univ_lsets */ locksToDelete + WordSetID /* in univ_laog */ locksToDelete ) { Word i, ws_size; @@ -5586,6 +5658,8 @@ (Int)TC_(cardinalityWSU)( univ_lsets )); VG_(printf)("threadsets: %8d unique thread sets\n", (Int)TC_(cardinalityWSU)( univ_tsets )); + VG_(printf)("univ_laog: %8d unique lock sets\n", + (Int)TC_(cardinalityWSU)( univ_laog )); VG_(printf)("L(ast)L(ock) map: %8lu inserts (%d map size)\n", stats__ga_LL_adds, ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ Valgrind-developers mailing list Valgrind-developers@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/valgrind-developers