[PATCH] libstdc++: Make __gnu_test::semaphore work without SysV semget [PR127425]
Jonathan Wakely
jwakely@redhat.com
Wed Sep 16 15:04:01 GMT 2026
Port the testsuite's simple semaphore type to use POSIX semaphores when
System V semaphores are not supported, as the latter are part of the XSI
option and not mandated by POSIX. For the POSIX semaphore path we need
to use mmap to create the semaphore in shared memory and also need to
handle older systems without MAP_ANONYMOUS support. We need to use
unnamed semaphores because using sem_open to create a named semaphore
requires creating two or more unique names per test that work even when
the tests are run in parallel.
Although it might make sense to prefer the new path and use POSIX
semaphores by default, but macOS defines _POSIX_SEMAPHORES to a positive
value but its sem_init always returns ENOSYS at runtime. Instead of
trying that and then switching to shmget as a runtime fallback, we might
as well just continue using the code that we know works fine - i.e. the
SysV semaphore implementation.
For the case where neither SysV nor POSIX semaphores are available, make
the __gnu_test::semaphore constructor abort, so the tests FAIL instead
of silently PASS.
Move the definition of the semaphore to a new header, so that it's only
defined in the handful of tests that actually use it, and the
definitions of the member functions to a new file.
Also add a dejagnu dg-require-sysv-or-posix-semaphore directive so that
tests which don't support either type of semaphore will be UNSUPPORTED
instead of PASS (or FAIL with the new aborting constructor). This test
uses _XOPEN_UNIX rather than the three autoconf macros that are checked
in testsuite_semaphore.cc but that is a reasonable proxy for SysV
semaphore support. It might mean that some very old systems mark those
tests as UNSUPPORTED when they do actually support the SysV semaphores
without defining the _XOPEN_UNIX macro. I can live with that.
libstdc++-v3/ChangeLog:
PR libstdc++/127425
* doc/xml/manual/test.xml: Document new testsuite header.
* doc/html/manual/test.html: Regenerate.
* testsuite/27_io/basic_filebuf/close/char/4879.cc: Use new
dg-require-sysv-or-posix-semaphore directive.
* testsuite/27_io/basic_filebuf/close/char/9964.cc: Likewise.
* testsuite/27_io/basic_filebuf/imbue/char/13171-2.cc: Likewise.
* testsuite/27_io/basic_filebuf/imbue/wchar_t/14975-2.cc:
Likewise.
* testsuite/27_io/basic_filebuf/seekoff/char/26777.cc: Likewise.
* testsuite/27_io/basic_filebuf/underflow/char/10097.cc:
Likewise.
* testsuite/27_io/objects/char/7.cc: Likewise.
* testsuite/27_io/objects/char/9661-1.cc: Likewise.
* testsuite/27_io/objects/wchar_t/7.cc: Likewise.
* testsuite/27_io/objects/wchar_t/9661-1.cc: Likewise.
* testsuite/lib/dg-options.exp
(dg-require-sysv-or-posix-semaphore): New proc.
* testsuite/lib/libstdc++.exp (v3-build_support): Add new file
to list of testsuite source files.
(check_v3_target_posix_or_sysv_semaphore): New proc.
* testsuite/util/testsuite_hooks.cc (semaphore): Move to new
file.
* testsuite/util/testsuite_hooks.h (semaphore): Likewise.
* testsuite/util/testsuite_semaphore.cc: Move definition of
semaphore member functions here. Fix resource leak in
constructor if semctl fails. Prefer to use mmap+sem_init instead
of semget+semctl.
* testsuite/util/testsuite_semaphore.h: Move definition of
semaphore to here.
---
Tested 27_io/* on x86_64-linux and the rest of the testsuite is running
now.
libstdc++-v3/doc/html/manual/test.html | 6 +-
libstdc++-v3/doc/xml/manual/test.xml | 8 +
.../27_io/basic_filebuf/close/char/4879.cc | 2 +
.../27_io/basic_filebuf/close/char/9964.cc | 2 +
.../27_io/basic_filebuf/imbue/char/13171-2.cc | 2 +
.../basic_filebuf/imbue/wchar_t/14975-2.cc | 2 +
.../27_io/basic_filebuf/seekoff/char/26777.cc | 2 +
.../basic_filebuf/underflow/char/10097.cc | 2 +
.../testsuite/27_io/objects/char/7.cc | 2 +
.../testsuite/27_io/objects/char/9661-1.cc | 2 +
.../testsuite/27_io/objects/wchar_t/7.cc | 2 +
.../testsuite/27_io/objects/wchar_t/9661-1.cc | 2 +
libstdc++-v3/testsuite/lib/dg-options.exp | 9 ++
libstdc++-v3/testsuite/lib/libstdc++.exp | 11 ++
.../testsuite/util/testsuite_hooks.cc | 96 -----------
libstdc++-v3/testsuite/util/testsuite_hooks.h | 24 ---
.../testsuite/util/testsuite_semaphore.cc | 153 ++++++++++++++++++
.../testsuite/util/testsuite_semaphore.h | 62 +++++++
18 files changed, 268 insertions(+), 121 deletions(-)
create mode 100644 libstdc++-v3/testsuite/util/testsuite_semaphore.cc
create mode 100644 libstdc++-v3/testsuite/util/testsuite_semaphore.h
diff --git a/libstdc++-v3/doc/html/manual/test.html b/libstdc++-v3/doc/html/manual/test.html
index 404d7ddbf879..1db7dd5bcae7 100644
--- a/libstdc++-v3/doc/html/manual/test.html
+++ b/libstdc++-v3/doc/html/manual/test.html
@@ -647,7 +647,11 @@ only default variables.
</p><p>
A number of class abstractions for performance counters, and
reporting functions including:
- </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>time_counter</p></li><li class="listitem"><p>resource_counter</p></li><li class="listitem"><p>report_performance</p></li></ul></div></li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="test.special"></a>Special Topics</h3></div></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="test.exception.safety"></a>
+ </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>time_counter</p></li><li class="listitem"><p>resource_counter</p></li><li class="listitem"><p>report_performance</p></li></ul></div></li><li class="listitem"><p>
+ <span class="emphasis"><em>testsuite_semaphore.h</em></span>
+ </p><p>
+ A simple binary semaphore used for some multi-process I/O tests.
+ </p></li></ul></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="test.special"></a>Special Topics</h3></div></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="test.exception.safety"></a>
Qualifying Exception Safety Guarantees
<a id="id-1.3.6.3.5.7.2.1.1.1" class="indexterm"></a>
</h4></div></div></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="test.exception.safety.overview"></a>Overview</h5></div></div></div><p>
diff --git a/libstdc++-v3/doc/xml/manual/test.xml b/libstdc++-v3/doc/xml/manual/test.xml
index 68b5f8aedb41..f5c441bd9413 100644
--- a/libstdc++-v3/doc/xml/manual/test.xml
+++ b/libstdc++-v3/doc/xml/manual/test.xml
@@ -1081,6 +1081,14 @@ only default variables.
<listitem><para>report_performance</para></listitem>
</itemizedlist>
</listitem>
+ <listitem>
+ <para>
+ <emphasis>testsuite_semaphore.h</emphasis>
+ </para>
+ <para>
+ A simple binary semaphore used for some multi-process I/O tests.
+ </para>
+ </listitem>
</itemizedlist>
</section>
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/4879.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/4879.cc
index 3e0b134edb95..5246a33e8493 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/4879.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/4879.cc
@@ -1,5 +1,6 @@
// { dg-require-fork "" }
// { dg-require-mkfifo "" }
+// { dg-require-sysv-or-posix-semaphore "" }
// Copyright (C) 2001-2026 Free Software Foundation, Inc.
//
@@ -33,6 +34,7 @@
#include <sys/stat.h>
#include <testsuite_hooks.h>
+#include <testsuite_semaphore.h>
// libstdc++/2913, libstdc++/4879
// John Fardo <jfardo@laurelnetworks.com>, Brad Garcia <garsh@attbi.com>
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/9964.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/9964.cc
index ba864fa7e9e8..84b406ac0727 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/9964.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/close/char/9964.cc
@@ -1,5 +1,6 @@
// { dg-require-fork "" }
// { dg-require-mkfifo "" }
+// { dg-require-sysv-or-posix-semaphore "" }
// Copyright (C) 2001-2026 Free Software Foundation, Inc.
//
@@ -32,6 +33,7 @@
#include <sys/stat.h>
#include <testsuite_hooks.h>
+#include <testsuite_semaphore.h>
// libstdc++/9964
bool test_07()
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/13171-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/13171-2.cc
index 5a42e18834b0..210efae9a98a 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/13171-2.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/13171-2.cc
@@ -2,6 +2,7 @@
// { dg-require-namedlocale "en_US.ISO8859-1" }
// { dg-require-fork "" }
// { dg-require-mkfifo "" }
+// { dg-require-sysv-or-posix-semaphore "" }
// Copyright (C) 2003-2026 Free Software Foundation, Inc.
//
@@ -30,6 +31,7 @@
#include <sys/stat.h>
#include <testsuite_hooks.h>
+#include <testsuite_semaphore.h>
// libstdc++/13171
bool test01()
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/14975-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/14975-2.cc
index f4dadd917ee9..886b7d66053b 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/14975-2.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/14975-2.cc
@@ -1,6 +1,7 @@
// { dg-require-namedlocale "en_US.ISO8859-1" }
// { dg-require-fork "" }
// { dg-require-mkfifo "" }
+// { dg-require-sysv-or-posix-semaphore "" }
// 2004-04-16 Petur Runolfsson <peturr02@ru.is>
@@ -31,6 +32,7 @@
#include <sys/stat.h>
#include <testsuite_hooks.h>
+#include <testsuite_semaphore.h>
// libstdc++/14975
bool test01()
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/26777.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/26777.cc
index b003090f920c..1931db09ad04 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/26777.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/26777.cc
@@ -1,5 +1,6 @@
// { dg-require-fork "" }
// { dg-require-mkfifo "" }
+// { dg-require-sysv-or-posix-semaphore "" }
// 2006-03-22 Paolo Carlini <pcarlini@suse.de>
@@ -21,6 +22,7 @@
// <http://www.gnu.org/licenses/>.
#include <testsuite_hooks.h>
+#include <testsuite_semaphore.h>
#include <fstream>
#include <sstream>
#include <cstdlib>
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/char/10097.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/char/10097.cc
index e7c9a91aca04..c320b99920bd 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/char/10097.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/underflow/char/10097.cc
@@ -1,5 +1,6 @@
// { dg-require-fork "" }
// { dg-require-mkfifo "" }
+// { dg-require-sysv-or-posix-semaphore "" }
// 2001-05-21 Benjamin Kosnik <bkoz@redhat.com>
@@ -31,6 +32,7 @@
#include <sys/stat.h>
#include <testsuite_hooks.h>
+#include <testsuite_semaphore.h>
class UnderBuf : public std::filebuf
{
diff --git a/libstdc++-v3/testsuite/27_io/objects/char/7.cc b/libstdc++-v3/testsuite/27_io/objects/char/7.cc
index b5e6fe5b6d7b..2edcf56f7889 100644
--- a/libstdc++-v3/testsuite/27_io/objects/char/7.cc
+++ b/libstdc++-v3/testsuite/27_io/objects/char/7.cc
@@ -1,5 +1,6 @@
// { dg-require-fork "" }
// { dg-require-mkfifo "" }
+// { dg-require-sysv-or-posix-semaphore "" }
// 2003-04-26 Petur Runolfsson <peturr02@ru.is>
@@ -31,6 +32,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <testsuite_hooks.h>
+#include <testsuite_semaphore.h>
// Check that cout.flush() is called when last ios_base::Init is destroyed.
bool test07()
diff --git a/libstdc++-v3/testsuite/27_io/objects/char/9661-1.cc b/libstdc++-v3/testsuite/27_io/objects/char/9661-1.cc
index d9e39cd80c83..9374685969db 100644
--- a/libstdc++-v3/testsuite/27_io/objects/char/9661-1.cc
+++ b/libstdc++-v3/testsuite/27_io/objects/char/9661-1.cc
@@ -1,5 +1,6 @@
// { dg-require-fork "" }
// { dg-require-mkfifo "" }
+// { dg-require-sysv-or-posix-semaphore "" }
// 2003-04-30 Petur Runolfsson <peturr02@ru.is>
@@ -21,6 +22,7 @@
// <http://www.gnu.org/licenses/>.
#include <testsuite_hooks.h>
+#include <testsuite_semaphore.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
diff --git a/libstdc++-v3/testsuite/27_io/objects/wchar_t/7.cc b/libstdc++-v3/testsuite/27_io/objects/wchar_t/7.cc
index 2c03fa1791b9..cc6a2fa3e7d0 100644
--- a/libstdc++-v3/testsuite/27_io/objects/wchar_t/7.cc
+++ b/libstdc++-v3/testsuite/27_io/objects/wchar_t/7.cc
@@ -1,5 +1,6 @@
// { dg-require-fork "" }
// { dg-require-mkfifo "" }
+// { dg-require-sysv-or-posix-semaphore "" }
// 2003-05-01 Petur Runolfsson <peturr02@ru.is>
@@ -32,6 +33,7 @@
#include <sys/stat.h>
#include <testsuite_hooks.h>
+#include <testsuite_semaphore.h>
// Check that wcout.flush() is called when last ios_base::Init is destroyed.
bool test07()
diff --git a/libstdc++-v3/testsuite/27_io/objects/wchar_t/9661-1.cc b/libstdc++-v3/testsuite/27_io/objects/wchar_t/9661-1.cc
index f49d010fbf91..f8194aef3eec 100644
--- a/libstdc++-v3/testsuite/27_io/objects/wchar_t/9661-1.cc
+++ b/libstdc++-v3/testsuite/27_io/objects/wchar_t/9661-1.cc
@@ -1,5 +1,6 @@
// { dg-require-fork "" }
// { dg-require-mkfifo "" }
+// { dg-require-sysv-or-posix-semaphore "" }
// 2003-04-30 Petur Runolfsson <peturr02@ru.is>
@@ -21,6 +22,7 @@
// <http://www.gnu.org/licenses/>.
#include <testsuite_hooks.h>
+#include <testsuite_semaphore.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp
index 615a57992602..d8f31aae7387 100644
--- a/libstdc++-v3/testsuite/lib/dg-options.exp
+++ b/libstdc++-v3/testsuite/lib/dg-options.exp
@@ -286,6 +286,15 @@ proc dg-require-cpp-feature-test { n args } {
return
}
+proc dg-require-sysv-or-posix-semaphore { n args } {
+ if { ![ check_v3_target_posix_or_sysv_semaphore $args ] } {
+ upvar dg-do-what dg-do-what
+ set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+ return
+ }
+ return
+}
+
proc add_options_for_no_pch { flags } {
# Remove any inclusion of bits/stdc++.h from the options.
regsub -all -- "-include bits/stdc...h" $flags "" flags
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index cda231246cb0..4a11c9b47dd3 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -835,6 +835,7 @@ proc v3-build_support { } {
# Build the support objects.
set source_files [list testsuite_abi.cc testsuite_allocator.cc \
testsuite_character.cc testsuite_hooks.cc \
+ testsuite_semaphore.cc \
io/verified_cmd_line_input.cc \
io/prog_bar.cc performance/time/elapsed_timer.cc ]
foreach f $source_files {
@@ -1440,6 +1441,16 @@ proc check_v3_target_nprocs { } {
}]
}
+# Return 1 if the POSIX REALTIME option or the XSI option is supported
+# for the current target, 0 otherwise.
+proc check_v3_target_posix_or_sysv_semaphore { cond } {
+ set name "posix_or_sysv_semaphore"
+ set inc "#include <unistd.h>"
+ set cond "_POSIX_SEMAPHORES > 0 || _XOPEN_UNIX > 0"
+ set result [v3_check_preprocessor_condition $name $cond $inc]
+ return $result
+}
+
# Return 1 if linking with -static-libstdc++ works, 0 otherwise.
proc check_v3_target_static_libstdcxx { } {
return [check_v3_target_prop_cached et_static_libstdcxx {
diff --git a/libstdc++-v3/testsuite/util/testsuite_hooks.cc b/libstdc++-v3/testsuite/util/testsuite_hooks.cc
index 946bd4a3847a..33ce7112701a 100644
--- a/libstdc++-v3/testsuite/util/testsuite_hooks.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_hooks.cc
@@ -36,20 +36,6 @@
#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
@@ -227,88 +213,6 @@ namespace __gnu_test
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
- // Remember 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)
- std::__throw_runtime_error("could not obtain semaphore set");
-
- // Initialize the semaphore.
- union semun val;
- val.val = 0;
- if (semctl(sem_set_, 0, SETVAL, val) == -1)
- std::__throw_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;
- val.val = 0; // Avoid uninitialized variable warning.
- // 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)
- std::__throw_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)
- std::__throw_runtime_error("could not wait for semaphore");
-#endif
- }
-
// For use in 22_locale/time_get and time_put.
std::tm
test_tm(int sec, int min, int hour, int mday, int mon,
diff --git a/libstdc++-v3/testsuite/util/testsuite_hooks.h b/libstdc++-v3/testsuite/util/testsuite_hooks.h
index 49e8f0fe30bf..9d7bec18aa6f 100644
--- a/libstdc++-v3/testsuite/util/testsuite_hooks.h
+++ b/libstdc++-v3/testsuite/util/testsuite_hooks.h
@@ -335,30 +335,6 @@ namespace __gnu_test
}
};
- // A binary semaphore for use across multiple processes.
- class semaphore
- {
- public:
- // Creates a binary semaphore. The semaphore is initially in the
- // unsignaled state.
- semaphore();
-
- // Destroy the semaphore.
- ~semaphore();
-
- // Signal the semaphore. If there are processes blocked in
- // "wait", exactly one will be permitted to proceed.
- void signal();
-
- // Wait until the semaphore is signaled.
- void wait();
-
- private:
- int sem_set_;
-
- pid_t pid_;
- };
-
// For use in 22_locale/time_get and time_put.
std::tm test_tm(int sec, int min, int hour, int mday, int mon,
int year, int wday, int yday, int isdst);
diff --git a/libstdc++-v3/testsuite/util/testsuite_semaphore.cc b/libstdc++-v3/testsuite/util/testsuite_semaphore.cc
new file mode 100644
index 000000000000..23bfba8af4cd
--- /dev/null
+++ b/libstdc++-v3/testsuite/util/testsuite_semaphore.cc
@@ -0,0 +1,153 @@
+// -*- C++ -*-
+
+// Semaphore type for the C++ library testsuite.
+//
+// Copyright (C) 2005-2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#include "testsuite_semaphore.h"
+#include <bits/stdexcept_throw.h>
+
+#if defined(_GLIBCXX_HAVE_SYS_TYPES_H) \
+ && defined(_GLIBCXX_HAVE_SYS_IPC_H) \
+ && defined(_GLIBCXX_HAVE_SYS_SEM_H)
+// If we have <sys/types.h>, <sys/ipc.h>, and <sys/sem.h>, then assume
+// that System V semaphores are available.
+# include <sys/types.h>
+# include <sys/ipc.h>
+# include <sys/sem.h>
+# define _GLIBCXX_SYSV_SEM
+#elif defined(_POSIX_SEMAPHORES) && _POSIX_SEMAPHORES > 0
+# include <semaphore.h> // sem_init, sem_post etc.
+# include <sys/mman.h> // mmap, MAP_SHARED etc.
+# include <errno.h> // EINTR
+# include <fcntl.h> // open, O_RDWR
+# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+# define MAP_ANONYMOUS MAP_ANON
+# endif
+# define _GLIBCXX_POSIX_SEM
+#else
+# include <stdlib.h> // abort
+#endif
+
+namespace __gnu_test
+{
+#ifdef _GLIBCXX_SYSV_SEM
+ // This union is not declared in system headers. Instead, it must
+ // be defined by user programs.
+ union semun
+ {
+ int val = 0;
+ struct semid_ds *buf;
+ unsigned short *array;
+ };
+
+ static void
+ destroy_semset(int set)
+ {
+ semctl(set, 0, IPC_RMID, semun{});
+ }
+#endif
+
+ semaphore::semaphore()
+ {
+#ifdef _GLIBCXX_SYSV_SEM
+ // Get a semaphore set with one semaphore.
+ sem_set_ = semget(IPC_PRIVATE, 1, 0600);
+ if (sem_set_ == -1)
+ std::__throw_runtime_error("could not obtain semaphore set");
+
+ // Initialize the semaphore.
+ if (semctl(sem_set_, 0, SETVAL, semun{}) == -1)
+ {
+ destroy_semset(sem_set_);
+ std::__throw_runtime_error("could not initialize semaphore");
+ }
+#elif defined _GLIBCXX_POSIX_SEM
+#ifdef MAP_ANONYMOUS
+ sem_ = mmap(nullptr, sizeof(sem_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+#else
+ int fd = open("/dev/zero", O_RDWR);
+ if (fd == -1)
+ std::__throw_runtime_error("could not open /dev/zero");
+ sem_ = mmap(nullptr, sizeof(sem_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ close(fd);
+#endif
+ if (sem_ == MAP_FAILED || sem_init((sem_t*)sem_, 1, 0))
+ std::__throw_runtime_error("could not create mmap'd semaphore");
+#else
+ // There are no semaphores on this system. We have no way to mark
+ // a test as "unsupported" at runtime, so we just fail the test.
+ // Use { dg-require-sysv-or-posix-semaphore "" } to make tests UNSUPPORTED.
+ abort();
+#endif
+
+ // Remember the PID for the process that created the semaphore
+ // so that only one process will destroy it.
+ pid_ = getpid();
+ }
+
+ semaphore::~semaphore()
+ {
+ // Destroy the semaphore set only in the process that created it.
+#ifdef _GLIBCXX_SYSV_SEM
+ if (pid_ == getpid())
+ destroy_semset(sem_set_);
+#elif defined _GLIBCXX_POSIX_SEM
+ if (pid_ == getpid())
+ sem_destroy((sem_t*)sem_);
+ munmap(sem_, sizeof(sem_t));
+#endif
+ }
+
+ void
+ semaphore::signal()
+ {
+#ifdef _GLIBCXX_SYSV_SEM
+ struct sembuf op[1] = { };
+ op[0].sem_op = 1;
+ if (semop(sem_set_, op, 1) == -1)
+ std::__throw_runtime_error("could not signal semaphore");
+#elif defined _GLIBCXX_POSIX_SEM
+ if (sem_post((sem_t*)sem_))
+ std::__throw_runtime_error("could not signal semaphore");
+#endif
+ }
+
+ void
+ semaphore::wait()
+ {
+#ifdef _GLIBCXX_SYSV_SEM
+ struct sembuf op[1] = { };
+ op[0].sem_op = -1;
+ op[0].sem_flg = SEM_UNDO;
+ if (semop(sem_set_, op, 1) == -1)
+ std::__throw_runtime_error("could not wait for semaphore");
+#elif defined _GLIBCXX_POSIX_SEM
+ while (true)
+ {
+ if (sem_wait((sem_t*)sem_) == 0)
+ return;
+ if (errno != EINTR)
+ std::__throw_runtime_error("could not wait for semaphore");
+ }
+#endif
+ }
+} // namespace __gnu_test
diff --git a/libstdc++-v3/testsuite/util/testsuite_semaphore.h b/libstdc++-v3/testsuite/util/testsuite_semaphore.h
new file mode 100644
index 000000000000..99e2e453668b
--- /dev/null
+++ b/libstdc++-v3/testsuite/util/testsuite_semaphore.h
@@ -0,0 +1,62 @@
+// -*- C++ -*-
+// Semaphore type for the C++ library testsuite.
+//
+// Copyright (C) 2005-2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#ifndef _GLIBCXX_TESTSUITE_SEMAPHORE_H
+#define _GLIBCXX_TESTSUITE_SEMAPHORE_H
+
+#include <bits/c++config.h>
+
+#ifdef _GLIBCXX_HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+namespace __gnu_test
+{
+ // A binary semaphore for use across multiple processes.
+ class semaphore
+ {
+ public:
+ // Creates a binary semaphore. The semaphore is initially in the
+ // unsignaled state.
+ semaphore();
+
+ // Destroy the semaphore.
+ ~semaphore();
+
+ // Signal the semaphore. If there are processes blocked in
+ // "wait", exactly one will be permitted to proceed.
+ void signal();
+
+ // Wait until the semaphore is signaled.
+ void wait();
+
+ private:
+ union {
+ int sem_set_;
+ void* sem_;
+ };
+ pid_t pid_;
+ };
+
+} // namespace __gnu_test
+
+#endif // _GLIBCXX_TESTSUITE_SEMAPHORE_H
+
--
2.55.0
More information about the Libstdc++
mailing list