.. 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 `_ 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`.