https://gcc.gnu.org/g:e0525a6d2bba07d623424ab6f10a023de90e65a2

commit r16-4426-ge0525a6d2bba07d623424ab6f10a023de90e65a2
Author: Mike Crowe <[email protected]>
Date:   Sun Sep 14 21:21:28 2025 +0100

    libstdc++: Add std::binary_semaphore tests for negative timeouts [PR116586]
    
    Add test cases to prove that negative timeouts are correctly handled by
    std::binary_semaphore (which is just an alias for
    std::counting_semaphore<1>).  The tests exercise cases that aren't
    problematic with the current code since system_clock is converted to
    steady_clock before calling __platform_wait_until() is called but they
    will protect against changes in the implementation reintroducing this
    bug.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/116586
            * testsuite/30_threads/semaphore/try_acquire_for.cc: Add tests.
            * testsuite/30_threads/semaphore/try_acquire_until.cc: Add
            tests.
    
    Signed-off-by: Mike Crowe <[email protected]>

Diff:
---
 .../30_threads/semaphore/try_acquire_for.cc        | 22 ++++++++++++++++++++
 .../30_threads/semaphore/try_acquire_until.cc      | 24 ++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc 
b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc
index 39681c7ee56b..94acb253091e 100644
--- a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc
@@ -24,6 +24,7 @@
 #include <chrono>
 #include <thread>
 #include <atomic>
+#include <initializer_list>
 #include <testsuite_hooks.h>
 
 void test01()
@@ -90,9 +91,30 @@ test03()
   s.try_acquire_for(timeout);
 }
 
+// Prove semaphore doesn't suffer from PR116586
+template <typename Clock>
+void
+test_relative(std::chrono::nanoseconds offset)
+{
+  std::binary_semaphore sem(1);
+  VERIFY(sem.try_acquire_for(offset));
+  VERIFY(!sem.try_acquire_for(offset));
+}
+
 int main()
 {
   test01();
   test02();
   test03();
+  using namespace std::chrono;
+  for (const nanoseconds offset : {
+      nanoseconds{0},
+      nanoseconds{-10ms},
+      nanoseconds{-10s}
+    }) {
+    test_relative<std::chrono::system_clock>(offset);
+    test_relative<std::chrono::system_clock>(offset - 
std::chrono::system_clock::now().time_since_epoch());
+    test_relative<std::chrono::steady_clock>(offset);
+    test_relative<std::chrono::steady_clock>(offset - 
std::chrono::steady_clock::now().time_since_epoch());
+  }
 }
diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc 
b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
index de0068d670ad..ed6bd118fee4 100644
--- a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
@@ -24,6 +24,7 @@
 #include <chrono>
 #include <thread>
 #include <atomic>
+#include <initializer_list>
 #include <testsuite_hooks.h>
 
 void test01()
@@ -87,8 +88,31 @@ void test02()
   b.wait(1);
 }
 
+// Prove semaphore doesn't suffer from PR116586
+template <typename Clock>
+void
+test_absolute(std::chrono::nanoseconds offset)
+{
+  std::binary_semaphore sem(1);
+  std::chrono::time_point<Clock> tp(offset);
+  VERIFY(sem.try_acquire_until(tp));
+  VERIFY(!sem.try_acquire_until(tp));
+}
+
 int main()
 {
   test01();
   test02();
+  using namespace std::chrono;
+  for (const nanoseconds offset : {
+      // tv_sec == 0, tv_nsec == 0
+      nanoseconds{0},
+      // tv_sec == 0, tv_nsec < 0
+      nanoseconds{-10ms},
+      // tv_sec < 0
+      nanoseconds{-10s}
+    }) {
+    test_absolute<std::chrono::system_clock>(offset);
+    test_absolute<std::chrono::steady_clock>(offset);
+  }
 }

Reply via email to