<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>