LCOV - code coverage report
Current view: top level - home/h/core/forks/m4-libzmq/src - clock.cpp (source / functions) Hit Total Coverage
Test: zeromq-4.2.0 Code Coverage Lines: 20 24 83.3 %
Date: 2016-05-09 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :     Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
       3             : 
       4             :     This file is part of libzmq, the ZeroMQ core engine in C++.
       5             : 
       6             :     libzmq is free software; you can redistribute it and/or modify it under
       7             :     the terms of the GNU Lesser General Public License (LGPL) as published
       8             :     by the Free Software Foundation; either version 3 of the License, or
       9             :     (at your option) any later version.
      10             : 
      11             :     As a special exception, the Contributors give you permission to link
      12             :     this library with independent modules to produce an executable,
      13             :     regardless of the license terms of these independent modules, and to
      14             :     copy and distribute the resulting executable under terms of your choice,
      15             :     provided that you also meet, for each linked independent module, the
      16             :     terms and conditions of the license of that module. An independent
      17             :     module is a module which is not derived from or based on this library.
      18             :     If you modify this library, you must extend this exception to your
      19             :     version of the library.
      20             : 
      21             :     libzmq is distributed in the hope that it will be useful, but WITHOUT
      22             :     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      23             :     FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
      24             :     License for more details.
      25             : 
      26             :     You should have received a copy of the GNU Lesser General Public License
      27             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      28             : */
      29             : 
      30             : #include "precompiled.hpp"
      31             : #include "clock.hpp"
      32             : #include "platform.hpp"
      33             : #include "likely.hpp"
      34             : #include "config.hpp"
      35             : #include "err.hpp"
      36             : #include "mutex.hpp"
      37             : 
      38             : #include <stddef.h>
      39             : 
      40             : #if defined _MSC_VER
      41             : #if defined _WIN32_WCE
      42             : #include <cmnintrin.h>
      43             : #else
      44             : #include <intrin.h>
      45             : #endif
      46             : #endif
      47             : 
      48             : #if !defined ZMQ_HAVE_WINDOWS
      49             : #include <sys/time.h>
      50             : #endif
      51             : 
      52             : #if defined HAVE_CLOCK_GETTIME || defined HAVE_GETHRTIME
      53             : #include <time.h>
      54             : #endif
      55             : 
      56             : #if defined ZMQ_HAVE_OSX
      57             : #include <mach/clock.h>
      58             : #include <mach/mach.h>
      59             : #include <time.h>
      60             : #include <sys/time.h>
      61             : 
      62             : int clock_gettime (int clock_id, timespec *ts)
      63             : {
      64             :     // The clock_id specified is not supported on this system.
      65             :     if (clock_id != CLOCK_REALTIME) {
      66             :         errno = EINVAL;
      67             :         return -1;
      68             :     }
      69             : 
      70             :     clock_serv_t cclock;
      71             :     mach_timespec_t mts;
      72             :     host_get_clock_service (mach_host_self (), CALENDAR_CLOCK, &cclock);
      73             :     clock_get_time (cclock, &mts);
      74             :     mach_port_deallocate (mach_task_self (), cclock);
      75             :     ts->tv_sec = mts.tv_sec;
      76             :     ts->tv_nsec = mts.tv_nsec;
      77             :     return 0;
      78             : }
      79             : #endif
      80             : 
      81             : #ifdef ZMQ_HAVE_WINDOWS
      82             : typedef ULONGLONG (*f_compatible_get_tick_count64)();
      83             : 
      84             : static zmq::mutex_t compatible_get_tick_count64_mutex;
      85             : 
      86             : ULONGLONG compatible_get_tick_count64()
      87             : {
      88             :   compatible_get_tick_count64_mutex.lock();
      89             :   static DWORD s_wrap = 0;
      90             :   static DWORD s_last_tick = 0;
      91             :   const DWORD current_tick = ::GetTickCount();
      92             :   if (current_tick < s_last_tick)
      93             :     ++s_wrap;
      94             : 
      95             :   s_last_tick = current_tick;
      96             :   const ULONGLONG result = (static_cast<ULONGLONG>(s_wrap) << 32) + static_cast<ULONGLONG>(current_tick);
      97             :   compatible_get_tick_count64_mutex.unlock();
      98             :   return result;
      99             : }
     100             : 
     101             : f_compatible_get_tick_count64 init_compatible_get_tick_count64()
     102             : {
     103             :   f_compatible_get_tick_count64 func = NULL;
     104             :   HMODULE module = ::LoadLibraryA("Kernel32.dll");
     105             :   if (module != NULL)
     106             :     func = reinterpret_cast<f_compatible_get_tick_count64>(::GetProcAddress(module, "GetTickCount64"));
     107             : 
     108             :   if (func == NULL)
     109             :     func = compatible_get_tick_count64;
     110             : 
     111             :   ::FreeLibrary(module);
     112             : 
     113             :   return func;
     114             : }
     115             : 
     116             : static f_compatible_get_tick_count64 my_get_tick_count64 = init_compatible_get_tick_count64();
     117             : #endif
     118             : 
     119      542687 : zmq::clock_t::clock_t () :
     120             :     last_tsc (rdtsc ()),
     121             : #ifdef ZMQ_HAVE_WINDOWS
     122             :     last_time (static_cast<uint64_t>((*my_get_tick_count64)()))
     123             : #else
     124      542687 :     last_time (now_us () / 1000)
     125             : #endif
     126             : {
     127      542687 : }
     128             : 
     129      542687 : zmq::clock_t::~clock_t ()
     130             : {
     131      542687 : }
     132             : 
     133      546948 : uint64_t zmq::clock_t::now_us ()
     134             : {
     135             : #if defined ZMQ_HAVE_WINDOWS
     136             : 
     137             :     //  Get the high resolution counter's accuracy.
     138             :     LARGE_INTEGER ticksPerSecond;
     139             :     QueryPerformanceFrequency (&ticksPerSecond);
     140             : 
     141             :     //  What time is it?
     142             :     LARGE_INTEGER tick;
     143             :     QueryPerformanceCounter (&tick);
     144             : 
     145             :     //  Convert the tick number into the number of seconds
     146             :     //  since the system was started.
     147             :     double ticks_div = ticksPerSecond.QuadPart / 1000000.0;
     148             :     return (uint64_t) (tick.QuadPart / ticks_div);
     149             : 
     150             : #elif defined HAVE_CLOCK_GETTIME && defined CLOCK_MONOTONIC
     151             : 
     152             :     //  Use POSIX clock_gettime function to get precise monotonic time.
     153             :     struct timespec tv;
     154      546948 :     int rc = clock_gettime (CLOCK_MONOTONIC, &tv);
     155             :     // Fix case where system has clock_gettime but CLOCK_MONOTONIC is not supported.
     156             :     // This should be a configuration check, but I looked into it and writing an
     157             :     // AC_FUNC_CLOCK_MONOTONIC seems beyond my powers.
     158      546948 :     if( rc != 0) {
     159             :         //  Use POSIX gettimeofday function to get precise time.
     160             :         struct timeval tv;
     161           0 :         int rc = gettimeofday (&tv, NULL);
     162           0 :         errno_assert (rc == 0);
     163           0 :         return (tv.tv_sec * (uint64_t) 1000000 + tv.tv_usec);
     164             :     }
     165      546948 :     return (tv.tv_sec * (uint64_t) 1000000 + tv.tv_nsec / 1000);
     166             : 
     167             : #elif defined HAVE_GETHRTIME
     168             : 
     169             :     return (gethrtime () / 1000);
     170             : 
     171             : #else
     172             : 
     173             :     //  Use POSIX gettimeofday function to get precise time.
     174             :     struct timeval tv;
     175             :     int rc = gettimeofday (&tv, NULL);
     176             :     errno_assert (rc == 0);
     177             :     return (tv.tv_sec * (uint64_t) 1000000 + tv.tv_usec);
     178             : 
     179             : #endif
     180             : }
     181             : 
     182       19317 : uint64_t zmq::clock_t::now_ms ()
     183             : {
     184       19319 :     uint64_t tsc = rdtsc ();
     185             : 
     186             :     //  If TSC is not supported, get precise time and chop off the microseconds.
     187       19319 :     if (!tsc)
     188             :     {
     189             : #ifdef ZMQ_HAVE_WINDOWS
     190             :         // Under Windows, now_us is not so reliable since QueryPerformanceCounter
     191             :         // does not guarantee that it will use a hardware that offers a monotonic timer.
     192             :         // So, lets use GetTickCount when GetTickCount64 is not available with an workaround
     193             :         // to its 32 bit limitation.
     194             :         return static_cast<uint64_t>((*my_get_tick_count64)());
     195             : #else
     196           0 :         return now_us () / 1000;
     197             : #endif
     198             :     }
     199             : 
     200             :     //  If TSC haven't jumped back (in case of migration to a different
     201             :     //  CPU core) and if not too much time elapsed since last measurement,
     202             :     //  we can return cached time value.
     203       19319 :     if (likely (tsc - last_tsc <= (clock_precision / 2) && tsc >= last_tsc))
     204       15064 :         return last_time;
     205             : 
     206        4255 :     last_tsc = tsc;
     207             : #ifdef ZMQ_HAVE_WINDOWS
     208             :     last_time = static_cast<uint64_t>((*my_get_tick_count64)());
     209             : #else
     210        4255 :     last_time = now_us () / 1000;
     211             : #endif
     212        4255 :     return last_time;
     213             : }
     214             : 
     215     4955020 : uint64_t zmq::clock_t::rdtsc ()
     216             : {
     217             : #if (defined _MSC_VER && (defined _M_IX86 || defined _M_X64))
     218             :     return __rdtsc ();
     219             : #elif (defined __GNUC__ && (defined __i386__ || defined __x86_64__))
     220             :     uint32_t low, high;
     221     5517024 :     __asm__ volatile ("rdtsc" : "=a" (low), "=d" (high));
     222     5517033 :     return (uint64_t) high << 32 | low;
     223             : #elif (defined __SUNPRO_CC && (__SUNPRO_CC >= 0x5100) && (defined __i386 || \
     224             :     defined __amd64 || defined __x86_64))
     225             :     union {
     226             :         uint64_t u64val;
     227             :         uint32_t u32val [2];
     228             :     } tsc;
     229             :     asm("rdtsc" : "=a" (tsc.u32val [0]), "=d" (tsc.u32val [1]));
     230             :     return tsc.u64val;
     231             : #elif defined(__s390__)
     232             :     uint64_t tsc;
     233             :     asm("\tstck\t%0\n" : "=Q" (tsc) : : "cc");
     234             :     return(tsc);
     235             : #else
     236             :     return 0;
     237             : #endif
     238             : }

Generated by: LCOV version 1.10