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.

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

Reply via email to