~n-muench/ubuntu/oneiric/open-vm-tools/open-vm-tools.fix-836277

« back to all changes in this revision

Viewing changes to services/plugins/timeSync/timeSyncPosix.c

  • Committer: Evan Broder
  • Date: 2010-03-21 23:26:53 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: broder@mit.edu-20100321232653-5a57r7v7ch4o6byv
Merging shared upstream rev into target branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 */
24
24
 
25
25
#include "timeSync.h"
 
26
#include "timeSyncPosix.h"
26
27
 
27
28
#include <errno.h>
28
29
#include <glib.h>
30
31
#include <time.h>
31
32
#include <sys/wait.h>
32
33
#include <sys/time.h>
33
 
#if !defined(__APPLE__)
34
 
#include <sys/timex.h>
35
 
#endif
36
34
#include "vm_assert.h"
37
35
 
38
 
/*
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.
42
 
 */
43
 
#ifdef __linux__
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 */
48
 
#endif
49
 
 
50
36
 
51
37
/*
52
38
 ******************************************************************************
53
39
 * TimeSync_AddToCurrentTime --                                         */ /**
54
40
 *
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
57
 
 * guest time.
 
41
 * Adjust the current system time by adding the given number of
 
42
 * microseconds. This function disables any time slewing to correctly set
 
43
 * the guest time.
58
44
 *
59
 
 * @param[in] deltaSecs     Seconds to add.
60
 
 * @param[in] deltaUsecs    Microseconds to add.
 
45
 * @param[in] delta    Microseconds to add.
61
46
 *
62
47
 * @return TRUE on success.
63
48
 *
65
50
 */
66
51
 
67
52
Bool
68
 
TimeSync_AddToCurrentTime(int64 deltaSecs,
69
 
                          int64 deltaUsecs)
 
53
TimeSync_AddToCurrentTime(int64 delta)
70
54
{
71
55
   struct timeval tv;
72
56
   int64 newTime;
73
 
   int64 secs;
74
 
   int64 usecs;
 
57
   int64 now;
75
58
 
76
 
   if (!TimeSync_GetCurrentTime(&secs, &usecs)) {
 
59
   if (!TimeSync_GetCurrentTime(&now)) {
77
60
      return FALSE;
78
61
   }
79
62
 
80
 
   if (TimeSync_IsTimeSlewEnabled()) {
81
 
      TimeSync_DisableTimeSlew();
82
 
   }
83
 
 
84
 
   newTime = (secs + deltaSecs) * 1000000L + (usecs + deltaUsecs);
 
63
   newTime = now + delta;
85
64
   ASSERT(newTime > 0);
86
65
 
87
66
   /*
91
70
    *
92
71
    * If it is a 64-bit linux, everything should be fine.
93
72
    */
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);
96
75
      return FALSE;
97
76
   }
98
77
 
99
 
   tv.tv_sec = newTime / 1000000L;
100
 
   tv.tv_usec = newTime % 1000000L;
 
78
   TimeSyncWriteTimeVal(newTime, &tv);
101
79
 
