Author: njn
Date: 2009-02-23 03:30:27 +0000 (Mon, 23 Feb 2009)
New Revision: 9232
Log:
Merged r9208..r9216 (DRD changes, plus a couple of other minor things) from
the trunk.
Added:
branches/DARWIN/drd/tests/pth_barrier_race.c
branches/DARWIN/drd/tests/pth_barrier_race.stderr.exp
branches/DARWIN/drd/tests/pth_barrier_race.vgtest
Modified:
branches/DARWIN/coregrind/m_oset.c
branches/DARWIN/drd/Testing.txt
branches/DARWIN/drd/docs/drd-manual.xml
branches/DARWIN/drd/drd_barrier.c
branches/DARWIN/drd/drd_barrier.h
branches/DARWIN/drd/drd_clientobj.c
branches/DARWIN/drd/drd_clientobj.h
branches/DARWIN/drd/drd_clientreq.c
branches/DARWIN/drd/drd_clientreq.h
branches/DARWIN/drd/drd_cond.c
branches/DARWIN/drd/drd_cond.h
branches/DARWIN/drd/drd_error.c
branches/DARWIN/drd/drd_error.h
branches/DARWIN/drd/drd_mutex.c
branches/DARWIN/drd/drd_mutex.h
branches/DARWIN/drd/drd_pthread_intercepts.c
branches/DARWIN/drd/drd_rwlock.c
branches/DARWIN/drd/drd_rwlock.h
branches/DARWIN/drd/drd_semaphore.c
branches/DARWIN/drd/drd_semaphore.h
branches/DARWIN/drd/drd_thread.c
branches/DARWIN/drd/tests/
branches/DARWIN/drd/tests/Makefile.am
branches/DARWIN/drd/tests/bar_bad.stderr.exp
branches/DARWIN/drd/tests/tc04_free_lock.stderr.exp
branches/DARWIN/drd/tests/tc09_bad_unlock.stderr.exp
branches/DARWIN/drd/tests/tc20_verifywrap.stderr.exp-glibc2.3
branches/DARWIN/drd/tests/tc20_verifywrap.stderr.exp-glibc2.5
branches/DARWIN/drd/tests/tc20_verifywrap.stderr.exp-glibc2.5-ppc
branches/DARWIN/drd/tests/tc20_verifywrap.stderr.exp-glibc2.8
branches/DARWIN/drd/tests/tc20_verifywrap2.stderr.exp-glibc2.3
branches/DARWIN/drd/tests/tc20_verifywrap2.stderr.exp-glibc2.3-b
branches/DARWIN/drd/tests/tc20_verifywrap2.stderr.exp-glibc2.5
branches/DARWIN/drd/tests/tc20_verifywrap2.stderr.exp-glibc2.5-ppc
branches/DARWIN/drd/tests/tc20_verifywrap2.stderr.exp-glibc2.8
branches/DARWIN/massif/tests/
branches/DARWIN/memcheck/tests/
branches/DARWIN/memcheck/tests/linux/
branches/DARWIN/memcheck/tests/x86-linux/
branches/DARWIN/none/tests/linux/
branches/DARWIN/tests/
Modified: branches/DARWIN/coregrind/m_oset.c
===================================================================
--- branches/DARWIN/coregrind/m_oset.c 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/coregrind/m_oset.c 2009-02-23 03:30:27 UTC (rev 9232)
@@ -808,9 +808,6 @@
if (oset->cmp) {
cmpresS = (Word)slow_cmp(oset, k, t);
} else {
- /* this is believed to be correct, but really needs testing
- before the assertion is removed. */
- vg_assert(0);
cmpresS = fast_cmp(k, t);
}
Modified: branches/DARWIN/drd/Testing.txt
===================================================================
--- branches/DARWIN/drd/Testing.txt 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/Testing.txt 2009-02-23 03:30:27 UTC (rev 9232)
@@ -1,28 +1,34 @@
How to test DRD
~~~~~~~~~~~~~~~
-1. Run the regression tests. After having compiled DRD, run the following
- command:
+1. Start with compiling DRD.
+2. Check as follows that all global symbols in DRD have been wrapped by the
+ DRD_() macro (output must be empty):
+ nm -A drd*.o|grep ' T '|grep -v ' T vgDrd_'
+3. Check as follows that all global symbols in the preloaded shared library
+ are redirected functions (output must be empty):
+ nm -A vgpreload*.o|grep ' T '|grep -v ' T _vg'
+4. Run the regression tests as follows:
perl tests/vg_regtest drd
-2. Run Konstantin's regression tests:
+5. Run Konstantin's regression tests:
svn checkout http://data-race-test.googlecode.com/svn/trunk drt
make -C drt/unittest -s build
./vg-in-place --tool=drd --check-stack-var=yes drt/unittest/racecheck_unittest 2>&1|less
-3. Test the slowdown for matinv for various matrix sizes via the script
+6. Test the slowdown for matinv for various matrix sizes via the script
drd/scripts/run-matinv (must be about 24 for i == 1 and about
31 for i == 10 with n == 200).
-4. Test whether DRD works with standard KDE applications and whether it does
+7. Test whether DRD works with standard KDE applications and whether it does
not print any false positives. Test this both with KDE3 and KDE4.
./vg-in-place --tool=drd --var-info=yes kate
./vg-in-place --tool=drd --var-info=yes --check-stack-var=yes kate
./vg-in-place --tool=drd --var-info=yes --trace-children=yes knode
./vg-in-place --tool=drd --var-info=yes --check-stack-var=yes --trace-children=yes knode
./vg-in-place --tool=drd --var-info=yes --check-stack-var=yes /usr/bin/designer
-5. Test whether DRD works with standard GNOME applications. Expect
+8. Test whether DRD works with standard GNOME applications. Expect
race reports triggered by ORBit_RootObject_duplicate() and after
having closed the GNOME terminal window:
./vg-in-place --tool=drd --var-info=yes --trace-children=yes gnome-terminal
-6. Test DRD with Firefox. First of all, make sure that Valgrind is patched
+9. Test DRD with Firefox. First of all, make sure that Valgrind is patched
such that it supports libjemalloc.so:
drd/scripts/add-libjemalloc-support
Next, build and install Firefox 3:
Modified: branches/DARWIN/drd/docs/drd-manual.xml
===================================================================
--- branches/DARWIN/drd/docs/drd-manual.xml 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/docs/drd-manual.xml 2009-02-23 03:30:27 UTC (rev 9232)
@@ -799,6 +799,11 @@
</listitem>
<listitem>
<para>
+ Missing synchronization between barrier wait and barrier destruction.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
Exiting a thread without first unlocking the spinlocks,
mutexes or reader-writer locks that were locked by that
thread.
Modified: branches/DARWIN/drd/drd_barrier.c
===================================================================
--- branches/DARWIN/drd/drd_barrier.c 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_barrier.c 2009-02-23 03:30:27 UTC (rev 9232)
@@ -40,57 +40,75 @@
/** Information associated with one thread participating in a barrier. */
struct barrier_thread_info
{
- UWord tid; // A DrdThreadId
+ UWord tid; // A DrdThreadId declared as UWord because
+ // this member variable is the key of an OSet.
Word iteration; // iteration of last pthread_barrier_wait()
// call thread tid participated in.
Segment* sg[2]; // Segments of the last two
// pthread_barrier() calls by thread tid.
+ ExeContext* wait_call_ctxt;// call stack for *_barrier_wait() call.
+ Segment* post_wait_sg; // Segment created after *_barrier_wait() finished
};
/* Local functions. */
-static void DRD_(barrier_cleanup)(struct barrier_info* p);
-static const char* DRD_(barrier_get_typename)(struct barrier_info* const p);
-static const char* DRD_(barrier_type_name)(const BarrierT bt);
+static void barrier_cleanup(struct barrier_info* p);
+static void barrier_delete_thread(struct barrier_info* const p,
+ const DrdThreadId tid);
+static const char* barrier_get_typename(struct barrier_info* const p);
+static const char* barrier_type_name(const BarrierT bt);
+static
+void barrier_report_wait_delete_race(const struct barrier_info* const p,
+ const struct barrier_thread_info* const q);
/* Local variables. */
-static Bool DRD_(s_trace_barrier) = False;
-static ULong DRD_(s_barrier_segment_creation_count);
+static Bool s_trace_barrier = False;
+static ULong s_barrier_segment_creation_count;
/* Function definitions. */
void DRD_(barrier_set_trace)(const Bool trace_barrier)
{
- DRD_(s_trace_barrier) = trace_barrier;
+ s_trace_barrier = trace_barrier;
}
-/** Initialize the structure *p with the specified thread ID and iteration
- * information. */
+/**
+ * Initialize the structure *p with the specified thread ID and iteration
+ * information.
+ */
static
void DRD_(barrier_thread_initialize)(struct barrier_thread_info* const p,
const DrdThreadId tid,
const Word iteration)
{
- p->tid = tid;
- p->iteration = iteration;
- p->sg[0] = 0;
- p->sg[1] = 0;
+ p->tid = tid;
+ p->iteration = iteration;
+ p->sg[0] = 0;
+ p->sg[1] = 0;
+ p->wait_call_ctxt = 0;
+ p->post_wait_sg = 0;
}
-/** Deallocate the memory that was allocated in barrier_thread_initialize(). */
+/**
+ * Deallocate the memory that is owned by members of
+ * struct barrier_thread_info.
+ */
static void DRD_(barrier_thread_destroy)(struct barrier_thread_info* const p)
{
tl_assert(p);
DRD_(sg_put)(p->sg[0]);
DRD_(sg_put)(p->sg[1]);
+ DRD_(sg_put)(p->post_wait_sg);
}
-/** Initialize the structure *p with the specified client-side barrier address,
- * barrier object size and number of participants in each barrier. */
+/**
+ * Initialize the structure *p with the specified client-side barrier address,
+ * barrier object size and number of participants in each barrier.
+ */
static
void DRD_(barrier_initialize)(struct barrier_info* const p,
const Addr barrier,
@@ -101,13 +119,16 @@
tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier);
tl_assert(p->a1 == barrier);
- p->cleanup = (void(*)(DrdClientobj*))DRD_(barrier_cleanup);
+ p->cleanup = (void(*)(DrdClientobj*))barrier_cleanup;
+ p->delete_thread
+ = (void(*)(DrdClientobj*, DrdThreadId))barrier_delete_thread;
p->barrier_type = barrier_type;
p->count = count;
p->pre_iteration = 0;
p->post_iteration = 0;
p->pre_waiters_left = count;
p->post_waiters_left = count;
+
tl_assert(sizeof(((struct barrier_thread_info*)0)->tid) == sizeof(Word));
tl_assert(sizeof(((struct barrier_thread_info*)0)->tid)
>= sizeof(DrdThreadId));
@@ -116,18 +137,21 @@
}
/**
- * Deallocate the memory allocated by barrier_initialize() and in p->oset.
+ * Deallocate the memory owned by the struct barrier_info object and also
+ * all the nodes in the OSet p->oset.
+ *
* Called by clientobj_destroy().
*/
-void DRD_(barrier_cleanup)(struct barrier_info* p)
+static void barrier_cleanup(struct barrier_info* p)
{
struct barrier_thread_info* q;
+ Segment* latest_sg = 0;
tl_assert(p);
if (p->pre_waiters_left != p->count)
{
- BarrierErrInfo bei = { p->a1 };
+ BarrierErrInfo bei = { p->a1, 0, 0 };
VG_(maybe_record_error)(VG_(get_running_tid)(),
BarrierErr,
VG_(get_IP)(VG_(get_running_tid)()),
@@ -136,16 +160,29 @@
&bei);
}
+ DRD_(thread_get_latest_segment)(&latest_sg, DRD_(thread_get_running_tid)());
+ tl_assert(latest_sg);
+
VG_(OSetGen_ResetIter)(p->oset);
for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; )
{
+ if (q->post_wait_sg
+ && ! DRD_(vc_lte)(&q->post_wait_sg->vc, &latest_sg->vc))
+ {
+ barrier_report_wait_delete_race(p, q);
+ }
+
DRD_(barrier_thread_destroy)(q);
}
VG_(OSetGen_Destroy)(p->oset);
+
+ DRD_(sg_put)(latest_sg);
}
-/** Look up the client-side barrier address barrier in s_barrier[]. If not
- * found, add it. */
+/**
+ * Look up the client-side barrier address barrier in s_barrier[]. If not
+ * found, add it.
+ */
static
struct barrier_info*
DRD_(barrier_get_or_allocate)(const Addr barrier,
@@ -165,17 +202,21 @@
return p;
}
-/** Look up the address of the information associated with the client-side
- * barrier object. */
+/**
+ * Look up the address of the information associated with the client-side
+ * barrier object.
+ */
static struct barrier_info* DRD_(barrier_get)(const Addr barrier)
{
tl_assert(offsetof(DrdClientobj, barrier) == 0);
return &(DRD_(clientobj_get)(barrier, ClientBarrier)->barrier);
}
-/** Initialize a barrier with client address barrier, client size size, and
- * where count threads participate in each barrier.
- * Called before pthread_barrier_init().
+/**
+ * Initialize a barrier with client address barrier, client size size, and
+ * where count threads participate in each barrier.
+ *
+ * Called before pthread_barrier_init().
*/
void DRD_(barrier_init)(const Addr barrier,
const BarrierT barrier_type, const Word count,
@@ -187,7 +228,7 @@
if (count == 0)
{
- BarrierErrInfo bei = { barrier };
+ BarrierErrInfo bei = { barrier, 0, 0 };
VG_(maybe_record_error)(VG_(get_running_tid)(),
BarrierErr,
VG_(get_IP)(VG_(get_running_tid)()),
@@ -200,7 +241,7 @@
p = DRD_(barrier_get)(barrier);
if (p)
{
- BarrierErrInfo bei = { barrier };
+ BarrierErrInfo bei = { barrier, 0, 0 };
VG_(maybe_record_error)(VG_(get_running_tid)(),
BarrierErr,
VG_(get_IP)(VG_(get_running_tid)()),
@@ -210,7 +251,7 @@
}
p = DRD_(barrier_get_or_allocate)(barrier, barrier_type, count);
- if (DRD_(s_trace_barrier))
+ if (s_trace_barrier)
{
if (reinitialization)
{
@@ -218,7 +259,7 @@
"[%d/%d] barrier_reinit %s 0x%lx count %ld -> %ld",
VG_(get_running_tid)(),
DRD_(thread_get_running_tid)(),
- DRD_(barrier_get_typename)(p),
+ barrier_get_typename(p),
barrier,
p->count,
count);
@@ -229,7 +270,7 @@
"[%d/%d] barrier_init %s 0x%lx",
VG_(get_running_tid)(),
DRD_(thread_get_running_tid)(),
- DRD_(barrier_get_typename)(p),
+ barrier_get_typename(p),
barrier);
}
}
@@ -238,7 +279,7 @@
{
if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
{
- BarrierErrInfo bei = { p->a1 };
+ BarrierErrInfo bei = { p->a1, 0, 0 };
VG_(maybe_record_error)(VG_(get_running_tid)(),
BarrierErr,
VG_(get_IP)(VG_(get_running_tid)()),
@@ -250,20 +291,20 @@
}
}
-/** Called after pthread_barrier_destroy(). */
+/** Called after pthread_barrier_destroy() / gomp_barrier_destroy(). */
void DRD_(barrier_destroy)(const Addr barrier, const BarrierT barrier_type)
{
struct barrier_info* p;
p = DRD_(barrier_get)(barrier);
- if (DRD_(s_trace_barrier))
+ if (s_trace_barrier)
{
VG_(message)(Vg_UserMsg,
"[%d/%d] barrier_destroy %s 0x%lx",
VG_(get_running_tid)(),
DRD_(thread_get_running_tid)(),
- DRD_(barrier_get_typename)(p),
+ barrier_get_typename(p),
barrier);
}
@@ -280,7 +321,7 @@
if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
{
- BarrierErrInfo bei = { p->a1 };
+ BarrierErrInfo bei = { p->a1, 0, 0 };
VG_(maybe_record_error)(VG_(get_running_tid)(),
BarrierErr,
VG_(get_IP)(VG_(get_running_tid)()),
@@ -291,7 +332,7 @@
DRD_(clientobj_remove)(p->a1, ClientBarrier);
}
-/** Called before pthread_barrier_wait(). */
+/** Called before pthread_barrier_wait() / gomp_barrier_wait(). */
void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
const BarrierT barrier_type)
{
@@ -302,6 +343,11 @@
p = DRD_(barrier_get)(barrier);
if (p == 0 && barrier_type == gomp_barrier)
{
+ /*
+ * gomp_barrier_wait() call has been intercepted but gomp_barrier_init()
+ * not. The only cause I know of that can trigger this is that libgomp.so
+ * has been compiled with --enable-linux-futex.
+ */
VG_(message)(Vg_UserMsg, "");
VG_(message)(Vg_UserMsg,
"Please verify whether gcc has been configured"
@@ -312,17 +358,18 @@
}
tl_assert(p);
- if (DRD_(s_trace_barrier))
+ if (s_trace_barrier)
{
VG_(message)(Vg_UserMsg,
"[%d/%d] barrier_pre_wait %s 0x%lx iteration %ld",
VG_(get_running_tid)(),
DRD_(thread_get_running_tid)(),
- DRD_(barrier_get_typename)(p),
+ barrier_get_typename(p),
barrier,
p->pre_iteration);
}
+ /* Allocate the per-thread data structure if necessary. */
q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
if (q == 0)
{
@@ -331,8 +378,21 @@
VG_(OSetGen_Insert)(p->oset, q);
tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
}
+
+ /* Record *_barrier_wait() call context. */
+ q->wait_call_ctxt = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
+
+ /*
+ * Store a pointer to the latest segment of the current thread in the
+ * per-thread data structure.
+ */
DRD_(thread_get_latest_segment)(&q->sg[p->pre_iteration], tid);
+ /*
+ * If the same number of threads as the barrier count indicates have
+ * called the pre *_barrier_wait() wrapper, toggle p->pre_iteration and
+ * reset the p->pre_waiters_left counter.
+ */
if (--p->pre_waiters_left <= 0)
{
p->pre_iteration = 1 - p->pre_iteration;
@@ -340,107 +400,148 @@
}
}
-/** Called after pthread_barrier_wait(). */
+/** Called after pthread_barrier_wait() / gomp_barrier_wait(). */
void DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier,
- const BarrierT barrier_type, const Bool waited)
+ const BarrierT barrier_type, const Bool waited,
+ const Bool serializing)
{
struct barrier_info* p;
+ const UWord word_tid = tid;
+ struct barrier_thread_info* q;
+ struct barrier_thread_info* r;
p = DRD_(barrier_get)(barrier);
- if (DRD_(s_trace_barrier))
+ if (s_trace_barrier)
{
VG_(message)(Vg_UserMsg,
- "[%d/%d] barrier_post_wait %s 0x%lx iteration %ld",
+ "[%d/%d] barrier_post_wait %s 0x%lx iteration %ld%s",
VG_(get_running_tid)(),
tid,
- p ? DRD_(barrier_get_typename)(p) : "(?)",
+ p ? barrier_get_typename(p) : "(?)",
barrier,
- p ? p->post_iteration : -1);
+ p ? p->post_iteration : -1,
+ serializing ? " (serializing)" : "");
}
- /* If p == 0, this means that the barrier has been destroyed after */
- /* *_barrier_wait() returned and before this function was called. Just */
- /* return in that case. */
+ /*
+ * If p == 0, this means that the barrier has been destroyed after
+ * *_barrier_wait() returned and before this function was called. Just
+ * return in that case -- race conditions between *_barrier_wait()
+ * and *_barrier_destroy() are detected by the *_barrier_destroy() wrapper.
+ */
if (p == 0)
return;
- if (waited)
+ /* If the *_barrier_wait() call returned an error code, exit. */
+ if (! waited)
+ return;
+
+ q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
+ if (q == 0)
{
- const UWord word_tid = tid;
- struct barrier_thread_info* q;
- struct barrier_thread_info* r;
+ BarrierErrInfo bei = { p->a1, 0, 0 };
+ VG_(maybe_record_error)(VG_(get_running_tid)(),
+ BarrierErr,
+ VG_(get_IP)(VG_(get_running_tid)()),
+ "Error in barrier implementation"
+ " -- barrier_wait() started before"
+ " barrier_destroy() and finished after"
+ " barrier_destroy()",
+ &bei);
- q = VG_(OSetGen_Lookup)(p->oset, &word_tid);
- if (q == 0)
+ q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
+ DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration);
+ VG_(OSetGen_Insert)(p->oset, q);
+ tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
+ }
+ /*
+ * Combine all vector clocks that were stored in the pre_barrier_wait
+ * wrapper with the vector clock of the current thread.
+ */
+ VG_(OSetGen_ResetIter)(p->oset);
+ for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; )
+ {
+ if (r != q)
{
- BarrierErrInfo bei = { p->a1 };
- VG_(maybe_record_error)(VG_(get_running_tid)(),
- BarrierErr,
- VG_(get_IP)(VG_(get_running_tid)()),
- "Error in barrier implementation"
- " -- barrier_wait() started before"
- " barrier_destroy() and finished after"
- " barrier_destroy()",
- &bei);
-
- q = VG_(OSetGen_AllocNode)(p->oset, sizeof(*q));
- DRD_(barrier_thread_initialize)(q, tid, p->pre_iteration);
- VG_(OSetGen_Insert)(p->oset, q);
- tl_assert(VG_(OSetGen_Lookup)(p->oset, &word_tid) == q);
+ tl_assert(r->sg[p->post_iteration]);
+ DRD_(thread_combine_vc2)(tid, &r->sg[p->post_iteration]->vc);
}
- VG_(OSetGen_ResetIter)(p->oset);
- for ( ; (r = VG_(OSetGen_Next)(p->oset)) != 0; )
- {
- if (r != q)
- {
- tl_assert(r->sg[p->post_iteration]);
- DRD_(thread_combine_vc2)(tid, &r->sg[p->post_iteration]->vc);
- }
- }
+ }
- DRD_(thread_new_segment)(tid);
- DRD_(s_barrier_segment_creation_count)++;
+ /* Create a new segment and store a pointer to that segment. */
+ DRD_(thread_new_segment)(tid);
+ DRD_(thread_get_latest_segment)(&q->post_wait_sg, tid);
+ s_barrier_segment_creation_count++;
- if (--p->post_waiters_left <= 0)
- {
- p->post_iteration = 1 - p->post_iteration;
- p->post_waiters_left = p->count;
- }
+ /*
+ * If the same number of threads as the barrier count indicates have
+ * called the post *_barrier_wait() wrapper, toggle p->post_iteration and
+ * reset the p->post_waiters_left counter.
+ */
+ if (--p->post_waiters_left <= 0)
+ {
+ p->post_iteration = 1 - p->post_iteration;
+ p->post_waiters_left = p->count;
}
}
-/** Call this function when thread tid stops to exist. */
-void DRD_(barrier_thread_delete)(const DrdThreadId tid)
+/** Called when thread tid stops to exist. */
+static void barrier_delete_thread(struct barrier_info* const p,
+ const DrdThreadId tid)
{
- struct barrier_info* p;
+ struct barrier_thread_info* q;
+ const UWord word_tid = tid;
- DRD_(clientobj_resetiter)();
- for ( ; (p = &(DRD_(clientobj_next)(ClientBarrier)->barrier)) != 0; )
+ q = VG_(OSetGen_Remove)(p->oset, &word_tid);
+
+ /*
+ * q is only non-zero if the barrier object has been used by thread tid
+ * after the barrier_init() call and before the thread finished.
+ */
+ if (q)
{
- struct barrier_thread_info* q;
- const UWord word_tid = tid;
- q = VG_(OSetGen_Remove)(p->oset, &word_tid);
- /* q is only non-zero if the barrier object has been used by thread tid
- * after the barrier_init() call and before the thread finished.
- */
- if (q)
- {
- DRD_(barrier_thread_destroy)(q);
- VG_(OSetGen_FreeNode)(p->oset, q);
- }
+ DRD_(barrier_thread_destroy)(q);
+ VG_(OSetGen_FreeNode)(p->oset, q);
}
}
-static const char* DRD_(barrier_get_typename)(struct barrier_info* const p)
+/**
+ * Report that *_barrier_destroy() has been called but that this call was
+ * not synchronized with the last *_barrier_wait() call on the same barrier.
+ *
+ * This topic has been discussed extensively on comp.programming.threads
+ * (February 3, 2009). See also
+ * <a href="http://groups.google.com/group/comp.programming.threads/browse_thread/thread/4f65535d6192aa50/a5f4bf1e3b437c4d">Immediately destroying pthread barriers</a>.
+ */
+static
+void barrier_report_wait_delete_race(const struct barrier_info* const p,
+ const struct barrier_thread_info* const q)
{
tl_assert(p);
+ tl_assert(q);
- return DRD_(barrier_type_name)(p->barrier_type);
+ {
+ BarrierErrInfo bei
+ = { p->a1, q->tid, q->wait_call_ctxt };
+ VG_(maybe_record_error)(VG_(get_running_tid)(),
+ BarrierErr,
+ VG_(get_IP)(VG_(get_running_tid)()),
+ "Destruction of barrier not synchronized with"
+ " barrier wait call",
+ &bei);
+ }
}
-static const char* DRD_(barrier_type_name)(const BarrierT bt)
+static const char* barrier_get_typename(struct barrier_info* const p)
{
+ tl_assert(p);
+
+ return barrier_type_name(p->barrier_type);
+}
+
+static const char* barrier_type_name(const BarrierT bt)
+{
switch (bt)
{
case pthread_barrier:
@@ -453,5 +554,5 @@
ULong DRD_(get_barrier_segment_creation_count)(void)
{
- return DRD_(s_barrier_segment_creation_count);
+ return s_barrier_segment_creation_count;
}
Modified: branches/DARWIN/drd/drd_barrier.h
===================================================================
--- branches/DARWIN/drd/drd_barrier.h 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_barrier.h 2009-02-23 03:30:27 UTC (rev 9232)
@@ -45,8 +45,8 @@
void DRD_(barrier_pre_wait)(const DrdThreadId tid, const Addr barrier,
const BarrierT barrier_type);
void DRD_(barrier_post_wait)(const DrdThreadId tid, const Addr barrier,
- const BarrierT barrier_type, const Bool waited);
-void DRD_(barrier_thread_delete)(const DrdThreadId threadid);
+ const BarrierT barrier_type, const Bool waited,
+ const Bool serializing);
void DRD_(barrier_stop_using_mem)(const Addr a1, const Addr a2);
ULong DRD_(get_barrier_segment_creation_count)(void);
Modified: branches/DARWIN/drd/drd_clientobj.c
===================================================================
--- branches/DARWIN/drd/drd_clientobj.c 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_clientobj.c 2009-02-23 03:30:27 UTC (rev 9232)
@@ -37,26 +37,29 @@
/* Local variables. */
-static OSet* DRD_(s_clientobj_set);
-static Bool DRD_(s_trace_clientobj);
+static OSet* s_clientobj_set;
+static Bool s_trace_clientobj;
+/* Local functions. */
+
+static Bool clientobj_remove_obj(DrdClientobj* const p);
+
+
/* Function definitions. */
void DRD_(clientobj_set_trace)(const Bool trace)
{
- DRD_(s_trace_clientobj) = trace;
+ s_trace_clientobj = trace;
}
/** Initialize the client object set. */
void DRD_(clientobj_init)(void)
{
- tl_assert(DRD_(s_clientobj_set) == 0);
- DRD_(s_clientobj_set) = VG_(OSetGen_Create)(0, 0,
- VG_(malloc),
- "drd.clientobj.ci.1",
- VG_(free));
- tl_assert(DRD_(s_clientobj_set));
+ tl_assert(s_clientobj_set == 0);
+ s_clientobj_set = VG_(OSetGen_Create)(0, 0, VG_(malloc),
+ "drd.clientobj.ci.1", VG_(free));
+ tl_assert(s_clientobj_set);
}
/**
@@ -66,29 +69,31 @@
*/
void DRD_(clientobj_cleanup)(void)
{
- tl_assert(DRD_(s_clientobj_set));
- tl_assert(VG_(OSetGen_Size)(DRD_(s_clientobj_set)) == 0);
- VG_(OSetGen_Destroy)(DRD_(s_clientobj_set));
- DRD_(s_clientobj_set) = 0;
+ tl_assert(s_clientobj_set);
+ tl_assert(VG_(OSetGen_Size)(s_clientobj_set) == 0);
+ VG_(OSetGen_Destroy)(s_clientobj_set);
+ s_clientobj_set = 0;
}
-/** Return the data associated with the client object at client address addr.
- * Return 0 if there is no client object in the set with the specified start
- * address.
+/**
+ * Return the data associated with the client object at client address addr.
+ * Return 0 if there is no client object in the set with the specified start
+ * address.
*/
DrdClientobj* DRD_(clientobj_get_any)(const Addr addr)
{
- return VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &addr);
+ return VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
}
-/** Return the data associated with the client object at client address addr
- * and that has object type t. Return 0 if there is no client object in the
- * set with the specified start address.
+/**
+ * Return the data associated with the client object at client address addr
+ * and that has object type t. Return 0 if there is no client object in the
+ * set with the specified start address.
*/
DrdClientobj* DRD_(clientobj_get)(const Addr addr, const ObjType t)
{
DrdClientobj* p;
- p = VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &addr);
+ p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
if (p && p->any.type == t)
return p;
return 0;
@@ -102,8 +107,8 @@
DrdClientobj *p;
tl_assert(a1 < a2);
- VG_(OSetGen_ResetIter)(DRD_(s_clientobj_set));
- for ( ; (p = VG_(OSetGen_Next)(DRD_(s_clientobj_set))) != 0; )
+ VG_(OSetGen_ResetIter)(s_clientobj_set);
+ for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; )
{
if (a1 <= p->any.a1 && p->any.a1 < a2)
{
@@ -122,50 +127,64 @@
DrdClientobj* p;
tl_assert(! DRD_(clientobj_present)(a1, a1 + 1));
- tl_assert(VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &a1) == 0);
+ tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == 0);
- if (DRD_(s_trace_clientobj))
+ if (s_trace_clientobj)
{
VG_(message)(Vg_UserMsg, "Adding client object 0x%lx of type %d", a1, t);
}
- p = VG_(OSetGen_AllocNode)(DRD_(s_clientobj_set), sizeof(*p));
+ p = VG_(OSetGen_AllocNode)(s_clientobj_set, sizeof(*p));
VG_(memset)(p, 0, sizeof(*p));
p->any.a1 = a1;
p->any.type = t;
p->any.first_observed_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
- VG_(OSetGen_Insert)(DRD_(s_clientobj_set), p);
- tl_assert(VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &a1) == p);
+ VG_(OSetGen_Insert)(s_clientobj_set, p);
+ tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == p);
DRD_(start_suppression)(a1, a1 + 1, "clientobj");
return p;
}
+/**
+ * Remove the information that was stored about the client object.
+ *
+ * @param[in] addr Address of the client object in the client address space.
+ * @param[in] t Type of the client object.
+ */
Bool DRD_(clientobj_remove)(const Addr addr, const ObjType t)
{
DrdClientobj* p;
- if (DRD_(s_trace_clientobj))
+ p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
+ tl_assert(p);
+ tl_assert(p->any.type == t);
+ return clientobj_remove_obj(p);
+}
+
+/**
+ * Remove the information that was stored about the client object p.
+ *
+ * @note The order of operations below is important. The client object is
+ * removed from the client object set after the cleanup function has been
+ * called such that if the cleanup function can still use the function
+ * DRD_(clientobj_get_any)(). This happens e.g. in the function
+ * first_observed() in drd_error.c.
+ */
+static Bool clientobj_remove_obj(DrdClientobj* const p)
+{
+ tl_assert(p);
+
+ if (s_trace_clientobj)
{
VG_(message)(Vg_UserMsg, "Removing client object 0x%lx of type %d",
- addr, t);
-#if 0
- VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
- VG_(clo_backtrace_size));
-#endif
+ p->any.a1, p->any.type);
}
- p = VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &addr);
- tl_assert(p->any.type == t);
- p = VG_(OSetGen_Remove)(DRD_(s_clientobj_set), &addr);
- if (p)
- {
- tl_assert(VG_(OSetGen_Lookup)(DRD_(s_clientobj_set), &addr) == 0);
- tl_assert(p->any.cleanup);
- (*p->any.cleanup)(p);
- VG_(OSetGen_FreeNode)(DRD_(s_clientobj_set), p);
- return True;
- }
- return False;
+ tl_assert(p->any.cleanup);
+ (*p->any.cleanup)(p);
+ VG_(OSetGen_Remove)(s_clientobj_set, &p->any.a1);
+ VG_(OSetGen_FreeNode)(s_clientobj_set, p);
+ return True;
}
void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2)
@@ -173,45 +192,46 @@
Addr removed_at;
DrdClientobj* p;
- tl_assert(DRD_(s_clientobj_set));
+ tl_assert(s_clientobj_set);
if (! DRD_(is_any_suppressed)(a1, a2))
return;
- VG_(OSetGen_ResetIter)(DRD_(s_clientobj_set));
- p = VG_(OSetGen_Next)(DRD_(s_clientobj_set));
+ VG_(OSetGen_ResetIter)(s_clientobj_set);
+ p = VG_(OSetGen_Next)(s_clientobj_set);
for ( ; p != 0; )
{
if (a1 <= p->any.a1 && p->any.a1 < a2)
{
removed_at = p->any.a1;
- DRD_(clientobj_remove)(p->any.a1, p->any.type);
+ clientobj_remove_obj(p);
/* The above call removes an element from the oset and hence */
/* invalidates the iterator. Set the iterator back. */
- VG_(OSetGen_ResetIter)(DRD_(s_clientobj_set));
- while ((p = VG_(OSetGen_Next)(DRD_(s_clientobj_set))) != 0
- && p->any.a1 <= removed_at)
- { }
+ VG_(OSetGen_ResetIterAt)(s_clientobj_set, &removed_at);
}
else
{
- p = VG_(OSetGen_Next)(DRD_(s_clientobj_set));
+ p = VG_(OSetGen_Next)(s_clientobj_set);
}
}
}
-void DRD_(clientobj_resetiter)(void)
+/**
+ * Delete the per-thread information stored in client objects for the
+ * specified thread.
+ */
+void DRD_(clientobj_delete_thread)(const DrdThreadId tid)
{
- VG_(OSetGen_ResetIter)(DRD_(s_clientobj_set));
-}
+ DrdClientobj *p;
-DrdClientobj* DRD_(clientobj_next)(const ObjType t)
-{
- DrdClientobj* p;
- while ((p = VG_(OSetGen_Next)(DRD_(s_clientobj_set))) != 0
- && p->any.type != t)
- ;
- return p;
+ VG_(OSetGen_ResetIter)(s_clientobj_set);
+ for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; )
+ {
+ if (p->any.delete_thread)
+ {
+ (*p->any.delete_thread)(p, tid);
+ }
+ }
}
const char* DRD_(clientobj_type_name)(const ObjType t)
Modified: branches/DARWIN/drd/drd_clientobj.h
===================================================================
--- branches/DARWIN/drd/drd_clientobj.h 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_clientobj.h 2009-02-23 03:30:27 UTC (rev 9232)
@@ -53,7 +53,8 @@
{
Addr a1;
ObjType type;
- void (*cleanup)(union drd_clientobj*);
+ void (*cleanup)(union drd_clientobj*);
+ void (*delete_thread)(union drd_clientobj*, DrdThreadId);
ExeContext* first_observed_at;
};
@@ -62,6 +63,7 @@
Addr a1;
ObjType type;
void (*cleanup)(union drd_clientobj*);
+ void (*delete_thread)(union drd_clientobj*, DrdThreadId);
ExeContext* first_observed_at;
MutexT mutex_type; // pthread_mutex_t or pthread_spinlock_t.
int recursion_count; // 0 if free, >= 1 if locked.
@@ -75,7 +77,8 @@
{
Addr a1;
ObjType type;
- void (*cleanup)(union drd_clientobj*);
+ void (*cleanup)(union drd_clientobj*);
+ void (*delete_thread)(union drd_clientobj*, DrdThreadId);
ExeContext* first_observed_at;
int waiter_count;
Addr mutex; // Client mutex specified in pthread_cond_wait() call, and
@@ -87,6 +90,7 @@
Addr a1;
ObjType type;
void (*cleanup)(union drd_clientobj*);
+ void (*delete_thread)(union drd_clientobj*, DrdThreadId);
ExeContext* first_observed_at;
UInt waits_to_skip; // Number of sem_wait() calls to skip
// (due to the value assigned by sem_init()).
@@ -101,14 +105,15 @@
Addr a1;
ObjType type;
void (*cleanup)(union drd_clientobj*);
+ void (*delete_thread)(union drd_clientobj*, DrdThreadId);
ExeContext* first_observed_at;
BarrierT barrier_type; // pthread_barrier or gomp_barrier.
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_iteration; // pre barrier completion count modulo two.
+ Word post_iteration; // post barrier completion 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.
+ OSet* oset; // Per-thread barrier information.
};
struct rwlock_info
@@ -116,6 +121,7 @@
Addr a1;
ObjType type;
void (*cleanup)(union drd_clientobj*);
+ void (*delete_thread)(union drd_clientobj*, DrdThreadId);
ExeContext* first_observed_at;
OSet* thread_info;
ULong acquiry_time_ms;
@@ -144,8 +150,7 @@
DrdClientobj* DRD_(clientobj_add)(const Addr a1, const ObjType t);
Bool DRD_(clientobj_remove)(const Addr addr, const ObjType t);
void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2);
-void DRD_(clientobj_resetiter)(void);
-DrdClientobj* DRD_(clientobj_next)(const ObjType t);
+void DRD_(clientobj_delete_thread)(const DrdThreadId tid);
const char* DRD_(clientobj_type_name)(const ObjType t);
Modified: branches/DARWIN/drd/drd_clientreq.c
===================================================================
--- branches/DARWIN/drd/drd_clientreq.c 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_clientreq.c 2009-02-23 03:30:27 UTC (rev 9232)
@@ -327,7 +327,7 @@
case VG_USERREQ__POST_BARRIER_WAIT:
if (DRD_(thread_leave_synchr)(drd_tid) == 0)
- DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3]);
+ DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3], arg[4]);
break;
case VG_USERREQ__PRE_RWLOCK_INIT:
Modified: branches/DARWIN/drd/drd_clientreq.h
===================================================================
--- branches/DARWIN/drd/drd_clientreq.h 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_clientreq.h 2009-02-23 03:30:27 UTC (rev 9232)
@@ -178,7 +178,7 @@
/* args: Addr barrier, BarrierT type. */
/* To notify the drd tool of a pthread_barrier_wait call. */
VG_USERREQ__POST_BARRIER_WAIT,
- /* args: Addr barrier, BarrierT type, Word has_waited */
+ /* args: Addr barrier, BarrierT type, Word has_waited, Word serializing */
/* To notify the drd tool of a pthread_rwlock_init call. */
VG_USERREQ__PRE_RWLOCK_INIT,
Modified: branches/DARWIN/drd/drd_cond.c
===================================================================
--- branches/DARWIN/drd/drd_cond.c 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_cond.c 2009-02-23 03:30:27 UTC (rev 9232)
@@ -65,9 +65,10 @@
tl_assert(p->a1 == cond);
tl_assert(p->type == ClientCondvar);
- p->cleanup = (void(*)(DrdClientobj*))(DRD_(cond_cleanup));
- p->waiter_count = 0;
- p->mutex = 0;
+ p->cleanup = (void(*)(DrdClientobj*))(DRD_(cond_cleanup));
+ p->delete_thread = 0;
+ p->waiter_count = 0;
+ p->mutex = 0;
}
/**
@@ -328,7 +329,3 @@
DRD_(cond_signal)(cond);
}
-
-/** Called after pthread_cond_destroy(). */
-void DRD_(cond_thread_delete)(const DrdThreadId tid)
-{ }
Modified: branches/DARWIN/drd/drd_cond.h
===================================================================
--- branches/DARWIN/drd/drd_cond.h 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_cond.h 2009-02-23 03:30:27 UTC (rev 9232)
@@ -45,7 +45,6 @@
int DRD_(cond_post_wait)(const Addr cond);
void DRD_(cond_pre_signal)(const Addr cond);
void DRD_(cond_pre_broadcast)(const Addr cond);
-void DRD_(cond_thread_delete)(const DrdThreadId tid);
#endif /* __DRD_COND_H */
Modified: branches/DARWIN/drd/drd_error.c
===================================================================
--- branches/DARWIN/drd/drd_error.c 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_error.c 2009-02-23 03:30:27 UTC (rev 9232)
@@ -42,12 +42,12 @@
/* Local variables. */
-static Bool DRD_(s_show_conflicting_segments) = True;
+static Bool s_show_conflicting_segments = True;
void DRD_(set_show_conflicting_segments)(const Bool scs)
{
- DRD_(s_show_conflicting_segments) = scs;
+ s_show_conflicting_segments = scs;
}
/**
@@ -55,8 +55,7 @@
* messages, putting the result in ai.
*/
static
-void DRD_(describe_malloced_addr)(Addr const a, SizeT const len,
- AddrInfo* const ai)
+void describe_malloced_addr(Addr const a, SizeT const len, AddrInfo* const ai)
{
Addr data;
@@ -76,7 +75,7 @@
* call stack will either refer to a pthread_*_init() or a pthread_*lock()
* call.
*/
-static void DRD_(first_observed)(const Addr obj)
+static void first_observed(const Addr obj)
{
DrdClientobj* cl;
@@ -93,8 +92,7 @@
}
static
-void DRD_(drd_report_data_race)(Error* const err,
- const DataRaceErrInfo* const dri)
+void drd_report_data_race(Error* const err, const DataRaceErrInfo* const dri)
{
AddrInfo ai;
const unsigned descr_size = 256;
@@ -112,7 +110,7 @@
VG_(get_data_description)(descr1, descr2, descr_size, dri->addr);
if (descr1[0] == 0)
{
- DRD_(describe_malloced_addr)(dri->addr, dri->size, &ai);
+ describe_malloced_addr(dri->addr, dri->size, &ai);
}
VG_(message)(Vg_UserMsg,
"Conflicting %s by thread %d/%d at 0x%08lx size %ld",
@@ -153,7 +151,7 @@
VG_(message)(Vg_UserMsg, "Allocation context: unknown.");
}
}
- if (DRD_(s_show_conflicting_segments))
+ if (s_show_conflicting_segments)
{
DRD_(thread_report_conflicting_segments)(dri->tid,
dri->addr, dri->size,
@@ -164,17 +162,17 @@
VG_(free)(descr1);
}
-static Bool DRD_(drd_tool_error_eq)(VgRes res, Error* e1, Error* e2)
+static Bool drd_tool_error_eq(VgRes res, Error* e1, Error* e2)
{
return False;
}
-static void DRD_(drd_tool_error_pp)(Error* const e)
+static void drd_tool_error_pp(Error* const e)
{
switch (VG_(get_error_kind)(e))
{
case DataRaceErr: {
- DRD_(drd_report_data_race)(e, VG_(get_error_extra)(e));
+ drd_report_data_race(e, VG_(get_error_extra)(e));
break;
}
case MutexErr: {
@@ -196,7 +194,7 @@
p->mutex);
}
VG_(pp_ExeContext)(VG_(get_error_where)(e));
- DRD_(first_observed)(p->mutex);
+ first_observed(p->mutex);
break;
}
case CondErr: {
@@ -206,7 +204,7 @@
VG_(get_error_string)(e),
cdei->cond);
VG_(pp_ExeContext)(VG_(get_error_where)(e));
- DRD_(first_observed)(cdei->cond);
+ first_observed(cdei->cond);
break;
}
case CondDestrErr: {
@@ -217,7 +215,7 @@
cdi->cond, cdi->mutex,
DRD_(DrdThreadIdToVgThreadId)(cdi->tid), cdi->tid);
VG_(pp_ExeContext)(VG_(get_error_where)(e));
- DRD_(first_observed)(cdi->mutex);
+ first_observed(cdi->mutex);
break;
}
case CondRaceErr: {
@@ -228,8 +226,8 @@
" by the signalling thread.",
cei->cond, cei->mutex);
VG_(pp_ExeContext)(VG_(get_error_where)(e));
- DRD_(first_observed)(cei->cond);
- DRD_(first_observed)(cei->mutex);
+ first_observed(cei->cond);
+ first_observed(cei->mutex);
break;
}
case CondWaitErr: {
@@ -241,9 +239,9 @@
cwei->mutex1,
cwei->mutex2);
VG_(pp_ExeContext)(VG_(get_error_where)(e));
- DRD_(first_observed)(cwei->cond);
- DRD_(first_observed)(cwei->mutex1);
- DRD_(first_observed)(cwei->mutex2);
+ first_observed(cwei->cond);
+ first_observed(cwei->mutex1);
+ first_observed(cwei->mutex2);
break;
}
case SemaphoreErr: {
@@ -254,18 +252,26 @@
VG_(get_error_string)(e),
sei->semaphore);
VG_(pp_ExeContext)(VG_(get_error_where)(e));
- DRD_(first_observed)(sei->semaphore);
+ first_observed(sei->semaphore);
break;
}
case BarrierErr: {
- BarrierErrInfo* bei =(BarrierErrInfo*)(VG_(get_error_extra)(e));
+ BarrierErrInfo* bei = (BarrierErrInfo*)(VG_(get_error_extra)(e));
tl_assert(bei);
VG_(message)(Vg_UserMsg,
"%s: barrier 0x%lx",
VG_(get_error_string)(e),
bei->barrier);
VG_(pp_ExeContext)(VG_(get_error_where)(e));
- DRD_(first_observed)(bei->barrier);
+ if (bei->other_context)
+ {
+ VG_(message)(Vg_UserMsg,
+ "Conflicting wait call by thread %d/%d:",
+ DRD_(DrdThreadIdToVgThreadId)(bei->other_tid),
+ bei->other_tid);
+ VG_(pp_ExeContext)(bei->other_context);
+ }
+ first_observed(bei->barrier);
break;
}
case RwlockErr: {
@@ -276,7 +282,7 @@
VG_(get_error_string)(e),
p->rwlock);
VG_(pp_ExeContext)(VG_(get_error_where)(e));
- DRD_(first_observed)(p->rwlock);
+ first_observed(p->rwlock);
break;
}
case HoldtimeErr: {
@@ -292,7 +298,7 @@
p->hold_time_ms,
p->threshold_ms);
VG_(pp_ExeContext)(VG_(get_error_where)(e));
- DRD_(first_observed)(p->synchronization_object);
+ first_observed(p->synchronization_object);
break;
}
case GenericErr: {
@@ -310,7 +316,7 @@
}
}
-static UInt DRD_(drd_tool_error_update_extra)(Error* e)
+static UInt drd_tool_error_update_extra(Error* e)
{
switch (VG_(get_error_kind)(e))
{
@@ -342,7 +348,7 @@
}
}
-static Bool DRD_(drd_tool_error_recog)(Char* const name, Supp* const supp)
+static Bool drd_tool_error_recog(Char* const name, Supp* const supp)
{
SuppKind skind = 0;
@@ -376,12 +382,12 @@
}
static
-Bool DRD_(drd_tool_error_read_extra)(Int fd, Char* buf, Int nBuf, Supp* supp)
+Bool drd_tool_error_read_extra(Int fd, Char* buf, Int nBuf, Supp* supp)
{
return True;
}
-static Bool DRD_(drd_tool_error_matches)(Error* const e, Supp* const supp)
+static Bool drd_tool_error_matches(Error* const e, Supp* const supp)
{
switch (VG_(get_supp_kind)(supp))
{
@@ -389,7 +395,7 @@
return True;
}
-static Char* DRD_(drd_tool_error_name)(Error* e)
+static Char* drd_tool_error_name(Error* e)
{
switch (VG_(get_error_kind)(e))
{
@@ -410,19 +416,19 @@
return 0;
}
-static void DRD_(drd_tool_error_print_extra)(Error* e)
+static void drd_tool_error_print_extra(Error* e)
{ }
void DRD_(register_error_handlers)(void)
{
// Tool error reporting.
- VG_(needs_tool_errors)(DRD_(drd_tool_error_eq),
- DRD_(drd_tool_error_pp),
+ VG_(needs_tool_errors)(drd_tool_error_eq,
+ drd_tool_error_pp,
True,
- DRD_(drd_tool_error_update_extra),
- DRD_(drd_tool_error_recog),
- DRD_(drd_tool_error_read_extra),
- DRD_(drd_tool_error_matches),
- DRD_(drd_tool_error_name),
- DRD_(drd_tool_error_print_extra));
+ drd_tool_error_update_extra,
+ drd_tool_error_recog,
+ drd_tool_error_read_extra,
+ drd_tool_error_matches,
+ drd_tool_error_name,
+ drd_tool_error_print_extra);
}
Modified: branches/DARWIN/drd/drd_error.h
===================================================================
--- branches/DARWIN/drd/drd_error.h 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_error.h 2009-02-23 03:30:27 UTC (rev 9232)
@@ -128,7 +128,9 @@
} SemaphoreErrInfo;
typedef struct {
- Addr barrier;
+ Addr barrier;
+ DrdThreadId other_tid;
+ ExeContext* other_context;
} BarrierErrInfo;
typedef struct {
Modified: branches/DARWIN/drd/drd_mutex.c
===================================================================
--- branches/DARWIN/drd/drd_mutex.c 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_mutex.c 2009-02-23 03:30:27 UTC (rev 9232)
@@ -38,16 +38,17 @@
/* Local functions. */
-static void DRD_(mutex_cleanup)(struct mutex_info* p);
-static Bool DRD_(mutex_is_locked)(struct mutex_info* const p);
+static void mutex_cleanup(struct mutex_info* p);
+static Bool mutex_is_locked(struct mutex_info* const p);
+static void mutex_delete_thread(struct mutex_info* p, const DrdThreadId tid);
/* Local variables. */
-static Bool DRD_(s_trace_mutex);
-static ULong DRD_(s_mutex_lock_count);
-static ULong DRD_(s_mutex_segment_creation_count);
-static UInt DRD_(s_mutex_lock_threshold_ms) = 1000 * 1000;
+static Bool s_trace_mutex;
+static ULong s_mutex_lock_count;
+static ULong s_mutex_segment_creation_count;
+static UInt s_mutex_lock_threshold_ms = 1000 * 1000;
/* Function definitions. */
@@ -55,12 +56,12 @@
void DRD_(mutex_set_trace)(const Bool trace_mutex)
{
tl_assert(!! trace_mutex == trace_mutex);
- DRD_(s_trace_mutex) = trace_mutex;
+ s_trace_mutex = trace_mutex;
}
void DRD_(mutex_set_lock_threshold)(const UInt lock_threshold_ms)
{
- DRD_(s_mutex_lock_threshold_ms) = lock_threshold_ms;
+ s_mutex_lock_threshold_ms = lock_threshold_ms;
}
static
@@ -71,7 +72,9 @@
tl_assert(mutex_type != mutex_type_unknown);
tl_assert(p->a1 == mutex);
- p->cleanup = (void(*)(DrdClientobj*))&(DRD_(mutex_cleanup));
+ p->cleanup = (void(*)(DrdClientobj*))mutex_cleanup;
+ p->delete_thread
+ = (void(*)(DrdClientobj*, DrdThreadId))mutex_delete_thread;
p->mutex_type = mutex_type;
p->recursion_count = 0;
p->owner = DRD_INVALID_THREADID;
@@ -81,11 +84,11 @@
}
/** Deallocate the memory that was allocated by mutex_initialize(). */
-static void DRD_(mutex_cleanup)(struct mutex_info* p)
+static void mutex_cleanup(struct mutex_info* p)
{
tl_assert(p);
- if (DRD_(s_trace_mutex))
+ if (s_trace_mutex)
{
VG_(message)(Vg_UserMsg,
"[%d/%d] mutex_destroy %s 0x%lx rc %d owner %d",
@@ -97,7 +100,7 @@
p ? p->owner : DRD_INVALID_THREADID);
}
- if (DRD_(mutex_is_locked)(p))
+ if (mutex_is_locked(p))
{
MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner };
VG_(maybe_record_error)(VG_(get_running_tid)(),
@@ -162,7 +165,7 @@
tl_assert(mutex_type != mutex_type_unknown);
- if (DRD_(s_trace_mutex))
+ if (s_trace_mutex)
{
VG_(message)(Vg_UserMsg,
"[%d/%d] mutex_init %s 0x%lx",
@@ -225,7 +228,7 @@
if (mutex_type == mutex_type_unknown)
mutex_type = p->mutex_type;
- if (DRD_(s_trace_mutex))
+ if (s_trace_mutex)
{
VG_(message)(Vg_UserMsg,
"[%d/%d] %s %s 0x%lx rc %d owner %d",
@@ -279,7 +282,7 @@
p = DRD_(mutex_get)(mutex);
- if (DRD_(s_trace_mutex))
+ if (s_trace_mutex)
{
VG_(message)(Vg_UserMsg,
"[%d/%d] %s %s 0x%lx rc %d owner %d%s",
@@ -306,12 +309,12 @@
DRD_(thread_combine_vc2)(drd_tid, &p->last_locked_segment->vc);
}
DRD_(thread_new_segment)(drd_tid);
- DRD_(s_mutex_segment_creation_count)++;
+ s_mutex_segment_creation_count++;
p->owner = drd_tid;
p->acquiry_time_ms = VG_(read_millisecond_timer)();
p->acquired_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
- DRD_(s_mutex_lock_count)++;
+ s_mutex_lock_count++;
}
else if (p->owner != drd_tid)
{
@@ -328,9 +331,8 @@
/**
* Update mutex_info state when unlocking the pthread_mutex_t mutex.
*
- * @param mutex Pointer to pthread_mutex_t data structure in the client space.
- * @param tid ThreadId of the thread calling pthread_mutex_unlock().
- * @param vc Pointer to the current vector clock of thread tid.
+ * @param[in] mutex Address of the client mutex.
+ * @param[in] mutex_type Mutex type.
*
* @return New value of the mutex recursion count.
*
@@ -347,7 +349,7 @@
if (mutex_type == mutex_type_unknown)
mutex_type = p->mutex_type;
- if (DRD_(s_trace_mutex))
+ if (s_trace_mutex)
{
VG_(message)(Vg_UserMsg,
"[%d/%d] mutex_unlock %s 0x%lx rc %d",
@@ -400,13 +402,13 @@
if (p->recursion_count == 0)
{
- if (DRD_(s_mutex_lock_threshold_ms) > 0)
+ if (s_mutex_lock_threshold_ms > 0)
{
ULong held = VG_(read_millisecond_timer)() - p->acquiry_time_ms;
- if (held > DRD_(s_mutex_lock_threshold_ms))
+ if (held > s_mutex_lock_threshold_ms)
{
HoldtimeErrInfo HEI
- = { mutex, p->acquired_at, held, DRD_(s_mutex_lock_threshold_ms) };
+ = { mutex, p->acquired_at, held, s_mutex_lock_threshold_ms };
VG_(maybe_record_error)(vg_tid,
HoldtimeErr,
VG_(get_IP)(vg_tid),
@@ -422,7 +424,7 @@
DRD_(thread_get_latest_segment)(&p->last_locked_segment, drd_tid);
DRD_(thread_new_segment)(drd_tid);
p->acquired_at = 0;
- DRD_(s_mutex_segment_creation_count)++;
+ s_mutex_segment_creation_count++;
}
}
@@ -467,7 +469,7 @@
}
/** Return true if the specified mutex is locked by any thread. */
-static Bool DRD_(mutex_is_locked)(struct mutex_info* const p)
+static Bool mutex_is_locked(struct mutex_info* const p)
{
tl_assert(p);
return (p->recursion_count > 0);
@@ -494,33 +496,29 @@
* 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 DRD_(mutex_thread_delete)(const DrdThreadId tid)
+static void mutex_delete_thread(struct mutex_info* p, const DrdThreadId tid)
{
- struct mutex_info* p;
+ tl_assert(p);
- DRD_(clientobj_resetiter)();
- for ( ; (p = &(DRD_(clientobj_next)(ClientMutex)->mutex)) != 0; )
+ if (p->owner == tid && p->recursion_count > 0)
{
- if (p->owner == tid && p->recursion_count > 0)
- {
- MutexErrInfo MEI
- = { p->a1, p->recursion_count, p->owner };
- VG_(maybe_record_error)(VG_(get_running_tid)(),
- MutexErr,
- VG_(get_IP)(VG_(get_running_tid)()),
- "Mutex still locked at thread exit",
- &MEI);
- p->owner = VG_INVALID_THREADID;
- }
+ MutexErrInfo MEI
+ = { p->a1, p->recursion_count, p->owner };
+ VG_(maybe_record_error)(VG_(get_running_tid)(),
+ MutexErr,
+ VG_(get_IP)(VG_(get_running_tid)()),
+ "Mutex still locked at thread exit",
+ &MEI);
+ p->owner = VG_INVALID_THREADID;
}
}
ULong DRD_(get_mutex_lock_count)(void)
{
- return DRD_(s_mutex_lock_count);
+ return s_mutex_lock_count;
}
ULong DRD_(get_mutex_segment_creation_count)(void)
{
- return DRD_(s_mutex_segment_creation_count);
+ return s_mutex_segment_creation_count;
}
Modified: branches/DARWIN/drd/drd_mutex.h
===================================================================
--- branches/DARWIN/drd/drd_mutex.h 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_mutex.h 2009-02-23 03:30:27 UTC (rev 9232)
@@ -50,7 +50,6 @@
const char* DRD_(mutex_type_name)(const MutexT mt);
Bool DRD_(mutex_is_locked_by)(const Addr mutex, const DrdThreadId tid);
int DRD_(mutex_get_recursion_count)(const Addr mutex);
-void DRD_(mutex_thread_delete)(const DrdThreadId tid);
ULong DRD_(get_mutex_lock_count)(void);
ULong DRD_(get_mutex_segment_creation_count)(void);
Modified: branches/DARWIN/drd/drd_pthread_intercepts.c
===================================================================
--- branches/DARWIN/drd/drd_pthread_intercepts.c 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_pthread_intercepts.c 2009-02-23 03:30:27 UTC (rev 9232)
@@ -194,8 +194,10 @@
}
/**
- * Return 1 if the LinuxThread implementation has been detected, and 0
- * otherwise. For more information about the confstr() function, see also
+ * Return 1 if the LinuxThreads implementation of POSIX Threads has been
+ * detected, and 0 otherwise.
+ *
+ * @see For more information about the confstr() function, see also
* http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html
*/
static int DRD_(detected_linuxthreads)(void)
@@ -283,7 +285,7 @@
/*
* Find out whether the thread will be started as a joinable thread
* or as a detached thread. If no thread attributes have been specified,
- * the new thread will be started as a joinable thread.
+ * this means that the new thread will be started as a joinable thread.
*/
thread_args.detachstate = PTHREAD_CREATE_JOINABLE;
if (attr)
@@ -710,7 +712,7 @@
VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
barrier, pthread_barrier,
ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
- 0, 0);
+ ret == PTHREAD_BARRIER_SERIAL_THREAD, 0);
return ret;
}
#endif // HAVE_PTHREAD_BARRIER_INIT
Modified: branches/DARWIN/drd/drd_rwlock.c
===================================================================
--- branches/DARWIN/drd/drd_rwlock.c 2009-02-23 02:09:34 UTC (rev 9231)
+++ branches/DARWIN/drd/drd_rwlock.c 2009-02-23 03:30:27 UTC (rev 9232)
@@ -49,7 +49,9 @@
/* Local functions. */
-static void DRD_(rwlock_cleanup)(struct rwlock_info* p);
+static void rwlock_cleanup(struct rwlock_info* p);
+static void rwlock_delete_thread(struct rwlock_info* const p,
+ const DrdThreadId tid);
/* Local variables. */
@@ -184,7 +186,8 @@
tl_assert(p->a1 == rwlock);
tl_assert(p->type == ClientRwlock);
- p->cleanup = (void(*)(DrdClientobj*))&(DRD_(rwlock_cleanup));
+ p->cleanup = (void(*)(DrdClientobj*))rwlock_cleanup;
+ p->delete_thread = (void(*)(DrdClientobj*, DrdThreadId))rwlock_delete_thread;
p->thread_info = VG_(OSetGen_Create)(
0, 0, VG_(malloc), "drd.rwlock.ri.1", VG_(free));
p->acquiry_time_ms = 0;
@@ -192,7 +195,7 @@
}
/** Deallocate the memory that was allocated by rwlock_initialize(). */
-static void DRD_(rwlock_cleanup)(struct rwlock_info* p)
+static void rwlock_cleanup(struct rwlock_info* p)
{
struct rwlock_thread_info* q;
@@ -464,12 +467,13 @@
/**
* 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.
+ *
+ * @return New value of the rwlock recursion count.
+ *
+ * @note This function must be called before pthread_rwlock_unlock() is called,
+ * or a race condition is triggered !
*/
void DRD_(rwlock_pre_unlock)(const Addr rwlock)
{
@@ -567,26 +571,21 @@
* 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 DRD_(rwlock_thread_delete)(const DrdThreadId tid)
+static void rwlock_delete_thread(struct rwlock_info* const p,
+ const DrdThreadId tid)
{
- struct rwlock_info* p;
-
- DRD_(clientobj_resetiter)();
- for ( ; (p = &(DRD_(clientobj_next)(ClientRwlock)->rwlock)) != 0; )
+ struct rwlock_thread_info* q;
+ if (DRD_(rwlock_is_locked_by)(p, tid))
{
- struct rwlock_thread_info* q;
- if (DRD_(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 = DRD_(lookup_or_insert_node)(p->thread_info, tid);
- q->reader_nesting_count = 0;
- q->writer_nesting_count = 0;
- }
+ RwlockErrInfo REI = { p->a1 };
+ VG_(maybe_record_error)(VG_(...
[truncated message content] |