|
From: <sv...@va...> - 2008-03-02 17:43:16
|
Author: bart Date: 2008-03-02 17:43:18 +0000 (Sun, 02 Mar 2008) New Revision: 7531 Log: Added support for POSIX reader-writer locks. Modified exp-drd/tests/filter-stderr such that i386 and AMD64 now generate the same output. Removed *.stderr.exp2 files. Added section that explains differences between LinuxThreads and NPTL to exp-drd/docs/README.txt. Made error message about LinuxThreads more clear. Made error messages more uniform. Added: trunk/exp-drd/drd_rwlock.c trunk/exp-drd/drd_rwlock.h Removed: trunk/exp-drd/tests/fp_race.stderr.exp2 trunk/exp-drd/tests/hg03_inherit.stderr.exp2 trunk/exp-drd/tests/hg04_race.stderr.exp2 trunk/exp-drd/tests/sem_as_mutex.stderr.exp2 trunk/exp-drd/tests/tc01_simple_race.stderr.exp2 trunk/exp-drd/tests/tc04_free_lock.stderr.exp2 trunk/exp-drd/tests/tc06_two_races.stderr.exp2 trunk/exp-drd/tests/tc07_hbl1.stderr.exp2 trunk/exp-drd/tests/tc11_XCHG.stderr.exp2 trunk/exp-drd/tests/tc16_byterace.stderr.exp2 trunk/exp-drd/tests/tc20_verifywrap.stderr.exp2 trunk/exp-drd/tests/tc20_verifywrap2.stderr.exp2 Modified: trunk/exp-drd/Makefile.am trunk/exp-drd/docs/README.txt trunk/exp-drd/drd_clientobj.h trunk/exp-drd/drd_clientreq.c trunk/exp-drd/drd_clientreq.h trunk/exp-drd/drd_error.c trunk/exp-drd/drd_error.h trunk/exp-drd/drd_intercepts.c trunk/exp-drd/drd_mutex.c trunk/exp-drd/drd_mutex.h trunk/exp-drd/tests/Makefile.am trunk/exp-drd/tests/filter_stderr trunk/exp-drd/tests/fp_race.stderr.exp trunk/exp-drd/tests/hg05_race2.stderr.exp trunk/exp-drd/tests/recursive_mutex.stderr.exp trunk/exp-drd/tests/sem_as_mutex.stderr.exp trunk/exp-drd/tests/tc04_free_lock.stderr.exp trunk/exp-drd/tests/tc09_bad_unlock.stderr.exp trunk/exp-drd/tests/tc10_rec_lock.stderr.exp trunk/exp-drd/tests/tc12_rwl_trivial.stderr.exp trunk/exp-drd/tests/tc18_semabuse.stderr.exp trunk/exp-drd/tests/tc20_verifywrap.stderr.exp trunk/exp-drd/tests/tc20_verifywrap2.stderr.exp trunk/exp-drd/tests/tc23_bogus_condwait.stderr.exp Modified: trunk/exp-drd/Makefile.am =================================================================== --- trunk/exp-drd/Makefile.am 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/Makefile.am 2008-03-02 17:43:18 UTC (rev 7531) @@ -81,6 +81,7 @@ drd_main.c \ drd_malloc_wrappers.c \ drd_mutex.c \ + drd_rwlock.c \ drd_segment.c \ drd_semaphore.c \ drd_suppression.c \ @@ -96,6 +97,7 @@ drd_error.h \ drd_malloc_wrappers.h \ drd_mutex.h \ + drd_rwlock.h \ drd_segment.h \ drd_semaphore.h \ drd_suppression.h \ Modified: trunk/exp-drd/docs/README.txt =================================================================== --- trunk/exp-drd/docs/README.txt 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/docs/README.txt 2008-03-02 17:43:18 UTC (rev 7531) @@ -30,10 +30,10 @@ 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. +The de facto standard library for multithreading with the C and C++ +programming languages 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 @@ -202,9 +202,24 @@ 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. +also [Yodaiken 2004] for more information. Lock-free data structures +like circular buffers are well suited for real-time software. +Linux and POSIX Threads +----------------------- + +There exist two implementations of the POSIX threads API for +Linux. These implementations are called LinuxThreads and +NPTL. LinuxThreads was historically the first POSIX threads +implementation for Linux. LinuxThreads was compliant to most but not +all POSIX threads specifications. That is why a new threading library +for Linux was developed, called the NPTL (Native POSIX Threads +Library). Most Linux distributions switched from LinuxThreads to NPTL +around 2004. DRD only supports the NPTL. See also [Shukla 2006] for +more information. + + How to use DRD -------------- @@ -373,6 +388,12 @@ http://iacoma.cs.uiuc.edu/iacoma-papers/asid06.pdf http://portal.acm.org/citation.cfm?id=1181309.1181315 +[Shukla 2006] + Vikram Shukla + NPTL -- A rundown of the key differences for developers who need to port + July 31, 2006. + http://www-128.ibm.com/developerworks/linux/library/l-threading.html?ca=dgr-lnxw07LinuxThreadsAndNPTL + [Müehlenfeld 2007] Arndt Müehlenfeld, Franz Wotawa. Fault Detection in Multi-threaded C++ Server Applications. Modified: trunk/exp-drd/drd_clientobj.h =================================================================== --- trunk/exp-drd/drd_clientobj.h 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/drd_clientobj.h 2008-03-02 17:43:18 UTC (rev 7531) @@ -45,6 +45,7 @@ ClientCondvar = 2, ClientSemaphore = 3, ClientBarrier = 4, + ClientRwlock = 5, } ObjType; struct any @@ -96,14 +97,23 @@ Addr a2; ObjType type; void (*cleanup)(union drd_clientobj*); - Word count; // Participant count in a barrier wait. - Word pre_iteration; // pthread_barrier_wait() call count modulo two. - Word post_iteration; // pthread_barrier_wait() call count modulo two. - Word pre_waiters_left; // number of waiters left for a complete barrier. - Word post_waiters_left; // number of waiters left for a complete barrier. - OSet* oset; // Thread-specific barrier information. + Word count; // Participant count in a barrier wait. + Word pre_iteration; // pthread_barrier_wait() call count modulo two. + Word post_iteration; // pthread_barrier_wait() call count modulo two. + Word pre_waiters_left; // number of waiters left for a complete barrier. + Word post_waiters_left; // number of waiters left for a complete barrier. + OSet* oset; // Thread-specific barrier information. }; +struct rwlock_info +{ + Addr a1; + Addr a2; + ObjType type; + void (*cleanup)(union drd_clientobj*); + OSet* thread_info; +}; + typedef union drd_clientobj { struct any any; @@ -111,6 +121,7 @@ struct cond_info cond; struct semaphore_info semaphore; struct barrier_info barrier; + struct rwlock_info rwlock; } DrdClientobj; Modified: trunk/exp-drd/drd_clientreq.c =================================================================== --- trunk/exp-drd/drd_clientreq.c 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/drd_clientreq.c 2008-03-02 17:43:18 UTC (rev 7531) @@ -30,6 +30,7 @@ #include "drd_suppression.h" // drd_start_suppression() #include "drd_thread.h" #include "drd_track.h" +#include "drd_rwlock.h" #include "priv_drd_clientreq.h" #include "pub_tool_basics.h" // Bool #include "pub_tool_libcassert.h" @@ -214,24 +215,31 @@ break; case VG_USERREQ__PRE_RWLOCK_INIT: + rwlock_pre_init(arg[1], arg[2]); break; case VG_USERREQ__POST_RWLOCK_DESTROY: + rwlock_post_destroy(arg[1]); break; case VG_USERREQ__PRE_RWLOCK_RDLOCK: + rwlock_pre_rdlock(arg[1], arg[2]); break; case VG_USERREQ__POST_RWLOCK_RDLOCK: + rwlock_post_rdlock(arg[1], arg[2]); break; case VG_USERREQ__PRE_RWLOCK_WRLOCK: + rwlock_pre_wrlock(arg[1], arg[2]); break; case VG_USERREQ__POST_RWLOCK_WRLOCK: + rwlock_post_wrlock(arg[1], arg[2]); break; - case VG_USERREQ__POST_RWLOCK_UNLOCK: + case VG_USERREQ__PRE_RWLOCK_UNLOCK: + rwlock_pre_unlock(arg[1]); break; default: Modified: trunk/exp-drd/drd_clientreq.h =================================================================== --- trunk/exp-drd/drd_clientreq.h 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/drd_clientreq.h 2008-03-02 17:43:18 UTC (rev 7531) @@ -128,7 +128,7 @@ VG_USERREQ__POST_RWLOCK_WRLOCK, /* args: Addr rwlock, Bool took_lock */ /* To notify the drd tool of a pthread_rwlock_unlock call. */ - VG_USERREQ__POST_RWLOCK_UNLOCK, + VG_USERREQ__PRE_RWLOCK_UNLOCK, /* args: Addr rwlock, Bool unlocked */ }; Modified: trunk/exp-drd/drd_error.c =================================================================== --- trunk/exp-drd/drd_error.c 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/drd_error.c 2008-03-02 17:43:18 UTC (rev 7531) @@ -261,7 +261,7 @@ MutexErrInfo* p = (MutexErrInfo*)(VG_(get_error_extra)(e)); tl_assert(p); VG_(message)(Vg_UserMsg, - "%s: address 0x%lx, recursion count %d, owner %d.", + "%s: mutex 0x%lx, recursion count %d, owner %d.", VG_(get_error_string)(e), p->mutex, p->recursion_count, @@ -272,7 +272,7 @@ case CondErr: { CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e)); VG_(message)(Vg_UserMsg, - "cond 0x%lx: %s", + "%s: cond 0x%lx", cdei->cond, VG_(get_error_string)(e)); VG_(pp_ExeContext)(VG_(get_error_where)(e)); @@ -300,7 +300,7 @@ SemaphoreErrInfo* sei =(SemaphoreErrInfo*)(VG_(get_error_extra)(e)); tl_assert(sei); VG_(message)(Vg_UserMsg, - "%s 0x%lx", + "%s: semaphore 0x%lx", VG_(get_error_string)(e), sei->semaphore); VG_(pp_ExeContext)(VG_(get_error_where)(e)); @@ -316,6 +316,16 @@ VG_(pp_ExeContext)(VG_(get_error_where)(e)); break; } + case RwlockErr: { + RwlockErrInfo* p = (RwlockErrInfo*)(VG_(get_error_extra)(e)); + tl_assert(p); + VG_(message)(Vg_UserMsg, + "%s: rwlock 0x%lx.", + VG_(get_error_string)(e), + p->rwlock); + VG_(pp_ExeContext)(VG_(get_error_where)(e)); + break; + } case GenericErr: { //GenericErrInfo* gei =(GenericErrInfo*)(VG_(get_error_extra)(e)); VG_(message)(Vg_UserMsg, "%s", VG_(get_error_string)(e)); @@ -349,6 +359,8 @@ return sizeof(SemaphoreErrInfo); case BarrierErr: return sizeof(BarrierErrInfo); + case RwlockErr: + return sizeof(RwlockErrInfo); case GenericErr: return sizeof(GenericErrInfo); default: @@ -387,9 +399,15 @@ { switch (VG_(get_error_kind)(e)) { - case DataRaceErr: return "ConflictingAccess"; - case MutexErr: return "MutexErr"; - case CondRaceErr: return "CondRaceErr"; + case DataRaceErr: return "DataRaceErr"; + case MutexErr: return "MutexErr"; + case CondErr: return "CondErr"; + case CondRaceErr: return "CondRaceErr"; + case CondDestrErr: return "CondDestrErr"; + case SemaphoreErr: return "SemaphoreErr"; + case BarrierErr: return "BarrierErr"; + case RwlockErr: return "RwlockErr"; + case GenericErr: return "GenericErr"; default: tl_assert(0); } Modified: trunk/exp-drd/drd_error.h =================================================================== --- trunk/exp-drd/drd_error.h 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/drd_error.h 2008-03-02 17:43:18 UTC (rev 7531) @@ -44,7 +44,8 @@ CondDestrErr = 5, SemaphoreErr = 6, BarrierErr = 7, - GenericErr = 8, + RwlockErr = 8, + GenericErr = 9, } DrdErrorKind; /* The classification of a faulting address. */ @@ -113,6 +114,10 @@ } BarrierErrInfo; typedef struct { + Addr rwlock; +} RwlockErrInfo; + +typedef struct { } GenericErrInfo; void describe_addr(Addr const a, SizeT const len, AddrInfo* const ai); Modified: trunk/exp-drd/drd_intercepts.c =================================================================== --- trunk/exp-drd/drd_intercepts.c 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/drd_intercepts.c 2008-03-02 17:43:18 UTC (rev 7531) @@ -143,11 +143,23 @@ if (getpid() != vg_main_thread_pid) { - fprintf(stderr, - "Detected the linuxthreads threading library.\n" - "Sorry, but DRD does not support linuxthreads.\n" - "Please try to run DRD on a system with NPTL instead.\n" - "Giving up.\n"); + if (getenv("LD_ASSUME_KERNEL")) + { + fprintf(stderr, +"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" +"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" +"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n" + ); + } + else + { + fprintf(stderr, +"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" +"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" +"after having upgraded to a newer version of your Linux distribution.\n" +"Giving up.\n" + ); + } abort(); } @@ -940,7 +952,7 @@ OrigFn fn; VALGRIND_GET_ORIG_FN(fn); CALL_FN_W_W(ret, fn, rwlock); - VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK, + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK, rwlock, ret == 0, 0, 0, 0); return ret; } Modified: trunk/exp-drd/drd_mutex.c =================================================================== --- trunk/exp-drd/drd_mutex.c 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/drd_mutex.c 2008-03-02 17:43:18 UTC (rev 7531) @@ -159,7 +159,7 @@ VG_(maybe_record_error)(VG_(get_running_tid)(), GenericErr, VG_(get_IP)(VG_(get_running_tid)()), - "Invalid mutex", + "Not a mutex", &GEI); return 0; } @@ -231,7 +231,7 @@ VG_(maybe_record_error)(VG_(get_running_tid)(), GenericErr, VG_(get_IP)(VG_(get_running_tid)()), - "Invalid mutex", + "Not a mutex", &GEI); return; } @@ -261,7 +261,7 @@ * Note: this function must be called after pthread_mutex_lock() has been * called, or a race condition is triggered ! */ -int mutex_post_lock(const Addr mutex, const Bool took_lock) +void mutex_post_lock(const Addr mutex, const Bool took_lock) { const DrdThreadId drd_tid = thread_get_running_tid(); struct mutex_info* p; @@ -280,14 +280,9 @@ p ? p->owner : VG_INVALID_THREADID); } - if (p == 0) - { - return 0; - } + if (! p || ! took_lock) + return; - if (! took_lock) - return p->recursion_count; - if (p->recursion_count == 0) { p->owner = drd_tid; @@ -312,8 +307,6 @@ thread_combine_vc2(drd_tid, mutex_get_last_vc(mutex)); thread_new_segment(drd_tid); } - - return p->recursion_count; } /** @@ -325,45 +318,34 @@ * @param tid ThreadId of the thread calling pthread_mutex_unlock(). * @param vc Pointer to the current vector clock of thread tid. */ -int mutex_unlock(const Addr mutex, const MutexT mutex_type) +void mutex_unlock(const Addr mutex, const MutexT mutex_type) { const DrdThreadId drd_tid = thread_get_running_tid(); const ThreadId vg_tid = VG_(get_running_tid)(); const VectorClock* const vc = thread_get_vc(drd_tid); struct mutex_info* const p = mutex_get(mutex); - if (s_trace_mutex && p != 0) + if (s_trace_mutex) { VG_(message)(Vg_UserMsg, "[%d/%d] mutex_unlock %s 0x%lx rc %d", vg_tid, drd_tid, - mutex_get_typename(p), + p ? mutex_get_typename(p) : "?", mutex, - p->recursion_count, - p->owner); + p ? p->recursion_count : 0, + p ? p->owner : 0); } - if (mutex_type == mutex_type_invalid_mutex) + if (p == 0 || mutex_type == mutex_type_invalid_mutex) { - GenericErrInfo GEI; - VG_(maybe_record_error)(VG_(get_running_tid)(), - GenericErr, - VG_(get_IP)(VG_(get_running_tid)()), - "Invalid mutex", - &GEI); - return 0; - } - - if (p == 0) - { GenericErrInfo GEI; VG_(maybe_record_error)(vg_tid, GenericErr, VG_(get_IP)(vg_tid), "Not a mutex", &GEI); - return 0; + return; } if (p->owner == DRD_INVALID_THREADID) @@ -374,7 +356,7 @@ VG_(get_IP)(vg_tid), "Mutex not locked", &MEI); - return 0; + return; } tl_assert(p); @@ -386,27 +368,19 @@ tl_assert(p->mutex_type == mutex_type); tl_assert(p->owner != DRD_INVALID_THREADID); - if (p->owner != drd_tid) + if (p->owner != drd_tid || p->recursion_count <= 0) { MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner }; VG_(maybe_record_error)(vg_tid, MutexErr, VG_(get_IP)(vg_tid), - "Mutex not unlocked by owner thread", + "Mutex not locked by calling thread", &MEI); + return; } + tl_assert(p->recursion_count > 0); p->recursion_count--; - if (p->recursion_count < 0) - { - MutexErrInfo MEI - = { p->a1, p->recursion_count, p->owner }; - VG_(maybe_record_error)(vg_tid, - MutexErr, - VG_(get_IP)(vg_tid), - "Attempt to unlock a mutex that is not locked", - &MEI); - p->recursion_count = 0; - } + tl_assert(p->recursion_count >= 0); if (p->recursion_count == 0) { @@ -417,7 +391,6 @@ thread_new_segment(drd_tid); } - return p->recursion_count; } const char* mutex_get_typename(struct mutex_info* const p) Modified: trunk/exp-drd/drd_mutex.h =================================================================== --- trunk/exp-drd/drd_mutex.h 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/drd_mutex.h 2008-03-02 17:43:18 UTC (rev 7531) @@ -26,8 +26,8 @@ // Mutex state information: owner thread and recursion count. -#ifndef __MUTEX_H -#define __MUTEX_H +#ifndef __DRD_MUTEX_H +#define __DRD_MUTEX_H #include "drd_clientreq.h" // MutexT @@ -46,8 +46,8 @@ struct mutex_info* mutex_get(const Addr mutex); void mutex_pre_lock(const Addr mutex, const SizeT size, const MutexT mutex_type); -int mutex_post_lock(const Addr mutex, const Bool took_lock); -int mutex_unlock(const Addr mutex, const MutexT mutex_type); +void mutex_post_lock(const Addr mutex, const Bool took_lock); +void mutex_unlock(const Addr mutex, const MutexT mutex_type); const char* mutex_get_typename(struct mutex_info* const p); const char* mutex_type_name(const MutexT mt); Bool mutex_is_locked_by(const Addr mutex, const DrdThreadId tid); @@ -57,4 +57,4 @@ ULong get_mutex_lock_count(void); -#endif /* __MUTEX_H */ +#endif /* __DRD_MUTEX_H */ Added: trunk/exp-drd/drd_rwlock.c =================================================================== --- trunk/exp-drd/drd_rwlock.c (rev 0) +++ trunk/exp-drd/drd_rwlock.c 2008-03-02 17:43:18 UTC (rev 7531) @@ -0,0 +1,519 @@ +/* + This file is part of drd, a data race detector. + + Copyright (C) 2006-2008 Bart Van Assche + bar...@gm... + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + + +#include "drd_clientobj.h" +#include "drd_error.h" +#include "drd_rwlock.h" +#include "priv_drd_clientreq.h" +#include "pub_tool_errormgr.h" // VG_(maybe_record_error)() +#include "pub_tool_libcassert.h" // tl_assert() +#include "pub_tool_libcprint.h" // VG_(message)() +#include "pub_tool_machine.h" // VG_(get_IP)() +#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)() +#include "pub_tool_threadstate.h" // VG_(get_running_tid)() + + +// Type definitions. + +struct rwlock_thread_info +{ + UWord tid; // DrdThreadId. + UInt reader_nesting_count; + UInt writer_nesting_count; + VectorClock vc; // Vector clock associated with last unlock by this thread. +}; + + +// Local functions. + +static void rwlock_cleanup(struct rwlock_info* p); + + +// Local variables. + +static Bool s_trace_rwlock; + + +// Function definitions. + +void rwlock_set_trace(const Bool trace_rwlock) +{ + tl_assert(!! trace_rwlock == trace_rwlock); + s_trace_rwlock = trace_rwlock; +} + +static Bool rwlock_is_rdlocked(struct rwlock_info* p) +{ + struct rwlock_thread_info* q; + + VG_(OSetGen_ResetIter)(p->thread_info); + for ( ; (q = VG_(OSetGen_Next)(p->thread_info)); q++) + { + return q->reader_nesting_count > 0; + } + return False; +} + +static Bool rwlock_is_wrlocked(struct rwlock_info* p) +{ + struct rwlock_thread_info* q; + + VG_(OSetGen_ResetIter)(p->thread_info); + for ( ; (q = VG_(OSetGen_Next)(p->thread_info)); q++) + { + return q->writer_nesting_count > 0; + } + return False; +} + +static Bool rwlock_is_locked(struct rwlock_info* p) +{ + return rwlock_is_rdlocked(p) || rwlock_is_wrlocked(p); +} + +static Bool rwlock_is_rdlocked_by(struct rwlock_info* p, const DrdThreadId tid) +{ + const UWord uword_tid = tid; + struct rwlock_thread_info* q; + + q = VG_(OSetGen_Lookup)(p->thread_info, &uword_tid); + return q && q->reader_nesting_count > 0; +} + +static Bool rwlock_is_wrlocked_by(struct rwlock_info* p, const DrdThreadId tid) +{ + const UWord uword_tid = tid; + struct rwlock_thread_info* q; + + q = VG_(OSetGen_Lookup)(p->thread_info, &uword_tid); + return q && q->writer_nesting_count > 0; +} + +static Bool rwlock_is_locked_by(struct rwlock_info* p, const DrdThreadId tid) +{ + return rwlock_is_rdlocked_by(p, tid) || rwlock_is_wrlocked_by(p, tid); +} + +static +struct rwlock_thread_info* lookup_or_insert_node(OSet* oset, const UWord tid) +{ + struct rwlock_thread_info* q; + + q = VG_(OSetGen_Lookup)(oset, &tid); + if (q == 0) + { + q = VG_(OSetGen_AllocNode)(oset, sizeof(*q)); + q->tid = tid; + q->reader_nesting_count = 0; + q->writer_nesting_count = 0; + vc_init(&q->vc, 0, 0); + VG_(OSetGen_Insert)(oset, q); + } + tl_assert(q); + return q; +} + +static void rwlock_combine_other_vc(struct rwlock_info* const p, + const DrdThreadId tid) +{ + struct rwlock_thread_info* q; + + VG_(OSetGen_ResetIter)(p->thread_info); + for ( ; (q = VG_(OSetGen_Next)(p->thread_info)) != 0; ) + { + if (q->tid != tid) + { + thread_combine_vc2(tid, &q->vc); + } + } +} + +static +void rwlock_initialize(struct rwlock_info* const p, + const Addr rwlock, + const SizeT size) +{ + tl_assert(rwlock != 0); + tl_assert(size > 0); + tl_assert(p->a1 == rwlock); + tl_assert(p->a2 == rwlock + size); + tl_assert(p->type == ClientRwlock); + + p->cleanup = (void(*)(DrdClientobj*))&rwlock_cleanup; + p->thread_info = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free)); +} + +/** Deallocate the memory that was allocated by rwlock_initialize(). */ +static void rwlock_cleanup(struct rwlock_info* p) +{ + struct rwlock_thread_info* q; + + tl_assert(p); + + if (s_trace_rwlock) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] rwlock_destroy 0x%lx", + VG_(get_running_tid)(), + thread_get_running_tid(), + p->a1); + } + + if (rwlock_is_locked(p)) + { + RwlockErrInfo REI = { p->a1 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + RwlockErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Destroying locked rwlock", + &REI); + } + + VG_(OSetGen_ResetIter)(p->thread_info); + for ( ; (q = VG_(OSetGen_Next)(p->thread_info)); q++) + { + vc_cleanup(&q->vc); + } + VG_(OSetGen_Destroy)(p->thread_info); +} + +static +struct rwlock_info* +rwlock_get_or_allocate(const Addr rwlock, const SizeT size) +{ + struct rwlock_info* p; + + tl_assert(offsetof(DrdClientobj, rwlock) == 0); + p = &clientobj_get(rwlock, ClientRwlock)->rwlock; + if (p) + { + tl_assert(p->a2 - p->a1 == size); + return p; + } + + if (clientobj_present(rwlock, rwlock + size)) + { + GenericErrInfo GEI; + VG_(maybe_record_error)(VG_(get_running_tid)(), + GenericErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Not a reader-writer lock", + &GEI); + return 0; + } + + p = &clientobj_add(rwlock, rwlock + size, ClientRwlock)->rwlock; + rwlock_initialize(p, rwlock, size); + return p; +} + +static struct rwlock_info* rwlock_get(const Addr rwlock) +{ + tl_assert(offsetof(DrdClientobj, rwlock) == 0); + return &clientobj_get(rwlock, ClientRwlock)->rwlock; +} + +/** Called before pthread_rwlock_init(). */ +struct rwlock_info* +rwlock_pre_init(const Addr rwlock, const SizeT size) +{ + struct rwlock_info* p; + + if (s_trace_rwlock) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] rwlock_init %s 0x%lx", + VG_(get_running_tid)(), + thread_get_running_tid(), + rwlock); + } + + p = rwlock_get(rwlock); + + if (p) + { + const ThreadId vg_tid = VG_(get_running_tid)(); + RwlockErrInfo REI + = { p->a1 }; + VG_(maybe_record_error)(vg_tid, + RwlockErr, + VG_(get_IP)(vg_tid), + "Reader-writer lock reinitialization", + &REI); + return p; + } + + p = rwlock_get_or_allocate(rwlock, size); + + return p; +} + +/** Called after pthread_rwlock_destroy(). */ +void rwlock_post_destroy(const Addr rwlock) +{ + struct rwlock_info* p; + + p = rwlock_get(rwlock); + if (p == 0) + { + GenericErrInfo GEI; + VG_(maybe_record_error)(VG_(get_running_tid)(), + GenericErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Not a reader-writer lock", + &GEI); + return; + } + + clientobj_remove(rwlock, ClientRwlock); +} + +/** Called before pthread_rwlock_rdlock() is invoked. If a data structure for + * the client-side object was not yet created, do this now. Also check whether + * an attempt is made to lock recursively a synchronization object that must + * not be locked recursively. + */ +void rwlock_pre_rdlock(const Addr rwlock, const SizeT size) +{ + struct rwlock_info* p; + + p = rwlock_get_or_allocate(rwlock, size); + + tl_assert(p); + + if (s_trace_rwlock) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] pre_rwlock_rdlock 0x%lx", + VG_(get_running_tid)(), + thread_get_running_tid(), + rwlock); + } + + if (rwlock_is_wrlocked_by(p, thread_get_running_tid())) + { + VG_(message)(Vg_UserMsg, + "reader-writer lock 0x%lx is already locked for" + " writing by calling thread", + p->a1); + } +} + +/** + * Update rwlock_info state when locking the pthread_rwlock_t mutex. + * Note: this function must be called after pthread_rwlock_rdlock() has been + * called, or a race condition is triggered ! + */ +void rwlock_post_rdlock(const Addr rwlock, const Bool took_lock) +{ + const DrdThreadId drd_tid = thread_get_running_tid(); + struct rwlock_info* p; + struct rwlock_thread_info* q; + + p = rwlock_get(rwlock); + + if (s_trace_rwlock) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] post_rwlock_rdlock 0x%lx", + VG_(get_running_tid)(), + drd_tid, + rwlock); + } + + if (! p || ! took_lock) + return; + + tl_assert(! rwlock_is_wrlocked(p)); + + q = lookup_or_insert_node(p->thread_info, drd_tid); + if (++q->reader_nesting_count == 1) + { + rwlock_combine_other_vc(p, drd_tid); + thread_new_segment(drd_tid); + } +} + +/** Called before pthread_rwlock_wrlock() is invoked. If a data structure for + * the client-side object was not yet created, do this now. Also check whether + * an attempt is made to lock recursively a synchronization object that must + * not be locked recursively. + */ +void rwlock_pre_wrlock(const Addr rwlock, const SizeT size) +{ + struct rwlock_info* p; + + p = rwlock_get(rwlock); + + if (s_trace_rwlock) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] pre_rwlock_wrlock 0x%lx", + VG_(get_running_tid)(), + thread_get_running_tid(), + rwlock); + } + + if (p == 0) + { + p = rwlock_get_or_allocate(rwlock, size); + } + + tl_assert(p); + + if (rwlock_is_wrlocked_by(p, thread_get_running_tid())) + { + RwlockErrInfo REI = { p->a1 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + RwlockErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Recursive writer locking not allowed", + &REI); + } +} + +/** + * Update rwlock_info state when locking the pthread_rwlock_t rwlock. + * Note: this function must be called after pthread_rwlock_wrlock() has been + * called, or a race condition is triggered ! + */ +void rwlock_post_wrlock(const Addr rwlock, const Bool took_lock) +{ + const DrdThreadId drd_tid = thread_get_running_tid(); + struct rwlock_info* p; + struct rwlock_thread_info* q; + + p = rwlock_get(rwlock); + + if (s_trace_rwlock) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] post_rwlock_wrlock 0x%lx", + VG_(get_running_tid)(), + drd_tid, + rwlock); + } + + if (! p || ! took_lock) + return; + + q = lookup_or_insert_node(p->thread_info, thread_get_running_tid()); + tl_assert(q->writer_nesting_count == 0); + q->writer_nesting_count++; + tl_assert(q->writer_nesting_count == 1); + rwlock_combine_other_vc(p, drd_tid); + thread_new_segment(drd_tid); +} + +/** + * Update rwlock_info state when unlocking the pthread_rwlock_t rwlock. + * Note: this function must be called before pthread_rwlock_unlock() is called, + * or a race condition is triggered ! + * @return New value of the rwlock recursion count. + * @param rwlock Pointer to pthread_rwlock_t data structure in the client space. + * @param tid ThreadId of the thread calling pthread_rwlock_unlock(). + * @param vc Pointer to the current vector clock of thread tid. + */ +void rwlock_pre_unlock(const Addr rwlock) +{ + const DrdThreadId drd_tid = thread_get_running_tid(); + const ThreadId vg_tid = VG_(get_running_tid)(); + const VectorClock* const vc = thread_get_vc(drd_tid); + struct rwlock_info* const p = rwlock_get(rwlock); + struct rwlock_thread_info* q; + + if (s_trace_rwlock && p != 0) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] rwlock_unlock 0x%lx", + vg_tid, + drd_tid, + rwlock); + } + + if (p == 0 || ! rwlock_is_locked_by(p, drd_tid)) + { + RwlockErrInfo REI = { p->a1 }; + VG_(maybe_record_error)(vg_tid, + RwlockErr, + VG_(get_IP)(vg_tid), + "Reader-writer lock not locked by calling thread", + &REI); + return; + } + tl_assert(p); + q = lookup_or_insert_node(p->thread_info, drd_tid); + tl_assert(q); + if (q->reader_nesting_count > 0) + q->reader_nesting_count--; + else if (q->writer_nesting_count > 0) + q->writer_nesting_count--; + else + tl_assert(False); + + if (q->reader_nesting_count == 0 && q->writer_nesting_count == 0) + { + /* This pthread_rwlock_unlock() call really unlocks the rwlock. Save the */ + /* current vector clock of the thread such that it is available when */ + /* this rwlock is locked again. */ + vc_assign(&q->vc, vc); + + thread_new_segment(drd_tid); + } +} + +/** + * Call this function when thread tid stops to exist, such that the + * "last owner" field can be cleared if it still refers to that thread. + */ +void rwlock_thread_delete(const DrdThreadId tid) +{ + struct rwlock_info* p; + + clientobj_resetiter(); + for ( ; (p = &clientobj_next(ClientRwlock)->rwlock) != 0; ) + { + struct rwlock_thread_info* q; + if (rwlock_is_locked_by(p, tid)) + { + RwlockErrInfo REI = { p->a1 }; + VG_(maybe_record_error)(VG_(get_running_tid)(), + RwlockErr, + VG_(get_IP)(VG_(get_running_tid)()), + "Reader-writer lock still locked at thread exit", + &REI); + q = lookup_or_insert_node(p->thread_info, tid); + q->reader_nesting_count = 0; + q->writer_nesting_count = 0; + } + } +} + + +/* + * Local variables: + * c-basic-offset: 2 + * End: + */ Added: trunk/exp-drd/drd_rwlock.h =================================================================== --- trunk/exp-drd/drd_rwlock.h (rev 0) +++ trunk/exp-drd/drd_rwlock.h 2008-03-02 17:43:18 UTC (rev 7531) @@ -0,0 +1,53 @@ +/* + This file is part of drd, a data race detector. + + Copyright (C) 2006-2008 Bart Van Assche + bar...@gm... + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + + +// Reader-writer lock state information. + + +#ifndef __DRD_RWLOCK_H +#define __DRD_RWLOCK_H + + +#include "drd_clientobj.h" // struct rwlock_info +#include "drd_thread.h" // DrdThreadId +#include "drd_vc.h" +#include "pub_tool_basics.h" // Addr, SizeT + + +struct rwlock_info; + + +void rwlock_set_trace(const Bool trace_rwlock); +struct rwlock_info* rwlock_pre_init(const Addr rwlock, const SizeT size); +void rwlock_post_destroy(const Addr rwlock); +void rwlock_pre_rdlock(const Addr rwlock, const SizeT size); +void rwlock_post_rdlock(const Addr rwlock, const Bool took_lock); +void rwlock_pre_wrlock(const Addr rwlock, const SizeT size); +void rwlock_post_wrlock(const Addr rwlock, const Bool took_lock); +void rwlock_pre_unlock(const Addr rwlock); +void rwlock_thread_delete(const DrdThreadId tid); + + +#endif /* __DRD_RWLOCK_H */ Modified: trunk/exp-drd/tests/Makefile.am =================================================================== --- trunk/exp-drd/tests/Makefile.am 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/Makefile.am 2008-03-02 17:43:18 UTC (rev 7531) @@ -16,7 +16,6 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ fp_race.vgtest \ fp_race.stdout.exp fp_race.stderr.exp \ - fp_race.stderr.exp2 \ fp_race2.vgtest \ fp_race2.stdout.exp fp_race2.stderr.exp \ hg01_all_ok.vgtest \ @@ -25,10 +24,8 @@ hg02_deadlock.stderr.exp \ hg03_inherit.vgtest \ hg03_inherit.stderr.exp \ - hg03_inherit.stderr.exp2 \ hg04_race.vgtest \ hg04_race.stderr.exp \ - hg04_race.stderr.exp2 \ hg05_race2.vgtest \ hg05_race2.stderr.exp \ hg06_readshared.vgtest \ @@ -51,13 +48,10 @@ pth_detached2.vgtest \ pth_detached2.stdout.exp pth_detached2.stderr.exp \ recursive_mutex.vgtest recursive_mutex.stderr.exp \ - sem_as_mutex.vgtest \ - sem_as_mutex.stderr.exp sem_as_mutex.stderr.exp2 \ - sem_as_mutex2.vgtest \ - sem_as_mutex2.stderr.exp \ + sem_as_mutex.vgtest sem_as_mutex.stderr.exp \ + sem_as_mutex2.vgtest sem_as_mutex2.stderr.exp \ tc01_simple_race.vgtest \ tc01_simple_race.stderr.exp \ - tc01_simple_race.stderr.exp2 \ tc02_simple_tls.vgtest \ tc02_simple_tls.stderr.exp \ tc03_re_excl.vgtest \ @@ -74,7 +68,6 @@ tc10_rec_lock.stderr.exp \ tc11_XCHG.vgtest \ tc11_XCHG.stderr.exp tc11_XCHG.stdout.exp \ - tc11_XCHG.stderr.exp2 \ tc12_rwl_trivial.vgtest \ tc12_rwl_trivial.stderr.exp \ tc13_laog1.vgtest \ @@ -83,17 +76,14 @@ tc15_laog_lockdel.stderr.exp \ tc16_byterace.vgtest \ tc16_byterace.stderr.exp \ - tc16_byterace.stderr.exp2 \ tc17_sembar.vgtest \ tc17_sembar.stderr.exp \ tc18_semabuse.vgtest \ tc18_semabuse.stderr.exp \ tc19_shadowmem.vgtest \ tc19_shadowmem.stderr.exp \ - tc20_verifywrap.vgtest \ - tc20_verifywrap.stderr.exp tc20_verifywrap.stderr.exp2 \ - tc20_verifywrap2.vgtest \ - tc20_verifywrap2.stderr.exp tc20_verifywrap2.stderr.exp2\ + tc20_verifywrap.vgtest tc20_verifywrap.stderr.exp \ + tc20_verifywrap2.vgtest tc20_verifywrap2.stderr.exp \ tc21_pthonce.vgtest \ tc21_pthonce.stderr.exp tc21_pthonce.stdout.exp \ tc22_exit_w_lock.vgtest \ Modified: trunk/exp-drd/tests/filter_stderr =================================================================== --- trunk/exp-drd/tests/filter_stderr 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/filter_stderr 2008-03-02 17:43:18 UTC (rev 7531) @@ -11,6 +11,7 @@ sed \ -e "/^exp-drd, a data race detector\.$/d" \ -e "s/^Allocation context: stack of thread \([0-9]*\), offset -[0-9]*$/Allocation context: stack of thread \1, offset .../" \ +-e "s/^Allocation context: .*$/Allocation context: unknown/" \ -e "/^NOTE: This is an Experimental-Class Valgrind Tool.$/d" \ -e "/^Copyright (C) 2006-200., and GNU GPL'd, by Bart Van Assche.$/d" \ -e "s/\(pthread_create.c:[0-9]*\)/in libpthread-?.?.so/" \ Modified: trunk/exp-drd/tests/fp_race.stderr.exp =================================================================== --- trunk/exp-drd/tests/fp_race.stderr.exp 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/fp_race.stderr.exp 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,7 +1,7 @@ Conflicting load by main at 0x........ size 8 at 0x........: main (fp_race.c:?) -Allocation context: s_d3 (offset 0, size 8) in fp_race, NONE:BSS +Allocation context: unknown Other segment start (thread_func) (thread finished, call stack no longer available) Other segment end (thread_func) @@ -9,7 +9,7 @@ Conflicting store by main at 0x........ size 8 at 0x........: main (fp_race.c:?) -Allocation context: s_d3 (offset 0, size 8) in fp_race, NONE:BSS +Allocation context: unknown Other segment start (thread_func) (thread finished, call stack no longer available) Other segment end (thread_func) Deleted: trunk/exp-drd/tests/fp_race.stderr.exp2 =================================================================== --- trunk/exp-drd/tests/fp_race.stderr.exp2 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/fp_race.stderr.exp2 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,18 +0,0 @@ - -Conflicting load by main at 0x........ size 8 - at 0x........: main (fp_race.c:?) -Allocation context: unknown -Other segment start (thread_func) - (thread finished, call stack no longer available) -Other segment end (thread_func) - (thread finished, call stack no longer available) - -Conflicting store by main at 0x........ size 8 - at 0x........: main (fp_race.c:?) -Allocation context: unknown -Other segment start (thread_func) - (thread finished, call stack no longer available) -Other segment end (thread_func) - (thread finished, call stack no longer available) - -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Deleted: trunk/exp-drd/tests/hg03_inherit.stderr.exp2 =================================================================== --- trunk/exp-drd/tests/hg03_inherit.stderr.exp2 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/hg03_inherit.stderr.exp2 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,31 +0,0 @@ - -Thread 3: -Conflicting store by thread 3 at 0x........ size 4 - at 0x........: t2 (hg03_inherit.c:28) - by 0x........: vg_thread_wrapper (drd_intercepts.c:?) - by 0x........: start_thread (in libpthread-?.?.so) - by 0x........: clone (in /...libc...) -Allocation context: unknown -Other segment start (thread 1) - at 0x........: pthread_join (drd_intercepts.c:?) - by 0x........: main (hg03_inherit.c:49) -Other segment end (thread 1) - at 0x........: pthread_join (in libpthread-?.?.so) - by 0x........: pthread_join (drd_intercepts.c:?) - by 0x........: main (hg03_inherit.c:63) - -Conflicting store by thread 3 at 0x........ size 4 - at 0x........: t2 (hg03_inherit.c:29) - by 0x........: vg_thread_wrapper (drd_intercepts.c:?) - by 0x........: start_thread (in libpthread-?.?.so) - by 0x........: clone (in /...libc...) -Allocation context: unknown -Other segment start (thread 1) - at 0x........: pthread_join (drd_intercepts.c:?) - by 0x........: main (hg03_inherit.c:49) -Other segment end (thread 1) - at 0x........: pthread_join (in libpthread-?.?.so) - by 0x........: pthread_join (drd_intercepts.c:?) - by 0x........: main (hg03_inherit.c:63) - -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Deleted: trunk/exp-drd/tests/hg04_race.stderr.exp2 =================================================================== --- trunk/exp-drd/tests/hg04_race.stderr.exp2 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/hg04_race.stderr.exp2 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,25 +0,0 @@ - -Thread 2: -Conflicting load by thread 2 at 0x........ size 4 - at 0x........: th (hg04_race.c:10) - by 0x........: vg_thread_wrapper (drd_intercepts.c:?) - by 0x........: start_thread (in libpthread-?.?.so) - by 0x........: clone (in /...libc...) -Allocation context: unknown -Other segment start (thread 2) - (thread finished, call stack no longer available) -Other segment end (thread 2) - (thread finished, call stack no longer available) - -Conflicting store by thread 2 at 0x........ size 4 - at 0x........: th (hg04_race.c:10) - by 0x........: vg_thread_wrapper (drd_intercepts.c:?) - by 0x........: start_thread (in libpthread-?.?.so) - by 0x........: clone (in /...libc...) -Allocation context: unknown -Other segment start (thread 2) - (thread finished, call stack no longer available) -Other segment end (thread 2) - (thread finished, call stack no longer available) - -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Modified: trunk/exp-drd/tests/hg05_race2.stderr.exp =================================================================== --- trunk/exp-drd/tests/hg05_race2.stderr.exp 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/hg05_race2.stderr.exp 2008-03-02 17:43:18 UTC (rev 7531) @@ -5,7 +5,7 @@ by 0x........: vg_thread_wrapper (drd_intercepts.c:?) by 0x........: start_thread (in libpthread-?.?.so) by 0x........: clone (in /...libc...) -Allocation context: stack of thread 1, offset ... +Allocation context: unknown Other segment start (thread 2) (thread finished, call stack no longer available) Other segment end (thread 2) @@ -16,7 +16,7 @@ by 0x........: vg_thread_wrapper (drd_intercepts.c:?) by 0x........: start_thread (in libpthread-?.?.so) by 0x........: clone (in /...libc...) -Allocation context: stack of thread 1, offset ... +Allocation context: unknown Other segment start (thread 2) (thread finished, call stack no longer available) Other segment end (thread 2) Modified: trunk/exp-drd/tests/recursive_mutex.stderr.exp =================================================================== --- trunk/exp-drd/tests/recursive_mutex.stderr.exp 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/recursive_mutex.stderr.exp 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,15 +1,15 @@ -Recursive locking not allowed: address 0x........, recursion count 1, owner 1. +Recursive locking not allowed: mutex 0x........, recursion count 1, owner 1. at 0x........: pthread_mutex_lock (drd_intercepts.c:?) by 0x........: lock_twice (recursive_mutex.c:?) by 0x........: main (recursive_mutex.c:?) -Attempt to unlock a mutex that is not locked: address 0x........, recursion count -1, owner 1. +Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1. at 0x........: pthread_mutex_unlock (drd_intercepts.c:?) by 0x........: lock_twice (recursive_mutex.c:?) by 0x........: main (recursive_mutex.c:?) -Recursive locking not allowed: address 0x........, recursion count 1, owner 1. +Recursive locking not allowed: mutex 0x........, recursion count 1, owner 1. at 0x........: pthread_mutex_lock (drd_intercepts.c:?) by 0x........: lock_twice (recursive_mutex.c:?) by 0x........: main (recursive_mutex.c:?) Modified: trunk/exp-drd/tests/sem_as_mutex.stderr.exp =================================================================== --- trunk/exp-drd/tests/sem_as_mutex.stderr.exp 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/sem_as_mutex.stderr.exp 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,7 +1,7 @@ Conflicting load by main at 0x........ size 8 at 0x........: main (sem_as_mutex.c:?) -Allocation context: s_d3 (offset 0, size 8) in sem_as_mutex, NONE:BSS +Allocation context: unknown Other segment start (thread_func) (thread finished, call stack no longer available) Other segment end (thread_func) @@ -9,7 +9,7 @@ Conflicting store by main at 0x........ size 8 at 0x........: main (sem_as_mutex.c:?) -Allocation context: s_d3 (offset 0, size 8) in sem_as_mutex, NONE:BSS +Allocation context: unknown Other segment start (thread_func) (thread finished, call stack no longer available) Other segment end (thread_func) Deleted: trunk/exp-drd/tests/sem_as_mutex.stderr.exp2 =================================================================== --- trunk/exp-drd/tests/sem_as_mutex.stderr.exp2 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/sem_as_mutex.stderr.exp2 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,18 +0,0 @@ - -Conflicting load by main at 0x........ size 8 - at 0x........: main (sem_as_mutex.c:?) -Allocation context: unknown -Other segment start (thread_func) - (thread finished, call stack no longer available) -Other segment end (thread_func) - (thread finished, call stack no longer available) - -Conflicting store by main at 0x........ size 8 - at 0x........: main (sem_as_mutex.c:?) -Allocation context: unknown -Other segment start (thread_func) - (thread finished, call stack no longer available) -Other segment end (thread_func) - (thread finished, call stack no longer available) - -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Deleted: trunk/exp-drd/tests/tc01_simple_race.stderr.exp2 =================================================================== --- trunk/exp-drd/tests/tc01_simple_race.stderr.exp2 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc01_simple_race.stderr.exp2 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,18 +0,0 @@ - -Conflicting load by thread 1 at 0x........ size 4 - at 0x........: main (tc01_simple_race.c:28) -Allocation context: unknown -Other segment start (thread 2) - (thread finished, call stack no longer available) -Other segment end (thread 2) - (thread finished, call stack no longer available) - -Conflicting store by thread 1 at 0x........ size 4 - at 0x........: main (tc01_simple_race.c:28) -Allocation context: unknown -Other segment start (thread 2) - (thread finished, call stack no longer available) -Other segment end (thread 2) - (thread finished, call stack no longer available) - -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Modified: trunk/exp-drd/tests/tc04_free_lock.stderr.exp =================================================================== --- trunk/exp-drd/tests/tc04_free_lock.stderr.exp 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc04_free_lock.stderr.exp 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,17 +1,17 @@ -Destroying locked mutex: address 0x........, recursion count 1, owner 1. +Destroying locked mutex: mutex 0x........, recursion count 1, owner 1. at 0x........: free (vg_replace_malloc.c:...) by 0x........: main (tc04_free_lock.c:24) -Destroying locked mutex: address 0x........, recursion count 1, owner 1. +Destroying locked mutex: mutex 0x........, recursion count 1, owner 1. at 0x........: bar (tc04_free_lock.c:40) by 0x........: main (tc04_free_lock.c:26) -Destroying locked mutex: address 0x........, recursion count 1, owner 1. +Destroying locked mutex: mutex 0x........, recursion count 1, owner 1. at 0x........: foo (tc04_free_lock.c:49) by 0x........: main (tc04_free_lock.c:27) -Destroying locked mutex: address 0x........, recursion count 1, owner 1. +Destroying locked mutex: mutex 0x........, recursion count 1, owner 1. at 0x........: bar (tc04_free_lock.c:40) by 0x........: main (tc04_free_lock.c:28) Deleted: trunk/exp-drd/tests/tc04_free_lock.stderr.exp2 =================================================================== --- trunk/exp-drd/tests/tc04_free_lock.stderr.exp2 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc04_free_lock.stderr.exp2 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,14 +0,0 @@ - -Destroying locked mutex: address 0x........, recursion count 1, owner 1. - at 0x........: bar (tc04_free_lock.c:40) - by 0x........: (below main) (in /...libc...) - -Destroying locked mutex: address 0x........, recursion count 1, owner 1. - at 0x........: foo (tc04_free_lock.c:49) - by 0x........: (below main) (in /...libc...) - -Destroying locked mutex: address 0x........, recursion count 1, owner 1. - at 0x........: bar (tc04_free_lock.c:40) - by 0x........: (below main) (in /...libc...) - -ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0) Deleted: trunk/exp-drd/tests/tc06_two_races.stderr.exp2 =================================================================== --- trunk/exp-drd/tests/tc06_two_races.stderr.exp2 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc06_two_races.stderr.exp2 2008-03-02 17:43:18 UTC (rev 7531) @@ -1 +0,0 @@ -ERROR SUMMARY: 4 errors from 4 contexts Deleted: trunk/exp-drd/tests/tc07_hbl1.stderr.exp2 =================================================================== --- trunk/exp-drd/tests/tc07_hbl1.stderr.exp2 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc07_hbl1.stderr.exp2 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,18 +0,0 @@ - -Conflicting load by thread 1 at 0x........ size 4 - at 0x........: main (tc07_hbl1.c:68) -Allocation context: unknown -Other segment start (thread 2) - (thread finished, call stack no longer available) -Other segment end (thread 2) - (thread finished, call stack no longer available) - -Conflicting store by thread 1 at 0x........ size 4 - at 0x........: main (tc07_hbl1.c:68) -Allocation context: unknown -Other segment start (thread 2) - (thread finished, call stack no longer available) -Other segment end (thread 2) - (thread finished, call stack no longer available) - -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Modified: trunk/exp-drd/tests/tc09_bad_unlock.stderr.exp =================================================================== --- trunk/exp-drd/tests/tc09_bad_unlock.stderr.exp 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc09_bad_unlock.stderr.exp 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,11 +1,11 @@ -Attempt to unlock a mutex that is not locked: address 0x........, recursion count -1, owner 1. +Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1. at 0x........: pthread_mutex_unlock (drd_intercepts.c:?) by 0x........: nearly_main (tc09_bad_unlock.c:27) by 0x........: main (tc09_bad_unlock.c:49) Thread 2: -Mutex not unlocked by owner thread: address 0x........, recursion count 1, owner 1. +Mutex not locked by calling thread: mutex 0x........, recursion count 1, owner 1. at 0x........: pthread_mutex_unlock (drd_intercepts.c:?) by 0x........: child_fn (tc09_bad_unlock.c:11) by 0x........: vg_thread_wrapper (drd_intercepts.c:?) @@ -13,18 +13,22 @@ by 0x........: clone (in /...libc...) Thread 1: -Invalid mutex +Not a mutex at 0x........: pthread_mutex_unlock (drd_intercepts.c:?) by 0x........: nearly_main (tc09_bad_unlock.c:41) by 0x........: main (tc09_bad_unlock.c:49) -Attempt to unlock a mutex that is not locked: address 0x........, recursion count -1, owner 1. +Destroying locked mutex: mutex 0x........, recursion count 1, owner 1. + at 0x........: nearly_main (tc09_bad_unlock.c:45) + by 0x........: main (tc09_bad_unlock.c:49) + +Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1. at 0x........: pthread_mutex_unlock (drd_intercepts.c:?) by 0x........: nearly_main (tc09_bad_unlock.c:27) by 0x........: main (tc09_bad_unlock.c:50) Thread 2: -Mutex not unlocked by owner thread: address 0x........, recursion count 1, owner 1. +Mutex not locked by calling thread: mutex 0x........, recursion count 1, owner 1. at 0x........: pthread_mutex_unlock (drd_intercepts.c:?) by 0x........: child_fn (tc09_bad_unlock.c:11) by 0x........: vg_thread_wrapper (drd_intercepts.c:?) @@ -32,9 +36,13 @@ by 0x........: clone (in /...libc...) Thread 1: -Invalid mutex +Not a mutex at 0x........: pthread_mutex_unlock (drd_intercepts.c:?) by 0x........: nearly_main (tc09_bad_unlock.c:41) by 0x........: main (tc09_bad_unlock.c:50) -ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0) +Destroying locked mutex: mutex 0x........, recursion count 1, owner 1. + at 0x........: nearly_main (tc09_bad_unlock.c:45) + by 0x........: main (tc09_bad_unlock.c:50) + +ERROR SUMMARY: 8 errors from 8 contexts (suppressed: 0 from 0) Modified: trunk/exp-drd/tests/tc10_rec_lock.stderr.exp =================================================================== --- trunk/exp-drd/tests/tc10_rec_lock.stderr.exp 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc10_rec_lock.stderr.exp 2008-03-02 17:43:18 UTC (rev 7531) @@ -6,7 +6,7 @@ before unlock #2 before unlock #3 before unlock #4 -Attempt to unlock a mutex that is not locked: address 0x........, recursion count -1, owner 1. +Mutex not locked by calling thread: mutex 0x........, recursion count 0, owner 1. at 0x........: pthread_mutex_unlock (drd_intercepts.c:?) by 0x........: nearly_main (tc10_rec_lock.c:42) by 0x........: main (tc10_rec_lock.c:47) Deleted: trunk/exp-drd/tests/tc11_XCHG.stderr.exp2 =================================================================== --- trunk/exp-drd/tests/tc11_XCHG.stderr.exp2 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc11_XCHG.stderr.exp2 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,18 +0,0 @@ - -Conflicting load by thread 1 at 0x........ size 4 - at 0x........: main (tc11_XCHG.c:78) -Allocation context: unknown -Other segment start (thread 2) - (thread finished, call stack no longer available) -Other segment end (thread 2) - (thread finished, call stack no longer available) - -Conflicting store by thread 1 at 0x........ size 4 - at 0x........: main (tc11_XCHG.c:78) -Allocation context: unknown -Other segment start (thread 2) - (thread finished, call stack no longer available) -Other segment end (thread 2) - (thread finished, call stack no longer available) - -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Modified: trunk/exp-drd/tests/tc12_rwl_trivial.stderr.exp =================================================================== --- trunk/exp-drd/tests/tc12_rwl_trivial.stderr.exp 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc12_rwl_trivial.stderr.exp 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,3 +1,6 @@ +Reader-writer lock not locked by calling thread: rwlock 0x......... + at 0x........: pthread_rwlock_unlock* (drd_intercepts.c:?) + by 0x........: main (tc12_rwl_trivial.c:29) -ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) +ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) Deleted: trunk/exp-drd/tests/tc16_byterace.stderr.exp2 =================================================================== --- trunk/exp-drd/tests/tc16_byterace.stderr.exp2 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc16_byterace.stderr.exp2 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,18 +0,0 @@ - -Conflicting load by thread 1 at 0x........ size 1 - at 0x........: main (tc16_byterace.c:34) -Allocation context: unknown -Other segment start (thread 2) - (thread finished, call stack no longer available) -Other segment end (thread 2) - (thread finished, call stack no longer available) - -Conflicting store by thread 1 at 0x........ size 1 - at 0x........: main (tc16_byterace.c:34) -Allocation context: unknown -Other segment start (thread 2) - (thread finished, call stack no longer available) -Other segment end (thread 2) - (thread finished, call stack no longer available) - -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) Modified: trunk/exp-drd/tests/tc18_semabuse.stderr.exp =================================================================== --- trunk/exp-drd/tests/tc18_semabuse.stderr.exp 2008-03-01 22:04:10 UTC (rev 7530) +++ trunk/exp-drd/tests/tc18_semabuse.stderr.exp 2008-03-02 17:43:18 UTC (rev 7531) @@ -1,5 +1,5 @@ -Invalid semaphore 0x........ +Invalid semaphore: ... [truncated message content] |