31
32
#include <sys/wait.h>
32
33
#include <sys/time.h>
33
#if !defined(__APPLE__)
34
#include <sys/timex.h>
36
34
#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
38
******************************************************************************
53
39
* TimeSync_AddToCurrentTime -- */ /**
55
* Adjust the current system time by adding the given number of seconds &
56
* milliseconds. This function disables any time slewing to correctly set the
41
* Adjust the current system time by adding the given number of
42
* microseconds. This function disables any time slewing to correctly set
59
* @param[in] deltaSecs Seconds to add.
60
* @param[in] deltaUsecs Microseconds to add.
45
* @param[in] delta Microseconds to add.
62
47
* @return TRUE on success.
68
TimeSync_AddToCurrentTime(int64 deltaSecs,
53
TimeSync_AddToCurrentTime(int64 delta)
76
if (!TimeSync_GetCurrentTime(&secs, &usecs)) {
59
if (!TimeSync_GetCurrentTime(&now)) {
80
if (TimeSync_IsTimeSlewEnabled()) {
81
TimeSync_DisableTimeSlew();
84
newTime = (secs + deltaSecs) * 1000000L + (usecs + deltaUsecs);
63
newTime = now + delta;
85
64
ASSERT(newTime > 0);
92
71
* If it is a 64-bit linux, everything should be fine.
94
if (sizeof tv.tv_sec < 8 && newTime / 1000000L > MAX_INT32) {
95
g_debug("overflow: deltaSecs=%"FMT64"d, secs=%"FMT64"d\n", deltaSecs, secs);
73
if (sizeof tv.tv_sec < 8 && newTime / US_PER_SEC > MAX_INT32) {
74
g_debug("overflow: delta=%"FMT64"d, now=%"FMT64"d\n", delta, now);
99
tv.tv_sec = newTime / 1000000L;
100
tv.tv_usec = newTime % 1000000L;
78
TimeSyncWriteTimeVal(newTime, &tv);
102
80
if (settimeofday(&tv, NULL) < 0) {
111
89
******************************************************************************
112
* TimeSync_DisableTimeSlew -- */ /**
114
* Disable time slewing, setting the tick frequency to default. If failed to
115
* disable the tick frequency, system time will not reflect the actual time -
118
* @return TRUE on success.
120
******************************************************************************
124
TimeSync_DisableTimeSlew(void)
126
#if defined(__FreeBSD__) || defined(sun)
128
struct timeval tx = {0};
131
error = adjtime(&tx, NULL);
133
g_debug("adjtime failed: %s\n", strerror(errno));
138
#elif defined(__linux__) /* For Linux. */
144
tx.tick = TICK_INCR_NOMINAL;
146
error = adjtimex(&tx);
148
g_debug("adjtimex failed: %s\n", strerror(errno));
151
g_debug("time slew end\n");
162
******************************************************************************
163
* TimeSync_EnableTimeSlew -- */ /**
165
* Slew the clock so that the time difference is covered within the
166
* timeSyncPeriod. timeSyncPeriod is the interval of the time sync loop and we
167
* intend to catch up delta us.
169
* timeSyncPeriod is ignored on FreeBSD and Solaris.
171
* This changes the tick frequency and hence needs to be reset after the time
174
* @param[in] delta Time difference in us.
175
* @param[in] timeSyncPeriod Time interval in us.
177
* @return TRUE on success.
179
******************************************************************************
183
TimeSync_EnableTimeSlew(int64 delta,
184
int64 timeSyncPeriod)
186
#if defined(__FreeBSD__) || defined(sun)
189
struct timeval oldTx;
192
tx.tv_sec = delta / 1000000L;
193
tx.tv_usec = delta % 1000000L;
195
error = adjtime(&tx, &oldTx);
197
g_debug("adjtime failed: %s\n", strerror(errno));
200
g_debug("time slew start.\n");
203
#elif defined(__linux__) /* For Linux. */
209
ASSERT(timeSyncPeriod > 0);
212
* Set the tick so that delta time is corrected in timeSyncPeriod period.
213
* tick is the number of microseconds added per clock tick. We adjust this
214
* so that we get the desired delta + the timeSyncPeriod in timeSyncPeriod
218
tick = (timeSyncPeriod + delta) /
219
((timeSyncPeriod / 1000000) * USER_HZ);
220
if (tick > TICK_INCR_MAX) {
221
tick = TICK_INCR_MAX;
222
} else if (tick < TICK_INCR_MIN) {
223
tick = TICK_INCR_MIN;
227
error = adjtimex(&tx);
229
g_debug("adjtimex failed: %s\n", strerror(errno));
232
g_debug("time slew start: %ld\n", tx.tick);
244
******************************************************************************
245
90
* TimeSync_GetCurrentTime -- */ /**
247
92
* Get the system time in seconds & microseconds.
258
TimeSync_GetCurrentTime(int64 *secs,
103
TimeSync_GetCurrentTime(int64 *now)
261
105
struct timeval tv;
266
109
if (gettimeofday(&tv, NULL) < 0) {
113
*now = (int64)tv.tv_sec * US_PER_SEC + (int64)tv.tv_usec;
278
******************************************************************************
279
* TimeSync_IsTimeSlewEnabled -- */ /**
281
* Returns TRUE if time slewing has been enabled.
283
* @return Whether time slew is enabled.
285
******************************************************************************
289
TimeSync_IsTimeSlewEnabled(void)
291
#if defined(__FreeBSD__) || defined(sun)
293
struct timeval oldTx;
297
* Solaris needs first argument non-NULL and zero
298
* to get the old timeval value.
301
struct timeval tx = {0};
302
error = adjtime(&tx, &oldTx);
304
error = adjtime(NULL, &oldTx);
307
g_debug("adjtime failed: %s.\n", strerror(errno));
310
return ((oldTx.tv_sec || oldTx.tv_usec) ? TRUE : FALSE);
312
#elif defined(__linux__) /* For Linux. */
314
struct timex tx = {0};
317
error = adjtimex(&tx);
319
g_debug("adjtimex failed: %s\n", strerror(errno));
322
return ((tx.tick == TICK_INCR_NOMINAL) ? FALSE : TRUE);