LCOV - code coverage report
Current view: top level - js/src/vm - Time.h (source / functions) Hit Total Coverage
Test: output.info Lines: 4 5 80.0 %
Date: 2017-07-14 16:53:18 Functions: 2 3 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef vm_Time_h
       8             : #define vm_Time_h
       9             : 
      10             : #include <stddef.h>
      11             : #include <stdint.h>
      12             : 
      13             : /*
      14             :  * Broken down form of 64 bit time value.
      15             :  */
      16             : struct PRMJTime {
      17             :     int32_t tm_usec;            /* microseconds of second (0-999999) */
      18             :     int8_t tm_sec;              /* seconds of minute (0-59) */
      19             :     int8_t tm_min;              /* minutes of hour (0-59) */
      20             :     int8_t tm_hour;             /* hour of day (0-23) */
      21             :     int8_t tm_mday;             /* day of month (1-31) */
      22             :     int8_t tm_mon;              /* month of year (0-11) */
      23             :     int8_t tm_wday;             /* 0=sunday, 1=monday, ... */
      24             :     int32_t tm_year;            /* absolute year, AD */
      25             :     int16_t tm_yday;            /* day of year (0 to 365) */
      26             :     int8_t tm_isdst;            /* non-zero if DST in effect */
      27             : };
      28             : 
      29             : /* Some handy constants */
      30             : #define PRMJ_USEC_PER_SEC       1000000L
      31             : #define PRMJ_USEC_PER_MSEC      1000L
      32             : 
      33             : /* Return the current local time in micro-seconds */
      34             : extern int64_t
      35             : PRMJ_Now();
      36             : 
      37             : /* Initialize the resources associated with PRMJ_Now. */
      38             : #if defined(XP_WIN)
      39             : extern void
      40             : PRMJ_NowInit();
      41             : #else
      42             : inline void
      43           3 : PRMJ_NowInit() {}
      44             : #endif
      45             : 
      46             : /* Release the resources associated with PRMJ_Now; don't call PRMJ_Now again */
      47             : #ifdef XP_WIN
      48             : extern void
      49             : PRMJ_NowShutdown();
      50             : #else
      51             : inline void
      52           0 : PRMJ_NowShutdown() {}
      53             : #endif
      54             : 
      55             : /* Format a time value into a buffer. Same semantics as strftime() */
      56             : extern size_t
      57             : PRMJ_FormatTime(char* buf, int buflen, const char* fmt, PRMJTime* tm);
      58             : 
      59             : 
      60             : /**
      61             :  * Requesting the number of cycles from the CPU.
      62             :  *
      63             :  * `rdtsc`, or Read TimeStamp Cycle, is an instruction provided by
      64             :  * x86-compatible CPUs that lets processes request the number of
      65             :  * cycles spent by the CPU executing instructions since the CPU was
      66             :  * started. It may be used for performance monitoring, but you should
      67             :  * be aware of the following limitations.
      68             :  *
      69             :  *
      70             :  * 1. The value is *not* monotonic.
      71             :  *
      72             :  * The value is reset to 0 whenever a CPU is turned off (e.g. computer
      73             :  * in full hibernation, single CPU going turned off). Moreover, on
      74             :  * multi-core/multi-CPU architectures, the cycles of each core/CPU are
      75             :  * generally not synchronized.  Therefore, is a process or thread is
      76             :  * rescheduled to another core/CPU, the result of `rdtsc` may decrease
      77             :  * arbitrarily.
      78             :  *
      79             :  * The only way to prevent this is to pin your thread to a particular
      80             :  * CPU, which is generally not a good idea.
      81             :  *
      82             :  *
      83             :  *
      84             :  * 2. The value increases independently.
      85             :  *
      86             :  * The value may increase whenever the CPU executes an instruction,
      87             :  * regardless of the process that has issued this
      88             :  * instruction. Moreover, if a process or thread is rescheduled to
      89             :  * another core/CPU, the result of `rdtsc` may increase arbitrarily.
      90             :  *
      91             :  * The only way to prevent this is to ensure that your thread is the
      92             :  * sole owner of the CPU. See [1] for an example. This is also
      93             :  * generally not a good idea.
      94             :  *
      95             :  *
      96             :  *
      97             :  * 3. The value does not measure time.
      98             :  *
      99             :  * On older architectures (pre-Pentium 4), there was no constant mapping
     100             :  * between rdtsc and CPU time.
     101             :  *
     102             :  *
     103             :  * 4. Instructions may be reordered.
     104             :  *
     105             :  * The CPU can reorder instructions. Also, rdtsc does not necessarily
     106             :  * wait until all previous instructions have finished executing before
     107             :  * reading the counter. Similarly, subsequent instructions may begin
     108             :  * execution before the read operation is performed. If you use rdtsc
     109             :  * for micro-benchmarking, you may end up measuring something else
     110             :  * than what you expect. See [1] for a study of countermeasures.
     111             :  *
     112             :  *
     113             :  * ** Performance
     114             :  *
     115             :  * According to unchecked sources on the web, the overhead of rdtsc is
     116             :  * expected to be 150-200 cycles on old architectures, 6-50 on newer
     117             :  * architectures. Agner's instruction tables [2] seem to confirm the latter
     118             :  * results.
     119             :  *
     120             :  *
     121             :  * [1]
     122             :  * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf
     123             :  * [2] http://www.agner.org/optimize/instruction_tables.pdf
     124             :  */
     125             : 
     126             : #define MOZ_HAVE_RDTSC 1
     127             : 
     128             : #if defined(_WIN32)
     129             : 
     130             : #include <intrin.h>
     131             : static __inline uint64_t
     132             : ReadTimestampCounter(void)
     133             : {
     134             :     return __rdtsc();
     135             : }
     136             : 
     137             : #elif defined(__i386__)
     138             : 
     139             : static __inline__ uint64_t
     140             : ReadTimestampCounter(void)
     141             : {
     142             :     uint64_t x;
     143             :     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
     144             :     return x;
     145             : }
     146             : 
     147             : #elif defined(__x86_64__)
     148             : 
     149             : static __inline__ uint64_t
     150           3 : ReadTimestampCounter(void)
     151             : {
     152             :     unsigned hi, lo;
     153           3 :     __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
     154           3 :     return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 );
     155             : }
     156             : 
     157             : #else
     158             : 
     159             : #undef MOZ_HAVE_RDTSC
     160             : 
     161             : #endif
     162             : 
     163             : #endif /* vm_Time_h */

Generated by: LCOV version 1.13