1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <string.h> 6 #include <stdio.h> 7 #include <unistd.h> 8 #include <inttypes.h> 9 #include <sys/types.h> 10 #include <time.h> 11 #include <errno.h> 12 13 #include <rte_common.h> 14 #include <rte_compat.h> 15 #include <rte_log.h> 16 #include <rte_cycles.h> 17 #include <rte_pause.h> 18 19 #include "eal_private.h" 20 21 /* The frequency of the RDTSC timer resolution */ 22 static uint64_t eal_tsc_resolution_hz; 23 24 /* Pointer to user delay function */ 25 void (*rte_delay_us)(unsigned int) = NULL; 26 27 void 28 rte_delay_us_block(unsigned int us) 29 { 30 const uint64_t start = rte_get_timer_cycles(); 31 const uint64_t ticks = (uint64_t)us * rte_get_timer_hz() / 1E6; 32 while ((rte_get_timer_cycles() - start) < ticks) 33 rte_pause(); 34 } 35 36 void __rte_experimental 37 rte_delay_us_sleep(unsigned int us) 38 { 39 struct timespec wait[2]; 40 int ind = 0; 41 42 wait[0].tv_sec = 0; 43 if (us >= US_PER_S) { 44 wait[0].tv_sec = us / US_PER_S; 45 us -= wait[0].tv_sec * US_PER_S; 46 } 47 wait[0].tv_nsec = 1000 * us; 48 49 while (nanosleep(&wait[ind], &wait[1 - ind]) && errno == EINTR) { 50 /* 51 * Sleep was interrupted. Flip the index, so the 'remainder' 52 * will become the 'request' for a next call. 53 */ 54 ind = 1 - ind; 55 } 56 } 57 58 uint64_t 59 rte_get_tsc_hz(void) 60 { 61 return eal_tsc_resolution_hz; 62 } 63 64 static uint64_t 65 estimate_tsc_freq(void) 66 { 67 RTE_LOG(WARNING, EAL, "WARNING: TSC frequency estimated roughly" 68 " - clock timings may be less accurate.\n"); 69 /* assume that the sleep(1) will sleep for 1 second */ 70 uint64_t start = rte_rdtsc(); 71 sleep(1); 72 return rte_rdtsc() - start; 73 } 74 75 void 76 set_tsc_freq(void) 77 { 78 uint64_t freq; 79 80 freq = get_tsc_freq_arch(); 81 if (!freq) 82 freq = get_tsc_freq(); 83 if (!freq) 84 freq = estimate_tsc_freq(); 85 86 RTE_LOG(DEBUG, EAL, "TSC frequency is ~%" PRIu64 " KHz\n", freq / 1000); 87 eal_tsc_resolution_hz = freq; 88 } 89 90 void rte_delay_us_callback_register(void (*userfunc)(unsigned int)) 91 { 92 rte_delay_us = userfunc; 93 } 94 95 RTE_INIT(rte_timer_init) 96 { 97 /* set rte_delay_us_block as a delay function */ 98 rte_delay_us_callback_register(rte_delay_us_block); 99 } 100