1
/*********************************************************
2
* Copyright (C) 2008 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
*********************************************************/
20
* @file monotonicTimer.c
22
* A GSource that implements a timer backed by a monotonic time source.
28
#include "vmware/tools/utils.h"
30
typedef struct MTimerSource {
38
*******************************************************************************
39
* MTimerSourcePrepare -- */ /**
41
* Callback for the "prepare()" event source function. Sets the timeout to
42
* the number of milliseconds this timer expects to sleep for. If the timeout
43
* has already expired, update the internal state tracking the last time the
46
* @param[in] src The source.
47
* @param[out] timeout Where to store the timeout.
49
* @return TRUE if timeout has already expired.
51
*******************************************************************************
55
MTimerSourcePrepare(GSource *src,
58
MTimerSource *timer = (MTimerSource *) src;
60
if (timer->timeout == 0) {
64
uint64 now = System_GetTimeMonotonic() * 10;
67
ASSERT(now >= timer->last);
69
diff = now - timer->last;
70
if (diff >= timer->timeout) {
76
*timeout = MIN(INT_MAX, timer->timeout - diff);
83
*******************************************************************************
84
* MTimerSourceCheck -- */ /**
86
* Checks whether the timeout has expired.
88
* @param[in] src The source.
90
* @return Whether the timeout has expired.
92
*******************************************************************************
96
MTimerSourceCheck(GSource *src)
99
return MTimerSourcePrepare(src, &unused);
104
*******************************************************************************
105
* MTimerSourceDispatch -- */ /**
107
* Calls the callback associated with the timer, if any.
109
* @param[in] src Unused.
110
* @param[in] callback The callback to be called.
111
* @param[in] data User-supplied data.
113
* @return The return value of the callback, or FALSE if the callback is NULL.
115
*******************************************************************************
119
MTimerSourceDispatch(GSource *src,
120
GSourceFunc callback,
123
return (callback != NULL) ? callback(data) : FALSE;
128
*******************************************************************************
129
* MTimerSourceFinalize -- */ /**
131
* Does nothing. The main glib code already does all the cleanup needed.
133
* @param[in] src The source.
135
*******************************************************************************
139
MTimerSourceFinalize(GSource *src)
146
* @addtogroup vmtools_utils
151
*******************************************************************************
152
* VMTools_CreateTimer -- */ /**
154
* @brief Create a timer based on a monotonic clock source.
156
* This timer differs from the glib timeout source, which uses the system time.
157
* It is recommended for code that needs more reliable time tracking, using a
158
* clock that is not affected by changes in the system time (which can happen
159
* when using NTP or the Tools time synchronization feature).
161
* @param[in] timeout The timeout for the timer, must be >= 0.
163
* @return The new source.
165
*******************************************************************************
169
VMTools_CreateTimer(gint timeout)
171
static GSourceFuncs srcFuncs = {
174
MTimerSourceDispatch,
175
MTimerSourceFinalize,
181
ASSERT(timeout >= 0);
183
ret = (MTimerSource *) g_source_new(&srcFuncs, sizeof *ret);
184
ret->last = System_GetTimeMonotonic() * 10;
185
ret->timeout = timeout;