]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Merge patch from JeremyF:
authorJulian Seward <jseward@acm.org>
Wed, 13 Nov 2002 22:37:41 +0000 (22:37 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 13 Nov 2002 22:37:41 +0000 (22:37 +0000)
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

helgrind/hg_main.c

index ecb1df7333ddf7c50aef0c4b8b40a80e5548b894..85dcc80d70b9a2c57e5f132426a3a93608b79ec6 100644 (file)
@@ -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)