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 <mac@mcrowe.com>
This commit is contained in:
Mike Crowe 2025-09-14 21:21:28 +01:00 committed by Jonathan Wakely
parent 5dba17a3e7
commit e0525a6d2b
No known key found for this signature in database
2 changed files with 46 additions and 0 deletions

View File

@ -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());
}
}

View File

@ -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);
}
}