blob: f999e08cb08abf513cff539ebcea3f128ee46733 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tillerf215f182016-02-01 16:16:14 -08003 * Copyright 2015-2016, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
nnoble0c475f02014-12-05 15:37:39 -080034#include <grpc/support/port_platform.h>
Hongyu Chena0f149e2015-08-24 16:27:19 -070035#include <src/core/support/time_precise.h>
nnoble0c475f02014-12-05 15:37:39 -080036
37#ifdef GPR_POSIX_TIME
38
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080039#include <stdlib.h>
40#include <time.h>
41#include <unistd.h>
Craig Tiller22a91392016-02-01 14:34:00 -080042#ifdef __linux__
43#include <sys/syscall.h>
44#endif
Craig Tiller143e7bf2015-07-13 08:41:49 -070045#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080046#include <grpc/support/time.h>
vjpai9839d282015-09-24 17:55:18 -070047#include "src/core/support/block_annotate.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080048
David Klempner9b60fa32015-02-04 09:48:53 -080049static struct timespec timespec_from_gpr(gpr_timespec gts) {
50 struct timespec rv;
Craig Tiller7536af02015-12-22 13:49:30 -080051 if (sizeof(time_t) < sizeof(int64_t)) {
Jan Tattermusch88086372015-12-10 10:54:12 -080052 /* fine to assert, as this is only used in gpr_sleep_until */
Craig Tiller620e9652015-12-14 12:02:50 -080053 GPR_ASSERT(gts.tv_sec <= INT32_MAX && gts.tv_sec >= INT32_MIN);
Jan Tattermusch88086372015-12-10 10:54:12 -080054 }
55 rv.tv_sec = (time_t)gts.tv_sec;
David Klempner9b60fa32015-02-04 09:48:53 -080056 rv.tv_nsec = gts.tv_nsec;
57 return rv;
58}
59
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080060#if _POSIX_TIMERS > 0
Craig Tiller143e7bf2015-07-13 08:41:49 -070061static gpr_timespec gpr_from_timespec(struct timespec ts,
Vijay Pai7b080ba2015-09-29 22:22:36 +000062 gpr_clock_type clock_type) {
Jan Tattermusch88086372015-12-10 10:54:12 -080063 /*
64 * timespec.tv_sec can have smaller size than gpr_timespec.tv_sec,
65 * but we are only using this function to implement gpr_now
66 * so there's no need to handle "infinity" values.
67 */
David Klempner9b60fa32015-02-04 09:48:53 -080068 gpr_timespec rv;
69 rv.tv_sec = ts.tv_sec;
Craig Tiller7536af02015-12-22 13:49:30 -080070 rv.tv_nsec = (int32_t)ts.tv_nsec;
Vijay Pai7b080ba2015-09-29 22:22:36 +000071 rv.clock_type = clock_type;
David Klempner9b60fa32015-02-04 09:48:53 -080072 return rv;
73}
74
Craig Tillerf3756c12015-07-01 17:21:01 -070075/** maps gpr_clock_type --> clockid_t for clock_gettime */
Craig Tiller22a91392016-02-01 14:34:00 -080076static const clockid_t clockid_for_gpr_clock[] = {CLOCK_MONOTONIC,
77 CLOCK_REALTIME};
Craig Tillerf3756c12015-07-01 17:21:01 -070078
Craig Tiller504ed592015-10-08 07:38:43 -070079void gpr_time_init(void) { gpr_precise_clock_init(); }
Craig Tillerf3756c12015-07-01 17:21:01 -070080
Vijay Pai7b080ba2015-09-29 22:22:36 +000081gpr_timespec gpr_now(gpr_clock_type clock_type) {
David Klempner9b60fa32015-02-04 09:48:53 -080082 struct timespec now;
Vijay Pai7b080ba2015-09-29 22:22:36 +000083 GPR_ASSERT(clock_type != GPR_TIMESPAN);
84 if (clock_type == GPR_CLOCK_PRECISE) {
Hongyu Chena0f149e2015-08-24 16:27:19 -070085 gpr_timespec ret;
86 gpr_precise_clock_now(&ret);
87 return ret;
88 } else {
Craig Tiller71ea4a12016-02-04 15:06:41 -080089#if defined(GPR_BACKWARDS_COMPATIBILITY_MODE) && defined(__linux__)
Craig Tiller22a91392016-02-01 14:34:00 -080090 /* avoid ABI problems by invoking syscalls directly */
91 syscall(SYS_clock_gettime, clockid_for_gpr_clock[clock_type], &now);
92#else
Vijay Pai7b080ba2015-09-29 22:22:36 +000093 clock_gettime(clockid_for_gpr_clock[clock_type], &now);
Craig Tiller22a91392016-02-01 14:34:00 -080094#endif
Vijay Pai7b080ba2015-09-29 22:22:36 +000095 return gpr_from_timespec(now, clock_type);
Hongyu Chena0f149e2015-08-24 16:27:19 -070096 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080097}
98#else
99/* For some reason Apple's OSes haven't implemented clock_gettime. */
vjpaic2340872015-02-13 11:12:36 -0800100
Craig Tillerf3756c12015-07-01 17:21:01 -0700101#include <mach/mach.h>
102#include <mach/mach_time.h>
Craig Tillerf40df232016-03-25 13:38:14 -0700103#include <sys/time.h>
vjpaic2340872015-02-13 11:12:36 -0800104
Craig Tillerf3756c12015-07-01 17:21:01 -0700105static double g_time_scale;
106static uint64_t g_time_start;
107
108void gpr_time_init(void) {
Craig Tillerf1bff012015-07-06 11:20:50 -0700109 mach_timebase_info_data_t tb = {0, 1};
Craig Tiller1c4319a2015-10-08 08:43:37 -0700110 gpr_precise_clock_init();
Craig Tillerf3756c12015-07-01 17:21:01 -0700111 mach_timebase_info(&tb);
112 g_time_scale = tb.numer;
113 g_time_scale /= tb.denom;
114 g_time_start = mach_absolute_time();
115}
116
117gpr_timespec gpr_now(gpr_clock_type clock) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800118 gpr_timespec now;
119 struct timeval now_tv;
Craig Tillerf3756c12015-07-01 17:21:01 -0700120 double now_dbl;
121
Craig Tiller21038ce2015-07-14 06:55:47 -0700122 now.clock_type = clock;
Craig Tillerf3756c12015-07-01 17:21:01 -0700123 switch (clock) {
124 case GPR_CLOCK_REALTIME:
125 gettimeofday(&now_tv, NULL);
126 now.tv_sec = now_tv.tv_sec;
127 now.tv_nsec = now_tv.tv_usec * 1000;
128 break;
129 case GPR_CLOCK_MONOTONIC:
130 now_dbl = (mach_absolute_time() - g_time_start) * g_time_scale;
Craig Tiller7536af02015-12-22 13:49:30 -0800131 now.tv_sec = (int64_t)(now_dbl * 1e-9);
132 now.tv_nsec = (int32_t)(now_dbl - ((double)now.tv_sec) * 1e9);
Craig Tillerf3756c12015-07-01 17:21:01 -0700133 break;
Hongyu Chena0f149e2015-08-24 16:27:19 -0700134 case GPR_CLOCK_PRECISE:
135 gpr_precise_clock_now(&now);
136 break;
Craig Tiller143e7bf2015-07-13 08:41:49 -0700137 case GPR_TIMESPAN:
138 abort();
Craig Tillerf3756c12015-07-01 17:21:01 -0700139 }
140
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800141 return now;
142}
143#endif
144
145void gpr_sleep_until(gpr_timespec until) {
146 gpr_timespec now;
147 gpr_timespec delta;
David Klempner9b60fa32015-02-04 09:48:53 -0800148 struct timespec delta_ts;
vjpai50d65342015-09-24 17:25:35 -0700149 int ns_result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800150
151 for (;;) {
152 /* We could simplify by using clock_nanosleep instead, but it might be
153 * slightly less portable. */
Craig Tiller6a7626c2015-07-19 22:21:41 -0700154 now = gpr_now(until.clock_type);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800155 if (gpr_time_cmp(until, now) <= 0) {
156 return;
157 }
158
159 delta = gpr_time_sub(until, now);
David Klempner9b60fa32015-02-04 09:48:53 -0800160 delta_ts = timespec_from_gpr(delta);
vjpai9839d282015-09-24 17:55:18 -0700161 GRPC_SCHEDULING_START_BLOCKING_REGION;
vjpai50d65342015-09-24 17:25:35 -0700162 ns_result = nanosleep(&delta_ts, NULL);
vjpai9839d282015-09-24 17:55:18 -0700163 GRPC_SCHEDULING_END_BLOCKING_REGION;
vjpai50d65342015-09-24 17:25:35 -0700164 if (ns_result == 0) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800165 break;
166 }
167 }
168}
nnoble0c475f02014-12-05 15:37:39 -0800169
Craig Tiller190d3602015-02-18 09:23:38 -0800170#endif /* GPR_POSIX_TIME */