This is helpful to synchronise the time of day effectively. The new
adjustment argument is not optional and so testing its value is used
instead to determine whether it can be disregarded. Only adjustments
within the range -MACH_ADJTIME_SECS_MAX to MACH_ADJTIME_SECS_MAX are
considered. The outstanding adjustment is however always returned.
---
 include/mach/time_value.h |  5 +++++
 kern/mach_clock.c         | 31 ++++++++++++++++++-------------
 2 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/include/mach/time_value.h b/include/mach/time_value.h
index 9c660e7e..6095cdd8 100644
--- a/include/mach/time_value.h
+++ b/include/mach/time_value.h
@@ -80,6 +80,11 @@ static __inline__ time_value_t 
convert_time_value_from_user(rpc_time_value_t tv)
        return kernel;
 }
 
+/* The absolute maximum number of seconds that can successfully
+   schedule a time of day adjustment (host_adjust_time and
+   host_adjust_time64). */
+#define MACH_ADJTIME_SECS_MAX (2145)
+
 /*
  *     Macros to manipulate time values.  Assume that time values
  *     are normalized (microseconds <= 999999).
diff --git a/kern/mach_clock.c b/kern/mach_clock.c
index c59ed7ad..82c0fb91 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,27 @@ 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.seconds >= -MACH_ADJTIME_SECS_MAX &&
+           new_adjustment.seconds <=  MACH_ADJTIME_SECS_MAX)
+         {
+           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