]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sys_macosx: add option to run chronyd as real-time process
authorBryan Christianson <bryan@whatroute.net>
Mon, 24 Aug 2015 20:32:14 +0000 (08:32 +1200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 25 Aug 2015 15:43:57 +0000 (17:43 +0200)
Adds option -P to chronyd on MacOS X which can be used to enable the
thread time constraint scheduling policy. This near real-time scheduling
policy removes a 1usec bias from the 'System time' offset.

chrony.texi.in
chronyd.8.in
sys.c
sys_macosx.c
sys_macosx.h

index 50cccfc3f27ea00585ba032d7ac65e50b416ceed..30b429a30b7b9cad46c91aea8727dc78ea2fb864 100644 (file)
@@ -1039,9 +1039,11 @@ not correct the clock.
 This option displays @code{chronyd's} version number to the terminal and
 exits.
 @item -P <priority>
-This option will select the SCHED_FIFO real-time scheduler at the
-specified priority (which must be between 0 and 100).  This mode is
-supported only on Linux.
+On Linux, this option will select the SCHED_FIFO real-time scheduler at the
+specified priority (which must be between 0 and 100).  On Mac OS X, this option
+must have either a value of 0 (the default) to disable the thread time
+constraint policy or 1 for the policy to be enabled. Other systems do not
+support this option.
 @item -m     
 This option will lock chronyd into RAM so that it will never be paged
 out.  This mode is only supported on Linux.
@@ -2910,13 +2912,15 @@ is used.
 @node sched_priority directive
 @subsection sched_priority
 
-The @code{sched_priority} directive will select the SCHED_FIFO real-time
-scheduler at the specified priority (which must be between 0 and 100).
-This mode is supported only on Linux.
+On Linux, the @code{sched_priority} directive will select the SCHED_FIFO
+real-time scheduler at the specified priority (which must be between 0 and
+100).  On Mac OS X, this option must have either a value of 0 (the default) to
+disable the thread time constraint policy or 1 for the policy to be enabled.
+Other systems do not support this option.
 
-This directive uses the Linux sched_setscheduler() system call to
-instruct the kernel to use the SCHED_FIFO first-in, first-out
-real-time scheduling policy for @code{chronyd} with the specified priority.
+On Linux, this directive uses the sched_setscheduler() system call to instruct
+the kernel to use the SCHED_FIFO first-in, first-out real-time scheduling
+policy for @code{chronyd} with the specified priority.
 This means that whenever @code{chronyd} is ready to run it will run,
 interrupting whatever else is running unless it is a higher priority
 real-time process.  This should not impact performance as @code{chronyd's}
@@ -2924,6 +2928,10 @@ resource requirements are modest, but it should result in lower and
 more consistent latency since @code{chronyd} will not need to wait for the
 scheduler to get around to running it.  You should not use this unless
 you really need it.  The sched_setscheduler man page has more details.
+
+On Mac OS X, this directive uses the thread_policy_set() kernel call to specify
+real-time scheduling. As noted for Linux, you should not use this directive
+unless you really need it.
 @c }}}
 @c {{{ server
 @node server directive
index 387ea21be175a66bfcc812ed316ffbe21058faad..954bfddbae04d68b6afe258b3ffdc96f7f72ef20 100644 (file)
@@ -40,9 +40,11 @@ A summary of the options supported by \fBchronyd\fR is included below.
 
 .TP
 \fB\-P\fR \fIpriority\fR
-This option will select the SCHED_FIFO real-time scheduler at the specified
-priority (which must be between 0 and 100).  This mode is supported only on
-Linux.
+On Linux, this option will select the SCHED_FIFO real-time scheduler at the
+specified priority (which must be between 0 and 100).  On Mac OS X, this
+option must have either a value of 0 (the default) to disable the thread
+time constraint policy or 1 for the policy to be enabled.  Other systems do not
+support this option.
 .TP
 .B \-m
 This option will lock chronyd into RAM so that it will never be paged out.
diff --git a/sys.c b/sys.c
index 918db4bbab791a093a0f67099e76d98ff84af379..94fc2172edf73de86d9cfe3ec51972b3efcb318f 100644 (file)
--- a/sys.c
+++ b/sys.c
@@ -126,6 +126,8 @@ void SYS_SetScheduler(int SchedPriority)
 {
 #if defined(LINUX) && defined(HAVE_SCHED_SETSCHEDULER)
   SYS_Linux_SetScheduler(SchedPriority);
+#elif defined(MACOSX)
+  SYS_MacOSX_SetScheduler(SchedPriority);
 #else
   LOG_FATAL(LOGF_Sys, "scheduler priority setting not supported");
 #endif
index 33da60d1ae7a5eb1813077f38bd85f90ab97c3b4..503f8f18ab3aae72febd4dcc24fe8de58723ea85 100644 (file)
 #include <stdio.h>
 #include <signal.h>
 
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <pthread.h>
+
 #include "sys_macosx.h"
 #include "localp.h"
 #include "sched.h"
@@ -85,6 +89,8 @@ static struct timeval Tdrift;
 /* minimum resolution of current_frequency */
 #define FREQUENCY_RES (1.0e-9)
 
+#define NANOS_PER_MSEC (1000000ULL)
+
 /* ================================================== */
 
 static void
@@ -334,6 +340,53 @@ drift_removal_timeout(SCH_ArbitraryArgument not_used)
   drift_removal_id = SCH_AddTimeoutByDelay(drift_removal_interval, drift_removal_timeout, NULL);
 }
 
+/* ================================================== */
+/*
+  Give chronyd real time priority so that time critical calculations
+  are not pre-empted by the kernel.
+*/
+
+static int
+set_realtime(void)
+{
+  /* https://developer.apple.com/library/ios/technotes/tn2169/_index.html */
+
+  mach_timebase_info_data_t timebase_info;
+  double clock2abs;
+  thread_time_constraint_policy_data_t policy;
+  int kr;
+
+  mach_timebase_info(&timebase_info);
+  clock2abs = ((double)timebase_info.denom / (double)timebase_info.numer) * NANOS_PER_MSEC;
+
+  policy.period = 0;
+  policy.computation = (uint32_t)(5 * clock2abs); /* 5 ms of work */
+  policy.constraint = (uint32_t)(10 * clock2abs);
+  policy.preemptible = 0;
+
+  kr = thread_policy_set(
+          pthread_mach_thread_np(pthread_self()),
+          THREAD_TIME_CONSTRAINT_POLICY,
+          (thread_policy_t)&policy,
+          THREAD_TIME_CONSTRAINT_POLICY_COUNT);
+
+  if (kr != KERN_SUCCESS) {
+    LOG(LOGS_WARN, LOGF_SysMacOSX, "Cannot set real-time priority: %d", kr);
+    return -1;
+  }
+  return 0;
+}
+
+/* ================================================== */
+
+void
+SYS_MacOSX_SetScheduler(int SchedPriority)
+{
+  if (SchedPriority) {
+    set_realtime();
+  }
+}
+
 /* ================================================== */
 
 void
index b5794158ba9139e894ca314b6c9bf8afaecbd779..707700db45dc3c008b0898d66c1d831e654ecbb4 100644 (file)
@@ -30,8 +30,8 @@
 #ifndef GOT_SYS_MACOSX_H
 #define GOT_SYS_MACOSX_H
 
+void SYS_MacOSX_SetScheduler(int SchedPriority);
 void SYS_MacOSX_Initialise(void);
-
 void SYS_MacOSX_Finalise(void);
 
 #endif