• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)29 static 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)37 static 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)46 void 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)61 void 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)72 void gpr_precise_clock_init(void) {}
73 
gpr_precise_clock_now(gpr_timespec * clk)74 void 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