OSDN Git Service

* configure.ac: Check for sys/ipc.h and sys/sem.h.
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / testsuite / testsuite_hooks.cc
index f503979..e4cf7fd 100644 (file)
 #include <locale>
 #include <cxxabi.h>
 
+// If we have <sys/types.h>, <sys/ipc.h>, and <sys/sem.h>, then assume
+// that System V semaphores are available.
+#if defined(_GLIBCXX_HAVE_SYS_TYPES_H)         \
+    && defined(_GLIBCXX_HAVE_SYS_IPC_H)                \
+    && defined(_GLIBCXX_HAVE_SYS_SEM_H)
+#define _GLIBCXX_SYSV_SEM
+#endif
+
+#ifdef _GLIBCXX_SYSV_SEM
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#endif
+
 namespace __gnu_test
 {
 #ifdef _GLIBCXX_RES_LIMITS
@@ -252,6 +266,84 @@ namespace __gnu_test
   unsigned int assignment_operator::throw_on_ = 0;
   unsigned int destructor::_M_count = 0;
   int copy_tracker::next_id_ = 0;
+
+#ifdef _GLIBCXX_SYSV_SEM
+  // This union is not declared in system headers.  Instead, it must
+  // be defined by user programs.
+  union semun 
+  {
+    int val;
+    struct semid_ds *buf;
+    unsigned short *array;
+  };
+#endif
+
+  semaphore::semaphore ()
+  {
+#ifdef _GLIBCXX_SYSV_SEM
+    // Remeber the PID for the process that created the semaphore set
+    // so that only one process will destroy the set.
+    pid_ = getpid();
+
+    // GLIBC does not define SEM_R and SEM_A.
+#ifndef SEM_R
+#define SEM_R 0400
+#endif
+    
+#ifndef SEM_A
+#define SEM_A 0200
+#endif
+
+    // Get a semaphore set with one semaphore.
+    sem_set_ = semget (IPC_PRIVATE, 1, SEM_R | SEM_A);
+    if (sem_set_ == -1)
+      throw std::runtime_error ("could not obtain semaphore set");
+
+    // Initialize the semaphore.
+    union semun val;
+    val.val = 0;
+    if (semctl (sem_set_, 0, SETVAL, val) == -1)
+      throw std::runtime_error ("could not initialize semaphore");
+#else
+    // There are no semaphores on this system.  We have no way to mark
+    // a test as "unsupported" at runtime, so we just exit, pretending
+    // that the test passed.
+    exit (0);
+#endif
+  }
+
+  semaphore::~semaphore ()
+  {
+#ifdef _GLIBCXX_SYSV_SEM
+    union semun val;
+    // Destroy the semaphore set only in the process that created it. 
+    if (pid_ == getpid ())
+      semctl (sem_set_, 0, IPC_RMID, val);
+#endif
+  }
+
+  void
+  semaphore::signal ()
+  {
+#ifdef _GLIBCXX_SYSV_SEM
+    struct sembuf op[1] = {
+      { 0, 1, 0 }
+    };
+    if (semop (sem_set_, op, 1) == -1)
+      throw std::runtime_error ("could not signal semaphore");
+#endif
+  }
+
+  void
+  semaphore::wait() {
+#ifdef _GLIBCXX_SYSV_SEM
+    struct sembuf op[1] = {
+      { 0, -1, SEM_UNDO }
+    };
+    if (semop (sem_set_, op, 1) == -1)
+      throw std::runtime_error ("could not wait for semaphore");
+#endif    
+  }
 }; // namespace __gnu_test
 
 namespace std