aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/iomgr/exec_ctx.cc
diff options
context:
space:
mode:
authorGravatar Noah Eisen <ncteisen@google.com>2017-11-13 16:44:02 -0800
committerGravatar Noah Eisen <ncteisen@google.com>2017-11-13 16:44:02 -0800
commit68bb1bf7480e87005220003985da19ea0a0929d0 (patch)
treec434576b07f94f427925dd7f7dfba4dbdeecee31 /src/core/lib/iomgr/exec_ctx.cc
parent6bf73e8cf6d9d2ede844ab628a0b88000ffc9afa (diff)
parentb0bad8f3864dc9c8745736fe68efe513b2b84932 (diff)
Merge branch 'master' of https://github.com/grpc/grpc into tracing++
Diffstat (limited to 'src/core/lib/iomgr/exec_ctx.cc')
-rw-r--r--src/core/lib/iomgr/exec_ctx.cc78
1 files changed, 67 insertions, 11 deletions
diff --git a/src/core/lib/iomgr/exec_ctx.cc b/src/core/lib/iomgr/exec_ctx.cc
index 6661f677f7..b637da377e 100644
--- a/src/core/lib/iomgr/exec_ctx.cc
+++ b/src/core/lib/iomgr/exec_ctx.cc
@@ -25,6 +25,9 @@
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/profiling/timers.h"
+#define GRPC_START_TIME_UPDATE_INTERVAL 10000
+extern grpc_core::TraceFlag grpc_timer_check_trace;
+
bool grpc_exec_ctx_ready_to_finish(grpc_exec_ctx* exec_ctx) {
if ((exec_ctx->flags & GRPC_EXEC_CTX_FLAG_IS_FINISHED) == 0) {
if (exec_ctx->check_ready_to_finish(exec_ctx,
@@ -47,7 +50,7 @@ bool grpc_always_ready_to_finish(grpc_exec_ctx* exec_ctx, void* arg_ignored) {
}
bool grpc_exec_ctx_has_work(grpc_exec_ctx* exec_ctx) {
- return exec_ctx->active_combiner != NULL ||
+ return exec_ctx->active_combiner != nullptr ||
!grpc_closure_list_empty(exec_ctx->closure_list);
}
@@ -82,8 +85,8 @@ bool grpc_exec_ctx_flush(grpc_exec_ctx* exec_ctx) {
for (;;) {
if (!grpc_closure_list_empty(exec_ctx->closure_list)) {
grpc_closure* c = exec_ctx->closure_list.head;
- exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL;
- while (c != NULL) {
+ exec_ctx->closure_list.head = exec_ctx->closure_list.tail = nullptr;
+ while (c != nullptr) {
grpc_closure* next = c->next_data.next;
grpc_error* error = c->error_data.error;
did_something = true;
@@ -94,7 +97,7 @@ bool grpc_exec_ctx_flush(grpc_exec_ctx* exec_ctx) {
break;
}
}
- GPR_ASSERT(exec_ctx->active_combiner == NULL);
+ GPR_ASSERT(exec_ctx->active_combiner == nullptr);
GPR_TIMER_END("grpc_exec_ctx_flush", 0);
return did_something;
}
@@ -104,23 +107,49 @@ static void exec_ctx_sched(grpc_exec_ctx* exec_ctx, grpc_closure* closure,
grpc_closure_list_append(&exec_ctx->closure_list, closure, error);
}
-static gpr_timespec
+/* This time pair is not entirely thread-safe as store/load of tv_sec and
+ * tv_nsec are performed separately. However g_start_time do not need to have
+ * sub-second precision, so it is ok if the value of tv_nsec is off in this
+ * case. */
+typedef struct time_atm_pair {
+ gpr_atm tv_sec;
+ gpr_atm tv_nsec;
+} time_atm_pair;
+
+static time_atm_pair
g_start_time[GPR_TIMESPAN + 1]; // assumes GPR_TIMESPAN is the
// last enum value in
// gpr_clock_type
+static grpc_millis g_last_start_time_update;
+
+static gpr_timespec timespec_from_time_atm_pair(const time_atm_pair* src,
+ gpr_clock_type clock_type) {
+ gpr_timespec time;
+ time.tv_nsec = (int32_t)gpr_atm_no_barrier_load(&src->tv_nsec);
+ time.tv_sec = (int64_t)gpr_atm_no_barrier_load(&src->tv_sec);
+ time.clock_type = clock_type;
+ return time;
+}
+
+static void time_atm_pair_store(time_atm_pair* dst, const gpr_timespec src) {
+ gpr_atm_no_barrier_store(&dst->tv_sec, src.tv_sec);
+ gpr_atm_no_barrier_store(&dst->tv_nsec, src.tv_nsec);
+}
void grpc_exec_ctx_global_init(void) {
for (int i = 0; i < GPR_TIMESPAN; i++) {
- g_start_time[i] = gpr_now((gpr_clock_type)i);
+ time_atm_pair_store(&g_start_time[i], gpr_now((gpr_clock_type)i));
}
// allows uniform treatment in conversion functions
- g_start_time[GPR_TIMESPAN] = gpr_time_0(GPR_TIMESPAN);
+ time_atm_pair_store(&g_start_time[GPR_TIMESPAN], gpr_time_0(GPR_TIMESPAN));
}
void grpc_exec_ctx_global_shutdown(void) {}
static gpr_atm timespec_to_atm_round_down(gpr_timespec ts) {
- ts = gpr_time_sub(ts, g_start_time[ts.clock_type]);
+ gpr_timespec start_time =
+ timespec_from_time_atm_pair(&g_start_time[ts.clock_type], ts.clock_type);
+ ts = gpr_time_sub(ts, start_time);
double x =
GPR_MS_PER_SEC * (double)ts.tv_sec + (double)ts.tv_nsec / GPR_NS_PER_MS;
if (x < 0) return 0;
@@ -129,7 +158,9 @@ static gpr_atm timespec_to_atm_round_down(gpr_timespec ts) {
}
static gpr_atm timespec_to_atm_round_up(gpr_timespec ts) {
- ts = gpr_time_sub(ts, g_start_time[ts.clock_type]);
+ gpr_timespec start_time =
+ timespec_from_time_atm_pair(&g_start_time[ts.clock_type], ts.clock_type);
+ ts = gpr_time_sub(ts, start_time);
double x = GPR_MS_PER_SEC * (double)ts.tv_sec +
(double)ts.tv_nsec / GPR_NS_PER_MS +
(double)(GPR_NS_PER_SEC - 1) / (double)GPR_NS_PER_SEC;
@@ -164,8 +195,9 @@ gpr_timespec grpc_millis_to_timespec(grpc_millis millis,
if (clock_type == GPR_TIMESPAN) {
return gpr_time_from_millis(millis, GPR_TIMESPAN);
}
- return gpr_time_add(g_start_time[clock_type],
- gpr_time_from_millis(millis, GPR_TIMESPAN));
+ gpr_timespec start_time =
+ timespec_from_time_atm_pair(&g_start_time[clock_type], clock_type);
+ return gpr_time_add(start_time, gpr_time_from_millis(millis, GPR_TIMESPAN));
}
grpc_millis grpc_timespec_to_millis_round_down(gpr_timespec ts) {
@@ -176,6 +208,30 @@ grpc_millis grpc_timespec_to_millis_round_up(gpr_timespec ts) {
return timespec_to_atm_round_up(ts);
}
+void grpc_exec_ctx_maybe_update_start_time(grpc_exec_ctx* exec_ctx) {
+ grpc_millis now = grpc_exec_ctx_now(exec_ctx);
+ grpc_millis last_start_time_update =
+ gpr_atm_no_barrier_load(&g_last_start_time_update);
+
+ if (now > last_start_time_update &&
+ now - last_start_time_update > GRPC_START_TIME_UPDATE_INTERVAL) {
+ /* Get the current system time and subtract \a now from it, where \a now is
+ * the relative time from grpc_init() from monotonic clock. This calibrates
+ * the time when grpc_exec_ctx_global_init was called based on current
+ * system clock. */
+ gpr_atm_no_barrier_store(&g_last_start_time_update, now);
+ gpr_timespec real_now = gpr_now(GPR_CLOCK_REALTIME);
+ gpr_timespec real_start_time =
+ gpr_time_sub(real_now, gpr_time_from_millis(now, GPR_TIMESPAN));
+ time_atm_pair_store(&g_start_time[GPR_CLOCK_REALTIME], real_start_time);
+
+ if (grpc_timer_check_trace.enabled()) {
+ gpr_log(GPR_DEBUG, "Update realtime clock start time: %" PRId64 "s %dns",
+ real_start_time.tv_sec, real_start_time.tv_nsec);
+ }
+ }
+}
+
static const grpc_closure_scheduler_vtable exec_ctx_scheduler_vtable = {
exec_ctx_run, exec_ctx_sched, "exec_ctx"};
static grpc_closure_scheduler exec_ctx_scheduler = {&exec_ctx_scheduler_vtable};