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++;
 }