1 /* 2 * 3 * Copyright 2015 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #include <grpc/support/port_platform.h> 20 21 #include <grpc/support/log.h> 22 #include <grpc/support/time.h> 23 #include <stdio.h> 24 25 #include "src/core/lib/gpr/time_precise.h" 26 27 #ifdef GRPC_TIMERS_RDTSC 28 #if defined(__i386__) gpr_get_cycle_counter(int64_t int * clk)29static void gpr_get_cycle_counter(int64_t int* clk) { 30 int64_t int ret; 31 __asm__ volatile("rdtsc" : "=A"(ret)); 32 *clk = ret; 33 } 34 35 // ---------------------------------------------------------------- 36 #elif defined(__x86_64__) || defined(__amd64__) gpr_get_cycle_counter(int64_t * clk)37static void gpr_get_cycle_counter(int64_t* clk) { 38 uint64_t low, high; 39 __asm__ volatile("rdtsc" : "=a"(low), "=d"(high)); 40 *clk = (int64_t)(high << 32) | (int64_t)low; 41 } 42 #endif 43 44 static double cycles_per_second = 0; 45 static int64_t start_cycle; gpr_precise_clock_init(void)46void gpr_precise_clock_init(void) { 47 time_t start; 48 int64_t end_cycle; 49 gpr_log(GPR_DEBUG, "Calibrating timers"); 50 start = time(NULL); 51 while (time(NULL) == start) 52 ; 53 gpr_get_cycle_counter(&start_cycle); 54 while (time(NULL) <= start + 10) 55 ; 56 gpr_get_cycle_counter(&end_cycle); 57 cycles_per_second = (double)(end_cycle - start_cycle) / 10.0; 58 gpr_log(GPR_DEBUG, "... cycles_per_second = %f\n", cycles_per_second); 59 } 60 gpr_precise_clock_now(gpr_timespec * clk)61void gpr_precise_clock_now(gpr_timespec* clk) { 62 int64_t counter; 63 double secs; 64 gpr_get_cycle_counter(&counter); 65 secs = (double)(counter - start_cycle) / cycles_per_second; 66 clk->clock_type = GPR_CLOCK_PRECISE; 67 clk->tv_sec = (int64_t)secs; 68 clk->tv_nsec = (int32_t)(1e9 * (secs - (double)clk->tv_sec)); 69 } 70 71 #else /* GRPC_TIMERS_RDTSC */ gpr_precise_clock_init(void)72void gpr_precise_clock_init(void) {} 73 gpr_precise_clock_now(gpr_timespec * clk)74void gpr_precise_clock_now(gpr_timespec* clk) { 75 *clk = gpr_now(GPR_CLOCK_REALTIME); 76 clk->clock_type = GPR_CLOCK_PRECISE; 77 } 78 #endif /* GRPC_TIMERS_RDTSC */ 79