<pre style='margin:0'>
Christopher Nielsen (mascguy) pushed a commit to branch master
in repository macports-legacy-support.

</pre>
<p><a href="https://github.com/macports/macports-legacy-support/commit/8fcbe43d516e67c96711f8d031cbb1305d88e9dd">https://github.com/macports/macports-legacy-support/commit/8fcbe43d516e67c96711f8d031cbb1305d88e9dd</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 8fcbe43d516e67c96711f8d031cbb1305d88e9dd
</span>Author: Fred Wright <fw@fwright.net>
AuthorDate: Mon Feb 24 18:55:14 2025 -0800

<span style='display:block; white-space:pre;color:#404040;'>    Make CLOCK_MONOTONIC actually monotonic.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Copying Apple's CLOCK_MONOTONIC algorithm doesn't work on OS <10.12,
</span><span style='display:block; white-space:pre;color:#404040;'>    where boottime isn't appropriately managed for this purpose.  The only
</span><span style='display:block; white-space:pre;color:#404040;'>    adequate solution is to make it the same as CLOCK_MONOTONIC_RAW.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    TESTED:
</span><span style='display:block; white-space:pre;color:#404040;'>    Passes the new monotonicity test (which the old code failed).
</span>---
 src/time.c | 83 +++++++++++++++++++++++---------------------------------------
 1 file changed, 30 insertions(+), 53 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/time.c b/src/time.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 33edfc3..7ebb10d 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/time.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/time.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -69,10 +69,9 @@ uint64_t mach_continuous_approximate_time(void)
</span> #include <time.h>
 #include <unistd.h>
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <sys/time.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <sys/syscall.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <sys/sysctl.h>
</span> #include <sys/resource.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/syscall.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/time.h>
</span> 
 #include <mach/mach_init.h>
 #include <mach/mach_port.h>
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -84,43 +83,30 @@ uint64_t mach_continuous_approximate_time(void)
</span> #define BILLION64 1000000000ULL
 
 /*
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * Get the system boot time.  The faster means of doing this via a
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * communication page wasn't introduced until 10.12, where this code is
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * inapplicable, so we're stuck with doing it the slow way.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * CLOCK_MONOTONIC
</span>  *
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * Apple's similar code uses sysctlbyname(), which not only is slower
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * but also doesn't work on 10.4.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Apple's implementation of CLOCK_MONOTONIC involves subtracting boottime
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * from the current time of day.  That relies on boottime's having step
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * adjustments applied to it, so that they cancel out in the difference.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * But aside from the fact that corrupting boottime for this purpose is
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * a kludge, this method doesn't even work at all prior to 10.12, since
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * pre-10.12 kernels don't adjust boottime in settimeofday().  Also, prior
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * to 10.12, boottime only had one-second resolution, so the scheme
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * wouldn't work for adjustments less than one second.  Hence, the Apple
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * algorithm for CLOCK_MONOTONIC is completely invalid prior to 10.12.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Aside from the mach_absolute_time() variants used for the RAW & UPTIME
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * clocks, the only other non-timeofday clock is the mach SYSTEM_CLOCK.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * But this is just a slow and more complicated wrapper around
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * mach_absolute_time(), with scaling to nanoseconds, so it's not helpful
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * for this purpose.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * The net result is that CLOCK_MONOTONIC on pre-10.12 systems can't be made
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * any different from CLOCK_MONOTONIC_RAW without losing the mandatory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * monotonicity property.  Note that neither following adjtime() slewing
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * nor counting during sleeps are mandatory properties of CLOCK_MONOTONIC
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * in general, though they happen to be true of the 10.12+ Apple version.
</span>  */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-static int
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-get_boottime(struct timeval *bt)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  size_t boottime_len = sizeof(*bt);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  int bt_mib[] = {CTL_KERN, KERN_BOOTTIME};
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  size_t bt_miblen = sizeof(bt_mib) / sizeof(bt_mib[0]);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  return sysctl(bt_mib, bt_miblen, bt, &boottime_len, NULL, 0);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-/* Get a consistent boot time / time of day pair. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-static int
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-get_boot_and_tod(struct timeval *bt, struct timeval *tod)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-{
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  int ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  /*
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   * Note that older systems that only have one-second resolution on boottime
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   * don't store the tv_usec field at all, making initialization mandatory.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   * Otherwise, infinite loops may result.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  struct timeval tv1 = {0, 0}, tv2 = {0, 0};
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  do {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if ((ret = get_boottime(&tv1))) return ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if ((ret = gettimeofday(tod, NULL))) return ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if ((ret = get_boottime(&tv2))) return ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  } while (tv1.tv_sec != tv2.tv_sec || tv1.tv_usec != tv2.tv_usec);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  *bt = tv1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  return 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-}
</span> 
 /*
  * Mach timebase scaling
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -436,9 +422,9 @@ get_thread_usage_ts(struct timespec *ts)
</span> uint64_t
 clock_gettime_nsec_np(clockid_t clk_id)
 {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  uint64_t mach_time;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  struct timeval tod, bt;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  struct timeval tod;
</span>   struct rusage ru;
<span style='display:block; white-space:pre;background:#e0ffe0;'>+  uint64_t mach_time;
</span> 
   /* Set up mach scaling early, whether we need it or not. */
   if (!mach_mult) setup_mach_mult();
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -449,11 +435,6 @@ clock_gettime_nsec_np(clockid_t clk_id)
</span>     if (gettimeofday(&tod, NULL)) return 0;
     return tod.tv_sec * BILLION64 + tod.tv_usec * 1000;
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  case CLOCK_MONOTONIC:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (get_boot_and_tod(&bt, &tod)) return 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    return (tod.tv_sec - bt.tv_sec) * BILLION64
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-           + (tod.tv_usec - bt.tv_usec) * 1000;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span>   case CLOCK_PROCESS_CPUTIME_ID:
     if (getrusage(RUSAGE_SELF, &ru)) return 0;
     return (ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) * BILLION64
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -462,6 +443,7 @@ clock_gettime_nsec_np(clockid_t clk_id)
</span>   case CLOCK_THREAD_CPUTIME_ID:
     return get_thread_usage_ns();
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+  case CLOCK_MONOTONIC:  /* See CLOCK_MONOTONIC comment above */
</span>   case CLOCK_MONOTONIC_RAW:
     mach_time = mach_continuous_time();
     break;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -491,7 +473,7 @@ int
