time_precise.cc 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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. #include <grpc/support/port_platform.h>
  19. #include <grpc/support/log.h>
  20. #include <grpc/support/time.h>
  21. #include <stdio.h>
  22. #include "src/core/lib/gpr/time_precise.h"
  23. #ifdef GRPC_TIMERS_RDTSC
  24. #if defined(__i386__)
  25. static void gpr_get_cycle_counter(int64_t int* clk) {
  26. int64_t int ret;
  27. __asm__ volatile("rdtsc" : "=A"(ret));
  28. *clk = ret;
  29. }
  30. // ----------------------------------------------------------------
  31. #elif defined(__x86_64__) || defined(__amd64__)
  32. static void gpr_get_cycle_counter(int64_t* clk) {
  33. uint64_t low, high;
  34. __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
  35. *clk = (int64_t)(high << 32) | (int64_t)low;
  36. }
  37. #endif
  38. static double cycles_per_second = 0;
  39. static int64_t start_cycle;
  40. void gpr_precise_clock_init(void) {
  41. time_t start;
  42. int64_t end_cycle;
  43. gpr_log(GPR_DEBUG, "Calibrating timers");
  44. start = time(NULL);
  45. while (time(NULL) == start)
  46. ;
  47. gpr_get_cycle_counter(&start_cycle);
  48. while (time(NULL) <= start + 10)
  49. ;
  50. gpr_get_cycle_counter(&end_cycle);
  51. cycles_per_second = (double)(end_cycle - start_cycle) / 10.0;
  52. gpr_log(GPR_DEBUG, "... cycles_per_second = %f\n", cycles_per_second);
  53. }
  54. void gpr_precise_clock_now(gpr_timespec* clk) {
  55. int64_t counter;
  56. double secs;
  57. gpr_get_cycle_counter(&counter);
  58. secs = (double)(counter - start_cycle) / cycles_per_second;
  59. clk->clock_type = GPR_CLOCK_PRECISE;
  60. clk->tv_sec = (int64_t)secs;
  61. clk->tv_nsec = (int32_t)(1e9 * (secs - (double)clk->tv_sec));
  62. }
  63. #else /* GRPC_TIMERS_RDTSC */
  64. void gpr_precise_clock_init(void) {}
  65. void gpr_precise_clock_now(gpr_timespec* clk) {
  66. *clk = gpr_now(GPR_CLOCK_REALTIME);
  67. clk->clock_type = GPR_CLOCK_PRECISE;
  68. }
  69. #endif /* GRPC_TIMERS_RDTSC */