<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/73eff77dae97bcca8812fe7829f20e24d0c98041">https://github.com/macports/macports-legacy-support/commit/73eff77dae97bcca8812fe7829f20e24d0c98041</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 73eff77dae97bcca8812fe7829f20e24d0c98041
</span>Author: Fred Wright <fw@fwright.net>
AuthorDate: Wed Feb 26 15:19:46 2025 -0800

<span style='display:block; white-space:pre;color:#404040;'>    libtest_settime: Report any adjustments to boottime.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Since settimeofday() in 10.12+ adjusts boottime as a kludge to support
</span><span style='display:block; white-space:pre;color:#404040;'>    CLOCK_MONOTONIC, it's useful to report such changes, and hence which
</span><span style='display:block; white-space:pre;color:#404040;'>    OS versions actually do it.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    To be certain whether lack of adjustments is due to the limited
</span><span style='display:block; white-space:pre;color:#404040;'>    resolution of boottime in the older OS versions, this mode includes
</span><span style='display:block; white-space:pre;color:#404040;'>    arranging for the step adjustment to straddle either the second
</span><span style='display:block; white-space:pre;color:#404040;'>    boundary (for truncation) or the odd half-second boundary (for
</span><span style='display:block; white-space:pre;color:#404040;'>    rounding).
</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;'>    Demonstrates adjustments in 10.12+, and lack of adjustments in <10.12,
</span><span style='display:block; white-space:pre;color:#404040;'>    even when timing is arranged to expect an adjustment when
</span><span style='display:block; white-space:pre;color:#404040;'>    implemented.
</span>---
 manual_tests/libtest_settime.c | 82 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 67 insertions(+), 15 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/manual_tests/libtest_settime.c b/manual_tests/libtest_settime.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 5aba3fa..e345bb5 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/manual_tests/libtest_settime.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/manual_tests/libtest_settime.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -59,9 +59,17 @@
