.. highlight:: none
.. index::
pair: clock; design
.. _design-clock:
Fast high-resolution clock
==========================
.. mps:prefix:: design.mps.clock
Introduction
------------
:mps:tag:`intro` This is the design of the clock module, which implements a
fast high-resolution clock for use by the telemetry system.
:mps:tag:`readership` This document is intended for any MPS developer.
Requirements
------------
:mps:tag:`req.monotonic` Successive calls to :c:func:`EVENT_CLOCK()` must yield
values that are monotonically increasing. (So that comparing the
timestamp on two events never gives false positives.)
:mps:tag:`req.fast` :c:func:`EVENT_CLOCK()` should take very little time; it
should not require a system call. (So that programs that use the MPS
remain usable when telemetry is turned on.)
:mps:tag:`req.high-resolution` Successive calls to :c:func:`EVENT_CLOCK()` should
yield values that are strictly monotonically increasing (so that
sorting the telemetry stream puts the events in the order they
happened).
Interface
---------
:c:type:`EventClock`
:mps:tag:`if.type` The type of timestamps. It must be an unsigned 64-bit
integral type, for example a ``typedef`` for ``uint64_t`` or
``unsigned __int64``.
.. c:macro:: EVENT_CLOCK_MAKE(lvalue, low, high)
:mps:tag:`if.make` Construct an :c:type:`EventClock` timestamp from its two
halves. The first parameter is an lvalue with type :c:type:`EventClock`, and
the second and third parameters are 32-bit unsigned integers. The
macro must assign a timestamp to ``lvalue`` with the value ``(high
<< 32) + low``.
.. c:macro:: EVENT_CLOCK(lvalue)
:mps:tag:`if.get` Assign an :c:type:`EventClock` timestamp for the current time to
``lvalue``, which is an lvalue with type :c:type:`EventClock`.
.. c:macro:: EVENT_CLOCK_PRINT(stream, clock)
:mps:tag:`if.print` Write the value of ``clock`` to the standard C output
file handle ``stream`` as 16 hexadecimal digits (with leading zeros,
and capital letters A to F).
.. c:macro:: EVENT_CLOCK_WRITE(stream, clock)
:mps:tag:`if.write` Write the value of ``clock`` to the output stream
``stream`` as 16 hexadecimal digits (with leading zeros, and capital
letters A to F). The macro should be implemented using :c:func:`WriteF()`.
Implementation
--------------
:mps:tag:`impl.tsc` On IA-32 and x86-64, the `Time Stamp Counter
<https://en.wikipedia.org/wiki/Time_Stamp_Counter>`_ returned by the
RDTSC instruction is a suitable clock for single-core CPUs, but on
multiple-core CPUs, different cores may have different values or tick at different speeds, and so it may fail to meet :mps:ref:`.req.monotonic`.