Eliminated upper bounds on the number of condition variables, semaphores and barriers. Added command-line option --trace-semaphore.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7508 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/exp-drd/drd_barrier.c b/exp-drd/drd_barrier.c
index 088872c..b4fca3d 100644
--- a/exp-drd/drd_barrier.c
+++ b/exp-drd/drd_barrier.c
@@ -24,6 +24,7 @@
#include "drd_barrier.h"
+#include "drd_clientobj.h"
#include "drd_error.h"
#include "drd_suppression.h"
#include "priv_drd_clientreq.h"
@@ -38,19 +39,6 @@
// Type definitions.
-/* Information associated with a client-side pthread_barrier_t object. */
-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 pre_iteration; // pthread_barrier_wait() call count modulo two.
- Word post_iteration; // pthread_barrier_wait() call count modulo two.
- Word pre_waiters_left; // number of waiters left for a complete barrier.
- Word post_waiters_left; // number of waiters left for a complete barrier.
- OSet* oset; // Thread-specific barrier information.
-};
-
/* Information associated with one thread participating in a barrier. */
struct barrier_thread_info
{
@@ -62,11 +50,14 @@
};
+// Local functions.
+
+void barrier_cleanup(struct barrier_info* p);
+
+
// Local variables.
static Bool s_trace_barrier = False;
-/* To do: eliminate the upper limit on the number of barriers (4). */
-struct barrier_info s_barrier[4];
// Function definitions.
@@ -106,9 +97,10 @@
tl_assert(barrier != 0);
tl_assert(size > 0);
tl_assert(count > 0);
+ tl_assert(p->a1 == barrier);
+ tl_assert(p->a2 - p->a1 == size);
- p->barrier = barrier;
- p->size = size;
+ p->cleanup = (void(*)(DrdClientobj*))barrier_cleanup;
p->count = count;
p->pre_iteration = 0;
p->post_iteration = 0;
@@ -120,14 +112,20 @@
p->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free));
}
-/** Deallocate the memory allocated by barrier_initialize() and in p->oset. */
-void barrier_destroy(struct barrier_info* const p)
+/** Deallocate the memory allocated by barrier_initialize() and in p->oset.
+ * Called by drd_clientobj_destroy().
+ */
+void barrier_cleanup(struct barrier_info* p)
{
struct barrier_thread_info* q;
tl_assert(p);
- drd_finish_suppression(p->barrier, p->barrier + p->size);
+ if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
+ {
+ VG_(message)(Vg_UserMsg, "Destruction of barrier 0x%lx being waited upon",
+ p->a1);
+ }
VG_(OSetGen_ResetIter)(p->oset);
for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; )
@@ -135,13 +133,6 @@
barrier_thread_destroy(q);
}
VG_(OSetGen_Destroy)(p->oset);
- p->barrier = 0;
- p->size = 0;
- p->count = 0;
- p->pre_iteration = 0;
- p->post_iteration = 0;
- p->pre_waiters_left = 0;
- p->post_waiters_left = 0;
}
/** Look up the client-side barrier address barrier in s_barrier[]. If not
@@ -150,31 +141,30 @@
struct barrier_info*
barrier_get_or_allocate(const Addr barrier, const SizeT size, const Word count)
{
- int i;
+ struct barrier_info *p;
- for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
+ tl_assert(offsetof(DrdClientobj, barrier) == 0);
+ p = &drd_clientobj_get(barrier, ClientBarrier)->barrier;
+ if (p == 0)
{
- if (s_barrier[i].barrier == barrier)
- {
- tl_assert(s_barrier[i].size == size);
- return &s_barrier[i];
- }
+ p = &drd_clientobj_add(barrier, barrier + size, ClientBarrier)->barrier;
+ barrier_initialize(p, barrier, size, count);
}
- 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;
+ return p;
+}
+
+/** Look up the address of the information associated with the client-side
+ * barrier object. */
+struct barrier_info* 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. */
+ * where count threads participate in each barrier.
+ * Called before pthread_barrier_init().
+ */
struct barrier_info*
barrier_init(const Addr barrier, const SizeT size, const Word count)
{
@@ -182,17 +172,14 @@
return barrier_get_or_allocate(barrier, size, count);
}
-/** Look up the address of the information associated with the client-side
- * barrier object. */
-struct barrier_info* barrier_get(const Addr barrier)
+/** Called after pthread_barrier_destroy(). */
+void barrier_destroy(struct barrier_info* const p)
{
- 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;
+ tl_assert(p);
+ drd_clientobj_remove(p->a1, ClientBarrier);
}
+/** Called before pthread_barrier_wait(). */
void barrier_pre_wait(const DrdThreadId tid, const Addr barrier)
{
struct barrier_info* p;
@@ -227,6 +214,7 @@
}
}
+/** Called after pthread_barrier_wait(). */
void barrier_post_wait(const DrdThreadId tid, const Addr barrier,
const Bool waited)
{
@@ -286,31 +274,15 @@
/** Call this function when thread tid stops to exist. */
void barrier_thread_delete(const DrdThreadId tid)
{
- int i;
+ struct barrier_info* p;
- for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
+ drd_clientobj_resetiter();
+ for ( ; (p = &drd_clientobj_next(ClientBarrier)->barrier) != 0; )
{
- struct barrier_info* const p = &s_barrier[i];
- if (p->barrier)
- {
- struct barrier_thread_info* q;
- const UWord word_tid = tid;
- q = VG_(OSetGen_Remove)(p->oset, &word_tid);
- barrier_thread_destroy(q);
- VG_(OSetGen_FreeNode)(p->oset, q);
- }
- }
-}
-
-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]);
- }
+ struct barrier_thread_info* q;
+ const UWord word_tid = tid;
+ q = VG_(OSetGen_Remove)(p->oset, &word_tid);
+ barrier_thread_destroy(q);
+ VG_(OSetGen_FreeNode)(p->oset, q);
}
}