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

</pre>
<p><a href="https://github.com/macports/macports-legacy-support/commit/fd311adb67210a68307191cbafc84bdb541e5c8d">https://github.com/macports/macports-legacy-support/commit/fd311adb67210a68307191cbafc84bdb541e5c8d</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new fd311ad  Implemented `CLOCK_THREAD_CPUTIME_ID` via `thread_info`
</span>fd311ad is described below

<span style='display:block; white-space:pre;color:#808000;'>commit fd311adb67210a68307191cbafc84bdb541e5c8d
</span>Author: Kirill A. Korinsky <kirill@korins.ky>
AuthorDate: Tue Aug 22 21:57:10 2023 +0200

<span style='display:block; white-space:pre;color:#404040;'>    Implemented `CLOCK_THREAD_CPUTIME_ID` via `thread_info`
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    This seems the best source of that value on macOS since 10.0
</span>---
 include/time.h     |  4 +++
 src/time.c         | 21 +++++++++++--
 test/test_time.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 110 insertions(+), 3 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/include/time.h b/include/time.h
</span><span style='display:block; white-space:pre;color:#808080;'>index 4a62300..7f2e88a 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/include/time.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/include/time.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -74,6 +74,10 @@ typedef int clockid_t;
</span> #define CLOCK_PROCESS_CPUTIME_ID    12
 #endif
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifndef CLOCK_THREAD_CPUTIME_ID
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#define CLOCK_THREAD_CPUTIME_ID     16
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> __MP__BEGIN_DECLS
 
 extern int clock_gettime( clockid_t clk_id, struct timespec *ts );
<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 61a078c..ec3885c 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;'>@@ -22,7 +22,11 @@
</span> #include <sys/time.h>
 #include <sys/sysctl.h>
 #include <sys/resource.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <mach/mach_init.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <mach/mach_port.h>
</span> #include <mach/mach_time.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <mach/thread_act.h>
</span> 
 #define BILLION  1000000000L
 #define MILLION  1000000L
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -61,6 +65,19 @@ int clock_gettime( clockid_t clk_id, struct timespec *ts )
</span>       ts->tv_sec  = ru.ru_utime.tv_sec;
       ts->tv_nsec = ru.ru_utime.tv_usec * 1000;
     }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    else if ( CLOCK_THREAD_CPUTIME_ID == clk_id )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</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_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;'>+      thread_port_t thread = mach_thread_self();
</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;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      time_value_add(&info.user_time, &info.system_time);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      ts->tv_sec  = info.user_time.seconds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      ts->tv_nsec = info.user_time.microseconds * 1000;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span>     else if ( CLOCK_MONOTONIC_RAW == clk_id ||
               CLOCK_MONOTONIC_RAW_APPROX == clk_id ||
               CLOCK_UPTIME_RAW == clk_id ||
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -87,7 +104,8 @@ int clock_getres( clockid_t clk_id, struct timespec *ts )
</span>   {
     if ( CLOCK_REALTIME  == clk_id ||
          CLOCK_MONOTONIC == clk_id ||
<span style='display:block; white-space:pre;background:#ffe0e0;'>-         CLOCK_PROCESS_CPUTIME_ID == clk_id )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         CLOCK_PROCESS_CPUTIME_ID == clk_id ||
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+         CLOCK_THREAD_CPUTIME_ID == clk_id)
</span>     {
       // return 1us precision
       ts->tv_sec  = 0;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -96,7 +114,6 @@ int clock_getres( clockid_t clk_id, struct timespec *ts )
</span>     }
     else if ( CLOCK_MONOTONIC_RAW == clk_id ||
               CLOCK_MONOTONIC_RAW_APPROX == clk_id ||
<span style='display:block; white-space:pre;background:#ffe0e0;'>-              CLOCK_PROCESS_CPUTIME_ID == clk_id ||
</span>               CLOCK_UPTIME_RAW == clk_id ||
               CLOCK_UPTIME_RAW_APPROX == clk_id )
     {
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_time.cpp b/test/test_time.cpp
</span><span style='display:block; white-space:pre;color:#808080;'>index 1c8b81a..41b2a03 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/test/test_time.cpp
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_time.cpp
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,7 +1,9 @@
</span> 
 #include <iostream>
<span style='display:block; white-space:pre;background:#ffe0e0;'>-//#include <cstdint>
</span> 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <pthread.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <unistd.h>
</span> #include <time.h>
 
 static unsigned long long kSecondsToNanos = 1000ULL * 1000ULL * 1000ULL;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -26,6 +28,64 @@ inline void res( CLOCKID clk_id )
</span>             << std::endl;
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static void* test_thread_sleep(void *arg)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int delay = *(int *)arg;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int c = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  while ( ++c < 10 )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    unsigned long long was = time(CLOCK_THREAD_CPUTIME_ID);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    usleep(delay);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    unsigned long long now = time(CLOCK_THREAD_CPUTIME_ID);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_mutex_lock(&lock);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    std::cout << "[sleep for " << delay << "us] consumed thread CPU time: "<< now - was << " ns" << std::endl;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_mutex_unlock(&lock);
</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;'>+  return NULL;
</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;'>+static void* test_blackhole_thread(void *arg)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int cycles = *(int *)arg;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int c = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  while ( ++c < 10 )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    unsigned long long was = time(CLOCK_THREAD_CPUTIME_ID);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int i = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int cc = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    while ( ++cc < cycles )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      i = cc * cc % c;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    unsigned long long now = time(CLOCK_THREAD_CPUTIME_ID);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_mutex_lock(&lock);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    std::cout << "[" << i << "~" << cycles << "] consumed thread CPU time: "<< now - was << " ns" << std::endl;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_mutex_unlock(&lock);
</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;'>+  return NULL;
</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;'>+static void* test_wait_thread(void *arg)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  int c = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  while ( ++c < 10 )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    usleep(100);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_mutex_lock(&lock);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    std::cout << "[t2] CLOCK_THREAD_CPUTIME_ID ("<< CLOCK_THREAD_CPUTIME_ID << ") " << time(CLOCK_THREAD_CPUTIME_ID) << std::endl;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_mutex_unlock(&lock);
</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;'>+  return NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> int main()
 {
   {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -84,5 +144,31 @@ int main()
</span>       std::cout << "CLOCK_PROCESS_CPUTIME_ID ("<< CLOCK_PROCESS_CPUTIME_ID << ") " << time(CLOCK_PROCESS_CPUTIME_ID) << std::endl;
     }
   }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+  {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int c = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    res(CLOCK_THREAD_CPUTIME_ID);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    while ( ++c < 10 )
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+      std::cout << "CLOCK_THREAD_CPUTIME_ID ("<< CLOCK_THREAD_CPUTIME_ID << ") " << time(CLOCK_THREAD_CPUTIME_ID) << std::endl;
</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;'>+    pthread_t t1, t2, t3, t4;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int sleep1 = 100;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int sleep2 = 100000;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int cycles1 = 1000;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    int cycles2 = 10000000;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_create(&t1, NULL, test_thread_sleep, &sleep1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_create(&t2, NULL, test_thread_sleep, &sleep2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_create(&t3, NULL, test_blackhole_thread, &cycles1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_create(&t4, NULL, test_blackhole_thread, &cycles2);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_join(t1, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_join(t2, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_join(t3, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::pthread_join(t4, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+  }
</span>   return 0;
 }
</pre><pre style='margin:0'>

</pre>