1be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# Copyright 2016 The Chromium Authors. All rights reserved.
2be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# Use of this source code is governed by a BSD-style license that can be
3be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# found in the LICENSE file.
4be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
5be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport ctypes
6be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport ctypes.util
7be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport logging
8be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport os
9be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport platform
10be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport sys
11be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport time
12be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikimport threading
13be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
14be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
15be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris CraikGET_TICK_COUNT_LAST_NOW = 0
16be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# If GET_TICK_COUNTER_LAST_NOW is less than the current time, the clock has
17be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# rolled over, and this needs to be accounted for.
18be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris CraikGET_TICK_COUNT_WRAPAROUNDS = 0
19be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# The current detected platform
20a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik_CLOCK = None
21a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik_NOW_FUNCTION = None
22be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# Mapping of supported platforms and what is returned by sys.platform.
23be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik_PLATFORMS = {
24be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'mac': 'darwin',
25be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'linux': 'linux',
26be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'windows': 'win32',
27be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'cygwin': 'cygwin',
28be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'freebsd': 'freebsd',
29be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'sunos': 'sunos5',
30be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'bsd': 'bsd'
31be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik}
32be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik# Mapping of what to pass get_clocktime based on platform.
33be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik_CLOCK_MONOTONIC = {
34be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'linux': 1,
35be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'freebsd': 4,
36be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'bsd': 3,
37be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    'sunos5': 4
38be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik}
39be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
40a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik_LINUX_CLOCK = 'LINUX_CLOCK_MONOTONIC'
41a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik_MAC_CLOCK = 'MAC_MACH_ABSOLUTE_TIME'
42a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik_WIN_HIRES = 'WIN_QPC'
43a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik_WIN_LORES = 'WIN_ROLLOVER_PROTECTED_TIME_GET_TIME'
44be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
45a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craikdef InitializeMacNowFunction(plat):
46a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  """Sets a monotonic clock for the Mac platform.
47be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
48be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
49be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      plat: Platform that is being run on. Unused in GetMacNowFunction. Passed
50be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        for consistency between initilaizers.
51be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """
52a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  del plat  # Unused
53a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _CLOCK  # pylint: disable=global-statement
54a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _NOW_FUNCTION  # pylint: disable=global-statement
55a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  _CLOCK = _MAC_CLOCK
56be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  libc = ctypes.CDLL('/usr/lib/libc.dylib', use_errno=True)
57be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  class MachTimebaseInfoData(ctypes.Structure):
58be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """System timebase info. Defined in <mach/mach_time.h>."""
59be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    _fields_ = (('numer', ctypes.c_uint32),
60be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik                ('denom', ctypes.c_uint32))
61be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
62be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  mach_absolute_time = libc.mach_absolute_time
63be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  mach_absolute_time.restype = ctypes.c_uint64
64be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
65be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  timebase = MachTimebaseInfoData()
66be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  libc.mach_timebase_info(ctypes.byref(timebase))
67be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  ticks_per_second = timebase.numer / timebase.denom * 1.0e9
68be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
69a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  def MacNowFunctionImpl():
70be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    return mach_absolute_time() / ticks_per_second
71a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  _NOW_FUNCTION = MacNowFunctionImpl
72be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
73be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
74be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikdef GetClockGetTimeClockNumber(plat):
75be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  for key in _CLOCK_MONOTONIC:
76be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if plat.startswith(key):
77be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      return _CLOCK_MONOTONIC[key]
78be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  raise LookupError('Platform not in clock dicitonary')
79be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
80a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craikdef InitializeLinuxNowFunction(plat):
81a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  """Sets a monotonic clock for linux platforms.
82be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
83be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
84be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      plat: Platform that is being run on.
85be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """
86a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _CLOCK  # pylint: disable=global-statement
87a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _NOW_FUNCTION  # pylint: disable=global-statement
88a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  _CLOCK = _LINUX_CLOCK
89be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  clock_monotonic = GetClockGetTimeClockNumber(plat)
90be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  try:
91be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    # Attempt to find clock_gettime in the C library.
92be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    clock_gettime = ctypes.CDLL(ctypes.util.find_library('c'),
93be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik                                use_errno=True).clock_gettime
94be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  except AttributeError:
95be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    # If not able to find int in the C library, look in rt library.
96be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    clock_gettime = ctypes.CDLL(ctypes.util.find_library('rt'),
97be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik                                use_errno=True).clock_gettime
98be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
99be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  class Timespec(ctypes.Structure):
100be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    """Time specification, as described in clock_gettime(3)."""
101be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    _fields_ = (('tv_sec', ctypes.c_long),
102be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik                ('tv_nsec', ctypes.c_long))
103be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
104a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  def LinuxNowFunctionImpl():
105be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    ts = Timespec()
106be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if clock_gettime(clock_monotonic, ctypes.pointer(ts)):
107be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      errno = ctypes.get_errno()
108be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      raise OSError(errno, os.strerror(errno))
109be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    return ts.tv_sec + ts.tv_nsec / 1.0e9
110be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
111a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  _NOW_FUNCTION = LinuxNowFunctionImpl
112be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
113be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
114be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikdef IsQPCUsable():
115a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  """Determines if system can query the performance counter.
116be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    The performance counter is a high resolution timer on windows systems.
117be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Some chipsets have unreliable performance counters, so this checks that one
118be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    of those chipsets is not present.
119be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
120be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Returns:
121be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      True if QPC is useable, false otherwise.
122be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """
123be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
124be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  # Sample output: 'Intel64 Family 6 Model 23 Stepping 6, GenuineIntel'
125be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  info = platform.processor()
126be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  if 'AuthenticAMD' in info and 'Family 15' in info:
127be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    return False
128576fd2a645575980f16b6731dab0f4f150100657Chris Craik  if not hasattr(ctypes, 'windll'):
129576fd2a645575980f16b6731dab0f4f150100657Chris Craik    return False
130a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  try:  # If anything goes wrong during this, assume QPC isn't available.
131be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    frequency = ctypes.c_int64()
132be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    ctypes.windll.Kernel32.QueryPerformanceFrequency(
133be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        ctypes.byref(frequency))
134be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if float(frequency.value) <= 0:
135be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      return False
136a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  except Exception:  # pylint: disable=broad-except
137be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    logging.exception('Error when determining if QPC is usable.')
138be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    return False
139be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  return True
140be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
141be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
142a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craikdef InitializeWinNowFunction(plat):
143a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  """Sets a monotonic clock for windows platforms.
144be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
145be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
146be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      plat: Platform that is being run on.
147be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """
148a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _CLOCK  # pylint: disable=global-statement
149a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _NOW_FUNCTION  # pylint: disable=global-statement
150a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
151be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  if IsQPCUsable():
152a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    _CLOCK = _WIN_HIRES
153be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    qpc_return = ctypes.c_int64()
154be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    qpc_frequency = ctypes.c_int64()
155be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    ctypes.windll.Kernel32.QueryPerformanceFrequency(
156be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        ctypes.byref(qpc_frequency))
157be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    qpc_frequency = float(qpc_frequency.value)
158be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    qpc = ctypes.windll.Kernel32.QueryPerformanceCounter
159a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
160a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    def WinNowFunctionImpl():
161be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      qpc(ctypes.byref(qpc_return))
162be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      return qpc_return.value / qpc_frequency
163be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
164be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  else:
165a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    _CLOCK = _WIN_LORES
166be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    kernel32 = (ctypes.cdll.kernel32
167be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik                if plat.startswith(_PLATFORMS['cygwin'])
168be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik                else ctypes.windll.kernel32)
169be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    get_tick_count_64 = getattr(kernel32, 'GetTickCount64', None)
170be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
171be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    # Windows Vista or newer
172be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if get_tick_count_64:
173be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      get_tick_count_64.restype = ctypes.c_ulonglong
174a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
175a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      def WinNowFunctionImpl():
176be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        return get_tick_count_64() / 1000.0
177be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
178a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    else:  # Pre Vista.
179be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      get_tick_count = kernel32.GetTickCount
180be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      get_tick_count.restype = ctypes.c_uint32
181be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      get_tick_count_lock = threading.Lock()
182a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
183a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      def WinNowFunctionImpl():
184a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik        global GET_TICK_COUNT_LAST_NOW  # pylint: disable=global-statement
185a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik        global GET_TICK_COUNT_WRAPAROUNDS  # pylint: disable=global-statement
186be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        with get_tick_count_lock:
187be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          current_sample = get_tick_count()
188be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          if current_sample < GET_TICK_COUNT_LAST_NOW:
189be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            GET_TICK_COUNT_WRAPAROUNDS += 1
190be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          GET_TICK_COUNT_LAST_NOW = current_sample
191be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          final_ms = GET_TICK_COUNT_WRAPAROUNDS << 32
192be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          final_ms += GET_TICK_COUNT_LAST_NOW
193be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          return final_ms / 1000.0
194a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
195a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  _NOW_FUNCTION = WinNowFunctionImpl
196be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
197be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
198be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikdef InitializeNowFunction(plat):
199a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  """Sets a monotonic clock for the current platform.
200be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
201be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
202be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      plat: Platform that is being run on.
203be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """
204be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  if plat.startswith(_PLATFORMS['mac']):
205a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    InitializeMacNowFunction(plat)
206be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
207be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  elif (plat.startswith(_PLATFORMS['linux'])
208be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        or plat.startswith(_PLATFORMS['freebsd'])
209be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        or plat.startswith(_PLATFORMS['bsd'])
210be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        or plat.startswith(_PLATFORMS['sunos'])):
211a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    InitializeLinuxNowFunction(plat)
212be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
213be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  elif (plat.startswith(_PLATFORMS['windows'])
214be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        or plat.startswith(_PLATFORMS['cygwin'])):
215a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    InitializeWinNowFunction(plat)
216be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
217be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  else:
218be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    raise RuntimeError('%s is not a supported platform.' % plat)
219be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
220a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _NOW_FUNCTION
221a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _CLOCK
222a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  assert _NOW_FUNCTION, 'Now function not properly set during initialization.'
223a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  assert _CLOCK, 'Clock not properly set during initialization.'
224a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
225a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
226be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikdef Now():
227a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  return _NOW_FUNCTION() * 1e6  # convert from seconds to microseconds
228a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
229a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
230a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craikdef GetClock():
231a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  return _CLOCK
232a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
233be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
234a23c9e9f6fc22fe5611def685e1984062b13b560Chris CraikInitializeNowFunction(sys.platform)
235