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_cond.c b/exp-drd/drd_cond.c
index 6fdd912..3de2f3b 100644
--- a/exp-drd/drd_cond.c
+++ b/exp-drd/drd_cond.c
@@ -23,6 +23,7 @@
*/
+#include "drd_clientobj.h"
#include "drd_cond.h"
#include "drd_error.h"
#include "drd_mutex.h"
@@ -35,10 +36,18 @@
#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
-static struct cond_info s_cond[256];
+// Local functions.
+
+static void cond_cleanup(struct cond_info* p);
+
+
+// Local variables.
+
static Bool s_trace_cond;
+// Function definitions.
+
void cond_set_trace(const Bool trace_cond)
{
s_trace_cond = trace_cond;
@@ -49,81 +58,82 @@
const SizeT size)
{
tl_assert(cond != 0);
+ tl_assert(p->a1 == cond);
+ tl_assert(p->a2 - p->a1 == size);
+ tl_assert(p->type == ClientCondvar);
- p->cond = cond;
- p->size = size;
+ p->cleanup = (void(*)(DrdClientobj*))cond_cleanup;
p->waiter_count = 0;
p->mutex = 0;
}
+/** Free the memory that was allocated by cond_initialize(). Called by
+ * drd_clientobj_remove().
+ */
+static void cond_cleanup(struct cond_info* p)
+{
+ tl_assert(p);
+ if (p->mutex)
+ {
+ struct mutex_info* q;
+ q = &drd_clientobj_get(p->mutex, ClientMutex)->mutex;
+ VG_(message)(Vg_UserMsg,
+ "Error: destroying condition variable 0x%lx while thread %d"
+ " is waiting on it.\n",
+ p->a1, q ? q->owner : -1);
+ }
+}
+
static struct cond_info*
cond_get_or_allocate(const Addr cond, const SizeT size)
{
- int i;
- for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
+ struct cond_info *p;
+
+ tl_assert(offsetof(DrdClientobj, cond) == 0);
+ p = &drd_clientobj_get(cond, ClientCondvar)->cond;
+ if (p == 0)
{
- if (s_cond[i].cond == cond)
- {
- tl_assert(s_cond[i].size == size);
- return &s_cond[i];
- }
+ p = &drd_clientobj_add(cond, cond + size, ClientCondvar)->cond;
+ cond_initialize(p, cond, size);
}
- for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
- {
- if (s_cond[i].cond == 0)
- {
- cond_initialize(&s_cond[i], cond, size);
- /* TO DO: replace the constant below by a symbolic constant referring */
- /* to sizeof(pthread_cond_t). */
- drd_start_suppression(cond, cond + size, "cond");
- return &s_cond[i];
- }
- }
- tl_assert(0);
- return 0;
+ return p;
}
+struct cond_info* cond_get(const Addr cond)
+{
+ tl_assert(offsetof(DrdClientobj, cond) == 0);
+ return &drd_clientobj_get(cond, ClientCondvar)->cond;
+}
+
+/** Called before pthread_cond_init(). */
void cond_init(const Addr cond, const SizeT size)
{
if (s_trace_cond)
{
VG_(message)(Vg_UserMsg, "Initializing condition variable 0x%lx", cond);
- VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
- VG_(clo_backtrace_size));
+ VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size));
}
tl_assert(cond_get(cond) == 0);
tl_assert(size > 0);
cond_get_or_allocate(cond, size);
}
+/** Called after pthread_cond_destroy(). */
void cond_destroy(struct cond_info* const p)
{
if (s_trace_cond)
{
- VG_(message)(Vg_UserMsg, "Destroying condition variable 0x%lx", p->cond);
- VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
- VG_(clo_backtrace_size));
+ VG_(message)(Vg_UserMsg, "Destroying condition variable 0x%lx", p->a1);
+ VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), VG_(clo_backtrace_size));
}
// TO DO: print a proper error message if waiter_count != 0.
tl_assert(p->waiter_count == 0);
- drd_finish_suppression(p->cond, p->cond + p->size);
-
- p->cond = 0;
- p->waiter_count = 0;
- p->mutex = 0;
+ drd_clientobj_remove(p->a1, ClientCondvar);
}
-struct cond_info* cond_get(const Addr cond)
-{
- int i;
- for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
- if (s_cond[i].cond == cond)
- return &s_cond[i];
- return 0;
-}
-
+/** Called before pthread_cond_wait(). */
int cond_pre_wait(const Addr cond, const SizeT cond_size, const Addr mutex)
{
struct cond_info* p;
@@ -143,6 +153,7 @@
return ++p->waiter_count;
}
+/** Called after pthread_cond_wait(). */
int cond_post_wait(const Addr cond)
{
struct cond_info* p;
@@ -158,17 +169,12 @@
return p->waiter_count;
}
+/** Called before pthread_cond_signal(). */
void cond_pre_signal(Addr const cond)
{
const ThreadId vg_tid = VG_(get_running_tid)();
const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(vg_tid);
struct cond_info* const cond_p = cond_get(cond);
-#if 0
- VG_(message)(Vg_DebugMsg, "cond_pre_signal cond %d, w.c. %d, mutex %d",
- cond,
- cond_p ? cond_p->waiter_count : 0,
- cond_p ? cond_p->mutex : 0);
-#endif
if (cond_p && cond_p->waiter_count > 0)
{
if (! mutex_is_locked_by(cond_p->mutex, drd_tid))
@@ -190,23 +196,12 @@
}
}
+/** Called before pthread_cond_broadcast(). */
void cond_pre_broadcast(Addr const cond)
{
cond_pre_signal(cond);
}
+/** Called after pthread_cond_destroy(). */
void cond_thread_delete(const DrdThreadId tid)
{ }
-
-void cond_stop_using_mem(const Addr a1, const Addr a2)
-{
- unsigned i;
- for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
- {
- if (a1 <= s_cond[i].cond && s_cond[i].cond < a2)
- {
- tl_assert(s_cond[i].cond + s_cond[i].size <= a2);
- cond_destroy(&s_cond[i]);
- }
- }
-}