1
/*********************************************************
2
* Copyright (C) 2010 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
22
* Implementation of slewing using Linux's adjtimex system call to alter
27
#include "timeSyncPosix.h"
35
#include <sys/timex.h>
36
#include "vm_assert.h"
39
* The interval between two ticks (in usecs) can only be altered by 10%,
40
* and the default value is 10000. So the values 900000L and 1000000L
41
* divided by USER_HZ, which is 100.
44
# define USER_HZ 100 /* from asm/param.h */
45
# define TICK_INCR_NOMINAL (1000000L / USER_HZ) /* nominal tick increment */
46
# define TICK_INCR_MAX (1100000L / USER_HZ) /* maximum tick increment */
47
# define TICK_INCR_MIN (900000L / USER_HZ) /* minimum tick increment */
52
******************************************************************************
53
* TimeSync_DisableTimeSlew -- */ /**
55
* Disable time slewing, setting the tick frequency to default. If failed to
56
* disable the tick frequency, system time will not reflect the actual time -
59
* @return TRUE on success.
61
******************************************************************************
65
TimeSync_DisableTimeSlew(void)
71
tx.tick = TICK_INCR_NOMINAL;
73
error = adjtimex(&tx);
75
g_debug("adjtimex failed: %s\n", strerror(errno));
78
g_debug("time slew end\n");
84
******************************************************************************
85
* TimeSync_EnableTimeSlew -- */ /**
87
* Slew the clock so that the time difference is covered within the
88
* timeSyncPeriod. timeSyncPeriod is the interval of the time sync loop and we
89
* intend to catch up delta us.
91
* This changes the tick frequency and hence needs to be reset after the time
94
* @param[in] delta Time difference in us.
95
* @param[in] timeSyncPeriod Time interval in us.
97
* @return TRUE on success.
99
******************************************************************************
103
TimeSync_EnableTimeSlew(int64 delta,
104
int64 timeSyncPeriod)
110
ASSERT(timeSyncPeriod > 0);
113
* Set the tick so that delta time is corrected in timeSyncPeriod period.
114
* tick is the number of microseconds added per clock tick. We adjust this
115
* so that we get the desired delta + the timeSyncPeriod in timeSyncPeriod
119
tick = (timeSyncPeriod + delta) /
120
((timeSyncPeriod / US_PER_SEC) * USER_HZ);
121
if (tick > TICK_INCR_MAX) {
122
tick = TICK_INCR_MAX;
123
} else if (tick < TICK_INCR_MIN) {
124
tick = TICK_INCR_MIN;
128
error = adjtimex(&tx);
130
g_debug("adjtimex failed: %s\n", strerror(errno));
133
g_debug("time slew start: %ld\n", tx.tick);