|
|
|
@ -62,6 +62,7 @@ struct grpc_combiner { |
|
|
|
|
// offload safely
|
|
|
|
|
gpr_atm covered_by_poller; |
|
|
|
|
bool time_to_execute_final_list; |
|
|
|
|
bool final_list_covered_by_poller; |
|
|
|
|
grpc_closure_list final_list; |
|
|
|
|
grpc_closure offload; |
|
|
|
|
}; |
|
|
|
@ -81,6 +82,11 @@ static error_data unpack_error_data(uintptr_t p) { |
|
|
|
|
return (error_data){(grpc_error *)(p & ~(uintptr_t)1), p & 1}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool is_covered_by_poller(grpc_combiner *lock) { |
|
|
|
|
return lock->final_list_covered_by_poller || |
|
|
|
|
gpr_atm_acq_load(&lock->covered_by_poller) > 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { |
|
|
|
|
grpc_combiner *lock = gpr_malloc(sizeof(*lock)); |
|
|
|
|
lock->next_combiner_on_this_exec_ctx = NULL; |
|
|
|
@ -183,8 +189,7 @@ bool grpc_combiner_continue_exec_ctx(grpc_exec_ctx *exec_ctx) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (lock->optional_workqueue != NULL && |
|
|
|
|
grpc_exec_ctx_ready_to_finish(exec_ctx) && |
|
|
|
|
gpr_atm_acq_load(&lock->covered_by_poller) > 0) { |
|
|
|
|
grpc_exec_ctx_ready_to_finish(exec_ctx) && is_covered_by_poller(lock)) { |
|
|
|
|
GPR_TIMER_MARK("offload_from_finished_exec_ctx", 0); |
|
|
|
|
// this execution context wants to move on, and we have a workqueue (and
|
|
|
|
|
// so can help the execution context out): schedule remaining work to be
|
|
|
|
@ -205,8 +210,7 @@ bool grpc_combiner_continue_exec_ctx(grpc_exec_ctx *exec_ctx) { |
|
|
|
|
// queue is in an inconsistant state: use this as a cue that we should
|
|
|
|
|
// go off and do something else for a while (and come back later)
|
|
|
|
|
GPR_TIMER_MARK("delay_busy", 0); |
|
|
|
|
if (lock->optional_workqueue != NULL && |
|
|
|
|
gpr_atm_acq_load(&lock->covered_by_poller) > 0) { |
|
|
|
|
if (lock->optional_workqueue != NULL && is_covered_by_poller(lock)) { |
|
|
|
|
queue_offload(exec_ctx, lock); |
|
|
|
|
} |
|
|
|
|
GPR_TIMER_END("combiner.continue_exec_ctx", 0); |
|
|
|
@ -225,6 +229,7 @@ bool grpc_combiner_continue_exec_ctx(grpc_exec_ctx *exec_ctx) { |
|
|
|
|
grpc_closure *c = lock->final_list.head; |
|
|
|
|
GPR_ASSERT(c != NULL); |
|
|
|
|
grpc_closure_list_init(&lock->final_list); |
|
|
|
|
lock->final_list_covered_by_poller = false; |
|
|
|
|
int loops = 0; |
|
|
|
|
while (c != NULL) { |
|
|
|
|
GPR_TIMER_BEGIN("combiner.exec_1final", 0); |
|
|
|
@ -277,11 +282,12 @@ bool grpc_combiner_continue_exec_ctx(grpc_exec_ctx *exec_ctx) { |
|
|
|
|
static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, |
|
|
|
|
grpc_error *error) { |
|
|
|
|
grpc_combiner_execute_finally(exec_ctx, exec_ctx->active_combiner, closure, |
|
|
|
|
GRPC_ERROR_REF(error)); |
|
|
|
|
GRPC_ERROR_REF(error), false); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, |
|
|
|
|
grpc_closure *closure, grpc_error *error) { |
|
|
|
|
grpc_closure *closure, grpc_error *error, |
|
|
|
|
bool covered_by_poller) { |
|
|
|
|
GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, |
|
|
|
|
"C:%p grpc_combiner_execute_finally c=%p; ac=%p", |
|
|
|
|
lock, closure, exec_ctx->active_combiner)); |
|
|
|
@ -298,6 +304,9 @@ void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, |
|
|
|
|
if (grpc_closure_list_empty(lock->final_list)) { |
|
|
|
|
gpr_atm_full_fetch_add(&lock->state, 2); |
|
|
|
|
} |
|
|
|
|
if (covered_by_poller) { |
|
|
|
|
lock->final_list_covered_by_poller = true; |
|
|
|
|
} |
|
|
|
|
grpc_closure_list_append(&lock->final_list, closure, error); |
|
|
|
|
GPR_TIMER_END("combiner.execute_finally", 0); |
|
|
|
|
} |
|
|
|
|