LCOV - code coverage report
Current view: directory - src/shared/platform/win - nacl_clock.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 58 31 53.4 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include <time.h>
       8                 : #include <errno.h>
       9                 : 
      10                 : #include "native_client/src/shared/platform/nacl_clock.h"
      11                 : 
      12                 : #include "native_client/src/include/nacl_macros.h"
      13                 : #include "native_client/src/shared/platform/nacl_host_desc.h"
      14                 : #include "native_client/src/shared/platform/nacl_log.h"
      15                 : #include "native_client/src/shared/platform/nacl_sync.h"
      16                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      17                 : #include "native_client/src/shared/platform/nacl_time.h"
      18                 : #include "native_client/src/shared/platform/win/nacl_time_types.h"
      19                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      20                 : 
      21                 : /*
      22                 :  * Windows does not implement POSIX.1-2001, so we must emulate the
      23                 :  * clock_get{res,time} functions using Windows primitives.
      24                 :  *
      25                 :  * We assume that NaClTimeInit has been invoked.  This is true w/
      26                 :  * NaClPlatformInit.
      27                 :  */
      28                 : 
      29                 : #define MAGIC_OFFSET    (0xd00f05)  /* random offset so monotonic != real */
      30                 : 
      31                 : static int              g_NaClClock_is_initialized = 0;
      32                 : struct NaClMutex        g_nacl_clock_mu;
      33                 : struct nacl_abi_timeval g_nacl_clock_tv;
      34                 : 
      35              15 : int NaClClockInit(void) {
      36              15 :   if (0 != NaClGetTimeOfDay(&g_nacl_clock_tv)) {
      37               0 :     return 0;
      38                 :   }
      39              15 :   g_NaClClock_is_initialized = NaClMutexCtor(&g_nacl_clock_mu);
      40              15 :   return g_NaClClock_is_initialized;
      41              15 : }
      42                 : 
      43              11 : void NaClClockFini(void) {
      44              11 :   NaClMutexDtor(&g_nacl_clock_mu);
      45              11 : }
      46                 : 
      47                 : int NaClClockGetRes(nacl_clockid_t            clk_id,
      48               0 :                     struct nacl_abi_timespec  *res) {
      49               0 :   int       rv = -NACL_ABI_EINVAL;
      50                 :   uint64_t  t_resolution_ns;
      51                 : 
      52               0 :   if (!g_NaClClock_is_initialized) {
      53                 :     NaClLog(LOG_FATAL,
      54               0 :             "NaClClockGetRes invoked without successful NaClClockInit\n");
      55                 :   }
      56               0 :   switch (clk_id) {
      57                 :     case NACL_CLOCK_REALTIME:
      58                 :     case NACL_CLOCK_MONOTONIC:
      59                 :     case NACL_CLOCK_PROCESS_CPUTIME_ID:
      60                 :     case NACL_CLOCK_THREAD_CPUTIME_ID:
      61               0 :       t_resolution_ns = NaClTimerResolutionNanoseconds();
      62               0 :       res->tv_sec  = (nacl_abi_time_t) (t_resolution_ns / NACL_NANOS_PER_UNIT);
      63               0 :       res->tv_nsec = (int32_t)         (t_resolution_ns % NACL_NANOS_PER_UNIT);
      64                 :       /*
      65                 :        * very surprised if res->tv_sec != 0, since that would be a
      66                 :        * rather low resolution timer!
      67                 :        */
      68               0 :       rv = 0;
      69                 :       break;
      70                 :   }
      71                 : 
      72               0 :   return rv;
      73               0 : }
      74                 : 
      75               0 : static INLINE uint64_t FiletimeToUint64(FILETIME ft) {
      76               0 :   return (((uint64_t) ft.dwHighDateTime << 32) | ft.dwLowDateTime);
      77               0 : }
      78                 : 
      79                 : int NaClClockGetTime(nacl_clockid_t           clk_id,
      80               1 :                      struct nacl_abi_timespec *tp) {
      81               1 :   int                     rv = -NACL_ABI_EINVAL;
      82                 :   struct nacl_abi_timeval tv;
      83                 :   uint64_t                t_mono_prev_us;
      84                 :   uint64_t                t_mono_cur_us;
      85                 :   FILETIME                t_creat;
      86                 :   FILETIME                t_exit;
      87                 :   FILETIME                t_kernel;
      88                 :   FILETIME                t_user;
      89                 :   uint64_t                tick_ns;
      90                 : 
      91               1 :   if (!g_NaClClock_is_initialized) {
      92                 :     NaClLog(LOG_FATAL,
      93               0 :             "NaClClockGetTime invoked without successful NaClClockInit\n");
      94                 :   }
      95               1 :   switch (clk_id) {
      96                 :     case NACL_CLOCK_REALTIME:
      97               1 :       rv = NaClGetTimeOfDay(&tv);
      98               1 :       if (0 == rv) {
      99               1 :         tp->tv_sec = tv.nacl_abi_tv_sec;
     100               1 :         tp->tv_nsec = tv.nacl_abi_tv_usec * 1000;
     101                 :       }
     102               1 :       break;
     103                 :     case NACL_CLOCK_MONOTONIC:
     104                 :       /*
     105                 :        * Get real time, compare with last monotonic time.  If later
     106                 :        * than last monotonic time, set last monotonic time to real
     107                 :        * time timestamp; otherwise we leave last monotonoic time
     108                 :        * alone.  In either case, return last monotonic time.
     109                 :        *
     110                 :        * The interpretation used here is that "monotonic" means
     111                 :        * monotonic non-decreasing, as opposed to monotonic increasing.
     112                 :        * We don't assume that GetTimeOfDay only yields high-order bits
     113                 :        * so we can replace low-order bits of the time value with a
     114                 :        * counter to fake monotonicity.  We are dangerously close to
     115                 :        * the resolution limit of 1ns imposed by the timespec structure
     116                 :        * already -- it's only a few Moore's Law generations away where
     117                 :        * we may have to return the same time stamp for repeated calls
     118                 :        * to clock_gettime (if CPU frequency clock is continued to be
     119                 :        * used to drive performance counters; RTDSC is moving to a
     120                 :        * fixed rate [constant_tsc], fortunately).
     121                 :        */
     122               1 :       rv = NaClGetTimeOfDay(&tv);
     123               1 :       if (0 == rv) {
     124               1 :         NaClXMutexLock(&g_nacl_clock_mu);
     125                 :         t_mono_prev_us = g_nacl_clock_tv.nacl_abi_tv_sec * 1000000
     126               1 :             + g_nacl_clock_tv.nacl_abi_tv_usec;
     127                 :         t_mono_cur_us  = tv.nacl_abi_tv_sec * 1000000
     128               1 :             + tv.nacl_abi_tv_usec;
     129               1 :         if (t_mono_cur_us > t_mono_prev_us) {
     130               1 :           g_nacl_clock_tv = tv;
     131                 :         }
     132               1 :         tp->tv_sec = g_nacl_clock_tv.nacl_abi_tv_sec + MAGIC_OFFSET;
     133               1 :         tp->tv_nsec = g_nacl_clock_tv.nacl_abi_tv_usec * 1000;
     134               1 :         NaClXMutexUnlock(&g_nacl_clock_mu);
     135               1 :         rv = 0;
     136                 :       }
     137               1 :       break;
     138                 :     case NACL_CLOCK_PROCESS_CPUTIME_ID:
     139                 :       if (GetProcessTimes(GetCurrentProcess(),
     140               0 :             &t_creat, &t_exit, &t_kernel, &t_user)) {
     141               0 :         tick_ns = (FiletimeToUint64(t_kernel) + FiletimeToUint64(t_user)) * 100;
     142               0 :         tp->tv_sec =  tick_ns / NACL_NANOS_PER_UNIT;
     143               0 :         tp->tv_nsec = tick_ns % NACL_NANOS_PER_UNIT;
     144               0 :         rv = 0;
     145                 :       }
     146               0 :       break;
     147                 :     case NACL_CLOCK_THREAD_CPUTIME_ID:
     148                 :       if (GetThreadTimes(GetCurrentThread(),
     149               0 :             &t_creat, &t_exit, &t_kernel, &t_user)) {
     150               0 :         tick_ns = (FiletimeToUint64(t_kernel) + FiletimeToUint64(t_user)) * 100;
     151               0 :         tp->tv_sec =  tick_ns / NACL_NANOS_PER_UNIT;
     152               0 :         tp->tv_nsec = tick_ns % NACL_NANOS_PER_UNIT;
     153               0 :         rv = 0;
     154                 :       }
     155                 :       break;
     156                 :   }
     157               1 :   return rv;
     158               1 : }

Generated by: LCOV version 1.7