|
From: <sv...@va...> - 2009-05-31 18:54:01
|
Author: bart Date: 2009-05-31 19:53:54 +0100 (Sun, 31 May 2009) New Revision: 10186 Log: - Added support for most of the ANNOTATE_...() macro's supported by ThreadSanitizer. - Modified DRD's error reporting code such that it does no longer let the Valgrind core print the Valgrind thread ID but that it now prints the DRD thread ID and name. Updated expected output files where necessary. - Modified drd/test/Makefile.am such that the tests using gcc's built-in functions for atomic memory access such that these are only compiled when the gcc version in use supports these built-in functions. Added: trunk/drd/tests/annotate_ignore_read.stderr.exp trunk/drd/tests/annotate_ignore_read.vgtest trunk/drd/tests/annotate_order_1.stderr.exp trunk/drd/tests/annotate_order_1.vgtest trunk/drd/tests/annotate_order_2.stderr.exp trunk/drd/tests/annotate_order_2.vgtest trunk/drd/tests/annotate_order_3.stderr.exp trunk/drd/tests/annotate_order_3.vgtest trunk/drd/tests/annotate_rwlock.c trunk/drd/tests/annotate_rwlock.stderr.exp trunk/drd/tests/annotate_rwlock.vgtest trunk/drd/tests/annotate_spinlock.stderr.exp trunk/drd/tests/annotate_spinlock.vgtest trunk/drd/tests/annotate_trace_memory.stderr.exp trunk/drd/tests/annotate_trace_memory.vgtest trunk/drd/tests/atomic_var.stderr.exp trunk/drd/tests/circular_buffer.stderr.exp trunk/drd/tests/thread_name.c trunk/drd/tests/thread_name.stderr.exp trunk/drd/tests/thread_name.vgtest Removed: trunk/drd/tests/atomic_var.stderr.exp-with-atomic-builtins trunk/drd/tests/atomic_var.stderr.exp-without-atomic-builtins trunk/drd/tests/circular_buffer.stderr.exp-with-atomic-builtins trunk/drd/tests/circular_buffer.stderr.exp-without-atomic-builtins Modified: trunk/drd/TODO.txt trunk/drd/Testing.txt trunk/drd/drd.h trunk/drd/drd_barrier.c trunk/drd/drd_clientreq.c trunk/drd/drd_clientreq.h trunk/drd/drd_cond.c trunk/drd/drd_cond.h trunk/drd/drd_error.c trunk/drd/drd_error.h trunk/drd/drd_load_store.c trunk/drd/drd_main.c trunk/drd/drd_mutex.c trunk/drd/drd_rwlock.c trunk/drd/drd_rwlock.h trunk/drd/drd_semaphore.c trunk/drd/drd_thread.c trunk/drd/drd_thread.h trunk/drd/tests/ trunk/drd/tests/Makefile.am trunk/drd/tests/atomic_var.c trunk/drd/tests/circular_buffer.c trunk/drd/tests/hg04_race.stderr.exp trunk/drd/tests/hg05_race2.stderr.exp trunk/drd/tests/hg05_race2.stderr.exp-powerpc trunk/drd/tests/rwlock_test.c trunk/drd/tests/sigalrm.c Modified: trunk/drd/TODO.txt =================================================================== --- trunk/drd/TODO.txt 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/TODO.txt 2009-05-31 18:53:54 UTC (rev 10186) @@ -1,29 +1,34 @@ -Last updated July 1, 2008. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Last updated May 30, 2009. +~~~~~~~~~~~~~~~~~~~~~~~~~~ -Data-race detection algorithm -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Memory pool support. -- Find out why DRD reports an error on the POSIX implementation of libgomp.so. +The DRD tool +~~~~~~~~~~~~ +- Eliminate Valgrind's thread ID's from DRD's output, and only keep the + DrdThreadId. +- Add support for Ist_CAS once the DCAS branch has been merged to the trunk. - Add locking order checking. Start from the following information: * http://sourceforge.net/mailarchive/message.php?msg_id=alpine.LNX.1.10.0803270822080.17890%40mudge.stoecker.eu * http://lwn.net/Articles/185605/ * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/lockdep-design.txt;h=488773018152056ea159685e732e42452a7ae142;hb=HEAD -- Make sure tc14_laog_dinphils is run during exp-drd regression tests +- Make sure tc14_laog_dinphils is run during drd regression tests (only possible after locking order checking is implemented). +- Evaluate whether integration of drd with one of the available Valgrind GUI's + makes sense (http://valgrind.org/downloads/guis.html). - Find out why no variable name information is printed for races detected in parallel sections of OpenMP programs. An example: - ./vg-in-place --tool=exp-drd exp-drd/tests/omp_prime 4 -t 2 -- Improve the code for suppressing races reported on glibc FILE objects, e.g. by intercepting - all operations on FILE objects and by associating mutex semantics with FILE objects. Verify - that races on unsynchronized *_unlocked() operations are reported. Remove FILE-I/O suppression - patterns from glibc-2.X-drd.supp. See also http://www.unix.org/whitepapers/reentrant.html. + ./vg-in-place --tool=drd drd/tests/omp_prime 4 -t 2 +- Improve the code for suppressing races reported on glibc FILE objects, e.g. by + intercepting all operations on FILE objects and by associating mutex semantics + with FILE objects. Verify that races on unsynchronized *_unlocked() operations + are reported. Remove FILE-I/O suppression patterns from glibc-2.X-drd.supp. + See also http://www.unix.org/whitepapers/reentrant.html. +- Find out why DRD reports an error on the POSIX implementation of libgomp.so. Testing ~~~~~~~ -- Measure the performance and the memory overhead of exp-drd on the PARSEC +- Measure the performance and the memory overhead of drd on the PARSEC benchmark (http://parsec.cs.princeton.edu/license.htm). - Test with Synfig Studio (see also http://bugs.kde.org/show_bug.cgi?id=158555) - Test with a multithreaded Python application. @@ -31,8 +36,9 @@ Documentation ~~~~~~~~~~~~~ +- Document the features added after the 3.4.0 release. +- Document the algorithms used in drd. - Add comment on double checked locking. -- Add comment on circular buffers. +- Add comment on lockless algorithms in general and circular buffers in + particular. - Explain how to handle transactions (with regard to locking order). -- Continue the discussion on the Valgrind mailing list about docbook and - 'make dist'. See also http://bugs.kde.org/show_bug.cgi?id=162121. Modified: trunk/drd/Testing.txt =================================================================== --- trunk/drd/Testing.txt 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/Testing.txt 2009-05-31 18:53:54 UTC (rev 10186) @@ -2,34 +2,60 @@ ~~~~~~~~~~~~~~~ 1. Start with compiling DRD. + 2. Check as follows that all global symbols in DRD have been wrapped by the DRD_() macro (output must be empty): - nm -A drd*.o|grep ' T '|grep -v ' T vgDrd_' + ( cd drd && nm -A drd*.o|grep ' T '|grep -v ' T vgDrd_' ) + 3. Check as follows that all global symbols in the preloaded shared library - are redirected functions (output must be empty): - nm -A vgpreload*.o|grep ' T '|grep -v ' T _vg' -4. Run the regression tests as follows: + are redirected functions (output must contain one symbol that starts with + a double underscore, something like __i686.get_pc_thunk.bx): + ( cd drd && nm -A vgpreload*.o|grep ' T '|grep -v ' T _vg' ) + +4. Verify that all files needed for the regression tests are included in + drd/tests/Makefile.am: + ( + cd drd/tests; + for f in *.vgtest *.exp*; do grep -q "$f" Makefile.am || echo $f; done + ) + +5. Verify that all files referenced in EXTRA_DIST in drd/tests/Makefile.am + exist: + ( + cd drd/tests; + for e in $(awk '/\\$/{n=$0; sub("\\\\$", "", n); if (line != "") { line = line " " n } else { line=n }} /[^\\]$/{if (line != ""){print line;line=""};print}' < Makefile.am | sed -n 's/^EXTRA_DIST *=//p' | sed 's/..noinst_SCRIPTS.//') + do + [ -e "$e" ] || echo "$e" + done + ) + +6. Run the regression tests as follows: perl tests/vg_regtest drd -5. Run Konstantin's regression tests: + +7. Run Konstantin's regression tests: mkdir -p drt/unittest svn checkout http://data-race-test.googlecode.com/svn/trunk/unittest drt/unittest make -C drt/unittest -s all ./vg-in-place --tool=drd --check-stack-var=yes drt/unittest/racecheck_unittest 2>&1|less -6. Test the slowdown for matinv for various matrix sizes via the script + +8. Test the slowdown for matinv for various matrix sizes via the script drd/scripts/run-matinv (must be about 24 for i == 1 and about 31 for i == 10 with n == 200). -7. Test whether DRD works with standard KDE applications and whether it does + +9. Test whether DRD works with standard KDE applications and whether it does not print any false positives. Test this both with KDE3 and KDE4. ./vg-in-place --tool=drd --var-info=yes kate ./vg-in-place --tool=drd --var-info=yes --check-stack-var=yes kate ./vg-in-place --tool=drd --var-info=yes --trace-children=yes knode ./vg-in-place --tool=drd --var-info=yes --check-stack-var=yes --trace-children=yes knode ./vg-in-place --tool=drd --var-info=yes --check-stack-var=yes /usr/bin/designer -8. Test whether DRD works with standard GNOME applications. Expect + +10. Test whether DRD works with standard GNOME applications. Expect race reports triggered by ORBit_RootObject_duplicate() and after having closed the GNOME terminal window: ./vg-in-place --tool=drd --var-info=yes --trace-children=yes gnome-terminal -9. Test DRD with Firefox. First of all, make sure that Valgrind is patched + +11. Test DRD with Firefox. First of all, make sure that Valgrind is patched such that it supports libjemalloc.so: drd/scripts/add-libjemalloc-support Next, build and install Firefox 3: Modified: trunk/drd/drd.h =================================================================== --- trunk/drd/drd.h 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd.h 2009-05-31 18:53:54 UTC (rev 10186) @@ -11,7 +11,7 @@ ---------------------------------------------------------------- - This file is part of drd, a Valgrind tool for verification of + This file is part of DRD, a Valgrind tool for verification of multithreaded programs. Copyright (C) 2006-2009 Bart Van Assche <bar...@gm...>. @@ -65,55 +65,232 @@ #include "valgrind.h" +/** Prefix for the (inline) functions defined in this header file. */ +#define DRDCL_(str) vgDrdCl_##str + + +/** Obtain the thread ID assigned by Valgrind's core. */ +#define DRD_GET_VALGRIND_THREADID (DRDCL_(get_valgrind_threadid)()) + +/** Obtain the thread ID assigned by DRD. */ +#define DRD_GET_DRD_THREADID (DRDCL_(get_drd_threadid)()) + +/** Tell DRD not to complain about data races for the specified variable. */ +#define DRD_IGNORE_VAR(x) DRDCL_(ignore_range)(&(x), sizeof(x)) + +/** + * Tell DRD to trace all memory accesses on the specified variable. + * until the memory that was allocated for the variable is freed. + */ +#define DRD_TRACE_VAR(x) DRDCL_(trace_range)(&(x), sizeof(x)) + +/** + * Tell DRD to insert a mark. addr is either the address of a pthread condition + * variable or the address of an object that is not a pthread synchronization + * object. Inserting two 'happens before' annotations while + * no thread has passed by a 'happens after' annotation is an error. + */ +#define ANNOTATE_HAPPENS_BEFORE(addr) DRDCL_(annotate_happens_before)(addr) + +/** + * Tell DRD that the memory accesses executed after this annotation will happen + * after the memory accesses performed before the most recent + * ANNOTATE_HAPPENS_BEFORE(addr). addr is either the address of a pthread + * condition variable or the address of an object that is not a pthread + * synchronization object. Inserting a 'happens after' annotation before any + * other thread has passed by a 'happens before' annotation for the same + * address or inserting two 'happens after' annotations while no thread has + * passed by a 'happens before' annotation is an error. + */ +#define ANNOTATE_HAPPENS_AFTER(addr) DRDCL_(annotate_happens_after)(addr) + +/** + * Tell DRD that no more ANNOTATE_HAPPENS_AFTER(addr) annotations + * will be inserted before the next ANNOTATE_HAPPENS_BEFORE(addr). + */ +#define ANNOTATE_HAPPENS_AFTER_DONE(addr) \ + DRDCL_(annotate_happens_after_done)(addr) + +/** + * Tell DRD that waiting on the condition variable at address cv has succeeded + * and a lock on the mutex at address mtx is now held. Since DRD always inserts + * a happens before relation between the pthread_cond_signal() or + * pthread_cond_broadcast() call that wakes up a pthread_cond_wait() or + * pthread_cond_timedwait() call and the woken up thread, this macro has been + * left empty. + */ +#define ANNOTATE_CONDVAR_LOCK_WAIT(cv, mtx) + +/** + * Tell DRD that the condition variable at address cv is about to be signaled. + * cv is either the address of a condition variable or the address of an object + * that is not a POSIX synchronization object. + */ +#define ANNOTATE_CONDVAR_SIGNAL(cv) ANNOTATE_HAPPENS_BEFORE(cv) + +/** + * Tell DRD that waiting on condition variable at address cv succeeded. + * cv is either the address of a condition variable or the address of an object + * that is not a POSIX synchronization object. + */ +#define ANNOTATE_CONDVAR_WAIT(cv) ANNOTATE_HAPPENS_AFTER(cv) + +/** + * Tell DRD to consider the memory operations that happened before a mutex + * unlock event and after the subsequent mutex lock event on the same mutex as + * ordered. This is how DRD always behaves, so this macro has been left empty. + */ +#define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mtx) + +/** Tell DRD that a reader-writer lock object has been initialized. */ +#define ANNOTATE_RWLOCK_CREATE(rwlock) \ + DRDCL_(annotate_rwlock)(rwlock, 0, 0) + +/** Tell DRD that a reader-writer lock object has been destroyed. */ +#define ANNOTATE_RWLOCK_DESTROY(rwlock) \ + DRDCL_(annotate_rwlock)(rwlock, 1, 0) + +/** + * Tell DRD that a reader-writer lock has been acquired. is_w == 1 means that + * a write lock has been obtained, is_w == 0 means that a read lock has been + * obtained. + */ +#define ANNOTATE_RWLOCK_ACQUIRED(rwlock, is_w) \ + DRDCL_(annotate_rwlock)(rwlock, 2, is_w) + +/** + * Tell DRD that a reader-writer lock is about to be released. is_w == 1 means + * that a write lock is about to be released, is_w == 0 means that a read lock + * is about to be released. + */ +#define ANNOTATE_RWLOCK_RELEASED(rwlock, is_w) \ + DRDCL_(annotate_rwlock)(rwlock, 3, is_w) + +/** + * Tell DRD that data races in the specified address range are expected and + * must not be reported. + */ +#define ANNOTATE_BENIGN_RACE(addr, descr) DRDCL_(ignore_range)(addr, 4) + +/** Tell DRD to ignore all reads performed by the current thread. */ +#define ANNOTATE_IGNORE_READS_BEGIN() DRDCL_(set_record_loads)(0) + +/** Tell DRD to no longer ignore the reads performed by the current thread. */ +#define ANNOTATE_IGNORE_READS_END() DRDCL_(set_record_loads)(1) + +/** Tell DRD to ignore all writes performed by the current thread. */ +#define ANNOTATE_IGNORE_WRITES_BEGIN() DRDCL_(set_record_stores)(0) + +/** Tell DRD to no longer ignore the writes performed by the current thread. */ +#define ANNOTATE_IGNORE_WRITES_END() DRDCL_(set_record_stores)(1) + +/** Tell DRD to ignore all memory accesses performed by the current thread. */ +#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \ + do { DRDCL_(set_record_loads)(0); DRD_(set_record_stores)(0); } while(0) + +/** + * Tell DRD to no longer ignore the memory accesses performed by the current + * thread. + */ +#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \ + do { DRDCL_(set_record_loads)(1); DRD_(set_record_stores)(1); } while(0) + +/** + * Tell DRD that size bytes starting at addr has been allocated by a custom + * memory allocator. + */ +#define ANNOTATE_NEW_MEMORY(addr, size) DRDCL_(clean_memory)(addr, size) + +/** Ask DRD to report every access to the specified address range. */ +#define ANNOTATE_TRACE_MEMORY(addr) DRDCL_(trace_range)(addr, 1) + +/** + * Tell DRD to assign the specified name to the current thread. This name will + * be used in error messages printed by DRD. + */ +#define ANNOTATE_THREAD_NAME(name) DRDCL_(set_thread_name)(name) + + /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! This enum comprises an ABI exported by Valgrind to programs which use client requests. DO NOT CHANGE THE ORDER OF THESE ENTRIES, NOR DELETE ANY -- add new ones at the end. */ -enum - { - /* Ask the core the thread ID assigned by Valgrind. */ - VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE('D','R'), - /* args: none. */ - /* Ask the core the thread ID assigned by DRD. */ - VG_USERREQ__DRD_GET_DRD_THREAD_ID, - /* args: none. */ +enum { + /* Ask the DRD tool to discard all information about memory accesses */ + /* and client objects for the specified range. This client request is */ + /* binary compatible with the similarly named Helgrind client request. */ + VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'), + /* args: Addr, SizeT. */ - /* To tell the drd tool to suppress data race detection on the */ - /* specified address range. */ - VG_USERREQ__DRD_START_SUPPRESSION, - /* args: start address, size in bytes */ - /* To tell the drd tool no longer to suppress data race detection on */ - /* the specified address range. */ - VG_USERREQ__DRD_FINISH_SUPPRESSION, - /* args: start address, size in bytes */ + /* Ask the DRD tool the thread ID assigned by Valgrind. */ + VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID = VG_USERREQ_TOOL_BASE('D','R'), + /* args: none. */ + /* Ask the DRD tool the thread ID assigned by DRD. */ + VG_USERREQ__DRD_GET_DRD_THREAD_ID, + /* args: none. */ - /* To ask the drd tool to trace all accesses to the specified range. */ - VG_USERREQ__DRD_START_TRACE_ADDR, - /* args: Addr, SizeT. */ - /* To ask the drd tool to stop tracing accesses to the specified range. */ - VG_USERREQ__DRD_STOP_TRACE_ADDR, - /* args: Addr, SizeT. */ + /* To tell the DRD tool to suppress data race detection on the */ + /* specified address range. */ + VG_USERREQ__DRD_START_SUPPRESSION, + /* args: start address, size in bytes */ + /* To tell the DRD tool no longer to suppress data race detection on */ + /* the specified address range. */ + VG_USERREQ__DRD_FINISH_SUPPRESSION, + /* args: start address, size in bytes */ - /* To ask the drd tool to discard all information about memory accesses */ - /* and client objects for the specified range. This client request is */ - /* binary compatible with the similarly named Helgrind client request. */ - VG_USERREQ__DRD_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'), - /* args: Addr, SizeT. */ - }; + /* To ask the DRD tool to trace all accesses to the specified range. */ + VG_USERREQ__DRD_START_TRACE_ADDR, + /* args: Addr, SizeT. */ + /* To ask the DRD tool to stop tracing accesses to the specified range. */ + VG_USERREQ__DRD_STOP_TRACE_ADDR, + /* args: Addr, SizeT. */ + /* Tell DRD whether or not to record memory loads in the calling thread. */ + VG_USERREQ__DRD_RECORD_LOADS, + /* args: Bool. */ + /* Tell DRD whether or not to record memory stores in the calling thread. */ + VG_USERREQ__DRD_RECORD_STORES, + /* args: Bool. */ -/** Tell DRD to suppress data race detection on the specified variable. */ -#define DRD_IGNORE_VAR(x) vg_drd_ignore_range(&(x), sizeof(x)) + /* Set the name of the thread that performs this client request. */ + VG_USERREQ__DRD_SET_THREAD_NAME, + /* args: null-terminated character string. */ -/** Tell DRD to trace all memory accesses on the specified variable. - * until the memory that was allocated for the variable is freed. + /* Tell DRD to insert a happens before annotation. */ + VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE, + /* args: Addr. */ + /* Tell DRD to insert a happens after annotation. */ + VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER, + /* args: Addr. */ + /* Tell DRD that no more happens after annotations will follow until the + * next happens before annotation. */ + VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER_DONE, + /* args: Addr. */ + + /* Tell DRD about an operation performed on a user-defined reader-writer + * synchronization object. */ + VG_USERREQ__DRD_ANNOTATE_RWLOCK, + /* args: Addr, Int operation_type, Int is_rw. */ +}; + + +/* + * Do not call the inline functions below directly but use the macro's defined + * above. The names of these inline functions may change from one release to + * another. */ -#define DRD_TRACE_VAR(x) vg_drd_trace_range(&(x), sizeof(x)) +static __inline__ +void DRDCL_(clean_memory)(const void* const addr, const int size) +{ + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_CLEAN_MEMORY, + addr, size, 0, 0, 0); +} static __inline__ -int vg_get_valgrind_threadid(void) +int DRDCL_(get_valgrind_threadid)(void) { int res; VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID, @@ -122,7 +299,7 @@ } static __inline__ -int vg_get_drd_threadid(void) +int DRDCL_(get_drd_threadid)(void) { int res; VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_GET_DRD_THREAD_ID, @@ -131,20 +308,78 @@ } static __inline__ -void vg_drd_ignore_range(const void* const p, const int size) +void DRDCL_(ignore_range)(const void* const addr, const int size) { int res; VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_SUPPRESSION, - p, size, 0, 0, 0); + addr, size, 0, 0, 0); } static __inline__ -void vg_drd_trace_range(const void* const p, const int size) +void DRDCL_(trace_range)(const void* const addr, const int size) { int res; VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_TRACE_ADDR, - p, size, 0, 0, 0); + addr, size, 0, 0, 0); } +static __inline__ +void DRDCL_(set_record_loads)(const int enabled) +{ + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_RECORD_LOADS, + enabled, 0, 0, 0, 0); +} +static __inline__ +void DRDCL_(set_record_stores)(const int enabled) +{ + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_RECORD_STORES, + enabled, 0, 0, 0, 0); +} + +static __inline__ +void DRDCL_(set_thread_name)(const char* const name) +{ + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SET_THREAD_NAME, + name, 0, 0, 0, 0); +} + +static __inline__ +void DRDCL_(annotate_happens_before)(const void* const addr) +{ + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE, + addr, 0, 0, 0, 0); +} + +static __inline__ +void DRDCL_(annotate_happens_after)(const void* const addr) +{ + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER, + addr, 0, 0, 0, 0); +} + +static __inline__ +void DRDCL_(annotate_happens_after_done)(const void* const addr) +{ + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, + VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER_DONE, + addr, 0, 0, 0, 0); +} + +static __inline__ +void DRDCL_(annotate_rwlock)(const void* const rwlock, const int op, + const int is_w) +{ + int res; + VALGRIND_DO_CLIENT_REQUEST(res, 0, + VG_USERREQ__DRD_ANNOTATE_RWLOCK, + rwlock, op, is_w, 0, 0); +} + #endif /* __VALGRIND_DRD_H */ Modified: trunk/drd/drd_barrier.c =================================================================== --- trunk/drd/drd_barrier.c 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_barrier.c 2009-05-31 18:53:54 UTC (rev 10186) @@ -152,7 +152,7 @@ if (p->pre_waiters_left != p->count) { - BarrierErrInfo bei = { p->a1, 0, 0 }; + BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; VG_(maybe_record_error)(VG_(get_running_tid)(), BarrierErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -229,7 +229,7 @@ if (count == 0) { - BarrierErrInfo bei = { barrier, 0, 0 }; + BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 }; VG_(maybe_record_error)(VG_(get_running_tid)(), BarrierErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -242,7 +242,7 @@ p = DRD_(barrier_get)(barrier); if (p) { - BarrierErrInfo bei = { barrier, 0, 0 }; + BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), barrier, 0, 0 }; VG_(maybe_record_error)(VG_(get_running_tid)(), BarrierErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -280,7 +280,7 @@ { if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) { - BarrierErrInfo bei = { p->a1, 0, 0 }; + BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; VG_(maybe_record_error)(VG_(get_running_tid)(), BarrierErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -311,7 +311,7 @@ if (p == 0) { - GenericErrInfo GEI; + GenericErrInfo GEI = { DRD_(thread_get_running_tid)() }; VG_(maybe_record_error)(VG_(get_running_tid)(), GenericErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -322,7 +322,7 @@ if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) { - BarrierErrInfo bei = { p->a1, 0, 0 }; + BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; VG_(maybe_record_error)(VG_(get_running_tid)(), BarrierErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -441,7 +441,7 @@ q = VG_(OSetGen_Lookup)(p->oset, &word_tid); if (q == 0) { - BarrierErrInfo bei = { p->a1, 0, 0 }; + BarrierErrInfo bei = { DRD_(thread_get_running_tid)(), p->a1, 0, 0 }; VG_(maybe_record_error)(VG_(get_running_tid)(), BarrierErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -524,7 +524,7 @@ { BarrierErrInfo bei - = { p->a1, q->tid, q->wait_call_ctxt }; + = { DRD_(thread_get_running_tid)(), p->a1, q->tid, q->wait_call_ctxt }; VG_(maybe_record_error)(VG_(get_running_tid)(), BarrierErr, VG_(get_IP)(VG_(get_running_tid)()), Modified: trunk/drd/drd_clientreq.c =================================================================== --- trunk/drd/drd_clientreq.c 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_clientreq.c 2009-05-31 18:53:54 UTC (rev 10186) @@ -83,11 +83,12 @@ case VG_USERREQ__FREELIKE_BLOCK: if (arg[1] && ! DRD_(freelike_block)(vg_tid, arg[1]/*addr*/)) { + GenericErrInfo GEI = { DRD_(thread_get_running_tid)() }; VG_(maybe_record_error)(vg_tid, GenericErr, VG_(get_IP)(vg_tid), "Invalid VG_USERREQ__FREELIKE_BLOCK request", - NULL); + &GEI); } break; @@ -99,6 +100,10 @@ result = drd_tid; break; + case VG_USERREQ__DRD_SET_THREAD_NAME: + DRD_(thread_set_name)(drd_tid, (const char*)arg[1]); + break; + case VG_USERREQ__DRD_START_SUPPRESSION: DRD_(start_suppression)(arg[1], arg[1] + arg[2], "client"); break; @@ -107,6 +112,75 @@ DRD_(finish_suppression)(arg[1], arg[1] + arg[2]); break; + case VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE: + { + struct cond_info* const cond_p = DRD_(cond_get)(arg[1]); + if (! cond_p) + { + DRD_(mutex_init)(arg[1], mutex_type_order_annotation); + DRD_(mutex_pre_lock)(arg[1], mutex_type_order_annotation, False); + DRD_(mutex_post_lock)(arg[1], mutex_type_order_annotation, False); + DRD_(mutex_unlock)(arg[1], mutex_type_order_annotation); + } + } + break; + + case VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER: + { + struct cond_info* const cond_p = DRD_(cond_get)(arg[1]); + if (! cond_p) + { + DRD_(mutex_pre_lock)(arg[1], mutex_type_order_annotation, False); + DRD_(mutex_post_lock)(arg[1], mutex_type_order_annotation, False); + DRD_(mutex_unlock)(arg[1], mutex_type_order_annotation); + } + } + break; + + case VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER_DONE: + { + struct cond_info* const cond_p = DRD_(cond_get)(arg[1]); + if (! cond_p) + DRD_(mutex_post_destroy)(arg[1]); + } + break; + + case VG_USERREQ__DRD_ANNOTATE_RWLOCK: + { + struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]); + if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock) + break; + } + switch (arg[2]) + { + case 0: + DRD_(rwlock_pre_init)(arg[1], user_rwlock); + break; + case 1: + DRD_(rwlock_post_destroy)(arg[1], user_rwlock); + break; + case 2: + tl_assert(arg[3] == !! arg[3]); + if (arg[3]) + { + DRD_(rwlock_pre_wrlock)(arg[1], user_rwlock); + DRD_(rwlock_post_wrlock)(arg[1], user_rwlock, True); + } + else + { + DRD_(rwlock_pre_rdlock)(arg[1], user_rwlock); + DRD_(rwlock_post_rdlock)(arg[1], user_rwlock, True); + } + break; + case 3: + tl_assert(arg[3] == !! arg[3]); + DRD_(rwlock_pre_unlock)(arg[1], user_rwlock); + break; + default: + tl_assert(False); + } + break; + case VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK: { const Addr topmost_sp = highest_used_stack_address(vg_tid); @@ -145,12 +219,12 @@ DRD_(stop_tracing_address_range)(arg[1], arg[1] + arg[2]); break; - case VG_USERREQ__DRD_STOP_RECORDING: - DRD_(thread_stop_recording)(drd_tid); + case VG_USERREQ__DRD_RECORD_LOADS: + DRD_(thread_set_record_loads)(drd_tid, arg[1]); break; - case VG_USERREQ__DRD_START_RECORDING: - DRD_(thread_start_recording)(drd_tid); + case VG_USERREQ__DRD_RECORD_STORES: + DRD_(thread_set_record_stores)(drd_tid, arg[1]); break; case VG_USERREQ__SET_PTHREADID: @@ -349,36 +423,36 @@ break; case VG_USERREQ__PRE_RWLOCK_INIT: - DRD_(rwlock_pre_init)(arg[1]); + DRD_(rwlock_pre_init)(arg[1], pthread_rwlock); break; case VG_USERREQ__POST_RWLOCK_DESTROY: - DRD_(rwlock_post_destroy)(arg[1]); + DRD_(rwlock_post_destroy)(arg[1], pthread_rwlock); break; case VG_USERREQ__PRE_RWLOCK_RDLOCK: if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(rwlock_pre_rdlock)(arg[1]); + DRD_(rwlock_pre_rdlock)(arg[1], pthread_rwlock); break; case VG_USERREQ__POST_RWLOCK_RDLOCK: if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(rwlock_post_rdlock)(arg[1], arg[2]); + DRD_(rwlock_post_rdlock)(arg[1], pthread_rwlock, arg[2]); break; case VG_USERREQ__PRE_RWLOCK_WRLOCK: if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(rwlock_pre_wrlock)(arg[1]); + DRD_(rwlock_pre_wrlock)(arg[1], pthread_rwlock); break; case VG_USERREQ__POST_RWLOCK_WRLOCK: if (DRD_(thread_leave_synchr)(drd_tid) == 0) - DRD_(rwlock_post_wrlock)(arg[1], arg[2]); + DRD_(rwlock_post_wrlock)(arg[1], pthread_rwlock, arg[2]); break; case VG_USERREQ__PRE_RWLOCK_UNLOCK: if (DRD_(thread_enter_synchr)(drd_tid) == 0) - DRD_(rwlock_pre_unlock)(arg[1]); + DRD_(rwlock_pre_unlock)(arg[1], pthread_rwlock); break; case VG_USERREQ__POST_RWLOCK_UNLOCK: @@ -408,7 +482,7 @@ * of the highest stack frame. It is assumed that there are no more than * ten stack frames above the current frame. This should be no problem * since this function is either called indirectly from the _init() function - * in vgpreload_exp-drd-*.so or from the thread wrapper for a newly created + * in vgpreload_drd-*.so or from the thread wrapper for a newly created * thread. See also drd_pthread_intercepts.c. */ static Addr highest_used_stack_address(const ThreadId vg_tid) Modified: trunk/drd/drd_clientreq.h =================================================================== --- trunk/drd/drd_clientreq.h 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_clientreq.h 2009-05-31 18:53:54 UTC (rev 10186) @@ -52,12 +52,6 @@ /* To ask the drd tool to start a new segment in the specified thread. */ VG_USERREQ__DRD_START_NEW_SEGMENT, /* args: POSIX thread ID. */ - /* Let the drd tool stop recording memory accesses in the calling thread. */ - VG_USERREQ__DRD_STOP_RECORDING, - /* args: none. */ - /* Let the drd tool start recording memory accesses in the calling thread. */ - VG_USERREQ__DRD_START_RECORDING, - /* args: none. */ /* Tell drd the pthread_t of the running thread. */ VG_USERREQ__SET_PTHREADID, @@ -183,56 +177,65 @@ /* To notify the drd tool of a pthread_rwlock_init call. */ VG_USERREQ__PRE_RWLOCK_INIT, - /* args: Addr rwlock */ + /* args: Addr rwlock, RwLockT */ /* To notify the drd tool of a pthread_rwlock_destroy call. */ VG_USERREQ__POST_RWLOCK_DESTROY, - /* args: Addr rwlock */ + /* args: Addr rwlock, RwLockT */ /* To notify the drd tool of a pthread_rwlock_rdlock call. */ VG_USERREQ__PRE_RWLOCK_RDLOCK, - /* args: Addr rwlock */ + /* args: Addr rwlock, RwLockT */ /* To notify the drd tool of a pthread_rwlock_rdlock call. */ VG_USERREQ__POST_RWLOCK_RDLOCK, - /* args: Addr rwlock, Bool took_lock */ + /* args: Addr rwlock, RwLockT, Bool took_lock */ /* To notify the drd tool of a pthread_rwlock_wrlock call. */ VG_USERREQ__PRE_RWLOCK_WRLOCK, - /* args: Addr rwlock */ + /* args: Addr rwlock, RwLockT */ /* To notify the drd tool of a pthread_rwlock_wrlock call. */ VG_USERREQ__POST_RWLOCK_WRLOCK, - /* args: Addr rwlock, Bool took_lock */ + /* args: Addr rwlock, RwLockT, Bool took_lock */ /* To notify the drd tool of a pthread_rwlock_unlock call. */ VG_USERREQ__PRE_RWLOCK_UNLOCK, - /* args: Addr rwlock */ + /* args: Addr rwlock, RwLockT */ /* To notify the drd tool of a pthread_rwlock_unlock call. */ VG_USERREQ__POST_RWLOCK_UNLOCK - /* args: Addr rwlock, Bool unlocked */ + /* args: Addr rwlock, RwLockT, Bool unlocked */ }; -/* +/** * Error checking on POSIX recursive mutexes, POSIX error checking mutexes, - * POSIX default mutexes and POSIX spinlocks happens by the same code. The - * values defined below specify which of these types a mutex really is. + * POSIX default mutexes and POSIX spinlocks happens the code in drd_mutex.c. + * The values defined below specify the mutex type. */ -typedef enum - { - mutex_type_unknown = -1, - mutex_type_invalid_mutex = 0, - mutex_type_recursive_mutex = 1, - mutex_type_errorcheck_mutex = 2, - mutex_type_default_mutex = 3, - mutex_type_spinlock = 4 - } MutexT; +typedef enum { + mutex_type_unknown = -1, + mutex_type_invalid_mutex = 0, + mutex_type_recursive_mutex = 1, + mutex_type_errorcheck_mutex = 2, + mutex_type_default_mutex = 3, + mutex_type_spinlock = 4, + mutex_type_order_annotation = 5, +} MutexT; +/** + * Error checking on POSIX reader/writer locks and user-defined reader/writer + * locks happens by the code in drd_rwlock.c. The values defined below specify + * the rwlock type. + */ +typedef enum { + pthread_rwlock = 1, + user_rwlock = 2, +} RwLockT; + /* * Error checking on POSIX barriers and GOMP barriers happens by the same * code. The integer values defined below specify the type of a barrier with * a given client address. */ -typedef enum - { - pthread_barrier = 1, - gomp_barrier = 2 - } BarrierT; +typedef enum { + pthread_barrier = 1, + gomp_barrier = 2, +} BarrierT; void DRD_(clientreq_init)(void); Modified: trunk/drd/drd_cond.c =================================================================== --- trunk/drd/drd_cond.c 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_cond.c 2009-05-31 18:53:54 UTC (rev 10186) @@ -85,7 +85,8 @@ q = &(DRD_(clientobj_get)(p->mutex, ClientMutex)->mutex); tl_assert(q); { - CondDestrErrInfo cde = { p->a1, q->a1, q->owner }; + CondDestrErrInfo cde = { DRD_(thread_get_running_tid)(), + p->a1, q->a1, q->owner }; VG_(maybe_record_error)(VG_(get_running_tid)(), CondDestrErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -96,7 +97,7 @@ } } -static struct cond_info* DRD_(cond_get_or_allocate)(const Addr cond) +static struct cond_info* cond_get_or_allocate(const Addr cond) { struct cond_info *p; @@ -110,7 +111,7 @@ return p; } -static struct cond_info* DRD_(cond_get)(const Addr cond) +struct cond_info* DRD_(cond_get)(const Addr cond) { tl_assert(offsetof(DrdClientobj, cond) == 0); return &(DRD_(clientobj_get)(cond, ClientCondvar)->cond); @@ -134,7 +135,7 @@ if (p) { - CondErrInfo cei = { .cond = cond }; + CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; VG_(maybe_record_error)(VG_(get_running_tid)(), CondErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -142,7 +143,7 @@ &cei); } - p = DRD_(cond_get_or_allocate)(cond); + p = cond_get_or_allocate(cond); } /** Called after pthread_cond_destroy(). */ @@ -162,7 +163,7 @@ p = DRD_(cond_get)(cond); if (p == 0) { - CondErrInfo cei = { .cond = cond }; + CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; VG_(maybe_record_error)(VG_(get_running_tid)(), CondErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -173,7 +174,7 @@ if (p->waiter_count != 0) { - CondErrInfo cei = { .cond = cond }; + CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; VG_(maybe_record_error)(VG_(get_running_tid)(), CondErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -202,7 +203,7 @@ cond); } - p = DRD_(cond_get_or_allocate)(cond); + p = cond_get_or_allocate(cond); tl_assert(p); if (p->waiter_count == 0) @@ -212,7 +213,8 @@ else if (p->mutex != mutex) { CondWaitErrInfo cwei - = { .cond = cond, .mutex1 = p->mutex, .mutex2 = mutex }; + = { .tid = DRD_(thread_get_running_tid)(), + .cond = cond, .mutex1 = p->mutex, .mutex2 = mutex }; VG_(maybe_record_error)(VG_(get_running_tid)(), CondWaitErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -226,7 +228,8 @@ && q->owner == DRD_(thread_get_running_tid)() && q->recursion_count > 0) { const ThreadId vg_tid = VG_(get_running_tid)(); - MutexErrInfo MEI = { q->a1, q->recursion_count, q->owner }; + MutexErrInfo MEI = { DRD_(thread_get_running_tid)(), + q->a1, q->recursion_count, q->owner }; VG_(maybe_record_error)(vg_tid, MutexErr, VG_(get_IP)(vg_tid), @@ -284,9 +287,10 @@ { /* A signal is sent while the associated mutex has not been locked. */ /* This can indicate but is not necessarily a race condition. */ - CondRaceErrInfo cei; - cei.cond = cond; - cei.mutex = cond_p->mutex; + CondRaceErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), + .cond = cond, + .mutex = cond_p->mutex, + }; VG_(maybe_record_error)(vg_tid, CondRaceErr, VG_(get_IP)(vg_tid), Modified: trunk/drd/drd_cond.h =================================================================== --- trunk/drd/drd_cond.h 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_cond.h 2009-05-31 18:53:54 UTC (rev 10186) @@ -40,6 +40,7 @@ void DRD_(cond_set_report_signal_unlocked)(const Bool r); void DRD_(cond_set_trace)(const Bool trace_cond); +struct cond_info* DRD_(cond_get)(const Addr cond); void DRD_(cond_pre_init)(const Addr cond); void DRD_(cond_post_destroy)(const Addr cond); int DRD_(cond_pre_wait)(const Addr cond, const Addr mutex); Modified: trunk/drd/drd_error.c =================================================================== --- trunk/drd/drd_error.c 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_error.c 2009-05-31 18:53:54 UTC (rev 10186) @@ -171,6 +171,17 @@ static void drd_tool_error_pp(Error* const e) { + static DrdThreadId s_last_tid_printed = 1; + DrdThreadId* err_extra; + + err_extra = VG_(get_error_extra)(e); + + if (err_extra && *err_extra != s_last_tid_printed) + { + VG_UMSG("%s:", DRD_(thread_get_name)(*err_extra)); + s_last_tid_printed = *err_extra; + } + switch (VG_(get_error_kind)(e)) { case DataRaceErr: { @@ -215,7 +226,7 @@ "%s: cond 0x%lx, mutex 0x%lx locked by thread %d/%d", VG_(get_error_string)(e), cdi->cond, cdi->mutex, - DRD_(DrdThreadIdToVgThreadId)(cdi->tid), cdi->tid); + DRD_(DrdThreadIdToVgThreadId)(cdi->owner), cdi->owner); VG_(pp_ExeContext)(VG_(get_error_where)(e)); first_observed(cdi->mutex); break; @@ -426,7 +437,7 @@ // Tool error reporting. VG_(needs_tool_errors)(drd_tool_error_eq, drd_tool_error_pp, - True, + False, drd_tool_error_update_extra, drd_tool_error_recog, drd_tool_error_read_extra, Modified: trunk/drd/drd_error.h =================================================================== --- trunk/drd/drd_error.h 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_error.h 2009-05-31 18:53:54 UTC (rev 10186) @@ -87,9 +87,12 @@ DebugInfo* debuginfo; // Segment Char name[256]; // Segment Char descr[256]; // Segment -} - AddrInfo; +} AddrInfo; +/* + * NOTE: the first member of each error info structure MUST be the thread ID + * in which the error has been observed. + */ typedef struct { DrdThreadId tid; // Thread ID of the running thread. Addr addr; // Conflicting address in current thread. @@ -98,47 +101,56 @@ } DataRaceErrInfo; typedef struct { - Addr mutex; - Int recursion_count; + DrdThreadId tid; + Addr mutex; + Int recursion_count; DrdThreadId owner; } MutexErrInfo; typedef struct { - Addr cond; + DrdThreadId tid; + Addr cond; } CondErrInfo; typedef struct { + DrdThreadId tid; Addr cond; Addr mutex; - DrdThreadId tid; + DrdThreadId owner; } CondDestrErrInfo; typedef struct { - Addr cond; - Addr mutex; + DrdThreadId tid; + Addr cond; + Addr mutex; } CondRaceErrInfo; typedef struct { - Addr cond; - Addr mutex1; - Addr mutex2; + DrdThreadId tid; + Addr cond; + Addr mutex1; + Addr mutex2; } CondWaitErrInfo; typedef struct { - Addr semaphore; + DrdThreadId tid; + Addr semaphore; } SemaphoreErrInfo; typedef struct { + DrdThreadId tid; Addr barrier; DrdThreadId other_tid; ExeContext* other_context; } BarrierErrInfo; typedef struct { - Addr rwlock; + DrdThreadId tid; + Addr rwlock; } RwlockErrInfo; typedef struct { + DrdThreadId tid; Addr synchronization_object; ExeContext* acquired_at; UInt hold_time_ms; @@ -146,6 +158,7 @@ } HoldtimeErrInfo; typedef struct { + DrdThreadId tid; } GenericErrInfo; Modified: trunk/drd/drd_load_store.c =================================================================== --- trunk/drd/drd_load_store.c 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_load_store.c 2009-05-31 18:53:54 UTC (rev 10186) @@ -151,7 +151,7 @@ == VgThreadIdToDrdThreadId(VG_(get_running_tid()))); #endif - if (DRD_(running_thread_is_recording)() + if (DRD_(running_thread_is_recording_loads)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_load_triggers_conflict(addr, addr + size) @@ -163,7 +163,7 @@ static VG_REGPARM(1) void drd_trace_load_1(Addr addr) { - if (DRD_(running_thread_is_recording)() + if (DRD_(running_thread_is_recording_loads)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_load_1_triggers_conflict(addr) @@ -175,7 +175,7 @@ static VG_REGPARM(1) void drd_trace_load_2(Addr addr) { - if (DRD_(running_thread_is_recording)() + if (DRD_(running_thread_is_recording_loads)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_load_2_triggers_conflict(addr) @@ -187,7 +187,7 @@ static VG_REGPARM(1) void drd_trace_load_4(Addr addr) { - if (DRD_(running_thread_is_recording)() + if (DRD_(running_thread_is_recording_loads)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_load_4_triggers_conflict(addr) @@ -199,7 +199,7 @@ static VG_REGPARM(1) void drd_trace_load_8(Addr addr) { - if (DRD_(running_thread_is_recording)() + if (DRD_(running_thread_is_recording_loads)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_load_8_triggers_conflict(addr) @@ -217,7 +217,7 @@ == VgThreadIdToDrdThreadId(VG_(get_running_tid()))); #endif - if (DRD_(running_thread_is_recording)() + if (DRD_(running_thread_is_recording_stores)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_store_triggers_conflict(addr, addr + size) @@ -229,7 +229,7 @@ static VG_REGPARM(1) void drd_trace_store_1(Addr addr) { - if (DRD_(running_thread_is_recording)() + if (DRD_(running_thread_is_recording_stores)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_store_1_triggers_conflict(addr) @@ -241,7 +241,7 @@ static VG_REGPARM(1) void drd_trace_store_2(Addr addr) { - if (DRD_(running_thread_is_recording)() + if (DRD_(running_thread_is_recording_stores)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_store_2_triggers_conflict(addr) @@ -253,7 +253,7 @@ static VG_REGPARM(1) void drd_trace_store_4(Addr addr) { - if (DRD_(running_thread_is_recording)() + if (DRD_(running_thread_is_recording_stores)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_store_4_triggers_conflict(addr) @@ -265,7 +265,7 @@ static VG_REGPARM(1) void drd_trace_store_8(Addr addr) { - if (DRD_(running_thread_is_recording)() + if (DRD_(running_thread_is_recording_stores)() && (s_check_stack_accesses || ! DRD_(thread_address_on_stack)(addr)) && bm_access_store_8_triggers_conflict(addr) Modified: trunk/drd/drd_main.c =================================================================== --- trunk/drd/drd_main.c 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_main.c 2009-05-31 18:53:54 UTC (rev 10186) @@ -524,7 +524,8 @@ DRD_(thread_get_stack_max)(drd_tid) - DRD_(thread_get_stack_min)(drd_tid), True); - DRD_(thread_stop_recording)(drd_tid); + DRD_(thread_set_record_loads)(drd_tid, False); + DRD_(thread_set_record_stores)(drd_tid, False); DRD_(thread_finished)(drd_tid); } Modified: trunk/drd/drd_mutex.c =================================================================== --- trunk/drd/drd_mutex.c 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_mutex.c 2009-05-31 18:53:54 UTC (rev 10186) @@ -103,7 +103,8 @@ if (mutex_is_locked(p)) { - MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; + MutexErrInfo MEI = { DRD_(thread_get_running_tid)(), + p->a1, p->recursion_count, p->owner }; VG_(maybe_record_error)(VG_(get_running_tid)(), MutexErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -118,7 +119,8 @@ /** Let Valgrind report that there is no mutex object at address 'mutex'. */ void DRD_(not_a_mutex)(const Addr mutex) { - MutexErrInfo MEI = { mutex, -1, DRD_INVALID_THREADID }; + MutexErrInfo MEI = { DRD_(thread_get_running_tid)(), + mutex, -1, DRD_INVALID_THREADID }; VG_(maybe_record_error)(VG_(get_running_tid)(), MutexErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -186,8 +188,8 @@ if (p) { const ThreadId vg_tid = VG_(get_running_tid)(); - MutexErrInfo MEI - = { p->a1, p->recursion_count, p->owner }; + MutexErrInfo MEI = { DRD_(thread_get_running_tid)(), + p->a1, p->recursion_count, p->owner }; VG_(maybe_record_error)(vg_tid, MutexErr, VG_(get_IP)(vg_tid), @@ -262,7 +264,8 @@ && p->recursion_count >= 1 && mutex_type != mutex_type_recursive_mutex) { - MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; + MutexErrInfo MEI = { DRD_(thread_get_running_tid)(), + p->a1, p->recursion_count, p->owner }; VG_(maybe_record_error)(VG_(get_running_tid)(), MutexErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -370,7 +373,8 @@ if (p->owner == DRD_INVALID_THREADID) { - MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; + MutexErrInfo MEI = { DRD_(thread_get_running_tid)(), + p->a1, p->recursion_count, p->owner }; VG_(maybe_record_error)(vg_tid, MutexErr, VG_(get_IP)(vg_tid), @@ -390,7 +394,8 @@ if (p->owner != drd_tid || p->recursion_count <= 0) { - MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; + MutexErrInfo MEI = { DRD_(thread_get_running_tid)(), + p->a1, p->recursion_count, p->owner }; VG_(maybe_record_error)(vg_tid, MutexErr, VG_(get_IP)(vg_tid), @@ -410,7 +415,8 @@ if (held > s_mutex_lock_threshold_ms) { HoldtimeErrInfo HEI - = { mutex, p->acquired_at, held, s_mutex_lock_threshold_ms }; + = { DRD_(thread_get_running_tid)(), + mutex, p->acquired_at, held, s_mutex_lock_threshold_ms }; VG_(maybe_record_error)(vg_tid, HoldtimeErr, VG_(get_IP)(vg_tid), @@ -504,8 +510,8 @@ if (p->owner == tid && p->recursion_count > 0) { - MutexErrInfo MEI - = { p->a1, p->recursion_count, p->owner }; + MutexErrInfo MEI = { DRD_(thread_get_running_tid)(), + p->a1, p->recursion_count, p->owner }; VG_(maybe_record_error)(VG_(get_running_tid)(), MutexErr, VG_(get_IP)(VG_(get_running_tid)()), Modified: trunk/drd/drd_rwlock.c =================================================================== --- trunk/drd/drd_rwlock.c 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_rwlock.c 2009-05-31 18:53:54 UTC (rev 10186) @@ -214,7 +214,7 @@ if (DRD_(rwlock_is_locked)(p)) { - RwlockErrInfo REI = { p->a1 }; + RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 }; VG_(maybe_record_error)(VG_(get_running_tid)(), RwlockErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -245,7 +245,7 @@ if (DRD_(clientobj_present)(rwlock, rwlock + 1)) { - GenericErrInfo GEI; + GenericErrInfo GEI = { DRD_(thread_get_running_tid)() }; VG_(maybe_record_error)(VG_(get_running_tid)(), GenericErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -266,7 +266,8 @@ } /** Called before pthread_rwlock_init(). */ -struct rwlock_info* DRD_(rwlock_pre_init)(const Addr rwlock) +struct rwlock_info* DRD_(rwlock_pre_init)(const Addr rwlock, + const RwLockT rwlock_type) { struct rwlock_info* p; @@ -284,8 +285,7 @@ if (p) { const ThreadId vg_tid = VG_(get_running_tid)(); - RwlockErrInfo REI - = { p->a1 }; + RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 }; VG_(maybe_record_error)(vg_tid, RwlockErr, VG_(get_IP)(vg_tid), @@ -300,14 +300,14 @@ } /** Called after pthread_rwlock_destroy(). */ -void DRD_(rwlock_post_destroy)(const Addr rwlock) +void DRD_(rwlock_post_destroy)(const Addr rwlock, const RwLockT rwlock_type) { struct rwlock_info* p; p = DRD_(rwlock_get)(rwlock); if (p == 0) { - GenericErrInfo GEI; + GenericErrInfo GEI = { DRD_(thread_get_running_tid)() }; VG_(maybe_record_error)(VG_(get_running_tid)(), GenericErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -325,7 +325,7 @@ * an attempt is made to lock recursively a synchronization object that must * not be locked recursively. */ -void DRD_(rwlock_pre_rdlock)(const Addr rwlock) +void DRD_(rwlock_pre_rdlock)(const Addr rwlock, const RwLockT rwlock_type) { struct rwlock_info* p; @@ -355,7 +355,8 @@ * Note: this function must be called after pthread_rwlock_rdlock() has been * called, or a race condition is triggered ! */ -void DRD_(rwlock_post_rdlock)(const Addr rwlock, const Bool took_lock) +void DRD_(rwlock_post_rdlock)(const Addr rwlock, const RwLockT rwlock_type, + const Bool took_lock) { const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); struct rwlock_info* p; @@ -396,7 +397,7 @@ * an attempt is made to lock recursively a synchronization object that must * not be locked recursively. */ -void DRD_(rwlock_pre_wrlock)(const Addr rwlock) +void DRD_(rwlock_pre_wrlock)(const Addr rwlock, const RwLockT rwlock_type) { struct rwlock_info* p; @@ -420,7 +421,7 @@ if (DRD_(rwlock_is_wrlocked_by)(p, DRD_(thread_get_running_tid)())) { - RwlockErrInfo REI = { p->a1 }; + RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 }; VG_(maybe_record_error)(VG_(get_running_tid)(), RwlockErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -434,7 +435,8 @@ * Note: this function must be called after pthread_rwlock_wrlock() has * finished, or a race condition is triggered ! */ -void DRD_(rwlock_post_wrlock)(const Addr rwlock, const Bool took_lock) +void DRD_(rwlock_post_wrlock)(const Addr rwlock, const RwLockT rwlock_type, + const Bool took_lock) { const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); struct rwlock_info* p; @@ -477,7 +479,7 @@ * @note This function must be called before pthread_rwlock_unlock() is called, * or a race condition is triggered ! */ -void DRD_(rwlock_pre_unlock)(const Addr rwlock) +void DRD_(rwlock_pre_unlock)(const Addr rwlock, const RwLockT rwlock_type) { const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); const ThreadId vg_tid = VG_(get_running_tid)(); @@ -496,7 +498,7 @@ p = DRD_(rwlock_get)(rwlock); if (p == 0) { - GenericErrInfo GEI; + GenericErrInfo GEI = { DRD_(thread_get_running_tid)() }; VG_(maybe_record_error)(VG_(get_running_tid)(), GenericErr, VG_(get_IP)(VG_(get_running_tid)()), @@ -506,7 +508,7 @@ } if (! DRD_(rwlock_is_locked_by)(p, drd_tid)) { - RwlockErrInfo REI = { p->a1 }; + RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 }; VG_(maybe_record_error)(vg_tid, RwlockErr, VG_(get_IP)(vg_tid), @@ -525,7 +527,8 @@ if (held > DRD_(s_shared_threshold_ms)) { HoldtimeErrInfo HEI - = { rwlock, p->acquired_at, held, DRD_(s_shared_threshold_ms) }; + = { DRD_(thread_get_running_tid)(), + rwlock, p->acquired_at, held, DRD_(s_shared_threshold_ms) }; VG_(maybe_record_error)(vg_tid, HoldtimeErr, VG_(get_IP)(vg_tid), @@ -543,7 +546,8 @@ if (held > DRD_(s_exclusive_threshold_ms)) { HoldtimeErrInfo HEI - = { rwlock, p->acquired_at, held, + = { DRD_(thread_get_running_tid)(), + rwlock, p->acquired_at, held, DRD_(s_exclusive_threshold_ms) }; VG_(maybe_record_error)(vg_tid, HoldtimeErr, @@ -580,7 +584,7 @@ struct rwlock_thread_info* q; if (DRD_(rwlock_is_locked_by)(p, tid)) { - RwlockErrInfo REI = { p->a1 }; + RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 }; VG_(maybe_record_error)(VG_(get_running_tid)(), RwlockErr, VG_(get_IP)(VG_(get_running_tid)()), Modified: trunk/drd/drd_rwlock.h =================================================================== --- trunk/drd/drd_rwlock.h 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_rwlock.h 2009-05-31 18:53:54 UTC (rev 10186) @@ -41,13 +41,16 @@ void DRD_(rwlock_set_trace)(const Bool trace_rwlock); void DRD_(rwlock_set_exclusive_threshold)(const UInt exclusive_threshold_ms); void DRD_(rwlock_set_shared_threshold)(const UInt shared_threshold_ms); -struct rwlock_info* DRD_(rwlock_pre_init)(const Addr rwlock); -void DRD_(rwlock_post_destroy)(const Addr rwlock); -void DRD_(rwlock_pre_rdlock)(const Addr rwlock); -void DRD_(rwlock_post_rdlock)(const Addr rwlock, const Bool took_lock); -void DRD_(rwlock_pre_wrlock)(const Addr rwlock); -void DRD_(rwlock_post_wrlock)(const Addr rwlock, const Bool took_lock); -void DRD_(rwlock_pre_unlock)(const Addr rwlock); +struct rwlock_info* DRD_(rwlock_pre_init)(const Addr rwlock, + const RwLockT rwlock_type); +void DRD_(rwlock_post_destroy)(const Addr rwlock, const RwLockT rwlock_type); +void DRD_(rwlock_pre_rdlock)(const Addr rwlock, const RwLockT rwlock_type); +void DRD_(rwlock_post_rdlock)(const Addr rwlock, const RwLockT rwlock_type, + const Bool took_lock); +void DRD_(rwlock_pre_wrlock)(const Addr rwlock, const RwLockT rwlock_type); +void DRD_(rwlock_post_wrlock)(const Addr rwlock, const RwLockT rwlock_type, + const Bool took_lock); +void DRD_(rwlock_pre_unlock)(const Addr rwlock, const RwLockT rwlock_type); ULong DRD_(get_rwlock_segment_creation_count)(void); Modified: trunk/drd/drd_semaphore.c =================================================================== --- trunk/drd/drd_semaphore.c 2009-05-31 18:00:39 UTC (rev 10185) +++ trunk/drd/drd_semaphore.c 2009-05-31 18:53:54 UTC (rev 10186) @@ -121,7... [truncated message content] |