This change supports returning the remaining time adjustment without
making any alteration to it. The implementation disregards the
mandatory new delta argument in cases where the time spec. is out of
bounds (not within the range -MACH_ADJTIME_SECS_INVALID to
MACH_ADJTIME_SECS_INVALID).
---
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..12b2b2d3 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 number of seconds that can be specified to
+ successfully schedule a time of day adjustment (host_adjust_time
+ and host_adjust_time64) must be less than this. */
+#define MACH_ADJTIME_SECS_INVALID (0x20000000000000)
+
/*
* 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..ab6d3394 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_INVALID &&
+ new_adjustment.seconds < MACH_ADJTIME_SECS_INVALID)
+ {
+ uint64_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)
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