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 : : }