LCOV - code coverage report
Current view: top level - vppinfra - time.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 26 26 100.0 %
Date: 2023-07-05 22:20:52 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : /*
      16             :   Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
      17             : 
      18             :   Permission is hereby granted, free of charge, to any person obtaining
      19             :   a copy of this software and associated documentation files (the
      20             :   "Software"), to deal in the Software without restriction, including
      21             :   without limitation the rights to use, copy, modify, merge, publish,
      22             :   distribute, sublicense, and/or sell copies of the Software, and to
      23             :   permit persons to whom the Software is furnished to do so, subject to
      24             :   the following conditions:
      25             : 
      26             :   The above copyright notice and this permission notice shall be
      27             :   included in all copies or substantial portions of the Software.
      28             : 
      29             :   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      30             :   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      31             :   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      32             :   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      33             :   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      34             :   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      35             :   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      36             : */
      37             : 
      38             : #ifndef included_time_h
      39             : #define included_time_h
      40             : 
      41             : #include <vppinfra/clib.h>
      42             : #include <vppinfra/format.h>
      43             : 
      44             : typedef struct
      45             : {
      46             :   /* Total run time in clock cycles
      47             :      since clib_time_init call. */
      48             :   u64 total_cpu_time;
      49             : 
      50             :   /* Last recorded time stamp. */
      51             :   u64 last_cpu_time;
      52             : 
      53             :   /* CPU clock frequency. */
      54             :   f64 clocks_per_second;
      55             : 
      56             :   /* 1 / cpu clock frequency: conversion factor
      57             :      from clock cycles into seconds. */
      58             :   f64 seconds_per_clock;
      59             : 
      60             :   /* Time stamp of call to clib_time_init call. */
      61             :   u64 init_cpu_time;
      62             :   f64 init_reference_time;
      63             : 
      64             :   u64 last_verify_cpu_time;
      65             : 
      66             :   /* Same but for reference time (if present). */
      67             :   f64 last_verify_reference_time;
      68             : 
      69             :   u32 log2_clocks_per_second, log2_clocks_per_frequency_verify;
      70             : 
      71             :   /* Damping constant */
      72             :   f64 damping_constant;
      73             : 
      74             : } clib_time_t;
      75             : 
      76             : format_function_t format_clib_time;
      77             : 
      78             : /* Return CPU time stamp as 64bit number. */
      79             : #if defined(__x86_64__) || defined(i386)
      80             : always_inline u64
      81  2920977571 : clib_cpu_time_now (void)
      82             : {
      83             :   u32 a, d;
      84  2920977571 :   asm volatile ("rdtsc":"=a" (a), "=d" (d));
      85  2921022732 :   return (u64) a + ((u64) d << (u64) 32);
      86             : }
      87             : 
      88             : #elif defined (__powerpc64__)
      89             : 
      90             : always_inline u64
      91             : clib_cpu_time_now (void)
      92             : {
      93             :   u64 t;
      94             :   asm volatile ("mftb %0":"=r" (t));
      95             :   return t;
      96             : }
      97             : 
      98             : #elif defined (__SPU__)
      99             : 
     100             : always_inline u64
     101             : clib_cpu_time_now (void)
     102             : {
     103             : #ifdef _XLC
     104             :   return spu_rdch (0x8);
     105             : #else
     106             :   return 0 /* __builtin_si_rdch (0x8) FIXME */ ;
     107             : #endif
     108             : }
     109             : 
     110             : #elif defined (__powerpc__)
     111             : 
     112             : always_inline u64
     113             : clib_cpu_time_now (void)
     114             : {
     115             :   u32 hi1, hi2, lo;
     116             :   asm volatile ("1:\n"
     117             :                 "mftbu %[hi1]\n"
     118             :                 "mftb  %[lo]\n"
     119             :                 "mftbu %[hi2]\n"
     120             :                 "cmpw %[hi1],%[hi2]\n"
     121             :                 "bne 1b\n":[hi1] "=r" (hi1),[hi2] "=r" (hi2),[lo] "=r" (lo));
     122             :   return (u64) lo + ((u64) hi2 << (u64) 32);
     123             : }
     124             : 
     125             : #elif defined (__aarch64__)
     126             : always_inline u64
     127             : clib_cpu_time_now (void)
     128             : {
     129             :   u64 vct;
     130             :   /* User access to cntvct_el0 is enabled in Linux kernel since 3.12. */
     131             :   asm volatile ("mrs %0, cntvct_el0":"=r" (vct));
     132             :   return vct;
     133             : }
     134             : 
     135             : #elif defined (__arm__)
     136             : #if defined(__ARM_ARCH_8A__)
     137             : always_inline u64
     138             : clib_cpu_time_now (void)        /* We may run arm64 in aarch32 mode, to leverage 64bit counter */
     139             : {
     140             :   u64 tsc;
     141             :   asm volatile ("mrrc p15, 0, %Q0, %R0, c9":"=r" (tsc));
     142             :   return tsc;
     143             : }
     144             : #elif defined(__ARM_ARCH_7A__)
     145             : always_inline u64
     146             : clib_cpu_time_now (void)
     147             : {
     148             :   u32 tsc;
     149             :   asm volatile ("mrc p15, 0, %0, c9, c13, 0":"=r" (tsc));
     150             :   return (u64) tsc;
     151             : }
     152             : #else
     153             : always_inline u64
     154             : clib_cpu_time_now (void)
     155             : {
     156             :   u32 lo;
     157             :   asm volatile ("mrc p15, 0, %[lo], c15, c12, 1":[lo] "=r" (lo));
     158             :   return (u64) lo;
     159             : }
     160             : #endif
     161             : 
     162             : #elif defined (__xtensa__)
     163             : 
     164             : /* Stub for now. */
     165             : always_inline u64
     166             : clib_cpu_time_now (void)
     167             : {
     168             :   return 0;
     169             : }
     170             : 
     171             : #elif defined (__TMS320C6X__)
     172             : 
     173             : always_inline u64
     174             : clib_cpu_time_now (void)
     175             : {
     176             :   u32 l, h;
     177             : 
     178             :   asm volatile (" dint\n"
     179             :                 " mvc .s2 TSCL,%0\n"
     180             :                 " mvc .s2 TSCH,%1\n" " rint\n":"=b" (l), "=b" (h));
     181             : 
     182             :   return ((u64) h << 32) | l;
     183             : }
     184             : 
     185             : #elif defined(_mips) && __mips == 64
     186             : 
     187             : always_inline u64
     188             : clib_cpu_time_now (void)
     189             : {
     190             :   u64 result;
     191             :   asm volatile ("rdhwr %0,$31\n":"=r" (result));
     192             :   return result;
     193             : }
     194             : 
     195             : #elif defined(__riscv)
     196             : 
     197             : always_inline u64
     198             : clib_cpu_time_now (void)
     199             : {
     200             :   u64 result;
     201             :   asm volatile("rdcycle %0\n" : "=r"(result));
     202             :   return result;
     203             : }
     204             : #else
     205             : #error "don't know how to read CPU time stamp"
     206             : 
     207             : #endif
     208             : 
     209             : void clib_time_verify_frequency (clib_time_t * c);
     210             : 
     211             : /* Define it as the type returned by clib_time_now */
     212             : typedef f64 clib_time_type_t;
     213             : typedef u64 clib_us_time_t;
     214             : 
     215             : #define CLIB_US_TIME_PERIOD (1e-6)
     216             : #define CLIB_US_TIME_FREQ (1.0/CLIB_US_TIME_PERIOD)
     217             : 
     218             : always_inline f64
     219  1698365737 : clib_time_now_internal (clib_time_t * c, u64 n)
     220             : {
     221  1698365737 :   u64 l = c->last_cpu_time;
     222  1698365737 :   u64 t = c->total_cpu_time;
     223             :   f64 rv;
     224  1698365737 :   t += n - l;
     225  1698365737 :   c->total_cpu_time = t;
     226  1698365737 :   c->last_cpu_time = n;
     227  1698365737 :   rv = t * c->seconds_per_clock;
     228  1698365737 :   if (PREDICT_FALSE
     229             :       ((c->last_cpu_time -
     230             :         c->last_verify_cpu_time) >> c->log2_clocks_per_frequency_verify))
     231         470 :     clib_time_verify_frequency (c);
     232  1698984748 :   return rv;
     233             : }
     234             : 
     235             : /* Maximum f64 value as max clib_time */
     236             : #define CLIB_TIME_MAX (1.7976931348623157e+308)
     237             : 
     238             : always_inline f64
     239  1146442170 : clib_time_now (clib_time_t * c)
     240             : {
     241  1146442170 :   return clib_time_now_internal (c, clib_cpu_time_now ());
     242             : }
     243             : 
     244             : always_inline void
     245             : clib_cpu_time_wait (u64 dt)
     246             : {
     247             :   u64 t_end = clib_cpu_time_now () + dt;
     248             :   while (clib_cpu_time_now () < t_end)
     249             :     ;
     250             : }
     251             : 
     252             : void clib_time_init (clib_time_t * c);
     253             : 
     254             : #ifdef CLIB_UNIX
     255             : 
     256             : #include <time.h>
     257             : #include <sys/time.h>
     258             : #include <sys/resource.h>
     259             : #include <unistd.h>
     260             : #include <sys/syscall.h>
     261             : 
     262             : /* Use 64bit floating point to represent time offset from epoch. */
     263             : always_inline f64
     264        3992 : unix_time_now (void)
     265             : {
     266             :   struct timespec ts;
     267             : #ifdef __MACH__
     268             :   clock_gettime (CLOCK_REALTIME, &ts);
     269             : #else
     270             :   /* clock_gettime without indirect syscall uses GLIBC wrappers which
     271             :      we don't want.  Just the bare metal, please. */
     272        3992 :   syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
     273             : #endif
     274        3996 :   return ts.tv_sec + 1e-9 * ts.tv_nsec;
     275             : }
     276             : 
     277             : /* As above but integer number of nano-seconds. */
     278             : always_inline u64
     279        1677 : unix_time_now_nsec (void)
     280             : {
     281             :   struct timespec ts;
     282             : #ifdef __MACH__
     283             :   clock_gettime (CLOCK_REALTIME, &ts);
     284             : #else
     285        1677 :   syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
     286             : #endif
     287        1677 :   return 1e9 * ts.tv_sec + ts.tv_nsec;
     288             : }
     289             : 
     290             : always_inline void
     291         182 : unix_time_now_nsec_fraction (u32 * sec, u32 * nsec)
     292             : {
     293             :   struct timespec ts;
     294             : #ifdef __MACH__
     295             :   clock_gettime (CLOCK_REALTIME, &ts);
     296             : #else
     297         182 :   syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts);
     298             : #endif
     299         182 :   *sec = ts.tv_sec;
     300         182 :   *nsec = ts.tv_nsec;
     301         182 : }
     302             : 
     303             : always_inline f64
     304             : unix_usage_now (void)
     305             : {
     306             :   struct rusage u;
     307             :   getrusage (RUSAGE_SELF, &u);
     308             :   return u.ru_utime.tv_sec + 1e-6 * u.ru_utime.tv_usec
     309             :     + u.ru_stime.tv_sec + 1e-6 * u.ru_stime.tv_usec;
     310             : }
     311             : 
     312             : always_inline void
     313             : unix_sleep (f64 dt)
     314             : {
     315             :   struct timespec ts, tsrem;
     316             :   ts.tv_sec = dt;
     317             :   ts.tv_nsec = 1e9 * (dt - (f64) ts.tv_sec);
     318             : 
     319             :   while (nanosleep (&ts, &tsrem) < 0)
     320             :     ts = tsrem;
     321             : }
     322             : 
     323             : #else /* ! CLIB_UNIX */
     324             : 
     325             : always_inline f64
     326             : unix_time_now (void)
     327             : {
     328             :   return 0;
     329             : }
     330             : 
     331             : always_inline u64
     332             : unix_time_now_nsec (void)
     333             : {
     334             :   return 0;
     335             : }
     336             : 
     337             : always_inline void
     338             : unix_time_now_nsec_fraction (u32 * sec, u32 * nsec)
     339             : {
     340             : }
     341             : 
     342             : always_inline f64
     343             : unix_usage_now (void)
     344             : {
     345             :   return 0;
     346             : }
     347             : 
     348             : always_inline void
     349             : unix_sleep (f64 dt)
     350             : {
     351             : }
     352             : 
     353             : #endif
     354             : 
     355             : #endif /* included_time_h */
     356             : 
     357             : /*
     358             :  * fd.io coding-style-patch-verification: ON
     359             :  *
     360             :  * Local Variables:
     361             :  * eval: (c-set-style "gnu")
     362             :  * End:
     363             :  */

Generated by: LCOV version 1.14