time_posix.cc
Go to the documentation of this file.
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 
20 
22 
23 #ifdef GPR_POSIX_TIME
24 
25 #include <stdlib.h>
26 #include <time.h>
27 #include <unistd.h>
28 #ifdef __linux__
29 #include <sys/syscall.h>
30 #endif
31 #include <grpc/support/atm.h>
32 #include <grpc/support/log.h>
33 #include <grpc/support/time.h>
34 
35 static struct timespec timespec_from_gpr(gpr_timespec gts) {
36  struct timespec rv;
37  if (sizeof(time_t) < sizeof(int64_t)) {
38  /* fine to assert, as this is only used in gpr_sleep_until */
39  GPR_ASSERT(gts.tv_sec <= INT32_MAX && gts.tv_sec >= INT32_MIN);
40  }
41  rv.tv_sec = static_cast<time_t>(gts.tv_sec);
42  rv.tv_nsec = gts.tv_nsec;
43  return rv;
44 }
45 
46 #if _POSIX_TIMERS > 0 || defined(__OpenBSD__)
47 static gpr_timespec gpr_from_timespec(struct timespec ts,
48  gpr_clock_type clock_type) {
49  /*
50  * timespec.tv_sec can have smaller size than gpr_timespec.tv_sec,
51  * but we are only using this function to implement gpr_now
52  * so there's no need to handle "infinity" values.
53  */
54  gpr_timespec rv;
55  rv.tv_sec = ts.tv_sec;
56  rv.tv_nsec = static_cast<int32_t>(ts.tv_nsec);
57  rv.clock_type = clock_type;
58  return rv;
59 }
60 
62 static const clockid_t clockid_for_gpr_clock[] = {CLOCK_MONOTONIC,
63  CLOCK_REALTIME};
64 
65 void gpr_time_init(void) { gpr_precise_clock_init(); }
66 
67 static gpr_timespec now_impl(gpr_clock_type clock_type) {
68  struct timespec now;
69  GPR_ASSERT(clock_type != GPR_TIMESPAN);
70  if (clock_type == GPR_CLOCK_PRECISE) {
73  return ret;
74  } else {
75 #if defined(GPR_BACKWARDS_COMPATIBILITY_MODE) && defined(__linux__)
76  /* avoid ABI problems by invoking syscalls directly */
77  syscall(SYS_clock_gettime, clockid_for_gpr_clock[clock_type], &now);
78 #else
79  clock_gettime(clockid_for_gpr_clock[clock_type], &now);
80 #endif
81  return gpr_from_timespec(now, clock_type);
82  }
83 }
84 #else
85 /* For some reason Apple's OSes haven't implemented clock_gettime. */
86 
87 #include <mach/mach.h>
88 #include <mach/mach_time.h>
89 #include <sys/time.h>
90 
91 static double g_time_scale = []() {
92  mach_timebase_info_data_t tb = {0, 1};
93  mach_timebase_info(&tb);
94  return static_cast<double>(tb.numer) / static_cast<double>(tb.denom);
95 }();
96 static uint64_t g_time_start = mach_absolute_time();
97 
98 void gpr_time_init(void) { gpr_precise_clock_init(); }
99 
100 static gpr_timespec now_impl(gpr_clock_type clock) {
102  struct timeval now_tv;
103  double now_dbl;
104 
105  now.clock_type = clock;
106  switch (clock) {
107  case GPR_CLOCK_REALTIME:
108  // gettimeofday(...) function may return with a value whose tv_usec is
109  // greater than 1e6 on iOS The case is resolved with the guard at end of
110  // this function.
111  gettimeofday(&now_tv, nullptr);
112  now.tv_sec = now_tv.tv_sec;
113  now.tv_nsec = now_tv.tv_usec * 1000;
114  break;
115  case GPR_CLOCK_MONOTONIC:
116  now_dbl = ((double)(mach_absolute_time() - g_time_start)) * g_time_scale;
117  now.tv_sec = (int64_t)(now_dbl * 1e-9);
118  now.tv_nsec = (int32_t)(now_dbl - ((double)now.tv_sec) * 1e9);
119  break;
120  case GPR_CLOCK_PRECISE:
122  break;
123  case GPR_TIMESPAN:
124  abort();
125  }
126 
127  // Guard the tv_nsec field in valid range for all clock types
128  while (GPR_UNLIKELY(now.tv_nsec >= 1e9)) {
129  now.tv_sec++;
130  now.tv_nsec -= 1e9;
131  }
132  while (GPR_UNLIKELY(now.tv_nsec < 0)) {
133  now.tv_sec--;
134  now.tv_nsec += 1e9;
135  }
136 
137  return now;
138 }
139 #endif
140 
142 
143 #ifdef GPR_LOW_LEVEL_COUNTERS
144 gpr_atm gpr_now_call_count;
145 #endif
146 gpr_timespec gpr_now(gpr_clock_type clock_type) {
147 #ifdef GPR_LOW_LEVEL_COUNTERS
148  __atomic_fetch_add(&gpr_now_call_count, 1, __ATOMIC_RELAXED);
149 #endif
150  // validate clock type
151  GPR_ASSERT(clock_type == GPR_CLOCK_MONOTONIC ||
152  clock_type == GPR_CLOCK_REALTIME ||
153  clock_type == GPR_CLOCK_PRECISE);
154  gpr_timespec ts = gpr_now_impl(clock_type);
155  // tv_nsecs must be in the range [0, 1e9).
156  GPR_ASSERT(ts.tv_nsec >= 0 && ts.tv_nsec < 1e9);
157  return ts;
158 }
159 
160 void gpr_sleep_until(gpr_timespec until) {
162  gpr_timespec delta;
163  struct timespec delta_ts;
164  int ns_result;
165 
166  for (;;) {
167  /* We could simplify by using clock_nanosleep instead, but it might be
168  * slightly less portable. */
169  now = gpr_now(until.clock_type);
170  if (gpr_time_cmp(until, now) <= 0) {
171  return;
172  }
173 
174  delta = gpr_time_sub(until, now);
175  delta_ts = timespec_from_gpr(delta);
176  ns_result = nanosleep(&delta_ts, nullptr);
177  if (ns_result == 0) {
178  break;
179  }
180  }
181 }
182 
183 #endif /* GPR_POSIX_TIME */
gpr_timespec::tv_nsec
int32_t tv_nsec
Definition: gpr_types.h:52
GPR_TIMESPAN
@ GPR_TIMESPAN
Definition: gpr_types.h:45
gpr_timespec::tv_sec
int64_t tv_sec
Definition: gpr_types.h:51
now
static double now(void)
Definition: test/core/fling/client.cc:130
log.h
gpr_now_impl
gpr_timespec(* gpr_now_impl)(gpr_clock_type clock_type)
nanosleep
int nanosleep(const struct timespec *req, struct timespec *rem)
Definition: os390-syscalls.c:385
gpr_precise_clock_now
void gpr_precise_clock_now(gpr_timespec *clk)
time.h
now_impl
static gpr_timespec now_impl(gpr_clock_type clock_type)
Definition: filter_fuzzer.cc:41
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
gpr_time_cmp
GPRAPI int gpr_time_cmp(gpr_timespec a, gpr_timespec b)
Definition: src/core/lib/gpr/time.cc:30
gpr_time_sub
GPRAPI gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b)
Definition: src/core/lib/gpr/time.cc:168
GPR_UNLIKELY
#define GPR_UNLIKELY(x)
Definition: impl/codegen/port_platform.h:770
gpr_sleep_until
GPRAPI void gpr_sleep_until(gpr_timespec until)
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
syscall
const char * syscall
Definition: third_party/libuv/src/win/internal.h:270
GPR_CLOCK_MONOTONIC
@ GPR_CLOCK_MONOTONIC
Definition: gpr_types.h:36
gpr_now
GPRAPI gpr_timespec gpr_now(gpr_clock_type clock)
gpr_timespec::clock_type
gpr_clock_type clock_type
Definition: gpr_types.h:55
GPR_CLOCK_PRECISE
@ GPR_CLOCK_PRECISE
Definition: gpr_types.h:42
gpr_atm
intptr_t gpr_atm
Definition: impl/codegen/atm_gcc_atomic.h:32
INT32_MIN
#define INT32_MIN
Definition: stdint-msvc2008.h:136
gpr_timespec
struct gpr_timespec gpr_timespec
timeval
Definition: setup_once.h:113
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
atm.h
gpr_timespec
Definition: gpr_types.h:50
GPR_CLOCK_REALTIME
@ GPR_CLOCK_REALTIME
Definition: gpr_types.h:39
INT32_MAX
#define INT32_MAX
Definition: stdint-msvc2008.h:137
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
gpr_time_init
GPRAPI void gpr_time_init(void)
gpr_precise_clock_init
void gpr_precise_clock_init(void)
gpr_clock_type
gpr_clock_type
Definition: gpr_types.h:34
time_precise.h
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:37