Merge patch from JeremyF:

26-hg-client-reqs

HELGRIND: first client requests. Adds a request to return memory to
its virginal state (useful for allocators which recycle memory), and
one to put memory into an error state (useful for suppressing errors
from known races).


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1301 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/helgrind/helgrind.h b/helgrind/helgrind.h
new file mode 100644
index 0000000..2b25d47
--- /dev/null
+++ b/helgrind/helgrind.h
@@ -0,0 +1,91 @@
+/*
+   ----------------------------------------------------------------
+
+   Notice that the following BSD-style license applies to this one
+   file (helgrind.h) only.  The entire rest of Valgrind is licensed
+   under the terms of the GNU General Public License, version 2.  See
+   the COPYING file in the source distribution for details.
+
+   ----------------------------------------------------------------
+
+   This file is part of helgrind, a Valgrind skin for detecting
+   data races in threaded programs.
+
+   Copyright (C) 2000-2002 Nicholas Nethercote.  All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+   2. The origin of this software must not be misrepresented; you must 
+      not claim that you wrote the original software.  If you use this 
+      software in a product, an acknowledgment in the product 
+      documentation would be appreciated but is not required.
+
+   3. Altered source versions must be plainly marked as such, and must
+      not be misrepresented as being the original software.
+
+   4. The name of the author may not be used to endorse or promote 
+      products derived from this software without specific prior written 
+      permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   ----------------------------------------------------------------
+
+   Notice that the above BSD-style license applies to this one file
+   (helgrind.h) only.  The entire rest of Valgrind is licensed under
+   the terms of the GNU General Public License, version 2.  See the
+   COPYING file in the source distribution for details.
+
+   ---------------------------------------------------------------- 
+*/
+
+#ifndef __HELGRIND_H
+#define __HELGRIND_H
+
+#include "valgrind.h"
+
+typedef
+   enum {
+      VG_USERREQ__HG_CLEAN_MEMORY = VG_USERREQ_SKIN_BASE('H','G'),
+      VG_USERREQ__HG_KNOWN_RACE,
+   } Vg_HelgrindClientRequest;
+
+/* Clean memory state.  This makes Helgrind forget everything it knew
+   about the specified memory range, and resets it to virgin.  This is
+   particularly useful for memory allocators who wish to recycle
+   memory. */
+#define VALGRIND_HG_CLEAN_MEMORY(_qzz_start, _qzz_len)			\
+   do {									\
+     unsigned int _qzz_res;						\
+     VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, VG_USERREQ__HG_CLEAN_MEMORY,	\
+			     _qzz_start, _qzz_len, 0, 0);		\
+     (void)0;								\
+   } while(0)
+
+/* Mark memory as known racy.  This puts the memory range specified
+   into the error state, so that data race errors are not reported
+   against it. */
+#define VALGRIND_HG_KNOWN_RACE(_qzz_start, _qzz_len)			\
+   do {									\
+     unsigned int _qzz_res;						\
+     VALGRIND_MAGIC_SEQUENCE(_qzz_res, 0, VG_USERREQ__HG_KNOWN_RACE,	\
+			     _qzz_start, _qzz_len, 0, 0);		\
+     (void)0;								\
+   } while(0)
+
+#endif /* __HELGRIND_H */
diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c
index 12db6ba..34d44ca 100644
--- a/helgrind/hg_main.c
+++ b/helgrind/hg_main.c
@@ -30,6 +30,7 @@
 */
 
 #include "vg_skin.h"
+#include "helgrind.h"
 
 VG_DETERMINE_INTERFACE_VERSION
 
@@ -114,7 +115,7 @@
 /*------------------------------------------------------------*/
 
 typedef enum 
-   { Vge_VirginInit, Vge_NonVirginInit, Vge_SegmentInit } 
+   { Vge_VirginInit, Vge_NonVirginInit, Vge_SegmentInit, Vge_Error } 
    VgeInitStatus;
 
 /* Should add up to 32 to fit in one word */
@@ -152,7 +153,8 @@
 static ESecMap* primary_map[ 65536 ];
 static ESecMap  distinguished_secondary_map;
 
-static shadow_word virgin_sword = { 0, Vge_Virgin };
+static const shadow_word virgin_sword = { 0, Vge_Virgin };
+static const shadow_word error_sword = { TID_INDICATING_ALL, Vge_Excl };
 
 #define VGE_IS_DISTINGUISHED_SM(smap) \
    ((smap) == &distinguished_secondary_map)
@@ -268,6 +270,11 @@
    set_sword(a, virgin_sword);
 }
 
+static __inline__
+void init_error_sword(Addr a)
+{
+   set_sword(a, error_sword);
+}
 
 /* 'a' is guaranteed to be 4-byte aligned here (not that that's important,
  * really) */
@@ -1375,6 +1382,13 @@
          init_magically_inited_sword(a);
       }
       break;
+
+   case Vge_Error:
+      for ( ; a < end; a += 4) {
+         //PROF_EVENT(31);  PPP
+         init_error_sword(a);
+      }
+      break;
    
    default:
       VG_(printf)("init_status = %u\n", status);
@@ -1861,7 +1875,6 @@
 				  shadow_word prevstate )
 {
    HelgrindError err_extra;
-   static const shadow_word err_sw = { TID_INDICATING_ALL, Vge_Excl };
 
    n_eraser_warnings++;
 
@@ -1874,7 +1887,7 @@
                             (is_write ? "writing" : "reading"),
                             &err_extra);
 
-   set_sword(a, err_sw);
+   set_sword(a, error_sword);
 }
 
 static void record_mutex_error(ThreadId tid, hg_mutex_t *mutex, 
@@ -2441,6 +2454,34 @@
 }
 
 /*--------------------------------------------------------------------*/
+/*--- Client requests                                              ---*/
+/*--------------------------------------------------------------------*/
+
+Bool SK_(handle_client_request)(ThreadState *tst, UInt *args, UInt *ret)
+{
+   if (!VG_IS_SKIN_USERREQ('H','G',args[0]))
+      return False;
+
+   switch(args[0]) {
+   case VG_USERREQ__HG_CLEAN_MEMORY:
+      set_address_range_state(args[1], args[2], Vge_VirginInit);
+      *ret = 0;			/* meaningless */
+      break;
+
+   case VG_USERREQ__HG_KNOWN_RACE:
+      set_address_range_state(args[1], args[2], Vge_Error);
+      *ret = 0;			/* meaningless */
+      break;
+
+   default:
+      return False;
+   }
+
+   return True;
+}
+
+
+/*--------------------------------------------------------------------*/
 /*--- Setup                                                        ---*/
 /*--------------------------------------------------------------------*/
 
@@ -2461,6 +2502,7 @@
    needs->data_syms             = True;
    needs->sizeof_shadow_block	= SHADOW_EXTRA;
    needs->alternative_free      = True;
+   needs->client_requests       = True;
 
    track->new_mem_startup       = & eraser_new_mem_startup;
    track->new_mem_heap          = & eraser_new_mem_heap;