</span> #define TARGET_PRIO -20
 
 #define MILLION 1000000LL
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#define UMILLION 1000000ULL
</span> #define BILLION (MILLION * 1000)
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#define BILLION64 (UMILLION * 1000U)
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-typedef long long nstime_t;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define ALIGN_CYCLE_NS BILLION64
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define ALIGN_CYCLE_UNIT_NS (ALIGN_CYCLE_NS / 2)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define ALIGN_CYCLE_OFFSET_NS (-TIME_BUMP_MS * MILLION / 2)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define ALIGN_CYCLE_LIMIT_NS (TIME_BUMP_MS * MILLION / 10)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+typedef unsigned long long nstime_t;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+typedef long long snstime_t;
</span> 
 typedef struct info_s {
   nstime_t init_raw;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -101,6 +109,12 @@ clock_getns(clockid_t clock_id, nstime_t *nsp)
</span>   return *nsp ? 0 : errno;
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+static nstime_t
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+clock_gettodns(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return clock_gettime_nsec_np(CLOCK_REALTIME);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> static int
 clock_setns(nstime_t nsec)
 {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -110,8 +124,6 @@ clock_setns(nstime_t nsec)
</span>   return 0;
 }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-#define BILLION64 1000000000ULL
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span> static int
 get_boottime_ns(nstime_t *nsp)
 {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -151,7 +163,9 @@ static int
</span> do_test(info_t *tp, int extra)
 {
   int err, tverr;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  nstime_t delta, scratch;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  snstime_t delta, scratch;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  nstime_t target, limit, tod, todmod, delay;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  snstime_t todmin, todmax;
</span>   struct timeval orig_tv;
 
   /* First warm up the clocks */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -165,6 +179,22 @@ do_test(info_t *tp, int extra)
</span>   /* Get us a fresh quantum */
   (void) usleep(SLEEP_MS * 1000);
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+  /* In "extra" mode, align time to a suitable boundary */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (extra) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    target = ((ALIGN_CYCLE_NS + (extra -1) * ALIGN_CYCLE_UNIT_NS)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+              + ALIGN_CYCLE_OFFSET_NS) % ALIGN_CYCLE_NS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    limit = (target + ALIGN_CYCLE_LIMIT_NS) % ALIGN_CYCLE_NS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    while (1) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      tod = clock_gettodns();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      todmod = tod % ALIGN_CYCLE_NS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      todmin = todmod - target;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      todmax = todmod - limit;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      if (todmin >= 0 && todmax < 0 ) break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      delay = (target + ALIGN_CYCLE_NS - todmod) % ALIGN_CYCLE_NS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      (void) usleep(delay / 1000U);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>   /* Save original gettimeofday() time */
   tverr = gettimeofday(&orig_tv, NULL);
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -231,8 +261,8 @@ do_test(info_t *tp, int extra)
</span>   return 0;
 }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-#define PRINT_TIME(ptr,name) printf("  " #name " = %lld ns\n", \
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    (long long) ptr->name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define PRINT_TIME(ptr,name) printf("  " #name " = %llu.%09llu s\n", \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ptr->name / BILLION64, ptr->name % BILLION64)
</span> 
 static void
 print_times(info_t *tp, int extra) {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -295,7 +325,9 @@ hog_cpus(pthread_t threads[], int nthreads)
</span> int
 main(int argc, char *argv[])
 {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  int verbose = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  char *progname = basename(argv[0]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int argn, verbose = 0, extra = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  char *cp;
</span>   int nc_mib[] = {CTL_HW, HW_NCPU};
   size_t nc_miblen = sizeof(nc_mib) / sizeof(nc_mib[0]);
   int ncpus;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -303,13 +335,21 @@ main(int argc, char *argv[])
</span>   int orig_prio;
   pthread_t *threads;
   int err;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  nstime_t dur1, dur2, diff1, diff2;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  snstime_t dur1, dur2, diff1, diff2;
</span>   info_t info = {0};
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (argc > 1 && !strcmp(argv[1], "-v")) verbose = 1;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (argc > 1 && !strcmp(argv[1], "-vv")) verbose = 2;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  for (argn = 1; argn < argc; ++argn) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    cp = argv[argn];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (*cp++ != '-') continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    while (*cp) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      switch (*cp++) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      case 'v': ++verbose; break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      case 'x': ++extra; break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  }
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (verbose) printf("%s starting.\n", basename(argv[0]));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (verbose) printf("%s starting, extra = %d.\n", progname, extra);
</span> 
   if (sysctl(nc_mib, nc_miblen, &ncpus, &ncpus_sz, NULL, 0) < 0) {
     perror("sysctl for ncpus failed");
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -346,7 +386,7 @@ main(int argc, char *argv[])
</span>   }
 
   /* Do the test */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  err = do_test(&info, verbose >=2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  err = do_test(&info, extra);
</span> 
   /* Undo our hogging */
   unhog_cpus(threads, ncpus);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -358,7 +398,7 @@ main(int argc, char *argv[])
</span>   if (err) {
     printf("Error encountered: %s\n", strerror(err));
     printf("Dumping partial results:\n");
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    print_times(&info, verbose >= 2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    print_times(&info, extra);
</span>     return 1;
   }
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -423,10 +463,22 @@ main(int argc, char *argv[])
</span>   }
 
   if (verbose) {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    print_times(&info, verbose >= 2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    print_times(&info, extra);
</span>     printf("Total ns = %lld\n", info.final_raw - info.init_raw);
   }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  printf("%s %s.\n", basename(argv[0]), err ? "failed" : "passed");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (extra && !err) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    diff1 = info.middle_boot - info.init_boot;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    diff2 = info.final_boot - info.middle_boot;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (diff1 || diff2) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      printf("Boot time changed by %+.06f s, then %+.06f s\n",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             (double) diff1 / 1E9,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+             (double) diff2 / 1E9);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      printf("Boot time not changed by clock_settime()\n");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  printf("%s %s.\n", progname, err ? "failed" : "passed");
</span>   return err;
 }
</pre><pre style='margin:0'>

</pre>