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
(21) |
|
2
(19) |
3
(33) |
4
(24) |
5
(18) |
6
(13) |
7
(22) |
8
(21) |
|
9
(38) |
10
(25) |
11
(20) |
12
(27) |
13
(43) |
14
(9) |
15
(19) |
|
16
(37) |
17
(19) |
18
(13) |
19
(11) |
20
(8) |
21
(11) |
22
(25) |
|
23
(21) |
24
(30) |
25
(18) |
26
(11) |
27
(10) |
28
(14) |
29
(40) |
|
30
(24) |
31
(14) |
|
|
|
|
|
|
From: Josef W. <Jos...@gm...> - 2008-03-09 22:15:19
|
Hi, On Sunday 09 March 2008, waseem wrote: > At moment i anticipate it could be done in following two ways. > > 1). inserting some sort of macro in file myTest.C so that when ever we > encounter it we know that following function is an event. This macro would be a Valgrind client request, as I already said before. It needs you to be comfortable with modifying the code to analyze. > 2). or some sort of functionality already provided in VALGRIND 3.3.0 (which > i failed to find out). Nothing "high level". You need to do this manually: Check at instrumentation time, if an instruction enters a given function (event1/2) by using debug info, and insert a callback into the instruction stream to call your own function which does act as needed. If you do not want to hardcode the function names into your tool, you could have a look at command line parsing in callgrind. E.g. there, "--dump-before=<func>" allows to specify a function where profiling result should be dumped before entering. Here, "<func>" can even include wildcards. Josef > > So i hope, my question is much clear now and i will appreciate all sort of > help . > > Thanking you in anticipation for your time and consideration > > With Best Regards > Waseem > |
|
From: Julian S. <js...@ac...> - 2008-03-09 21:48:44
|
> I have ignored the BHL by the comparison of various states as you told.
> But still dealing with BHL is not completely clear to me.
Now that I look again at the MSMHelgrind code, I have to admit I do
not understand the BHL kludges I put in it :-( In particular I cannot
see why msm__handle_read uses add_BHL.
I can only suggest that you ignore what MSMHelgrind does and
figure it out yourself from first principles.
I think what MSMHelgrind tries to do is handle the BHL as if it
was a normal mutex, iow a writer-lock. This is more restrictive
than how the hardware behaves, but at least it is simple. THe
hardware requires a LOCK prefix only for writes or modifies of
shared locations; reading does not require a lock.
The instrumentation function (hg_instrument, instrument_memory_bus_event)
creates calls to evh__bus_{lock,unlock} around every LOCK-prefixed
instruction. And those behave exactly as if the program had
called "pthread_mutex_lock( &__bus_lock )" /
"pthread_mutex_unlock( &__bus_lock )".
This means the bus lock handling is more restrictive than for the
real hardware. It requires readers to hold the lock (iow, to use
a LOCK prefix) even though this is not required by the h/w.
Other than that, I don't think I can tell you anything useful.
If you have any insights, and/or if you can figure out a way to model
the h/w more accurately than described above, I would be interested
to hear. I suggest also playing with tc07_hbl1.c and tc08_hbl2.c
as they are simple programs and the behaviour should be easy
to understand.
J
|
|
From: Julian S. <js...@ac...> - 2008-03-09 21:18:48
|
On Sunday 09 March 2008 14:38, Bart Van Assche wrote: > Hello, > > As far as I understood the libgomp source code directly, libgomp has > its own barrier implementation based on the futex system call. This > means that if I want to support OpenMP in DRD, I have to intercept the > futex system call. sys_futex is only called (iow, the kernel is only involved) when a lock is contended. Since that is in general very rare, monitoring sys_futex will not work as you will miss most inter-thread dependencies. > Is there a better way than adding calls to > appropriate tracking functions in PRE(sys_futex) and POST(sys_futex) > (defined in coregrind/m_syswrap/syswrap-linux.c) ? Patch libgomp as described in the README in the tarball and make sure you configure the gcc build with --disable-linux-futex. J |
|
From: Julian S. <js...@ac...> - 2008-03-09 21:15:24
|
> > > Which modifications do we need to use Helgrind on OpenMP. Is there > > > any patch to use? > > > > The attached tarball gives details of how to use GNU OpenMP in > > gcc-4.2.3. > Is it correct that OpenMP uses a lot of POSIX threads barriers ? It uses a lot of barriers but these are not done using pthread_barrier_wait as that is too restrictive -- it uses its own implementation. As detailed in the README in the tarball I posted. So in fact, providing you follow the directions in the README, it is possible to successfully check programs compiled by gcc-4.2.3 using Helgrind. > that case I think you better verify the barrier implementation in > Helgrind first. Helgrind doesn't support pthread barriers right now, although that will change in future -- should be relatively straightforward. J |
|
From: <sv...@va...> - 2008-03-09 21:09:02
|
Author: sewardj
Date: 2008-03-09 21:09:05 +0000 (Sun, 09 Mar 2008)
New Revision: 7625
Log:
A bit of unrollery in the SVal cache writeback code. Hey, it's a
no-brainer and is worth about 1.5% on one test.
Modified:
branches/HGDEV/helgrind/hg_main.c
Modified: branches/HGDEV/helgrind/hg_main.c
===================================================================
--- branches/HGDEV/helgrind/hg_main.c 2008-03-09 20:44:20 UTC (rev 7624)
+++ branches/HGDEV/helgrind/hg_main.c 2008-03-09 21:09:05 UTC (rev 7625)
@@ -4231,10 +4231,37 @@
if (lineZ->dict[3] == 0) { lineZ->dict[3] = sv; j = 3; goto dict_ok; }
break; /* we'll have to use the f rep */
dict_ok:
- for (m = csvals[k].count; m > 0; m--) {
- write_twobit_array( lineZ->ix2s, i, j );
- i++;
+ m = csvals[k].count;
+ if (m == 8) {
+ write_twobit_array( lineZ->ix2s, i+0, j );
+ write_twobit_array( lineZ->ix2s, i+1, j );
+ write_twobit_array( lineZ->ix2s, i+2, j );
+ write_twobit_array( lineZ->ix2s, i+3, j );
+ write_twobit_array( lineZ->ix2s, i+4, j );
+ write_twobit_array( lineZ->ix2s, i+5, j );
+ write_twobit_array( lineZ->ix2s, i+6, j );
+ write_twobit_array( lineZ->ix2s, i+7, j );
+ i += 8;
}
+ else if (m == 4) {
+ write_twobit_array( lineZ->ix2s, i+0, j );
+ write_twobit_array( lineZ->ix2s, i+1, j );
+ write_twobit_array( lineZ->ix2s, i+2, j );
+ write_twobit_array( lineZ->ix2s, i+3, j );
+ i += 4;
+ }
+ else if (m == 1) {
+ write_twobit_array( lineZ->ix2s, i+0, j );
+ i += 1;
+ }
+ else if (m == 2) {
+ write_twobit_array( lineZ->ix2s, i+0, j );
+ write_twobit_array( lineZ->ix2s, i+1, j );
+ i += 2;
+ }
+ else {
+ tl_assert(0); /* 8 4 2 or 1 are the only legitimate values for m */
+ }
}
|
|
From: waseem <exa...@gm...> - 2008-03-09 20:59:56
|
>
> You can define a client request for your tool, and insert this client
> request at the beginning of the pro3 function. Or am I missing something
> here?
>
> Josef
>
> >
>
>
> Dear Josef ,
First and foremost I am really grateful to you for your reply. It
seems that i could not be able to present my question properly, so therefore
i am again presenting this question to the forum. Lets consider following
diagram for a while and then i will ask the question.
Our Tool
program we are analyzing ( myTest.C )
|
| | |
\/ \/
%%%%%%%%%%%%%%%%%%%%%
|------------------------------------------
% %
| 26: int main(){
% %
| 27:
% %%%%%%%%%%%%%% | 28: fun1();
% % %
| 29: fun2();
% % MEM CHECK % |
30: fun3();
% % %
| 31:
% %%%%%%%%%%%%%% | 32: event1();
%
% | 33:
% %%%%%%%%%%%%%% | 34: fun1();
% % %
| 35: fun1();
% % CALL GRIND % |
36: fun2();
% % %
| 37:
% %%%%%%%%%%%%%% | 38: event2();
% VALGRIND % | 39:
% /\ %%%%%%%%%%%%%% | 40: fun1();
% | % %
| 41:
% ------------> % EMBLA % |
42: event1();
% % %
| 43:
% %%%%%%%%%%%%%% | 44: funX();
%
% | 45:
% %%%%%%%%%%%%%% | 46: event1();
% % %
| 47:
% % OTHER_TOOL % | 48:
% % %
| 49: return 0;
% %%%%%%%%%%%%%% | 50: }
%
% | 51:
%
% | 52:
%%%%%%%%%%%%%%%%%%%%%
|-------------------------------------------
In this scenario I am working with EMBLA which uses VALGRIND,
so lets asume we are analyzing myTest.C file using tool. In file
myTest.C there are lot of function calls but at line 32, 38, 42 and 46 there
are function calls that corresponds to certain events. So I wanted a
suitable method that tells my tool Embla that this function call correspond
to some event (which are mentioned on line 32, 38, 42 and 46), so that Embla
will know that it has to profile them differently.
At moment i anticipate it could be done in following two ways.
1). inserting some sort of macro in file myTest.C so that when ever we
encounter it we know that following function is an event.
2). or some sort of functionality already provided in VALGRIND 3.3.0 (which
i failed to find out).
So i hope, my question is much clear now and i will appreciate all sort of
help .
Thanking you in anticipation for your time and consideration
With Best Regards
Waseem
--
With Regards
Waseem
|
|
From: <sv...@va...> - 2008-03-09 20:44:17
|
Author: sewardj
Date: 2008-03-09 20:44:20 +0000 (Sun, 09 Mar 2008)
New Revision: 7624
Log:
Remove the .mbHasShared hint bits SecMaps. They are now pointless.
Removing them also reduces the cost of writing cache lines back to the
backing store (cacheline_wback).
Modified:
branches/HGDEV/helgrind/hg_main.c
Modified: branches/HGDEV/helgrind/hg_main.c
===================================================================
--- branches/HGDEV/helgrind/hg_main.c 2008-03-09 20:20:37 UTC (rev 7623)
+++ branches/HGDEV/helgrind/hg_main.c 2008-03-09 20:44:20 UTC (rev 7624)
@@ -47,6 +47,21 @@
- Have something like mk_SHVAL_fail instead of merely asserting
+ - More comments re deletion of memory containing Locks.
+
+ New proposal: Locks are never deleted, and entries never removed
+ from map_locks. Instead have a .dormant bit in Lock indicating
+ that they are have been freed by the user.
+
+ (Later): remove map_locks. Instead, on each SecMap have a set of
+ Locks which are known to live, or have lived, in that SecMap
+ (that is, their GA is in that SecMap).
+
+ This effectively means that we allocate one Lock entry for every
+ address that the client uses for a lock, and remember it forever.
+
+ - Fix command line ordering assumptions for --ignore-i= vs --ignore-n=
+
STUFF I DON'T UNDERSTAND:
Make sense of ignore-n/ignore-i. What exactly does this do?
@@ -487,7 +502,6 @@
struct {
UInt magic;
Bool mbHasLocks; /* hint: any locks in range? safe: True */
- Bool mbHasShared; /* hint: any ShM/ShR states in range? safe: True */
CacheLineZ linesZ[N_SECMAP_ZLINES];
CacheLineF* linesF;
UInt linesF_size;
@@ -2602,7 +2616,6 @@
tl_assert(sm);
sm->magic = SecMap_MAGIC;
sm->mbHasLocks = False; /* dangerous */
- sm->mbHasShared = False; /* dangerous */
for (i = 0; i < N_SECMAP_ZLINES; i++) {
sm->linesZ[i].dict[0] = SHVAL_New;
sm->linesZ[i].dict[1] = 0; /* completely invalid SHVAL */
@@ -2675,27 +2688,7 @@
sm->mbHasLocks = b;
}
-static void shmem__set_mbHasShared ( Addr a, Bool b )
-{
- SecMap* sm;
- Addr aKey = shmem__round_to_SecMap_base(a);
- tl_assert(b == False || b == True);
- // avoid creating a SecMap for memory that we ignore.
- if (b == False && clo_ignore_n != 1 && address_may_be_ignored(a)) return;
- if (HG_(lookupFM)( map_shmem,
- NULL/*keyP*/, (Word*)&sm, (Word)aKey )) {
- /* Found; address of SecMap is in sm */
- } else {
- /* create a new one */
- sm = shmem__alloc_SecMap();
- tl_assert(sm);
- HG_(addToFM)( map_shmem, (Word)aKey, (Word)sm );
- }
- sm->mbHasShared = b;
-}
-
-
/*----------------------------------------------------------------*/
/*--- Sanity checking the data structures ---*/
/*----------------------------------------------------------------*/
@@ -2956,7 +2949,7 @@
while (HG_(nextIterFM)( map_shmem, &smga, (Word*)&sm )) {
SecMapIter itr;
SVal* sv_p = NULL;
- Bool mbHasShared = False;
+ //Bool mbHasShared = False;
//Bool allNoAccess = True;
if (!is_sane_SecMap(sm)) BAD("1");
// sm properly aligned
@@ -2965,8 +2958,8 @@
initSecMapIter( &itr );
while (stepSecMapIter( &sv_p, &itr, sm )) {
SVal sv = *sv_p;
- if (is_SHVAL_Shared(sv))
- mbHasShared = True;
+ //if (is_SHVAL_Shared(sv))
+ // mbHasShared = True;
//if (!is_SHVAL_NoAccess(sv))
// allNoAccess = False;
@@ -3004,7 +2997,7 @@
}
} /* iterating over a SecMap */
// Check essential safety property
- if (mbHasShared && !sm->mbHasShared) BAD("13");
+ //if (mbHasShared && !sm->mbHasShared) BAD("13");
// This is optional - check that destroyed memory has its hint
// bits cleared. NB won't work properly unless full, eager
// GCing of SecMaps is implemented
@@ -4114,12 +4107,11 @@
typedef struct { UChar count; SVal sval; } CountedSVal;
static
-Bool sequentialise_CacheLine ( /*OUT*/CountedSVal* dst,
+void sequentialise_CacheLine ( /*OUT*/CountedSVal* dst,
/*OUT*/Word* dstUsedP,
Word nDst, CacheLine* src )
{
Word tno, cloff, dstUsed;
- Bool anyShared = False;
tl_assert(nDst == N_LINE_ARANGE);
dstUsed = 0;
@@ -4130,9 +4122,7 @@
/* sequentialise the tree described by (descr,tree). */
# define PUT(_n,_v) \
- do { if (is_SHVAL_Shared(_v)) \
- anyShared = True; \
- dst[dstUsed ].count = (_n); \
+ do { dst[dstUsed ].count = (_n); \
dst[dstUsed++].sval = (_v); \
} while (0)
@@ -4168,7 +4158,6 @@
tl_assert(dstUsed <= nDst);
*dstUsedP = dstUsed;
- return anyShared;
}
/* Write the cacheline 'wix' to backing store. Where it ends up
@@ -4176,7 +4165,6 @@
static __attribute__((noinline)) void cacheline_wback ( UWord wix )
{
Word i, j, k, m;
- Bool anyShared = False;
Addr tag;
SecMap* sm;
CacheLine* cl;
@@ -4214,8 +4202,8 @@
tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
csvalsUsed = -1;
- anyShared = sequentialise_CacheLine( csvals, &csvalsUsed,
- N_LINE_ARANGE, cl );
+ sequentialise_CacheLine( csvals, &csvalsUsed,
+ N_LINE_ARANGE, cl );
tl_assert(csvalsUsed >= 1 && csvalsUsed <= N_LINE_ARANGE);
if (0) VG_(printf)("%lu ", csvalsUsed);
@@ -4284,8 +4272,8 @@
stats__cache_F_wbacks++;
}
- if (anyShared)
- sm->mbHasShared = True;
+ //if (anyShared)
+ // sm->mbHasShared = True;
/* mb_tidy_one_cacheline(); */
}
@@ -5320,7 +5308,7 @@
if (firstA <= sma && sma + N_SECMAP_ARANGE - 1 <= lastA) {
/* Yes. Clear the hint bits. */
shmem__set_mbHasLocks( sma, False );
- shmem__set_mbHasShared( sma, False );
+ //shmem__set_mbHasShared( sma, False );
}
}
@@ -8971,13 +8959,17 @@
else if (VG_CLO_STREQ(arg, "--happens-before=all"))
clo_happens_before = 2;
+ /* FIXME this is bad. It assumes that --ignore-n= occurs before
+ --ignore-i= on the command line. */
else if (VG_CLO_STREQN(11, arg, "--ignore-n=")) {
clo_ignore_n = VG_(atoll)(&arg[11]);
- tl_assert(clo_ignore_n == 0 || (clo_ignore_n > 0 && clo_ignore_i < clo_ignore_n));
+ tl_assert(clo_ignore_n == 0 || (clo_ignore_n > 0
+ && clo_ignore_i < clo_ignore_n));
}
else if (VG_CLO_STREQN(11, arg, "--ignore-i=")) {
clo_ignore_i = VG_(atoll)(&arg[11]);
- tl_assert(clo_ignore_n == 0 || (clo_ignore_n > 0 && clo_ignore_i < clo_ignore_n));
+ tl_assert(clo_ignore_n == 0 || (clo_ignore_n > 0
+ && clo_ignore_i < clo_ignore_n));
}
else if (VG_CLO_STREQ(arg, "--gen-vcg=no"))
|
|
From: <sv...@va...> - 2008-03-09 20:20:37
|
Author: sewardj
Date: 2008-03-09 20:20:37 +0000 (Sun, 09 Mar 2008)
New Revision: 7623
Log:
Get rid of the NoAccess ShVal state. It's just a time waster and we
don't even emit any warnings when memory in NoAccess state is
accessed, so it was a time waster with no purpose.
Modified:
branches/HGDEV/helgrind/hg_main.c
Modified: branches/HGDEV/helgrind/hg_main.c
===================================================================
--- branches/HGDEV/helgrind/hg_main.c 2008-03-09 20:04:31 UTC (rev 7622)
+++ branches/HGDEV/helgrind/hg_main.c 2008-03-09 20:20:37 UTC (rev 7623)
@@ -45,6 +45,8 @@
all lines become dirty and have to be written back. Quantify.
(I think they are not present anyway)
+ - Have something like mk_SHVAL_fail instead of merely asserting
+
STUFF I DON'T UNDERSTAND:
Make sense of ignore-n/ignore-i. What exactly does this do?
@@ -228,9 +230,6 @@
Original Eraser paper also says "all active locks".
*/
-// Major stuff to fix:
-// - reader-writer locks
-
/* Thread async exit:
remove the map_threads entry
@@ -392,14 +391,14 @@
}
Segment;
-/**
- This structure contains data from
- VG_USERREQ__HG_BENIGN_RACE or VG_USERREQ__HG_EXPECT_RACE client request.
- These two client requests are similar: they both suppress reports about a
- data race. The only difference is that for VG_USERREQ__HG_EXPECT_RACE
- helgrind will complain if the race was not detected (useful for unit tests).
-*/
+/* This structure contains data from VG_USERREQ__HG_BENIGN_RACE or
+ VG_USERREQ__HG_EXPECT_RACE client request.
+
+ These two client requests are similar: they both suppress reports
+ about a data race. The only difference is that for
+ VG_USERREQ__HG_EXPECT_RACE helgrind will complain if the race was
+ not detected (useful for unit tests). */
typedef
struct {
Addr ptr; ///< Pointer from the client request.
@@ -994,52 +993,7 @@
return sm != NULL && sm->magic == SecMap_MAGIC;
}
-/* Shadow value encodings:
- 11 WordSetID:TSID_BITS WordSetID:LSID_BITS ShM thread-set lock-set
- 10 WordSetID:TSID_BITS WordSetID:LSID_BITS ShR thread-set lock-set
- 01 TSegmentID:30 Excl thread-segment
- 00 0--(20)--0 10 0000 0000 New
- 00 0--(20)--0 01 0000 0000 NoAccess
- 00 0--(20)--0 00 0000 0000 Invalid
-
- TSID_BITS + LSID_BITS must equal 30.
- The elements in thread sets are Thread*, casted to Word.
- The elements in lock sets are Lock*, casted to Word.
-*/
-
-#define N_LSID_BITS 17
-#define N_LSID_MASK ((1 << (N_LSID_BITS)) - 1)
-#define N_LSID_SHIFT 0
-
-#define N_TSID_BITS (30 - (N_LSID_BITS))
-#define N_TSID_MASK ((1 << (N_TSID_BITS)) - 1)
-#define N_TSID_SHIFT (N_LSID_BITS)
-
-static inline Bool is_sane_WordSetID_LSet ( WordSetID wset ) {
- return wset >= 0 && wset <= N_LSID_MASK;
-}
-static inline Bool is_sane_WordSetID_TSet ( WordSetID wset ) {
- return wset >= 0 && wset <= N_TSID_MASK;
-}
-
-
-__attribute__((noinline))
-__attribute__((noreturn))
-static void mk_SHVAL_fail ( WordSetID tset, WordSetID lset, HChar* who ) {
- VG_(printf)("\n");
- VG_(printf)("Helgrind: Fatal internal error -- cannot continue.\n");
- VG_(printf)("Helgrind: mk_SHVAL_ShR(tset=%d,lset=%d): FAILED\n",
- (Int)tset, (Int)lset);
- VG_(printf)("Helgrind: max allowed tset=%d, lset=%d\n",
- (Int)N_TSID_MASK, (Int)N_LSID_MASK);
- VG_(printf)("Helgrind: program has too many thread "
- "sets or lock sets to track.\n");
- tl_assert(0);
-}
-
-
-
//
// SVal:
// 10SSSSSSSSSSSSSSSSSSSSSSSSSSrrrrrrrrrrrrLLLLLLLLLLLLLLLLLLLLLLLL Read
@@ -1048,7 +1002,6 @@
//
// 0100000000000000000000000000000000000000000000000000000000000000 Race
// 0000000000000000000000000000000000000000000000000000001000000000 New
-// 0000000000000000000000000000000000000000000000000000000100000000 NoAccess
// 0000000000000000000000000000000000000000000000000000000000000000 Invalid
// \______________________________64______________________________/
//
@@ -1068,11 +1021,10 @@
//------------- segment set, lock set --------------
-#define SEGMENT_SET_BITS 26
-#define LOCK_SET_BITS 24
+#define N_SEG_SEG_BITS 26
+#define N_LOCK_SET_BITS 24
#define SHVAL_New ((SVal)(2<<8))
-#define SHVAL_NoAccess ((SVal)(1<<8))
#define SHVAL_Invalid ((SVal)(0))
#define SHVAL_Race ((SVal)(1ULL << 62))
@@ -1080,11 +1032,11 @@
typedef WordSetID LockSet; /* UInt */
static inline Bool SS_valid (SegmentSet ss) {
- return ss < (1 << SEGMENT_SET_BITS);
+ return ss < (1 << N_SEG_SEG_BITS);
}
static inline Bool SS_is_singleton (SegmentSet ss) {
- return (ss & (1 << (SEGMENT_SET_BITS-1))) != 0;
+ return (ss & (1 << (N_SEG_SEG_BITS-1))) != 0;
}
static inline UWord SS_get_size (SegmentSet ss) {
@@ -1096,7 +1048,7 @@
static inline SegmentSet SS_mk_singleton (SegmentID ss) {
if (SCE_SVALS)
tl_assert(SEG_id_is_sane(ss));
- ss |= (1 << (SEGMENT_SET_BITS-1));
+ ss |= (1 << (N_SEG_SEG_BITS-1));
if (SCE_SVALS)
tl_assert(SS_is_singleton(ss));
return ss;
@@ -1104,13 +1056,13 @@
static inline SegmentID SS_get_singleton (SegmentSet ss) {
tl_assert(SS_is_singleton(ss));
- ss &= ~(1 << (SEGMENT_SET_BITS-1));
+ ss &= ~(1 << (N_SEG_SEG_BITS-1));
tl_assert(SEG_id_is_sane(ss));
return ss;
}
static inline SegmentID SS_get_singleton_UNCHECKED (SegmentSet ss) {
- ss &= ~(1 << (SEGMENT_SET_BITS-1));
+ ss &= ~(1 << (N_SEG_SEG_BITS-1));
if (SCE_SVALS)
tl_assert(SEG_id_is_sane(ss));
return ss;
@@ -1126,7 +1078,7 @@
}
static inline Bool LS_valid (LockSet ls) {
- return ls < (1 << LOCK_SET_BITS);
+ return ls < (1 << N_LOCK_SET_BITS);
}
static inline SVal mk_SHVAL_RW (Bool is_w, SegmentSet ss, LockSet ls) {
@@ -1137,7 +1089,7 @@
}
res = (1ULL << 63)
| ((SVal)is_w << 62)
- | ((SVal)ss << (62-SEGMENT_SET_BITS))
+ | ((SVal)ss << (62-N_SEG_SEG_BITS))
| ((SVal)ls);
// VG_(printf)("XX %llx\n", res);
return res;
@@ -1151,15 +1103,15 @@
static inline SegmentSet get_SHVAL_SS (SVal sv) {
SegmentSet ss;
- Int shift = 62 - SEGMENT_SET_BITS;
- ULong mask = (1 << SEGMENT_SET_BITS) - 1;
+ Int shift = 62 - N_SEG_SEG_BITS;
+ ULong mask = (1 << N_SEG_SEG_BITS) - 1;
ss = (sv >> shift) & mask;
tl_assert(SS_valid(ss));
return ss;
}
static inline LockSet get_SHVAL_LS (SVal sv) {
LockSet ls;
- ls = sv & ((1ULL << LOCK_SET_BITS) - 1);
+ ls = sv & ((1ULL << N_LOCK_SET_BITS) - 1);
tl_assert(LS_valid(ls));
return ls;
}
@@ -1179,13 +1131,12 @@
return is_SHVAL_RW(sv) && !SS_is_singleton(get_SHVAL_SS(sv));
}
-static inline Bool is_SHVAL_New (SVal sv) {return sv == SHVAL_New;}
-static inline Bool is_SHVAL_NoAccess(SVal sv) {return sv == SHVAL_NoAccess;}
-static inline Bool is_SHVAL_Race (SVal sv) {return sv == SHVAL_Race;}
+static inline Bool is_SHVAL_New (SVal sv) {return sv == SHVAL_New;}
+static inline Bool is_SHVAL_Race (SVal sv) {return sv == SHVAL_Race;}
static inline Bool is_SHVAL_valid ( SVal sv) {
- return is_SHVAL_RW(sv) || is_SHVAL_Race(sv)
- || is_SHVAL_New(sv) || is_SHVAL_NoAccess(sv);
+ return is_SHVAL_RW(sv) || is_SHVAL_New(sv)
+ || is_SHVAL_Race(sv);
}
@@ -1386,8 +1337,6 @@
VG_(memset)(buf, 0, nBuf);
if (is_SHVAL_New(sv)) {
VG_(sprintf)(buf, "%s", "New");
- } else if (is_SHVAL_NoAccess(sv)) {
- VG_(sprintf)(buf, "%s", "NoAccess");
} else if (is_SHVAL_Race(sv)) {
VG_(sprintf)(buf, "%s", "Race");
} else if (is_SHVAL_RW(sv)) {
@@ -2655,7 +2604,7 @@
sm->mbHasLocks = False; /* dangerous */
sm->mbHasShared = False; /* dangerous */
for (i = 0; i < N_SECMAP_ZLINES; i++) {
- sm->linesZ[i].dict[0] = SHVAL_NoAccess;
+ sm->linesZ[i].dict[0] = SHVAL_New;
sm->linesZ[i].dict[1] = 0; /* completely invalid SHVAL */
sm->linesZ[i].dict[2] = 0;
sm->linesZ[i].dict[3] = 0;
@@ -2910,7 +2859,7 @@
// FIXME: this could legitimately arise from a buggy guest
// that attempts to lock in (eg) freed memory. Detect this
// and warn about it in the pre/post-mutex-lock event handler.
- if (is_SHVAL_NoAccess(shadow_mem_get8(lk->guestaddr))) BAD("5");
+ //if (is_SHVAL_NoAccess(shadow_mem_get8(lk->guestaddr))) BAD("5");
// look at all threads mentioned as holders of this lock. Ensure
// this lock is mentioned in their locksets.
if (lk->heldBy) {
@@ -3008,7 +2957,7 @@
SecMapIter itr;
SVal* sv_p = NULL;
Bool mbHasShared = False;
- Bool allNoAccess = True;
+ //Bool allNoAccess = True;
if (!is_sane_SecMap(sm)) BAD("1");
// sm properly aligned
if (smga != shmem__round_to_SecMap_base(smga)) BAD("2");
@@ -3018,8 +2967,8 @@
SVal sv = *sv_p;
if (is_SHVAL_Shared(sv))
mbHasShared = True;
- if (!is_SHVAL_NoAccess(sv))
- allNoAccess = False;
+ //if (!is_SHVAL_NoAccess(sv))
+ // allNoAccess = False;
if (is_SHVAL_RW(sv)) {
LockSet LS = get_SHVAL_LS(sv);
@@ -3046,7 +2995,7 @@
if (!is_sane_LockN(lk)) BAD("10");
}
}
- else if (is_SHVAL_NoAccess(sv) || is_SHVAL_New(sv) || is_SHVAL_Race(sv)) {
+ else if (is_SHVAL_New(sv) || is_SHVAL_Race(sv)) {
/* nothing to check */
}
else {
@@ -3126,8 +3075,6 @@
static UWord stats__msm_W_to_W = 0;
static UWord stats__msm_New_to_W = 0;
static UWord stats__msm_New_to_R = 0;
-static UWord stats__msm_wr_NoAccess = 0;
-static UWord stats__msm_rd_NoAccess = 0;
static UWord stats__msm_oldSS_single = 0;
static UWord stats__msm_oldSS_multi = 0;
@@ -3540,14 +3487,6 @@
goto done;
}
- // NoAccess
- if (is_SHVAL_NoAccess(sv_old)) {
- // TODO: complain
- stats__msm_wr_NoAccess++;
- sv_new = sv_old;
- goto done;
- }
-
/*NOTREACHED*/
tl_assert(0);
@@ -3686,14 +3625,6 @@
goto done;
}
- // NoAccess
- if (is_SHVAL_NoAccess(sv_old)) {
- // TODO: complain
- stats__msm_rd_NoAccess++;
- sv_new = sv_old;
- goto done;
- }
-
/*NOTREACHED*/
tl_assert(0);
@@ -5380,15 +5311,9 @@
if (len > 0 && firstA <= clo_trace_addr && clo_trace_addr <= lastA) {
SVal sv_old = shadow_mem_get8( clo_trace_addr );
msm__show_state_change( thr, firstA, (Int)len, 'p',
- sv_old, SHVAL_NoAccess );
+ sv_old, SHVAL_New );
}
}
- shadow_mem_modify_range( thr, firstA, len,
- shadow_mem_set8,
- shadow_mem_set16,
- shadow_mem_set32,
- shadow_mem_set64,
- SHVAL_NoAccess/*opaque*/ );
for (sma = firstSM; sma <= lastSM; sma += N_SECMAP_ARANGE) {
/* Is this sm entirely within the deleted range? */
@@ -5476,8 +5401,15 @@
map_locks_delete(lk->guestaddr);
unset_mu_is_cv(lk->guestaddr);
/* release storage (incl. associated .heldBy Bag) */
+ /* XXX NO: we must let locks live forever now. Consider this:
+ client frees memory containing a lock. However, a SVal
+ could reference a LockSet which references this Lock. If
+ we free the Lock then we have a dangling pointer. Since
+ scanning all shadow memory so as to remove this Lock from
+ all LockSets is unfeasibly expensive, it's simpler just to
+ let the lock live forever. */
{ Lock* tmp = lk->admin;
- del_LockN(lk);
+ //del_LockN(lk);
lk = tmp;
}
}
@@ -9221,8 +9153,6 @@
stats__msm_W_to_R, stats__msm_W_to_W);
VG_(printf)(" msm: %,12lu %,12lu New_to_R, New_to_W\n",
stats__msm_New_to_R, stats__msm_New_to_W);
- VG_(printf)(" msm: %,12lu %,12lu rd_NoAccess, wr_NoAccess\n",
- stats__msm_rd_NoAccess, stats__msm_rd_NoAccess);
VG_(printf)(" msm: %,12lu %,12lu oldSS_single, oldSS_multi\n",
stats__msm_oldSS_single, stats__msm_oldSS_multi);
|
|
From: <sv...@va...> - 2008-03-09 20:04:35
|
Author: bart
Date: 2008-03-09 20:04:31 +0000 (Sun, 09 Mar 2008)
New Revision: 7622
Log:
More cleanup.
Modified:
trunk/exp-drd/tests/matinv_openmp.c
Modified: trunk/exp-drd/tests/matinv_openmp.c
===================================================================
--- trunk/exp-drd/tests/matinv_openmp.c 2008-03-09 19:21:14 UTC (rev 7621)
+++ trunk/exp-drd/tests/matinv_openmp.c 2008-03-09 20:04:31 UTC (rev 7622)
@@ -25,13 +25,6 @@
typedef double elem_t;
-/********************/
-/* Local variables. */
-/********************/
-
-static int s_nthread;
-
-
/*************************/
/* Function definitions. */
/*************************/
@@ -264,8 +257,7 @@
double ratio;
matrix_size = (argc > 1) ? atoi(argv[1]) : 3;
- s_nthread = (argc > 2) ? atoi(argv[2]) : 3;
- silent = (argc > 3) ? atoi(argv[3]) : 0;
+ silent = (argc > 2) ? atoi(argv[2]) : 0;
eps = epsilon();
a = new_matrix(matrix_size, matrix_size);
@@ -280,7 +272,7 @@
printf("error = %g; epsilon = %g; error / (epsilon * n) = %g\n",
error, eps, ratio);
}
- if (ratio < 100)
+ if (isfinite(ratio) && ratio < 100)
printf("Error within bounds.\n");
else
printf("Error out of bounds.\n");
|
|
From: Bart V. A. <bar...@gm...> - 2008-03-09 20:03:06
|
On Tue, Mar 4, 2008 at 7:18 PM, Ali Jannesari <a.j...@gm...> wrote: > Actually I am interested to compare MSMunika and MSMhelgrind on some > benchmarks and student projects which have used OpenMP. Hello Ali, I'm interested to learn which compiler and which compiler version you use for compiling OpenMP programs ? I'm not sure the gcc 4.2.3 implementation of libgomp is race-free. See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35517. Bart. |
|
From: <sv...@va...> - 2008-03-09 19:21:10
|
Author: bart
Date: 2008-03-09 19:21:14 +0000 (Sun, 09 Mar 2008)
New Revision: 7621
Log:
Added NPTL-0.60 suppression patterns.
Modified:
trunk/glibc-2.X-drd.supp
Modified: trunk/glibc-2.X-drd.supp
===================================================================
--- trunk/glibc-2.X-drd.supp 2008-03-09 19:20:27 UTC (rev 7620)
+++ trunk/glibc-2.X-drd.supp 2008-03-09 19:21:14 UTC (rev 7621)
@@ -113,6 +113,14 @@
{
pthread
exp-drd:ConflictingAccess
+ fun:clone
+ fun:create_thread
+ fun:pthread_create*
+ fun:pthread_create*
+}
+{
+ pthread
+ exp-drd:ConflictingAccess
obj:/lib*/libc-*.so
fun:__libc_thread_freeres
fun:start_thread
@@ -217,6 +225,21 @@
{
pthread
exp-drd:ConflictingAccess
+ fun:allocate_stack
+ fun:pthread_create*
+ fun:pthread_create*
+}
+{
+ pthread
+ exp-drd:ConflictingAccess
+ fun:get_cached_stack
+ fun:allocate_stack
+ fun:pthread_create*
+ fun:pthread_create*
+}
+{
+ pthread
+ exp-drd:ConflictingAccess
fun:__deallocate_stack
}
{
|
|
From: <sv...@va...> - 2008-03-09 19:20:25
|
Author: bart Date: 2008-03-09 19:20:27 +0000 (Sun, 09 Mar 2008) New Revision: 7620 Log: Added yet another output variant. Added: trunk/exp-drd/tests/tc20_verifywrap2.stderr.exp-glibc2.3-b Modified: trunk/exp-drd/tests/Makefile.am Modified: trunk/exp-drd/tests/Makefile.am =================================================================== --- trunk/exp-drd/tests/Makefile.am 2008-03-09 18:46:07 UTC (rev 7619) +++ trunk/exp-drd/tests/Makefile.am 2008-03-09 19:20:27 UTC (rev 7620) @@ -165,6 +165,7 @@ tc20_verifywrap.vgtest \ tc20_verifywrap2.stderr.exp \ tc20_verifywrap2.stderr.exp-glibc2.3 \ + tc20_verifywrap2.stderr.exp-glibc2.3-b \ tc20_verifywrap2.stderr.exp-linuxthreads \ tc20_verifywrap2.vgtest \ tc21_pthonce.stderr.exp \ Added: trunk/exp-drd/tests/tc20_verifywrap2.stderr.exp-glibc2.3-b =================================================================== --- trunk/exp-drd/tests/tc20_verifywrap2.stderr.exp-glibc2.3-b (rev 0) +++ trunk/exp-drd/tests/tc20_verifywrap2.stderr.exp-glibc2.3-b 2008-03-09 19:20:27 UTC (rev 7620) @@ -0,0 +1,138 @@ + + + +------ This is output for < glibc 2.4 ------ + +---------------- pthread_create/join ---------------- + +Conflicting store by thread 1 at 0x........ size 2 + at 0x........: main (tc20_verifywrap.c:78) +Location 0x........ is 0 bytes inside global var "unprotected" +declared at tc20_verifywrap.c:27 +Other segment start (thread 2) + (thread finished, call stack no longer available) +Other segment end (thread 2) + (thread finished, call stack no longer available) + +---------------- pthread_mutex_lock et al ---------------- + +[1/1] mutex_init invalid mutex 0x........ + +Not a mutex + at 0x........: pthread_mutex_init (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:92) +[1/1] mutex_init mutex 0x........ +[1/1] pre_mutex_lock mutex 0x........ rc 0 owner 0 +[1/1] post_mutex_lock mutex 0x........ rc 0 owner 0 +[1/1] mutex_destroy mutex 0x........ + +Destroying locked mutex: mutex 0x........, recursion count 1, owner 1. + at 0x........: pthread_mutex_destroy (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:102) + +make pthread_mutex_lock fail: skipped on glibc < 2.4 + +[1/1] pre_mutex_lock (?) 0x........ rc 0 owner 0 + +Not a mutex + at 0x........: pthread_mutex_trylock (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:116) +[1/1] post_mutex_lock (?) 0x........ rc 0 owner 0 +[1/1] pre_mutex_lock (?) 0x........ rc 0 owner 0 + +Not a mutex + at 0x........: pthread_mutex_timedlock (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:121) +[1/1] post_mutex_lock (?) 0x........ rc 0 owner 0 +[1/1] mutex_unlock ? 0x........ rc 0 + +Not a mutex + at 0x........: pthread_mutex_unlock (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:125) + +---------------- pthread_cond_wait et al ---------------- + +[1/1] mutex_init error checking mutex 0x........ +[1/1] cond_init 0x........ +[1/1] mutex_unlock error checking mutex 0x........ rc 0 + +Mutex not locked: mutex 0x........, recursion count 0, owner 0. + at 0x........: pthread_cond_wait* (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:147) +[1/1] cond_pre_wait 0x........ +[1/1] cond_post_wait 0x........ +[1/1] post_mutex_lock error checking mutex 0x........ rc 0 owner 0 +[1/1] cond_signal 0x........ + +FIXME: can't figure out how to verify wrap of pthread_cond_signal + +[1/1] cond_broadcast 0x........ + +FIXME: can't figure out how to verify wrap of pthread_broadcast_signal + +[1/1] mutex_unlock error checking mutex 0x........ rc 0 + +Mutex not locked: mutex 0x........, recursion count 0, owner 0. + at 0x........: pthread_cond_timedwait* (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:165) +[1/1] cond_pre_wait 0x........ +[1/1] cond_post_wait 0x........ +[1/1] post_mutex_lock error checking mutex 0x........ rc 0 owner 0 + +---------------- pthread_rwlock_* ---------------- + + +Reader-writer lock not locked by calling thread: rwlock 0x......... + at 0x........: pthread_rwlock_unlock* (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:179) +(1) no error on next line +(2) no error on next line +(3) ERROR on next line + +Reader-writer lock not locked by calling thread: rwlock 0x......... + at 0x........: pthread_rwlock_unlock* (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:196) + +Reader-writer lock reinitialization: rwlock 0x......... + at 0x........: pthread_rwlock_init* (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:199) +(4) no error on next line +(5) no error on next line +(6) no error on next line +(7) no error on next line +(8) ERROR on next line + +Reader-writer lock not locked by calling thread: rwlock 0x......... + at 0x........: pthread_rwlock_unlock* (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:212) + +---------------- sem_* ---------------- + +[1/1] semaphore_init 0x........ + +FIXME: can't figure out how to verify wrap of sem_destroy + +[1/1] semaphore_pre_wait 0x........ +[1/1] semaphore_post_wait 0x........ + +Invalid semaphore: semaphore 0x........ + at 0x........: sem_wait* (drd_intercepts.c:?) + by 0x........: main (tc20_verifywrap.c:242) +[1/1] semaphore_post 0x........ + +FIXME: can't figure out how to verify wrap of sem_post + +[1/1] semaphore_destroy 0x........ + +------------ dealloc of mem holding locks ------------ + + +Destroying locked rwlock: rwlock 0x......... + at 0x........: main (tc20_verifywrap.c:262) +[1/1] mutex_destroy error checking mutex 0x........ +[1/1] pre_mutex_lock (?) 0x........ rc 0 owner 0 +[1/1] mutex_init recursive mutex 0x........ +[1/1] post_mutex_lock recursive mutex 0x........ rc 0 owner 0 +[1/1] mutex_unlock recursive mutex 0x........ rc 1 + +ERROR SUMMARY: 14 errors from 14 contexts (suppressed: 0 from 0) |
|
From: <sv...@va...> - 2008-03-09 18:46:03
|
Author: bart Date: 2008-03-09 18:46:07 +0000 (Sun, 09 Mar 2008) New Revision: 7619 Log: Cleanup. Modified: trunk/exp-drd/tests/matinv_openmp.c Modified: trunk/exp-drd/tests/matinv_openmp.c =================================================================== --- trunk/exp-drd/tests/matinv_openmp.c 2008-03-09 18:45:28 UTC (rev 7618) +++ trunk/exp-drd/tests/matinv_openmp.c 2008-03-09 18:46:07 UTC (rev 7619) @@ -14,7 +14,6 @@ #include <assert.h> #include <math.h> -#include <pthread.h> #include <stdlib.h> #include <stdio.h> |
|
From: <sv...@va...> - 2008-03-09 18:45:24
|
Author: bart Date: 2008-03-09 18:45:28 +0000 (Sun, 09 Mar 2008) New Revision: 7618 Log: Added LinuxThreads output files for exp-drd/tests/linuxthreads_det. Added: trunk/exp-drd/tests/linuxthreads_det.stderr.exp-linuxthreads trunk/exp-drd/tests/linuxthreads_det.stdout.exp-linuxthreads Added: trunk/exp-drd/tests/linuxthreads_det.stderr.exp-linuxthreads =================================================================== --- trunk/exp-drd/tests/linuxthreads_det.stderr.exp-linuxthreads (rev 0) +++ trunk/exp-drd/tests/linuxthreads_det.stderr.exp-linuxthreads 2008-03-09 18:45:28 UTC (rev 7618) @@ -0,0 +1,7 @@ + +Detected the LinuxThreads threading library. Sorry, but DRD only supports +the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD +after having upgraded to a newer version of your Linux distribution. +Giving up. + +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) Added: trunk/exp-drd/tests/linuxthreads_det.stdout.exp-linuxthreads =================================================================== |
|
From: <sv...@va...> - 2008-03-09 16:18:28
|
Author: bart
Date: 2008-03-09 16:18:31 +0000 (Sun, 09 Mar 2008)
New Revision: 7617
Log:
Fixed spelling error.
Modified:
trunk/exp-drd/tests/linuxthreads_det.c
trunk/exp-drd/tests/linuxthreads_det.stdout.exp
Modified: trunk/exp-drd/tests/linuxthreads_det.c
===================================================================
--- trunk/exp-drd/tests/linuxthreads_det.c 2008-03-09 16:16:06 UTC (rev 7616)
+++ trunk/exp-drd/tests/linuxthreads_det.c 2008-03-09 16:18:31 UTC (rev 7617)
@@ -17,7 +17,7 @@
{
if (s_main_thread_pid == getpid())
{
- printf("NPTL or non-Linux POSIX threads implemenentation detected.\n");
+ printf("NPTL or non-Linux POSIX threads implementation detected.\n");
}
else
{
Modified: trunk/exp-drd/tests/linuxthreads_det.stdout.exp
===================================================================
--- trunk/exp-drd/tests/linuxthreads_det.stdout.exp 2008-03-09 16:16:06 UTC (rev 7616)
+++ trunk/exp-drd/tests/linuxthreads_det.stdout.exp 2008-03-09 16:18:31 UTC (rev 7617)
@@ -1 +1 @@
-NPTL or non-Linux POSIX threads implemenentation detected.
+NPTL or non-Linux POSIX threads implementation detected.
|
|
From: <sv...@va...> - 2008-03-09 16:16:02
|
Author: bart
Date: 2008-03-09 16:16:06 +0000 (Sun, 09 Mar 2008)
New Revision: 7616
Log:
Added test for LinuxThreads detection.
Added:
trunk/exp-drd/tests/linuxthreads_det.c
trunk/exp-drd/tests/linuxthreads_det.stderr.exp
trunk/exp-drd/tests/linuxthreads_det.stdout.exp
trunk/exp-drd/tests/linuxthreads_det.vgtest
Modified:
trunk/exp-drd/tests/Makefile.am
Modified: trunk/exp-drd/tests/Makefile.am
===================================================================
--- trunk/exp-drd/tests/Makefile.am 2008-03-09 15:59:30 UTC (rev 7615)
+++ trunk/exp-drd/tests/Makefile.am 2008-03-09 16:16:06 UTC (rev 7616)
@@ -42,11 +42,14 @@
hg06_readshared.stderr.exp \
hg06_readshared.stderr.exp-linuxthreads \
hg06_readshared.vgtest \
+ linuxthreads_det.stderr.exp \
+ linuxthreads_det.stderr.exp-linuxthreads \
+ linuxthreads_det.stdout.exp \
+ linuxthreads_det.stdout.exp-linuxthreads \
matinv.stderr.exp \
matinv.stderr.exp-linuxthreads \
matinv.stdout.exp \
matinv.stdout.exp-linuxthreads \
- matinv.stdout.exp-linuxthreads \
matinv.vgtest \
pth_barrier.stderr.exp \
pth_barrier.stderr.exp-linuxthreads \
@@ -194,6 +197,7 @@
hg04_race \
hg05_race2 \
hg06_readshared \
+ linuxthreads_det \
matinv \
pth_barrier \
pth_broadcast \
@@ -261,13 +265,16 @@
hg06_readshared_SOURCES = ../../helgrind/tests/hg06_readshared.c
hg06_readshared_LDADD = -lpthread
+linuxthreads_det_SOURCES = linuxthreads_det.c
+linuxthreads_det_LDADD = -lpthread
+
matinv_SOURCES = matinv.c
matinv_LDADD = -lpthread -lm
if HAVE_GCC_FOPENMP
matinv_openmp_SOURCES = matinv_openmp.c
matinv_openmp_CFLAGS = -fopenmp
-matinv_openmp_LDADD = -lpthread -lm
+matinv_openmp_LDADD = -lm
endif
pth_barrier_SOURCES = pth_barrier.c
Added: trunk/exp-drd/tests/linuxthreads_det.c
===================================================================
--- trunk/exp-drd/tests/linuxthreads_det.c (rev 0)
+++ trunk/exp-drd/tests/linuxthreads_det.c 2008-03-09 16:16:06 UTC (rev 7616)
@@ -0,0 +1,41 @@
+/** Test whether DRD recognizes LinuxThreads as LinuxThreads and NPTL as
+ * NPTL.
+ */
+
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static sem_t s_sem;
+static pid_t s_main_thread_pid;
+
+
+void* thread_func(void* arg)
+{
+ if (s_main_thread_pid == getpid())
+ {
+ printf("NPTL or non-Linux POSIX threads implemenentation detected.\n");
+ }
+ else
+ {
+ printf("Detected LinuxThreads as POSIX threads implemenentation.\n");
+ }
+ sem_post(&s_sem);
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ pthread_t threadid;
+
+ s_main_thread_pid = getpid();
+ sem_init(&s_sem, 0, 0);
+ pthread_create(&threadid, 0, thread_func, 0);
+ sem_wait(&s_sem);
+ pthread_join(threadid, 0);
+ sem_destroy(&s_sem);
+ return 0;
+}
Added: trunk/exp-drd/tests/linuxthreads_det.stderr.exp
===================================================================
--- trunk/exp-drd/tests/linuxthreads_det.stderr.exp (rev 0)
+++ trunk/exp-drd/tests/linuxthreads_det.stderr.exp 2008-03-09 16:16:06 UTC (rev 7616)
@@ -0,0 +1,3 @@
+
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Added: trunk/exp-drd/tests/linuxthreads_det.stdout.exp
===================================================================
--- trunk/exp-drd/tests/linuxthreads_det.stdout.exp (rev 0)
+++ trunk/exp-drd/tests/linuxthreads_det.stdout.exp 2008-03-09 16:16:06 UTC (rev 7616)
@@ -0,0 +1 @@
+NPTL or non-Linux POSIX threads implemenentation detected.
Added: trunk/exp-drd/tests/linuxthreads_det.vgtest
===================================================================
--- trunk/exp-drd/tests/linuxthreads_det.vgtest (rev 0)
+++ trunk/exp-drd/tests/linuxthreads_det.vgtest 2008-03-09 16:16:06 UTC (rev 7616)
@@ -0,0 +1 @@
+prog: linuxthreads_det
|
|
From: <sv...@va...> - 2008-03-09 15:59:38
|
Author: bart
Date: 2008-03-09 15:59:30 +0000 (Sun, 09 Mar 2008)
New Revision: 7615
Log:
Un-break compilation on systems with a compiler that does not support -fopenmp.
Modified:
trunk/configure.in
trunk/exp-drd/tests/Makefile.am
Modified: trunk/configure.in
===================================================================
--- trunk/configure.in 2008-03-09 13:41:26 UTC (rev 7614)
+++ trunk/configure.in 2008-03-09 15:59:30 UTC (rev 7615)
@@ -550,6 +550,27 @@
fi
+# does this compiler support -fopenmp ?
+AC_MSG_CHECKING([if gcc accepts -fopenmp])
+
+safe_CFLAGS=$CFLAGS
+CFLAGS="-fopenmp"
+
+AC_TRY_COMPILE(, [
+int main () { return 0 ; }
+],
+[
+ac_have_gcc_fopenmp=yes
+AC_MSG_RESULT([yes])
+], [
+ac_have_gcc_fopenmp=no
+AC_MSG_RESULT([no])
+])
+CFLAGS=$safe_CFLAGS
+
+AM_CONDITIONAL([HAVE_GCC_FOPENMP], [test x$ac_have_gcc_fopenmp = xyes])
+
+
# does this compiler support -m32 ?
AC_MSG_CHECKING([if gcc accepts -m32])
Modified: trunk/exp-drd/tests/Makefile.am
===================================================================
--- trunk/exp-drd/tests/Makefile.am 2008-03-09 13:41:26 UTC (rev 7614)
+++ trunk/exp-drd/tests/Makefile.am 2008-03-09 15:59:30 UTC (rev 7615)
@@ -186,7 +186,7 @@
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_builddir)/include
AM_CXXFLAGS = $(AM_CFLAGS)
-check_PROGRAMS = \
+check_PROGRAMS_COMMON = \
fp_race \
hg01_all_ok \
hg02_deadlock \
@@ -195,7 +195,6 @@
hg05_race2 \
hg06_readshared \
matinv \
- matinv_openmp \
pth_barrier \
pth_broadcast \
pth_cond_race \
@@ -230,6 +229,14 @@
tc24_nonzero_sem \
trylock
+check_PROGRAMS_OPENMP = matinv_openmp
+
+if HAVE_GCC_FOPENMP
+check_PROGRAMS = $(check_PROGRAMS_COMMON) $(check_PROGRAMS_OPENMP)
+else
+check_PROGRAMS = $(check_PROGRAMS_COMMON)
+endif
+
# tc14_laog_dinphils -- hangs.
@@ -257,9 +264,11 @@
matinv_SOURCES = matinv.c
matinv_LDADD = -lpthread -lm
+if HAVE_GCC_FOPENMP
matinv_openmp_SOURCES = matinv_openmp.c
matinv_openmp_CFLAGS = -fopenmp
matinv_openmp_LDADD = -lpthread -lm
+endif
pth_barrier_SOURCES = pth_barrier.c
pth_barrier_LDADD = -lpthread
|
|
From: <sv...@va...> - 2008-03-09 13:41:24
|
Author: bart
Date: 2008-03-09 13:41:26 +0000 (Sun, 09 Mar 2008)
New Revision: 7614
Log:
Added OpenMP test program.
Added:
trunk/exp-drd/tests/matinv_openmp.c
Modified:
trunk/exp-drd/tests/Makefile.am
Modified: trunk/exp-drd/tests/Makefile.am
===================================================================
--- trunk/exp-drd/tests/Makefile.am 2008-03-09 13:39:58 UTC (rev 7613)
+++ trunk/exp-drd/tests/Makefile.am 2008-03-09 13:41:26 UTC (rev 7614)
@@ -195,6 +195,7 @@
hg05_race2 \
hg06_readshared \
matinv \
+ matinv_openmp \
pth_barrier \
pth_broadcast \
pth_cond_race \
@@ -256,6 +257,10 @@
matinv_SOURCES = matinv.c
matinv_LDADD = -lpthread -lm
+matinv_openmp_SOURCES = matinv_openmp.c
+matinv_openmp_CFLAGS = -fopenmp
+matinv_openmp_LDADD = -lpthread -lm
+
pth_barrier_SOURCES = pth_barrier.c
pth_barrier_LDADD = -lpthread
Added: trunk/exp-drd/tests/matinv_openmp.c
===================================================================
--- trunk/exp-drd/tests/matinv_openmp.c (rev 0)
+++ trunk/exp-drd/tests/matinv_openmp.c 2008-03-09 13:41:26 UTC (rev 7614)
@@ -0,0 +1,293 @@
+/** Compute the matrix inverse via Gauss-Jordan elimination.
+ * This program uses OpenMP separate computation steps but no
+ * mutexes. It is an example of a race-free program on which no data races
+ * are reported by the happens-before algorithm (drd), but a lot of data races
+ * (all false positives) are reported by the Eraser-algorithm (helgrind).
+ */
+
+
+#define _GNU_SOURCE
+
+/***********************/
+/* Include directives. */
+/***********************/
+
+#include <assert.h>
+#include <math.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+/*********************/
+/* Type definitions. */
+/*********************/
+
+typedef double elem_t;
+
+
+/********************/
+/* Local variables. */
+/********************/
+
+static int s_nthread;
+
+
+/*************************/
+/* Function definitions. */
+/*************************/
+
+/** Allocate memory for a matrix with the specified number of rows and
+ * columns.
+ */
+static elem_t* new_matrix(const int rows, const int cols)
+{
+ assert(rows > 0);
+ assert(cols > 0);
+ return malloc(rows * cols * sizeof(elem_t));
+}
+
+/** Free the memory that was allocated for a matrix. */
+static void delete_matrix(elem_t* const a)
+{
+ free(a);
+}
+
+/** Fill in some numbers in a matrix.
+ * @note It is important not to call srand() in this program, such that
+ * the results of a run are reproducible.
+ */
+static void init_matrix(elem_t* const a, const int rows, const int cols)
+{
+ int i, j;
+ for (i = 0; i < rows; i++)
+ {
+ for (j = 0; j < rows; j++)
+ {
+ a[i * cols + j] = rand() * 1.0 / RAND_MAX;
+ }
+ }
+}
+
+/** Print all elements of a matrix. */
+void print_matrix(const char* const label,
+ const elem_t* const a, const int rows, const int cols)
+{
+ int i, j;
+ printf("%s:\n", label);
+ for (i = 0; i < rows; i++)
+ {
+ for (j = 0; j < cols; j++)
+ {
+ printf("%g ", a[i * cols + j]);
+ }
+ printf("\n");
+ }
+}
+
+/** Copy a subset of the elements of a matrix into another matrix. */
+static void copy_matrix(const elem_t* const from,
+ const int from_rows,
+ const int from_cols,
+ const int from_row_first,
+ const int from_row_last,
+ const int from_col_first,
+ const int from_col_last,
+ elem_t* const to,
+ const int to_rows,
+ const int to_cols,
+ const int to_row_first,
+ const int to_row_last,
+ const int to_col_first,
+ const int to_col_last)
+{
+ int i, j;
+
+ assert(from_row_last - from_row_first == to_row_last - to_row_first);
+ assert(from_col_last - from_col_first == to_col_last - to_col_first);
+
+ for (i = from_row_first; i < from_row_last; i++)
+ {
+ assert(i < from_rows);
+ assert(i - from_row_first + to_row_first < to_rows);
+ for (j = from_col_first; j < from_col_last; j++)
+ {
+ assert(j < from_cols);
+ assert(j - from_col_first + to_col_first < to_cols);
+ to[(i - from_row_first + to_col_first) * to_cols
+ + (j - from_col_first + to_col_first)]
+ = from[i * from_cols + j];
+ }
+ }
+}
+
+/** Compute the matrix product of a1 and a2. */
+static elem_t* multiply_matrices(const elem_t* const a1,
+ const int rows1,
+ const int cols1,
+ const elem_t* const a2,
+ const int rows2,
+ const int cols2)
+{
+ int i, j, k;
+ elem_t* prod;
+
+ assert(cols1 == rows2);
+
+ prod = new_matrix(rows1, cols2);
+ for (i = 0; i < rows1; i++)
+ {
+ for (j = 0; j < cols2; j++)
+ {
+ prod[i * cols2 + j] = 0;
+ for (k = 0; k < cols1; k++)
+ {
+ prod[i * cols2 + j] += a1[i * cols1 + k] * a2[k * cols2 + j];
+ }
+ }
+ }
+ return prod;
+}
+
+/** Apply the Gauss-Jordan elimination algorithm on the matrix p->a starting
+ * at row r0 and up to but not including row r1. It is assumed that as many
+ * threads execute this function concurrently as the count barrier p->b was
+ * initialized with. If the matrix p->a is nonsingular, and if matrix p->a
+ * has at least as many columns as rows, the result of this algorithm is that
+ * submatrix p->a[0..p->rows-1,0..p->rows-1] is the identity matrix.
+ * @see http://en.wikipedia.org/wiki/Gauss-Jordan_elimination
+ */
+static void gj(elem_t* const a, const int rows, const int cols)
+{
+ int i, j, k;
+
+ for (i = 0; i < rows; i++)
+ {
+ {
+ // Pivoting.
+ j = i;
+ for (k = i + 1; k < rows; k++)
+ {
+ if (a[k * cols + i] > a[j * cols + i])
+ {
+ j = k;
+ }
+ }
+ if (j != i)
+ {
+ for (k = 0; k < cols; k++)
+ {
+ const elem_t t = a[i * cols + k];
+ a[i * cols + k] = a[j * cols + k];
+ a[j * cols + k] = t;
+ }
+ }
+ // Normalize row i.
+ if (a[i * cols + i] != 0)
+ {
+ for (k = cols - 1; k >= 0; k--)
+ {
+ a[i * cols + k] /= a[i * cols + i];
+ }
+ }
+ }
+
+ // Reduce all rows j != i.
+#pragma omp parallel for
+ for (j = 0; j < rows; j++)
+ {
+ if (i != j)
+ {
+ const elem_t factor = a[j * cols + i];
+ for (k = 0; k < cols; k++)
+ {
+ a[j * cols + k] -= a[i * cols + k] * factor;
+ }
+ }
+ }
+ }
+}
+
+/** Matrix inversion via the Gauss-Jordan algorithm. */
+static elem_t* invert_matrix(const elem_t* const a, const int n)
+{
+ int i, j;
+ elem_t* const inv = new_matrix(n, n);
+ elem_t* const tmp = new_matrix(n, 2*n);
+ copy_matrix(a, n, n, 0, n, 0, n, tmp, n, 2 * n, 0, n, 0, n);
+ for (i = 0; i < n; i++)
+ for (j = 0; j < n; j++)
+ tmp[i * 2 * n + n + j] = (i == j);
+ gj(tmp, n, 2*n);
+ copy_matrix(tmp, n, 2*n, 0, n, n, 2*n, inv, n, n, 0, n, 0, n);
+ delete_matrix(tmp);
+ return inv;
+}
+
+/** Compute the average square error between the identity matrix and the
+ * product of matrix a with its inverse matrix.
+ */
+static double identity_error(const elem_t* const a, const int n)
+{
+ int i, j;
+ elem_t e = 0;
+ for (i = 0; i < n; i++)
+ {
+ for (j = 0; j < n; j++)
+ {
+ const elem_t d = a[i * n + j] - (i == j);
+ e += d * d;
+ }
+ }
+ return sqrt(e / (n * n));
+}
+
+/** Compute epsilon for the numeric type elem_t. Epsilon is defined as the
+ * smallest number for which the sum of one and that number is different of
+ * one. It is assumed that the underlying representation of elem_t uses
+ * base two.
+ */
+static elem_t epsilon()
+{
+ elem_t eps;
+ for (eps = 1; 1 + eps != 1; eps /= 2)
+ ;
+ return 2 * eps;
+}
+
+int main(int argc, char** argv)
+{
+ int matrix_size;
+ int silent;
+ elem_t *a, *inv, *prod;
+ elem_t eps;
+ double error;
+ double ratio;
+
+ matrix_size = (argc > 1) ? atoi(argv[1]) : 3;
+ s_nthread = (argc > 2) ? atoi(argv[2]) : 3;
+ silent = (argc > 3) ? atoi(argv[3]) : 0;
+
+ eps = epsilon();
+ a = new_matrix(matrix_size, matrix_size);
+ init_matrix(a, matrix_size, matrix_size);
+ inv = invert_matrix(a, matrix_size);
+ prod = multiply_matrices(a, matrix_size, matrix_size,
+ inv, matrix_size, matrix_size);
+ error = identity_error(prod, matrix_size);
+ ratio = error / (eps * matrix_size);
+ if (! silent)
+ {
+ printf("error = %g; epsilon = %g; error / (epsilon * n) = %g\n",
+ error, eps, ratio);
+ }
+ if (ratio < 100)
+ printf("Error within bounds.\n");
+ else
+ printf("Error out of bounds.\n");
+ delete_matrix(prod);
+ delete_matrix(inv);
+ delete_matrix(a);
+
+ return 0;
+}
|
|
From: <sv...@va...> - 2008-03-09 13:39:57
|
Author: bart
Date: 2008-03-09 13:39:58 +0000 (Sun, 09 Mar 2008)
New Revision: 7613
Log:
Fixed typo.
Modified:
trunk/exp-drd/drd_error.c
Modified: trunk/exp-drd/drd_error.c
===================================================================
--- trunk/exp-drd/drd_error.c 2008-03-09 13:39:35 UTC (rev 7612)
+++ trunk/exp-drd/drd_error.c 2008-03-09 13:39:58 UTC (rev 7613)
@@ -255,7 +255,7 @@
}
else
{
- VG_(message)(Vg_UserMsg, "Allocation context: unknown.\n");
+ VG_(message)(Vg_UserMsg, "Allocation context: unknown.");
}
thread_report_conflicting_segments(VgThreadIdToDrdThreadId(dri->tid),
dri->addr, dri->size, dri->access_type);
|
|
From: <sv...@va...> - 2008-03-09 13:39:30
|
Author: bart
Date: 2008-03-09 13:39:35 +0000 (Sun, 09 Mar 2008)
New Revision: 7612
Log:
Fixed compiler warning.
Modified:
trunk/exp-drd/drd_intercepts.c
Modified: trunk/exp-drd/drd_intercepts.c
===================================================================
--- trunk/exp-drd/drd_intercepts.c 2008-03-09 13:10:47 UTC (rev 7611)
+++ trunk/exp-drd/drd_intercepts.c 2008-03-09 13:39:35 UTC (rev 7612)
@@ -171,7 +171,7 @@
#if defined(_CS_GNU_LIBPTHREAD_VERSION)
/* Linux with a recent glibc. */
char buffer[256];
- int len;
+ unsigned len;
len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
assert(len <= sizeof(buffer));
return len > 0 && buffer[0] == 'l';
|
|
From: Bart V. A. <bar...@gm...> - 2008-03-09 13:38:02
|
Hello, As far as I understood the libgomp source code directly, libgomp has its own barrier implementation based on the futex system call. This means that if I want to support OpenMP in DRD, I have to intercept the futex system call. Is there a better way than adding calls to appropriate tracking functions in PRE(sys_futex) and POST(sys_futex) (defined in coregrind/m_syswrap/syswrap-linux.c) ? Bart. |
|
From: <sv...@va...> - 2008-03-09 13:10:44
|
Author: sewardj
Date: 2008-03-09 13:10:47 +0000 (Sun, 09 Mar 2008)
New Revision: 7611
Log:
More scaling stuff from Konstantin Serebryany:
Handle pthread_barrier_wait
New end-user client requests:
EXPECT_RACE -- useful for unit tests.
BENIGN_RACE -- to annotate benign races in user code
PCQ_* -- to annotate FIFO message queues in user code.
TRACE_MEM -- useful for debugging races.
MUTEX_IS_USED_AS_CONDVAR
-- mark a particular mutex so that it is handled like in a pure
HB detector.
GET_THREAD_ID, GET_SEGMENT_ID -- just for debugging.
--ignore-n= and --ignore-i= flags (need a better name!). For better
performance and memory usage ignore addresses that != i mod n. See
address_may_be_ignored.
Modified:
branches/HGDEV/helgrind/helgrind.h
branches/HGDEV/helgrind/hg_intercepts.c
branches/HGDEV/helgrind/hg_main.c
Modified: branches/HGDEV/helgrind/helgrind.h
===================================================================
--- branches/HGDEV/helgrind/helgrind.h 2008-03-09 11:13:07 UTC (rev 7610)
+++ branches/HGDEV/helgrind/helgrind.h 2008-03-09 13:10:47 UTC (rev 7611)
@@ -63,7 +63,18 @@
typedef
enum {
VG_USERREQ__HG_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'),
+ VG_USERREQ__HG_BENIGN_RACE, /* void*, char*, char*, int */
+ VG_USERREQ__HG_EXPECT_RACE, /* void*, char*, char*, int */
+ VG_USERREQ__HG_PCQ_CREATE, /* void* */
+ VG_USERREQ__HG_PCQ_DESTROY, /* void* */
+ VG_USERREQ__HG_PCQ_PUT, /* void* */
+ VG_USERREQ__HG_PCQ_GET, /* void* */
+ VG_USERREQ__HG_TRACE_MEM, /* void* */
+ VG_USERREQ__HG_MUTEX_IS_USED_AS_CONDVAR, /* void* */
+ VG_USERREQ__HG_IGNORE_READS_BEGIN, /* none */
+ VG_USERREQ__HG_IGNORE_READS_END, /* none */
+
/* The rest are for Helgrind's internal use. Not for end-user
use. Do not use them unless you are a Valgrind developer. */
@@ -92,7 +103,9 @@
_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, /* sem_t* */
_VG_USERREQ__HG_POSIX_SEM_POST_PRE, /* sem_t* */
_VG_USERREQ__HG_POSIX_SEM_WAIT_POST, /* sem_t* */
- _VG_USERREQ__HG_GET_MY_SEGMENT /* -> Segment* */
+ _VG_USERREQ__HG_GET_MY_SEGMENT, /* -> Segment* */
+ _VG_USERREQ__HG_GET_THREAD_ID, /* -> Thread ID */
+ _VG_USERREQ__HG_GET_SEGMENT_ID /* -> Segment ID */
} Vg_TCheckClientRequest;
/* Clean memory state. This makes Helgrind forget everything it knew
Modified: branches/HGDEV/helgrind/hg_intercepts.c
===================================================================
--- branches/HGDEV/helgrind/hg_intercepts.c 2008-03-09 11:13:07 UTC (rev 7610)
+++ branches/HGDEV/helgrind/hg_intercepts.c 2008-03-09 13:10:47 UTC (rev 7611)
@@ -718,7 +718,42 @@
return ret;
}
+/*----------------------------------------------------------------*/
+/*--- pthread_barrier_t functions ---*/
+/*----------------------------------------------------------------*/
+PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait.
+ pthread_barrier_t* b)
+{
+ int ret;
+ OrigFn fn;
+ VALGRIND_GET_ORIG_FN(fn);
+ if (TRACE_PTH_FNS) {
+ fprintf(stderr, "<< pthread_barrier_wait %p", b);
+ fflush(stderr);
+ }
+
+ // We blocked, signal.
+ DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE,
+ void*,b);
+ CALL_FN_W_W(ret, fn, b);
+
+ // FIXME: handle ret
+
+ // We unblocked, finish wait.
+ DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
+ void *, b, void *, b);
+
+ if (TRACE_PTH_FNS) {
+ fprintf(stderr, " pthread_barrier_wait -> %d >>\n", ret);
+ }
+
+ return ret;
+}
+
+
+
+
/*----------------------------------------------------------------*/
/*--- pthread_rwlock_t functions ---*/
/*----------------------------------------------------------------*/
Modified: branches/HGDEV/helgrind/hg_main.c
===================================================================
--- branches/HGDEV/helgrind/hg_main.c 2008-03-09 11:13:07 UTC (rev 7610)
+++ branches/HGDEV/helgrind/hg_main.c 2008-03-09 13:10:47 UTC (rev 7611)
@@ -34,7 +34,8 @@
without prior written permission.
*/
-/* JRS: TODO 2008 Mar 03:
+/* JRS: TODO 2008 Mar 09:
+
- Consider what to do about BHL all over again
- Consider what to do about last-lock-lossage mechanism.
@@ -42,9 +43,16 @@
- get rid of SVal-cache dirty bits? Basically pointless; almost
all lines become dirty and have to be written back. Quantify.
+ (I think they are not present anyway)
- - get rid of 64-bit mod in happens_before hash calculation
- (is very expensive on 32-bit platforms)
+ STUFF I DON'T UNDERSTAND:
+
+ Make sense of ignore-n/ignore-i. What exactly does this do?
+ Why shift by the secmap size before modding?
+
+ How does the pthread_barrier_wait wrapper create the correct
+ segments? In particular, why does it use the same client requests
+ as for pthread_cond_* operations?
*/
#include "pub_tool_basics.h"
@@ -176,6 +184,14 @@
SCE_{THREADS,LOCKS,BIGRANGE,ACCESS,LAOG}. */
static Int clo_sanity_flags = 0;
+/* If clo_ignore_n == 0, the state machine ignores all memory addresses.
+ If clo_ignore_n >= 2, the addresses are ignored if
+ (addr mod clo_ignore_n != clo_ignore_i)
+
+ TODO: Find a better (descriptive) name for command line parameters. */
+static UWord clo_ignore_n = 1;
+static UWord clo_ignore_i = 0;
+
/* This has to do with printing error messages. See comments on
announce_threadset() and summarise_threadset(). Perhaps it
should be a command line option. */
@@ -294,6 +310,7 @@
/* Place where parent was when this thread was created. */
ExeContext* created_at;
Bool announced;
+ Bool ignore_reads;
/* Index for generating references in error messages. */
Int errmsg_index;
}
@@ -375,7 +392,26 @@
}
Segment;
+/**
+ This structure contains data from
+ VG_USERREQ__HG_BENIGN_RACE or VG_USERREQ__HG_EXPECT_RACE client request.
+ These two client requests are similar: they both suppress reports about a
+ data race. The only difference is that for VG_USERREQ__HG_EXPECT_RACE
+ helgrind will complain if the race was not detected (useful for unit tests).
+*/
+typedef
+ struct {
+ Addr ptr; ///< Pointer from the client request.
+ HChar* descr; ///< Arbitrary text supplied by client.
+ HChar* file; ///< File name (for debug output).
+ Int line; ///< Line number (for debug output)
+ Bool detected; ///< Will be set once an error with 'ptr' is detected.
+ Bool is_benign; ///< True iff VG_USERREQ__HG_BENIGN_RACE was called.
+ }
+ ExpectedError;
+
+
/* ------ CacheLine ------ */
#define N_LINE_BITS 6 /* must be >= 3 */
@@ -574,8 +610,10 @@
static Int __bus_lock = 0;
static Lock* __bus_lock_Lock = NULL;
+static WordFM *map_expected_errors = NULL; /* WordFM Addr ExpectedError */
+
/*----------------------------------------------------------------*/
/*--- Simple helpers for the data structures ---*/
/*----------------------------------------------------------------*/
@@ -1155,7 +1193,7 @@
/*--- Print out the primary data structures ---*/
/*----------------------------------------------------------------*/
-static WordSetID del_BHL ( WordSetID lockset ); /* fwds */
+// static WordSetID del_BHL ( WordSetID lockset ); /* fwds */
static
void get_ZF_by_index ( /*OUT*/CacheLineZ** zp, /*OUT*/CacheLineF** fp,
SecMap* sm, UInt zix ); /* fwds */
@@ -1515,6 +1553,10 @@
univ_laog = HG_(newWordSetU)( hg_zalloc, hg_free, 24/*cacheSize*/ );
tl_assert(univ_laog != NULL);
+ tl_assert(map_expected_errors == NULL);
+ map_expected_errors = HG_(newFM)( hg_zalloc, hg_free, NULL /*unboxed cmp*/);
+ tl_assert(map_expected_errors != NULL);
+
/* Set up entries for the root thread */
// FIXME: this assumes that the first real ThreadId is 1
@@ -2018,7 +2060,226 @@
VG_(strcat)(buf, "]");
}
+/*------------ handle expected errors -----------------------*/
+// See definition of ExpectedError for details.
+
+static ExpectedError *get_expected_error (Addr ptr)
+{
+ ExpectedError *expected_error = NULL;
+ if (HG_(lookupFM)( map_expected_errors,
+ NULL/*keyP*/, (Word*)&expected_error, (Word)ptr)) {
+ tl_assert(expected_error->ptr == ptr);
+ VG_(printf)("Found expected race: %s:%d %p\t%s\n",
+ expected_error->file, expected_error->line, ptr, expected_error->descr);
+ return expected_error;
+ }
+ return NULL;
+}
+
+static Bool maybe_set_expected_error (Addr ptr,
+ HChar* description,
+ HChar* file,
+ Int line,
+ Bool is_benign)
+{
+ ExpectedError *error = NULL;
+// VG_(printf)("Expected data race: %s:%d %p\t", file, line, ptr);
+ if (HG_(lookupFM)( map_expected_errors,
+ NULL/*keyP*/, (Word*)&error, (Word)ptr)) {
+// VG_(printf)("Found\n");
+ tl_assert(error);
+ return False;
+ }
+ /* create a new one */
+// VG_(printf)("New\n");
+ error = (ExpectedError*)hg_zalloc(sizeof(ExpectedError));
+ error->ptr = ptr;
+ error->detected = False;
+ error->is_benign = is_benign;
+ error->descr = description;
+ error->file = file; /* need to copy?*/
+ error->line = line;
+ tl_assert(error);
+ HG_(addToFM)( map_expected_errors, (Word)ptr, (Word)error );
+ return True;
+}
+
+/*------- mem trace -------------------------------------------*/
+/* a client may request to trace certain memory (for better debugging) */
+static WordFM *mem_trace_map = NULL;
+static void mem_trace_on(Word mem, ThreadId tid)
+{
+ if (clo_trace_level <= 0) return;
+ if (!mem_trace_map) {
+ mem_trace_map = HG_(newFM)( hg_zalloc, hg_free, NULL);
+ }
+ HG_(addToFM)(mem_trace_map, mem, mem);
+ VG_(printf)("trace on: %p\n", mem);
+ if (clo_trace_level >= 2) {
+ VG_(get_and_pp_StackTrace)( tid, 15);
+ }
+}
+
+static inline void mem_trace_off(Addr first, Addr last)
+{
+ Bool cont = True;
+ Addr a;
+ if (LIKELY(!mem_trace_map)) return;
+ // Turn memory trace off for all addresses in range [first, last].
+ while(cont) {
+ cont = False;
+ HG_(initIterAtFM)(mem_trace_map, first);
+ while (HG_(nextIterFM)(mem_trace_map, (Word*)&a, NULL) && a <= last) {
+ HG_(delFromFM)(mem_trace_map, NULL, NULL, a);
+ cont = True;
+ // we deleted one address from the map. Repeat everything again.
+ break;
+ }
+ }
+}
+
+static Bool mem_trace_is_on(Word mem)
+{
+ return mem_trace_map != NULL
+ && HG_(lookupFM)(mem_trace_map, NULL, NULL, mem);
+}
+
+
+/*---------- MU is used as CV -------------------------*/
+
+/* In some cases mutexes are used in such a way that
+ regular lockset algorithms will always report a race even though
+ the code is perfectly synchronized.
+ We can treat such mutexes as pure happens-before detectors do.
+ For example, see test61.
+
+*/
+
+static WordFM *mu_is_cv_map = NULL;
+static void set_mu_is_cv(Word mu)
+{
+ if (!mu_is_cv_map) {
+ mu_is_cv_map = HG_(newFM) (hg_zalloc, hg_free, NULL);
+ }
+ HG_(addToFM)(mu_is_cv_map, mu, mu);
+// VG_(printf)("mu is cv: %p\n", mu);
+}
+
+static void unset_mu_is_cv(Word mu)
+{
+ if (mu_is_cv_map) {
+ HG_(delFromFM)(mu_is_cv_map, NULL, NULL, mu);
+ }
+}
+
+static Bool mu_is_cv(Word mu)
+{
+ return mu_is_cv_map != NULL
+ && HG_(lookupFM)(mu_is_cv_map, NULL, NULL, mu);
+}
+
+
+/*------- PCQ (aka ProducerConsumerQueue, Message queue) ------ */
+/*
+ Producer-consumer queue (aka Message queue) creates
+ happens-before relation.
+ Put() is like posting a semaphore and
+ Get() is like waiting on that semaphore.
+
+ When Get() is called, helgrind has to find the corresponding Put().
+ Current implementation will work only for FIFO queues.
+
+ For each PCQ we maintain a structure that contains the number
+ of puts and the number of gets.
+ The n-th Put() corresponds to n-th Get().
+
+
+ TODO:
+ Currently we reuse semaphore routines evh__HG_POSIX_SEM_*.
+ It's better to have separate implementations for Put()/Get().
+
+*/
+typedef struct {
+ Word client_pcq; // just for consistency checking.
+ Word n_puts;
+ Word n_gets;
+} PCQ;
+
+static WordFM *pcq_map = NULL; // WordFM client_pcq my_pcq
+
+// Create PCQ for client_pcq. Should be called
+// when the client creates its PCQ.
+static void pcq_create(Word client_pcq)
+{
+ PCQ *my_pcq;
+ if (pcq_map == NULL) {
+ // first time init.
+ pcq_map = HG_(newFM)( hg_zalloc, hg_free, NULL);
+ tl_assert(pcq_map != NULL);
+ }
+
+ my_pcq = (PCQ*) hg_zalloc(sizeof(PCQ));
+ my_pcq->client_pcq = client_pcq;
+ my_pcq->n_puts = 0;
+ my_pcq->n_gets = 0;
+
+ tl_assert(!HG_(lookupFM)(pcq_map, NULL, NULL, client_pcq));
+ HG_(addToFM)(pcq_map, client_pcq, (Word)my_pcq);
+}
+
+// Destroy PCQ (called when client PCQ is destroyed).
+static void pcq_destroy(Word client_pcq)
+{
+ PCQ *my_pcq;
+ Word old_client_pcq;
+ Bool found = HG_(delFromFM)(pcq_map, &old_client_pcq,
+ (Word*)&my_pcq, client_pcq);
+ tl_assert(found == True);
+ tl_assert(old_client_pcq == client_pcq);
+ tl_assert(my_pcq->client_pcq == client_pcq);
+}
+
+// fwds
+static void evh__HG_POSIX_SEM_WAIT_POST ( ThreadId tid, void* sem );
+static void evh__HG_POSIX_SEM_POST_PRE ( ThreadId tid, void* sem );
+
+// Handle PCQ::Put().
+static void pcq_put(ThreadId tid, Word client_pcq)
+{
+ PCQ *my_pcq;
+ Word old_client_pcq;
+ Bool found = HG_(lookupFM)(pcq_map, &old_client_pcq,
+ (Word*)&my_pcq, client_pcq);
+ tl_assert(found == True);
+ tl_assert(old_client_pcq == client_pcq);
+ tl_assert(my_pcq->client_pcq == client_pcq);
+
+ evh__HG_POSIX_SEM_POST_PRE(tid,
+ (void*)((client_pcq << 5) ^ my_pcq->n_puts)
+ );
+ my_pcq->n_puts++;
+}
+
+// Handle PCQ::Get().
+static void pcq_get(ThreadId tid, Word client_pcq)
+{
+ PCQ *my_pcq;
+ Word old_client_pcq;
+ Bool found = HG_(lookupFM)(pcq_map, &old_client_pcq,
+ (Word*)&my_pcq, client_pcq);
+ tl_assert(found == True);
+ tl_assert(old_client_pcq == client_pcq);
+ tl_assert(my_pcq->client_pcq == client_pcq);
+
+ evh__HG_POSIX_SEM_WAIT_POST(tid,
+ (void*)((client_pcq << 5) ^ my_pcq->n_gets)
+ );
+ my_pcq->n_gets++;
+}
+
+
+
/*------------ searching the happens-before graph ------------*/
static UWord stats__hbefore_queries = 0; // total # queries
@@ -2357,6 +2618,7 @@
}
/*--------------- SecMap allocation --------------- */
+static inline Bool address_may_be_ignored ( Addr a ); // fwds
static HChar* shmem__bigchunk_next = NULL;
static HChar* shmem__bigchunk_end1 = NULL;
@@ -2449,6 +2711,9 @@
SecMap* sm;
Addr aKey = shmem__round_to_SecMap_base(a);
tl_assert(b == False || b == True);
+ // avoid creating a SecMap for memory that we ignore.
+ if (b == False && clo_ignore_n != 1 && address_may_be_ignored(a)) return;
+
if (HG_(lookupFM)( map_shmem,
NULL/*keyP*/, (Word*)&sm, (Word)aKey )) {
/* Found; address of SecMap is in sm */
@@ -2466,6 +2731,9 @@
SecMap* sm;
Addr aKey = shmem__round_to_SecMap_base(a);
tl_assert(b == False || b == True);
+ // avoid creating a SecMap for memory that we ignore.
+ if (b == False && clo_ignore_n != 1 && address_may_be_ignored(a)) return;
+
if (HG_(lookupFM)( map_shmem,
NULL/*keyP*/, (Word*)&sm, (Word)aKey )) {
/* Found; address of SecMap is in sm */
@@ -2883,13 +3151,13 @@
// KCC: If you agree with the new scheme of handling BHL,
// KCC: add_BHL/del_BHL could be deleted completely.
-
+// KCC: Now these functions are commented out to avoid compiler warnings.
//static WordSetID add_BHL ( WordSetID lockset ) {
// return HG_(addToWS)( univ_lsets, lockset, (Word)__bus_lock_Lock );
//}
-static WordSetID del_BHL ( WordSetID lockset ) {
- return HG_(delFromWS)( univ_lsets, lockset, (Word)__bus_lock_Lock );
-}
+//static WordSetID del_BHL ( WordSetID lockset ) {
+// return HG_(delFromWS)( univ_lsets, lockset, (Word)__bus_lock_Lock );
+//}
/* Last-lock-lossage records. This mechanism exists to help explain
@@ -2928,6 +3196,7 @@
static WordFM* ga_to_lastlock = NULL; /* GuestAddr -> ExeContext* */
+#if 0 // commented out to avoid a compiler warning about unused function
static
void record_last_lock_lossage ( Addr ga_of_access,
WordSetID lset_old, WordSetID lset_new )
@@ -2990,6 +3259,7 @@
stats__ga_LL_adds++;
}
}
+#endif // #if 0
/* This queries the table (ga_to_lastlock) made by
record_last_lock_lossage, when constructing error messages. It
@@ -3140,7 +3410,36 @@
}
+static void msm_do_trace(Thread *thr, Addr a, SVal sv_new, Bool is_w)
+{
+ HChar buf[200];
+ VG_(printf)("RW-Locks held: ");
+ show_lockset(thr->locksetA);
+ VG_(printf)("\n");
+ if (thr->locksetA != thr->locksetW) {
+ VG_(printf)(" W-Locks held: ");
+ show_lockset(thr->locksetW);
+ VG_(printf)("\n");
+ }
+
+ if (__bus_lock_Lock->heldBy) {
+ VG_(printf)("BHL is held\n");
+ }
+
+ show_sval(buf, sizeof(buf), sv_new);
+ VG_(message)(Vg_UserMsg, "TRACE: %p S%d/T%d %c %llx %s", a,
+ (int)thr->csegid, thr->errmsg_index,
+ is_w ? 'w' : 'r', sv_new, buf);
+ if (clo_trace_level >= 2) {
+ ThreadId tid = map_threads_maybe_reverse_lookup_SLOW(thr);
+ if (tid != VG_INVALID_THREADID) {
+ VG_(get_and_pp_StackTrace)( tid, 15);
+ }
+ }
+}
+
+
static
SVal msm_handle_write(Thread* thr, Addr a, SVal sv_old, Int sz)
{
@@ -3160,6 +3459,15 @@
// current locks.
LockSet currLS = thr->locksetW;
+ // Check if trace was requested for this address by a client request.
+ if (UNLIKELY(clo_trace_level > 0 && mem_trace_is_on(a))) {
+ do_trace = True;
+ }
+
+ if (UNLIKELY(clo_ignore_n != 1)) {
+ tl_assert(!address_may_be_ignored(a));
+ }
+
if (UNLIKELY(is_SHVAL_Race(sv_old))) {
// we already reported a race, don't bother again.
stats__msm_Race++;
@@ -3246,31 +3554,7 @@
done:
if (do_trace) {
- HChar buf[200];
-
- VG_(printf)("RW-Locks held: ");
- show_lockset(thr->locksetA);
- VG_(printf)("\n");
- if (thr->locksetA != thr->locksetW) {
- VG_(printf)(" W-Locks held: ");
- show_lockset(thr->locksetW);
- VG_(printf)("\n");
- }
-
- if (__bus_lock_Lock->heldBy) {
- VG_(printf)("BHL is held\n");
- }
-
- show_sval(buf, sizeof(buf), sv_new);
- VG_(message)(Vg_UserMsg, "TRACE: %p S%d/T%d %c %llx %s", a,
- (int)currS, thr->errmsg_index,
- 'w' , sv_new, buf);
- if (clo_trace_level >= 2) {
- ThreadId tid = map_threads_maybe_reverse_lookup_SLOW(thr);
- if (tid != VG_INVALID_THREADID) {
- VG_(get_and_pp_StackTrace)( tid, 15);
- }
- }
+ msm_do_trace(thr, a, sv_new, True);
}
if (clo_trace_level > 0 && !do_trace) {
@@ -3311,6 +3595,20 @@
// current locks.
LockSet currLS = thr->locksetA;
+ // Check if trace was requested for this address by a client request.
+ if (UNLIKELY(clo_trace_level > 0 && mem_trace_is_on(a))) {
+ do_trace = True;
+ }
+
+ if (UNLIKELY(clo_ignore_n != 1)) {
+ tl_assert(!address_may_be_ignored(a));
+ }
+
+ if (UNLIKELY(thr->ignore_reads)) {
+ sv_new = sv_old;
+ goto done;
+ }
+
if (UNLIKELY(is_SHVAL_Race(sv_old))) {
// we already reported a race, don't bother again.
stats__msm_Race++;
@@ -3402,31 +3700,7 @@
done:
if (do_trace) {
- HChar buf[200];
-
- VG_(printf)("RW-Locks held: ");
- show_lockset(thr->locksetA);
- VG_(printf)("\n");
- if (thr->locksetA != thr->locksetW) {
- VG_(printf)(" W-Locks held: ");
- show_lockset(thr->locksetW);
- VG_(printf)("\n");
- }
-
- if (__bus_lock_Lock->heldBy) {
- VG_(printf)("BHL is held\n");
- }
-
- show_sval(buf, sizeof(buf), sv_new);
- VG_(message)(Vg_UserMsg, "TRACE: %p S%d/T%d %c %llx %s", a,
- (int)currS, thr->errmsg_index,
- 'r', sv_new, buf);
- if (clo_trace_level >= 2) {
- ThreadId tid = map_threads_maybe_reverse_lookup_SLOW(thr);
- if (tid != VG_INVALID_THREADID) {
- VG_(get_and_pp_StackTrace)( tid, 15);
- }
- }
+ msm_do_trace(thr, a, sv_new, False);
}
if (clo_trace_level > 0 && !do_trace) {
@@ -4167,6 +4441,26 @@
/* ------------ Basic shadow memory read/write ops ------------ */
+// handle clo_ignore_n and clo_ignore_i.
+static inline Bool address_may_be_ignored ( Addr a ) {
+ UWord w = (UWord)a;
+ UWord n = clo_ignore_n;
+ UWord i = clo_ignore_i;
+ const Int sh = N_SECMAP_BITS;
+ tl_assert(n != 1); // must not be called if clo_ignore_n == 1
+ if (n == 0) return True;
+ // Optimize for the case when clo_ignore_n is a power of two.
+ if ((n & (n-1)) == 0) return (((w >> sh) & (n-1)) != i);
+ // Optimize for some more values.
+ if (n == 3) return (((w >> sh) % 3) != i);
+ if (n == 7) return (((w >> sh) % 7) != i);
+ if (n == 13) return (((w >> sh) % 13) != i);
+ // general case: slow (division).
+ if (((w >> sh) % n) != i) return True;
+ return False;
+}
+
+
static inline Bool aligned16 ( Addr a ) {
return 0 == (a & 1);
}
@@ -4414,6 +4708,7 @@
UWord cloff, tno, toff;
SVal svOld, svNew;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_read8s++;
cl = get_cacheline(a);
cloff = get_cacheline_offset(a);
@@ -4435,6 +4730,7 @@
UWord cloff, tno, toff;
SVal svOld, svNew;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_read16s++;
if (UNLIKELY(!aligned16(a))) goto slowcase;
cl = get_cacheline(a);
@@ -4468,6 +4764,7 @@
UWord cloff, tno, toff;
SVal svOld, svNew;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
if (UNLIKELY(!aligned32(a))) goto slowcase;
cl = get_cacheline(a);
cloff = get_cacheline_offset(a);
@@ -4498,6 +4795,7 @@
CacheLine* cl;
UWord cloff, tno, toff;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_read32s++;
if (UNLIKELY(!aligned32(a))) goto slowcase;
cl = get_cacheline(a);
@@ -4520,6 +4818,7 @@
UWord cloff, tno, toff;
SVal svOld, svNew;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_read64s++;
if (UNLIKELY(!aligned64(a))) goto slowcase;
cl = get_cacheline(a);
@@ -4545,6 +4844,7 @@
UWord cloff, tno, toff;
SVal svOld, svNew;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_write8s++;
cl = get_cacheline(a);
cloff = get_cacheline_offset(a);
@@ -4566,6 +4866,7 @@
UWord cloff, tno, toff;
SVal svOld, svNew;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_write16s++;
if (UNLIKELY(!aligned16(a))) goto slowcase;
cl = get_cacheline(a);
@@ -4599,6 +4900,7 @@
UWord cloff, tno, toff;
SVal svOld, svNew;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
if (UNLIKELY(!aligned32(a))) goto slowcase;
cl = get_cacheline(a);
cloff = get_cacheline_offset(a);
@@ -4629,6 +4931,7 @@
CacheLine* cl;
UWord cloff, tno, toff;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_write32s++;
if (UNLIKELY(!aligned32(a))) goto slowcase;
cl = get_cacheline(a);
@@ -4651,6 +4954,7 @@
UWord cloff, tno, toff;
SVal svOld, svNew;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_write64s++;
if (UNLIKELY(!aligned64(a))) goto slowcase;
cl = get_cacheline(a);
@@ -4675,6 +4979,7 @@
CacheLine* cl;
UWord cloff, tno, toff;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_set8s++;
cl = get_cacheline(a);
cloff = get_cacheline_offset(a);
@@ -4693,6 +4998,7 @@
CacheLine* cl;
UWord cloff, tno, toff;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_set16s++;
if (UNLIKELY(!aligned16(a))) goto slowcase;
cl = get_cacheline(a);
@@ -4728,6 +5034,7 @@
CacheLine* cl;
UWord cloff, tno, toff;
UShort descr;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_set32s++;
if (UNLIKELY(!aligned32(a))) goto slowcase;
cl = get_cacheline(a);
@@ -4765,6 +5072,7 @@
static void shadow_mem_set64 ( Thread* uu_thr_acc, Addr a, SVal svNew ) {
CacheLine* cl;
UWord cloff, tno, toff;
+ if (UNLIKELY(clo_ignore_n != 1 && address_may_be_ignored(a))) return;
stats__cline_set64s++;
if (UNLIKELY(!aligned64(a))) goto slowcase;
cl = get_cacheline(a);
@@ -5063,6 +5371,9 @@
}
}
+ // turn off memory trace
+ mem_trace_off(firstA, lastA);
+
/* --- Step 2 --- */
if (UNLIKELY(clo_trace_level > 0)) {
@@ -5163,6 +5474,7 @@
}
/* and get it out of map_locks */
map_locks_delete(lk->guestaddr);
+ unset_mu_is_cv(lk->guestaddr);
/* release storage (incl. associated .heldBy Bag) */
{ Lock* tmp = lk->admin;
del_LockN(lk);
@@ -5187,6 +5499,10 @@
/*--------- Event handler helpers (evhH__* functions) ---------*/
+
+static void evhH__do_cv_signal(Thread *thr, Word cond);
+static Bool evhH__do_cv_wait(Thread *thr, Word cond, Bool must_match_signal);
+
/* Create a new segment for 'thr', making it depend (.prev) on its
existing segment, bind together the SegmentID and Segment, and
return both of them. Also update 'thr' so it references the new
@@ -5291,6 +5607,12 @@
/* update the thread's held-locks set */
thr->locksetA = HG_(addToWS)( univ_lsets, thr->locksetA, (Word)lk );
thr->locksetW = HG_(addToWS)( univ_lsets, thr->locksetW, (Word)lk );
+
+ if (mu_is_cv(lock_ga)) {
+ // VG_(printf)("mu is cv: w-lock %p\n", lock_ga);
+ evhH__do_cv_wait(thr, lock_ga, False);
+ }
+
/* fall through */
error:
@@ -5360,6 +5682,12 @@
/* update the thread's held-locks set */
thr->locksetA = HG_(addToWS)( univ_lsets, thr->locksetA, (Word)lk );
/* but don't update thr->locksetW, since lk is only rd-held */
+
+ if (mu_is_cv(lock_ga)) {
+ // VG_(printf)("mu is cv: r-lock %p\n", lock_ga);
+ evhH__do_cv_wait(thr, lock_ga, False);
+ }
+
/* fall through */
error:
@@ -5471,6 +5799,11 @@
thr->locksetW
= HG_(delFromWS)( univ_lsets, thr->locksetW, (Word)lock );
}
+
+ if (mu_is_cv(lock_ga) ) {
+ // VG_(printf)("mu is cv: unlock %p\n", lock_ga);
+ evhH__do_cv_signal(thr, lock_ga);
+ }
/* fall through */
error:
@@ -6027,6 +6360,125 @@
}
}
+void evhH__do_cv_signal(Thread *thr, Word cond)
+{
+ static Thread *fake_thread;
+ SegmentID new_segid;
+ Segment* new_seg;
+ SegmentID fake_segid;
+ Segment* fake_seg;
+ Segment *signalling_seg = NULL;
+
+ map_cond_to_Segment_INIT();
+ if (clo_happens_before < 2) return;
+ /* create a new segment ... */
+ new_segid = 0; /* bogus */
+ new_seg = NULL;
+ evhH__start_new_segment_for_thread( &new_segid, &new_seg, thr );
+ tl_assert( SEG_id_is_sane(new_segid) );
+ tl_assert( is_sane_Segment(new_seg) );
+ tl_assert( new_seg->thr == thr );
+ tl_assert( is_sane_Segment(new_seg->prev) );
+ tl_assert( new_seg->prev->vts );
+ new_seg->vts = tick_VTS( new_seg->thr, new_seg->prev->vts );
+
+ /* ... and add the binding. */
+
+ if (fake_thread == NULL) {
+ SegmentID segid = mk_Segment(NULL, NULL, NULL);
+ Segment *seg = SEG_get(segid);
+ fake_thread = mk_Thread(segid);
+ seg->thr = fake_thread;
+ seg->vts = singleton_VTS(seg->thr, 1);
+ }
+
+
+ // create a fake segment.
+ evhH__start_new_segment_for_thread(&fake_segid, &fake_seg, fake_thread);
+ tl_assert( SEG_id_is_sane(fake_segid) );
+ tl_assert( is_sane_Segment(fake_seg) );
+ tl_assert( fake_seg->prev != NULL );
+ tl_assert( fake_seg->other == NULL );
+ fake_seg->vts = NULL;
+ fake_seg->other = new_seg->prev;
+
+
+ HG_(lookupFM)( map_cond_to_Segment,
+ NULL, (Word*)&signalling_seg,
+ (Word)cond );
+ if (signalling_seg != 0) {
+ fake_seg->prev = signalling_seg;
+
+ }
+ fake_seg->vts = tickL_and_joinR_VTS(fake_thread,
+ fake_seg->prev->vts,
+ fake_seg->other->vts);
+ HG_(addToFM)( map_cond_to_Segment, (Word)cond, (Word)(fake_seg) );
+ // FIXME. test67 gives false negative.
+ // But this looks more like a feature than a bug.
+ //
+ // FIXME. At this point the old signalling_seg is not needed any more
+ // if we use only VTS. If we stop using HB graph, we can have only
+ // one fake segment for a CV.
+
+}
+
+
+Bool evhH__do_cv_wait(Thread *thr, Word cond, Bool must_match_signal)
+{
+ SegmentID new_segid;
+ Segment* new_seg;
+ Segment* signalling_seg;
+ Bool found;
+ map_cond_to_Segment_INIT();
+ if (clo_happens_before >= 2) {
+ /* create a new segment ... */
+ new_segid = 0; /* bogus */
+ new_seg = NULL;
+ evhH__start_new_segment_for_thread( &new_segid, &new_seg, thr );
+ tl_assert( SEG_id_is_sane(new_segid) );
+ tl_assert( is_sane_Segment(new_seg) );
+ tl_assert( new_seg->thr == thr );
+ tl_assert( is_sane_Segment(new_seg->prev) );
+ tl_assert( new_seg->other == NULL);
+
+ /* and find out which thread signalled us; then add a dependency
+ edge back to it. */
+ signalling_seg = NULL;
+ found = HG_(lookupFM)( map_cond_to_Segment,
+ NULL, (Word*)&signalling_seg,
+ (Word)cond );
+ if (found) {
+ tl_assert(is_sane_Segment(signalling_seg));
+ tl_assert(new_seg->prev);
+ tl_assert(new_seg->prev->vts);
+ new_seg->other = signalling_seg;
+ new_seg->other_hint = 's';
+ tl_assert(new_seg->other->vts);
+ new_seg->vts = tickL_and_joinR_VTS(
+ new_seg->thr,
+ new_seg->prev->vts,
+ new_seg->other->vts );
+ return True;
+ } else {
+ if (must_match_signal) {
+ /* Hmm. How can a wait on 'cond' succeed if nobody signalled
+ it? If this happened it would surely be a bug in the
+ threads library. Or one of those fabled "spurious
+ wakeups". */
+ record_error_Misc( thr, "Bug in libpthread: pthread_cond_wait "
+ "succeeded on"
+ " without prior pthread_cond_post");
+ }
+ tl_assert(new_seg->prev->vts);
+ new_seg->vts = tick_VTS( new_seg->thr, new_seg->prev->vts );
+ return False;
+ }
+ }
+ return False;
+}
+
+
static void evh__HG_PTHREAD_COND_SIGNAL_PRE ( ThreadId tid, void* cond )
{
/* 'tid' has signalled on 'cond'. Start a new segment for this
@@ -6037,8 +6489,6 @@
back to it can be constructed. */
Thread* thr;
- SegmentID new_segid;
- Segment* new_seg;
if (SHOW_EVENTS >= 1)
VG_(printf)("evh__HG_PTHREAD_COND_SIGNAL_PRE(ctid=%d, cond=%p)\n",
@@ -6051,22 +6501,8 @@
// error-if: mutex is bogus
// error-if: mutex is not locked
- if (clo_happens_before >= 2) {
- /* create a new segment ... */
- new_segid = 0; /* bogus */
- new_seg = NULL;
- evhH__start_new_segment_for_thread( &new_segid, &new_seg, thr );
- tl_assert( SEG_id_is_sane(new_segid) );
- tl_assert( is_sane_Segment(new_seg) );
- tl_assert( new_seg->thr == thr );
- tl_assert( is_sane_Segment(new_seg->prev) );
- tl_assert( new_seg->prev->vts );
- new_seg->vts = tick_VTS( new_seg->thr, new_seg->prev->vts );
- /* ... and add the binding. */
- HG_(addToFM)( map_cond_to_Segment, (Word)cond,
- (Word)(new_seg->prev) );
- }
+ evhH__do_cv_signal(thr, (Word)cond);
}
/* returns True if it reckons 'mutex' is valid and held by this
@@ -6133,10 +6569,6 @@
the new segment back to it. */
Thread* thr;
- SegmentID new_segid;
- Segment* new_seg;
- Segment* signalling_seg;
- Bool found;
if (SHOW_EVENTS >= 1)
VG_(printf)("evh__HG_PTHREAD_COND_WAIT_POST"
@@ -6149,46 +6581,7 @@
// error-if: cond is also associated with a different mutex
- if (clo_happens_before >= 2) {
- /* create a new segment ... */
- new_segid = 0; /* bogus */
- new_seg = NULL;
- evhH__start_new_segment_for_thread( &new_segid, &new_seg, thr );
- tl_assert( SEG_id_is_sane(new_segid) );
- tl_assert( is_sane_Segment(new_seg) );
- tl_assert( new_seg->thr == thr );
- tl_assert( is_sane_Segment(new_seg->prev) );
- tl_assert( new_seg->other == NULL);
-
- /* and find out which thread signalled us; then add a dependency
- edge back to it. */
- signalling_seg = NULL;
- found = HG_(lookupFM)( map_cond_to_Segment,
- NULL, (Word*)&signalling_seg,
- (Word)cond );
- if (found) {
- tl_assert(is_sane_Segment(signalling_seg));
- tl_assert(new_seg->prev);
- tl_assert(new_seg->prev->vts);
- new_seg->other = signalling_seg;
- new_seg->other_hint = 's';
- tl_assert(new_seg->other->vts);
- new_seg->vts = tickL_and_joinR_VTS(
- new_seg->thr,
- new_seg->prev->vts,
- new_seg->other->vts );
- } else {
- /* Hmm. How can a wait on 'cond' succeed if nobody signalled
- it? If this happened it would surely be a bug in the
- threads library. Or one of those fabled "spurious
- wakeups". */
- record_error_Misc( thr, "Bug in libpthread: pthread_cond_wait "
- "succeeded on"
- " without prior pthread_cond_post");
- tl_assert(new_seg->prev->vts);
- new_seg->vts = tick_VTS( new_seg->thr, new_seg->prev->vts );
- }
- }
+ evhH__do_cv_wait(thr, (Word)cond, True);
}
@@ -7707,6 +8100,84 @@
break;
}
+ case _VG_USERREQ__HG_GET_THREAD_ID: { // -> Thread ID
+ Thread* thr;
+ thr = map_threads_maybe_lookup( tid );
+ tl_assert(thr); /* cannot fail */
+ *ret = (UWord)thr->errmsg_index;
+ break;
+ }
+
+ case _VG_USERREQ__HG_GET_SEGMENT_ID: { // -> SegmentID
+ Thread* thr;
+ thr = map_threads_maybe_lookup( tid );
+ tl_assert(thr); /* cannot fail */
+ *ret = (UWord)thr->csegid;
+ break;
+ }
+
+
+
+ case VG_USERREQ__HG_EXPECT_RACE: { // void*, char*, char *, int
+ Addr ptr = (Addr)args[1];
+ char *descr = (char*)args[2];
+ char *file = (char*)args[3];
+ int line = (int) args[4];
+ maybe_set_expected_error(ptr, descr, file, line, False);
+ break;
+ }
+
+ case VG_USERREQ__HG_BENIGN_RACE: { // void*, char*, char *, int
+ Addr ptr = (Addr)args[1];
+ char *descr = (char*)args[2];
+ char *file = (char*)args[3];
+ int line = (int) args[4];
+ maybe_set_expected_error(ptr, descr, file, line, True);
+ break;
+ }
+
+
+ case VG_USERREQ__HG_PCQ_CREATE: // void *
+ pcq_create(args[1]);
+ break;
+ case VG_USERREQ__HG_PCQ_DESTROY: // void *
+ pcq_destroy(args[1]);
+ break;
+ case VG_USERREQ__HG_PCQ_PUT: // void *
+ pcq_put(tid, args[1]);
+ break;
+ case VG_USERREQ__HG_PCQ_GET: // void *
+ pcq_get(tid, args[1]);
+ break;
+
+
+ case VG_USERREQ__HG_TRACE_MEM: // void *
+ mem_trace_on(args[1], tid);
+ break;
+
+ case VG_USERREQ__HG_MUTEX_IS_USED_AS_CONDVAR: // void *
+ set_mu_is_cv(args[1]);
+ break;
+
+ // These two client requests are useful to mark a section of code
+ // were user wants helgrind to ignore all reads.
+ // For and example of such case, see test69.
+ case VG_USERREQ__HG_IGNORE_READS_BEGIN: {
+ Thread *thr = map_threads_maybe_lookup( tid );
+ tl_assert(thr); /* cannot fail */
+ tl_assert(!thr->ignore_reads);
+ thr->ignore_reads = True;
+ break;
+ }
+ case VG_USERREQ__HG_IGNORE_READS_END: {
+ Thread *thr = map_threads_maybe_lookup( tid );
+ tl_assert(thr); /* cannot fail */
+ tl_assert(thr->ignore_reads);
+ thr->ignore_reads = False;
+ break;
+ }
+
+
default:
/* Unhandled Helgrind client request! */
tl_assert2(0, "unhandled Helgrind client request!");
@@ -7937,6 +8408,16 @@
}
}
+
+ if (1) { // Do not print an error if it is expected or benign.
+ ExpectedError *expected_error = get_expected_error((Word)data_addr);
+ if (expected_error) {
+ expected_error->detected = True;
+ return;
+ }
+ }
+
+
/* Ok, so we're really going to collect this race. */
tl_assert(sizeof(xe.XE.Race.descr1) == sizeof(xe.XE.Race.descr2));
xe.XE.Race.descr1[0] = xe.XE.Race.descr2[0] = 0;
@@ -8558,6 +9039,15 @@
else if (VG_CLO_STREQ(arg, "--happens-before=all"))
clo_happens_before = 2;
+ else if (VG_CLO_STREQN(11, arg, "--ignore-n=")) {
+ clo_ignore_n = VG_(atoll)(&arg[11]);
+ tl_assert(clo_ignore_n == 0 || (clo_ignore_n > 0 && clo_ignore_i < clo_ignore_n));
+ }
+ else if (VG_CLO_STREQN(11, arg, "--ignore-i=")) {
+ clo_ignore_i = VG_(atoll)(&arg[11]);
+ tl_assert(clo_ignore_n == 0 || (clo_ignore_n > 0 && clo_ignore_i < clo_ignore_n));
+ }
+
else if (VG_CLO_STREQ(arg, "--gen-vcg=no"))
clo_gen_vcg = 0;
else if (VG_CLO_STREQ(arg, "--gen-vcg=yes"))
@@ -8650,6 +9140,25 @@
if (clo_gen_vcg > 0)
segments__generate_vcg();
+
+ if (1) {
+ // If we expected some errors but not detected them -- complain.
+ Addr ptr;
+ ExpectedError *expected_error;
+ HG_(initIterFM)( map_expected_errors );
+ while (HG_(nextIterFM)( map_expected_errors, (Word*)&ptr,
+ (Word*)&expected_error )) {
+ if(expected_error->detected == False && !expected_error->is_benign) {
+ VG_(printf)("Expected race was not detected: %s:%d %p\t%s\n",
+ expected_error->file, expected_error->line,
+ ptr, expected_error->descr);
+ }
+ }
+ HG_(doneIterFM) ( map_expected_errors );
+ }
+
+
+
if (VG_(clo_verbosity) >= 2) {
if (1) {
@@ -8876,5 +9385,4 @@
/*--- end hg_main.c ---*/
/*--------------------------------------------------------------------*/
-// KCC: settings for VIM. remove if don't like.
// vim:shiftwidth=3:softtabstop=3:expandtab
|
|
From: <sv...@va...> - 2008-03-09 11:13:03
|
Author: sewardj Date: 2008-03-09 11:13:07 +0000 (Sun, 09 Mar 2008) New Revision: 7610 Log: Start a file recording how to build big applications for testing Valgrind in various ways. This is much easier than endlessly trying to remember how to build and run (eg) Firefox. Added: branches/HGDEV/docs/internals/BIG_APP_NOTES.txt Modified: branches/HGDEV/docs/internals/Makefile.am Added: branches/HGDEV/docs/internals/BIG_APP_NOTES.txt =================================================================== --- branches/HGDEV/docs/internals/BIG_APP_NOTES.txt (rev 0) +++ branches/HGDEV/docs/internals/BIG_APP_NOTES.txt 2008-03-09 11:13:07 UTC (rev 7610) @@ -0,0 +1,31 @@ + +Building Firefox-2.0.0.12 from source, for testing Helgrind +----------------------------------------------------------- + +wget +ftp://ftp.mozilla.org/pub/firefox/releases/2.0.0.12/source/firefox-2.0.0.12-source.tar.bz2 + +bzip2 -dc firefox-2.0.0.12-source.tar.bz2 | tar xvf - + +mv mozilla firefox-2.0.0.12 + +mkdir InstFirefox20012 +export XYZZYFOOBAR=`pwd`/InstFirefox20012 + +cd firefox-2.0.0.12 + +./configure --prefix=$XYZZYFOOBAR --enable-application=browser \ + --enable-optimize="-O -g" + +make -j 2 +make install + +cd ../InstFirefox20012 + +MOZ_NO_REMOTE=1 NO_EM_RESTART=1 \ +LD_LIBRARY_PATH=`pwd`/lib/firefox-2.0.0.12:\ +`pwd`/lib/firefox-2.0.0.12/components:\ +`pwd`/lib/firefox-2.0.0.12/plugins \ +/home/sewardj/VgTRUNK/hgdev/Inst/bin/valgrind --tool=helgrind \ +--trace-children=no -v ./lib/firefox-2.0.0.12/firefox-bin + Modified: branches/HGDEV/docs/internals/Makefile.am =================================================================== --- branches/HGDEV/docs/internals/Makefile.am 2008-03-09 11:06:41 UTC (rev 7609) +++ branches/HGDEV/docs/internals/Makefile.am 2008-03-09 11:13:07 UTC (rev 7610) @@ -1,6 +1,7 @@ EXTRA_DIST = \ 3_0_BUGSTATUS.txt 3_1_BUGSTATUS.txt \ 3_2_BUGSTATUS.txt 3_3_BUGSTATUS.txt \ + BIG_APP_NOTES.txt \ darwin-notes.txt darwin-syscalls.txt \ directory-structure.txt \ m_replacemalloc.txt \ |
|
From: <sv...@va...> - 2008-03-09 11:06:37
|
Author: sewardj
Date: 2008-03-09 11:06:41 +0000 (Sun, 09 Mar 2008)
New Revision: 7609
Log:
find_stack_by_addr: fast track common case
Modified:
branches/HGDEV/coregrind/m_stacks.c
Modified: branches/HGDEV/coregrind/m_stacks.c
===================================================================
--- branches/HGDEV/coregrind/m_stacks.c 2008-03-09 09:17:48 UTC (rev 7608)
+++ branches/HGDEV/coregrind/m_stacks.c 2008-03-09 11:06:41 UTC (rev 7609)
@@ -152,6 +152,10 @@
if (0 && 0 == (n_searches % 10000))
VG_(printf)("(hgdev) %lu searches, %lu steps, %lu fails\n",
n_searches, n_steps+1, n_fails);
+ /* fast track common case */
+ if (i && sp >= i->start && sp <= i->end)
+ return i;
+ /* else search the list */
while (i) {
n_steps++;
if (sp >= i->start && sp <= i->end) {
|
|
From: <sv...@va...> - 2008-03-09 09:17:50
|
Author: bart
Date: 2008-03-09 09:17:48 +0000 (Sun, 09 Mar 2008)
New Revision: 7608
Log:
Added an additional suppression pattern.
Modified:
trunk/glibc-2.X-drd.supp
Modified: trunk/glibc-2.X-drd.supp
===================================================================
--- trunk/glibc-2.X-drd.supp 2008-03-09 08:48:01 UTC (rev 7607)
+++ trunk/glibc-2.X-drd.supp 2008-03-09 09:17:48 UTC (rev 7608)
@@ -20,6 +20,11 @@
fun:exit
}
{
+ dl
+ exp-drd:ConflictingAccess
+ fun:_dl_fixup
+}
+{
dl-2.6.*
exp-drd:ConflictingAccess
obj:/lib*/ld-*.so
|