LCOV - code coverage report
Current view: top level - lib/eal/linux - eal_timer.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 16 29 55.2 %
Date: 2026-04-01 20:02:27 Functions: 2 3 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 4 20 20.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2014 Intel Corporation.
       3                 :            :  * Copyright(c) 2012-2013 6WIND S.A.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <stdio.h>
       7                 :            : #include <stdint.h>
       8                 :            : #include <inttypes.h>
       9                 :            : 
      10                 :            : #include <rte_common.h>
      11                 :            : #include <rte_cycles.h>
      12                 :            : #include <rte_thread.h>
      13                 :            : 
      14                 :            : #include <eal_export.h>
      15                 :            : #include "eal_private.h"
      16                 :            : 
      17                 :            : RTE_EXPORT_SYMBOL(eal_timer_source)
      18                 :            : enum timer_source eal_timer_source = EAL_TIMER_HPET;
      19                 :            : 
      20                 :            : /* Check if the kernel deems the arch provided TSC frequency trustworthy. */
      21                 :            : 
      22                 :            : static bool
      23                 :          0 : is_tsc_known_freq(void)
      24                 :            : {
      25                 :            :         bool ret = true; /* Assume tsc_known_freq */
      26                 :            : 
      27                 :            : #if defined(RTE_ARCH_X86)
      28                 :            :         char line[2048];
      29                 :            :         FILE *stream;
      30                 :            : 
      31                 :          0 :         stream = fopen("/proc/cpuinfo", "r");
      32         [ #  # ]:          0 :         if (!stream) {
      33                 :          0 :                 EAL_LOG(WARNING, "Unable to open /proc/cpuinfo");
      34                 :          0 :                 return ret;
      35                 :            :         }
      36                 :            : 
      37         [ #  # ]:          0 :         while (fgets(line, sizeof(line), stream)) {
      38         [ #  # ]:          0 :                 if (strncmp(line, "flags", 5) != 0)
      39                 :          0 :                         continue;
      40                 :            : 
      41         [ #  # ]:          0 :                 if (!strstr(line, "tsc_known_freq"))
      42                 :            :                         ret = false;
      43                 :            : 
      44                 :            :                 break;
      45                 :            :         }
      46                 :            : 
      47                 :          0 :         fclose(stream);
      48                 :            : #endif
      49                 :            : 
      50                 :          0 :         return ret;
      51                 :            : }
      52                 :            : 
      53                 :            : uint64_t
      54                 :        179 : get_tsc_freq(uint64_t arch_hz)
      55                 :            : {
      56                 :            : #ifdef CLOCK_MONOTONIC_RAW
      57                 :            : #define NS_PER_SEC 1E9
      58                 :            : #define CYC_PER_100KHZ 1E5
      59                 :            : 
      60                 :        179 :         struct timespec sleeptime = {.tv_nsec = NS_PER_SEC / 10 }; /* 1/10 second */
      61                 :            : 
      62                 :            :         struct timespec t_start, t_end;
      63                 :            :         uint64_t tsc_hz;
      64                 :            : 
      65   [ -  +  -  - ]:        179 :         if (arch_hz && is_tsc_known_freq())
      66                 :            :                 return arch_hz;
      67                 :            : 
      68         [ +  - ]:        179 :         if (clock_gettime(CLOCK_MONOTONIC_RAW, &t_start) == 0) {
      69                 :            :                 uint64_t ns, end, start = rte_rdtsc();
      70                 :        179 :                 nanosleep(&sleeptime,NULL);
      71                 :        179 :                 clock_gettime(CLOCK_MONOTONIC_RAW, &t_end);
      72                 :            :                 end = rte_rdtsc();
      73                 :        179 :                 ns = ((t_end.tv_sec - t_start.tv_sec) * NS_PER_SEC);
      74                 :        179 :                 ns += (t_end.tv_nsec - t_start.tv_nsec);
      75                 :            : 
      76                 :        179 :                 double secs = (double)ns/NS_PER_SEC;
      77                 :        179 :                 tsc_hz = (uint64_t)((end - start)/secs);
      78                 :            : 
      79         [ -  + ]:        179 :                 if (arch_hz) {
      80                 :            :                         /* Make sure we're within 1% for sanity check */
      81         [ #  # ]:          0 :                         if (RTE_MAX(arch_hz, tsc_hz) - RTE_MIN(arch_hz, tsc_hz) > arch_hz / 100)
      82                 :            :                                 return arch_hz;
      83                 :            : 
      84                 :          0 :                         EAL_LOG(DEBUG,
      85                 :            :                                 "Refined arch frequency %"PRIu64" to measured frequency %"PRIu64,
      86                 :            :                                 arch_hz, tsc_hz);
      87                 :            :                 }
      88                 :            : 
      89                 :            :                 /* Round up to 100Khz. 1E5 ~ 100Khz */
      90         [ +  - ]:        358 :                 return RTE_ALIGN_MUL_NEAR(tsc_hz, CYC_PER_100KHZ);
      91                 :            :         }
      92                 :            : #endif
      93                 :            :         return arch_hz;
      94                 :            : }
      95                 :            : 
      96                 :            : int
      97                 :        204 : rte_eal_timer_init(void)
      98                 :            : {
      99                 :            : 
     100                 :        204 :         eal_timer_source = EAL_TIMER_TSC;
     101                 :            : 
     102                 :        204 :         set_tsc_freq();
     103                 :        204 :         return 0;
     104                 :            : }

Generated by: LCOV version 1.14