<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/a848fc1373097874d39cd524bdcb5aecf2ea2aa9">https://github.com/macports/macports-legacy-support/commit/a848fc1373097874d39cd524bdcb5aecf2ea2aa9</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit a848fc1373097874d39cd524bdcb5aecf2ea2aa9
</span>Author: Fred Wright <fw@fwright.net>
AuthorDate: Sat Feb 22 13:43:49 2025 -0800

<span style='display:block; white-space:pre;color:#404040;'>    clock_gettime*(): Use new syscall for thread time on 10.10+.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    High-resolution thread-time was made available via syscall as of
</span><span style='display:block; white-space:pre;color:#404040;'>    10.10.  Use that when available, otherwise fall back to the old way.
</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 new test on all platforms.
</span>---
 src/time.c | 117 +++++++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 86 insertions(+), 31 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 78437b4..33edfc3 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;'>@@ -67,8 +67,10 @@ uint64_t mach_continuous_approximate_time(void)
</span> #include <math.h>
 #include <stddef.h>
 #include <time.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <unistd.h>
</span> 
 #include <sys/time.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/syscall.h>
</span> #include <sys/sysctl.h>
 #include <sys/resource.h>
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -120,24 +122,6 @@ get_boot_and_tod(struct timeval *bt, struct timeval *tod)
</span>   return 0;
 }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-/* Get the CPU usage of the current thread into user/system timevals. */
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-static int
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-get_thread_usage(time_value_t *ut, time_value_t *st)
</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;'>-  mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  thread_basic_info_data_t info;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  thread_port_t thread = mach_thread_self();
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  ret = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t) &info, &count);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  mach_port_deallocate(mach_task_self(), thread);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  if (ret) return ret;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  *ut = info.user_time;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  *st = info.system_time;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-  return 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-}
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span> /*
  * Mach timebase scaling
  *
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -370,6 +354,83 @@ mach2timespec(uint64_t mach_time, struct timespec *ts)
</span>   nanos2timespec(mach2nanos(mach_time), ts);
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Get the best available thread time, using the syscall on 10.10+,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * but falling back to thread_info() on <10.10.
</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;'>+#if __MPLS_TARGET_OSVER < 101000
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Common thread usage code */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+get_thread_usage(thread_basic_info_data_t *info)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  thread_port_t thread = mach_thread_self();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  ret = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t) info, &count);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  mach_port_deallocate(mach_task_self(), thread);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return ret;
</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;'>+/* Get the CPU usage of the current thread, in nanoseconds */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static inline uint64_t
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+get_thread_usage_ns(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  thread_basic_info_data_t info;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (get_thread_usage(&info)) return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return (info.user_time.seconds + info.system_time.seconds) * BILLION64
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         + (info.user_time.microseconds + info.system_time.microseconds) * 1000;
</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;'>+/* Same but returning as timespec */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static inline int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+get_thread_usage_ts(struct timespec *ts)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  thread_basic_info_data_t info;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (get_thread_usage(&info)) return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  ts->tv_sec = info.user_time.seconds + info.system_time.seconds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  ts->tv_nsec = (info.user_time.microseconds + info.system_time.microseconds)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                * 1000;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  if (ts->tv_nsec >= BILLION32) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ++ts->tv_sec;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ts->tv_nsec -= BILLION32;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return 0;
</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;'>+#define HIRES_THREAD_TIME 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#else /* __MPLS_TARGET_OSVER >= 101000 */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Get the CPU usage of the current thread via syscall, in nanoseconds. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static inline uint64_t
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+get_thread_usage_ns(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  uint64_t mach_time = syscall(SYS_thread_selfusage);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return mach2nanos(mach_time);
</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;'>+/* Same but returning as timespec */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static inline int
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+get_thread_usage_ts(struct timespec *ts)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  uint64_t mach_time = syscall(SYS_thread_selfusage);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  mach2timespec(mach_time, ts);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  return mach_time ? 0 : -1;
</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;'>+#define HIRES_THREAD_TIME 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif /* __MPLS_TARGET_OSVER >= 101000 */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /* Now the actual public functions */
 
 uint64_t
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -378,7 +439,6 @@ clock_gettime_nsec_np(clockid_t clk_id)
</span>   uint64_t mach_time;
   struct timeval tod, bt;
   struct rusage ru;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  time_value_t ut, st;
</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;'>@@ -400,9 +460,7 @@ clock_gettime_nsec_np(clockid_t clk_id)
</span>            + (ru.ru_utime.tv_usec + ru.ru_stime.tv_usec) * 1000;
 
   case CLOCK_THREAD_CPUTIME_ID:
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (get_thread_usage(&ut, &st)) return 0;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    return (ut.seconds + st.seconds) * BILLION64
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-           + (ut.microseconds + st.microseconds) * 1000;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return get_thread_usage_ns();
</span> 
   case CLOCK_MONOTONIC_RAW:
     mach_time = mach_continuous_time();
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -435,7 +493,6 @@ clock_gettime(clockid_t clk_id, struct timespec *ts)
</span>   int ret, mserr = 0;
   struct timeval tod, bt;
   struct rusage ru;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-  time_value_t ut, st;
</span>   uint64_t mach_time;
 
   /* Set up mach scaling early, whether we need it or not. */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -461,14 +518,7 @@ clock_gettime(clockid_t clk_id, struct timespec *ts)
</span>     return ret;
 
   case CLOCK_THREAD_CPUTIME_ID:
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    ret = get_thread_usage(&ut, &st);
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    ts->tv_sec = ut.seconds + st.seconds;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    ts->tv_nsec = (ut.microseconds + st.microseconds) * 1000;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if (ts->tv_nsec >= BILLION32) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-      ++ts->tv_sec;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-      ts->tv_nsec -= BILLION32;
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return get_thread_usage_ts(ts);
</span> 
   case CLOCK_MONOTONIC_RAW:
     mach_time = mach_continuous_time();
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -510,7 +560,9 @@ clock_getres(clockid_t clk_id, struct timespec *res)
</span>   case CLOCK_REALTIME:
   case CLOCK_MONOTONIC:
   case CLOCK_PROCESS_CPUTIME_ID:
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#if !HIRES_THREAD_TIME
</span>   case CLOCK_THREAD_CPUTIME_ID:
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span>     *res = res_micros;
     return 0;
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -519,6 +571,9 @@ clock_getres(clockid_t clk_id, struct timespec *res)
</span>   case CLOCK_MONOTONIC_RAW_APPROX:
   case CLOCK_UPTIME_RAW:
   case CLOCK_UPTIME_RAW_APPROX:
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#if HIRES_THREAD_TIME
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  case CLOCK_THREAD_CPUTIME_ID:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span>     break;
 
   default:
</pre><pre style='margin:0'>

</pre>