From: Michael Kelly <[email protected]>

It's awkward to support an interface that returns 'old_adjustment'
without modifying 'new_adjustment' because the latter is not an
optional parameter. This solution disregards 'new_adjustment'
specifically when the nanoseconds component has the value
MACH_ADJTIME_NSECS_OMIT (which is beyond the normally permissible
range).
---
 include/mach/time_value.h |  9 +++++++++
 kern/mach_clock.c         | 30 +++++++++++++++++-------------
 2 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/include/mach/time_value.h b/include/mach/time_value.h
index 9c660e7e..fe8d0d6d 100644
--- a/include/mach/time_value.h
+++ b/include/mach/time_value.h
@@ -87,6 +87,15 @@ static __inline__ time_value_t 
convert_time_value_from_user(rpc_time_value_t tv)
 #define        TIME_MICROS_MAX (1000000)
 #define        TIME_NANOS_MAX  (1000000000)
 
+/* The host_adjust_time/host_adjust_time64 interfaces do not directly
+   support returning the outstanding time adjustment without
+   specifiying a new time adjustment. To overcome this limitation
+   these calls will not modify the time adjustment when the following
+   MACH_ADJTIME_ constants are specified as the sub-second component.
+ */
+#define MACH_ADJTIME_USECS_OMIT TIME_MICROS_MAX
+#define MACH_ADJTIME_NSECS_OMIT TIME_NANOS_MAX
+
 #define time_value_assert(val)                 \
   assert(0 <= (val)->microseconds && (val)->microseconds < TIME_MICROS_MAX);
 
diff --git a/kern/mach_clock.c b/kern/mach_clock.c
index c59ed7ad..04ae8291 100644
--- a/kern/mach_clock.c
+++ b/kern/mach_clock.c
@@ -667,16 +667,11 @@ host_adjust_time64(
        time_value64_t  *old_adjustment /* OUT */)
 {
        time_value64_t  oadj;
-       uint64_t ndelta_microseconds;
        spl_t           s;
 
        if (host == HOST_NULL)
                return (KERN_INVALID_HOST);
 
-       /* Note we only adjust up to microsecond precision */
-       ndelta_microseconds = new_adjustment.seconds * 
MICROSECONDS_IN_ONE_SECOND
-               + new_adjustment.nanoseconds / 1000;
-
 #if    NCPUS > 1
        thread_bind(current_thread(), master_processor);
        if (current_processor() != master_processor)
@@ -688,17 +683,26 @@ host_adjust_time64(
        oadj.seconds = timedelta / MICROSECONDS_IN_ONE_SECOND;
        oadj.nanoseconds = (timedelta % MICROSECONDS_IN_ONE_SECOND) * 1000;
 
-       if (timedelta == 0) {
-           if (ndelta_microseconds > bigadj)
+       if (new_adjustment.nanoseconds != MACH_ADJTIME_NSECS_OMIT)
+         {
+           int64_t ndelta_microseconds;
+
+           /* Note we only adjust up to microsecond precision */
+           ndelta_microseconds = new_adjustment.seconds * 
MICROSECONDS_IN_ONE_SECOND
+             + new_adjustment.nanoseconds / 1000;
+
+           if (timedelta == 0) {
+             if (ndelta_microseconds > bigadj || ndelta_microseconds < -bigadj)
                tickdelta = 10 * tickadj;
-           else
+             else
                tickdelta = tickadj;
-       }
-       /* Make ndelta_microseconds a multiple of tickdelta */
-       if (ndelta_microseconds % tickdelta)
-           ndelta_microseconds = ndelta_microseconds / tickdelta * tickdelta;
+           }
+           /* Make ndelta_microseconds a multiple of tickdelta */
+           if (ndelta_microseconds % tickdelta)
+             ndelta_microseconds = ndelta_microseconds / tickdelta * tickdelta;
 
-       timedelta = ndelta_microseconds;
+           timedelta = ndelta_microseconds;
+         }
 
        splx(s);
 #if    NCPUS > 1
-- 
2.47.3


Reply via email to