Fixed bug in vector clock updating for semaphores with non-zero initial value.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8854 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/drd/drd_clientobj.h b/drd/drd_clientobj.h
index 98f4fd9..f9c9446 100644
--- a/drd/drd_clientobj.h
+++ b/drd/drd_clientobj.h
@@ -89,6 +89,7 @@
ObjType type;
void (*cleanup)(union drd_clientobj*);
ExeContext* first_observed_at;
+ UInt initial_value; // Value assigned through sem_init().
UInt value; // Semaphore value.
UWord waiters; // Number of threads inside sem_wait().
DrdThreadId last_sem_post_tid; // Thread ID associated with last sem_post().
diff --git a/drd/drd_semaphore.c b/drd/drd_semaphore.c
index 2cc59dc..df3c886 100644
--- a/drd/drd_semaphore.c
+++ b/drd/drd_semaphore.c
@@ -87,16 +87,16 @@
}
static
-void semaphore_initialize(struct semaphore_info* const p,
- const Addr semaphore, const UWord value)
+void semaphore_initialize(struct semaphore_info* const p, const Addr semaphore)
{
tl_assert(semaphore != 0);
tl_assert(p->a1 == semaphore);
tl_assert(p->type == ClientSemaphore);
- p->cleanup = (void(*)(DrdClientobj*))semaphore_cleanup;
- p->value = value;
- p->waiters = 0;
+ p->cleanup = (void(*)(DrdClientobj*))semaphore_cleanup;
+ p->initial_value = 0;
+ p->value = 0;
+ p->waiters = 0;
p->last_sem_post_tid = DRD_INVALID_THREADID;
p->last_sem_post_seg = VG_(newXA)(VG_(malloc), "drd.sg-stack",
VG_(free), sizeof(Segment*));
@@ -136,7 +136,7 @@
{
tl_assert(offsetof(DrdClientobj, semaphore) == 0);
p = &clientobj_add(semaphore, ClientSemaphore)->semaphore;
- semaphore_initialize(p, semaphore, 0);
+ semaphore_initialize(p, semaphore);
}
return p;
}
@@ -151,7 +151,10 @@
struct semaphore_info* semaphore_init(const Addr semaphore,
const Word pshared, const UInt value)
{
+ unsigned n;
struct semaphore_info* p;
+ Segment* sg;
+ const DrdThreadId drd_tid = thread_get_running_tid();
if (s_trace_semaphore)
{
@@ -172,13 +175,19 @@
VG_(get_IP)(vg_tid),
"Semaphore reinitialization",
&SEI);
+ // Remove all segments from the segment stack.
+ while ((sg = segment_pop(p)))
+ {
+ sg_put(sg);
+ }
}
else
{
p = semaphore_get_or_allocate(semaphore);
}
tl_assert(p);
- p->value = value;
+ p->initial_value = value;
+ p->value = value;
return p;
}
@@ -263,17 +272,23 @@
}
p->value--;
tl_assert((int)p->value >= 0);
- sg = segment_pop(p);
- if (sg)
+ if (p->initial_value > 0)
+ p->initial_value--;
+ else
{
- if (p->last_sem_post_tid != tid
- && p->last_sem_post_tid != DRD_INVALID_THREADID)
+ sg = segment_pop(p);
+ tl_assert(sg);
+ if (sg)
{
- thread_combine_vc2(tid, &sg->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++;
}
- sg_put(sg);
- thread_new_segment(tid);
- s_semaphore_segment_creation_count++;
}
}