102
80
   if (settimeofday(&tv, NULL) < 0) {
103
81
      return FALSE;
109
87
 
110
88
/*
111
89
 ******************************************************************************
112
 
 * TimeSync_DisableTimeSlew --                                          */ /**
113
 
 *
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 -
116
 
 * it will be behind.
117
 
 *
118
 
 * @return TRUE on success.
119
 
 *
120
 
 ******************************************************************************
121
 
 */
122
 
 
123
 
Bool
124
 
TimeSync_DisableTimeSlew(void)
125
 
{
126
 
#if defined(__FreeBSD__) || defined(sun)
127
 
 
128
 
   struct timeval tx = {0};
129
 
   int error;
130
 
 
131
 
   error = adjtime(&tx, NULL);
132
 
   if (error == -1) {
133
 
      g_debug("adjtime failed: %s\n", strerror(errno));
134
 
      return FALSE;
135
 
   }
136
 
   return TRUE;
137
 
 
138
 
#elif defined(__linux__) /* For Linux. */
139
 
 
140
 
   struct timex tx;
141
 
   int error;
142
 
 
143
 
   tx.modes = ADJ_TICK;
144
 
   tx.tick = TICK_INCR_NOMINAL;
145
 
 
146
 
   error = adjtimex(&tx);
147
 
   if (error == -1) {
148
 
      g_debug("adjtimex failed: %s\n", strerror(errno));
149
 
      return FALSE;
150
 
   }
151
 
   g_debug("time slew end\n");
152
 
   return TRUE;
153
 
 
154
 
#else /* Apple */
155
 
   return TRUE;
156
 
 
157
 
#endif
158
 
}
159
 
 
160
 
 
161
 
/*
162
 
 ******************************************************************************
163
 
 * TimeSync_EnableTimeSlew --                                           */ /**
164
 
 *
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.
168
 
 *
169
 
 * timeSyncPeriod is ignored on FreeBSD and Solaris.
170
 
 *
171
 
 * This changes the tick frequency and hence needs to be reset after the time
172
 
 * sync is achieved.
173
 
 *
174
 
 * @param[in] delta              Time difference in us.
175
 
 * @param[in] timeSyncPeriod     Time interval in us.
176
 
 *
177
 
 * @return TRUE on success.
178
 
 *
179
 
 ******************************************************************************
180
 
 */
181
 
 
182
 
Bool
183
 
TimeSync_EnableTimeSlew(int64 delta,
184
 
                        int64 timeSyncPeriod)
185
 
{
186
 
#if defined(__FreeBSD__) || defined(sun)
187
 
 
188
 
   struct timeval tx;
189
 
   struct timeval oldTx;
190
 
   int error;
191
 
 
192
 
   tx.tv_sec = delta / 1000000L;
193
 
   tx.tv_usec = delta % 1000000L;
194
 
 
195
 
   error = adjtime(&tx, &oldTx);
196
 
   if (error == -1) {
197
 
      g_debug("adjtime failed: %s\n", strerror(errno));
198
 
      return FALSE;
199
 
   }
200
 
   g_debug("time slew start.\n");
201
 
   return TRUE;
202
 
 
203
 
#elif defined(__linux__) /* For Linux. */
204
 
 
205
 
   struct timex tx;
206
 
   int error;
207
 
   int64 tick;
208
 
 
209
 
   ASSERT(timeSyncPeriod > 0);
210
 
 
211
 
   /*
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
215
 
    * interval.
216
 
    */
217
 
   tx.modes = ADJ_TICK;
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;
224
 
   }
225
 
   tx.tick = tick;
226
 
 
227
 
   error = adjtimex(&tx);
228
 
   if (error == -1) {
229
 
      g_debug("adjtimex failed: %s\n", strerror(errno));
230
 
      return FALSE;
231
 
   }
232
 
   g_debug("time slew start: %ld\n", tx.tick);
233
 
   return TRUE;
234
 
 
235
 
#else /* Apple */
236
 
 
237
 
   return FALSE;
238
 
 
239
 
#endif
240
 
}
241
 
 
242
 
 
243
 
/*
244
 
 ******************************************************************************
245
90
 * TimeSync_GetCurrentTime --                                           */ /**
246
91
 *
247
92
 * Get the system time in seconds & microseconds.
255
100
 */
256
101
 
257
102
Bool
258
 
TimeSync_GetCurrentTime(int64 *secs,
259
 
                        int64 *usecs)
 
103
TimeSync_GetCurrentTime(int64 *now)
260
104
{
261
105
   struct timeval tv;
262
106
 
263
 
   ASSERT(secs);
264
 
   ASSERT(usecs);
 
107
   ASSERT(now);
265
108
 
266
109
   if (gettimeofday(&tv, NULL) < 0) {
267
110
      return FALSE;
268
111
   }
269
112
 
270
 
   *secs = tv.tv_sec;
271
 
   *usecs = tv.tv_usec;
 
113
   *now = (int64)tv.tv_sec * US_PER_SEC + (int64)tv.tv_usec;
272
114
 
273
115
   return TRUE;
274
116
}
275
 
 
276
 
 
277
 
/*
278
 
 ******************************************************************************
279
 
 * TimeSync_IsTimeSlewEnabled --                                        */ /**
280
 
 *
281
 
 * Returns TRUE if time slewing has been enabled.
282
 
 *
283
 
 * @return Whether time slew is enabled.
284
 
 *
285
 
 ******************************************************************************
286
 
 */
287
 
 
288
 
Bool
289
 
TimeSync_IsTimeSlewEnabled(void)
290
 
{
291
 
#if defined(__FreeBSD__) || defined(sun)
292
 
 
293
 
   struct timeval oldTx;
294
 
   int error;
295
 
 
296
 
   /*
297
 
    * Solaris needs first argument non-NULL and zero
298
 
    * to get the old timeval value.
299
 
    */
300
 
#if defined(sun)
301
 
   struct timeval tx = {0};
302
 
   error = adjtime(&tx, &oldTx);
303
 
#else
304
 
   error = adjtime(NULL, &oldTx);
305
 
#endif
306
 
   if (error == -1) {
307
 
      g_debug("adjtime failed: %s.\n", strerror(errno));
308
 
      return FALSE;
309
 
   }
310
 
   return ((oldTx.tv_sec || oldTx.tv_usec) ? TRUE : FALSE);
311
 
 
312
 
#elif defined(__linux__) /* For Linux. */
313
 
 
314
 
   struct timex tx = {0};
315
 
   int error;
316
 
 
317
 
   error = adjtimex(&tx);
318
 
   if (error == -1) {
319
 
      g_debug("adjtimex failed: %s\n", strerror(errno));
320
 
      return FALSE;
321
 
   }
322
 
   return ((tx.tick == TICK_INCR_NOMINAL) ? FALSE : TRUE);
323
 
 
324
 
#else /* Apple */
325
 
 
326
 
   return FALSE;
327
 
 
328
 
#endif
329
 
}
330