From 02d4041bfd29f7be5c65f1313cf69c39c59d6827 Mon Sep 17 00:00:00 2001
From: Iain Sandoe <iain@sandoe.co.uk>
Date: Fri, 5 Dec 2025 17:32:24 +0000
Subject: [PATCH 1/2] libstdc++, Darwin: Incremental patch for platform_wait.

Two small changes.

1. The __ulock_wait () function returns positive values which appear
to represent the remaining count of awaiters on the object.

2. We need to reverse the operands to the computation of the relative
time in __platform_wait_until.

libstdc++-v3/ChangeLog:

	* src/c++20/atomic.cc (__platform_wait): Account for positive
	non-error returns from __ulock_wait.
	(__platform_wait_until): Fix calculation of relative time offset.

Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
---
 libstdc++-v3/src/c++20/atomic.cc | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/libstdc++-v3/src/c++20/atomic.cc b/libstdc++-v3/src/c++20/atomic.cc
index c5c900be9fb..5b9c467bc39 100644
--- a/libstdc++-v3/src/c++20/atomic.cc
+++ b/libstdc++-v3/src/c++20/atomic.cc
@@ -40,7 +40,11 @@
 # include <unistd.h>
 # include <sys/time.h> // timespec
 # define _GLIBCXX_HAVE_PLATFORM_WAIT 1
-#elif defined __APPLE__
+#elif defined __APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ \
+      && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500
+// These are thin wrappers over the underlying syscall, they exist on
+// earlier versions of the OS, however those versions do not support the
+// UL_COMPARE_AND_WAIT64 operation.
 extern "C" int
 __ulock_wait(uint32_t operation, void* addr, uint64_t value, uint32_t timeout);
 extern "C" int
@@ -158,7 +162,8 @@ namespace
       }
     return true;
   }
-#elif defined __APPLE__
+#elif defined __APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ \
+      && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500
   [[gnu::always_inline]]
   inline uint32_t
   wait_op(int obj_sz) noexcept
@@ -167,7 +172,7 @@ namespace
   void
   __platform_wait(const void* addr, uint64_t val, int obj_sz) noexcept
   {
-    if (__ulock_wait(wait_op(obj_sz), const_cast<void*>(addr), val, 0))
+    if (0 > __ulock_wait(wait_op(obj_sz), const_cast<void*>(addr), val, 0))
       if (errno != EINTR && errno != EFAULT)
 	__throw_system_error(errno);
   }
@@ -188,14 +193,14 @@ namespace
 			int obj_sz) noexcept
   {
     auto reltime
-      = chrono::ceil<chrono::microseconds>(__wait_clock_t::now() - atime);
+      = chrono::ceil<chrono::microseconds>(atime - __wait_clock_t::now());
     if (reltime <= reltime.zero())
       return false;
     uint32_t timeout = numeric_limits<uint32_t>::max();
-    if (std::cmp_less(reltime.count(), timeout)
+    if (std::cmp_less(reltime.count(), timeout))
        timeout = reltime.count();
 
-    if (__ulock_wait(wait_op(obj_sz), const_cast<void*>(addr), val, timeout))
+    if (0 > __ulock_wait(wait_op(obj_sz), const_cast<void*>(addr), val, timeout))
       {
 	if (errno == ETIMEDOUT)
 	  return timeout == numeric_limits<uint32_t>::max();
-- 
2.39.5 (Apple Git-154)

