Fixed semaphore vector clock updating / simplified semaphore tracing.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8836 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/drd/drd_semaphore.c b/drd/drd_semaphore.c
index 0f16305..2cc59dc 100644
--- a/drd/drd_semaphore.c
+++ b/drd/drd_semaphore.c
@@ -31,6 +31,7 @@
#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_threadstate.h" // VG_(get_running_tid)()
@@ -47,6 +48,39 @@
// Function definitions.
+static void segment_push(struct semaphore_info* p, Segment* sg)
+{
+ Word n;
+
+ tl_assert(sg);
+ n = VG_(addToXA)(p->last_sem_post_seg, &sg);
+#if 0
+ VG_(message)(Vg_UserMsg, "0x%lx push: added at position %ld/%ld",
+ p->a1, n, VG_(sizeXA)(p->last_sem_post_seg));
+#endif
+ tl_assert(*(Segment**)VG_(indexXA)(p->last_sem_post_seg, n) == sg);
+}
+
+static Segment* segment_pop(struct semaphore_info* p)
+{
+ Word sz;
+ Segment* sg;
+
+ sz = VG_(sizeXA)(p->last_sem_post_seg);
+#if 0
+ VG_(message)(Vg_UserMsg, "0x%lx pop: removed from position %ld/%ld",
+ p->a1, sz - 1, sz);
+#endif
+ sg = 0;
+ if (sz > 0)
+ {
+ sg = *(Segment**)VG_(indexXA)(p->last_sem_post_seg, sz - 1);
+ tl_assert(sg);
+ VG_(dropTailXA)(p->last_sem_post_seg, 1);
+ }
+ return sg;
+}
+
void semaphore_set_trace(const Bool trace_semaphore)
{
s_trace_semaphore = trace_semaphore;
@@ -64,7 +98,8 @@
p->value = value;
p->waiters = 0;
p->last_sem_post_tid = DRD_INVALID_THREADID;
- p->last_sem_post_segment = 0;
+ p->last_sem_post_seg = VG_(newXA)(VG_(malloc), "drd.sg-stack",
+ VG_(free), sizeof(Segment*));
}
/** Free the memory that was allocated by semaphore_initialize(). Called by
@@ -72,6 +107,8 @@
*/
static void semaphore_cleanup(struct semaphore_info* p)
{
+ Segment* sg;
+
if (p->waiters > 0)
{
SemaphoreErrInfo sei = { p->a1 };
@@ -82,7 +119,9 @@
" upon",
&sei);
}
- sg_put(p->last_sem_post_segment);
+ while ((sg = segment_pop(p)))
+ sg_put(sg);
+ VG_(deleteXA)(p->last_sem_post_seg);
}
static
@@ -180,15 +219,6 @@
struct semaphore_info* p;
p = semaphore_get_or_allocate(semaphore);
- if (s_trace_semaphore)
- {
- VG_(message)(Vg_UserMsg,
- "[%d/%d] semaphore_pre_wait 0x%lx value %u",
- VG_(get_running_tid)(),
- thread_get_running_tid(),
- semaphore,
- p->value);
- }
tl_assert(p);
tl_assert((int)p->waiters >= 0);
p->waiters++;
@@ -203,17 +233,20 @@
const Bool waited)
{
struct semaphore_info* p;
+ Segment* sg;
p = semaphore_get(semaphore);
if (s_trace_semaphore)
{
VG_(message)(Vg_UserMsg,
- "[%d/%d] semaphore_post_wait 0x%lx value %u",
+ "[%d/%d] semaphore_wait 0x%lx value %u -> %u",
VG_(get_running_tid)(),
thread_get_running_tid(),
semaphore,
+ p ? p->value : 0,
p ? p->value - 1 : 0);
}
+ tl_assert(p);
tl_assert(p->waiters > 0);
p->waiters--;
tl_assert((int)p->waiters >= 0);
@@ -230,20 +263,25 @@
}
p->value--;
tl_assert((int)p->value >= 0);
- if (p->last_sem_post_tid != tid
- && p->last_sem_post_tid != DRD_INVALID_THREADID)
+ sg = segment_pop(p);
+ if (sg)
{
- tl_assert(p->last_sem_post_segment);
- thread_combine_vc2(tid, &p->last_sem_post_segment->vc);
+ if (p->last_sem_post_tid != tid
+ && p->last_sem_post_tid != DRD_INVALID_THREADID)
+ {
+ thread_combine_vc2(tid, &sg->vc);
+ }
+ sg_put(sg);
+ thread_new_segment(tid);
+ s_semaphore_segment_creation_count++;
}
- thread_new_segment(tid);
- s_semaphore_segment_creation_count++;
}
/** Called before sem_post(). */
void semaphore_pre_post(const DrdThreadId tid, const Addr semaphore)
{
struct semaphore_info* p;
+ Segment* sg;
p = semaphore_get_or_allocate(semaphore);
p->value++;
@@ -251,20 +289,20 @@
if (s_trace_semaphore)
{
VG_(message)(Vg_UserMsg,
- "[%d/%d] semaphore_post 0x%lx value %u",
+ "[%d/%d] semaphore_post 0x%lx value %u -> %u",
VG_(get_running_tid)(),
thread_get_running_tid(),
semaphore,
- p->value);
+ p->value - 1, p->value);
}
- if (p->value == 1)
- {
- p->last_sem_post_tid = tid;
- thread_new_segment(tid);
- thread_get_latest_segment(&p->last_sem_post_segment, tid);
- s_semaphore_segment_creation_count++;
- }
+ p->last_sem_post_tid = tid;
+ thread_new_segment(tid);
+ sg = 0;
+ thread_get_latest_segment(&sg, tid);
+ tl_assert(sg);
+ segment_push(p, sg);
+ s_semaphore_segment_creation_count++;
}
/** Called after sem_post() finished successfully. */