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