[PATCH] libstdc++: Make __gnu_test::semaphore work without SysV semget [PR127425]
Tomasz Kaminski
tkaminsk@redhat.com
Thu Sep 17 10:30:00 GMT 2026
On Thu, Sep 17, 2026 at 11:23 AM Jonathan Wakely <jwakely@redhat.com> wrote:
> On Thu, 17 Sept 2026 at 08:58, Tomasz Kaminski <tkaminsk@redhat.com>
> wrote:
> >
> >
> >
> > On Wed, Sep 16, 2026 at 5:09 PM Jonathan Wakely <jwakely@redhat.com>
> 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 <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))
> >
> > 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
> >>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260917/6c919f90/attachment-0001.htm>
More information about the Libstdc++
mailing list