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
(6) |
2
(7) |
|
3
(12) |
4
(9) |
5
(12) |
6
(9) |
7
(18) |
8
(10) |
9
(17) |
|
10
(15) |
11
(22) |
12
(16) |
13
(18) |
14
(9) |
15
(14) |
16
(18) |
|
17
(24) |
18
(11) |
19
(15) |
20
(29) |
21
(19) |
22
(20) |
23
(9) |
|
24
(25) |
25
(25) |
26
(38) |
27
(22) |
28
(16) |
29
(17) |
|
|
From: Julian S. <js...@ac...> - 2008-02-21 23:33:44
|
> I thought we had such an event -- I thought Josef used it in Callgrind.
> In include/pub_tool_tooliface.h I see:
>
> track_start_client_code
> track_stop_client_code
> track_pre_thread_ll_create
> track_pre_thread_ll_create
> track_pre_thread_ll_exit
>
> Are any of these good enough? (I really thought we had a
> track_thread_switch event...)
Indeed we do; track_{start,stop}_client code should provide the
required info.
J
|
|
From: Nicholas N. <nj...@cs...> - 2008-02-21 21:20:28
|
On Thu, 21 Feb 2008, Bart Van Assche wrote: > On Thu, Feb 21, 2008 at 6:38 PM, Vince Weaver <vi...@cs...> wrote: >> To do this properly, it would be nice if it were possible to be notified >> whenever a thread-change happened. That way the statistics from the >> various threads could be kept separately. > > This would be useful for exp-drd too. What I do now is to compare the > result of VG_(get_running_tid)() with a cached value in order to > detect when Valgrind scheduled another thread. This test is performed > upon every load, every store, and every time the stack pointer is > modified. I thought we had such an event -- I thought Josef used it in Callgrind. In include/pub_tool_tooliface.h I see: track_start_client_code track_stop_client_code track_pre_thread_ll_create track_pre_thread_ll_create track_pre_thread_ll_exit Are any of these good enough? (I really thought we had a track_thread_switch event...) Nick |
|
From: Nicholas N. <nj...@cs...> - 2008-02-21 21:16:25
|
On Thu, 21 Feb 2008, Bart Van Assche wrote: >> One of the things I have come to realise in the past year or so >> is what a terrible programming model explicit shared-memory parallelism >> is. It's simply too hard for humans to understand and reason about >> (in all but the most trivial of applications): even small threaded >> programs are extremely hard to make sense of. > > It depends. Although understanding concurrent activities is always > hard, it is possible to write multithreaded software that is > relatively easy to read and to maintain. What I have learned during > the past ten years about writing multithreaded software is a.o. the > following: So basically you need various higher-level abstractions layered over pthreads, plus a strong dose of programmer discipline. So it's doable, but hoping everyone will get it right is optimistic. N |
|
From: <sv...@va...> - 2008-02-21 20:32:56
|
Author: bart Date: 2008-02-21 20:32:57 +0000 (Thu, 21 Feb 2008) New Revision: 7433 Log: Added a section about programming with threads, added an acknowledgements section and added more references. Modified: trunk/exp-drd/docs/README.txt Modified: trunk/exp-drd/docs/README.txt =================================================================== --- trunk/exp-drd/docs/README.txt 2008-02-21 13:19:36 UTC (rev 7432) +++ trunk/exp-drd/docs/README.txt 2008-02-21 20:32:57 UTC (rev 7433) @@ -14,24 +14,28 @@ to and reading from the shared memory. Since the invention of the multithreading concept, there is an ongoing debate about which way to model concurrent activities is better -- shared memory programming or -message passing [Ousterhout 1996]. This debate exists because each -model has significant advantages and disadvantages. While shared -memory programming relieves the programmer from writing code for the -exchange of data between concurrent activities and while shared memory -programming has a performance advantage over message passing, shared -memory programming is error prone. Shared memory programs can exhibit -data races and/or deadlocks. Data races are harmful because these may -lead to unpredictable results and nondeterministic behavior in -multithreaded programs. There are two ways to detect data races and -deadlocks: static analysis and runtime detection by a tool. Since -there do not yet exist any tools that can carry out static analysis of -data races or deadlocks, the only option to statically detect such -anomolies is source reading by a human. It takes a huge effort however -to detect all possible data races or deadlocks via source -reading. This is why tools for detecting data races and deadlocks at -runtime are essential. +message passing. This debate exists because each model has significant +advantages and disadvantages. While shared memory programming relieves +the programmer from writing code for the exchange of data between +concurrent activities and while shared memory programming has a +performance advantage over message passing, shared memory programming +is error prone. Shared memory programs can exhibit data races and/or +deadlocks. Data races are harmful because these may lead to +unpredictable results and nondeterministic behavior in multithreaded +programs. There are two ways to detect data races and deadlocks: +static analysis and runtime detection by a tool. Since there do not +yet exist any tools that can carry out static analysis of data races +or deadlocks, the only option to statically detect such anomalies is +source reading by a human. It takes a huge effort however to detect +all possible data races or deadlocks via source reading. This is why +tools for detecting data races and deadlocks at runtime are essential. +The de facto standard library for multithreading on Unix systems is +the POSIX threads library, also known as pthreads. The exp-drd tool +has been developed for multithreaded software that uses the POSIX +threads library. + Data Races ---------- @@ -115,8 +119,95 @@ tests than Helgrind. +Programming with Threads +------------------------ + +The difficulties with shared memory programming are well known and +have been outlined in more than one paper [Ousterhout 1996, Lee +2006]. It is possible however to develop and to debug multithreaded +shared memory software with a reasonable effort, even for large +applications (more than one million lines of code). In what follows an +approach is explained that has proven to work in practice. Before you +decide to use another approach, make sure you understand very well the +consequences of doing so. + +1. Use of synchronization calls. + +Do not call synchronization functions directly but use objects that +encapsulate the mutex, Mesa monitor and reader/writer locking policies. +Never use POSIX condition variables directly, since direct use of +condition variables can easily introduce race conditions. And never +lock or unlock mutexes explicitly -- use scoped locking instead. + +2. Data hiding. + +It is very important in multithreaded software to hide data that is +shared over threads. Make sure that all shared data is declared as +private data members of a class (not public, not protected). Design +the classes that contain shared data such that the number of data +members and the number of member functions is relatively small. Define +accessor functions as needed for querying and modifying member +data. Declare the associated locking objects also as private data +members, and document which locking object protects which data +members. Make sure that the query functions return a copy of data +members instead of a reference -- returning a reference would violate +data hiding anyway. This approach has a big advantage, namely that +correct use of a locking policy can be verified by reviewing one class +at a time. + +3. Modularity and hierarchy. + +For multithreaded software it is even more important than for single +threaded software that the software has a modular structure and that +there exists a hierarchy between modules. This way every call of a +function to another function can be classified as either a regular +function call (a call from a higher level to a lower level), a +callback (a call from a lower level to a higher level) or a recursive +function call. + +4. Avoiding deadlocks. + +Deadlocks can be nasty to solve since some deadlocks are very hard to +reproduce. Prevent deadlocks instead of waiting until one pops +up. Preventing deadlocks is possible by making sure that whenever two +or more mutexes are locked simultaneously, these mutexes are always +locked in the same order. One way to ensure this is by assigning each +mutex a locking order and by verifying the locking order at runtime. +This reduces the complexity of testing for absence of deadlocks from a +multithreaded to a single-threaded problem, which is a huge win. In +order to verify a locking order policy at run time, one can either use +a threading library with built-in support for verifying such a policy +or one can use a tool that verifies the locking order. + +Make sure that no mutexes are locked while invoking a callback +(calling a function from a higher level module) -- invoking a +callback while a mutex is locked is a well known way to trigger +a deadlock. + +5. Real-time software + +Software with hard real-time constraints is a special case. There +exist real-time applications that must be able to generate a response +within e.g. 1 ms after a certain input has been received. The proper +way to implement time-critical paths is not to call any function in +that path for which it is not known how long the function call will +take. Exmples for Linux of actions with an unknown call time are: +- Locking a mutex. +- Dynamic memory allocation via e.g. malloc() since malloc() internally +uses mutexes. +- File I/O, since file I/O uses several resources that are shared over +threads and even over processes. + +An approach that has proven to work for interthread communication +between real-time threads is the use of preallocated fixed size +message queueus, and to lock any data needed by any real-time thread +in memory (mlock()). Avoid mutexes with priority inheritance -- see +also [Yodaiken 2004] for more information. + + How to use DRD -------------- + To use this tool, specify --tool=drd on the Valgrind command line. @@ -133,9 +224,43 @@ * Elimination of several artificial limitations. +Acknowledgements +---------------- + +The exp-drd tool is built on top of the Valgrind core and VEX, which +proved to be an excellent infrastructure for building such a tool. + +During 2006, the early versions of drd were improved via helpful +feedback of Julian Seward and Nicholas Nethercote. Any bugs are my +responsibility of course. + +Some of the regression tests used to test exp-drd were developed by +Julian Seward as regression tests for the Helgrind tool. + +I would also like to thank Michiel Ronsse for introducing me a long +time ago to vector clocks and the JiTI and DIOTA projects. + + References ---------- +[Hansen 1972] + Per Brinch Hansen + A Comparison of Two Synchronizing Concepts. + Acta Informatica, 1 3(1972), pp. 190--199. + +[Dijkstra 1974] + Edsger W. Dijkstra. + Over seinpalen (About Semaphores). + Circulated privately (never published), 1974. + http://www.cs.utexas.edu/users/EWD/transcriptions/EWD00xx/EWD74.html + +[Hoare 1974] + C. A. R. Hoare. + Monitors: an operating system structuring concept + Communications of the ACM, October 1974, Vol. 17 No. 10, 1974. + http://www.cs.wisc.edu/~remzi/Classes/736/Fall2003/Papers/hoare-monitors.pdf + [Lamport 1978] Leslie Lamport. Time, clocks, and the ordering of events in a distributed system. @@ -143,6 +268,22 @@ http://research.microsoft.com/users/lamport/pubs/time-clocks.pdf http://portal.acm.org/citation.cfm?id=359563 +[Accetta 1986] + Mike Accetta, Robert Baron, William Bolosky, David Golub, Richard Rashid, + Avadis Tevanian and Michael Young. + Mach: A New Kernel Foundation For UNIX Development. + USENIX 1986 (Atlanta. Ga., June 9-13), pp. 93-112, 1986. + http://www.fsl.cs.sunysb.edu/~gopalan/seminar/papers/mach.pdf + +[Young 1987] + Michael Young, Avadis Tevanian, Richard Rashid, David Golub, + Jeffrey Eppinger, Jonathan Chew, William Bolosky, David Black, Robert Baron. + The duality of memory and communication in the implementation of a + multiprocessor operating system. + ACM Symposium on Operating Systems Principles, pp. 63-76, 1987. + http://csalpha.ist.unomaha.edu/~stanw/papers/csci8550/87-duality.pdf + http://portal.acm.org/citation.cfm?id=41457.37507 + [Netzer 1992] Robert H. B. Netzer and Barton P. Miller. What are race conditions? Some issues and formalizations. @@ -186,12 +327,19 @@ Lecture Notes in Computer Science, pp. 82-89, 2004. http://escher.elis.ugent.be/publ/Edocs/DOC/P104_076.pdf +[Yodaiken 2004] + Victor Yodaiken. + Against Priority Inheritance. + FSMLabs Technical Report, 2004. + http://www.yodaiken.com/papers/inherit.pdf + [Banerjee 2006a] Utpal Banerjee, Brian Bliss, Zhiqiang Ma, Paul Petersen. Unraveling Data Race Detection in the Intel® Thread Checker. First Workshop on Software Tools for Multi-core Systems (STMCS), in conjunction with IEEE/ACM International Symposium on Code Generation and Optimization (CGO), March 26, 2006, Manhattan, New York, NY. + http://www.isi.edu/~kintali/stmcs06/UnravelingDataRace.pdf [Banerjee 2006b] Utpal Banerjee, Brian Bliss, Zhiqiang Ma, Paul Petersen. @@ -201,6 +349,13 @@ http://www.cs.ucsb.edu/~tiwari/papers/threadchecker06 http://portal.acm.org/citation.cfm?id=1147416 +[Lee 2006] + Edward A. Lee. + The Problem with Threads. + IEEE Computer, Volume 39, Issue 5 (May 2006), pp. 33-42, 2006. + http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf + http://portal.acm.org/citation.cfm?id=1137232.1137289 + [Lu 2006] Shan Lu, Joseph Tucek, Feng Qin, Yuanyuan Zhou. AVIO: detecting atomicity violations via access interleaving invariants. @@ -220,7 +375,7 @@ [Müehlenfeld 2007] Arndt Müehlenfeld, Franz Wotawa. - Fault detection in multi-threaded c++ server applications. + Fault Detection in Multi-threaded C++ Server Applications. Proceedings of the 12th ACM SIGPLAN symposium on Principles and practice of parallel programming, San Jose, California, USA, poster session, pp. 142-143, 2007. |
|
From: Bart V. A. <bar...@gm...> - 2008-02-21 19:01:13
|
On Thu, Feb 21, 2008 at 6:38 PM, Vince Weaver <vi...@cs...> wrote: > To do this properly, it would be nice if it were possible to be notified > whenever a thread-change happened. That way the statistics from the > various threads could be kept separately. This would be useful for exp-drd too. What I do now is to compare the result of VG_(get_running_tid)() with a cached value in order to detect when Valgrind scheduled another thread. This test is performed upon every load, every store, and every time the stack pointer is modified. Bart. |
|
From: Vince W. <vi...@cs...> - 2008-02-21 17:38:48
|
Hello
I was looking at extending my Basic Block Vector generating plugin so that
it can handle multi-threaded apps.
To do this properly, it would be nice if it were possible to be notified
whenever a thread-change happened. That way the statistics from the
various threads could be kept separately.
I looked through the code, and it didn't look like functionality existed
for this already.
I've attached a patch that implements registering a thread callback, but
I'm not sure if this is the best way to accomplish this. Also, it does
make some intrusive changes to the core so I wanted to see what opinions
people have on if this is useful or not.
Thanks,
Vince
--- ./include/pub_tool_tooliface.h.orig 2008-02-20 17:22:26.000000000 -0500
+++ ./include/pub_tool_tooliface.h 2008-02-20 17:40:22.000000000 -0500
@@ -446,6 +446,8 @@
function here. */
extern void VG_(needs_final_IR_tidy_pass) ( IRSB*(*final_tidy)(IRSB*) );
+extern void VG_(needs_thread_callback) (void(*thread_switch) (ThreadId));
+
/* ------------------------------------------------------------------ */
/* Core events to track */
--- ./coregrind/m_scheduler/scheduler.c.orig 2008-02-20 17:29:34.000000000 -0500
+++ ./coregrind/m_scheduler/scheduler.c 2008-02-20 17:47:42.000000000 -0500
@@ -945,6 +945,9 @@
VG_(message)(Vg_DebugMsg, "thread %d: running for %d bbs",
tid, VG_(dispatch_ctr) - 1 );
+ if (VG_(needs).thread_callback)
+ (VG_(tdict).tool_thread_callback) ( tid );
+
trc = run_thread_for_a_while ( tid );
if (VG_(clo_trace_sched) && VG_(clo_verbosity) > 2) {
--- ./coregrind/m_tooliface.c.orig 2008-02-20 16:33:45.000000000 -0500
+++ ./coregrind/m_tooliface.c 2008-02-20 17:37:08.000000000 -0500
@@ -94,7 +94,8 @@
.data_syms = False,
.malloc_replacement = False,
.xml_output = False,
- .final_IR_tidy_pass = False
+ .final_IR_tidy_pass = False,
+ .thread_callback = False,
};
/* static */
@@ -217,6 +218,14 @@
VG_(tdict).tool_handle_client_request = handle;
}
+void VG_(needs_thread_callback)(
+ void(*thread_switch) (ThreadID)
+)
+{
+ VG_(needs).thread_callback = True;
+ VG_(tdict).tool_thread_callback=thread_switch;
+}
+
void VG_(needs_syscall_wrapper)(
void(*pre) (ThreadId, UInt),
void(*post)(ThreadId, UInt, SysRes res)
--- ./coregrind/pub_core_tooliface.h.orig 2008-02-20 17:08:00.000000000 -0500
+++ ./coregrind/pub_core_tooliface.h 2008-02-20 17:39:47.000000000 -0500
@@ -92,6 +92,7 @@
Bool malloc_replacement;
Bool xml_output;
Bool final_IR_tidy_pass;
+ Bool thread_callback;
}
VgNeeds;
@@ -160,6 +161,9 @@
// VG_(needs).final_IR_tidy_pass
IRSB* (*tool_final_IR_tidy_pass) (IRSB*);
+ // VG_(needs).thread_callback
+ void (*tool_thread_callback) (ThreadId);
+
// -- Event tracking functions ------------------------------------
void (*track_new_mem_startup) (Addr, SizeT, Bool, Bool, Bool);
void (*track_new_mem_stack_signal)(Addr, SizeT);
|
|
From: <sv...@va...> - 2008-02-21 13:19:34
|
Author: sewardj
Date: 2008-02-21 13:19:36 +0000 (Thu, 21 Feb 2008)
New Revision: 7432
Log:
Distinguish properly between types that have unknown size and types
that have known zero size.
Modified:
branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
branches/DATASYMS/coregrind/m_debuginfo/priv_tytypes.h
branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c
branches/DATASYMS/coregrind/m_debuginfo/storage.c
branches/DATASYMS/coregrind/m_debuginfo/tytypes.c
Modified: branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-02-21 03:41:23 UTC (rev 7431)
+++ branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-02-21 13:19:36 UTC (rev 7432)
@@ -1597,20 +1597,35 @@
RegSummary* regs,
Addr data_addr )
{
- SizeT var_szB;
- GXResult res;
- Bool show = False;
+ MaybeUWord muw;
+ SizeT var_szB;
+ GXResult res;
+ Bool show = False;
vg_assert(var->name);
vg_assert(var->type);
vg_assert(var->gexpr);
- var_szB = ML_(sizeOfType)(var->type);
+ /* Figure out how big the variable is. */
+ muw = ML_(sizeOfType)(var->type);
+ /* if this var has a type whose size is unknown, it should never
+ have been added. ML_(addVar) should have rejected it. */
+ vg_assert(muw.b == True);
+
+ var_szB = muw.w;
+
if (show) {
VG_(printf)("VVVV: find loc: %s :: ", var->name );
ML_(pp_Type_C_ishly)( var->type );
VG_(printf)("\n");
}
+ /* ignore zero-sized vars; they can never match anything. */
+ if (var_szB == 0) {
+ if (show)
+ VG_(printf)("VVVV: -> Fail (variable is zero sized)\n");
+ return False;
+ }
+
res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs );
if (show) {
Modified: branches/DATASYMS/coregrind/m_debuginfo/priv_tytypes.h
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/priv_tytypes.h 2008-02-21 03:41:23 UTC (rev 7431)
+++ branches/DATASYMS/coregrind/m_debuginfo/priv_tytypes.h 2008-02-21 13:19:36 UTC (rev 7432)
@@ -149,10 +149,14 @@
been converted into pointers) */
void ML_(pp_Type_C_ishly) ( Type* ty );
-/* How big is this type? (post-resolved only) */
+/* How big is this type? (post-resolved only) If . b in the
+ returned struct is False, the size is unknown. */
/* FIXME: check all pointers before dereferencing */
-SizeT ML_(sizeOfType)( Type* ty );
+typedef struct { UWord w; Bool b; } MaybeUWord;
+
+MaybeUWord ML_(sizeOfType)( Type* ty );
+
/* Describe where in the type 'offset' falls. Caller must
deallocate the resulting XArray. */
XArray* /*UChar*/ ML_(describe_type)( /*OUT*/OffT* residual_offset,
Modified: branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c 2008-02-21 03:41:23 UTC (rev 7431)
+++ branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c 2008-02-21 13:19:36 UTC (rev 7432)
@@ -996,6 +996,11 @@
any */
UChar* fName; /* declaring file name, or NULL */
Int fLine; /* declaring file line number, or zero */
+ /* offset in .debug_info (for debug printing only). NB:
+ approximate value ONLY! NOT TO BE RELIED ON. Is only stored
+ so as to help readers make sense of the debug printed
+ output. */
+ UWord dioff;
}
TempVar;
@@ -1523,6 +1528,7 @@
tv->fName = fileName;
tv->fLine = lineNo;
tv->next = *tempvars;
+ tv->dioff = saved_die_c_offset - 2; /* NB! NOT EXACT! */
*tempvars = tv;
}
TRACE_D3(" Recording this variable, with %ld PC range(s)\n",
@@ -2558,9 +2564,9 @@
/* We're set up to look at the fields of this DIE. Hand it off to
any parser(s) that want to see it. Since they will in general
- advance both the DIE and abbrev cursors, remember where their
- current settings so that we can then back up and do one final
- pass over the DIE, to print out its contents. */
+ advance both the DIE and abbrev cursors, remember their current
+ settings so that we can then back up and do one final pass over
+ the DIE, to print out its contents. */
start_die_c_offset = get_position_of_Cursor( c );
start_abbv_c_offset = get_position_of_Cursor( &abbv );
@@ -3003,6 +3009,8 @@
} else {
VG_(printf)(" FrB=none\n");
}
+ VG_(printf)(" .debug_info offset = <%lx> "
+ "(or thereabouts; not exact)\n", varp->dioff);
VG_(printf)(" declared at: %s:%d\n",
varp->fName ? varp->fName : (UChar*)"(null)",
varp->fLine );
Modified: branches/DATASYMS/coregrind/m_debuginfo/storage.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/storage.c 2008-02-21 03:41:23 UTC (rev 7431)
+++ branches/DATASYMS/coregrind/m_debuginfo/storage.c 2008-02-21 13:19:36 UTC (rev 7432)
@@ -377,7 +377,7 @@
vg_assert(di->have_rx_map && di->have_rw_map);
if (cfsi->base + cfsi->len - 1 < di->rx_map_avma
|| cfsi->base >= di->rx_map_avma + di->rx_map_size) {
- static Int complaints = 3;
+ static Int complaints = 10;
if (VG_(clo_trace_cfi) || complaints > 0) {
complaints--;
if (VG_(clo_verbosity) > 1) {
@@ -747,12 +747,14 @@
it. We will never be able to actually relate a data address to
a data object with zero size, so there's no point in storing
info on it. */
- if (ML_(sizeOfType)(type) == 0) {
- if (VG_(clo_verbosity) >= 0) {
+ if (ML_(sizeOfType)(type).b != True) {
+ static Int complaints = 10;
+ if (VG_(clo_verbosity) >= 2 && complaints > 0) {
VG_(message)(Vg_DebugMsg,
- "warning: addVar: zero or unknown size (%s)",
+ "warning: addVar: unknown size (%s)",
name
);
+ complaints--;
}
return;
}
Modified: branches/DATASYMS/coregrind/m_debuginfo/tytypes.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/tytypes.c 2008-02-21 03:41:23 UTC (rev 7431)
+++ branches/DATASYMS/coregrind/m_debuginfo/tytypes.c 2008-02-21 13:19:36 UTC (rev 7432)
@@ -352,40 +352,63 @@
}
+static MaybeUWord mk_MaybeUWord_Nothing ( void ) {
+ MaybeUWord muw;
+ muw.w = 0;
+ muw.b = False;
+ return muw;
+}
+static MaybeUWord mk_MaybeUWord_Just ( UWord w ) {
+ MaybeUWord muw;
+ muw.w = w;
+ muw.b = True;
+ return muw;
+}
+static MaybeUWord mul_MaybeUWord ( MaybeUWord muw1, MaybeUWord muw2 ) {
+ if (!muw1.b) { vg_assert(muw1.w == 0); return muw1; }
+ if (!muw2.b) { vg_assert(muw2.w == 0); return muw2; }
+ muw1.w *= muw2.w;
+ return muw1;
+}
+
/* How big is this type? (post-resolved only) */
/* FIXME: check all pointers before dereferencing */
-SizeT ML_(sizeOfType)( Type* ty )
+MaybeUWord ML_(sizeOfType)( Type* ty )
{
- SizeT eszB;
- Word i;
+ Word i;
+ MaybeUWord eszB;
switch (ty->tag) {
case Ty_Base:
vg_assert(ty->Ty.Base.szB > 0);
- return ty->Ty.Base.szB;
+ return mk_MaybeUWord_Just( ty->Ty.Base.szB );
case Ty_Qual:
return ML_(sizeOfType)( ty->Ty.Qual.typeR );
case Ty_TyDef:
if (!ty->Ty.TyDef.typeR)
- return 0; /*UNKNOWN*/
+ return mk_MaybeUWord_Nothing(); /*UNKNOWN*/
return ML_(sizeOfType)( ty->Ty.TyDef.typeR );
case Ty_PorR:
vg_assert(ty->Ty.PorR.szB == 4 || ty->Ty.PorR.szB == 8);
- return ty->Ty.PorR.szB;
+ return mk_MaybeUWord_Just( ty->Ty.PorR.szB );
case Ty_StOrUn:
- return ty->Ty.StOrUn.szB;
+ return ty->Ty.StOrUn.complete
+ ? mk_MaybeUWord_Just( ty->Ty.StOrUn.szB )
+ : mk_MaybeUWord_Nothing();
case Ty_Enum:
- return ty->Ty.Enum.szB;
+ return mk_MaybeUWord_Just( ty->Ty.Enum.szB );
case Ty_Array:
if (!ty->Ty.Array.typeR)
- return 0;
+ return mk_MaybeUWord_Nothing(); /*UNKNOWN*/
eszB = ML_(sizeOfType)( ty->Ty.Array.typeR );
for (i = 0; i < VG_(sizeXA)( ty->Ty.Array.bounds ); i++) {
TyBounds* bo
= *(TyBounds**)VG_(indexXA)(ty->Ty.Array.bounds, i);
vg_assert(bo);
if (!(bo->knownL && bo->knownU))
- return 0;
- eszB *= (SizeT)( bo->boundU - bo->boundL + 1 );
+ return mk_MaybeUWord_Nothing(); /*UNKNOWN*/
+ eszB = mul_MaybeUWord(
+ eszB,
+ mk_MaybeUWord_Just( bo->boundU - bo->boundL + 1 ));
}
return eszB;
default:
@@ -423,10 +446,11 @@
goto done;
case Ty_StOrUn: {
- Word i;
- GXResult res;
- TyField *field = NULL, *fields;
- OffT offMin = 0, offMax1 = 0;
+ Word i;
+ GXResult res;
+ MaybeUWord muw;
+ TyField *field = NULL, *fields;
+ OffT offMin = 0, offMax1 = 0;
if (!ty->Ty.StOrUn.isStruct) goto done;
fields = ty->Ty.StOrUn.fields;
if ((!fields) || VG_(sizeXA)(fields) == 0) goto done;
@@ -445,8 +469,11 @@
}
if (res.kind != GXR_Value)
continue;
- offMin = res.word;
- offMax1 = offMin + ML_(sizeOfType)( field->typeR );
+ muw = ML_(sizeOfType)( field->typeR );
+ if (muw.b != True)
+ goto done; /* size of field is unknown (?!) */
+ offMin = res.word;
+ offMax1 = offMin + muw.w;
if (offMin == offMax1)
continue;
vg_assert(offMin < offMax1);
@@ -470,8 +497,9 @@
}
case Ty_Array: {
- TyBounds* bounds;
- UWord size, eszB, ix;
+ MaybeUWord muw;
+ TyBounds* bounds;
+ UWord size, eszB, ix;
/* Just deal with the simple, common C-case: 1-D array,
zero based, known size. */
if (!(ty->Ty.Array.typeR && ty->Ty.Array.bounds))
@@ -485,7 +513,10 @@
goto done;
size = bounds->boundU - bounds->boundL + 1;
vg_assert(size >= 1);
- eszB = ML_(sizeOfType)( ty->Ty.Array.typeR );
+ muw = ML_(sizeOfType)( ty->Ty.Array.typeR );
+ if (muw.b != True)
+ goto done; /* size of element type not known */
+ eszB = muw.w;
if (eszB == 0) goto done;
ix = offset / eszB;
VG_(addBytesToXA)( xa, "[", 1 );
|
|
From: Konstantin S. <kon...@gm...> - 2008-02-21 11:44:46
|
> > Another way is with O(log N) new segments. No need for segments > that do not belong to any thread, and you can implement it using > the existing Segment representation easily.... Emm, not sure about this. What I did is not just to implement barrier, but to implement any graph structure where one segment may have arbitrary number of segments that happen-before it. A more general example is when we have N1 threads signaling on one CV and N2 threads waiting on this CV. I heard that this technique or something like it is explained in > Arndt Muehlenfeld's thesis, although I did not read it. I did exactly what described there. See http://code.google.com/p/data-race-test/wiki/BarrierSupport. > > > It is inefficient (in space) compared to having a single fake segment. For barrier with N threads I create N fake segments. So it's 2x less memory-efficient than in current helgrind. > > |
|
From: Bart V. A. <bar...@gm...> - 2008-02-21 11:33:37
|
On Wed, Feb 20, 2008 at 11:51 PM, Julian Seward <js...@ac...> wrote: > I would add that > POSIX pthreads is the de-facto standard a way to do shared > memory programming, and MPI is the de-facto standard way to do > message passing. > > I'm sure that message-passing has some failure modes (deadlocks) > in common with shared memory programming, and I wouldn't be at > all surprised to hear it could suffer from races too. The following failures can occur in message-passing software: * Deadlocks. A deadlock can occur when two or more threads or processes pass messages synchronously and are waiting in a cycle on each other. A deadlock can also occur when synchronously sending a message to a queue that has reached its maximal size, and the messaging implementation is such that it waits in this case. * Race conditions. If two or more threads or processes send a message to the same destination thread or process, and the receiver does not specify which sender it wants to receive from, then this is a race condition. * Message queue size problems. Some message passing implementations use queues with no other bound on the queue size than the amount of available memory. For a programmer it can be very convenient not having to compute the maximal possible size of a message queue. I consider this as a design bug however -- if it is not known at design time how big a message queue can become, how can it be known that the queue will fit in the available memory ? A typical problem that occurs in multithreaded software that uses message passing instead of shared memory for interthread communication is performance degradation due to cache misses. If each thread performs a small task, then frequently work has to be passed between threads and there are many context switches needed. Each context switch has a performance penalty not only because of the time needed for the context switch but more importantly because of the cache misses it causes. > One of the things I have come to realise in the past year or so > is what a terrible programming model explicit shared-memory parallelism > is. It's simply too hard for humans to understand and reason about > (in all but the most trivial of applications): even small threaded > programs are extremely hard to make sense of. It depends. Although understanding concurrent activities is always hard, it is possible to write multithreaded software that is relatively easy to read and to maintain. What I have learned during the past ten years about writing multithreaded software is a.o. the following: * Encapsulate the mutex and thread concepts in an object, this makes multithreaded software more compact and saves a lot of typing. * Use scoped locking instead of explicit lock / unlock calls. * Never use POSIX threads condition variables directly -- use higher level abstractions, e.g. the Mesa-style monitor concept. Using POSIX condition variables directly can easily introduce race conditions. * Encapsulate all thread-shared data in classes. Make sure these classes have a limited number of data members and a limited number of member functions. This makes it possible for a human to verify a locking policy via source reading. * Make sure that the locking policy can be verified by verifying one class at a time. This implies that classes may never return references to their members (which violates data hiding anyway). * With regard to deadlock avoidance, assign a locking order to mutexes and other synchronization objects -- a locking order is the order in which nested locking must be performed. * Make sure the locking order is verified at runtime. This is possible either by using a threading library that supports this or via a tool that verifies this at runtime. Verifying the locking order reduces the complexity of deadlock detection from a multithreaded to a single-threaded problem. This is a huge win for reproducibility. * Make sure the software consists of modules, and that there exists a hierarchy between modules. This is necessary such that function calls can be labeled as either "high-level module calls low-level module" (downcall) or a "callback". * Performing a downcall while a mutex is locked is OK. When performing a callback however, make sure that no mutexes are locked by the thread from which the callback is performed. The above guidelines have allowed me to develop (embedded) software that works very well: e.g. a 70 KLOC (embedded) application with about ten threads never crashed or deadlocked at a customer site. There was only one threading-related bug that was reported by a customer: strange data was sometimes displayed in one specific data field. The cause of this was that in one place shared data was not protected by locking. Bart. |
|
From: Bart V. A. <bar...@gm...> - 2008-02-21 11:19:32
|
On Wed, Feb 20, 2008 at 10:26 PM, Julian Seward <js...@ac...> wrote:
> Typically only a small fraction of the memory in a program is shared;
> most is unshared. It might be easier to turn it upside down, so the
> tool is notified of areas which may be shared. Hmm. Not sure if
> that is a good idea. It would give stronger checking but would
> require exhaustively annotating all locations which might become
> shared.
In my previous e-mail I forgot to mention that exhaustively annotating
all shared locations would require to modify standard libraries.
Consider e.g. the std::string class defined in the ANSI C++ standard.
The language standard allows the standard library implementor to
choose between an implementation based on reference counting or an
implementation that copies the contents of a string in the copy
constructor. Consider now the following typical implementation of an
accessor function:
class PersonInformation;
std::string PersonInformation::GetName()
{ /* lock mutex */; std::string result = m_Name; /* unlock mutex */;
return result; }
If the member function GetName() is called from another thread than
the thread in which m_Name was initialized, the data inside the m_Name
object will or will not be shared over threads. This depends on the
implementation of the std::string class (reference counting or
copying). Or: any annotations with regard to sharing should be added
inside the std::string class implementation. And the implementation of
this class is inside a library header, which we do not want to modify.
Bart.
|
|
From: Bart V. A. <bar...@gm...> - 2008-02-21 10:31:37
|
On Wed, Feb 20, 2008 at 10:26 PM, Julian Seward <js...@ac...> wrote: > Typically only a small fraction of the memory in a program is shared; > most is unshared. It might be easier to turn it upside down, so the > tool is notified of areas which may be shared. Hmm. Not sure if > that is a good idea. It would give stronger checking but would > require exhaustively annotating all locations which might become > shared. There exist applications where most data is shared between threads, and only a small fraction is owned by only one thread. E.g. in multithreaded finite element simulations the majority of the data consists of element data, which is shared over all computation threads. Bart Van Assche. |
|
From: Nicholas N. <nj...@cs...> - 2008-02-21 06:02:02
|
On Wed, 20 Feb 2008, Julian Seward wrote: > Typically only a small fraction of the memory in a program is shared; > most is unshared. Exactly. One of the nasty things about threads is that this fact isn't recognised in the programming model -- every thread has full access to every byte of memory that every other thread has access to, there's no protection. Nick |
|
From: Tom H. <th...@cy...> - 2008-02-21 05:04:57
|
Nightly build on alvis ( i686, Red Hat 7.3 ) started at 2008-02-21 03:15:05 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 338 tests, 80 stderr failures, 1 stdout failure, 29 post failures == memcheck/tests/addressable (stderr) memcheck/tests/badjump (stderr) memcheck/tests/describe-block (stderr) memcheck/tests/erringfds (stderr) memcheck/tests/leak-0 (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-pool-0 (stderr) memcheck/tests/leak-pool-1 (stderr) memcheck/tests/leak-pool-2 (stderr) memcheck/tests/leak-pool-3 (stderr) memcheck/tests/leak-pool-4 (stderr) memcheck/tests/leak-pool-5 (stderr) memcheck/tests/leak-regroot (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/long_namespace_xml (stderr) memcheck/tests/lsframe1 (stderr) memcheck/tests/lsframe2 (stderr) memcheck/tests/malloc_free_fill (stderr) memcheck/tests/match-overrun (stderr) memcheck/tests/noisy_child (stderr) memcheck/tests/partial_load_dflt (stderr) memcheck/tests/partial_load_ok (stderr) memcheck/tests/partiallydefinedeq (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/sigkill (stderr) memcheck/tests/stack_changes (stderr) memcheck/tests/x86/bug152022 (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) memcheck/tests/x86/xor-undef-x86 (stderr) memcheck/tests/xml1 (stderr) massif/tests/alloc-fns-A (post) massif/tests/alloc-fns-B (post) massif/tests/basic (post) massif/tests/basic2 (post) massif/tests/big-alloc (post) massif/tests/culling1 (stderr) massif/tests/culling2 (stderr) massif/tests/custom_alloc (post) massif/tests/deep-A (post) massif/tests/deep-B (stderr) massif/tests/deep-B (post) massif/tests/deep-C (stderr) massif/tests/deep-C (post) massif/tests/deep-D (post) massif/tests/ignoring (post) massif/tests/insig (post) massif/tests/long-names (post) massif/tests/long-time (post) massif/tests/new-cpp (post) massif/tests/null (post) massif/tests/one (post) massif/tests/overloaded-new (post) massif/tests/peak (post) massif/tests/peak2 (stderr) massif/tests/peak2 (post) massif/tests/realloc (stderr) massif/tests/realloc (post) massif/tests/thresholds_0_0 (post) massif/tests/thresholds_0_10 (post) massif/tests/thresholds_10_0 (post) massif/tests/thresholds_10_10 (post) massif/tests/thresholds_5_0 (post) massif/tests/thresholds_5_10 (post) massif/tests/zero1 (post) massif/tests/zero2 (post) none/tests/blockfault (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) helgrind/tests/hg01_all_ok (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/hg06_readshared (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc02_simple_tls (stderr) helgrind/tests/tc03_re_excl (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc07_hbl1 (stderr) helgrind/tests/tc08_hbl2 (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc11_XCHG (stderr) helgrind/tests/tc12_rwl_trivial (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc18_semabuse (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) helgrind/tests/tc24_nonzero_sem (stderr) exp-drd/tests/fp_race (stderr) exp-drd/tests/fp_race2 (stderr) exp-drd/tests/matinv (stderr) exp-drd/tests/pth_barrier (stderr) exp-drd/tests/pth_broadcast (stderr) exp-drd/tests/pth_cond_race (stderr) exp-drd/tests/pth_cond_race2 (stderr) exp-drd/tests/pth_create_chain (stderr) exp-drd/tests/pth_detached (stderr) exp-drd/tests/pth_detached2 (stderr) exp-drd/tests/sem_as_mutex (stderr) exp-drd/tests/sem_as_mutex2 (stderr) exp-drd/tests/sigalrm (stderr) exp-drd/tests/tc17_sembar (stderr) exp-drd/tests/tc18_semabuse (stderr) |
|
From: Tom H. <th...@cy...> - 2008-02-21 04:05:59
|
Nightly build on lloyd ( x86_64, Fedora 7 ) started at 2008-02-21 03:05:07 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 372 tests, 7 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/malloc_free_fill (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) memcheck/tests/xml1 (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) |
|
From: Tom H. <th...@cy...> - 2008-02-21 03:48:00
|
Nightly build on aston ( x86_64, Fedora Core 5 ) started at 2008-02-21 03:20:13 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 378 tests, 8 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/malloc_free_fill (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/xml1 (stderr) none/tests/blockfault (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) |
|
From: Tom H. <th...@cy...> - 2008-02-21 03:42:01
|
Nightly build on trojan ( x86_64, Fedora Core 6 ) started at 2008-02-21 03:25:04 GMT Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 376 tests, 6 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/bug133694 (stdout) memcheck/tests/x86/bug133694 (stderr) memcheck/tests/x86/scalar (stderr) none/tests/cmdline1 (stdout) none/tests/cmdline2 (stdout) none/tests/mremap (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 376 tests, 7 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/bug133694 (stdout) memcheck/tests/x86/bug133694 (stderr) memcheck/tests/x86/scalar (stderr) none/tests/cmdline1 (stdout) none/tests/cmdline2 (stdout) none/tests/mremap (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Thu Feb 21 03:31:39 2008 --- new.short Thu Feb 21 03:42:05 2008 *************** *** 8,10 **** ! == 376 tests, 7 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) --- 8,10 ---- ! == 376 tests, 6 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) *************** *** 18,20 **** none/tests/mremap2 (stdout) - helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc20_verifywrap (stderr) --- 18,19 ---- |
|
From: <sv...@va...> - 2008-02-21 03:41:30
|
Author: sewardj
Date: 2008-02-21 03:41:23 +0000 (Thu, 21 Feb 2008)
New Revision: 7431
Log:
Deal with various Dwarf3 artefacts produced by icc9.
Modified:
branches/DATASYMS/coregrind/m_debuginfo/d3basics.c
branches/DATASYMS/coregrind/m_debuginfo/priv_tytypes.h
branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c
Modified: branches/DATASYMS/coregrind/m_debuginfo/d3basics.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/d3basics.c 2008-02-21 01:50:10 UTC (rev 7430)
+++ branches/DATASYMS/coregrind/m_debuginfo/d3basics.c 2008-02-21 03:41:23 UTC (rev 7431)
@@ -560,6 +560,20 @@
uw1 += (UWord)read_leb128U( &expr );
PUSH(uw1);
break;
+ case DW_OP_GNU_push_tls_address:
+ /* GDB contains the following cryptic comment: */
+ /* Variable is at a constant offset in the thread-local
+ storage block into the objfile for the current thread and
+ the dynamic linker module containing this expression. Here
+ we return returns the offset from that base. The top of the
+ stack has the offset from the beginning of the thread
+ control block at which the variable is located. Nothing
+ should follow this operator, so the top of stack would be
+ returned. */
+ /* But no spec resulting from Googling. Punt for now. */
+ FAIL("warning: evaluate_Dwarf3_Expr: unhandled "
+ "DW_OP_GNU_push_tls_address");
+ /*NOTREACHED*/
default:
if (!VG_(clo_xml))
VG_(message)(Vg_DebugMsg,
Modified: branches/DATASYMS/coregrind/m_debuginfo/priv_tytypes.h
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/priv_tytypes.h 2008-02-21 01:50:10 UTC (rev 7430)
+++ branches/DATASYMS/coregrind/m_debuginfo/priv_tytypes.h 2008-02-21 03:41:23 UTC (rev 7431)
@@ -89,7 +89,7 @@
struct {
UChar* name; /* in DebugInfo.strchunks */
Int szB;
- UChar enc; /* S:signed U:unsigned F:floating */
+ UChar enc; /* S:signed U:unsigned F:floating C:complex float */
} Base;
struct {
Int szB;
Modified: branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c 2008-02-21 01:50:10 UTC (rev 7430)
+++ branches/DATASYMS/coregrind/m_debuginfo/readdwarf3.c 2008-02-21 03:41:23 UTC (rev 7431)
@@ -166,6 +166,11 @@
vg_assert(is_sane_Cursor(c));
}
+static /*signed*/Word get_remaining_length_Cursor ( Cursor* c ) {
+ vg_assert(is_sane_Cursor(c));
+ return c->region_szB - c->region_next;
+}
+
static UChar* get_address_of_Cursor ( Cursor* c ) {
vg_assert(is_sane_Cursor(c));
return &c->region_start_img[ c->region_next ];
@@ -1835,6 +1840,8 @@
type->Ty.Base.enc = 'S'; break;
case DW_ATE_float:
type->Ty.Base.enc = 'F'; break;
+ case DW_ATE_complex_float:
+ type->Ty.Base.enc = 'C'; break;
default:
goto bad_DIE;
}
@@ -1843,15 +1850,28 @@
/* Do we have something that looks sane? */
if (/* must have a name */
type->Ty.Base.name == NULL
- /* and a plausible size */
- || type->Ty.Base.szB < 1 || type->Ty.Base.szB > 16
+ /* and a plausible size. Yes, really 32: "complex long
+ double" apparently has size=32 */
+ || type->Ty.Base.szB < 0 || type->Ty.Base.szB > 32
/* and a plausible encoding */
|| (type->Ty.Base.enc != 'U'
&& type->Ty.Base.enc != 'S'
- && type->Ty.Base.enc != 'F'))
+ && type->Ty.Base.enc != 'F'
+ && type->Ty.Base.enc != 'C'))
goto bad_DIE;
- else
- goto acquire_Type;
+ /* Last minute hack: if we see this
+ <1><515>: DW_TAG_base_type
+ DW_AT_byte_size : 0
+ DW_AT_encoding : 5
+ DW_AT_name : void
+ convert it into a real Void type. */
+ if (type->Ty.Base.szB == 0
+ && 0 == VG_(strcmp)("void", type->Ty.Base.name)) {
+ VG_(memset)(type, 0, sizeof(*type));
+ type->tag = Ty_Void;
+ type->Ty.Void.isFake = False; /* it's a real one! */
+ }
+ goto acquire_Type;
}
if (dtag == DW_TAG_pointer_type || dtag == DW_TAG_reference_type) {
@@ -1860,6 +1880,14 @@
/* target type defaults to void */
type->Ty.PorR.typeR = D3_FAKEVOID_CUOFF;
type->Ty.PorR.isPtr = dtag == DW_TAG_pointer_type;
+ /* Pointer types don't *have* to specify their size, in which
+ case we assume it's a machine word. But if they do specify
+ it, it must be a machine word :-) This probably assumes that
+ the word size of the Dwarf3 we're reading is the same size as
+ that on the machine. gcc appears to give a size whereas icc9
+ doesn't. */
+ if (type->Ty.PorR.isPtr)
+ type->Ty.PorR.szB = sizeof(Word);
while (True) {
DW_AT attr = (DW_AT) get_ULEB128( c_abbv );
DW_FORM form = (DW_FORM)get_ULEB128( c_abbv );
@@ -2408,8 +2436,8 @@
case Ty_Base:
enc = ty->Ty.Base.enc;
if ((!ty->Ty.Base.name)
- || ty->Ty.Base.szB < 1 || ty->Ty.Base.szB > 16
- || (enc != 'S' && enc != 'U' && enc != 'F'))
+ || ty->Ty.Base.szB < 1 || ty->Ty.Base.szB > 32
+ || (enc != 'S' && enc != 'U' && enc != 'F' && enc != 'C'))
goto baaad;
break;
case Ty_TyDef:
@@ -2809,8 +2837,19 @@
while (True) {
UWord cu_start_offset, cu_offset_now;
CUConst cc;
- if (is_at_end_Cursor( &info ))
+
+ /* It seems icc9 finishes the DIE info before debug_info_sz
+ bytes have been used up. So be flexible, and declare the
+ sequence complete if there is not enough remaining bytes to
+ hold even the smallest conceivable CU header. (11 bytes I
+ reckon). */
+ Word avail = get_remaining_length_Cursor( &info );
+ if (avail < 11) {
+ if (avail > 0)
+ TRACE_D3("new_dwarf3_reader_wrk: warning: "
+ "%ld unused bytes after end of DIEs\n", avail);
break;
+ }
/* Check the varparser's stack is in a sane state. */
{ Int i;
@@ -2875,7 +2914,7 @@
&info, td3, &cc, 0 );
cu_offset_now = get_position_of_Cursor( &info );
- if (0) TRACE_D3("offset now %ld, d-i-size %ld\n",
+ if (1) TRACE_D3("offset now %ld, d-i-size %ld\n",
cu_offset_now, debug_info_sz);
if (cu_offset_now > debug_info_sz)
barf("toplevel DIEs beyond end of CU");
|
|
From: Tom H. <th...@cy...> - 2008-02-21 03:16:08
|
Nightly build on gill ( x86_64, Fedora Core 2 ) started at 2008-02-21 03:00:04 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 378 tests, 29 stderr failures, 3 stdout failures, 0 post failures == memcheck/tests/malloc_free_fill (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_switch (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) none/tests/amd64/insn_ssse3 (stdout) none/tests/amd64/insn_ssse3 (stderr) none/tests/amd64/ssse3_misaligned (stderr) none/tests/blockfault (stderr) none/tests/fdleak_fcntl (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) none/tests/x86/insn_ssse3 (stdout) none/tests/x86/insn_ssse3 (stderr) none/tests/x86/ssse3_misaligned (stderr) helgrind/tests/hg01_all_ok (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) |
|
From: <sv...@va...> - 2008-02-21 01:50:11
|
Author: sewardj
Date: 2008-02-21 01:50:10 +0000 (Thu, 21 Feb 2008)
New Revision: 7430
Log:
When evaluating Dwarf3 expressions, clearly distinguish between those
that denote values (addresses) and those that denote identities of
registers. Use this to handle DW_AT_frame_base expressions whose
expression denotes a register name rather than a value.
Modified:
branches/DATASYMS/coregrind/m_debuginfo/d3basics.c
branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
branches/DATASYMS/coregrind/m_debuginfo/priv_d3basics.h
branches/DATASYMS/coregrind/m_debuginfo/tytypes.c
Modified: branches/DATASYMS/coregrind/m_debuginfo/d3basics.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/d3basics.c 2008-02-20 15:20:33 UTC (rev 7429)
+++ branches/DATASYMS/coregrind/m_debuginfo/d3basics.c 2008-02-21 01:50:10 UTC (rev 7430)
@@ -408,9 +408,8 @@
# define FAIL(_str) \
do { \
- GXResult res; \
- res.res = 0; \
- res.failure = (_str); \
+ res.kind = GXR_Failure; \
+ res.word = (UWord)(_str); \
return res; \
} while (0)
@@ -436,16 +435,44 @@
UChar* limit;
Int sp; /* # of top element: valid is -1 .. N_EXPR_STACK-1 */
Addr stack[N_EXPR_STACK]; /* stack of addresses, as per D3 spec */
- GXResult fbval;
+ GXResult fbval, res;
Addr a1;
Word sw1;
UWord uw1;
+ Bool ok;
sp = -1;
vg_assert(expr);
vg_assert(exprszB >= 0);
limit = expr + exprszB;
+ /* Deal with the case where the entire expression is a single
+ Register Name Operation (D3 spec sec 2.6.1). Then the
+ denotation of the expression as a whole is a register name. */
+ if (exprszB == 1
+ && expr[0] >= DW_OP_reg0 && expr[0] <= DW_OP_reg31) {
+ res.kind = GXR_RegNo;
+ res.word = (UWord)(expr[0] - DW_OP_reg0);
+ return res;
+ }
+ if (exprszB > 1
+ && expr[0] == DW_OP_regx) {
+ /* JRS: 2008Feb20: I believe the following is correct, but would
+ like to see a test case show up before enabling it. */
+ vg_assert(0);
+ expr++;
+ res.kind = GXR_RegNo;
+ res.word = (UWord)read_leb128U( &expr );
+ if (expr != limit)
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_regx*: invalid expr size");
+ else
+ return res;
+ /*NOTREACHED*/
+ }
+
+ /* Evidently this expresion denotes a value, not a register name.
+ So evaluate it accordingly. */
+
if (push_initial_zero)
PUSH(0);
@@ -479,19 +506,37 @@
FAIL("evaluate_Dwarf3_Expr: DW_OP_fbreg with "
"no expr for fbreg present");
fbval = ML_(evaluate_GX)(fbGX, NULL, regs);
- if (fbval.failure)
- return fbval;
+ /* Convert fbval into something we can use. If we got a
+ Value, no problem. However, as per D3 spec sec 3.3.5
+ (Low Level Information) sec 2, we could also get a
+ RegNo, and that is taken to mean the value in the
+ indicated register. So we have to manually
+ "dereference" it. */
+ a1 = 0;
+ switch (fbval.kind) {
+ case GXR_Failure:
+ return fbval; /* propagate failure */
+ case GXR_Value:
+ a1 = fbval.word; break; /* use as-is */
+ case GXR_RegNo:
+ ok = get_Dwarf_Reg( &a1, fbval.word, regs );
+ if (!ok) return fbval; /* propagate failure */
+ break;
+ default:
+ vg_assert(0);
+ }
sw1 = (Word)read_leb128S( &expr );
- PUSH( fbval.res + sw1 );
+ PUSH( a1 + sw1 );
break;
/* DW_OP_breg* denotes 'contents of specified register, plus
constant offset'. So provided we know what the register's
value is, we can evaluate this. Contrast DW_OP_reg*,
which indicates that denoted location is in a register
- itself. For DW_OP_reg* we must always fail, since this
- function is intended to compute a memory address of some
- kind. See D3 Spec sec 2.6.1 ("Register Name Operations")
- for details. */
+ itself. If DW_OP_reg* shows up here the expression is
+ malformed, since we are evaluating for value now, and
+ DW_OP_reg* denotes a register location, not a value. See
+ D3 Spec sec 2.6.1 ("Register Name Operations") for
+ details. */
case DW_OP_breg0 ... DW_OP_breg31:
if (!regs)
FAIL("evaluate_Dwarf3_Expr: DW_OP_breg* but no reg info");
@@ -504,9 +549,11 @@
break;
/* As per comment on DW_OP_breg*, the following denote that
the value in question is in a register, not in memory. So
- we simply return failure. */
+ we simply return failure. (iow, the expression is
+ malformed). */
case DW_OP_reg0 ... DW_OP_reg31:
- FAIL("evaluate_Dwarf3_Expr: DW_OP_reg* (value is in a register)");
+ FAIL("evaluate_Dwarf3_Expr: DW_OP_reg* "
+ "whilst evaluating for a value");
break;
case DW_OP_plus_uconst:
POP(uw1);
@@ -525,13 +572,10 @@
}
vg_assert(sp >= 0 && sp < N_EXPR_STACK);
-
- { GXResult res;
- res.res = stack[sp];
- res.failure = NULL;
- return res;
- }
-
+ res.word = stack[sp];
+ res.kind = GXR_Value;
+ return res;
+
# undef POP
# undef PUSH
# undef FAIL
@@ -558,8 +602,8 @@
uc = *p++;
if (uc == 1) { /*isEnd*/
/* didn't find any matching range. */
- res.res = 0;
- res.failure = "no matching range";
+ res.kind = GXR_Failure;
+ res.word = (UWord)"no matching range";
return res;
}
vg_assert(uc == 0);
@@ -593,6 +637,21 @@
}
+void ML_(pp_GXResult) ( GXResult res )
+{
+ switch (res.kind) {
+ case GXR_Failure:
+ VG_(printf)("GXR_Failure(%s)", (HChar*)res.word); break;
+ case GXR_Value:
+ VG_(printf)("GXR_Value(0x%lx)", res.word); break;
+ case GXR_RegNo:
+ VG_(printf)("GXR_RegNo(%lu)", res.word); break;
+ default:
+ VG_(printf)("GXR_???"); break;
+ }
+}
+
+
/*--------------------------------------------------------------------*/
/*--- end d3basics.c ---*/
/*--------------------------------------------------------------------*/
Modified: branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-02-20 15:20:33 UTC (rev 7429)
+++ branches/DATASYMS/coregrind/m_debuginfo/debuginfo.c 2008-02-21 01:50:10 UTC (rev 7430)
@@ -1613,11 +1613,16 @@
res = ML_(evaluate_GX)( var->gexpr, var->fbGX, regs );
- if (show) VG_(printf)("VVVV: -> 0x%lx %s\n", res.res,
- res.failure ? res.failure : "(success)");
- if (!res.failure && res.res <= data_addr
- && data_addr < res.res + var_szB) {
- *offset = data_addr - res.res;
+ if (show) {
+ VG_(printf)("VVVV: -> ");
+ ML_(pp_GXResult)( res );
+ VG_(printf)("\n");
+ }
+
+ if (res.kind == GXR_Value
+ && res.word <= data_addr
+ && data_addr < res.word + var_szB) {
+ *offset = data_addr - res.word;
return True;
} else {
return False;
Modified: branches/DATASYMS/coregrind/m_debuginfo/priv_d3basics.h
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/priv_d3basics.h 2008-02-20 15:20:33 UTC (rev 7429)
+++ branches/DATASYMS/coregrind/m_debuginfo/priv_d3basics.h 2008-02-21 01:50:10 UTC (rev 7430)
@@ -595,14 +595,20 @@
struct { Addr ip; Addr sp; Addr fp; }
RegSummary;
-/* This describes the result of evaluating a DWARF3 expression. If
- .failure is NULL, then evaluation succeeded and produced .res as
- the result. Else .failure is a zero terminated const string
- summarising the reason for failure. */
+/* This describes the result of evaluating a DWARF3 expression.
+ GXR_Failure: failed; .word is an asciiz string summarising why
+ GXR_Value: evaluated to a value, in .word
+ GXR_RegNo: evaluated to a DWARF3 register number, in .word
+*/
typedef
- struct { UWord res; HChar* failure; }
+ struct {
+ enum { GXR_Failure, GXR_Value, GXR_RegNo } kind;
+ UWord word;
+ }
GXResult;
+void ML_(pp_GXResult) ( GXResult res );
+
/* Evaluate a guarded expression. If regs is NULL, then gx is assumed
(and checked) to contain just a single guarded expression, with a
guard which covers the entire address space and so always evaluates
Modified: branches/DATASYMS/coregrind/m_debuginfo/tytypes.c
===================================================================
--- branches/DATASYMS/coregrind/m_debuginfo/tytypes.c 2008-02-20 15:20:33 UTC (rev 7429)
+++ branches/DATASYMS/coregrind/m_debuginfo/tytypes.c 2008-02-21 01:50:10 UTC (rev 7430)
@@ -438,10 +438,14 @@
field->loc->bytes, field->loc->nbytes,
NULL/*fbGX*/, NULL/*RegSummary*/,
True/*push_initial_zero*/ );
- if (0) VG_(printf)("QQQ %lu %s\n", res.res,res.failure);
- if (res.failure)
+ if (0) {
+ VG_(printf)("QQQ ");
+ ML_(pp_GXResult)(res);
+ VG_(printf)("\n");
+ }
+ if (res.kind != GXR_Value)
continue;
- offMin = res.res;
+ offMin = res.word;
offMax1 = offMin + ML_(sizeOfType)( field->typeR );
if (offMin == offMax1)
continue;
|