#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
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