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
128a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  try:  # If anything goes wrong during this, assume QPC isn't available.
129be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    frequency = ctypes.c_int64()
130be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    ctypes.windll.Kernel32.QueryPerformanceFrequency(
131be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        ctypes.byref(frequency))
132be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if float(frequency.value) <= 0:
133be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      return False
134a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  except Exception:  # pylint: disable=broad-except
135be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    logging.exception('Error when determining if QPC is usable.')
136be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    return False
137be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  return True
138be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
139be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
140a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craikdef InitializeWinNowFunction(plat):
141a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  """Sets a monotonic clock for windows platforms.
142be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
143be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
144be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      plat: Platform that is being run on.
145be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """
146a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _CLOCK  # pylint: disable=global-statement
147a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _NOW_FUNCTION  # pylint: disable=global-statement
148a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
149be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  if IsQPCUsable():
150a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    _CLOCK = _WIN_HIRES
151be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    qpc_return = ctypes.c_int64()
152be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    qpc_frequency = ctypes.c_int64()
153be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    ctypes.windll.Kernel32.QueryPerformanceFrequency(
154be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        ctypes.byref(qpc_frequency))
155be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    qpc_frequency = float(qpc_frequency.value)
156be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    qpc = ctypes.windll.Kernel32.QueryPerformanceCounter
157a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
158a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    def WinNowFunctionImpl():
159be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      qpc(ctypes.byref(qpc_return))
160be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      return qpc_return.value / qpc_frequency
161be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
162be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  else:
163a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    _CLOCK = _WIN_LORES
164be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    kernel32 = (ctypes.cdll.kernel32
165be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik                if plat.startswith(_PLATFORMS['cygwin'])
166be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik                else ctypes.windll.kernel32)
167be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    get_tick_count_64 = getattr(kernel32, 'GetTickCount64', None)
168be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
169be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    # Windows Vista or newer
170be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    if get_tick_count_64:
171be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      get_tick_count_64.restype = ctypes.c_ulonglong
172a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
173a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      def WinNowFunctionImpl():
174be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        return get_tick_count_64() / 1000.0
175be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
176a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    else:  # Pre Vista.
177be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      get_tick_count = kernel32.GetTickCount
178be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      get_tick_count.restype = ctypes.c_uint32
179be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      get_tick_count_lock = threading.Lock()
180a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
181a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik      def WinNowFunctionImpl():
182a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik        global GET_TICK_COUNT_LAST_NOW  # pylint: disable=global-statement
183a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik        global GET_TICK_COUNT_WRAPAROUNDS  # pylint: disable=global-statement
184be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        with get_tick_count_lock:
185be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          current_sample = get_tick_count()
186be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          if current_sample < GET_TICK_COUNT_LAST_NOW:
187be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik            GET_TICK_COUNT_WRAPAROUNDS += 1
188be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          GET_TICK_COUNT_LAST_NOW = current_sample
189be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          final_ms = GET_TICK_COUNT_WRAPAROUNDS << 32
190be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          final_ms += GET_TICK_COUNT_LAST_NOW
191be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik          return final_ms / 1000.0
192a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
193a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  _NOW_FUNCTION = WinNowFunctionImpl
194be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
195be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
196be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikdef InitializeNowFunction(plat):
197a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  """Sets a monotonic clock for the current platform.
198be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
199be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    Args:
200be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik      plat: Platform that is being run on.
201be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  """
202be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  if plat.startswith(_PLATFORMS['mac']):
203a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    InitializeMacNowFunction(plat)
204be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
205be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  elif (plat.startswith(_PLATFORMS['linux'])
206be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        or plat.startswith(_PLATFORMS['freebsd'])
207be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        or plat.startswith(_PLATFORMS['bsd'])
208be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        or plat.startswith(_PLATFORMS['sunos'])):
209a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    InitializeLinuxNowFunction(plat)
210be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
211be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  elif (plat.startswith(_PLATFORMS['windows'])
212be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik        or plat.startswith(_PLATFORMS['cygwin'])):
213a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik    InitializeWinNowFunction(plat)
214be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
215be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik  else:
216be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik    raise RuntimeError('%s is not a supported platform.' % plat)
217be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
218a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _NOW_FUNCTION
219a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  global _CLOCK
220a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  assert _NOW_FUNCTION, 'Now function not properly set during initialization.'
221a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  assert _CLOCK, 'Clock not properly set during initialization.'
222a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
223a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
224be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craikdef Now():
225a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  return _NOW_FUNCTION() * 1e6  # convert from seconds to microseconds
226a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
227a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
228a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craikdef GetClock():
229a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik  return _CLOCK
230a23c9e9f6fc22fe5611def685e1984062b13b560Chris Craik
231be1f909aea58dd8b153538c9fa19cb0bf50bdb17Chris Craik
232a23c9e9f6fc22fe5611def685e1984062b13b560Chris CraikInitializeNowFunction(sys.platform)
233