Added support for sem_open() and sem_close().
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10560 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/drd/drd_semaphore.c b/drd/drd_semaphore.c
index da3d867..f2e38e2 100644
--- a/drd/drd_semaphore.c
+++ b/drd/drd_semaphore.c
@@ -49,7 +49,7 @@
/* Function definitions. */
/** Push a segment at the end of the queue 'p->last_sem_post_seg'. */
-static void DRD_(segment_push)(struct semaphore_info* p, Segment* sg)
+static void drd_segment_push(struct semaphore_info* p, Segment* sg)
{
Word n;
@@ -63,7 +63,7 @@
}
/** Pop a segment from the beginning of the queue 'p->last_sem_post_seg'. */
-static Segment* DRD_(segment_pop)(struct semaphore_info* p)
+static Segment* drd_segment_pop(struct semaphore_info* p)
{
Word sz;
Segment* sg;
@@ -94,8 +94,8 @@
* client semaphore at client addres 'semaphore'.
*/
static
-void DRD_(semaphore_initialize)(struct semaphore_info* const p,
- const Addr semaphore)
+void drd_semaphore_initialize(struct semaphore_info* const p,
+ const Addr semaphore)
{
tl_assert(semaphore != 0);
tl_assert(p->a1 == semaphore);
@@ -129,7 +129,7 @@
" upon",
&sei);
}
- while ((sg = DRD_(segment_pop)(p)))
+ while ((sg = drd_segment_pop(p)))
DRD_(sg_put)(sg);
VG_(deleteXA)(p->last_sem_post_seg);
}
@@ -141,7 +141,7 @@
*/
static
struct semaphore_info*
-DRD_(semaphore_get_or_allocate)(const Addr semaphore)
+drd_semaphore_get_or_allocate(const Addr semaphore)
{
struct semaphore_info *p;
@@ -151,7 +151,7 @@
{
tl_assert(offsetof(DrdClientobj, semaphore) == 0);
p = &(DRD_(clientobj_add)(semaphore, ClientSemaphore)->semaphore);
- DRD_(semaphore_initialize)(p, semaphore);
+ drd_semaphore_initialize(p, semaphore);
}
return p;
}
@@ -193,14 +193,14 @@
"Semaphore reinitialization",
&SEI);
// Remove all segments from the segment stack.
- while ((sg = DRD_(segment_pop)(p)))
+ while ((sg = drd_segment_pop(p)))
{
DRD_(sg_put)(sg);
}
}
else
{
- p = DRD_(semaphore_get_or_allocate)(semaphore);
+ p = drd_semaphore_get_or_allocate(semaphore);
}
tl_assert(p);
p->waits_to_skip = value;
@@ -238,12 +238,89 @@
DRD_(clientobj_remove)(semaphore, ClientSemaphore);
}
+/** Called after sem_open(). */
+struct semaphore_info* DRD_(semaphore_open)(const Addr semaphore,
+ const Char* name, const Word oflag,
+ const Word mode, const UInt value)
+{
+ struct semaphore_info* p;
+ Segment* sg;
+
+ if (s_trace_semaphore)
+ {
+ VG_(message)(Vg_UserMsg,
+ "[%d] semaphore_open 0x%lx name %s"
+ " oflag %ld mode 0%lo value %u\n",
+ DRD_(thread_get_running_tid)(),
+ semaphore, name, oflag, mode, value);
+ }
+
+ /* Return if the sem_open() call failed. */
+ if (! semaphore)
+ return NULL;
+
+ p = semaphore_get(semaphore);
+ if (p)
+ {
+ const ThreadId vg_tid = VG_(get_running_tid)();
+ SemaphoreErrInfo SEI = { DRD_(thread_get_running_tid)(), semaphore };
+ VG_(maybe_record_error)(vg_tid,
+ SemaphoreErr,
+ VG_(get_IP)(vg_tid),
+ "Semaphore reinitialization",
+ &SEI);
+ // Remove all segments from the segment stack.
+ while ((sg = drd_segment_pop(p)))
+ {
+ DRD_(sg_put)(sg);
+ }
+ }
+ else
+ {
+ p = drd_semaphore_get_or_allocate(semaphore);
+ }
+ tl_assert(p);
+ p->waits_to_skip = value;
+ p->value = value;
+ return p;
+}
+
+/** Called before sem_close(). */
+void DRD_(semaphore_close)(const Addr semaphore)
+{
+ struct semaphore_info* p;
+
+ p = semaphore_get(semaphore);
+
+ if (s_trace_semaphore)
+ {
+ VG_(message)(Vg_UserMsg,
+ "[%d] semaphore_close 0x%lx value %u\n",
+ DRD_(thread_get_running_tid)(),
+ semaphore,
+ p ? p->value : 0);
+ }
+
+ if (p == 0)
+ {
+ GenericErrInfo GEI = { DRD_(thread_get_running_tid)() };
+ VG_(maybe_record_error)(VG_(get_running_tid)(),
+ GenericErr,
+ VG_(get_IP)(VG_(get_running_tid)()),
+ "Not a semaphore",
+ &GEI);
+ return;
+ }
+
+ DRD_(clientobj_remove)(semaphore, ClientSemaphore);
+}
+
/** Called before sem_wait(). */
void DRD_(semaphore_pre_wait)(const Addr semaphore)
{
struct semaphore_info* p;
- p = DRD_(semaphore_get_or_allocate)(semaphore);
+ p = drd_semaphore_get_or_allocate(semaphore);
tl_assert(p);
p->waiters++;
@@ -289,7 +366,7 @@
/*
* Note: if another thread destroyed and reinitialized a semaphore while
* the current thread was waiting in sem_wait, p->waiters may have been
- * set to zero by DRD_(semaphore_initialize)() after
+ * set to zero by drd_semaphore_initialize() after
* DRD_(semaphore_pre_wait)() has finished before
* DRD_(semaphore_post_wait)() has been called.
*/
@@ -308,7 +385,7 @@
p->waits_to_skip--;
else
{
- sg = DRD_(segment_pop)(p);
+ sg = drd_segment_pop(p);
tl_assert(sg);
if (sg)
{
@@ -331,7 +408,7 @@
struct semaphore_info* p;
Segment* sg;
- p = DRD_(semaphore_get_or_allocate)(semaphore);
+ p = drd_semaphore_get_or_allocate(semaphore);
p->value++;
if (s_trace_semaphore)
@@ -347,7 +424,7 @@
sg = 0;
DRD_(thread_get_latest_segment)(&sg, tid);
tl_assert(sg);
- DRD_(segment_push)(p, sg);
+ drd_segment_push(p, sg);
DRD_(thread_new_segment)(tid);
s_semaphore_segment_creation_count++;
}