From 415b71c98dce7af2de0b488ca9c5fdece512781a Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Thu, 7 May 2020 08:12:41 -0700 Subject: [PATCH] Defensive programming: ACEC is an optimization and not strictly needed --- src/core/lib/iomgr/exec_ctx.h | 5 +++++ src/core/lib/surface/completion_queue.cc | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index 4e746bc8505..ebea7cf6bfe 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -357,6 +357,11 @@ class ApplicationCallbackExecCtx { /** Global shutdown for ApplicationCallbackExecCtx. Called by init. */ static void GlobalShutdown(void) { gpr_tls_destroy(&callback_exec_ctx_); } + static bool Available() { + return reinterpret_cast( + gpr_tls_get(&callback_exec_ctx_)) != nullptr; + } + private: uintptr_t flags_{0u}; grpc_experimental_completion_queue_functor* head_{nullptr}; diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc index 60cbb244678..7c0c9aeb972 100644 --- a/src/core/lib/surface/completion_queue.cc +++ b/src/core/lib/surface/completion_queue.cc @@ -874,8 +874,15 @@ static void cq_end_op_for_callback( cq_finish_shutdown_callback(cq); } + // If possible, schedule the callback onto an existing thread-local + // ApplicationCallbackExecCtx, which is a work queue. This is possible for: + // 1. The callback is internally-generated and there is an ACEC available + // 2. The callback is marked inlineable and there is an ACEC available + // 3. We are already running in a background poller thread (which always has + // an ACEC available at the base of the stack). auto* functor = static_cast(tag); - if (internal || functor->inlineable || + if (((internal || functor->inlineable) && + grpc_core::ApplicationCallbackExecCtx::Available()) || grpc_iomgr_is_any_background_poller_thread()) { grpc_core::ApplicationCallbackExecCtx::Enqueue(functor, (error == GRPC_ERROR_NONE));