~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/slewLinux.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:
 
1
/*********************************************************
 
2
 * Copyright (C) 2010 VMware, Inc. All rights reserved.
 
3
 *
 
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.
 
7
 *
 
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.
 
12
 *
 
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.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/**
 
20
 * @file slewLinux.c
 
21
 *
 
22
 * Implementation of slewing using Linux's adjtimex system call to alter
 
23
 * the tick length.
 
24
 */
 
25
 
 
26
#include "timeSync.h"
 
27
#include "timeSyncPosix.h"
 
28
 
 
29
#include <errno.h>
 
30
#include <glib.h>
 
31
#include <string.h>
 
32
#include <time.h>
 
33
#include <sys/wait.h>
 
34
#include <sys/time.h>
 
35
#include <sys/timex.h>
 
36
#include "vm_assert.h"
 
37
 
 
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
 
 
51
/*
 
52
 ******************************************************************************
 
53
 * TimeSync_DisableTimeSlew --                                          */ /**
 
54
 *
 
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 -
 
57
 * it will be behind.
 
58
 *
 
59
 * @return TRUE on success.
 
60
 *
 
61
 ******************************************************************************
 
62
 */
 
63
 
 
64
Bool
 
65
TimeSync_DisableTimeSlew(void)
 
66
{
 
67
   struct timex tx;
 
68
   int error;
 
69
 
 
70
   tx.modes = ADJ_TICK;
 
71
   tx.tick = TICK_INCR_NOMINAL;
 
72
 
 
73
   error = adjtimex(&tx);
 
74
   if (error == -1) {
 
75
      g_debug("adjtimex failed: %s\n", strerror(errno));
 
76
      return FALSE;
 
77
   }
 
78
   g_debug("time slew end\n");
 
79
   return TRUE;
 
80
}
 
81
 
 
82
 
 
83
/*
 
84
 ******************************************************************************
 
85
 * TimeSync_EnableTimeSlew --                                           */ /**
 
86
 *
 
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.
 
90
 *
 
91
 * This changes the tick frequency and hence needs to be reset after the time
 
92
 * sync is achieved.
 
93
 *
 
94
 * @param[in] delta              Time difference in us.
 
95
 * @param[in] timeSyncPeriod     Time interval in us.
 
96
 *
 
97
 * @return TRUE on success.
 
98
 *
 
99
 ******************************************************************************
 
100
 */
 
101
 
 
102
Bool
 
103
TimeSync_EnableTimeSlew(int64 delta,
 
104
                        int64 timeSyncPeriod)
 
105
{
 
106
   struct timex tx;
 
107
   int error;
 
108
   int64 tick;
 
109
 
 
110
   ASSERT(timeSyncPeriod > 0);
 
111
 
 
112
   /*
 
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
 
116
    * interval.
 
117
    */
 
118
   tx.modes = ADJ_TICK;
 
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;
 
125
   }
 
126
   tx.tick = tick;
 
127
 
 
128
   error = adjtimex(&tx);
 
129
   if (error == -1) {
 
130
      g_debug("adjtimex failed: %s\n", strerror(errno));
 
131
      return FALSE;
 
132
   }
 
133
   g_debug("time slew start: %ld\n", tx.tick);
 
134
   return TRUE;
 
135
}