</span> clock_gettime(clockid_t clk_id, struct timespec *ts)
 {
   int ret, mserr = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  struct timeval tod, bt;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  struct timeval tod;
</span>   struct rusage ru;
   uint64_t mach_time;
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -505,12 +487,6 @@ clock_gettime(clockid_t clk_id, struct timespec *ts)
</span>     ts->tv_sec = tod.tv_sec; ts->tv_nsec = tod.tv_usec * 1000;
     return ret;
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  case CLOCK_MONOTONIC:
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    ret = get_boot_and_tod(&bt, &tod);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    timersub(&tod, &bt, &tod);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    TIMEVAL_TO_TIMESPEC(&tod, ts);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    return ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span>   case CLOCK_PROCESS_CPUTIME_ID:
     ret = getrusage(RUSAGE_SELF, &ru);
     timeradd(&ru.ru_utime, &ru.ru_stime, &ru.ru_utime);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -520,6 +496,7 @@ clock_gettime(clockid_t clk_id, struct timespec *ts)
</span>   case CLOCK_THREAD_CPUTIME_ID:
     return get_thread_usage_ts(ts);
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+  case CLOCK_MONOTONIC:  /* See CLOCK_MONOTONIC comment above */
</span>   case CLOCK_MONOTONIC_RAW:
     mach_time = mach_continuous_time();
     break;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -558,7 +535,6 @@ clock_getres(clockid_t clk_id, struct timespec *res)
</span> 
   /* Everything based on timeval has microsecond resolution. */
   case CLOCK_REALTIME:
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  case CLOCK_MONOTONIC:
</span>   case CLOCK_PROCESS_CPUTIME_ID:
 #if !HIRES_THREAD_TIME
   case CLOCK_THREAD_CPUTIME_ID:
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -567,6 +543,7 @@ clock_getres(clockid_t clk_id, struct timespec *res)
</span>     return 0;
 
   /* Everything based on mach_time has mach resolution. */
<span style='display:block; white-space:pre;background:#e0ffe0;'>+  case CLOCK_MONOTONIC:
</span>   case CLOCK_MONOTONIC_RAW:
   case CLOCK_MONOTONIC_RAW_APPROX:
   case CLOCK_UPTIME_RAW:
</pre><pre style='margin:0'>

</pre>