You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
|
|
1
(13) |
2
(15) |
|
3
(16) |
4
(42) |
5
(9) |
6
(20) |
7
(22) |
8
(24) |
9
(12) |
|
10
(24) |
11
(11) |
12
(2) |
13
(13) |
14
(8) |
15
|
16
(16) |
|
17
(24) |
18
(36) |
19
(100) |
20
(94) |
21
(50) |
22
(39) |
23
(10) |
|
24
(14) |
25
(19) |
26
(2) |
27
(6) |
28
(17) |
29
(9) |
30
(8) |
|
31
(21) |
|
|
|
|
|
|
|
From: Tom H. <th...@cy...> - 2009-05-23 02:44:39
|
Nightly build on lloyd ( x86_64, Fedora 7 ) started at 2009-05-23 03:05:05 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... done Regression test results follow == 481 tests, 0 stderr failures, 0 stdout failures, 0 post failures == |
|
From: Tom H. <th...@cy...> - 2009-05-23 02:27:39
|
Nightly build on mg ( x86_64, Fedora 9 ) started at 2009-05-23 03:10:05 BST Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 487 tests, 0 stderr failures, 1 stdout failure, 0 post failures == none/tests/linux/mremap2 (stdout) |
|
From: <sv...@va...> - 2009-05-23 02:10:22
|
Author: njn
Date: 2009-05-23 02:51:39 +0100 (Sat, 23 May 2009)
New Revision: 10120
Log:
Trunk sync: sys_readlink layout.
Modified:
branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c
Modified: branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c 2009-05-23 01:18:44 UTC (rev 10119)
+++ branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c 2009-05-23 01:51:39 UTC (rev 10120)
@@ -3661,8 +3661,7 @@
PRE(sys_readlink)
{
- Bool done = False;
- Word saved = SYSNO;
+ Word saved = SYSNO;
PRINT("sys_readlink ( %#lx(%s), %#lx, %llu )", ARG1,(char*)ARG1,ARG2,(ULong)ARG3);
PRE_REG_READ3(long, "readlink",
@@ -3670,28 +3669,28 @@
PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 );
-#if HAVE_PROC
- /*
- * Handle the case where readlink is looking at /proc/self/exe or
- * /proc/<pid>/exe.
- */
{
+#if HAVE_PROC
+ /*
+ * Handle the case where readlink is looking at /proc/self/exe or
+ * /proc/<pid>/exe.
+ */
HChar name[25];
- VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
- if (ML_(safe_to_deref)((void*)ARG1, 1)
- && (VG_(strcmp)((Char *)ARG1, name) == 0
- || VG_(strcmp)((Char *)ARG1, "/proc/self/exe") == 0)) {
- VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
- SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name,
- ARG2, ARG3));
- done = True;
- }
- }
+ Char* arg1s = (Char*) ARG1;
+ VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
+ if (ML_(safe_to_deref)(arg1s, 1) &&
+ (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/exe"))
+ )
+ {
+ VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
+ SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name,
+ ARG2, ARG3));
+ } else
#endif
-
- if (!done) {
- /* Normal case */
- SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3));
+ {
+ /* Normal case */
+ SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3));
+ }
}
if (SUCCESS && RES > 0)
|
|
From: <sv...@va...> - 2009-05-23 02:10:22
|
Author: njn
Date: 2009-05-23 02:51:54 +0100 (Sat, 23 May 2009)
New Revision: 10121
Log:
DARWIN sync: sys_readlink layout.
Modified:
trunk/coregrind/m_syswrap/syswrap-generic.c
Modified: trunk/coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-generic.c 2009-05-23 01:51:39 UTC (rev 10120)
+++ trunk/coregrind/m_syswrap/syswrap-generic.c 2009-05-23 01:51:54 UTC (rev 10121)
@@ -3540,8 +3540,7 @@
PRE(sys_readlink)
{
- HChar name[25];
- Word saved = SYSNO;
+ Word saved = SYSNO;
PRINT("sys_readlink ( %#lx(%s), %#lx, %llu )", ARG1,(char*)ARG1,ARG2,(ULong)ARG3);
PRE_REG_READ3(long, "readlink",
@@ -3549,20 +3548,26 @@
PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 );
- /*
- * Handle the case where readlink is looking at /proc/self/exe or
- * /proc/<pid>/exe.
- */
- VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
- if (ML_(safe_to_deref)((void*)ARG1, 1)
- && (VG_(strcmp)((Char *)ARG1, name) == 0
- || VG_(strcmp)((Char *)ARG1, "/proc/self/exe") == 0)) {
- VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
- SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name,
- ARG2, ARG3));
- } else {
- /* Normal case */
- SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3));
+ {
+ /*
+ * Handle the case where readlink is looking at /proc/self/exe or
+ * /proc/<pid>/exe.
+ */
+ HChar name[25];
+ Char* arg1s = (Char*) ARG1;
+ VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
+ if (ML_(safe_to_deref)(arg1s, 1) &&
+ (VG_STREQ(arg1s, name) || VG_STREQ(arg1s, "/proc/self/exe"))
+ )
+ {
+ VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
+ SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name,
+ ARG2, ARG3));
+ } else
+ {
+ /* Normal case */
+ SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3));
+ }
}
if (SUCCESS && RES > 0)
|
|
From: <sv...@va...> - 2009-05-23 01:18:51
|
Author: njn
Date: 2009-05-23 02:18:44 +0100 (Sat, 23 May 2009)
New Revision: 10119
Log:
DARWIN sync: remove '.' from some field names for consistency, and factor
out some variables.
Modified:
trunk/coregrind/m_syswrap/syswrap-generic.c
Modified: trunk/coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-generic.c 2009-05-23 01:18:16 UTC (rev 10118)
+++ trunk/coregrind/m_syswrap/syswrap-generic.c 2009-05-23 01:18:44 UTC (rev 10119)
@@ -911,6 +911,9 @@
struct vki_sockaddr *sa, UInt salen )
{
Char *outmsg;
+ struct vki_sockaddr_un* sun = (struct vki_sockaddr_un *)sa;
+ struct vki_sockaddr_in* sin = (struct vki_sockaddr_in *)sa;
+ struct vki_sockaddr_in6* sin6 = (struct vki_sockaddr_in6 *)sa;
/* NULL/zero-length sockaddrs are legal */
if ( sa == NULL || salen == 0 ) return;
@@ -918,45 +921,36 @@
outmsg = VG_(arena_malloc) ( VG_AR_CORE, "di.syswrap.pmr_sockaddr.1",
VG_(strlen)( description ) + 30 );
- VG_(sprintf) ( outmsg, description, ".sa_family" );
+ VG_(sprintf) ( outmsg, description, "sa_family" );
PRE_MEM_READ( outmsg, (Addr) &sa->sa_family, sizeof(vki_sa_family_t));
switch (sa->sa_family) {
case VKI_AF_UNIX:
- VG_(sprintf) ( outmsg, description, ".sun_path" );
- PRE_MEM_RASCIIZ( outmsg,
- (Addr) ((struct vki_sockaddr_un *) sa)->sun_path);
+ VG_(sprintf) ( outmsg, description, "sun_path" );
+ PRE_MEM_RASCIIZ( outmsg, (Addr) sun->sun_path );
break;
case VKI_AF_INET:
- VG_(sprintf) ( outmsg, description, ".sin_port" );
- PRE_MEM_READ( outmsg,
- (Addr) &((struct vki_sockaddr_in *) sa)->sin_port,
- sizeof (((struct vki_sockaddr_in *) sa)->sin_port));
- VG_(sprintf) ( outmsg, description, ".sin_addr" );
- PRE_MEM_READ( outmsg,
- (Addr) &((struct vki_sockaddr_in *) sa)->sin_addr,
- sizeof (struct vki_in_addr));
+ VG_(sprintf) ( outmsg, description, "sin_port" );
+ PRE_MEM_READ( outmsg, (Addr) &sin->sin_port, sizeof (sin->sin_port) );
+ VG_(sprintf) ( outmsg, description, "sin_addr" );
+ PRE_MEM_READ( outmsg, (Addr) &sin->sin_addr, sizeof (sin->sin_addr) );
break;
case VKI_AF_INET6:
- VG_(sprintf) ( outmsg, description, ".sin6_port" );
+ VG_(sprintf) ( outmsg, description, "sin6_port" );
PRE_MEM_READ( outmsg,
- (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_port,
- sizeof (((struct vki_sockaddr_in6 *) sa)->sin6_port));
- VG_(sprintf) ( outmsg, description, ".sin6_flowinfo" );
+ (Addr) &sin6->sin6_port, sizeof (sin6->sin6_port) );
+ VG_(sprintf) ( outmsg, description, "sin6_flowinfo" );
PRE_MEM_READ( outmsg,
- (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_flowinfo,
- sizeof (__vki_u32));
- VG_(sprintf) ( outmsg, description, ".sin6_addr" );
+ (Addr) &sin6->sin6_flowinfo, sizeof (sin6->sin6_flowinfo) );
+ VG_(sprintf) ( outmsg, description, "sin6_addr" );
PRE_MEM_READ( outmsg,
- (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_addr,
- sizeof (struct vki_in6_addr));
- VG_(sprintf) ( outmsg, description, ".sin6_scope_id" );
+ (Addr) &sin6->sin6_addr, sizeof (sin6->sin6_addr) );
+ VG_(sprintf) ( outmsg, description, "sin6_scope_id" );
PRE_MEM_READ( outmsg,
- (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_scope_id,
- sizeof (__vki_u32));
+ (Addr) &sin6->sin6_scope_id, sizeof (sin6->sin6_scope_id) );
break;
default:
|
|
From: <sv...@va...> - 2009-05-23 01:18:28
|
Author: njn
Date: 2009-05-23 02:18:16 +0100 (Sat, 23 May 2009)
New Revision: 10118
Log:
Spacing wibbles.
Modified:
branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c
Modified: branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c 2009-05-22 22:11:04 UTC (rev 10117)
+++ branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c 2009-05-23 01:18:16 UTC (rev 10118)
@@ -919,9 +919,9 @@
struct vki_sockaddr *sa, UInt salen )
{
Char *outmsg;
- struct vki_sockaddr_un *sun = (struct vki_sockaddr_un *)sa;
- struct vki_sockaddr_in *sin = (struct vki_sockaddr_in *)sa;
- struct vki_sockaddr_in6 *sin6 = (struct vki_sockaddr_in6 *)sa;
+ struct vki_sockaddr_un* sun = (struct vki_sockaddr_un *)sa;
+ struct vki_sockaddr_in* sin = (struct vki_sockaddr_in *)sa;
+ struct vki_sockaddr_in6* sin6 = (struct vki_sockaddr_in6 *)sa;
/* NULL/zero-length sockaddrs are legal */
if ( sa == NULL || salen == 0 ) return;
|
|
From: <sv...@va...> - 2009-05-22 22:11:15
|
Author: sewardj
Date: 2009-05-22 23:11:04 +0100 (Fri, 22 May 2009)
New Revision: 10117
Log:
Handle instrumentation of IRCAS (singleword only); just treat it as a
read. Which I think amounts to exactly the same as what happened
before IRCAS was introduced.
Modified:
branches/DCAS/helgrind/hg_main.c
Modified: branches/DCAS/helgrind/hg_main.c
===================================================================
--- branches/DCAS/helgrind/hg_main.c 2009-05-22 22:02:28 UTC (rev 10116)
+++ branches/DCAS/helgrind/hg_main.c 2009-05-22 22:11:04 UTC (rev 10117)
@@ -3642,10 +3642,11 @@
VexGuestExtents* vge,
IRType gWordTy, IRType hWordTy )
{
- Int i;
- IRSB* bbOut;
- Bool x86busLocked = False;
- Bool isSnoopedStore = False;
+ Int i;
+ IRSB* bbOut;
+ Bool isSnoopedStore = False;
+ Addr64 cia; /* address of current insn */
+ IRStmt* st;
if (gWordTy != hWordTy) {
/* We don't currently support this case. */
@@ -3665,8 +3666,16 @@
i++;
}
+ // Get the first statement, and initial cia from it
+ tl_assert(bbIn->stmts_used > 0);
+ tl_assert(i < bbIn->stmts_used);
+ st = bbIn->stmts[i];
+ tl_assert(Ist_IMark == st->tag);
+ cia = st->Ist.IMark.addr;
+ st = NULL;
+
for (/*use current i*/; i < bbIn->stmts_used; i++) {
- IRStmt* st = bbIn->stmts[i];
+ st = bbIn->stmts[i];
tl_assert(st);
tl_assert(isFlatIRStmt(st));
switch (st->tag) {
@@ -3674,11 +3683,15 @@
case Ist_AbiHint:
case Ist_Put:
case Ist_PutI:
- case Ist_IMark:
case Ist_Exit:
/* None of these can contain any memory references. */
break;
+ case Ist_IMark:
+ /* no mem refs, but note the insn address. */
+ cia = st->Ist.IMark.addr;
+ break;
+
case Ist_MBE:
//instrument_memory_bus_event( bbOut, st->Ist.MBE.event );
switch (st->Ist.MBE.event) {
@@ -3687,12 +3700,8 @@
/* Imbe_Bus{Lock,Unlock} arise from x86/amd64 LOCK
prefixed instructions. */
case Imbe_BusLock:
- tl_assert(x86busLocked == False);
- x86busLocked = True;
break;
case Imbe_BusUnlock:
- tl_assert(x86busLocked == True);
- x86busLocked = False;
break;
/* Imbe_SnoopedStore{Begin,End} arise from ppc
stwcx. instructions. */
@@ -3709,8 +3718,26 @@
}
break;
+ case Ist_CAS: {
+ /* Atomic read-modify-write cycle. Just pretend it's a
+ read. */
+ IRCAS* cas = st->Ist.CAS.details;
+ tl_assert(!isSnoopedStore);
+ /* FIXME: handle DCAS ! */
+ if (cas->oldHi != IRTemp_INVALID || cas->expdHi || cas->dataHi)
+ goto unhandled;
+ instrument_mem_access(
+ bbOut,
+ cas->addr,
+ sizeofIRType(typeOfIRExpr(bbIn->tyenv, cas->dataLo)),
+ False/*!isStore*/,
+ sizeofIRType(hWordTy)
+ );
+ break;
+ }
+
case Ist_Store:
- if (!x86busLocked && !isSnoopedStore)
+ if (!isSnoopedStore)
instrument_mem_access(
bbOut,
st->Ist.Store.addr,
@@ -3751,7 +3778,7 @@
}
/* This isn't really correct. Really the
instrumentation should be only added when
- (!x86busLocked && !isSnoopedStore), just like with
+ !isSnoopedStore, just like with
Ist_Store. Still, I don't think this is
particularly important. */
if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
|
|
From: <sv...@va...> - 2009-05-22 22:02:42
|
Author: sewardj
Date: 2009-05-22 23:02:28 +0100 (Fri, 22 May 2009)
New Revision: 10116
Log:
Add some branch prediction hints so as to make the common case code
straight-line.
Also, conditionalise some fast-case assertions.
Modified:
branches/DCAS/helgrind/libhb_core.c
Modified: branches/DCAS/helgrind/libhb_core.c
===================================================================
--- branches/DCAS/helgrind/libhb_core.c 2009-05-22 21:42:55 UTC (rev 10115)
+++ branches/DCAS/helgrind/libhb_core.c 2009-05-22 22:02:28 UTC (rev 10116)
@@ -2393,7 +2393,7 @@
return ord;
}
static inline POrd VtsID__getOrdering ( VtsID vi1, VtsID vi2 ) {
- return vi1 == vi2 ? POrd_EQ : VtsID__getOrdering_WRK(vi1, vi2);
+ return LIKELY(vi1 == vi2) ? POrd_EQ : VtsID__getOrdering_WRK(vi1, vi2);
}
/* compute binary join */
@@ -2424,7 +2424,7 @@
return res;
}
static inline VtsID VtsID__join2 ( VtsID vi1, VtsID vi2 ) {
- return vi1 == vi2 ? vi1 : VtsID__join2_WRK(vi1, vi2);
+ return LIKELY(vi1 == vi2) ? vi1 : VtsID__join2_WRK(vi1, vi2);
}
/* create a singleton VTS, namely [thr:1] */
@@ -3653,7 +3653,7 @@
tl_assert(is_sane_SVal_C(svOld));
}
- if (SVal__isC(svOld)) {
+ if (LIKELY(SVal__isC(svOld))) {
POrd ord;
VtsID tviR = acc_thr->viR;
VtsID tviW = acc_thr->viW;
@@ -3661,7 +3661,7 @@
VtsID wmini = SVal__unC_Wmin(svOld);
ord = VtsID__getOrdering(rmini,tviR);
- if (ord == POrd_EQ || ord == POrd_LT) {
+ if (LIKELY(ord == POrd_EQ || ord == POrd_LT)) {
/* no race */
/* Note: RWLOCK subtlety: use tviW, not tviR */
svNew = SVal__mkC( rmini, VtsID__join2(wmini, tviW) );
@@ -3708,9 +3708,10 @@
if (CHECK_MSM) {
tl_assert(is_sane_SVal_C(svNew));
}
- tl_assert(svNew != SVal_INVALID);
- if (svNew != svOld && HG_(clo_show_conflicts)) {
- if (SVal__isC(svOld) && SVal__isC(svNew)) {
+ if (UNLIKELY(svNew != svOld)) {
+ tl_assert(svNew != SVal_INVALID);
+ if (HG_(clo_show_conflicts)
+ && SVal__isC(svOld) && SVal__isC(svNew)) {
event_map_bind( acc_addr, szB, False/*!isWrite*/, acc_thr );
stats__msm_read_change++;
}
@@ -3734,13 +3735,13 @@
tl_assert(is_sane_SVal_C(svOld));
}
- if (SVal__isC(svOld)) {
+ if (LIKELY(SVal__isC(svOld))) {
POrd ord;
VtsID tviW = acc_thr->viW;
VtsID wmini = SVal__unC_Wmin(svOld);
ord = VtsID__getOrdering(wmini,tviW);
- if (ord == POrd_EQ || ord == POrd_LT) {
+ if (LIKELY(ord == POrd_EQ || ord == POrd_LT)) {
/* no race */
svNew = SVal__mkC( tviW, tviW );
goto out;
@@ -3807,9 +3808,10 @@
if (CHECK_MSM) {
tl_assert(is_sane_SVal_C(svNew));
}
- tl_assert(svNew != SVal_INVALID);
- if (svNew != svOld && HG_(clo_show_conflicts)) {
- if (SVal__isC(svOld) && SVal__isC(svNew)) {
+ if (UNLIKELY(svNew != svOld)) {
+ tl_assert(svNew != SVal_INVALID);
+ if (HG_(clo_show_conflicts)
+ && SVal__isC(svOld) && SVal__isC(svNew)) {
event_map_bind( acc_addr, szB, True/*isWrite*/, acc_thr );
stats__msm_write_change++;
}
@@ -3845,7 +3847,8 @@
}
svOld = cl->svals[cloff];
svNew = msm_read( svOld, thr,a,1 );
- tl_assert(svNew != SVal_INVALID);
+ if (CHECK_ZSM)
+ tl_assert(svNew != SVal_INVALID);
cl->svals[cloff] = svNew;
}
@@ -3868,7 +3871,8 @@
}
svOld = cl->svals[cloff];
svNew = msm_write( svOld, thr,a,1 );
- tl_assert(svNew != SVal_INVALID);
+ if (CHECK_ZSM)
+ tl_assert(svNew != SVal_INVALID);
cl->svals[cloff] = svNew;
}
@@ -3898,7 +3902,8 @@
}
svOld = cl->svals[cloff];
svNew = msm_read( svOld, thr,a,2 );
- tl_assert(svNew != SVal_INVALID);
+ if (CHECK_ZSM)
+ tl_assert(svNew != SVal_INVALID);
cl->svals[cloff] = svNew;
return;
slowcase: /* misaligned, or must go further down the tree */
@@ -3931,7 +3936,8 @@
}
svOld = cl->svals[cloff];
svNew = msm_write( svOld, thr,a,2 );
- tl_assert(svNew != SVal_INVALID);
+ if (CHECK_ZSM)
+ tl_assert(svNew != SVal_INVALID);
cl->svals[cloff] = svNew;
return;
slowcase: /* misaligned, or must go further down the tree */
@@ -3965,7 +3971,8 @@
}
svOld = cl->svals[cloff];
svNew = msm_read( svOld, thr,a,4 );
- tl_assert(svNew != SVal_INVALID);
+ if (CHECK_ZSM)
+ tl_assert(svNew != SVal_INVALID);
cl->svals[cloff] = svNew;
return;
slowcase: /* misaligned, or must go further down the tree */
@@ -3997,7 +4004,8 @@
}
svOld = cl->svals[cloff];
svNew = msm_write( svOld, thr,a,4 );
- tl_assert(svNew != SVal_INVALID);
+ if (CHECK_ZSM)
+ tl_assert(svNew != SVal_INVALID);
cl->svals[cloff] = svNew;
return;
slowcase: /* misaligned, or must go further down the tree */
@@ -4026,7 +4034,8 @@
}
svOld = cl->svals[cloff];
svNew = msm_read( svOld, thr,a,8 );
- tl_assert(svNew != SVal_INVALID);
+ if (CHECK_ZSM)
+ tl_assert(svNew != SVal_INVALID);
cl->svals[cloff] = svNew;
return;
slowcase: /* misaligned, or must go further down the tree */
@@ -4053,7 +4062,8 @@
}
svOld = cl->svals[cloff];
svNew = msm_write( svOld, thr,a,8 );
- tl_assert(svNew != SVal_INVALID);
+ if (CHECK_ZSM)
+ tl_assert(svNew != SVal_INVALID);
cl->svals[cloff] = svNew;
return;
slowcase: /* misaligned, or must go further down the tree */
|
|
From: <sv...@va...> - 2009-05-22 21:43:07
|
Author: sewardj
Date: 2009-05-22 22:42:55 +0100 (Fri, 22 May 2009)
New Revision: 10115
Log:
Minor update following recent-ish renaming of tool executables.
Modified:
branches/DCAS/docs/internals/howto_oprofile.txt
Modified: branches/DCAS/docs/internals/howto_oprofile.txt
===================================================================
--- branches/DCAS/docs/internals/howto_oprofile.txt 2009-05-22 18:59:02 UTC (rev 10114)
+++ branches/DCAS/docs/internals/howto_oprofile.txt 2009-05-22 21:42:55 UTC (rev 10115)
@@ -12,14 +12,18 @@
# produce a flat profile
opreport --merge=tgid --symbols -x \
- /home/sewardj/VgTRUNK/hgdev/Inst/lib/valgrind/x86-linux/helgrind \
+ /home/sewardj/VgTRUNK/atomk/Inst/lib/valgrind/helgrind-amd64-linux \
| less
# produce a profile w/ callgraph
opreport --merge=tgid --callgraph \
- /home/sewardj/VgTRUNK/hgdev/Inst/lib/valgrind/x86-linux/helgrind \
+ /home/sewardj/VgTRUNK/atomk/Inst/lib/valgrind/helgrind-amd64-linux \
| less
+# print annotated source
+opannotate --merge=tgid --source --include-file=libhb_core.c | less
+
+
#### notes.
1. on amd64, need to build V with -fno-omit-frame-pointer, else the
|
|
From: Bart V. A. <bar...@gm...> - 2009-05-22 19:08:03
|
Note: the MTA on the cellbuzz cluster isn't working properly since considerable time, so I'm sending this manually. Nightly build on georgia-tech-cellbuzz-native ( cellbuzz, ppc64, Fedora 7, native ) started at 2009-05-22 02:08:04 EDT Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... done Regression test results follow == 410 tests, 36 stderr failures, 12 stdout failures, 0 post failures == exp-ptrcheck/tests/bad_percentify (stdout) exp-ptrcheck/tests/bad_percentify (stderr) exp-ptrcheck/tests/base (stderr) exp-ptrcheck/tests/ccc (stderr) exp-ptrcheck/tests/fp (stderr) exp-ptrcheck/tests/globalerr (stderr) exp-ptrcheck/tests/hackedbz2 (stdout) exp-ptrcheck/tests/hackedbz2 (stderr) exp-ptrcheck/tests/hp_bounds (stderr) exp-ptrcheck/tests/hp_dangle (stderr) exp-ptrcheck/tests/justify (stderr) exp-ptrcheck/tests/partial_bad (stderr) exp-ptrcheck/tests/partial_good (stderr) exp-ptrcheck/tests/preen_invars (stdout) exp-ptrcheck/tests/preen_invars (stderr) exp-ptrcheck/tests/pth_create (stderr) exp-ptrcheck/tests/pth_specific (stderr) exp-ptrcheck/tests/realloc (stderr) exp-ptrcheck/tests/stackerr (stderr) exp-ptrcheck/tests/strcpy (stderr) exp-ptrcheck/tests/supp (stderr) exp-ptrcheck/tests/tricky (stderr) exp-ptrcheck/tests/unaligned (stderr) exp-ptrcheck/tests/zero (stderr) helgrind/tests/hg05_race2 (stderr) memcheck/tests/deep_templates (stdout) memcheck/tests/leak-cases-full (stderr) memcheck/tests/leak-cases-summary (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/varinfo1 (stderr) memcheck/tests/varinfo2 (stderr) memcheck/tests/varinfo3 (stderr) memcheck/tests/varinfo4 (stderr) memcheck/tests/varinfo5 (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/wrap8 (stderr) none/tests/linux/mremap (stderr) none/tests/linux/mremap2 (stdout) none/tests/ppc32/jm-fp (stdout) none/tests/ppc32/jm-vmx (stdout) none/tests/ppc32/round (stdout) none/tests/ppc32/test_gx (stdout) none/tests/ppc64/jm-fp (stdout) none/tests/ppc64/jm-vmx (stdout) none/tests/ppc64/round (stdout) none/tests/shell_valid2 (stderr) none/tests/shell_valid3 (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... done Regression test results follow == 410 tests, 36 stderr failures, 9 stdout failures, 0 post failures == exp-ptrcheck/tests/bad_percentify (stderr) exp-ptrcheck/tests/base (stderr) exp-ptrcheck/tests/ccc (stderr) exp-ptrcheck/tests/fp (stderr) exp-ptrcheck/tests/globalerr (stderr) exp-ptrcheck/tests/hackedbz2 (stderr) exp-ptrcheck/tests/hp_bounds (stderr) exp-ptrcheck/tests/hp_dangle (stderr) exp-ptrcheck/tests/justify (stderr) exp-ptrcheck/tests/partial_bad (stderr) exp-ptrcheck/tests/partial_good (stderr) exp-ptrcheck/tests/preen_invars (stderr) exp-ptrcheck/tests/pth_create (stderr) exp-ptrcheck/tests/pth_specific (stderr) exp-ptrcheck/tests/realloc (stderr) exp-ptrcheck/tests/stackerr (stderr) exp-ptrcheck/tests/strcpy (stderr) exp-ptrcheck/tests/supp (stderr) exp-ptrcheck/tests/tricky (stderr) exp-ptrcheck/tests/unaligned (stderr) exp-ptrcheck/tests/zero (stderr) helgrind/tests/hg05_race2 (stderr) memcheck/tests/deep_templates (stdout) memcheck/tests/leak-cases-full (stderr) memcheck/tests/leak-cases-summary (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/origin5-bz2 (stderr) memcheck/tests/varinfo1 (stderr) memcheck/tests/varinfo2 (stderr) memcheck/tests/varinfo3 (stderr) memcheck/tests/varinfo4 (stderr) memcheck/tests/varinfo5 (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/wrap8 (stderr) none/tests/linux/mremap (stderr) none/tests/linux/mremap2 (stdout) none/tests/ppc32/jm-fp (stdout) none/tests/ppc32/jm-vmx (stdout) none/tests/ppc32/round (stdout) none/tests/ppc32/test_gx (stdout) none/tests/ppc64/jm-fp (stdout) none/tests/ppc64/jm-vmx (stdout) none/tests/ppc64/round (stdout) none/tests/shell_valid2 (stderr) none/tests/shell_valid3 (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Fri May 22 02:55:51 2009 --- new.short Fri May 22 03:44:09 2009 *************** *** 8,10 **** ! == 410 tests, 36 stderr failures, 9 stdout failures, 0 post failures == exp-ptrcheck/tests/bad_percentify (stderr) --- 8,11 ---- ! == 410 tests, 36 stderr failures, 12 stdout failures, 0 post failures == ! exp-ptrcheck/tests/bad_percentify (stdout) exp-ptrcheck/tests/bad_percentify (stderr) *************** *** 14,15 **** --- 15,17 ---- exp-ptrcheck/tests/globalerr (stderr) + exp-ptrcheck/tests/hackedbz2 (stdout) exp-ptrcheck/tests/hackedbz2 (stderr) *************** *** 20,21 **** --- 22,24 ---- exp-ptrcheck/tests/partial_good (stderr) + exp-ptrcheck/tests/preen_invars (stdout) exp-ptrcheck/tests/preen_invars (stderr) |
|
From: <sv...@va...> - 2009-05-22 18:59:14
|
Author: bart
Date: 2009-05-22 19:59:02 +0100 (Fri, 22 May 2009)
New Revision: 10114
Log:
Reduced the number of conflict set updates further.
Modified:
branches/DRDDEV/drd/drd_thread.c
Modified: branches/DRDDEV/drd/drd_thread.c
===================================================================
--- branches/DRDDEV/drd/drd_thread.c 2009-05-22 18:39:35 UTC (rev 10113)
+++ branches/DRDDEV/drd/drd_thread.c 2009-05-22 18:59:02 UTC (rev 10114)
@@ -884,7 +884,7 @@
* Every change in the vector clock of a thread may cause segments that
* were previously ordered to this thread to become unordered. Hence,
* it may be necessary to recalculate the conflict set if the vector clock
- * of the current thread is updated. This function check whether such a
+ * of the current thread is updated. This function checks whether such a
* recalculation is necessary.
*
* @param tid Thread ID of the thread to which a new segment has been
@@ -892,12 +892,13 @@
* @param new_sg Pointer to the most recent segment of thread tid.
*/
static Bool conflict_set_update_needed(const DrdThreadId tid,
- const Segment* const new_sg)
+ const VectorClock* const old_vc,
+ const VectorClock* const new_vc)
{
unsigned j;
- const Segment* old_sg;
- tl_assert(new_sg);
+ tl_assert(old_vc);
+ tl_assert(new_vc);
/*
* If a new segment has been added to another thread than the running
@@ -908,14 +909,6 @@
tl_assert(tid == DRD_(g_drd_running_tid));
- /*
- * Always let the caller update the conflict set after creation of the
- * first segment.
- */
- old_sg = new_sg->prev;
- if (old_sg == 0)
- return True;
-
for (j = 0; j < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
j++)
{
@@ -927,11 +920,11 @@
for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
{
const int included_in_old_conflict_set
- = ! DRD_(vc_lte)(&q->vc, &old_sg->vc)
- && ! DRD_(vc_lte)(&old_sg->vc, &q->vc);
+ = ! DRD_(vc_lte)(&q->vc, old_vc)
+ && ! DRD_(vc_lte)(old_vc, &q->vc);
const int included_in_new_conflict_set
- = ! DRD_(vc_lte)(&q->vc, &new_sg->vc)
- && ! DRD_(vc_lte)(&new_sg->vc, &q->vc);
+ = ! DRD_(vc_lte)(&q->vc, new_vc)
+ && ! DRD_(vc_lte)(new_vc, &q->vc);
if (included_in_old_conflict_set != included_in_new_conflict_set)
return True;
}
@@ -954,7 +947,8 @@
new_sg = DRD_(sg_new)(tid, tid);
thread_append_segment(tid, new_sg);
- if (conflict_set_update_needed(tid, new_sg))
+ if (new_sg->prev == NULL
+ || conflict_set_update_needed(tid, &new_sg->prev->vc, &new_sg->vc))
{
thread_compute_conflict_set(&DRD_(g_conflict_set),
DRD_(g_drd_running_tid));
@@ -1010,9 +1004,16 @@
if (tid != sg->tid)
{
+ VectorClock old_vc;
+ DRD_(vc_copy)(&old_vc, &DRD_(g_threadinfo)[tid].last->vc);
DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
- thread_compute_conflict_set(&DRD_(g_conflict_set), tid);
- s_conflict_set_combine_vc_count++;
+ if (conflict_set_update_needed(tid, &old_vc,
+ &DRD_(g_threadinfo)[tid].last->vc))
+ {
+ thread_compute_conflict_set(&DRD_(g_conflict_set), tid);
+ s_conflict_set_combine_vc_count++;
+ }
+ DRD_(vc_cleanup)(&old_vc);
DRD_(thread_discard_ordered_segments)();
}
else
|
|
From: <sv...@va...> - 2009-05-22 18:39:53
|
Author: bart
Date: 2009-05-22 19:39:35 +0100 (Fri, 22 May 2009)
New Revision: 10113
Log:
Updated a comment (should have been included in the previous commit).
Modified:
branches/DRDDEV/drd/drd_thread.c
Modified: branches/DRDDEV/drd/drd_thread.c
===================================================================
--- branches/DRDDEV/drd/drd_thread.c 2009-05-22 18:16:28 UTC (rev 10112)
+++ branches/DRDDEV/drd/drd_thread.c 2009-05-22 18:39:35 UTC (rev 10113)
@@ -996,8 +996,7 @@
/**
* Call this function after thread 'tid' had to wait because of thread
- * synchronization until the memory accesses in the segment with vector clock
- * 'vc' finished.
+ * synchronization until the memory accesses in the segment 'sg' finished.
*/
void DRD_(thread_combine_vc2)(DrdThreadId tid, const Segment* sg)
{
|
|
From: <sv...@va...> - 2009-05-22 18:16:45
|
Author: bart
Date: 2009-05-22 19:16:28 +0100 (Fri, 22 May 2009)
New Revision: 10112
Log:
- New command-line parameter: --segment-merging-interval=<n>.
- Performance optimization: further reduced the number of conflict set
updates.
Modified:
branches/DRDDEV/drd/drd_barrier.c
branches/DRDDEV/drd/drd_main.c
branches/DRDDEV/drd/drd_mutex.c
branches/DRDDEV/drd/drd_rwlock.c
branches/DRDDEV/drd/drd_semaphore.c
branches/DRDDEV/drd/drd_thread.c
branches/DRDDEV/drd/drd_thread.h
Modified: branches/DRDDEV/drd/drd_barrier.c
===================================================================
--- branches/DRDDEV/drd/drd_barrier.c 2009-05-22 18:12:46 UTC (rev 10111)
+++ branches/DRDDEV/drd/drd_barrier.c 2009-05-22 18:16:28 UTC (rev 10112)
@@ -466,7 +466,7 @@
if (r != q)
{
tl_assert(r->sg[p->post_iteration]);
- DRD_(thread_combine_vc2)(tid, &r->sg[p->post_iteration]->vc);
+ DRD_(thread_combine_vc2)(tid, r->sg[p->post_iteration]);
}
}
Modified: branches/DRDDEV/drd/drd_main.c
===================================================================
--- branches/DRDDEV/drd/drd_main.c 2009-05-22 18:12:46 UTC (rev 10111)
+++ branches/DRDDEV/drd/drd_main.c 2009-05-22 18:16:28 UTC (rev 10112)
@@ -70,6 +70,7 @@
int first_race_only = -1;
int report_signal_unlocked = -1;
int segment_merging = -1;
+ int segment_merge_interval = -1;
int shared_threshold_ms = -1;
int show_confl_seg = -1;
int trace_barrier = -1;
@@ -88,8 +89,11 @@
if VG_BOOL_CLO(arg, "--check-stack-var", check_stack_accesses) {}
else if VG_BOOL_CLO(arg, "--drd-stats", DRD_(s_print_stats)) {}
else if VG_BOOL_CLO(arg, "--first-race-only", first_race_only) {}
- else if VG_BOOL_CLO(arg,"--report-signal-unlocked",report_signal_unlocked) {}
+ else if VG_BOOL_CLO(arg,"--report-signal-unlocked",report_signal_unlocked)
+ {}
else if VG_BOOL_CLO(arg, "--segment-merging", segment_merging) {}
+ else if VG_INT_CLO (arg, "--segment-merging-interval", segment_merge_interval)
+ {}
else if VG_BOOL_CLO(arg, "--show-confl-seg", show_confl_seg) {}
else if VG_BOOL_CLO(arg, "--show-stack-usage",
DRD_(s_show_stack_usage)) {}
@@ -132,6 +136,8 @@
}
if (segment_merging != -1)
DRD_(thread_set_segment_merging)(segment_merging);
+ if (segment_merge_interval != 1)
+ DRD_(thread_set_segment_merge_interval)(segment_merge_interval);
if (show_confl_seg != -1)
DRD_(set_show_conflicting_segments)(show_confl_seg);
if (trace_address)
@@ -183,6 +189,8 @@
" data race detection algorithm. Disabling segment merging may\n"
" improve the accuracy of the so-called 'other segments' displayed\n"
" in race reports but can also trigger an out of memory error.\n"
+" --segment-merging-interval=<n> Perform segment merging every time n new\n"
+" segments have been created. Default: 32.\n"
" --shared-threshold=<n> Print an error message if a reader lock\n"
" is held longer than the specified time (in milliseconds).\n"
" --show-confl-seg=yes|no Show conflicting segments in race reports [yes].\n"
@@ -582,20 +590,19 @@
DRD_(sg_get_max_segments_alive_count)(),
DRD_(thread_get_discard_ordered_segments_count)());
VG_(message)(Vg_UserMsg,
- " %lld merges.",
+ " %lld merges",
DRD_(sg_get_segment_merge_count)());
VG_(message)(Vg_UserMsg,
- " (%lld m, %lld rw, %lld s, %lld b)",
+ " (%lld mutex, %lld rwlock, %lld semaphore,"
+ " %lld barrier).",
DRD_(get_mutex_segment_creation_count)(),
DRD_(get_rwlock_segment_creation_count)(),
DRD_(get_semaphore_segment_creation_count)(),
DRD_(get_barrier_segment_creation_count)());
VG_(message)(Vg_UserMsg,
- " bitmaps: %lld level 1 / %lld level 2 bitmap refs",
+ " bitmaps: %lld level 1"
+ " and %lld level 2 bitmaps were allocated.",
DRD_(bm_get_bitmap_creation_count)(),
- DRD_(bm_get_bitmap2_node_creation_count)());
- VG_(message)(Vg_UserMsg,
- " and %lld level 2 bitmaps were allocated.",
DRD_(bm_get_bitmap2_creation_count)());
VG_(message)(Vg_UserMsg,
" mutex: %lld non-recursive lock/unlock events.",
Modified: branches/DRDDEV/drd/drd_mutex.c
===================================================================
--- branches/DRDDEV/drd/drd_mutex.c 2009-05-22 18:12:46 UTC (rev 10111)
+++ branches/DRDDEV/drd/drd_mutex.c 2009-05-22 18:16:28 UTC (rev 10112)
@@ -308,7 +308,7 @@
if (last_owner != drd_tid && last_owner != DRD_INVALID_THREADID)
{
tl_assert(p->last_locked_segment);
- DRD_(thread_combine_vc2)(drd_tid, &p->last_locked_segment->vc);
+ DRD_(thread_combine_vc2)(drd_tid, p->last_locked_segment);
}
DRD_(thread_new_segment)(drd_tid);
s_mutex_segment_creation_count++;
Modified: branches/DRDDEV/drd/drd_rwlock.c
===================================================================
--- branches/DRDDEV/drd/drd_rwlock.c 2009-05-22 18:12:46 UTC (rev 10111)
+++ branches/DRDDEV/drd/drd_rwlock.c 2009-05-22 18:16:28 UTC (rev 10112)
@@ -174,7 +174,7 @@
{
if (q->tid != tid && (readers_too || q->last_lock_was_writer_lock))
{
- DRD_(thread_combine_vc2)(tid, &q->last_unlock_segment->vc);
+ DRD_(thread_combine_vc2)(tid, q->last_unlock_segment);
}
}
}
Modified: branches/DRDDEV/drd/drd_semaphore.c
===================================================================
--- branches/DRDDEV/drd/drd_semaphore.c 2009-05-22 18:12:46 UTC (rev 10111)
+++ branches/DRDDEV/drd/drd_semaphore.c 2009-05-22 18:16:28 UTC (rev 10112)
@@ -302,7 +302,7 @@
if (p->last_sem_post_tid != tid
&& p->last_sem_post_tid != DRD_INVALID_THREADID)
{
- DRD_(thread_combine_vc2)(tid, &sg->vc);
+ DRD_(thread_combine_vc2)(tid, sg);
}
DRD_(sg_put)(sg);
DRD_(thread_new_segment)(tid);
Modified: branches/DRDDEV/drd/drd_thread.c
===================================================================
--- branches/DRDDEV/drd/drd_thread.c 2009-05-22 18:12:46 UTC (rev 10111)
+++ branches/DRDDEV/drd/drd_thread.c 2009-05-22 18:16:28 UTC (rev 10112)
@@ -72,6 +72,8 @@
static Bool s_trace_conflict_set = False;
static Bool s_trace_fork_join = False;
static Bool s_segment_merging = True;
+static Bool s_new_segments_since_last_merge;
+static int s_segment_merge_interval = 32;
/* Function definitions. */
@@ -110,6 +112,12 @@
s_segment_merging = m;
}
+/** Set the segment merging interval. */
+void DRD_(thread_set_segment_merge_interval)(const int i)
+{
+ s_segment_merge_interval = i;
+}
+
/**
* Convert Valgrind's ThreadId into a DrdThreadId.
*
@@ -841,6 +849,8 @@
{
unsigned i;
+ s_new_segments_since_last_merge = 0;
+
for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
i++)
{
@@ -957,7 +967,8 @@
DRD_(thread_discard_ordered_segments)();
- if (s_segment_merging)
+ if (s_segment_merging
+ && ++s_new_segments_since_last_merge >= s_segment_merge_interval)
{
thread_merge_segments();
}
@@ -988,16 +999,27 @@
* synchronization until the memory accesses in the segment with vector clock
* 'vc' finished.
*/
-void DRD_(thread_combine_vc2)(DrdThreadId tid, const VectorClock* const vc)
+void DRD_(thread_combine_vc2)(DrdThreadId tid, const Segment* sg)
{
+ const VectorClock* const vc = &sg->vc;
+
tl_assert(0 <= (int)tid && tid < DRD_N_THREADS
&& tid != DRD_INVALID_THREADID);
tl_assert(DRD_(g_threadinfo)[tid].last);
+ tl_assert(sg);
tl_assert(vc);
- DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
- thread_compute_conflict_set(&DRD_(g_conflict_set), tid);
- DRD_(thread_discard_ordered_segments)();
- s_conflict_set_combine_vc_count++;
+
+ if (tid != sg->tid)
+ {
+ DRD_(vc_combine)(&DRD_(g_threadinfo)[tid].last->vc, vc);
+ thread_compute_conflict_set(&DRD_(g_conflict_set), tid);
+ s_conflict_set_combine_vc_count++;
+ DRD_(thread_discard_ordered_segments)();
+ }
+ else
+ {
+ tl_assert(DRD_(vc_lte)(vc, &DRD_(g_threadinfo)[tid].last->vc));
+ }
}
/**
Modified: branches/DRDDEV/drd/drd_thread.h
===================================================================
--- branches/DRDDEV/drd/drd_thread.h 2009-05-22 18:12:46 UTC (rev 10111)
+++ branches/DRDDEV/drd/drd_thread.h 2009-05-22 18:16:28 UTC (rev 10112)
@@ -116,6 +116,7 @@
Bool DRD_(thread_get_trace_fork_join)(void);
void DRD_(thread_set_trace_fork_join)(const Bool t);
void DRD_(thread_set_segment_merging)(const Bool m);
+void DRD_(thread_set_segment_merge_interval)(const int i);
DrdThreadId DRD_(VgThreadIdToDrdThreadId)(const ThreadId tid);
DrdThreadId DRD_(NewVgThreadIdToDrdThreadId)(const ThreadId tid);
@@ -148,8 +149,7 @@
void DRD_(thread_get_latest_segment)(Segment** sg, const DrdThreadId tid);
void DRD_(thread_combine_vc)(const DrdThreadId joiner,
const DrdThreadId joinee);
-void DRD_(thread_combine_vc2)(const DrdThreadId tid,
- const VectorClock* const vc);
+void DRD_(thread_combine_vc2)(const DrdThreadId tid, const Segment* sg);
void DRD_(thread_stop_using_mem)(const Addr a1, const Addr a2);
void DRD_(thread_start_recording)(const DrdThreadId tid);
|
|
From: <sv...@va...> - 2009-05-22 18:12:58
|
Author: bart
Date: 2009-05-22 19:12:46 +0100 (Fri, 22 May 2009)
New Revision: 10111
Log:
Thread ID is now stored in each segment.
Modified:
branches/DRDDEV/drd/drd_segment.c
branches/DRDDEV/drd/drd_segment.h
Modified: branches/DRDDEV/drd/drd_segment.c
===================================================================
--- branches/DRDDEV/drd/drd_segment.c 2009-05-22 18:12:00 UTC (rev 10110)
+++ branches/DRDDEV/drd/drd_segment.c 2009-05-22 18:12:46 UTC (rev 10111)
@@ -72,6 +72,7 @@
sg->next = 0;
sg->prev = 0;
+ sg->tid = created;
sg->refcnt = 1;
if (vg_created != VG_INVALID_THREADID && VG_(get_SP)(vg_created) != 0)
Modified: branches/DRDDEV/drd/drd_segment.h
===================================================================
--- branches/DRDDEV/drd/drd_segment.h 2009-05-22 18:12:00 UTC (rev 10110)
+++ branches/DRDDEV/drd/drd_segment.h 2009-05-22 18:12:46 UTC (rev 10111)
@@ -45,6 +45,7 @@
/** Pointers to next and previous segments executed by the same thread. */
struct segment* next;
struct segment* prev;
+ DrdThreadId tid;
/** Reference count: number of pointers that point to this segment. */
int refcnt;
/** Stack trace of the first instruction of the segment. */
|
|
From: <sv...@va...> - 2009-05-22 18:12:12
|
Author: bart
Date: 2009-05-22 19:12:00 +0100 (Fri, 22 May 2009)
New Revision: 10110
Log:
Parameter tuning / removed an unused counter.
Modified:
branches/DRDDEV/drd/drd_bitmap.c
branches/DRDDEV/drd/drd_bitmap.h
branches/DRDDEV/drd/pub_drd_bitmap.h
Modified: branches/DRDDEV/drd/drd_bitmap.c
===================================================================
--- branches/DRDDEV/drd/drd_bitmap.c 2009-05-22 14:48:24 UTC (rev 10109)
+++ branches/DRDDEV/drd/drd_bitmap.c 2009-05-22 18:12:00 UTC (rev 10110)
@@ -1087,11 +1087,6 @@
return s_bitmap_creation_count;
}
-ULong DRD_(bm_get_bitmap2_node_creation_count)(void)
-{
- return s_bitmap2_node_creation_count;
-}
-
ULong DRD_(bm_get_bitmap2_creation_count)(void)
{
return s_bitmap2_creation_count;
Modified: branches/DRDDEV/drd/drd_bitmap.h
===================================================================
--- branches/DRDDEV/drd/drd_bitmap.h 2009-05-22 14:48:24 UTC (rev 10109)
+++ branches/DRDDEV/drd/drd_bitmap.h 2009-05-22 18:12:00 UTC (rev 10110)
@@ -66,7 +66,7 @@
/** Number of bits assigned to the least significant component of an address.
*/
-#define ADDR_LSB_BITS 12
+#define ADDR_LSB_BITS 14
/** Mask that has to be applied to an address of type Addr in order to
* compute the least significant part of an address split, after having
@@ -201,7 +201,6 @@
/* Local variables. */
static ULong s_bitmap2_creation_count;
-static ULong s_bitmap2_node_creation_count;
Modified: branches/DRDDEV/drd/pub_drd_bitmap.h
===================================================================
--- branches/DRDDEV/drd/pub_drd_bitmap.h 2009-05-22 14:48:24 UTC (rev 10109)
+++ branches/DRDDEV/drd/pub_drd_bitmap.h 2009-05-22 18:12:00 UTC (rev 10110)
@@ -122,7 +122,6 @@
struct bitmap* const bm2);
void DRD_(bm_print)(struct bitmap* bm);
ULong DRD_(bm_get_bitmap_creation_count)(void);
-ULong DRD_(bm_get_bitmap2_node_creation_count)(void);
ULong DRD_(bm_get_bitmap2_creation_count)(void);
ULong DRD_(bm_get_bitmap2_merge_count)(void);
|
|
From: <sv...@va...> - 2009-05-22 14:48:31
|
Author: sewardj
Date: 2009-05-22 15:48:24 +0100 (Fri, 22 May 2009)
New Revision: 10109
Log:
Handle IRStmt_IRCAS in Memcheck. This is complex because it requires
actually making up a bit of "did this IRCAS succeed?"
original-expression IR, and using that to steer the shadow values.
But this module really wasn't set up to generate more
original-expression IR, and many assertions to do with the management
of shadow temporaries failed. Hence this commit is much more complex
than it otherwise would have been.
Modified:
branches/DCAS/memcheck/mc_translate.c
Modified: branches/DCAS/memcheck/mc_translate.c
===================================================================
--- branches/DCAS/memcheck/mc_translate.c 2009-05-22 13:07:03 UTC (rev 10108)
+++ branches/DCAS/memcheck/mc_translate.c 2009-05-22 14:48:24 UTC (rev 10109)
@@ -126,26 +126,57 @@
/*--- Memcheck running state, and tmp management. ---*/
/*------------------------------------------------------------*/
+/* Carries info about a particular tmp. The tmp's number is not
+ recorded, as this is implied by (equal to) its index in the tmpMap
+ in MCEnv. The tmp's type is also not recorded, as this is present
+ in MCEnv.sb->tyenv.
+
+ When .kind is Orig, .shadowV and .shadowB may give the identities
+ of the temps currently holding the associated definedness (shadowV)
+ and origin (shadowB) values, or these may be IRTemp_INVALID if code
+ to compute such values has not yet been emitted.
+
+ When .kind is VSh or BSh then the tmp is holds a V- or B- value,
+ and so .shadowV and .shadowB must be IRTemp_INVALID, since it is
+ illogical for a shadow tmp itself to be shadowed.
+*/
+typedef
+ enum { Orig=1, VSh=2, BSh=3 }
+ TempKind;
+
+typedef
+ struct {
+ TempKind kind;
+ IRTemp shadowV;
+ IRTemp shadowB;
+ }
+ TempMapEnt;
+
+
/* Carries around state during memcheck instrumentation. */
typedef
struct _MCEnv {
/* MODIFIED: the superblock being constructed. IRStmts are
added. */
- IRSB* bb;
+ IRSB* sb;
Bool trace;
- /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
- original temps to their current their current shadow temp.
- Initially all entries are IRTemp_INVALID. Entries are added
- lazily since many original temps are not used due to
- optimisation prior to instrumentation. Note that floating
- point original tmps are shadowed by integer tmps of the same
- size, and Bit-typed original tmps are shadowed by the type
- Ity_I8. See comment below. */
- IRTemp* tmpMapV; /* V-bit tmp shadows */
- IRTemp* tmpMapB; /* origin tracking tmp shadows */
- Int n_originalTmps; /* for range checking */
+ /* MODIFIED: a table [0 .. #temps_in_sb-1] which gives the
+ current kind and possibly shadow temps for each temp in the
+ IRSB being constructed. Note that it does not contain the
+ type of each tmp. If you want to know the type, look at the
+ relevant entry in sb->tyenv. It follows that at all times
+ during the instrumentation process, the valid indices for
+ tmpMap and sb->tyenv are identical, being 0 .. N-1 where N is
+ total number of Orig, V- and B- temps allocated so far.
+ The reason for this strange split (types in one place, all
+ other info in another) is that we need the types to be
+ attached to sb so as to make it possible to do
+ "typeOfIRExpr(mce->bb->tyenv, ...)" at various places in the
+ instrumentation process. */
+ XArray* /* of TempMapEnt */ tmpMap;
+
/* MODIFIED: indicates whether "bogus" literals have so far been
found. Starts off False, and may change to True. */
Bool bogusLiterals;
@@ -185,17 +216,44 @@
sanity checker should catch all such anomalies, however.
*/
+/* Create a new IRTemp of type 'ty' and kind 'kind', and add it to
+ both the table in mce->sb and to our auxiliary mapping. Note that
+ newTemp may cause mce->tmpMap to resize, hence previous results
+ from VG_(indexXA)(mce->tmpMap) are invalidated. */
+static IRTemp newTemp ( MCEnv* mce, IRType ty, TempKind kind )
+{
+ Word newIx;
+ TempMapEnt ent;
+ IRTemp tmp = newIRTemp(mce->sb->tyenv, ty);
+ ent.kind = kind;
+ ent.shadowV = IRTemp_INVALID;
+ ent.shadowB = IRTemp_INVALID;
+ newIx = VG_(addToXA)( mce->tmpMap, &ent );
+ tl_assert(newIx == (Word)tmp);
+ return tmp;
+}
+
+
/* Find the tmp currently shadowing the given original tmp. If none
so far exists, allocate one. */
static IRTemp findShadowTmpV ( MCEnv* mce, IRTemp orig )
{
- tl_assert(orig < mce->n_originalTmps);
- if (mce->tmpMapV[orig] == IRTemp_INVALID) {
- mce->tmpMapV[orig]
- = newIRTemp(mce->bb->tyenv,
- shadowTypeV(mce->bb->tyenv->types[orig]));
+ TempMapEnt* ent;
+ /* VG_(indexXA) range-checks 'orig', hence no need to check
+ here. */
+ ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
+ tl_assert(ent->kind == Orig);
+ if (ent->shadowV == IRTemp_INVALID) {
+ IRTemp tmpV
+ = newTemp( mce, shadowTypeV(mce->sb->tyenv->types[orig]), VSh );
+ /* newTemp may cause mce->tmpMap to resize, hence previous results
+ from VG_(indexXA) are invalid. */
+ ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
+ tl_assert(ent->kind == Orig);
+ tl_assert(ent->shadowV == IRTemp_INVALID);
+ ent->shadowV = tmpV;
}
- return mce->tmpMapV[orig];
+ return ent->shadowV;
}
/* Allocate a new shadow for the given original tmp. This means any
@@ -203,13 +261,27 @@
necessary to give a new value to a shadow once it has been tested
for undefinedness, but unfortunately IR's SSA property disallows
this. Instead we must abandon the old shadow, allocate a new one
- and use that instead. */
+ and use that instead.
+
+ This is the same as findShadowTmpV, except we don't bother to see
+ if a shadow temp already existed -- we simply allocate a new one
+ regardless. */
static void newShadowTmpV ( MCEnv* mce, IRTemp orig )
{
- tl_assert(orig < mce->n_originalTmps);
- mce->tmpMapV[orig]
- = newIRTemp(mce->bb->tyenv,
- shadowTypeV(mce->bb->tyenv->types[orig]));
+ TempMapEnt* ent;
+ /* VG_(indexXA) range-checks 'orig', hence no need to check
+ here. */
+ ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
+ tl_assert(ent->kind == Orig);
+ if (1) {
+ IRTemp tmpV
+ = newTemp( mce, shadowTypeV(mce->sb->tyenv->types[orig]), VSh );
+ /* newTemp may cause mce->tmpMap to resize, hence previous results
+ from VG_(indexXA) are invalid. */
+ ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
+ tl_assert(ent->kind == Orig);
+ ent->shadowV = tmpV;
+ }
}
@@ -232,8 +304,10 @@
{
if (a1->tag == Iex_Const)
return True;
- if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp < mce->n_originalTmps)
- return True;
+ if (a1->tag == Iex_RdTmp) {
+ TempMapEnt* ent = VG_(indexXA)( mce->tmpMap, a1->Iex.RdTmp.tmp );
+ return ent->kind == Orig;
+ }
return False;
}
@@ -243,8 +317,10 @@
{
if (a1->tag == Iex_Const)
return True;
- if (a1->tag == Iex_RdTmp && a1->Iex.RdTmp.tmp >= mce->n_originalTmps)
- return True;
+ if (a1->tag == Iex_RdTmp) {
+ TempMapEnt* ent = VG_(indexXA)( mce->tmpMap, a1->Iex.RdTmp.tmp );
+ return ent->kind == VSh || ent->kind == BSh;
+ }
return False;
}
@@ -312,13 +388,13 @@
ppIRStmt(st);
VG_(printf)("\n");
}
- addStmtToIRSB(mce->bb, st);
+ addStmtToIRSB(mce->sb, st);
}
/* assign value to tmp */
static inline
void assign ( HChar cat, MCEnv* mce, IRTemp tmp, IRExpr* expr ) {
- stmt(cat, mce, IRStmt_WrTmp(tmp,expr));
+ stmt(cat, mce, IRStmt_WrTmp(tmp,expr));
}
/* build various kinds of expressions */
@@ -336,14 +412,24 @@
an atom.
'ty' is the type of 'e' and hence the type that the new temporary
- needs to be. But passing it is redundant, since we can deduce the
- type merely by inspecting 'e'. So at least that fact to assert
- that the two types agree. */
-static IRAtom* assignNew ( HChar cat, MCEnv* mce, IRType ty, IRExpr* e ) {
- IRTemp t;
- IRType tyE = typeOfIRExpr(mce->bb->tyenv, e);
+ needs to be. But passing it in is redundant, since we can deduce
+ the type merely by inspecting 'e'. So at least use that fact to
+ assert that the two types agree. */
+static IRAtom* assignNew ( HChar cat, MCEnv* mce, IRType ty, IRExpr* e )
+{
+ TempKind k;
+ IRTemp t;
+ IRType tyE = typeOfIRExpr(mce->sb->tyenv, e);
tl_assert(tyE == ty); /* so 'ty' is redundant (!) */
- t = newIRTemp(mce->bb->tyenv, ty);
+ switch (cat) {
+ case 'V': k = VSh; break;
+ case 'B': k = BSh; break;
+ case 'C': k = Orig; break;
+ /* happens when we are making up new "orig"
+ expressions, for IRCAS handling */
+ default: tl_assert(0);
+ }
+ t = newTemp(mce, ty, k);
assign(cat, mce, t, e);
return mkexpr(t);
}
@@ -569,7 +655,7 @@
/* Note, dst_ty is a shadow type, not an original type. */
/* First of all, collapse vbits down to a single bit. */
tl_assert(isShadowAtom(mce,vbits));
- src_ty = typeOfIRExpr(mce->bb->tyenv, vbits);
+ src_ty = typeOfIRExpr(mce->sb->tyenv, vbits);
/* Fast-track some common cases */
if (src_ty == Ity_I32 && dst_ty == Ity_I32)
@@ -928,7 +1014,7 @@
tl_assert(isShadowAtom(mce, vatom));
tl_assert(sameKindedAtoms(atom, vatom));
- ty = typeOfIRExpr(mce->bb->tyenv, vatom);
+ ty = typeOfIRExpr(mce->sb->tyenv, vatom);
/* sz is only used for constructing the error message */
sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
@@ -1112,7 +1198,7 @@
tl_assert(isShadowAtom(mce, vatom));
}
- ty = typeOfIRExpr(mce->bb->tyenv, vatom);
+ ty = typeOfIRExpr(mce->sb->tyenv, vatom);
tl_assert(ty != Ity_I1);
if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
/* later: no ... */
@@ -1226,8 +1312,8 @@
IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
{
IRAtom* at;
- IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
- IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
+ IRType t1 = typeOfIRExpr(mce->sb->tyenv, va1);
+ IRType t2 = typeOfIRExpr(mce->sb->tyenv, va2);
tl_assert(isShadowAtom(mce,va1));
tl_assert(isShadowAtom(mce,va2));
@@ -1275,9 +1361,9 @@
IRAtom* va1, IRAtom* va2, IRAtom* va3 )
{
IRAtom* at;
- IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
- IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
- IRType t3 = typeOfIRExpr(mce->bb->tyenv, va3);
+ IRType t1 = typeOfIRExpr(mce->sb->tyenv, va1);
+ IRType t2 = typeOfIRExpr(mce->sb->tyenv, va2);
+ IRType t3 = typeOfIRExpr(mce->sb->tyenv, va3);
tl_assert(isShadowAtom(mce,va1));
tl_assert(isShadowAtom(mce,va2));
tl_assert(isShadowAtom(mce,va3));
@@ -1344,10 +1430,10 @@
IRAtom* va1, IRAtom* va2, IRAtom* va3, IRAtom* va4 )
{
IRAtom* at;
- IRType t1 = typeOfIRExpr(mce->bb->tyenv, va1);
- IRType t2 = typeOfIRExpr(mce->bb->tyenv, va2);
- IRType t3 = typeOfIRExpr(mce->bb->tyenv, va3);
- IRType t4 = typeOfIRExpr(mce->bb->tyenv, va4);
+ IRType t1 = typeOfIRExpr(mce->sb->tyenv, va1);
+ IRType t2 = typeOfIRExpr(mce->sb->tyenv, va2);
+ IRType t3 = typeOfIRExpr(mce->sb->tyenv, va3);
+ IRType t4 = typeOfIRExpr(mce->sb->tyenv, va4);
tl_assert(isShadowAtom(mce,va1));
tl_assert(isShadowAtom(mce,va2));
tl_assert(isShadowAtom(mce,va3));
@@ -1416,7 +1502,7 @@
tl_assert(isOriginalAtom(mce, exprvec[i]));
if (cee->mcx_mask & (1<<i))
continue;
- if (typeOfIRExpr(mce->bb->tyenv, exprvec[i]) != Ity_I64)
+ if (typeOfIRExpr(mce->sb->tyenv, exprvec[i]) != Ity_I64)
mergeTy64 = False;
}
@@ -2726,7 +2812,7 @@
/* We need to have a place to park the V bits we're just about to
read. */
- datavbits = newIRTemp(mce->bb->tyenv, ty);
+ datavbits = newTemp(mce, ty, VSh);
di = unsafeIRDirty_1_N( datavbits,
1/*regparms*/,
hname, VG_(fnptr_to_fnentry)( helper ),
@@ -2786,7 +2872,7 @@
vbitsC = expr2vbits(mce, cond);
vbits0 = expr2vbits(mce, expr0);
vbitsX = expr2vbits(mce, exprX);
- ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
+ ty = typeOfIRExpr(mce->sb->tyenv, vbits0);
return
mkUifU(mce, ty, assignNew('V', mce, ty,
@@ -2812,7 +2898,7 @@
return IRExpr_RdTmp( findShadowTmpV(mce, e->Iex.RdTmp.tmp) );
case Iex_Const:
- return definedOfType(shadowTypeV(typeOfIRExpr(mce->bb->tyenv, e)));
+ return definedOfType(shadowTypeV(typeOfIRExpr(mce->sb->tyenv, e)));
case Iex_Qop:
return expr2vbits_Qop(
@@ -2875,7 +2961,7 @@
/* vatom is vbits-value and as such can only have a shadow type. */
tl_assert(isShadowAtom(mce,vatom));
- ty = typeOfIRExpr(mce->bb->tyenv, vatom);
+ ty = typeOfIRExpr(mce->sb->tyenv, vatom);
tyH = mce->hWordTy;
if (tyH == Ity_I32) {
@@ -2914,13 +3000,17 @@
/* Generate a shadow store. addr is always the original address atom.
You can pass in either originals or V-bits for the data atom, but
- obviously not both. */
+ obviously not both. guard :: Ity_I1 controls whether the store
+ really happens; NULL means it unconditionally does. Note that
+ guard itself is not checked for definedness; the caller of this
+ function must do that if necessary. */
static
void do_shadow_Store ( MCEnv* mce,
IREndness end,
IRAtom* addr, UInt bias,
- IRAtom* data, IRAtom* vdata )
+ IRAtom* data, IRAtom* vdata,
+ IRAtom* guard )
{
IROp mkAdd;
IRType ty, tyAddr;
@@ -2945,14 +3035,20 @@
tl_assert(isOriginalAtom(mce,addr));
tl_assert(isShadowAtom(mce,vdata));
- ty = typeOfIRExpr(mce->bb->tyenv, vdata);
+ if (guard) {
+ tl_assert(isOriginalAtom(mce, guard));
+ tl_assert(typeOfIRExpr(mce->sb->tyenv, guard) == Ity_I1);
+ }
+ ty = typeOfIRExpr(mce->sb->tyenv, vdata);
+
// If we're not doing undefined value checking, pretend that this value
// is "all valid". That lets Vex's optimiser remove some of the V bit
// shadow computation ops that precede it.
if (MC_(clo_mc_level) == 1) {
switch (ty) {
- case Ity_V128: c = IRConst_V128(V_BITS16_DEFINED); break; // V128 weirdness
+ case Ity_V128: // V128 weirdness
+ c = IRConst_V128(V_BITS16_DEFINED); break;
case Ity_I64: c = IRConst_U64 (V_BITS64_DEFINED); break;
case Ity_I32: c = IRConst_U32 (V_BITS32_DEFINED); break;
case Ity_I16: c = IRConst_U16 (V_BITS16_DEFINED); break;
@@ -3040,6 +3136,8 @@
hname, VG_(fnptr_to_fnentry)( helper ),
mkIRExprVec_2( addrHi64, vdataHi64 )
);
+ if (guard) diLo64->guard = guard;
+ if (guard) diHi64->guard = guard;
setHelperAnns( mce, diLo64 );
setHelperAnns( mce, diHi64 );
stmt( 'V', mce, IRStmt_Dirty(diLo64) );
@@ -3076,6 +3174,7 @@
zwidenToHostWord( mce, vdata ))
);
}
+ if (guard) di->guard = guard;
setHelperAnns( mce, di );
stmt( 'V', mce, IRStmt_Dirty(di) );
}
@@ -3180,7 +3279,7 @@
tl_assert(d->mAddr);
complainIfUndefined(mce, d->mAddr);
- tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
+ tyAddr = typeOfIRExpr(mce->sb->tyenv, d->mAddr);
tl_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
tl_assert(tyAddr == mce->hWordTy); /* not really right */
}
@@ -3221,7 +3320,7 @@
/* Outputs: the destination temporary, if there is one. */
if (d->tmp != IRTemp_INVALID) {
dst = findShadowTmpV(mce, d->tmp);
- tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
+ tyDst = typeOfIRTemp(mce->sb->tyenv, d->tmp);
assign( 'V', mce, dst, mkPCastTo( mce, tyDst, curr) );
}
@@ -3261,14 +3360,16 @@
while (toDo >= 4) {
do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
NULL, /* original data */
- mkPCastTo( mce, Ity_I32, curr ) );
+ mkPCastTo( mce, Ity_I32, curr ),
+ NULL/*guard*/ );
toDo -= 4;
}
/* chew off 16-bit chunks */
while (toDo >= 2) {
do_shadow_Store( mce, end, d->mAddr, d->mSize - toDo,
NULL, /* original data */
- mkPCastTo( mce, Ity_I16, curr ) );
+ mkPCastTo( mce, Ity_I16, curr ),
+ NULL/*guard*/ );
toDo -= 2;
}
tl_assert(toDo == 0); /* also need to handle 1-byte excess */
@@ -3276,6 +3377,7 @@
}
+
/* We have an ABI hint telling us that [base .. base+len-1] is to
become undefined ("writable"). Generate code to call a helper to
notify the A/V bit machinery of this fact.
@@ -3306,6 +3408,457 @@
}
+/* ------ Dealing with IRCAS (big and complex) ------ */
+
+/* FWDS */
+static IRAtom* gen_load_b ( MCEnv* mce, Int szB,
+ IRAtom* baseaddr, Int offset );
+static IRAtom* gen_maxU32 ( MCEnv* mce, IRAtom* b1, IRAtom* b2 );
+static void gen_store_b ( MCEnv* mce, Int szB,
+ IRAtom* baseaddr, Int offset, IRAtom* dataB,
+ IRAtom* guard );
+
+static void do_shadow_CAS_single ( MCEnv* mce, IRCAS* cas );
+static void do_shadow_CAS_double ( MCEnv* mce, IRCAS* cas );
+
+
+/* Either ORIG and SHADOW are both IRExpr.RdTmps, or they are both
+ IRExpr.Consts, else this asserts. If they are both Consts, it
+ doesn't do anything. So that just leaves the RdTmp case.
+
+ In which case: this assigns the shadow value SHADOW to the IR
+ shadow temporary associated with ORIG. That is, ORIG, being an
+ original temporary, will have a shadow temporary associated with
+ it. However, in the case envisaged here, there will so far have
+ been no IR emitted to actually write a shadow value into that
+ temporary. What this routine does is to (emit IR to) copy the
+ value in SHADOW into said temporary, so that after this call,
+ IRExpr.RdTmps of ORIG's shadow temp will correctly pick up the
+ value in SHADOW.
+
+ Point is to allow callers to compute "by hand" a shadow value for
+ ORIG, and force it to be associated with ORIG.
+
+ How do we know that that shadow associated with ORIG has not so far
+ been assigned to? Well, we don't per se know that, but supposing
+ it had. Then this routine would create a second assignment to it,
+ and later the IR sanity checker would barf. But that never
+ happens. QED.
+*/
+static void bind_shadow_tmp_to_orig ( UChar how,
+ MCEnv* mce,
+ IRAtom* orig, IRAtom* shadow )
+{
+ tl_assert(isOriginalAtom(mce, orig));
+ tl_assert(isShadowAtom(mce, shadow));
+ switch (orig->tag) {
+ case Iex_Const:
+ tl_assert(shadow->tag == Iex_Const);
+ break;
+ case Iex_RdTmp:
+ tl_assert(shadow->tag == Iex_RdTmp);
+ if (how == 'V') {
+ assign('V', mce, findShadowTmpV(mce,orig->Iex.RdTmp.tmp),
+ shadow);
+ } else {
+ tl_assert(how == 'B');
+ assign('B', mce, findShadowTmpB(mce,orig->Iex.RdTmp.tmp),
+ shadow);
+ }
+ break;
+ default:
+ tl_assert(0);
+ }
+}
+
+
+static
+void do_shadow_CAS ( MCEnv* mce, IRCAS* cas )
+{
+ /* Scheme is (both single- and double- cases):
+
+ 1. fetch data#,dataB (the proposed new value)
+
+ 2. fetch expd#,expdB (what we expect to see at the address)
+
+ 3. check definedness of address
+
+ 4. load old#,oldB from shadow memory; this also checks
+ addressibility of the address
+
+ 5. the CAS itself
+
+ 6. complain if "expected == old" is undefined
+
+ 7. if "expected == old"
+ store data#,dataB to shadow memory
+
+ Note that 5 reads 'old' but 4 reads 'old#'. Similarly, 5 stores
+ 'data' but 7 stores 'data#'. Hence it is possible for the
+ shadow data to be incorrectly checked and/or updated:
+
+ * 6 could falsely complain if 4 read old# as undefined, but some
+ other thread wrote a defined value to the location after 4 but
+ before 5.
+
+ * 6 could falsely not-complain if 4 read old# as defined, but
+ some other thread wrote an undefined value to the location
+ after 4 but before 5.
+
+ * 7 is at least gated correctly, since the 'expected == old'
+ condition is derived from outputs of 5. However, the shadow
+ write could happen too late: imagine after 5 we are
+ descheduled, a different thread runs, writes a different
+ (shadow) value at the address, and then we resume, hence
+ overwriting the shadow value written by the other thread.
+
+ Because the original memory access is atomic, there's no way to
+ make both the original and shadow accesses into a single atomic
+ thing, hence this is unavoidable.
+
+ At least as Valgrind stands, I don't think it's a problem, since
+ we're single threaded *and* we guarantee that there are no
+ context switches during the execution of any specific superblock
+ -- context switches can only happen at superblock boundaries.
+
+ If Valgrind ever becomes MT in the future, then it might be more
+ of a problem. A possible kludge would be to artificially
+ associate with the location, a lock, which we must acquire and
+ release around the transaction as a whole. Hmm, that probably
+ would't work properly since it only guards us against other
+ threads doing CASs on the same location, not against other
+ threads doing normal reads and writes.
+ */
+ if (cas->oldHi == IRTemp_INVALID) {
+ do_shadow_CAS_single( mce, cas );
+ } else {
+ do_shadow_CAS_double( mce, cas );
+ }
+}
+
+
+static void do_shadow_CAS_single ( MCEnv* mce, IRCAS* cas )
+{
+ IRAtom *vdataLo = NULL, *bdataLo = NULL;
+ IRAtom *vexpdLo = NULL, *bexpdLo = NULL;
+ IRAtom *voldLo = NULL, *boldLo = NULL;
+ IRAtom *expd_eq_old_V = NULL, *expd_eq_old_B = NULL;
+ IRAtom *expd_eq_old = NULL;
+ IROp opCmpEQ;
+ Int elemSzB;
+ IRType elemTy;
+ Bool otrak = MC_(clo_mc_level) >= 3; /* a shorthand */
+
+ /* single CAS */
+ tl_assert(cas->oldHi == IRTemp_INVALID);
+ tl_assert(cas->expdHi == NULL);
+ tl_assert(cas->dataHi == NULL);
+
+ elemTy = typeOfIRExpr(mce->sb->tyenv, cas->expdLo);
+ switch (elemTy) {
+ case Ity_I8: elemSzB = 1; opCmpEQ = Iop_CmpEQ8; break;
+ case Ity_I16: elemSzB = 2; opCmpEQ = Iop_CmpEQ16; break;
+ case Ity_I32: elemSzB = 4; opCmpEQ = Iop_CmpEQ32; break;
+ case Ity_I64: elemSzB = 8; opCmpEQ = Iop_CmpEQ64; break;
+ default: tl_assert(0); /* IR defn disallows any other types */
+ }
+
+ /* 1. fetch data# (the proposed new value) */
+ tl_assert(isOriginalAtom(mce, cas->dataLo));
+ vdataLo
+ = assignNew('V', mce, elemTy, expr2vbits(mce, cas->dataLo));
+ tl_assert(isShadowAtom(mce, vdataLo));
+ if (otrak) {
+ bdataLo
+ = assignNew('B', mce, Ity_I32, schemeE(mce, cas->dataLo));
+ tl_assert(isShadowAtom(mce, bdataLo));
+ }
+
+ /* 2. fetch expected# (what we expect to see at the address) */
+ tl_assert(isOriginalAtom(mce, cas->expdLo));
+ vexpdLo
+ = assignNew('V', mce, elemTy, expr2vbits(mce, cas->expdLo));
+ tl_assert(isShadowAtom(mce, vexpdLo));
+ if (otrak) {
+ bexpdLo
+ = assignNew('B', mce, Ity_I32, schemeE(mce, cas->expdLo));
+ tl_assert(isShadowAtom(mce, bexpdLo));
+ }
+
+ /* 3. check definedness of address */
+ /* 4. fetch old# from shadow memory; this also checks
+ addressibility of the address */
+ voldLo
+ = assignNew(
+ 'V', mce, elemTy,
+ expr2vbits_Load(
+ mce,
+ cas->end, elemTy, cas->addr, 0/*Addr bias*/
+ ));
+ if (otrak) {
+ boldLo
+ = assignNew('B', mce, Ity_I32,
+ gen_load_b(mce, elemSzB, cas->addr, 0/*addr bias*/));
+ }
+
+ /* 5. the CAS itself */
+ stmt( 'C', mce, IRStmt_CAS(cas) );
+
+ /* 6. complain if "expected == old" is undefined */
+ /* Doing this directly interacts in a complex way with origin
+ tracking. Much easier to make up an expression tree and hand
+ that off to expr2vbits_Binop. We will need the expression
+ tree in any case in order to decide whether or not to do a
+ shadow store. */
+ /* Note that 'C' is kinda faking it; it is indeed a non-shadow
+ tree, but it's not copied from the input block. */
+ expd_eq_old
+ = assignNew('C', mce, Ity_I1,
+ binop(opCmpEQ, cas->expdLo, mkexpr(cas->oldLo)));
+
+ /* Compute into expd_eq_old_V the definedness for expd_eq_old.
+ First we need to ensure that cas->oldLo's V-shadow is bound
+ voldLo, since expr2vbits_Binop will generate a use of it. */
+ bind_shadow_tmp_to_orig('V', mce, mkexpr(cas->oldLo), voldLo);
+ expd_eq_old_V
+ = expr2vbits_Binop( mce, opCmpEQ, cas->expdLo, mkexpr(cas->oldLo) );
+ if (otrak) {
+ bind_shadow_tmp_to_orig('B', mce, mkexpr(cas->oldLo), boldLo);
+ expd_eq_old_B
+ = gen_maxU32( mce, bexpdLo, boldLo );
+ }
+
+ /* Generate a complaint if expd_eq_old is undefined. As above,
+ first force expd_eq_old's definedness to be bound to its
+ V-shadow tmp. */
+ bind_shadow_tmp_to_orig('V', mce, expd_eq_old, expd_eq_old_V);
+ if (otrak)
+ bind_shadow_tmp_to_orig('B', mce, expd_eq_old, expd_eq_old_B);
+ complainIfUndefined(mce, expd_eq_old);
+
+ /* 7. if "expected == old"
+ store data# to shadow memory */
+ do_shadow_Store( mce, cas->end, cas->addr, 0/*bias*/,
+ NULL/*data*/, vdataLo/*vdata*/,
+ expd_eq_old/*guard for store*/ );
+ if (otrak) {
+ gen_store_b( mce, elemSzB, cas->addr, 0/*offset*/,
+ bdataLo/*bdata*/,
+ expd_eq_old/*guard for store*/ );
+ }
+}
+
+
+static void do_shadow_CAS_double ( MCEnv* mce, IRCAS* cas )
+{
+ IRAtom *vdataHi = NULL, *bdataHi = NULL;
+ IRAtom *vdataLo = NULL, *bdataLo = NULL;
+ IRAtom *vexpdHi = NULL, *bexpdHi = NULL;
+ IRAtom *vexpdLo = NULL, *bexpdLo = NULL;
+ IRAtom *voldHi = NULL, *boldHi = NULL;
+ IRAtom *voldLo = NULL, *boldLo = NULL;
+ IRAtom *xHi = NULL, *xLo = NULL, *xHL = NULL;
+ IRAtom *xHi_V = NULL, *xLo_V = NULL, *xHL_V = NULL;
+ IRAtom *xHi_B = NULL, *xLo_B = NULL, *xHL_B = NULL;
+ IRAtom *expd_eq_old_V = NULL, *expd_eq_old_B = NULL;
+ IRAtom *expd_eq_old = NULL, *zero = NULL;
+ IROp opCmpEQ, opOr, opXor;
+ Int elemSzB, memOffsLo, memOffsHi;
+ IRType elemTy;
+ Bool otrak = MC_(clo_mc_level) >= 3; /* a shorthand */
+
+ /* double CAS */
+ tl_assert(cas->oldHi != IRTemp_INVALID);
+ tl_assert(cas->expdHi != NULL);
+ tl_assert(cas->dataHi != NULL);
+
+ elemTy = typeOfIRExpr(mce->sb->tyenv, cas->expdLo);
+ switch (elemTy) {
+ case Ity_I8:
+ opCmpEQ = Iop_CmpEQ8; opOr = Iop_Or8; opXor = Iop_Xor8;
+ elemSzB = 1; zero = mkU8(0);
+ break;
+ case Ity_I16:
+ opCmpEQ = Iop_CmpEQ16; opOr = Iop_Or16; opXor = Iop_Xor16;
+ elemSzB = 2; zero = mkU16(0);
+ break;
+ case Ity_I32:
+ opCmpEQ = Iop_CmpEQ32; opOr = Iop_Or32; opXor = Iop_Xor32;
+ elemSzB = 4; zero = mkU32(0);
+ break;
+ case Ity_I64:
+ opCmpEQ = Iop_CmpEQ64; opOr = Iop_Or64; opXor = Iop_Xor64;
+ elemSzB = 8; zero = mkU64(0);
+ break;
+ default:
+ tl_assert(0); /* IR defn disallows any other types */
+ }
+
+ /* 1. fetch data# (the proposed new value) */
+ tl_assert(isOriginalAtom(mce, cas->dataHi));
+ tl_assert(isOriginalAtom(mce, cas->dataLo));
+ vdataHi
+ = assignNew('V', mce, elemTy, expr2vbits(mce, cas->dataHi));
+ vdataLo
+ = assignNew('V', mce, elemTy, expr2vbits(mce, cas->dataLo));
+ tl_assert(isShadowAtom(mce, vdataHi));
+ tl_assert(isShadowAtom(mce, vdataLo));
+ if (otrak) {
+ bdataHi
+ = assignNew('B', mce, Ity_I32, schemeE(mce, cas->dataHi));
+ bdataLo
+ = assignNew('B', mce, Ity_I32, schemeE(mce, cas->dataLo));
+ tl_assert(isShadowAtom(mce, bdataHi));
+ tl_assert(isShadowAtom(mce, bdataLo));
+ }
+
+ /* 2. fetch expected# (what we expect to see at the address) */
+ tl_assert(isOriginalAtom(mce, cas->expdHi));
+ tl_assert(isOriginalAtom(mce, cas->expdLo));
+ vexpdHi
+ = assignNew('V', mce, elemTy, expr2vbits(mce, cas->expdHi));
+ vexpdLo
+ = assignNew('V', mce, elemTy, expr2vbits(mce, cas->expdLo));
+ tl_assert(isShadowAtom(mce, vexpdHi));
+ tl_assert(isShadowAtom(mce, vexpdLo));
+ if (otrak) {
+ bexpdHi
+ = assignNew('B', mce, Ity_I32, schemeE(mce, cas->expdHi));
+ bexpdLo
+ = assignNew('B', mce, Ity_I32, schemeE(mce, cas->expdLo));
+ tl_assert(isShadowAtom(mce, bexpdHi));
+ tl_assert(isShadowAtom(mce, bexpdLo));
+ }
+
+ /* 3. check definedness of address */
+ /* 4. fetch old# from shadow memory; this also checks
+ addressibility of the address */
+ if (cas->end == Iend_LE) {
+ memOffsLo = 0;
+ memOffsHi = elemSzB;
+ } else {
+ tl_assert(cas->end == Iend_BE);
+ memOffsLo = elemSzB;
+ memOffsHi = 0;
+ }
+ voldHi
+ = assignNew(
+ 'V', mce, elemTy,
+ expr2vbits_Load(
+ mce,
+ cas->end, elemTy, cas->addr, memOffsHi/*Addr bias*/
+ ));
+ voldLo
+ = assignNew(
+ 'V', mce, elemTy,
+ expr2vbits_Load(
+ mce,
+ cas->end, elemTy, cas->addr, memOffsLo/*Addr bias*/
+ ));
+ if (otrak) {
+ boldHi
+ = assignNew('B', mce, Ity_I32,
+ gen_load_b(mce, elemSzB, cas->addr,
+ memOffsHi/*addr bias*/));
+ boldLo
+ = assignNew('B', mce, Ity_I32,
+ gen_load_b(mce, elemSzB, cas->addr,
+ memOffsLo/*addr bias*/));
+ }
+
+ /* 5. the CAS itself */
+ stmt( 'C', mce, IRStmt_CAS(cas) );
+
+ /* 6. complain if "expected == old" is undefined */
+ /* Doing this directly interacts in a complex way with origin
+ tracking. Much easier to make up an expression tree and hand
+ that off to expr2vbits_Binop. We will need the expression
+ tree in any case in order to decide whether or not to do a
+ shadow store. */
+ /* Note that 'C' is kinda faking it; it is indeed a non-shadow
+ tree, but it's not copied from the input block. */
+ /*
+ xHi = oldHi ^ expdHi;
+ xLo = oldLo ^ expdLo;
+ xHL = xHi | xLo;
+ expd_eq_old = xHL == 0;
+ */
+
+ /* --- xHi = oldHi ^ expdHi --- */
+ xHi = assignNew('C', mce, elemTy,
+ binop(opXor, cas->expdHi, mkexpr(cas->oldHi)));
+ bind_shadow_tmp_to_orig('V', mce, mkexpr(cas->oldHi), voldHi);
+ xHi_V
+ = expr2vbits_Binop( mce, opXor, cas->expdHi, mkexpr(cas->oldHi));
+ if (otrak) {
+ bind_shadow_tmp_to_orig('B', mce, mkexpr(cas->oldHi), boldHi);
+ xHi_B = gen_maxU32( mce, bexpdHi, boldHi );
+ }
+
+ /* --- xLo = oldLo ^ expdLo --- */
+ xLo = assignNew('C', mce, elemTy,
+ binop(opXor, cas->expdLo, mkexpr(cas->oldLo)));
+ bind_shadow_tmp_to_orig('V', mce, mkexpr(cas->oldLo), voldLo);
+ xLo_V
+ = expr2vbits_Binop( mce, opXor, cas->expdLo, mkexpr(cas->oldLo));
+ if (otrak) {
+ bind_shadow_tmp_to_orig('B', mce, mkexpr(cas->oldLo), boldLo);
+ xLo_B = gen_maxU32( mce, bexpdLo, boldLo );
+ }
+
+ /* --- xHL = xHi | xLo --- */
+ xHL = assignNew('C', mce, elemTy,
+ binop(opOr, xHi, xLo));
+ bind_shadow_tmp_to_orig('V', mce, xHi, xHi_V);
+ bind_shadow_tmp_to_orig('V', mce, xLo, xLo_V);
+ xHL_V
+ = expr2vbits_Binop( mce, opOr, xHi, xLo );
+ if (otrak) {
+ bind_shadow_tmp_to_orig('B', mce, xHi, xHi_B);
+ bind_shadow_tmp_to_orig('B', mce, xLo, xLo_B);
+ xHL_B = gen_maxU32( mce, xHi_B, xLo_B );
+ }
+
+ /* --- expd_eq_old = xHL == 0 --- */
+ expd_eq_old
+ = assignNew('C', mce, Ity_I1,
+ binop(opCmpEQ, xHL, zero));
+ bind_shadow_tmp_to_orig('V', mce, xHL, xHL_V);
+ expd_eq_old_V
+ = expr2vbits_Binop( mce, opCmpEQ, xHL, zero);
+ if (otrak) {
+ expd_eq_old_B = xHL_B; /* since the zero literal isn't going to
+ contribute any interesting origin */
+ }
+
+ /* The backend's register allocator is probably on fire by now :-) */
+ /* Generate a complaint if expd_eq_old is undefined. As above,
+ first force expd_eq_old's definedness to be bound to its
+ V-shadow tmp. */
+ bind_shadow_tmp_to_orig('V', mce, expd_eq_old, expd_eq_old_V);
+ if (otrak)
+ bind_shadow_tmp_to_orig('B', mce, expd_eq_old, expd_eq_old_B);
+ complainIfUndefined(mce, expd_eq_old);
+
+ /* 7. if "expected == old"
+ store data# to shadow memory */
+ do_shadow_Store( mce, cas->end, cas->addr, memOffsHi/*bias*/,
+ NULL/*data*/, vdataHi/*vdata*/,
+ expd_eq_old/*guard for store*/ );
+ do_shadow_Store( mce, cas->end, cas->addr, memOffsLo/*bias*/,
+ NULL/*data*/, vdataLo/*vdata*/,
+ expd_eq_old/*guard for store*/ );
+ if (otrak) {
+ gen_store_b( mce, elemSzB, cas->addr, memOffsHi/*offset*/,
+ bdataHi/*bdata*/,
+ expd_eq_old/*guard for store*/ );
+ gen_store_b( mce, elemSzB, cas->addr, memOffsLo/*offset*/,
+ bdataLo/*bdata*/,
+ expd_eq_old/*guard for store*/ );
+ }
+}
+
+
/*------------------------------------------------------------*/
/*--- Memcheck main ---*/
/*------------------------------------------------------------*/
@@ -3349,6 +3902,7 @@
Int i;
IRExpr* e;
IRDirty* d;
+ IRCAS* cas;
switch (st->tag) {
case Ist_WrTmp:
e = st->Ist.WrTmp.data;
@@ -3415,6 +3969,13 @@
case Ist_IMark:
case Ist_MBE:
return False;
+ case Ist_CAS:
+ cas = st->Ist.CAS.details;
+ return isBogusAtom(cas->addr)
+ || (cas->expdHi ? isBogusAtom(cas->expdHi) : False)
+ || isBogusAtom(cas->expdLo)
+ || (cas->dataHi ? isBogusAtom(cas->dataHi) : False)
+ || isBogusAtom(cas->dataLo);
default:
unhandled:
ppIRStmt(st);
@@ -3424,7 +3985,7 @@
IRSB* MC_(instrument) ( VgCallbackClosure* closure,
- IRSB* bb_in,
+ IRSB* sb_in,
VexGuestLayout* layout,
VexGuestExtents* vge,
IRType gWordTy, IRType hWordTy )
@@ -3434,7 +3995,7 @@
Int i, j, first_stmt;
IRStmt* st;
MCEnv mce;
- IRSB* bb;
+ IRSB* sb_out;
if (gWordTy != hWordTy) {
/* We don't currently support this case. */
@@ -3454,22 +4015,29 @@
tl_assert(MC_(clo_mc_level) >= 1 && MC_(clo_mc_level) <= 3);
/* Set up SB */
- bb = deepCopyIRSBExceptStmts(bb_in);
+ sb_out = deepCopyIRSBExceptStmts(sb_in);
- /* Set up the running environment. Only .bb is modified as we go
- along. */
- mce.bb = bb;
+ /* Set up the running environment. Both .sb and .tmpMap are
+ modified as we go along. Note that tmps are added to both
+ .sb->tyenv and .tmpMap together, so the valid index-set for
+ those two arrays should always be identical. */
+ VG_(memset)(&mce, 0, sizeof(mce));
+ mce.sb = sb_out;
mce.trace = verboze;
mce.layout = layout;
- mce.n_originalTmps = bb->tyenv->types_used;
mce.hWordTy = hWordTy;
mce.bogusLiterals = False;
- mce.tmpMapV = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
- mce.tmpMapB = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
- for (i = 0; i < mce.n_originalTmps; i++) {
- mce.tmpMapV[i] = IRTemp_INVALID;
- mce.tmpMapB[i] = IRTemp_INVALID;
+
+ mce.tmpMap = VG_(newXA)( VG_(malloc), "mc.MC_(instrument).1", VG_(free),
+ sizeof(TempMapEnt));
+ for (i = 0; i < sb_in->tyenv->types_used; i++) {
+ TempMapEnt ent;
+ ent.kind = Orig;
+ ent.shadowV = IRTemp_INVALID;
+ ent.shadowB = IRTemp_INVALID;
+ VG_(addToXA)( mce.tmpMap, &ent );
}
+ tl_assert( VG_(sizeXA)( mce.tmpMap ) == sb_in->tyenv->types_used );
/* Make a preliminary inspection of the statements, to see if there
are any dodgy-looking literals. If there are, we generate
@@ -3479,9 +4047,9 @@
bogus = False;
- for (i = 0; i < bb_in->stmts_used; i++) {
+ for (i = 0; i < sb_in->stmts_used; i++) {
- st = bb_in->stmts[i];
+ st = sb_in->stmts[i];
tl_assert(st);
tl_assert(isFlatIRStmt(st));
@@ -3500,16 +4068,17 @@
/* Copy verbatim any IR preamble preceding the first IMark */
- tl_assert(mce.bb == bb);
+ tl_assert(mce.sb == sb_out);
+ tl_assert(mce.sb != sb_in);
i = 0;
- while (i < bb_in->stmts_used && bb_in->stmts[i]->tag != Ist_IMark) {
+ while (i < sb_in->stmts_used && sb_in->stmts[i]->tag != Ist_IMark) {
- st = bb_in->stmts[i];
+ st = sb_in->stmts[i];
tl_assert(st);
tl_assert(isFlatIRStmt(st));
- stmt( 'C', &mce, bb_in->stmts[i] );
+ stmt( 'C', &mce, sb_in->stmts[i] );
i++;
}
@@ -3536,16 +4105,16 @@
no-origin, as appropriate for a defined value.
*/
for (j = 0; j < i; j++) {
- if (bb_in->stmts[j]->tag == Ist_WrTmp) {
+ if (sb_in->stmts[j]->tag == Ist_WrTmp) {
/* findShadowTmpV checks its arg is an original tmp;
no need to assert that here. */
- IRTemp tmp_o = bb_in->stmts[j]->Ist.WrTmp.tmp;
+ IRTemp tmp_o = sb_in->stmts[j]->Ist.WrTmp.tmp;
IRTemp tmp_v = findShadowTmpV(&mce, tmp_o);
- IRType ty_v = typeOfIRTemp(bb->tyenv, tmp_v);
+ IRType ty_v = typeOfIRTemp(sb_out->tyenv, tmp_v);
assign( 'V', &mce, tmp_v, definedOfType( ty_v ) );
if (MC_(clo_mc_level) == 3) {
IRTemp tmp_b = findShadowTmpB(&mce, tmp_o);
- tl_assert(typeOfIRTemp(bb->tyenv, tmp_b) == Ity_I32);
+ tl_assert(typeOfIRTemp(sb_out->tyenv, tmp_b) == Ity_I32);
assign( 'B', &mce, tmp_b, mkU32(0)/* UNKNOWN ORIGIN */);
}
if (0) {
@@ -3558,15 +4127,15 @@
/* Iterate over the remaining stmts to generate instrumentation. */
- tl_assert(bb_in->stmts_used > 0);
+ tl_assert(sb_in->stmts_used > 0);
tl_assert(i >= 0);
- tl_assert(i < bb_in->stmts_used);
- tl_assert(bb_in->stmts[i]->tag == Ist_IMark);
+ tl_assert(i < sb_in->stmts_used);
+ tl_assert(sb_in->stmts[i]->tag == Ist_IMark);
- for (/* use current i*/; i < bb_in->stmts_used; i++) {
+ for (/* use current i*/; i < sb_in->stmts_used; i++) {
- st = bb_in->stmts[i];
- first_stmt = bb->stmts_used;
+ st = sb_in->stmts[i];
+ first_stmt = sb_out->stmts_used;
if (verboze) {
VG_(printf)("\n");
@@ -3574,8 +4143,11 @@
VG_(printf)("\n");
}
- if (MC_(clo_mc_level) == 3)
- schemeS( &mce, st );
+ if (MC_(clo_mc_level) == 3) {
+ /* See comments on case Ist_CAS below. */
+ if (st->tag != Ist_CAS)
+ schemeS( &mce, st );
+ }
/* Generate instrumentation code for each stmt ... */
@@ -3605,7 +4177,8 @@
do_shadow_Store( &mce, st->Ist.Store.end,
st->Ist.Store.addr, 0/* addr bias */,
st->Ist.Store.data,
- NULL /* shadow data */ );
+ NULL /* shadow data */,
+ NULL/*guard*/ );
break;
case Ist_Exit:
@@ -3629,6 +4202,16 @@
st->Ist.AbiHint.nia );
break;
+ case Ist_CAS:
+ do_shadow_CAS( &mce, st->Ist.CAS.details );
+ /* Note, do_shadow_CAS copies the CAS itself to the output
+ block, because it needs to add instrumentation both
+ before and after it. Hence skip the copy below. Also
+ skip the origin-tracking stuff (call to schemeS) above,
+ since that's all tangled up with it too; do_shadow_CAS
+ does it all. */
+ break;
+
default:
VG_(printf)("\n");
ppIRStmt(st);
@@ -3638,40 +4221,48 @@
} /* switch (st->tag) */
if (0 && verboze) {
- for (j = first_stmt; j < bb->stmts_used; j++) {
+ for (j = first_stmt; j < sb_out->stmts_used; j++) {
VG_(printf)(" ");
- ppIRStmt(bb->stmts[j]);
+ ppIRStmt(sb_out->stmts[j]);
VG_(printf)("\n");
}
VG_(printf)("\n");
}
- /* ... and finally copy the stmt itself to the output. */
- stmt('C', &mce, st);
-
+ /* ... and finally copy the stmt itself to the output. Except,
+ skip the copy of IRCASs; see comments on case Ist_CAS
+ above. */
+ if (st->tag != Ist_CAS)
+ stmt('C', &mce, st);
}
/* Now we need to complain if the jump target is undefined. */
- first_stmt = bb->stmts_used;
+ first_stmt = sb_out->stmts_used;
if (verboze) {
- VG_(printf)("bb->next = ");
- ppIRExpr(bb->next);
+ VG_(printf)("sb_in->next = ");
+ ppIRExpr(sb_in->next);
VG_(printf)("\n\n");
}
- complainIfUndefined( &mce, bb->next );
+ complainIfUndefined( &mce, sb_in->next );
if (0 && verboze) {
- for (j = first_stmt; j < bb->stmts_used; j++) {
+ for (j = first_stmt; j < sb_out->stmts_used; j++) {
VG_(printf)(" ");
- ppIRStmt(bb->stmts[j]);
+ ppIRStmt(sb_out->stmts[j]);
VG_(printf)("\n");
}
VG_(printf)("\n");
}
- return bb;
+ /* If this fails, there's been some serious snafu with tmp management,
+ that should be investigated. */
+ tl_assert( VG_(sizeXA)( mce.tmpMap ) == mce.sb->tyenv->types_used );
+ VG_(deleteXA)( mce.tmpMap );
+
+ tl_assert(mce.sb == sb_out);
+ return sb_out;
}
/*------------------------------------------------------------*/
@@ -3826,14 +4417,25 @@
/*--- Origin tracking stuff ---*/
/*------------------------------------------------------------*/
+/* Almost identical to findShadowTmpV. */
static IRTemp findShadowTmpB ( MCEnv* mce, IRTemp orig )
{
- tl_assert(orig < mce->n_originalTmps);
- if (mce->tmpMapB[orig] == IRTemp_INVALID) {
- mce->tmpMapB[orig]
- = newIRTemp(mce->bb->tyenv, Ity_I32);
+ TempMapEnt* ent;
+ /* VG_(indexXA) range-checks 'orig', hence no need to check
+ here. */
+ ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
+ tl_assert(ent->kind == Orig);
+ if (ent->shadowB == IRTemp_INVALID) {
+ IRTemp tmpB
+ = newTemp( mce, Ity_I32, BSh );
+ /* newTemp may cause mce->tmpMap to resize, hence previous results
+ from VG_(indexXA) are invalid. */
+ ent = (TempMapEnt*)VG_(indexXA)( mce->tmpMap, (Word)orig );
+ tl_assert(ent->kind == Orig);
+ tl_assert(ent->shadowB == IRTemp_INVALID);
+ ent->shadowB = tmpB;
}
- return mce->tmpMapB[orig];
+ return ent->shadowB;
}
static IRAtom* gen_maxU32 ( MCEnv* mce, IRAtom* b1, IRAtom* b2 )
@@ -3848,7 +4450,7 @@
HChar* hName;
IRTemp bTmp;
IRDirty* di;
- IRType aTy = typeOfIRExpr( mce->bb->tyenv, baseaddr );
+ IRType aTy = typeOfIRExpr( mce->sb->tyenv, baseaddr );
IROp opAdd = aTy == Ity_I32 ? Iop_Add32 : Iop_Add64;
IRAtom* ea = baseaddr;
if (offset != 0) {
@@ -3856,7 +4458,7 @@
: mkU64( (Long)(Int)offset );
ea = assignNew( 'B', mce, aTy, binop(opAdd, ea, off));
}
- bTmp = newIRTemp(mce->bb->tyenv, mce->hWordTy);
+ bTmp = newTemp(mce, mce->hWordTy, BSh);
switch (szB) {
case 1: hFun = (void*)&MC_(helperc_b_load1);
@@ -3887,7 +4489,7 @@
stmt( 'B', mce, IRStmt_Dirty(di) );
if (mce->hWordTy == Ity_I64) {
/* 64-bit host */
- IRTemp bTmp32 = newIRTemp(mce->bb->tyenv, Ity_I32);
+ IRTemp bTmp32 = newTemp(mce, Ity_I32, BSh);
assign( 'B', mce, bTmp32, unop(Iop_64to32, mkexpr(bTmp)) );
return mkexpr(bTmp32);
} else {
@@ -3895,15 +4497,23 @@
return mkexpr(bTmp);
}
}
+
+/* Generate a shadow store. guard :: Ity_I1 controls whether the
+ store really happens; NULL means it unconditionally does. */
static void gen_store_b ( MCEnv* mce, Int szB,
- IRAtom* baseaddr, Int offset, IRAtom* dataB )
+ IRAtom* baseaddr, Int offset, IRAtom* dataB,
+ IRAtom* guard )
{
void* hFun;
HChar* hName;
IRDirty* di;
- IRType aTy = typeOfIRExpr( mce->bb->tyenv, baseaddr );
+ IRType aTy = typeOfIRExpr( mce->sb->tyenv, baseaddr );
IROp opAdd = aTy == Ity_I32 ? Iop_Add32 : Iop_Add64;
IRAtom* ea = baseaddr;
+ if (guard) {
+ tl_assert(isOriginalAtom(mce, guard));
+ tl_assert(typeOfIRExpr(mce->sb->tyenv, guard) == Ity_I1);
+ }
if (offset != 0) {
IRAtom* off = aTy == Ity_I32 ? mkU32( offset )
: mkU64( (Long)(Int)offset );
@@ -3937,11 +4547,12 @@
);
/* no need to mess with any annotations. This call accesses
neither guest state nor guest memory. */
+ if (guard) di->guard = guard;
stmt( 'B', mce, IRStmt_Dirty(di) );
}
static IRAtom* narrowTo32 ( MCEnv* mce, IRAtom* e ) {
- IRType eTy = typeOfIRExpr(mce->bb->tyenv, e);
+ IRType eTy = typeOfIRExpr(mce->sb->tyenv, e);
if (eTy == Ity_I64)
return assignNew( 'B', mce, Ity_I32, unop(Iop_64to32, e) );
if (eTy == Ity_I32)
@@ -3950,7 +4561,7 @@
}
static IRAtom* zWidenFrom32 ( MCEnv* mce, IRType dstTy, IRAtom* e ) {
- IRType eTy = typeOfIRExpr(mce->bb->tyenv, e);
+ IRType eTy = typeOfIRExpr(mce->sb->tyenv, e);
tl_assert(eTy == Ity_I32);
if (dstTy == Ity_I64)
return assignNew( 'B', mce, Ity_I64, unop(Iop_32Uto64, e) );
@@ -4220,12 +4831,14 @@
toDo = d->mSize;
/* chew off 32-bit chunks */
while (toDo >= 4) {
- gen_store_b( mce, 4, d->mAddr, d->mSize - toDo, curr );
+ gen_store_b( mce, 4, d->mAddr, d->mSize - toDo, curr,
+ NULL/*guard*/ );
toDo -= 4;
}
/* handle possible 16-bit excess */
while (toDo >= 2) {
- gen_store_b( mce, 2, d->mAddr, d->mSize - toDo, curr );
+ gen_store_b( mce, 2, d->mAddr, d->mSize - toDo, curr,
+ NULL/*guard*/ );
toDo -= 2;
}
tl_assert(toDo == 0); /* also need to handle 1-byte excess */
@@ -4282,16 +4895,17 @@
available (somewhere) */
tl_assert(isIRAtom(st->Ist.Store.addr));
dszB = sizeofIRType(
- typeOfIRExpr(mce->bb->tyenv, st->Ist.Store.data ));
+ typeOfIRExpr(mce->sb->tyenv, st->Ist.Store.data ));
dataB = schemeE( mce, st->Ist.Store.data );
- gen_store_b( mce, dszB, st->Ist.Store.addr, 0/*offset*/, dataB );
+ gen_store_b( mce, dszB, st->Ist.Store.addr, 0/*offset*/, dataB,
+ NULL/*guard*/ );
break;
}
case Ist_Put: {
Int b_offset
= MC_(get_otrack_shadow_offset)(
st->Ist.Put.offset,
- sizeofIRType(typeOfIRExpr(mce->bb->tyenv, st->Ist.Put.data))
+ sizeofIRType(typeOfIRExpr(mce->sb->tyenv, st->Ist.Put.data))
);
if (b_offset >= 0) {
/* FIXME: this isn't an atom! */
|
|
From: <sv...@va...> - 2009-05-22 13:07:07
|
Author: bart
Date: 2009-05-22 14:07:03 +0100 (Fri, 22 May 2009)
New Revision: 10108
Log:
Replaced segment merging algorithm and minimized the number of conflict set updates. This reduces the time needed to run the DRD regression tests by about 10%.
Modified:
branches/DRDDEV/drd/drd_thread.c
Modified: branches/DRDDEV/drd/drd_thread.c
===================================================================
--- branches/DRDDEV/drd/drd_thread.c 2009-05-22 11:40:47 UTC (rev 10107)
+++ branches/DRDDEV/drd/drd_thread.c 2009-05-22 13:07:03 UTC (rev 10108)
@@ -749,8 +749,34 @@
}
/**
- * Verify that all segments of other threads than 'tid' are ordered
- * consistently against both sg1 and sg2.
+ * An implementation of the property 'equiv(sg1, sg2)' as defined in the paper
+ * by Mark Christiaens e.a. The property equiv(sg1, sg2) holds if and only if
+ * all segments in the set CS are ordered consistently against both sg1 and
+ * sg2. The set CS is defined as the set of segments that can immediately
+ * precede future segments via inter-thread synchronization operations. In
+ * DRD the set CS consists of the latest segment of each thread combined with
+ * all segments for which the reference count is strictly greater than one.
+ * The code below is an optimized version of the following:
+ *
+ * for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
+ * i++)
+ * {
+ * Segment* sg;
+ *
+ * for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
+ * {
+ * if (sg == DRD_(g_threadinfo)[i].last || DRD_(sg_get_refcnt)(sg) > 1)
+ * {
+ * if ( DRD_(vc_lte)(&sg1->vc, &sg->vc)
+ * != DRD_(vc_lte)(&sg2->vc, &sg->vc)
+ * || DRD_(vc_lte)(&sg->vc, &sg1->vc)
+ * != DRD_(vc_lte)(&sg->vc, &sg2->vc))
+ * {
+ * return False;
+ * }
+ * }
+ * }
+ * }
*/
static Bool thread_consistent_segment_ordering(const DrdThreadId tid,
Segment* const sg1,
@@ -758,6 +784,9 @@
{
unsigned i;
+ tl_assert(sg1->next);
+ tl_assert(sg2->next);
+ tl_assert(sg1->next == sg2);
tl_assert(DRD_(vc_lte)(&sg1->vc, &sg2->vc));
for (i = 0; i < sizeof(DRD_(g_threadinfo)) / sizeof(DRD_(g_threadinfo)[0]);
@@ -765,22 +794,25 @@
{
Segment* sg;
- if (i == tid)
- continue;
-
for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
{
- if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
- break;
- if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
- return False;
+ if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
+ {
+ if (DRD_(vc_lte)(&sg2->vc, &sg->vc))
+ break;
+ if (DRD_(vc_lte)(&sg1->vc, &sg->vc))
+ return False;
+ }
}
for (sg = DRD_(g_threadinfo)[i].last; sg; sg = sg->prev)
{
- if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
- break;
- if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
- return False;
+ if (! sg->next || DRD_(sg_get_refcnt)(sg) > 1)
+ {
+ if (DRD_(vc_lte)(&sg->vc, &sg1->vc))
+ break;
+ if (DRD_(vc_lte)(&sg->vc, &sg2->vc))
+ return False;
+ }
}
}
return True;
@@ -789,11 +821,21 @@
/**
* Merge all segments that may be merged without triggering false positives
* or discarding real data races. For the theoretical background of segment
- * merging, see also the following paper:
- * Mark Christiaens, Michiel Ronsse and Koen De Bosschere.
- * Bounding the number of segment histories during data race detection.
- * Parallel Computing archive, Volume 28, Issue 9, pp 1221-1238,
- * September 2002.
+ * merging, see also the following paper: Mark Christiaens, Michiel Ronsse
+ * and Koen De Bosschere. Bounding the number of segment histories during
+ * data race detection. Parallel Computing archive, Volume 28, Issue 9,
+ * pp 1221-1238, September 2002. This paper contains a proof that merging
+ * consecutive segments for which the property equiv(s1,s2) holds can be
+ * merged without reducing the accuracy of datarace detection. Furthermore
+ * it is also proven that the total number of all segments will never grow
+ * unbounded if all segments s1, s2 for which equiv(s1, s2) holds are merged
+ * every time a new segment is created. The property equiv(s1, s2) is defined
+ * as follows: equiv(s1, s2) <=> for all segments in the set CS, the vector
+ * clocks of segments s and s1 are ordered in the same way as those of segments
+ * s and s2. The set CS is defined as the set of existing segments s that have
+ * the potential to conflict with not yet created segments, either because the
+ * segment s is the latest segment of a thread or because it can become the
+ * immediate predecessor of a new segment due to a synchronization operation.
*/
static void thread_merge_segments(void)
{
@@ -810,20 +852,9 @@
for (sg = DRD_(g_threadinfo)[i].first; sg; sg = sg->next)
{
-#if 1
if (DRD_(sg_get_refcnt)(sg) == 1
&& sg->next
&& DRD_(sg_get_refcnt)(sg->next) == 1
- && sg->next->next)
- {
- /* Merge sg and sg->next into sg. */
- DRD_(sg_merge)(sg, sg->next);
- thread_discard_segment(i, sg->next);
- }
-#else
- if (DRD_(sg_get_refcnt)(sg) == 1
- && sg->next
- && DRD_(sg_get_refcnt)(sg->next) == 1
&& sg->next->next
&& thread_consistent_segment_ordering(i, sg, sg->next))
{
@@ -831,7 +862,6 @@
DRD_(sg_merge)(sg, sg->next);
thread_discard_segment(i, sg->next);
}
-#endif
}
#if 0
@@ -854,7 +884,6 @@
static Bool conflict_set_update_needed(const DrdThreadId tid,
const Segment* const new_sg)
{
-#if 0
unsigned j;
const Segment* old_sg;
@@ -887,7 +916,6 @@
for (q = DRD_(g_threadinfo)[j].last; q; q = q->prev)
{
- /* Does not yield correct results because of segment merging. */
const int included_in_old_conflict_set
= ! DRD_(vc_lte)(&q->vc, &old_sg->vc)
&& ! DRD_(vc_lte)(&old_sg->vc, &q->vc);
@@ -900,9 +928,6 @@
}
return False;
-#else
- return True;
-#endif
}
/**
|
|
From: Konstantin S. <kon...@gm...> - 2009-05-22 11:45:31
|
On Fri, May 22, 2009 at 2:27 PM, Julian Seward <js...@ac...> wrote:
>
> Konstantin,
>
> (w/ apologies if you did already ..)
>
> Could you give some background to explain why you need to mark a
> particular memory access to a location as OK, but not others?
> Am kinda curious to see a bit the bigger picture.
Many people write code with strlen-like hacks, i.e. they access memory
out of bounds (or uninitialized memory) and know this is correct.
Example (from my initial message):
int *p = (int*)malloc(100);
// p is 4-aligned and not initialized
if (...) {
p[0] = '\0';
} else {
p[0] = 'h';
p[1] = 't';
p[2] = 't';
p[3] = 'p';
}
...
// here we read 4 first bytes of p.
// bytes p[1],p[2],p[3] may not be initialized, but this is safe, because
// in this case p[0] will not be equal to 'h'.
int first_four_bytes_of_p = ANNOTATE_SAFE_READ(*(int*)p);
if (first_four_bytes_of_p == combine_four_chars_into_int("http")) ...
And some of these warnings can't be easily suppressed with valgrind
suppressions (you know why, otherwise you wouldn't intercept strlen,
you would just suppress it).
Even if some warning can be suppressed with valgrind suppressions,
many people want to have the annotation in the code, not in the
external file.
With ThreadSanitizer the in-code annotations proved to be very useful.
--kcc
>
> J
>
> On Friday 22 May 2009, Konstantin Serebryany wrote:
>> Hi Nick,
>>
>> Here is my attempt for a patch and a unittest.
>> The first thing you would probably ask is how does this affect the
>> performance of Memcheck.
>> Would you suggest a benchmark to try?
>> Other comments?
>>
>> Thanks,
>>
>> --kcc
>>
>> % g++ -g -DHAVE_IGNORE_ANNOTATIONS memcheck_annotations.cc -I
>> $HOME/valgrind/ann/inst/include &&
>> $HOME/valgrind/ann/inst/bin/valgrind -q ./a.out
>> % g++ -g memcheck_annotations.cc -I $HOME/valgrind/ann/inst/include
>> && $HOME/valgrind/ann/inst/bin/valgrind -q ./a.out 2>&1 | head
>> ==16258== Invalid write of size 1
>> ==16258== at 0x4006D9: int test_memcheck_annotations<signed char>()
>> (memcheck_annotations.cc:16)
>> ==16258== by 0x4006A4: main (memcheck_annotations.cc:31)
>> ==16258== Address 0x58f603a is 0 bytes after a block of size 10 alloc'd
>> ==16258== at 0x4C1C87C: operator new[](unsigned long)
>> (vg_replace_malloc.c:245)
>> ==16258== by 0x4006CC: int test_memcheck_annotations<signed char>()
>> (memcheck_annotations.cc:13)
>> ==16258== by 0x4006A4: main (memcheck_annotations.cc:31)
>> ==16258==
>> ==16258== Invalid read of size 1
>> ==16258== at 0x4006E4: int test_memcheck_annotations<signed char>()
>> (memcheck_annotations.cc:19)
>> %
>>
>>
>>
>>
>>
>>
>> On Wed, Apr 8, 2009 at 6:25 PM, Konstantin Serebryany
>>
>> <kon...@gm...> wrote:
>> > On Wed, Apr 8, 2009 at 2:07 PM, Nicholas Nethercote
>> >
>> > <n.n...@gm...> wrote:
>> >> On Wed, Apr 8, 2009 at 2:20 AM, Konstantin Serebryany
>> >>
>> >> <kon...@gm...> wrote:
>> >>> Memcheck has client requests such as VALGRIND_MAKE_MEM_DEFINED(mem,
>> >>> size). These requests mark memory as initialized (i.e. safe to read).
>> >>> But there is no annotation that marks a specific memory access as safe.
>> >>> Is that not included intentionally? If yes, what was the reason? If no,
>> >>> do you mind to include such request(s)?
>> >>
>> >> I think the reason is that nobody has required them until now.
>> >>
>> >> I've previously thought about them in one context, involving more
>> >> aggressive checking by Memcheck of a program. Imagine you have a data
>> >> structure that should only be accessed through a small number of
>> >> access functions. You could mark the data structure as unaddressable,
>> >> and then wrap the accesses within the access functions with such
>> >> annotations. That way you would immediately know if any other part of
>> >> your program accessed the data structure not via those access
>> >> functions, which could be due to (a) failure to observe the access
>> >> function discipline, or (b) corrupted pointers or similar.
>> >>
>> >> I thought about doing this by marking the memory as
>> >> addressable-and-defined, doing the read/write, then marking it
>> >> unaddressable again, but your approach is more efficient. So I can see
>> >> these annotations would be useful. Here's an attempt at what they
>> >> would look like:
>> >>
>> >> // Memcheck normally checks that you do not read unaddressable or
>> >> // addressable-but-undefined memory. This wrapper causes that
>> >> // check to be omitted.
>> >> VALGRIND_UNCHECKED_MEM_READ(mem)
>> >>
>> >> // Memcheck normally checks that you do not write unaddressable memory.
>> >> // This wrapper causes that check to be omitted.
>> >> VALGRIND_UNCHECKED_MEM_WRITE(mem)
>> >
>> > In addition to these, we may want to have a BEGIN/END form, for the
>> > cases when the access happens in a routine which we can not annotate
>> > or which may be used in other contexts.
>> > VALGRIND_IGNORE_READS_BEGIN()
>> > external_function(pointer_to_uninitialized_but_safe_to_use_memory)
>> > VALGRIND_IGNORE_READS_END()
>> >
>> >>> Example:
>> >>>
>> >>> int *p = (int*)malloc(100);
>> >>> // p is 4-aligned and not initialized
>> >>
>> >> Not quite. p is 4-aligned and initialized. *p is unitialized.
>> >
>> > ah, yes.
>> >
>> > --kcc
>
>
>
|
Author: bart Date: 2009-05-22 12:40:47 +0100 (Fri, 22 May 2009) New Revision: 10107 Log: svn merge -r9796:10106 svn://svn.valgrind.org/valgrind/trunk . Added: branches/DRDDEV/coregrind/m_initimg/initimg-pathscan.c branches/DRDDEV/coregrind/m_initimg/priv_initimg_pathscan.h branches/DRDDEV/drd/tests/pth_mutex_reinit.c branches/DRDDEV/drd/tests/pth_mutex_reinit.stderr.exp branches/DRDDEV/drd/tests/pth_mutex_reinit.vgtest branches/DRDDEV/massif/tests/one.post.exp2 Modified: branches/DRDDEV/Makefile.am branches/DRDDEV/NEWS branches/DRDDEV/auxprogs/Makefile.am branches/DRDDEV/cachegrind/cg_main.c branches/DRDDEV/cachegrind/tests/filter_stderr branches/DRDDEV/callgrind/command.c branches/DRDDEV/callgrind/dump.c branches/DRDDEV/callgrind/fn.c branches/DRDDEV/callgrind/tests/filter_stderr branches/DRDDEV/configure.in branches/DRDDEV/coregrind/Makefile.am branches/DRDDEV/coregrind/m_aspacehl.c branches/DRDDEV/coregrind/m_aspacemgr/aspacemgr-common.c branches/DRDDEV/coregrind/m_aspacemgr/aspacemgr-linux.c branches/DRDDEV/coregrind/m_commandline.c branches/DRDDEV/coregrind/m_coredump/coredump-elf.c branches/DRDDEV/coregrind/m_debuginfo/d3basics.c branches/DRDDEV/coregrind/m_debuginfo/debuginfo.c branches/DRDDEV/coregrind/m_debuginfo/priv_readdwarf3.h branches/DRDDEV/coregrind/m_debuginfo/readdwarf.c branches/DRDDEV/coregrind/m_debuginfo/readelf.c branches/DRDDEV/coregrind/m_debuginfo/readstabs.c branches/DRDDEV/coregrind/m_debuglog.c branches/DRDDEV/coregrind/m_errormgr.c branches/DRDDEV/coregrind/m_initimg/initimg-linux.c branches/DRDDEV/coregrind/m_libcassert.c branches/DRDDEV/coregrind/m_libcbase.c branches/DRDDEV/coregrind/m_libcfile.c branches/DRDDEV/coregrind/m_libcproc.c branches/DRDDEV/coregrind/m_libcsignal.c branches/DRDDEV/coregrind/m_machine.c branches/DRDDEV/coregrind/m_main.c branches/DRDDEV/coregrind/m_mallocfree.c branches/DRDDEV/coregrind/m_replacemalloc/vg_replace_malloc.c branches/DRDDEV/coregrind/m_scheduler/scheduler.c branches/DRDDEV/coregrind/m_signals.c branches/DRDDEV/coregrind/m_syscall.c branches/DRDDEV/coregrind/m_syswrap/priv_syswrap-generic.h branches/DRDDEV/coregrind/m_syswrap/priv_types_n_macros.h branches/DRDDEV/coregrind/m_syswrap/syscall-amd64-linux.S branches/DRDDEV/coregrind/m_syswrap/syscall-ppc32-aix5.S branches/DRDDEV/coregrind/m_syswrap/syscall-ppc32-linux.S branches/DRDDEV/coregrind/m_syswrap/syscall-ppc64-aix5.S branches/DRDDEV/coregrind/m_syswrap/syscall-ppc64-linux.S branches/DRDDEV/coregrind/m_syswrap/syscall-x86-linux.S branches/DRDDEV/coregrind/m_syswrap/syswrap-amd64-linux.c branches/DRDDEV/coregrind/m_syswrap/syswrap-generic.c branches/DRDDEV/coregrind/m_syswrap/syswrap-linux.c branches/DRDDEV/coregrind/m_syswrap/syswrap-main.c branches/DRDDEV/coregrind/m_syswrap/syswrap-ppc32-linux.c branches/DRDDEV/coregrind/m_syswrap/syswrap-ppc64-linux.c branches/DRDDEV/coregrind/m_syswrap/syswrap-x86-linux.c branches/DRDDEV/coregrind/m_transtab.c branches/DRDDEV/coregrind/m_ume/elf.c branches/DRDDEV/coregrind/m_ume/main.c branches/DRDDEV/coregrind/m_ume/script.c branches/DRDDEV/coregrind/m_vki.c branches/DRDDEV/coregrind/pub_core_aspacemgr.h branches/DRDDEV/coregrind/pub_core_clreq.h branches/DRDDEV/coregrind/pub_core_debuglog.h branches/DRDDEV/coregrind/pub_core_libcfile.h branches/DRDDEV/coregrind/pub_core_libcsignal.h branches/DRDDEV/coregrind/pub_core_machine.h branches/DRDDEV/coregrind/pub_core_mallocfree.h branches/DRDDEV/coregrind/pub_core_signals.h branches/DRDDEV/coregrind/pub_core_syscall.h branches/DRDDEV/coregrind/pub_core_syswrap.h branches/DRDDEV/coregrind/pub_core_threadstate.h branches/DRDDEV/coregrind/pub_core_trampoline.h branches/DRDDEV/coregrind/pub_core_vki.h branches/DRDDEV/coregrind/pub_core_vkiscnums.h branches/DRDDEV/docs/README branches/DRDDEV/docs/xml/FAQ.xml branches/DRDDEV/drd/drd_mutex.c branches/DRDDEV/drd/drd_pthread_intercepts.c branches/DRDDEV/drd/tests/ branches/DRDDEV/drd/tests/Makefile.am branches/DRDDEV/exp-ptrcheck/h_main.c branches/DRDDEV/helgrind/hg_intercepts.c branches/DRDDEV/helgrind/hg_main.c branches/DRDDEV/helgrind/libhb_core.c branches/DRDDEV/helgrind/tests/Makefile.am branches/DRDDEV/helgrind/tests/filter_stderr branches/DRDDEV/include/pub_tool_basics.h branches/DRDDEV/include/pub_tool_libcbase.h branches/DRDDEV/include/pub_tool_libcfile.h branches/DRDDEV/include/pub_tool_redir.h branches/DRDDEV/include/pub_tool_vkiscnums.h branches/DRDDEV/include/valgrind.h branches/DRDDEV/include/vki/vki-amd64-linux.h branches/DRDDEV/include/vki/vki-ppc32-linux.h branches/DRDDEV/include/vki/vki-ppc64-linux.h branches/DRDDEV/include/vki/vki-x86-linux.h branches/DRDDEV/massif/ms_main.c branches/DRDDEV/massif/tests/ branches/DRDDEV/massif/tests/Makefile.am branches/DRDDEV/massif/tests/malloc_usable.vgtest branches/DRDDEV/memcheck/docs/mc-manual.xml branches/DRDDEV/memcheck/mc_leakcheck.c branches/DRDDEV/memcheck/mc_main.c branches/DRDDEV/memcheck/mc_malloc_wrappers.c branches/DRDDEV/memcheck/perf/ branches/DRDDEV/memcheck/tests/ branches/DRDDEV/memcheck/tests/Makefile.am branches/DRDDEV/memcheck/tests/badjump.c branches/DRDDEV/memcheck/tests/filter_xml branches/DRDDEV/memcheck/tests/unit_libcbase.c branches/DRDDEV/memcheck/tests/writev.c branches/DRDDEV/memcheck/tests/x86-linux/scalar.c branches/DRDDEV/memcheck/tests/x86-linux/scalar.stderr.exp branches/DRDDEV/memcheck/tests/x86/bug152022.stderr.exp branches/DRDDEV/memcheck/tests/x86/bug152022.vgtest branches/DRDDEV/nightly/ branches/DRDDEV/none/tests/Makefile.am branches/DRDDEV/none/tests/amd64/redundantRexW.c branches/DRDDEV/none/tests/fdleak_cmsg.c branches/DRDDEV/none/tests/linux/ branches/DRDDEV/none/tests/linux/Makefile.am branches/DRDDEV/none/tests/x86-linux/ branches/DRDDEV/none/tests/x86/Makefile.am branches/DRDDEV/tests/ branches/DRDDEV/tests/filter_addresses branches/DRDDEV/tests/filter_stderr_basic branches/DRDDEV/tests/x86_amd64_features.c [... diff too large to include ...] |
|
From: Philippe W. <phi...@sk...> - 2009-05-22 11:02:56
|
>> Testing this on firefox startup gives reasonable result: >> there is about 72000 different jCC stack traces, 4,000,000 elements in these stack traces. >> => so, on a x86, this needs about 20Mb of memory > > So there are around 72000 different calling contexts for heap allocations? That seems to > be manageble, yes. Do you do anything special for contexts with recursion? Nothing special is done for recursion: the "raw" stack of JCCs is stored. > > So if you have this, it would be easy to try whether this is practical at > least for some cases also for the cacheline usage... > >> I still have a few things to cleanup/improve. I will then send the current state of >> the code as a basis to discuss/review (there are for sure points to improve/change/enhance/...) > > Thanks, I am interested ;-) The jCC stack trace stuff will be easy to restructure so that it can be re-used for other things than the heap allocations. But I think this will be better done once you will have had the occasion to do a first review : there are a few pieces of code that I have done by trial and errors, without fully understanding the logic behind the code :). Philippe |
|
From: Julian S. <js...@ac...> - 2009-05-22 10:24:10
|
Konstantin, (w/ apologies if you did already ..) Could you give some background to explain why you need to mark a particular memory access to a location as OK, but not others? Am kinda curious to see a bit the bigger picture. J On Friday 22 May 2009, Konstantin Serebryany wrote: > Hi Nick, > > Here is my attempt for a patch and a unittest. > The first thing you would probably ask is how does this affect the > performance of Memcheck. > Would you suggest a benchmark to try? > Other comments? > > Thanks, > > --kcc > > % g++ -g -DHAVE_IGNORE_ANNOTATIONS memcheck_annotations.cc -I > $HOME/valgrind/ann/inst/include && > $HOME/valgrind/ann/inst/bin/valgrind -q ./a.out > % g++ -g memcheck_annotations.cc -I $HOME/valgrind/ann/inst/include > && $HOME/valgrind/ann/inst/bin/valgrind -q ./a.out 2>&1 | head > ==16258== Invalid write of size 1 > ==16258== at 0x4006D9: int test_memcheck_annotations<signed char>() > (memcheck_annotations.cc:16) > ==16258== by 0x4006A4: main (memcheck_annotations.cc:31) > ==16258== Address 0x58f603a is 0 bytes after a block of size 10 alloc'd > ==16258== at 0x4C1C87C: operator new[](unsigned long) > (vg_replace_malloc.c:245) > ==16258== by 0x4006CC: int test_memcheck_annotations<signed char>() > (memcheck_annotations.cc:13) > ==16258== by 0x4006A4: main (memcheck_annotations.cc:31) > ==16258== > ==16258== Invalid read of size 1 > ==16258== at 0x4006E4: int test_memcheck_annotations<signed char>() > (memcheck_annotations.cc:19) > % > > > > > > > On Wed, Apr 8, 2009 at 6:25 PM, Konstantin Serebryany > > <kon...@gm...> wrote: > > On Wed, Apr 8, 2009 at 2:07 PM, Nicholas Nethercote > > > > <n.n...@gm...> wrote: > >> On Wed, Apr 8, 2009 at 2:20 AM, Konstantin Serebryany > >> > >> <kon...@gm...> wrote: > >>> Memcheck has client requests such as VALGRIND_MAKE_MEM_DEFINED(mem, > >>> size). These requests mark memory as initialized (i.e. safe to read). > >>> But there is no annotation that marks a specific memory access as safe. > >>> Is that not included intentionally? If yes, what was the reason? If no, > >>> do you mind to include such request(s)? > >> > >> I think the reason is that nobody has required them until now. > >> > >> I've previously thought about them in one context, involving more > >> aggressive checking by Memcheck of a program. Imagine you have a data > >> structure that should only be accessed through a small number of > >> access functions. You could mark the data structure as unaddressable, > >> and then wrap the accesses within the access functions with such > >> annotations. That way you would immediately know if any other part of > >> your program accessed the data structure not via those access > >> functions, which could be due to (a) failure to observe the access > >> function discipline, or (b) corrupted pointers or similar. > >> > >> I thought about doing this by marking the memory as > >> addressable-and-defined, doing the read/write, then marking it > >> unaddressable again, but your approach is more efficient. So I can see > >> these annotations would be useful. Here's an attempt at what they > >> would look like: > >> > >> // Memcheck normally checks that you do not read unaddressable or > >> // addressable-but-undefined memory. This wrapper causes that > >> // check to be omitted. > >> VALGRIND_UNCHECKED_MEM_READ(mem) > >> > >> // Memcheck normally checks that you do not write unaddressable memory. > >> // This wrapper causes that check to be omitted. > >> VALGRIND_UNCHECKED_MEM_WRITE(mem) > > > > In addition to these, we may want to have a BEGIN/END form, for the > > cases when the access happens in a routine which we can not annotate > > or which may be used in other contexts. > > VALGRIND_IGNORE_READS_BEGIN() > > external_function(pointer_to_uninitialized_but_safe_to_use_memory) > > VALGRIND_IGNORE_READS_END() > > > >>> Example: > >>> > >>> int *p = (int*)malloc(100); > >>> // p is 4-aligned and not initialized > >> > >> Not quite. p is 4-aligned and initialized. *p is unitialized. > > > > ah, yes. > > > > --kcc |
|
From: Konstantin S. <kon...@gm...> - 2009-05-22 09:38:42
|
Hi Nick, Here is my attempt for a patch and a unittest. The first thing you would probably ask is how does this affect the performance of Memcheck. Would you suggest a benchmark to try? Other comments? Thanks, --kcc % g++ -g -DHAVE_IGNORE_ANNOTATIONS memcheck_annotations.cc -I $HOME/valgrind/ann/inst/include && $HOME/valgrind/ann/inst/bin/valgrind -q ./a.out % g++ -g memcheck_annotations.cc -I $HOME/valgrind/ann/inst/include && $HOME/valgrind/ann/inst/bin/valgrind -q ./a.out 2>&1 | head ==16258== Invalid write of size 1 ==16258== at 0x4006D9: int test_memcheck_annotations<signed char>() (memcheck_annotations.cc:16) ==16258== by 0x4006A4: main (memcheck_annotations.cc:31) ==16258== Address 0x58f603a is 0 bytes after a block of size 10 alloc'd ==16258== at 0x4C1C87C: operator new[](unsigned long) (vg_replace_malloc.c:245) ==16258== by 0x4006CC: int test_memcheck_annotations<signed char>() (memcheck_annotations.cc:13) ==16258== by 0x4006A4: main (memcheck_annotations.cc:31) ==16258== ==16258== Invalid read of size 1 ==16258== at 0x4006E4: int test_memcheck_annotations<signed char>() (memcheck_annotations.cc:19) % On Wed, Apr 8, 2009 at 6:25 PM, Konstantin Serebryany <kon...@gm...> wrote: > On Wed, Apr 8, 2009 at 2:07 PM, Nicholas Nethercote > <n.n...@gm...> wrote: >> On Wed, Apr 8, 2009 at 2:20 AM, Konstantin Serebryany >> <kon...@gm...> wrote: >>> >>> Memcheck has client requests such as VALGRIND_MAKE_MEM_DEFINED(mem, size). >>> These requests mark memory as initialized (i.e. safe to read). >>> But there is no annotation that marks a specific memory access as safe. >>> Is that not included intentionally? If yes, what was the reason? >>> If no, do you mind to include such request(s)? >> >> I think the reason is that nobody has required them until now. >> >> I've previously thought about them in one context, involving more >> aggressive checking by Memcheck of a program. Imagine you have a data >> structure that should only be accessed through a small number of >> access functions. You could mark the data structure as unaddressable, >> and then wrap the accesses within the access functions with such >> annotations. That way you would immediately know if any other part of >> your program accessed the data structure not via those access >> functions, which could be due to (a) failure to observe the access >> function discipline, or (b) corrupted pointers or similar. >> >> I thought about doing this by marking the memory as >> addressable-and-defined, doing the read/write, then marking it >> unaddressable again, but your approach is more efficient. So I can see >> these annotations would be useful. Here's an attempt at what they >> would look like: >> >> // Memcheck normally checks that you do not read unaddressable or >> // addressable-but-undefined memory. This wrapper causes that >> // check to be omitted. >> VALGRIND_UNCHECKED_MEM_READ(mem) >> >> // Memcheck normally checks that you do not write unaddressable memory. >> // This wrapper causes that check to be omitted. >> VALGRIND_UNCHECKED_MEM_WRITE(mem) > > In addition to these, we may want to have a BEGIN/END form, for the > cases when the access happens in a routine which we can not annotate > or which may be used in other contexts. > VALGRIND_IGNORE_READS_BEGIN() > external_function(pointer_to_uninitialized_but_safe_to_use_memory) > VALGRIND_IGNORE_READS_END() > > >> >> >>> Example: >>> >>> int *p = (int*)malloc(100); >>> // p is 4-aligned and not initialized >> >> Not quite. p is 4-aligned and initialized. *p is unitialized. > ah, yes. > > --kcc > |
|
From: <sv...@va...> - 2009-05-22 08:12:54
|
Author: njn
Date: 2009-05-22 09:12:46 +0100 (Fri, 22 May 2009)
New Revision: 10106
Log:
DARWIN sync: all the timeval stuff
Modified:
trunk/coregrind/m_syswrap/priv_syswrap-generic.h
trunk/coregrind/m_syswrap/priv_types_n_macros.h
trunk/coregrind/m_syswrap/syswrap-generic.c
trunk/memcheck/tests/x86-linux/scalar.c
trunk/memcheck/tests/x86-linux/scalar.stderr.exp
Modified: trunk/coregrind/m_syswrap/priv_syswrap-generic.h
===================================================================
--- trunk/coregrind/m_syswrap/priv_syswrap-generic.h 2009-05-22 08:07:13 UTC (rev 10105)
+++ trunk/coregrind/m_syswrap/priv_syswrap-generic.h 2009-05-22 08:12:46 UTC (rev 10106)
@@ -252,6 +252,26 @@
extern SysRes ML_(generic_PRE_sys_mmap) ( TId, UW, UW, UW, UW, UW, Off64T );
+#define PRE_timeval_READ(zzname, zzarg) \
+ do { \
+ struct vki_timeval *zztv = (struct vki_timeval *)zzarg; \
+ PRE_FIELD_READ(zzname, zztv->tv_sec); \
+ PRE_FIELD_READ(zzname, zztv->tv_usec); \
+ } while (0)
+#define PRE_timeval_WRITE(zzname, zzarg) \
+ do { \
+ struct vki_timeval *zztv = (struct vki_timeval *)zzarg; \
+ PRE_FIELD_WRITE(zzname, zztv->tv_sec); \
+ PRE_FIELD_WRITE(zzname, zztv->tv_usec); \
+ } while (0)
+#define POST_timeval_WRITE(zzarg) \
+ do { \
+ struct vki_timeval *zztv = (struct vki_timeval *)zzarg; \
+ POST_FIELD_WRITE(zztv->tv_sec); \
+ POST_FIELD_WRITE(zztv->tv_usec); \
+ } while (0)
+
+
#undef TId
#undef UW
#undef SR
Modified: trunk/coregrind/m_syswrap/priv_types_n_macros.h
===================================================================
--- trunk/coregrind/m_syswrap/priv_types_n_macros.h 2009-05-22 08:07:13 UTC (rev 10105)
+++ trunk/coregrind/m_syswrap/priv_types_n_macros.h 2009-05-22 08:12:46 UTC (rev 10106)
@@ -453,6 +453,16 @@
VG_TRACK( post_mem_write, Vg_CoreSysCall, tid, zzaddr, zzlen)
+#define PRE_FIELD_READ(zzname, zzfield) \
+ PRE_MEM_READ(zzname, (UWord)&zzfield, sizeof(zzfield))
+
+#define PRE_FIELD_WRITE(zzname, zzfield) \
+ PRE_MEM_WRITE(zzname, (UWord)&zzfield, sizeof(zzfield))
+
+#define POST_FIELD_WRITE(zzfield) \
+ POST_MEM_WRITE((UWord)&zzfield, sizeof(zzfield))
+
+
#endif // __PRIV_TYPES_N_MACROS_H
/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-generic.c 2009-05-22 08:07:13 UTC (rev 10105)
+++ trunk/coregrind/m_syswrap/syswrap-generic.c 2009-05-22 08:12:46 UTC (rev 10106)
@@ -2129,14 +2129,19 @@
PRE(sys_getitimer)
{
+ struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
PRINT("sys_getitimer ( %ld, %#lx )", ARG1, ARG2);
PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value);
- PRE_MEM_WRITE( "getitimer(value)", ARG2, sizeof(struct vki_itimerval) );
+
+ PRE_timeval_WRITE( "getitimer(&value->it_interval)", &(value->it_interval));
+ PRE_timeval_WRITE( "getitimer(&value->it_value)", &(value->it_value));
}
POST(sys_getitimer)
{
if (ARG2 != (Addr)NULL) {
- POST_MEM_WRITE(ARG2, sizeof(struct vki_itimerval));
+ struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
+ POST_timeval_WRITE( &(value->it_interval) );
+ POST_timeval_WRITE( &(value->it_value) );
}
}
@@ -2146,16 +2151,28 @@
PRE_REG_READ3(long, "setitimer",
int, which,
struct itimerval *, value, struct itimerval *, ovalue);
- if (ARG2 != (Addr)NULL)
- PRE_MEM_READ( "setitimer(value)", ARG2, sizeof(struct vki_itimerval) );
- if (ARG3 != (Addr)NULL)
- PRE_MEM_WRITE( "setitimer(ovalue)", ARG3, sizeof(struct vki_itimerval));
+ if (ARG2 != (Addr)NULL) {
+ struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
+ PRE_timeval_READ( "setitimer(&value->it_interval)",
+ &(value->it_interval));
+ PRE_timeval_READ( "setitimer(&value->it_value)",
+ &(value->it_value));
+ }
+ if (ARG3 != (Addr)NULL) {
+ struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
+ PRE_timeval_WRITE( "setitimer(&ovalue->it_interval)",
+ &(ovalue->it_interval));
+ PRE_timeval_WRITE( "setitimer(&ovalue->it_value)",
+ &(ovalue->it_value));
+ }
}
POST(sys_setitimer)
{
if (ARG3 != (Addr)NULL) {
- POST_MEM_WRITE(ARG3, sizeof(struct vki_itimerval));
+ struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
+ POST_timeval_WRITE( &(ovalue->it_interval) );
+ POST_timeval_WRITE( &(ovalue->it_value) );
}
}
@@ -3046,7 +3063,8 @@
PRINT("sys_gettimeofday ( %#lx, %#lx )", ARG1,ARG2);
PRE_REG_READ2(long, "gettimeofday",
struct timeval *, tv, struct timezone *, tz);
- PRE_MEM_WRITE( "gettimeofday(tv)", ARG1, sizeof(struct vki_timeval) );
+ if (ARG1 != 0)
+ PRE_timeval_WRITE( "gettimeofday(tv)", ARG1 );
if (ARG2 != 0)
PRE_MEM_WRITE( "gettimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
}
@@ -3055,7 +3073,8 @@
{
vg_assert(SUCCESS);
if (RES == 0) {
- POST_MEM_WRITE( ARG1, sizeof(struct vki_timeval) );
+ if (ARG1 != 0)
+ POST_timeval_WRITE( ARG1 );
if (ARG2 != 0)
POST_MEM_WRITE( ARG2, sizeof(struct vki_timezone) );
}
@@ -3066,7 +3085,8 @@
PRINT("sys_settimeofday ( %#lx, %#lx )", ARG1,ARG2);
PRE_REG_READ2(long, "settimeofday",
struct timeval *, tv, struct timezone *, tz);
- PRE_MEM_READ( "settimeofday(tv)", ARG1, sizeof(struct vki_timeval) );
+ if (ARG1 != 0)
+ PRE_MEM_READ( "settimeofday(tv)", ARG1, sizeof(struct vki_timeval) );
if (ARG2 != 0) {
PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
/* maybe should warn if tz->tz_dsttime is non-zero? */
@@ -3632,7 +3652,7 @@
PRE_MEM_READ( "select(exceptfds)",
ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
if (ARG5 != 0)
- PRE_MEM_READ( "select(timeout)", ARG5, sizeof(struct vki_timeval) );
+ PRE_timeval_READ( "select(timeout)", ARG5 );
}
PRE(sys_setgid)
@@ -3895,8 +3915,11 @@
PRINT("sys_utimes ( %#lx(%s), %#lx )", ARG1,(char*)ARG1,ARG2);
PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp);
PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 );
- if (ARG2 != 0)
- PRE_MEM_READ( "utimes(tvp)", ARG2, 2 * sizeof(struct vki_timeval) );
+ if (ARG2 != 0) {
+ PRE_timeval_READ( "utimes(tvp[0])", ARG2 );
+ PRE_timeval_READ( "utimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
+ }
+
}
PRE(sys_acct)
Modified: trunk/memcheck/tests/x86-linux/scalar.c
===================================================================
--- trunk/memcheck/tests/x86-linux/scalar.c 2009-05-22 08:07:13 UTC (rev 10105)
+++ trunk/memcheck/tests/x86-linux/scalar.c 2009-05-22 08:12:46 UTC (rev 10106)
@@ -371,11 +371,11 @@
// __NR_gettimeofday 78
GO(__NR_gettimeofday, "2s 2m");
- SY(__NR_gettimeofday, x0, x0+1); FAIL;
+ SY(__NR_gettimeofday, x0+1, x0+1); FAIL;
// __NR_settimeofday 79
GO(__NR_settimeofday, "2s 2m");
- SY(__NR_settimeofday, x0, x0+1); FAIL;
+ SY(__NR_settimeofday, x0+1, x0+1); FAIL;
// __NR_getgroups 80
GO(__NR_getgroups, "2s 1m");
Modified: trunk/memcheck/tests/x86-linux/scalar.stderr.exp
===================================================================
--- trunk/memcheck/tests/x86-linux/scalar.stderr.exp 2009-05-22 08:07:13 UTC (rev 10105)
+++ trunk/memcheck/tests/x86-linux/scalar.stderr.exp 2009-05-22 08:12:46 UTC (rev 10106)
@@ -978,13 +978,21 @@
Syscall param setitimer(ovalue) contains uninitialised byte(s)
...
-Syscall param setitimer(value) points to unaddressable byte(s)
+Syscall param setitimer(&value->it_interval) points to unaddressable byte(s)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-Syscall param setitimer(ovalue) points to unaddressable byte(s)
+Syscall param setitimer(&value->it_value) points to unaddressable byte(s)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
+Syscall param setitimer(&ovalue->it_interval) points to unaddressable byte(s)
+ ...
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
+Syscall param setitimer(&ovalue->it_value) points to unaddressable byte(s)
+ ...
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
-----------------------------------------------------
105: __NR_getitimer 2s 1m
-----------------------------------------------------
@@ -995,9 +1003,13 @@
Syscall param getitimer(value) contains uninitialised byte(s)
...
-Syscall param getitimer(value) points to unaddressable byte(s)
+Syscall param getitimer(&value->it_interval) points to unaddressable byte(s)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
+Syscall param getitimer(&value->it_value) points to unaddressable byte(s)
+ ...
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
-----------------------------------------------------
106: __NR_stat 2s 2m
-----------------------------------------------------
@@ -3085,9 +3097,13 @@
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-Syscall param utimes(tvp) points to unaddressable byte(s)
+Syscall param utimes(tvp[0]) points to unaddressable byte(s)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
+Syscall param utimes(tvp[1]) points to unaddressable byte(s)
+ ...
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
-----------------------------------------------------
272: __NR_fadvise64_64 n/a
-----------------------------------------------------
|
|
From: <sv...@va...> - 2009-05-22 08:07:25
|
Author: njn
Date: 2009-05-22 09:07:13 +0100 (Fri, 22 May 2009)
New Revision: 10105
Log:
- Don't check first arg of [sg]ettimeofday if NULL
- Make the timeval check messages make more sense
Modified:
branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c
branches/DARWIN/memcheck/tests/x86-linux/scalar.c
branches/DARWIN/memcheck/tests/x86-linux/scalar.stderr.exp
Modified: branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c 2009-05-22 07:59:26 UTC (rev 10104)
+++ branches/DARWIN/coregrind/m_syswrap/syswrap-generic.c 2009-05-22 08:07:13 UTC (rev 10105)
@@ -2219,8 +2219,8 @@
PRINT("sys_getitimer ( %ld, %#lx )", ARG1, ARG2);
PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value);
- PRE_timeval_WRITE( "getitimer(value.it_interval)", &(value->it_interval));
- PRE_timeval_WRITE( "getitimer(value.it_value)", &(value->it_value));
+ PRE_timeval_WRITE( "getitimer(&value->it_interval)", &(value->it_interval));
+ PRE_timeval_WRITE( "getitimer(&value->it_value)", &(value->it_value));
}
POST(sys_getitimer)
@@ -2240,16 +2240,16 @@
struct itimerval *, value, struct itimerval *, ovalue);
if (ARG2 != (Addr)NULL) {
struct vki_itimerval *value = (struct vki_itimerval*)ARG2;
- PRE_timeval_READ( "setitimer(value->it_interval)",
+ PRE_timeval_READ( "setitimer(&value->it_interval)",
&(value->it_interval));
- PRE_timeval_READ( "setitimer(value->it_value)",
+ PRE_timeval_READ( "setitimer(&value->it_value)",
&(value->it_value));
}
if (ARG3 != (Addr)NULL) {
struct vki_itimerval *ovalue = (struct vki_itimerval*)ARG3;
- PRE_timeval_WRITE( "setitimer(ovalue->it_interval)",
+ PRE_timeval_WRITE( "setitimer(&ovalue->it_interval)",
&(ovalue->it_interval));
- PRE_timeval_WRITE( "setitimer(ovalue->it_value)",
+ PRE_timeval_WRITE( "setitimer(&ovalue->it_value)",
&(ovalue->it_value));
}
}
@@ -3172,12 +3172,9 @@
PRINT("sys_gettimeofday ( %#lx, %#lx )", ARG1,ARG2);
PRE_REG_READ2(long, "gettimeofday",
struct timeval *, tv, struct timezone *, tz);
-#if defined(VGO_darwin)
- // GrP fixme linux too?
// GrP fixme does darwin write to *tz anymore?
if (ARG1 != 0)
-#endif
- PRE_timeval_WRITE( "gettimeofday(tv)", ARG1 );
+ PRE_timeval_WRITE( "gettimeofday(tv)", ARG1 );
if (ARG2 != 0)
PRE_MEM_WRITE( "gettimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
}
@@ -3186,11 +3183,8 @@
{
vg_assert(SUCCESS);
if (RES == 0) {
-#if defined(VGO_darwin)
- // GrP fixme linux too?
if (ARG1 != 0)
-#endif
- POST_timeval_WRITE( ARG1 );
+ POST_timeval_WRITE( ARG1 );
if (ARG2 != 0)
POST_MEM_WRITE( ARG2, sizeof(struct vki_timezone) );
}
@@ -3201,7 +3195,8 @@
PRINT("sys_settimeofday ( %#lx, %#lx )", ARG1,ARG2);
PRE_REG_READ2(long, "settimeofday",
struct timeval *, tv, struct timezone *, tz);
- PRE_timeval_READ( "settimeofday(tv)", ARG1 );
+ if (ARG1 != 0)
+ PRE_timeval_READ( "settimeofday(tv)", ARG1 );
if (ARG2 != 0) {
PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
/* maybe should warn if tz->tz_dsttime is non-zero? */
Modified: branches/DARWIN/memcheck/tests/x86-linux/scalar.c
===================================================================
--- branches/DARWIN/memcheck/tests/x86-linux/scalar.c 2009-05-22 07:59:26 UTC (rev 10104)
+++ branches/DARWIN/memcheck/tests/x86-linux/scalar.c 2009-05-22 08:07:13 UTC (rev 10105)
@@ -371,11 +371,11 @@
// __NR_gettimeofday 78
GO(__NR_gettimeofday, "2s 2m");
- SY(__NR_gettimeofday, x0, x0+1); FAIL;
+ SY(__NR_gettimeofday, x0+1, x0+1); FAIL;
// __NR_settimeofday 79
GO(__NR_settimeofday, "2s 2m");
- SY(__NR_settimeofday, x0, x0+1); FAIL;
+ SY(__NR_settimeofday, x0+1, x0+1); FAIL;
// __NR_getgroups 80
GO(__NR_getgroups, "2s 1m");
Modified: branches/DARWIN/memcheck/tests/x86-linux/scalar.stderr.exp
===================================================================
--- branches/DARWIN/memcheck/tests/x86-linux/scalar.stderr.exp 2009-05-22 07:59:26 UTC (rev 10104)
+++ branches/DARWIN/memcheck/tests/x86-linux/scalar.stderr.exp 2009-05-22 08:07:13 UTC (rev 10105)
@@ -978,19 +978,19 @@
Syscall param setitimer(ovalue) contains uninitialised byte(s)
...
-Syscall param setitimer(value->it_interval) points to unaddressable byte(s)
+Syscall param setitimer(&value->it_interval) points to unaddressable byte(s)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-Syscall param setitimer(value->it_value) points to unaddressable byte(s)
+Syscall param setitimer(&value->it_value) points to unaddressable byte(s)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-Syscall param setitimer(ovalue->it_interval) points to unaddressable byte(s)
+Syscall param setitimer(&ovalue->it_interval) points to unaddressable byte(s)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-Syscall param setitimer(ovalue->it_value) points to unaddressable byte(s)
+Syscall param setitimer(&ovalue->it_value) points to unaddressable byte(s)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-----------------------------------------------------
@@ -1003,11 +1003,11 @@
Syscall param getitimer(value) contains uninitialised byte(s)
...
-Syscall param getitimer(value.it_interval) points to unaddressable byte(s)
+Syscall param getitimer(&value->it_interval) points to unaddressable byte(s)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-Syscall param getitimer(value.it_value) points to unaddressable byte(s)
+Syscall param getitimer(&value->it_value) points to unaddressable byte(s)
...
Address 0x........ is not stack'd, malloc'd or (recently) free'd
-----------------------------------------------------
|
|
From: <sv...@va...> - 2009-05-22 07:59:35
|
Author: sewardj
Date: 2009-05-22 08:59:26 +0100 (Fri, 22 May 2009)
New Revision: 10104
Log:
Track core-tool iface changes (w.r.t. tool_{pre,post}_syscall)
committed in r10081/2.
Modified:
branches/DCAS/callgrind/main.c
branches/DCAS/exp-ptrcheck/h_main.c
branches/DCAS/exp-ptrcheck/h_main.h
Modified: branches/DCAS/callgrind/main.c
===================================================================
--- branches/DCAS/callgrind/main.c 2009-05-22 07:29:39 UTC (rev 10103)
+++ branches/DCAS/callgrind/main.c 2009-05-22 07:59:26 UTC (rev 10104)
@@ -867,7 +867,8 @@
#endif
static
-void CLG_(pre_syscalltime)(ThreadId tid, UInt syscallno)
+void CLG_(pre_syscalltime)(ThreadId tid, UInt syscallno,
+ UWord* args, UInt nArgs)
{
if (CLG_(clo).collect_systime) {
#if CLG_MICROSYSTIME
@@ -881,7 +882,8 @@
}
static
-void CLG_(post_syscalltime)(ThreadId tid, UInt syscallno, SysRes res)
+void CLG_(post_syscalltime)(ThreadId tid, UInt syscallno,
+ UWord* args, UInt nArgs, SysRes res)
{
if (CLG_(clo).collect_systime &&
CLG_(current_state).bbcc) {
Modified: branches/DCAS/exp-ptrcheck/h_main.c
===================================================================
--- branches/DCAS/exp-ptrcheck/h_main.c 2009-05-22 07:29:39 UTC (rev 10103)
+++ branches/DCAS/exp-ptrcheck/h_main.c 2009-05-22 07:59:26 UTC (rev 10104)
@@ -2113,7 +2113,8 @@
/*--- System calls ---*/
/*--------------------------------------------------------------------*/
-void h_pre_syscall ( ThreadId tid, UInt sysno )
+void h_pre_syscall ( ThreadId tid, UInt sysno,
+ UWord* args, UInt nArgs )
{
/* we don't do anything at the pre-syscall point */
}
@@ -2447,7 +2448,8 @@
}
-void h_post_syscall ( ThreadId tid, UInt sysno, SysRes res )
+void h_post_syscall ( ThreadId tid, UInt sysno,
+ UWord* args, UInt nArgs, SysRes res )
{
Word i, n;
UWordPair* pair;
Modified: branches/DCAS/exp-ptrcheck/h_main.h
===================================================================
--- branches/DCAS/exp-ptrcheck/h_main.h 2009-05-22 07:29:39 UTC (rev 10103)
+++ branches/DCAS/exp-ptrcheck/h_main.h 2009-05-22 07:59:26 UTC (rev 10104)
@@ -82,8 +82,10 @@
void h_post_reg_write_clientcall(ThreadId tid, PtrdiffT guest_state_offset,
SizeT size, Addr f );
-void h_pre_syscall ( ThreadId tid, UInt syscallno );
-void h_post_syscall ( ThreadId tid, UInt syscallno, SysRes res );
+void h_pre_syscall ( ThreadId tid, UInt syscallno,
+ UWord* args, UInt nArgs );
+void h_post_syscall ( ThreadId tid, UInt syscallno,
+ UWord* args, UInt nArgs, SysRes res );
/* Note that this also does the sg_ instrumentation. */
IRSB* h_instrument ( VgCallbackClosure* closure,
|