From: Julian Seward Date: Wed, 13 Nov 2002 22:37:41 +0000 (+0000) Subject: Merge patch from JeremyF: X-Git-Tag: svn/VALGRIND_1_9_4~138 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ef4e9cecd522a1e30a67a2da45433b0025889453;p=thirdparty%2Fvalgrind.git Merge patch from JeremyF: 38-hg-lazy-lasttouch HELGRIND: rather than recording the last access, record the last state change. This is more interesting and useful, and uses up a lot less memory when using (now inaccurately named) --show-last-access=all. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1309 --- diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index ecb1df7333..85dcc80d70 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -2393,6 +2393,7 @@ void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) ) VG_(message)(Vg_UserMsg, "Possible data race %s variable at %p %(y", err->string, err->addr, err->addr ); pp_ExeContext(); + pp_AddrInfo(err->addr, &extra->addrinfo); switch(extra->prevstate.state) { case Vge_Virgin: @@ -2428,14 +2429,12 @@ void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) ) if (*msg) VG_(message)(Vg_UserMsg, " Previous state: %s", msg); - pp_AddrInfo(err->addr, &extra->addrinfo); - if (clo_execontext == EC_Some && extra->lasttouched.eip != 0) { Char file[100]; UInt line; Addr eip = extra->lasttouched.eip; - VG_(message)(Vg_UserMsg, " Word at %p last accessed", err->addr); + VG_(message)(Vg_UserMsg, " Word at %p last changed state", err->addr); if (VG_(get_filename_linenum)(eip, file, sizeof(file), &line)) { VG_(message)(Vg_UserMsg, " at %p: %y (%s:%u)", @@ -2447,7 +2446,7 @@ void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) ) VG_(message)(Vg_UserMsg, " at %p: %y", eip, eip); } } else if (clo_execontext == EC_All && extra->lasttouched.ec != NULL) { - VG_(message)(Vg_UserMsg, " Word at %p last accessed", err->addr); + VG_(message)(Vg_UserMsg, " Word at %p last changed state", err->addr); VG_(pp_ExeContext)(extra->lasttouched.ec); } @@ -2642,120 +2641,111 @@ void dump_around_a(Addr a) #define DEBUG_STATE(args...) #endif - -static void eraser_mem_read(Addr a, UInt size, ThreadState *tst) +static void eraser_mem_read_word(Addr a, ThreadId tid, ThreadState *tst) { - ThreadId tid; - ThreadLifeSeg *tls; shadow_word* sword; - Addr end; shadow_word prevstate; + ThreadLifeSeg *tls; const LockSet *ls; + Bool statechange = False; - end = ROUNDUP(a+size, 4); - a = ROUNDDN(a, 4); - - if (tst == NULL) - tid = VG_(get_current_tid)(); - else - tid = VG_(get_tid_from_ThreadState)(tst); + static const void *const states[4] = { + [Vge_Virgin] &&st_virgin, + [Vge_Excl] &&st_excl, + [Vge_Shar] &&st_shar, + [Vge_SharMod] &&st_sharmod, + }; tls = thread_seg[tid]; sk_assert(tls != NULL && tls->tid == tid); - for ( ; a < end; a += 4) { - static const void *const states[4] = { - [Vge_Virgin] &&st_virgin, - [Vge_Excl] &&st_excl, - [Vge_Shar] &&st_shar, - [Vge_SharMod] &&st_sharmod, - }; - - sword = get_sword_addr(a); - if (sword == SEC_MAP_ACCESS) { - VG_(printf)("read distinguished 2ndary map! 0x%x\n", a); - continue; - } + sword = get_sword_addr(a); + if (sword == SEC_MAP_ACCESS) { + VG_(printf)("read distinguished 2ndary map! 0x%x\n", a); + return; + } - prevstate = *sword; + prevstate = *sword; - goto *states[sword->state]; + goto *states[sword->state]; - /* This looks like reading of unitialised memory, may be legit. Eg. - * calloc() zeroes its values, so untouched memory may actually be - * initialised. Leave that stuff to Valgrind. */ - st_virgin: - if (TID_INDICATING_NONVIRGIN == sword->other) { - DEBUG_STATE("Read VIRGIN --> EXCL: %8x, %u\n", a, tid); - if (DEBUG_VIRGIN_READS) - dump_around_a(a); - } else { - DEBUG_STATE("Read SPECIAL --> EXCL: %8x, %u\n", a, tid); - } - *sword = SW(Vge_Excl, packTLS(tls)); /* remember exclusive owner */ + /* This looks like reading of unitialised memory, may be legit. Eg. + * calloc() zeroes its values, so untouched memory may actually be + * initialised. Leave that stuff to Valgrind. */ + st_virgin: + if (TID_INDICATING_NONVIRGIN == sword->other) { + DEBUG_STATE("Read VIRGIN --> EXCL: %8x, %u\n", a, tid); + if (DEBUG_VIRGIN_READS) + dump_around_a(a); + } else { + DEBUG_STATE("Read SPECIAL --> EXCL: %8x, %u\n", a, tid); + } + statechange = True; + *sword = SW(Vge_Excl, packTLS(tls)); /* remember exclusive owner */ + tls->refcount++; + goto done; + + st_excl: { + ThreadLifeSeg *sw_tls = unpackTLS(sword->other); + + if (tls == sw_tls) { + DEBUG_STATE("Read EXCL: %8x, %u\n", a, tid); + } else if (unpackTLS(TLSP_INDICATING_ALL) == sw_tls) { + DEBUG_STATE("Read EXCL/ERR: %8x, %u\n", a, tid); + } else if (tlsIsDisjoint(tls, sw_tls)) { + DEBUG_STATE("Read EXCL(%u) --> EXCL: %8x, %u\n", sw_tls->tid, a, tid); + statechange = True; + sword->other = packTLS(tls); + sw_tls->refcount--; tls->refcount++; - goto done; - - st_excl: { - ThreadLifeSeg *sw_tls = unpackTLS(sword->other); - - if (tls == sw_tls) { - DEBUG_STATE("Read EXCL: %8x, %u\n", a, tid); - } else if (unpackTLS(TLSP_INDICATING_ALL) == sw_tls) { - DEBUG_STATE("Read EXCL/ERR: %8x, %u\n", a, tid); - } else if (tlsIsDisjoint(tls, sw_tls)) { - DEBUG_STATE("Read EXCL(%u) --> EXCL: %8x, %u\n", sw_tls->tid, a, tid); - sword->other = packTLS(tls); - sw_tls->refcount--; - tls->refcount++; - } else { - DEBUG_STATE("Read EXCL(%u) --> SHAR: %8x, %u\n", sw_tls->tid, a, tid); - sw_tls->refcount--; - *sword = SW(Vge_Shar, packLockSet(thread_locks[tid])); + } else { + DEBUG_STATE("Read EXCL(%u) --> SHAR: %8x, %u\n", sw_tls->tid, a, tid); + sw_tls->refcount--; + statechange = True; + *sword = SW(Vge_Shar, packLockSet(thread_locks[tid])); - if (DEBUG_MEM_LOCKSET_CHANGES) - print_LockSet("excl read locks", unpackLockSet(sword->other)); - } - goto done; + if (DEBUG_MEM_LOCKSET_CHANGES) + print_LockSet("excl read locks", unpackLockSet(sword->other)); } + goto done; + } - st_shar: - DEBUG_STATE("Read SHAR: %8x, %u\n", a, tid); - sword->other = packLockSet(intersect(unpackLockSet(sword->other), - thread_locks[tid])); - goto done; + st_shar: + DEBUG_STATE("Read SHAR: %8x, %u\n", a, tid); + sword->other = packLockSet(intersect(unpackLockSet(sword->other), + thread_locks[tid])); + statechange = sword->other != prevstate.other; + goto done; - st_sharmod: - DEBUG_STATE("Read SHAR_MOD: %8x, %u\n", a, tid); - ls = intersect(unpackLockSet(sword->other), - thread_locks[tid]); - sword->other = packLockSet(ls); + st_sharmod: + DEBUG_STATE("Read SHAR_MOD: %8x, %u\n", a, tid); + ls = intersect(unpackLockSet(sword->other), + thread_locks[tid]); + sword->other = packLockSet(ls); - if (isempty(ls)) { - record_eraser_error(tst, a, False /* !is_write */, prevstate); - } - goto done; + statechange = sword->other != prevstate.other; - done: - if (clo_execontext != EC_None) { - EC_EIP eceip; + if (isempty(ls)) { + record_eraser_error(tst, a, False /* !is_write */, prevstate); + } + goto done; - if (clo_execontext == EC_Some) - eceip.eip = VG_(get_EIP)(tst); - else - eceip.ec = VG_(get_ExeContext)(tst); - setExeContext(a, eceip); - } + done: + if (clo_execontext != EC_None && statechange) { + EC_EIP eceip; + + if (clo_execontext == EC_Some) + eceip.eip = VG_(get_EIP)(tst); + else + eceip.ec = VG_(get_ExeContext)(tst); + setExeContext(a, eceip); } } -static void eraser_mem_write(Addr a, UInt size, ThreadState *tst) +static void eraser_mem_read(Addr a, UInt size, ThreadState *tst) { ThreadId tid; - ThreadLifeSeg *tls; - shadow_word* sword; Addr end; - shadow_word prevstate; end = ROUNDUP(a+size, 4); a = ROUNDDN(a, 4); @@ -2764,92 +2754,123 @@ static void eraser_mem_write(Addr a, UInt size, ThreadState *tst) tid = VG_(get_current_tid)(); else tid = VG_(get_tid_from_ThreadState)(tst); - + + + for ( ; a < end; a += 4) + eraser_mem_read_word(a, tid, tst); +} + +static void eraser_mem_write_word(Addr a, ThreadId tid, ThreadState *tst) +{ + ThreadLifeSeg *tls; + shadow_word* sword; + shadow_word prevstate; + Bool statechange = False; + static const void *const states[4] = { + [Vge_Virgin] &&st_virgin, + [Vge_Excl] &&st_excl, + [Vge_Shar] &&st_shar, + [Vge_SharMod] &&st_sharmod, + }; + tls = thread_seg[tid]; sk_assert(tls != NULL && tls->tid == tid); - for ( ; a < end; a += 4) { - static const void *const states[4] = { - [Vge_Virgin] &&st_virgin, - [Vge_Excl] &&st_excl, - [Vge_Shar] &&st_shar, - [Vge_SharMod] &&st_sharmod, - }; - - sword = get_sword_addr(a); - if (sword == SEC_MAP_ACCESS) { - VG_(printf)("read distinguished 2ndary map! 0x%x\n", a); - continue; - } + sword = get_sword_addr(a); + if (sword == SEC_MAP_ACCESS) { + VG_(printf)("read distinguished 2ndary map! 0x%x\n", a); + return; + } - prevstate = *sword; + prevstate = *sword; - goto *states[sword->state]; + goto *states[sword->state]; - st_virgin: - if (TID_INDICATING_NONVIRGIN == sword->other) - DEBUG_STATE("Write VIRGIN --> EXCL: %8x, %u\n", a, tid); - else - DEBUG_STATE("Write SPECIAL --> EXCL: %8x, %u\n", a, tid); - *sword = SW(Vge_Excl, packTLS(tls));/* remember exclusive owner */ + st_virgin: + if (TID_INDICATING_NONVIRGIN == sword->other) + DEBUG_STATE("Write VIRGIN --> EXCL: %8x, %u\n", a, tid); + else + DEBUG_STATE("Write SPECIAL --> EXCL: %8x, %u\n", a, tid); + statechange = True; + *sword = SW(Vge_Excl, packTLS(tls));/* remember exclusive owner */ + tls->refcount++; + goto done; + + st_excl: { + ThreadLifeSeg *sw_tls = unpackTLS(sword->other); + + if (tls == sw_tls) { + DEBUG_STATE("Write EXCL: %8x, %u\n", a, tid); + goto done; + } else if (unpackTLS(TLSP_INDICATING_ALL) == sw_tls) { + DEBUG_STATE("Write EXCL/ERR: %8x, %u\n", a, tid); + goto done; + } else if (tlsIsDisjoint(tls, sw_tls)) { + DEBUG_STATE("Write EXCL(%u) --> EXCL: %8x, %u\n", sw_tls->tid, a, tid); + sword->other = packTLS(tls); + sw_tls->refcount--; tls->refcount++; - goto done; - - st_excl: { - ThreadLifeSeg *sw_tls = unpackTLS(sword->other); - - if (tls == sw_tls) { - DEBUG_STATE("Write EXCL: %8x, %u\n", a, tid); - goto done; - } else if (unpackTLS(TLSP_INDICATING_ALL) == sw_tls) { - DEBUG_STATE("Write EXCL/ERR: %8x, %u\n", a, tid); - goto done; - } else if (tlsIsDisjoint(tls, sw_tls)) { - DEBUG_STATE("Write EXCL(%u) --> EXCL: %8x, %u\n", sw_tls->tid, a, tid); - sword->other = packTLS(tls); - sw_tls->refcount--; - tls->refcount++; - goto done; - } else { - DEBUG_STATE("Write EXCL(%u) --> SHAR_MOD: %8x, %u\n", sw_tls->tid, a, tid); - sw_tls->refcount--; - *sword = SW(Vge_SharMod, packLockSet(thread_locks[tid])); - if(DEBUG_MEM_LOCKSET_CHANGES) - print_LockSet("excl write locks", unpackLockSet(sword->other)); - goto SHARED_MODIFIED; - } + goto done; + } else { + DEBUG_STATE("Write EXCL(%u) --> SHAR_MOD: %8x, %u\n", sw_tls->tid, a, tid); + statechange = True; + sw_tls->refcount--; + *sword = SW(Vge_SharMod, packLockSet(thread_locks[tid])); + if(DEBUG_MEM_LOCKSET_CHANGES) + print_LockSet("excl write locks", unpackLockSet(sword->other)); + goto SHARED_MODIFIED; } + } - st_shar: - DEBUG_STATE("Write SHAR --> SHAR_MOD: %8x, %u\n", a, tid); - sword->state = Vge_SharMod; - sword->other = packLockSet(intersect(unpackLockSet(sword->other), - thread_locks[tid])); - goto SHARED_MODIFIED; - - st_sharmod: - DEBUG_STATE("Write SHAR_MOD: %8x, %u\n", a, tid); - sword->other = packLockSet(intersect(unpackLockSet(sword->other), - thread_locks[tid])); - SHARED_MODIFIED: - if (isempty(unpackLockSet(sword->other))) { - record_eraser_error(tst, a, True /* is_write */, prevstate); - } - goto done; + st_shar: + DEBUG_STATE("Write SHAR --> SHAR_MOD: %8x, %u\n", a, tid); + sword->state = Vge_SharMod; + sword->other = packLockSet(intersect(unpackLockSet(sword->other), + thread_locks[tid])); + statechange = True; + goto SHARED_MODIFIED; - done: - if (clo_execontext != EC_None) { - EC_EIP eceip; + st_sharmod: + DEBUG_STATE("Write SHAR_MOD: %8x, %u\n", a, tid); + sword->other = packLockSet(intersect(unpackLockSet(sword->other), + thread_locks[tid])); + statechange = sword->other != prevstate.other; - if (clo_execontext == EC_Some) - eceip.eip = VG_(get_EIP)(tst); - else - eceip.ec = VG_(get_ExeContext)(tst); - setExeContext(a, eceip); - } + SHARED_MODIFIED: + if (isempty(unpackLockSet(sword->other))) { + record_eraser_error(tst, a, True /* is_write */, prevstate); + } + goto done; + + done: + if (clo_execontext != EC_None && statechange) { + EC_EIP eceip; + + if (clo_execontext == EC_Some) + eceip.eip = VG_(get_EIP)(tst); + else + eceip.ec = VG_(get_ExeContext)(tst); + setExeContext(a, eceip); } } +static void eraser_mem_write(Addr a, UInt size, ThreadState *tst) +{ + ThreadId tid; + Addr end; + + end = ROUNDUP(a+size, 4); + a = ROUNDDN(a, 4); + + if (tst == NULL) + tid = VG_(get_current_tid)(); + else + tid = VG_(get_tid_from_ThreadState)(tst); + + for ( ; a < end; a += 4) + eraser_mem_write_word(a, tid, tst); +} + #undef DEBUG_STATE static void eraser_mem_help_read_1(Addr a)