|
From: <sv...@va...> - 2008-01-14 11:55:03
|
Author: sewardj Date: 2008-01-14 11:54:56 +0000 (Mon, 14 Jan 2008) New Revision: 7346 Log: DRD updates (Bart Van Assche): - Updated copyright statement: replaced 2006-2007 by 2006-2008. - Added copyright statement in the files where it was missing (drd_track.h and drd_clientreq.c) - Eliminated dependencies on core header files -- there are no more #include "pub_core....h" directives in the exp-drd source code. - Added semaphore support. - Added barrier support. - Added pthread_mutex_timedlock() support. - Stack depth of stack traces printed by exp-drd can now be set via --num-callers=... - Added command-line option --trace-barrier=[yes|no]. - Added regression test for pthread_barrier() (matinv, a program that performs matrix inversion). - Added regression test sem_as_mutex, which tests whether race detection works correctly when a semaphore is used to ensure mutual exclusion of critical sections. - Some of helgrind's regression tests are now used to test both helgrind and exp-drd: tc17_sembar and tc18_semabuse. - Cleaned up bitmap implementation code now that the const keyword has been added to the declarations of the OSet functions. - Cleaned up exp-drd/Makefile.am - Updated exp-drd/TODO.txt Added: trunk/exp-drd/drd_barrier.c trunk/exp-drd/drd_barrier.h trunk/exp-drd/drd_semaphore.c trunk/exp-drd/drd_semaphore.h trunk/exp-drd/tests/matinv.c trunk/exp-drd/tests/matinv.stderr.exp trunk/exp-drd/tests/matinv.stdout.exp trunk/exp-drd/tests/matinv.vgtest trunk/exp-drd/tests/sem_as_mutex.c trunk/exp-drd/tests/sem_as_mutex.stderr.exp trunk/exp-drd/tests/sem_as_mutex.stderr.exp2 trunk/exp-drd/tests/sem_as_mutex.vgtest trunk/exp-drd/tests/sem_as_mutex2.stderr.exp trunk/exp-drd/tests/sem_as_mutex2.vgtest trunk/exp-drd/tests/tc17_sembar.stderr.exp trunk/exp-drd/tests/tc17_sembar.vgtest trunk/exp-drd/tests/tc18_semabuse.stderr.exp trunk/exp-drd/tests/tc18_semabuse.vgtest Modified: trunk/exp-drd/Makefile.am trunk/exp-drd/TODO.txt trunk/exp-drd/drd_bitmap.c trunk/exp-drd/drd_bitmap.h trunk/exp-drd/drd_clientreq.c trunk/exp-drd/drd_clientreq.h trunk/exp-drd/drd_cond.c trunk/exp-drd/drd_cond.h trunk/exp-drd/drd_error.c trunk/exp-drd/drd_error.h trunk/exp-drd/drd_intercepts.c trunk/exp-drd/drd_main.c trunk/exp-drd/drd_malloc_wrappers.c trunk/exp-drd/drd_malloc_wrappers.h trunk/exp-drd/drd_mutex.c trunk/exp-drd/drd_mutex.h trunk/exp-drd/drd_segment.c trunk/exp-drd/drd_segment.h trunk/exp-drd/drd_suppression.c trunk/exp-drd/drd_thread.c trunk/exp-drd/drd_thread.h trunk/exp-drd/drd_track.h trunk/exp-drd/drd_vc.c trunk/exp-drd/drd_vc.h trunk/exp-drd/priv_drd_clientreq.h trunk/exp-drd/pub_drd_bitmap.h trunk/exp-drd/tests/Makefile.am Modified: trunk/exp-drd/Makefile.am =================================================================== --- trunk/exp-drd/Makefile.am 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/Makefile.am 2008-01-14 11:54:56 UTC (rev 7346) @@ -67,6 +67,7 @@ DRD_SOURCES_COMMON = \ + drd_barrier.c \ drd_bitmap.c \ drd_clientreq.c \ drd_cond.c \ @@ -75,23 +76,27 @@ drd_malloc_wrappers.c \ drd_mutex.c \ drd_segment.c \ + drd_semaphore.c \ drd_suppression.c \ drd_thread.c \ drd_vc.c -noinst_HEADERS = drd_bitmap.h \ - drd_mutex.h \ - drd_vc.h \ - drd_clientreq.h \ - drd_segment.h \ - priv_drd_clientreq.h \ - drd_cond.h \ - drd_suppression.h \ - pub_drd_bitmap.h \ - drd_error.h \ - drd_thread.h \ - drd_malloc_wrappers.h \ - drd_track.h +noinst_HEADERS = \ + drd_barrier.h \ + drd_bitmap.h \ + drd_clientreq.h \ + drd_cond.h \ + drd_error.h \ + drd_malloc_wrappers.h \ + drd_mutex.h \ + drd_segment.h \ + drd_semaphore.h \ + drd_suppression.h \ + drd_thread.h \ + drd_track.h \ + drd_vc.h \ + priv_drd_clientreq.h \ + pub_drd_bitmap.h AM_CFLAGS_X86_LINUX += -I$(top_srcdir)/coregrind AM_CFLAGS_AMD64_LINUX += -I$(top_srcdir)/coregrind @@ -141,13 +146,3 @@ exp_drd_ppc64_aix5_DEPENDENCIES = $(COREGRIND_LIBS_PPC64_AIX5) exp_drd_ppc64_aix5_LDADD = $(TOOL_LDADD_PPC64_AIX5) exp_drd_ppc64_aix5_LDFLAGS = $(TOOL_LDFLAGS_PPC64_AIX5) - - -#all-local: -# for f in $(noinst_PROGRAMS); do \ -# p=`echo $$f | sed -e 's/^[^-]*-[^-]*-//' -e 's/\..*$$//'`; \ -# n=`echo $$f | sed -e 's/^\([^-]*-[^-]*\)-[^-]*-[^-]*/\1/'`; \ -# mkdir -p $(inplacedir)/$$p; \ -# rm -f $(inplacedir)/$$p/$$n; \ -# ln -f -s ../../$(subdir)/$$f $(inplacedir)/$$p/$$n; \ -# done Modified: trunk/exp-drd/TODO.txt =================================================================== --- trunk/exp-drd/TODO.txt 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/TODO.txt 2008-01-14 11:54:56 UTC (rev 7346) @@ -4,29 +4,22 @@ Data-race detection algorithm ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Rename drd_preloaded.c into drd_intercepts.c. -- Propose on the Valgrind developers mailing list to add scripts - "run-in-place" and "debug-in-place". +- pthread rwlock state tracking and support. +- Fix Fedora 7 / Fedora 8 pth_cond_race regression test failure. - Implement segment merging, such that the number of segments per thread remains limited even when there is no synchronization between threads. - Find out why a race is reported on std::string::string(std::string const&) (stc test case 16). -- Make sure that drd supports more than 256 mutexes. +- Eliminate the upper bounds on the number of mutexes, condition variables, + semaphores and barriers by converting arrays into OSet's. +- Add a regression test for pthread_mutex_timedlock(). - Performance testing and tuning. -- pthread semaphore support. -- pthread rwlock state tracking and support. -- pthread barrier state tracking and support. -- mutexes: support for pthread_mutex_timedlock() (recently added to the POSIX - spec, and present in glibc). See also - http://www.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_timedlock.html - testing on PPC and AIX (current implementation is only tested on X86 and AMD64). - Change s_threadinfo[] from an array into an OSet or VgHashTable, in order to make ThreadId <> DrdThreadId <> pthread_t conversions faster. -- [AMD64] Find out why removing 'write(1, "", 0)' in drd_preloaded.c triggers +- [AMD64] Find out why removing 'write(1, "", 0)' in drd_intercepts.c triggers a crash on AMD64. Is this a drd or a VEX bug ? -- Reintroduce the const keyword in the function declarations of the OSet - implementation in the core where appropriate. Testing ~~~~~~~ @@ -39,8 +32,8 @@ Documentation ~~~~~~~~~~~~~ -- Document the code. - Document how to use the tool. +- Document the code. Known bugs Added: trunk/exp-drd/drd_barrier.c =================================================================== --- trunk/exp-drd/drd_barrier.c (rev 0) +++ trunk/exp-drd/drd_barrier.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -0,0 +1,281 @@ +/* + 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_barrier.h" +#include "drd_error.h" +#include "drd_suppression.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_(printf)() +#include "pub_tool_machine.h" // VG_(get_IP)() +#include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)() +#include "pub_tool_oset.h" +#include "pub_tool_threadstate.h" // VG_(get_running_tid)() + + +// Type definitions. + +struct barrier_thread_info +{ + UWord tid; // A DrdThreadId + Word iteration; // barrier number corresponding to ongoing + // pthread_barrier() call modulo two. + VectorClock vc[2]; // vector clocks corresponding to the last two + // pthread_barrier() calls. +}; + +struct barrier_info +{ + Addr barrier; // Client address of barrier. + SizeT size; // Size in bytes of client-side object. + Word count; // Participant count in a barrier wait. + Word iteration; // barrier number corresponding to ongoing + // pthread_barrier() call modulo two. + Word participants; // Number of participants that still have to join + // the most recent barrier. + OSet* oset; // Information about specific threads. +}; + + +// Local variables. + +static Bool s_trace_barrier = False; +struct barrier_info s_barrier[4]; + + +// Function definitions. + +void barrier_set_trace(const Bool trace_barrier) +{ + s_trace_barrier = trace_barrier; +} + +static void barrier_thread_initialize(struct barrier_thread_info* const p, + const DrdThreadId tid, + const Word iteration) +{ + p->tid = tid; + p->iteration = iteration; + vc_init(&p->vc[0], 0, 0); + vc_init(&p->vc[1], 0, 0); +} + +static void barrier_thread_destroy(struct barrier_thread_info* const p) +{ + vc_cleanup(&p->vc[0]); + vc_cleanup(&p->vc[1]); +} + +static +void barrier_initialize(struct barrier_info* const p, + const Addr barrier, + const SizeT size, + const Word count) +{ + tl_assert(barrier != 0); + tl_assert(size > 0); + tl_assert(count > 0); + + p->barrier = barrier; + p->size = size; + p->count = count; + p->iteration = 0; + p->participants = count; + tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word)); + tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) + >= sizeof(DrdThreadId)); + p->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free)); +} + +void barrier_destroy(struct barrier_info* const p) +{ + struct barrier_thread_info* q; + + tl_assert(p); + + drd_finish_suppression(p->barrier, p->barrier + p->size); + + VG_(OSetGen_ResetIter)(p->oset); + for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; ) + { + barrier_thread_destroy(q); + } + VG_(OSetGen_Destroy)(p->oset); + p->barrier = 0; + p->size = 0; + p->count = 0; + p->iteration = 0; + p->participants = 0; +} + +static +struct barrier_info* +barrier_get_or_allocate(const Addr barrier, const SizeT size, const Word count) +{ + int i; + + for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++) + { + if (s_barrier[i].barrier == barrier) + { + tl_assert(s_barrier[i].size == size); + return &s_barrier[i]; + } + } + for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++) + { + if (s_barrier[i].barrier == 0) + { + barrier_initialize(&s_barrier[i], barrier, size, count); + drd_start_suppression(barrier, barrier + size, "barrier"); + return &s_barrier[i]; + } + } + tl_assert(0); + return 0; +} + +struct barrier_info* +barrier_init(const Addr barrier, const SizeT size, const Word count) +{ + tl_assert(barrier_get(barrier) == 0); + return barrier_get_or_allocate(barrier, size, count); +} + +struct barrier_info* barrier_get(const Addr barrier) +{ + int i; + for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++) + if (s_barrier[i].barrier == barrier) + return &s_barrier[i]; + return 0; +} + +void barrier_pre_wait(const DrdThreadId tid, const Addr barrier) +{ + struct barrier_info* p; + struct barrier_thread_info* q; + const UWord word_tid = tid; + + p = barrier_get(barrier); + tl_assert(p); + + if (s_trace_barrier) + { + VG_(message)(Vg_DebugMsg, + "[%d] barrier_pre_wait(%p) iteration %d / left %d/%d", + tid, barrier, p->iteration, p->participants, p->count); + } + + if (--p->participants <= 0) + { + p->iteration = ! p->iteration; + p->participants = p->count; + } + q = VG_(OSetGen_Lookup)(p->oset, &word_tid); + if (q == 0) + { + q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q)); + barrier_thread_initialize(q, tid, p->iteration); + tl_assert(q->tid == tid); + VG_(OSetGen_Insert)(p->oset, q); + tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q); + } + tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q); + vc_copy(&q->vc[p->iteration], &thread_get_segment(tid)->vc); +} + +void barrier_post_wait(const DrdThreadId tid, const Addr barrier, + const Bool waited) +{ + struct barrier_info* const p = barrier_get(barrier); + + if (s_trace_barrier) + { + VG_(message)(Vg_DebugMsg, "[%d] barrier_post_wait(%p) iteration %d", + tid, barrier, p ? 1 - p->iteration : -1); + } + + if (waited) + { + const UWord word_tid = tid; + struct barrier_thread_info* q; + struct barrier_thread_info* r; + + tl_assert(p); + q = VG_(OSetGen_Lookup)(p->oset, &word_tid); + tl_assert(q); + VG_(OSetGen_ResetIter)(p->oset); + for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; ) + { + if (r != q) + { + if (s_trace_barrier) + { + VG_(message)(Vg_DebugMsg, + "[%d] barrier_post_wait: combining vc of thread %d", + tid, r->tid); + } + thread_combine_vc2(tid, &r->vc[1 - q->iteration]); + } + } + } +} + +/** + * Call this function when thread threadid stops to exist, such that the + * "last owner" field can be cleared if it still refers to that thread. + */ +void barrier_thread_delete(const DrdThreadId tid) +{ + int i; + struct barrier_thread_info* q; + + for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++) + { + struct barrier_info* const p = &s_barrier[i]; + if (p->barrier) + { + VG_(OSetGen_ResetIter)(p->oset); + for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; ) + { + } + } + } +} + +void barrier_stop_using_mem(const Addr a1, const Addr a2) +{ + unsigned i; + for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++) + { + if (a1 <= s_barrier[i].barrier && s_barrier[i].barrier < a2) + { + tl_assert(s_barrier[i].barrier + s_barrier[i].size <= a2); + barrier_destroy(&s_barrier[i]); + } + } +} Added: trunk/exp-drd/drd_barrier.h =================================================================== --- trunk/exp-drd/drd_barrier.h (rev 0) +++ trunk/exp-drd/drd_barrier.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -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. +*/ + + +// Barrier state information. + + +#ifndef __BARRIER_H +#define __BARRIER_H + + +#include "drd_thread.h" // DrdThreadId +#include "drd_vc.h" +#include "pub_tool_basics.h" // Addr, SizeT + + +struct barrier_info; + + +void barrier_set_trace(const Bool trace_barrier); +struct barrier_info* barrier_init(const Addr barrier, const SizeT size, + const Word count); +void barrier_destroy(struct barrier_info* const p); +struct barrier_info* barrier_get(const Addr barrier); +void barrier_pre_wait(const DrdThreadId tid, const Addr barrier); +void barrier_post_wait(const DrdThreadId tid, const Addr barrier, + const Bool waited); +void barrier_thread_delete(const DrdThreadId threadid); +void barrier_stop_using_mem(const Addr a1, const Addr a2); + + +#endif /* __BARRIER_H */ Modified: trunk/exp-drd/drd_bitmap.c =================================================================== --- trunk/exp-drd/drd_bitmap.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_bitmap.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or Modified: trunk/exp-drd/drd_bitmap.h =================================================================== --- trunk/exp-drd/drd_bitmap.h 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_bitmap.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or @@ -75,13 +75,6 @@ #define UWORD_HIGHEST_ADDRESS(a) ((a) | (BITS_PER_UWORD - 1)) -// Local functions. - -// Similar to const_cast<> in C++. -static __inline__ OSet* const_to_non_const_oset(const OSet* os) -{ return (OSet*)os; } - - // Local constants. static ULong s_bitmap2_creation_count; @@ -134,7 +127,7 @@ struct bitmap2* bm_lookup(const struct bitmap* const bm, const Addr a) { const UWord a1 = a >> ADDR0_BITS; - return VG_(OSetGen_Lookup)(const_to_non_const_oset(bm->oset), (void*)&a1); + return VG_(OSetGen_Lookup)(bm->oset, &a1); } static __inline__ @@ -155,7 +148,7 @@ struct bitmap2* bm2_lookup_or_insert(const struct bitmap* const bm, const UWord a1) { - struct bitmap2* p2 = VG_(OSetGen_Lookup)(const_to_non_const_oset(bm->oset), (void*)&a1); + struct bitmap2* p2 = VG_(OSetGen_Lookup)(bm->oset, &a1); if (p2 == 0) { p2 = bm2_insert(bm, a1); Modified: trunk/exp-drd/drd_clientreq.c =================================================================== --- trunk/exp-drd/drd_clientreq.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_clientreq.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,11 +1,36 @@ +/* + 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_clientreq.h" #include "drd_cond.h" #include "drd_mutex.h" +#include "drd_semaphore.h" #include "drd_suppression.h" // drd_start_suppression() #include "drd_thread.h" #include "drd_track.h" #include "priv_drd_clientreq.h" -#include "pub_core_tooliface.h" // VG_TRACK() #include "pub_tool_basics.h" // Bool #include "pub_tool_libcassert.h" #include "pub_tool_libcassert.h" // tl_assert() @@ -155,6 +180,42 @@ drd_pre_cond_broadcast(arg[1]); break; + case VG_USERREQ__SEM_INIT: + drd_semaphore_init(arg[1], arg[2], arg[3], arg[4]); + break; + + case VG_USERREQ__SEM_DESTROY: + drd_semaphore_destroy(arg[1]); + break; + + case VG_USERREQ__POST_SEM_WAIT: + drd_semaphore_post_wait(thread_get_running_tid(), arg[1], arg[2]); + break; + + case VG_USERREQ__PRE_SEM_POST: + drd_semaphore_pre_post(thread_get_running_tid(), arg[1], arg[2]); + break; + + case VG_USERREQ__POST_SEM_POST: + drd_semaphore_post_post(thread_get_running_tid(), arg[1], arg[2]); + break; + + case VG_USERREQ__BARRIER_INIT: + drd_barrier_init(arg[1], arg[2], arg[3]); + break; + + case VG_USERREQ__BARRIER_DESTROY: + drd_barrier_destroy(arg[1]); + break; + + case VG_USERREQ__PRE_BARRIER_WAIT: + drd_barrier_pre_wait(thread_get_running_tid(), arg[1]); + break; + + case VG_USERREQ__POST_BARRIER_WAIT: + drd_barrier_post_wait(thread_get_running_tid(), arg[1], arg[2]); + break; + default: VG_(message)(Vg_DebugMsg, "Unrecognized client request 0x%lx 0x%lx", arg[0], arg[1]); Modified: trunk/exp-drd/drd_clientreq.h =================================================================== --- trunk/exp-drd/drd_clientreq.h 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_clientreq.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -52,29 +52,29 @@ VG_USERREQ__POST_THREAD_JOIN, /* args: pthread_t (joinee) */ - /* To notify the core of a pthread_mutex_init call */ + /* to notify the drd tool of a pthread_mutex_init call. */ VG_USERREQ__PRE_MUTEX_INIT, /* args: Addr, MutexT */ - /* To notify the core of a pthread_mutex_destroy call */ + /* to notify the drd tool of a pthread_mutex_destroy call. */ VG_USERREQ__POST_MUTEX_DESTROY, /* args: Addr, SizeT, MutexT */ - /* To notify the core of pthread_mutex_lock calls */ + /* to notify the drd tool of pthread_mutex_lock calls */ VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK, /* args: Addr, SizeT, MutexT */ - /* To notify the core of pthread_mutex_lock calls */ + /* to notify the drd tool of pthread_mutex_lock calls */ VG_USERREQ__POST_PTHREAD_MUTEX_LOCK, /* args: Addr, SizeT, MutexT */ - /* To notify the core of pthread_mutex_unlock calls */ + /* to notify the drd tool of pthread_mutex_unlock calls */ VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK, /* args: Addr */ VG_USERREQ__SPIN_INIT_OR_UNLOCK, /* args: Addr spinlock, SizeT size */ - /* To notify the core of a pthread_cond_init call */ + /* to notify the drd tool of a pthread_cond_init call. */ VG_USERREQ__POST_PTHREAD_COND_INIT, /* args: Addr */ - /* To notify the core of a pthread_cond_destroy call */ + /* to notify the drd tool of a pthread_cond_destroy call. */ VG_USERREQ__PRE_PTHREAD_COND_DESTROY, /* args: Addr cond, SizeT cond_size, Addr mutex, SizeT mutex_size */ VG_USERREQ__PRE_PTHREAD_COND_WAIT, @@ -86,6 +86,35 @@ VG_USERREQ__PRE_PTHREAD_COND_BROADCAST, /* args: Addr cond */ + /* To notify the drd tool of a sem_init call. */ + VG_USERREQ__SEM_INIT, + /* args: Addr sem, SizeT sem_size, Word pshared, Word value */ + /* To notify the drd tool of a sem_destroy call. */ + VG_USERREQ__SEM_DESTROY, + /* args: Addr sem */ + /* To notify the drd tool of a sem_wait call. */ + VG_USERREQ__POST_SEM_WAIT, + /* args: Addr sem, SizeT sem_size */ + /* To notify the drd tool before a sem_post call. */ + VG_USERREQ__PRE_SEM_POST, + /* args: Addr sem, SizeT sem_size */ + /* To notify the drd tool after a sem_post call. */ + VG_USERREQ__POST_SEM_POST, + /* args: Addr sem, SizeT sem_size */ + + /* To notify the drd tool of a pthread_barrier_init call. */ + VG_USERREQ__BARRIER_INIT, + /* args: Addr barrier, SizeT barrier_size, Word count */ + /* To notify the drd tool of a pthread_barrier_destroy call. */ + VG_USERREQ__BARRIER_DESTROY, + /* args: Addr barrier */ + /* To notify the drd tool of a pthread_barrier_wait call. */ + VG_USERREQ__PRE_BARRIER_WAIT, + /* args: Addr barrier */ + /* To notify the drd tool of a pthread_barrier_wait call. */ + VG_USERREQ__POST_BARRIER_WAIT, + /* args: Addr barrier, Word has_waited */ + }; typedef enum Modified: trunk/exp-drd/drd_cond.c =================================================================== --- trunk/exp-drd/drd_cond.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_cond.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or @@ -31,8 +31,8 @@ #include "pub_tool_libcassert.h" // tl_assert() #include "pub_tool_libcprint.h" // VG_(printf)() #include "pub_tool_machine.h" // VG_(get_IP)() +#include "pub_tool_options.h" // VG_(clo_backtrace_size) #include "pub_tool_threadstate.h" // VG_(get_running_tid)() -#include "pub_core_options.h" // VG_(clo_backtrace_size) static struct cond_info s_cond[256]; @@ -195,6 +195,9 @@ cond_pre_signal(cond); } +void cond_thread_delete(const DrdThreadId tid) +{ } + void cond_stop_using_mem(const Addr a1, const Addr a2) { unsigned i; Modified: trunk/exp-drd/drd_cond.h =================================================================== --- trunk/exp-drd/drd_cond.h 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_cond.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or @@ -48,11 +48,12 @@ void cond_set_trace(const Bool trace_cond); void cond_init(const Addr cond, const SizeT size); void cond_destroy(struct cond_info* const p); -struct cond_info* cond_get(Addr const mutex); +struct cond_info* cond_get(const Addr mutex); int cond_pre_wait(const Addr cond, const SizeT cond_size, const Addr mutex); int cond_post_wait(const Addr cond); -void cond_pre_signal(Addr const cond); -void cond_pre_broadcast(Addr const cond); +void cond_pre_signal(const Addr cond); +void cond_pre_broadcast(const Addr cond); +void cond_thread_delete(const DrdThreadId tid); void cond_stop_using_mem(const Addr a1, const Addr a2); Modified: trunk/exp-drd/drd_error.c =================================================================== --- trunk/exp-drd/drd_error.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_error.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or Modified: trunk/exp-drd/drd_error.h =================================================================== --- trunk/exp-drd/drd_error.h 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_error.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or Modified: trunk/exp-drd/drd_intercepts.c =================================================================== --- trunk/exp-drd/drd_intercepts.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_intercepts.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,12 +1,12 @@ /*--------------------------------------------------------------------*/ -/*--- Client-space code for drd. drd_preloaded.c ---*/ +/*--- Client-space code for drd. drd_intercepts.c ---*/ /*--------------------------------------------------------------------*/ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or @@ -47,15 +47,12 @@ #include <assert.h> #include <inttypes.h> // uintptr_t +#include <pthread.h> +#include <semaphore.h> #include <stdio.h> #include <unistd.h> -#include <pthread.h> #include "drd_clientreq.h" -#include "pub_core_basics.h" -#include "pub_core_clreq.h" -#include "pub_core_debuginfo.h" // Needed for pub_core_redir.h -#include "pub_core_redir.h" // For VG_NOTIFY_ON_LOAD -#include "pub_tool_threadstate.h"// VG_N_THREADS +#include "pub_tool_redir.h" // Defines. @@ -122,9 +119,6 @@ { int res; assert(joinable == 0 || joinable == 1); -#if 0 - printf("vg_set_joinable(%ld, %d)\n", tid, joinable); -#endif VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE, tid, joinable, 0, 0, 0); } @@ -217,7 +211,7 @@ #else // Yes, you see it correctly, busy waiting ... The problem is that // POSIX threads functions cannot be called here -- the functions defined - // in this file (vg_preloaded.c) would be called instead of those in + // in this file (drd_intercepts.c) would be called instead of those in // libpthread.so. This loop is necessary because vgargs is allocated on the // stack, and the created thread reads it. if (ret == 0) @@ -334,6 +328,24 @@ return ret; } +// pthread_mutex_timedlock +PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock + pthread_mutex_t *mutex, + const struct timespec *abs_timeout) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_WW(ret, fn, mutex, abs_timeout); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK, + mutex, sizeof(*mutex), mutex_type_mutex, 0, 0); + } + return ret; +} + // pthread_mutex_unlock PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock pthread_mutex_t *mutex) @@ -523,7 +535,272 @@ return ret; } +// pthread_barrier_init +PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init + pthread_barrier_t* barrier, + const pthread_barrierattr_t* attr, + unsigned count) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_INIT, + barrier, sizeof(*barrier), + count, 0, 0); + CALL_FN_W_WWW(ret, fn, barrier, attr, count); + return ret; +} + +// pthread_barrier_destroy +PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy + pthread_barrier_t* barrier) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_W(ret, fn, barrier); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_DESTROY, + barrier, 0, 0, 0, 0); + return ret; +} + +// pthread_barrier_wait +PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait + pthread_barrier_t* barrier) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT, + barrier, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, barrier); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT, + barrier, + ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD, + 0, 0, 0); + return ret; +} + + +// From glibc 2.0 linuxthreads/sysdeps/pthread/cmpxchg/semaphorebits.h +typedef struct { long int sem_status; } sem_t_glibc_2_0; + +// sem_init +PTH_FUNC(int, sem_initZAGLIBCZu2Zd0, // sem_init@GLIBC_2.0 + sem_t_glibc_2_0 *sem, + int pshared, + unsigned int value) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_WWW(ret, fn, sem, pshared, value); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT, + sem, sizeof(*sem), + pshared, value, 0); + } + return ret; +} + +PTH_FUNC(int, sem_initZa, // sem_init* + sem_t *sem, + int pshared, + unsigned int value) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_WWW(ret, fn, sem, pshared, value); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT, + sem, sizeof(*sem), + pshared, value, 0); + } + return ret; +} + +// sem_destroy +PTH_FUNC(int, sem_destroyZAGLIBCZu2Zd0, // sem_destroy@GLIBC_2.0 + sem_t_glibc_2_0 *sem) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_W(ret, fn, sem); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY, + sem, 0, 0, 0, 0); + } + return ret; +} + +PTH_FUNC(int, sem_destroyZa, // sem_destroy* + sem_t *sem) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_W(ret, fn, sem); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY, + sem, 0, 0, 0, 0); + } + return ret; +} + +// sem_wait +PTH_FUNC(int, sem_waitZAGLIBCZu2Zd0, // sem_wait@GLIBC_2.0 + sem_t_glibc_2_0 *sem) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_W(ret, fn, sem); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, + sem, sizeof(*sem), 0, 0, 0); + } + return ret; +} + +PTH_FUNC(int, sem_waitZa, // sem_wait* + sem_t *sem) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_W(ret, fn, sem); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, + sem, sizeof(*sem), 0, 0, 0); + } + return ret; +} + +// sem_trywait +PTH_FUNC(int, sem_trywaitZAGLIBCZu2Zd0, // sem_trywait@GLIBC_2.0 + sem_t_glibc_2_0 *sem) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_W(ret, fn, sem); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, + sem, sizeof(*sem), 0, 0, 0); + } + return ret; +} + +PTH_FUNC(int, sem_trywaitZa, // sem_trywait* + sem_t *sem) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_W(ret, fn, sem); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, + sem, sizeof(*sem), 0, 0, 0); + } + return ret; +} + +// sem_timedwait +PTH_FUNC(int, sem_timedwait, // sem_timedwait + sem_t *sem, const struct timespec *abs_timeout) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_WW(ret, fn, sem, abs_timeout); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, + sem, sizeof(*sem), 0, 0, 0); + } + return ret; +} + +// sem_post +PTH_FUNC(int, sem_postZAGLIBCZu2Zd0, // sem_post@GLIBC_2.0 + sem_t_glibc_2_0 *sem) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST, + sem, sizeof(*sem), 0, 0, 0); + CALL_FN_W_W(ret, fn, sem); + assert(ret == 0); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST, + sem, sizeof(*sem), 0, 0, 0); + } + return ret; +} + +PTH_FUNC(int, sem_postZa, // sem_post* + sem_t *sem) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST, + sem, sizeof(*sem), 0, 0, 0); + CALL_FN_W_W(ret, fn, sem); + assert(ret == 0); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST, + sem, sizeof(*sem), 0, 0, 0); + } + return ret; +} + /* +pthread_rwlock_destroy +pthread_rwlock_init +pthread_rwlock_rdlock +pthread_rwlock_timedrdlock +pthread_rwlock_timedwrlock +pthread_rwlock_tryrdlock +pthread_rwlock_trywrlock +pthread_rwlock_unlock +pthread_rwlock_wrlock +pthread_rwlockattr_destroy +pthread_rwlockattr_getkind_np +pthread_rwlockattr_getpshared +pthread_rwlockattr_init +pthread_rwlockattr_setkind_np +pthread_rwlockattr_setpshared + */ + +/* * Local variables: * c-basic-offset: 3 * End: Modified: trunk/exp-drd/drd_main.c =================================================================== --- trunk/exp-drd/drd_main.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_main.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or @@ -23,24 +23,26 @@ */ -#include "pub_drd_bitmap.h" +#include "drd_barrier.h" #include "drd_clientreq.h" #include "drd_cond.h" #include "drd_error.h" #include "drd_malloc_wrappers.h" #include "drd_mutex.h" #include "drd_segment.h" +#include "drd_semaphore.h" #include "drd_suppression.h" #include "drd_thread.h" #include "drd_track.h" #include "drd_vc.h" #include "priv_drd_clientreq.h" -#include "pub_tool_vki.h" +#include "pub_drd_bitmap.h" #include "pub_tool_basics.h" #include "pub_tool_debuginfo.h" // VG_(describe_IP)() #include "pub_tool_libcassert.h" // tl_assert() #include "pub_tool_libcbase.h" // VG_(strcmp) #include "pub_tool_libcprint.h" // VG_(printf) +#include "pub_tool_vki.h" // Must be included before pub_tool_libcproc #include "pub_tool_libcproc.h" #include "pub_tool_machine.h" #include "pub_tool_options.h" // command line options @@ -48,17 +50,6 @@ #include "pub_tool_tooliface.h" -// Type definitions. - -#if 0 -typedef struct -{ - const Char* const soname; - const Char* const symbol; -} SuppressedSymbol; -#endif - - // Function declarations. static void drd_start_client_code(const ThreadId tid, const ULong bbs_done); @@ -69,8 +60,8 @@ // Local variables. static Bool drd_print_stats = False; +static Bool drd_trace_fork_join = False; static Bool drd_trace_mem = False; -static Bool drd_trace_fork_join = False; static Addr drd_trace_address = 0; @@ -80,6 +71,7 @@ static Bool drd_process_cmd_line_option(Char* arg) { + Bool trace_barrier = False; Bool trace_cond = False; Bool trace_mutex = False; Bool trace_segment = False; @@ -87,6 +79,7 @@ Char* trace_address = 0; VG_BOOL_CLO (arg, "--drd-stats", drd_print_stats) + else VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier) else VG_BOOL_CLO(arg, "--trace-cond", trace_cond) else VG_BOOL_CLO(arg, "--trace-fork-join", drd_trace_fork_join) else VG_BOOL_CLO(arg, "--trace-mem", drd_trace_mem) @@ -99,6 +92,8 @@ if (trace_address) drd_trace_address = VG_(strtoll16)(trace_address, 0); + if (trace_barrier) + barrier_set_trace(trace_barrier); if (trace_cond) cond_set_trace(trace_cond); if (trace_mutex) @@ -150,7 +145,8 @@ thread_get_name(thread_get_running_tid()), VG_(get_running_tid)(), thread_get_running_tid()); - VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); + VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), + VG_(clo_backtrace_size)); tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid()) == VG_(get_running_tid)()); } @@ -192,7 +188,8 @@ VG_(get_running_tid)(), thread_get_running_tid(), addr - thread_get_stack_min(thread_get_running_tid())); - VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); + VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), + VG_(clo_backtrace_size)); tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid()) == VG_(get_running_tid)()); } @@ -247,7 +244,8 @@ VG_(message)(Vg_UserMsg, "start 0x%lx size %ld %s (tracing 0x%lx)", a1, a2 - a1, thread_get_name(thread_get_running_tid()), drd_trace_address); - VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); + VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), + VG_(clo_backtrace_size)); } } @@ -259,11 +257,14 @@ VG_(message)(Vg_UserMsg, "end 0x%lx size %ld %s (tracing 0x%lx)", a1, a2 - a1, thread_get_name(thread_get_running_tid()), drd_trace_address); - VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); + VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), + VG_(clo_backtrace_size)); } thread_stop_using_mem(a1, a2); mutex_stop_using_mem(a1, a2); cond_stop_using_mem(a1, a2); + semaphore_stop_using_mem(a1, a2); + barrier_stop_using_mem(a1, a2); drd_suppression_stop_using_mem(a1, a2); } @@ -373,12 +374,19 @@ thread_delete(drd_joinee); mutex_thread_delete(drd_joinee); + cond_thread_delete(drd_joinee); + semaphore_thread_delete(drd_joinee); + barrier_thread_delete(drd_joinee); } /* Called after a thread has performed its last memory access. */ static void drd_thread_finished(ThreadId tid) { - const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(tid); + DrdThreadId drd_tid; + + drd_set_running_tid(tid); + + drd_tid = VgThreadIdToDrdThreadId(tid); if (drd_trace_fork_join) { VG_(message)(Vg_DebugMsg, @@ -403,6 +411,7 @@ struct mutex_info* p; p = mutex_get(mutex); + tl_assert(p); if (p) { // TO DO: report an error in case the recursion count is not zero @@ -472,7 +481,71 @@ } } +void drd_semaphore_init(const Addr semaphore, const SizeT size, + const Word pshared, const Word value) +{ + semaphore_init(semaphore, size, pshared, value); +} +void drd_semaphore_destroy(const Addr semaphore) +{ + struct semaphore_info* p; + + p = semaphore_get(semaphore); + tl_assert(p); + if (p) + { + semaphore_destroy(p); + } +} + +void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore, + const SizeT size) +{ + semaphore_post_wait(tid, semaphore, size); +} + +void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore, + const SizeT size) +{ + semaphore_pre_post(tid, semaphore, size); +} + +void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore, + const SizeT size) +{ + semaphore_post_post(tid, semaphore, size); +} + + +void drd_barrier_init(const Addr barrier, const SizeT size, const Word count) +{ + barrier_init(barrier, size, count); +} + +void drd_barrier_destroy(const Addr barrier) +{ + struct barrier_info* p; + + p = barrier_get(barrier); + if (p) + { + barrier_destroy(p); + } +} + +void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier) +{ + barrier_pre_wait(tid, barrier); +} + +void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier, + const Bool waited) +{ + barrier_post_wait(tid, barrier, waited); +} + + // // Implementation of the tool interface. // @@ -686,7 +759,7 @@ VG_(details_name) ("exp-drd"); VG_(details_version) (NULL); VG_(details_description) ("a data race detector"); - VG_(details_copyright_author)("Copyright (C) 2006-2007, and GNU GPL'd," + VG_(details_copyright_author)("Copyright (C) 2006-2008, and GNU GPL'd," " by Bart Van Assche."); VG_(details_bug_reports_to) (VG_BUGS_TO); Modified: trunk/exp-drd/drd_malloc_wrappers.c =================================================================== --- trunk/exp-drd/drd_malloc_wrappers.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_malloc_wrappers.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or Modified: trunk/exp-drd/drd_malloc_wrappers.h =================================================================== --- trunk/exp-drd/drd_malloc_wrappers.h 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_malloc_wrappers.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or Modified: trunk/exp-drd/drd_mutex.c =================================================================== --- trunk/exp-drd/drd_mutex.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_mutex.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or Modified: trunk/exp-drd/drd_mutex.h =================================================================== --- trunk/exp-drd/drd_mutex.h 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_mutex.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or Modified: trunk/exp-drd/drd_segment.c =================================================================== --- trunk/exp-drd/drd_segment.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_segment.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or Modified: trunk/exp-drd/drd_segment.h =================================================================== --- trunk/exp-drd/drd_segment.h 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_segment.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or Added: trunk/exp-drd/drd_semaphore.c =================================================================== --- trunk/exp-drd/drd_semaphore.c (rev 0) +++ trunk/exp-drd/drd_semaphore.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -0,0 +1,187 @@ +/* + 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_error.h" +#include "drd_semaphore.h" +#include "drd_suppression.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_(printf)() +#include "pub_tool_machine.h" // VG_(get_IP)() +#include "pub_tool_threadstate.h" // VG_(get_running_tid)() + + +// Type definitions. + +struct semaphore_info +{ + Addr semaphore; // Pointer to client semaphore. + SizeT size; // Size in bytes of client-side object. + UWord value; // Semaphore value. + DrdThreadId last_sem_post_tid; // Thread ID associated with last sem_post(). + VectorClock vc; // Vector clock of last sem_post() call. +}; + + +// Local variables. + +static Bool s_trace_semaphore; +struct semaphore_info s_semaphore[256]; + + +// Function definitions. + +void semaphore_set_trace(const Bool trace_semaphore) +{ + s_trace_semaphore = trace_semaphore; +} + +static +void semaphore_initialize(struct semaphore_info* const p, + const Addr semaphore, + const SizeT size, + const UWord value) +{ + tl_assert(semaphore != 0); + tl_assert(size > 0); + + p->semaphore = semaphore; + p->size = size; + p->value = value; + p->last_sem_post_tid = DRD_INVALID_THREADID; + vc_init(&p->vc, 0, 0); +} + +static +struct semaphore_info* +semaphore_get_or_allocate(const Addr semaphore, const SizeT size) +{ + int i; + + for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++) + { + if (s_semaphore[i].semaphore == semaphore) + { + tl_assert(s_semaphore[i].size == size); + return &s_semaphore[i]; + } + } + for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++) + { + if (s_semaphore[i].semaphore == 0) + { + semaphore_initialize(&s_semaphore[i], semaphore, size, 0); + drd_start_suppression(semaphore, semaphore + size, "semaphore"); + return &s_semaphore[i]; + } + } + tl_assert(0); + return 0; +} + +struct semaphore_info* semaphore_init(const Addr semaphore, const SizeT size, + const Word pshared, const UWord value) +{ + struct semaphore_info* p; + + tl_assert(semaphore_get(semaphore) == 0); + p = semaphore_get_or_allocate(semaphore, size); + p->value = value; + return p; +} + +void semaphore_destroy(struct semaphore_info* const p) +{ + drd_finish_suppression(p->semaphore, p->semaphore + p->size); + + vc_cleanup(&p->vc); + p->semaphore = 0; +} + +struct semaphore_info* semaphore_get(const Addr semaphore) +{ + int i; + for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++) + if (s_semaphore[i].semaphore == semaphore) + return &s_semaphore[i]; + return 0; +} + +/** Called after sem_wait() finished successfully. */ +void semaphore_post_wait(const DrdThreadId tid, const Addr semaphore, + const SizeT size) +{ + struct semaphore_info* p; + + p = semaphore_get_or_allocate(semaphore, size); + tl_assert(p->value >= 0); + p->value--; + tl_assert(p->value >= 0); + if (p->last_sem_post_tid != tid) + thread_combine_vc2(tid, &p->vc); + thread_new_segment(tid); +} + +/** Called before sem_post(). */ +void semaphore_pre_post(const DrdThreadId tid, const Addr semaphore, + const SizeT size) +{ + struct semaphore_info* p; + + p = semaphore_get_or_allocate(semaphore, size); + p->value++; + if (p->value == 1) + { + p->last_sem_post_tid = tid; + } +} + +/** Called after sem_post() finished successfully. */ +void semaphore_post_post(const DrdThreadId tid, const Addr semaphore, + const SizeT size) +{ + struct semaphore_info* p; + + p = semaphore_get_or_allocate(semaphore, size); + thread_new_segment(tid); + vc_copy(&p->vc, thread_get_vc(tid)); +} + +void semaphore_thread_delete(const DrdThreadId threadid) +{ } + +void semaphore_stop_using_mem(const Addr a1, const Addr a2) +{ + unsigned i; + for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++) + { + if (a1 <= s_semaphore[i].semaphore && s_semaphore[i].semaphore < a2) + { + tl_assert(s_semaphore[i].semaphore + s_semaphore[i].size <= a2); + semaphore_destroy(&s_semaphore[i]); + } + } +} Added: trunk/exp-drd/drd_semaphore.h =================================================================== --- trunk/exp-drd/drd_semaphore.h (rev 0) +++ trunk/exp-drd/drd_semaphore.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -0,0 +1,56 @@ +/* + 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. +*/ + + +// Semaphore state information: owner thread and recursion count. + + +#ifndef __SEMAPHORE_H +#define __SEMAPHORE_H + + +#include "drd_thread.h" // DrdThreadId +#include "drd_vc.h" +#include "pub_tool_basics.h" // Addr, SizeT + + +struct semaphore_info; + + +void semaphore_set_trace(const Bool trace_semaphore); +struct semaphore_info* semaphore_init(const Addr semaphore, const SizeT size, + const Word pshared, const UWord value); +void semaphore_destroy(struct semaphore_info* const p); +struct semaphore_info* semaphore_get(const Addr semaphore); +void semaphore_post_wait(const DrdThreadId tid, const Addr semaphore, + const SizeT size); +void semaphore_pre_post(const DrdThreadId tid, const Addr semaphore, + const SizeT size); +void semaphore_post_post(const DrdThreadId tid, const Addr semaphore, + const SizeT size); +void semaphore_thread_delete(const DrdThreadId tid); +void semaphore_stop_using_mem(const Addr a1, const Addr a2); + + +#endif /* __SEMAPHORE_H */ Modified: trunk/exp-drd/drd_suppression.c =================================================================== --- trunk/exp-drd/drd_suppression.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_suppression.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or @@ -24,12 +24,11 @@ #include "drd_suppression.h" -#include "pub_core_libcassert.h" -#include "pub_core_libcprint.h" -#include "pub_core_options.h" // VG_(clo_backtrace_size) #include "pub_drd_bitmap.h" +#include "pub_tool_libcassert.h" // tl_assert() #include "pub_tool_stacktrace.h" // VG_(get_and_pp_StackTrace)() #include "pub_tool_threadstate.h" // VG_(get_running_tid)() +#include "pub_tool_libcprint.h" // Vg_DebugMsg // Local variables. @@ -72,16 +71,14 @@ { VG_(message)(Vg_DebugMsg, "finish suppression of 0x%lx sz %ld", a1, a2 - a1); - VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), - VG_(clo_backtrace_size)); + VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); } tl_assert(a1 < a2); if (! drd_is_suppressed(a1, a2)) { VG_(message)(Vg_DebugMsg, "?? not suppressed ??"); - VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), - VG_(clo_backtrace_size)); + VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); tl_assert(False); } bm_clear(s_suppressed, a1, a2); @@ -119,7 +116,6 @@ VG_(message)(Vg_DebugMsg, "stop_using_mem(0x%lx, %ld) finish suppression of 0x%lx", a1, a2 - a1, b); - //VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size)); } } } Modified: trunk/exp-drd/drd_thread.c =================================================================== --- trunk/exp-drd/drd_thread.c 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_thread.c 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or @@ -27,7 +27,6 @@ #include "drd_segment.h" #include "drd_suppression.h" #include "drd_thread.h" -#include "pub_core_options.h" // VG_(clo_backtrace_size) #include "pub_tool_basics.h" // Addr, SizeT #include "pub_tool_errormgr.h" // VG_(unique_error)() #include "pub_tool_libcassert.h" // tl_assert() @@ -35,6 +34,7 @@ #include "pub_tool_libcprint.h" // VG_(printf)() #include "pub_tool_machine.h" #include "pub_tool_mallocfree.h" // VG_(malloc)(), VG_(free)() +#include "pub_tool_options.h" // VG_(clo_backtrace_size) #include "pub_tool_threadstate.h" // VG_(get_pthread_id)() Modified: trunk/exp-drd/drd_thread.h =================================================================== --- trunk/exp-drd/drd_thread.h 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_thread.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,7 +1,7 @@ /* This file is part of drd, a data race detector. - Copyright (C) 2006-2007 Bart Van Assche + Copyright (C) 2006-2008 Bart Van Assche bar...@gm... This program is free software; you can redistribute it and/or Modified: trunk/exp-drd/drd_track.h =================================================================== --- trunk/exp-drd/drd_track.h 2008-01-13 15:36:15 UTC (rev 7345) +++ trunk/exp-drd/drd_track.h 2008-01-14 11:54:56 UTC (rev 7346) @@ -1,4 +1,30 @@ +/* + 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... [truncated message content] |