On Thu, Sep 17, 2026 at 11:23 AM Jonathan Wakely <[email protected]> wrote:
> On Thu, 17 Sept 2026 at 08:58, Tomasz Kaminski <[email protected]> > wrote: > > > > > > > > On Wed, Sep 16, 2026 at 5:09 PM Jonathan Wakely <[email protected]> > wrote: > >> > >> 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. > > > > One comment regarding a missing unmap in the error path, and an update > to the comment. > > Otherwise LGTM. > >> > >> > >> 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 <[email protected]>, Brad Garcia < > [email protected]> > >> 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 <[email protected]> > >> > >> @@ -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 <[email protected]> > >> > >> @@ -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 <[email protected]> > >> > >> @@ -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 <[email protected]> > >> > >> @@ -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 <[email protected]> > >> > >> @@ -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 <[email protected]> > >> > >> @@ -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 <[email protected]> > >> > >> @@ -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)) > > > > I think we need to separate this two cases, and call munmap(sem_, > sizeof(sem_t)), > > if mmap was successfull but sem_init failed. > > If we can't construct a semaphore the test will exit and the memory > mapping will be freed automatically, but I can make that change. > Yes, but at some point, an LLM scan will report this, and we will need to handle that; it's just easier to make the if. It have no impact on testsuite time, as we will be aborting anyway. > > >> > >> + 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. > > > > The comment above is no longer correct, as we have a way to mark a test > as unsupported. > > We still have no way to mark it unsupported *at runtime*. But we don't > need to, because we can mark it unsupported before compilation even > starts, so I'll clarify the comment. > > > > // There are no semaphores on this system, so fail the test, > to signal that it > > // should be marked as UNSUPPORTED. > >> > >> + // 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 > >> > >
