|
|
|
@ -187,12 +187,10 @@ static double ts_to_dbl(gpr_timespec ts) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* returns true if the first element in the list */ |
|
|
|
|
static bool list_join(grpc_timer *head, grpc_timer *timer) { |
|
|
|
|
bool is_first = head->next == head; |
|
|
|
|
static void list_join(grpc_timer *head, grpc_timer *timer) { |
|
|
|
|
timer->next = head; |
|
|
|
|
timer->prev = head->prev; |
|
|
|
|
timer->next->prev = timer->prev->next = timer; |
|
|
|
|
return is_first; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void list_remove(grpc_timer *timer) { |
|
|
|
@ -267,8 +265,7 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer, |
|
|
|
|
is_first_timer = grpc_timer_heap_add(&shard->heap, timer); |
|
|
|
|
} else { |
|
|
|
|
timer->heap_index = INVALID_HEAP_INDEX; |
|
|
|
|
is_first_timer = list_join(&shard->list, timer) && |
|
|
|
|
grpc_timer_heap_is_empty(&shard->heap); |
|
|
|
|
list_join(&shard->list, timer); |
|
|
|
|
} |
|
|
|
|
if (grpc_timer_trace) { |
|
|
|
|
gpr_log(GPR_DEBUG, " .. add to shard %d with queue_deadline_cap=%" PRIdPTR |
|
|
|
@ -428,15 +425,7 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_atm now, |
|
|
|
|
gpr_atm *next, grpc_error *error) { |
|
|
|
|
size_t n = 0; |
|
|
|
|
|
|
|
|
|
/* fetch from a thread-local first: this avoids contention on a globally
|
|
|
|
|
mutable cacheline in the common case */ |
|
|
|
|
gpr_atm min_timer = gpr_tls_get(&g_last_seen_min_timer); |
|
|
|
|
if (now < min_timer) { |
|
|
|
|
if (next != NULL) *next = GPR_MIN(*next, min_timer); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
min_timer = gpr_atm_no_barrier_load(&g_shared_mutables.min_timer); |
|
|
|
|
gpr_atm min_timer = gpr_atm_no_barrier_load(&g_shared_mutables.min_timer); |
|
|
|
|
gpr_tls_set(&g_last_seen_min_timer, min_timer); |
|
|
|
|
if (now < min_timer) { |
|
|
|
|
if (next != NULL) *next = GPR_MIN(*next, min_timer); |
|
|
|
@ -499,10 +488,28 @@ bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, |
|
|
|
|
// prelude
|
|
|
|
|
GPR_ASSERT(now.clock_type == g_clock_type); |
|
|
|
|
gpr_atm now_atm = timespec_to_atm_round_down(now); |
|
|
|
|
|
|
|
|
|
/* fetch from a thread-local first: this avoids contention on a globally
|
|
|
|
|
mutable cacheline in the common case */ |
|
|
|
|
gpr_atm min_timer = gpr_tls_get(&g_last_seen_min_timer); |
|
|
|
|
if (now_atm < min_timer) { |
|
|
|
|
if (next != NULL) { |
|
|
|
|
*next = |
|
|
|
|
atm_to_timespec(GPR_MIN(timespec_to_atm_round_up(*next), min_timer)); |
|
|
|
|
} |
|
|
|
|
if (grpc_timer_check_trace) { |
|
|
|
|
gpr_log(GPR_DEBUG, |
|
|
|
|
"TIMER CHECK SKIP: now_atm=%" PRId64 " min_timer=%" PRId64, |
|
|
|
|
now_atm, min_timer); |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_error *shutdown_error = |
|
|
|
|
gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0 |
|
|
|
|
? GRPC_ERROR_NONE |
|
|
|
|
: GRPC_ERROR_CREATE_FROM_STATIC_STRING("Shutting down timer system"); |
|
|
|
|
|
|
|
|
|
// tracing
|
|
|
|
|
if (grpc_timer_check_trace) { |
|
|
|
|
char *next_str; |
|
|
|
|