From dd36b15315cd691e86a94d4574bd9f3e3a33633f Mon Sep 17 00:00:00 2001
From: Craig Tiller <ctiller@google.com>
Date: Fri, 31 Mar 2017 08:27:28 -0700
Subject: [PATCH] Call ref/unref, bugfixes

---
 grpc.def                                      |  2 +-
 .../grpc++/impl/codegen/async_unary_call.h    | 75 +++++++------------
 include/grpc++/impl/codegen/call.h            | 50 +------------
 include/grpc/grpc.h                           | 12 ++-
 src/core/ext/lb_policy/grpclb/grpclb.c        |  2 +-
 src/core/lib/surface/call.c                   | 18 +++--
 src/core/lib/surface/server.c                 |  2 +-
 src/cpp/client/client_context.cc              |  2 +-
 src/cpp/server/server_context.cc              |  2 +-
 src/csharp/ext/grpc_csharp_ext.c              |  2 +-
 src/node/ext/call.cc                          |  4 +-
 .../GRPCClient/private/GRPCWrappedCall.m      |  2 +-
 .../tests/CronetUnitTests/CronetUnitTests.m   |  4 +-
 src/php/ext/grpc/call.c                       |  2 +-
 .../grpcio/grpc/_cython/_cygrpc/call.pyx.pxi  |  2 +-
 .../grpcio/grpc/_cython/_cygrpc/grpc.pxi      |  2 +-
 src/ruby/ext/grpc/rb_call.c                   |  2 +-
 src/ruby/ext/grpc/rb_grpc_imports.generated.c |  4 +-
 src/ruby/ext/grpc/rb_grpc_imports.generated.h |  6 +-
 .../bad_client/tests/head_of_line_blocking.c  |  2 +-
 test/core/bad_client/tests/large_metadata.c   |  4 +-
 .../tests/server_registered_method.c          |  4 +-
 test/core/bad_client/tests/simple_request.c   |  2 +-
 test/core/bad_ssl/bad_ssl_test.c              |  2 +-
 test/core/client_channel/lb_policies_test.c   |  6 +-
 test/core/end2end/bad_server_response_test.c  |  2 +-
 test/core/end2end/connection_refused_test.c   |  2 +-
 test/core/end2end/dualstack_socket_test.c     |  4 +-
 test/core/end2end/fixtures/h2_ssl_cert.c      |  2 +-
 test/core/end2end/fixtures/proxy.c            |  4 +-
 test/core/end2end/fuzzers/api_fuzzer.c        |  2 +-
 test/core/end2end/fuzzers/client_fuzzer.c     |  2 +-
 test/core/end2end/fuzzers/server_fuzzer.c     |  2 +-
 test/core/end2end/goaway_server_test.c        |  8 +-
 .../core/end2end/invalid_call_argument_test.c |  4 +-
 test/core/end2end/no_server_test.c            |  2 +-
 .../end2end/tests/authority_not_supported.c   |  2 +-
 test/core/end2end/tests/bad_hostname.c        |  2 +-
 test/core/end2end/tests/binary_metadata.c     |  4 +-
 test/core/end2end/tests/call_creds.c          |  6 +-
 test/core/end2end/tests/cancel_after_accept.c |  4 +-
 .../end2end/tests/cancel_after_client_done.c  |  4 +-
 test/core/end2end/tests/cancel_after_invoke.c |  2 +-
 .../core/end2end/tests/cancel_before_invoke.c |  2 +-
 test/core/end2end/tests/cancel_in_a_vacuum.c  |  2 +-
 test/core/end2end/tests/cancel_with_status.c  |  2 +-
 test/core/end2end/tests/compressed_payload.c  |  8 +-
 test/core/end2end/tests/default_host.c        |  4 +-
 test/core/end2end/tests/disappearing_server.c |  4 +-
 test/core/end2end/tests/empty_batch.c         |  2 +-
 .../end2end/tests/filter_call_init_fails.c    |  2 +-
 test/core/end2end/tests/filter_causes_close.c |  2 +-
 test/core/end2end/tests/filter_latency.c      |  4 +-
 .../end2end/tests/graceful_server_shutdown.c  |  4 +-
 test/core/end2end/tests/high_initial_seqno.c  |  4 +-
 test/core/end2end/tests/hpack_size.c          |  4 +-
 test/core/end2end/tests/idempotent_request.c  |  4 +-
 .../core/end2end/tests/invoke_large_request.c |  4 +-
 test/core/end2end/tests/keepalive_timeout.c   |  4 +-
 test/core/end2end/tests/large_metadata.c      |  4 +-
 test/core/end2end/tests/load_reporting_hook.c |  4 +-
 .../end2end/tests/max_concurrent_streams.c    | 26 +++----
 test/core/end2end/tests/max_message_length.c  |  8 +-
 test/core/end2end/tests/negative_deadline.c   |  2 +-
 .../end2end/tests/network_status_change.c     |  4 +-
 test/core/end2end/tests/no_logging.c          |  4 +-
 test/core/end2end/tests/payload.c             |  4 +-
 test/core/end2end/tests/ping_pong_streaming.c |  4 +-
 test/core/end2end/tests/registered_call.c     |  4 +-
 test/core/end2end/tests/request_with_flags.c  |  2 +-
 .../core/end2end/tests/request_with_payload.c |  4 +-
 .../end2end/tests/resource_quota_server.c     |  4 +-
 .../end2end/tests/server_finishes_request.c   |  4 +-
 .../end2end/tests/shutdown_finishes_calls.c   |  4 +-
 .../end2end/tests/simple_cacheable_request.c  |  4 +-
 .../end2end/tests/simple_delayed_request.c    |  4 +-
 test/core/end2end/tests/simple_metadata.c     |  4 +-
 test/core/end2end/tests/simple_request.c      |  4 +-
 .../end2end/tests/streaming_error_response.c  |  4 +-
 test/core/end2end/tests/trailing_metadata.c   |  4 +-
 test/core/end2end/tests/write_buffering.c     |  4 +-
 .../end2end/tests/write_buffering_at_end.c    |  4 +-
 test/core/fling/client.c                      |  4 +-
 test/core/fling/server.c                      |  4 +-
 test/core/memory_usage/client.c               |  4 +-
 test/core/memory_usage/server.c               |  4 +-
 test/core/surface/lame_client_test.c          |  2 +-
 test/cpp/grpclb/grpclb_test.cc                |  6 +-
 test/cpp/microbenchmarks/bm_call_create.cc    |  8 +-
 89 files changed, 213 insertions(+), 262 deletions(-)

diff --git a/grpc.def b/grpc.def
index 39f06d8cc0..266ca593ce 100644
--- a/grpc.def
+++ b/grpc.def
@@ -83,7 +83,7 @@ EXPORTS
     grpc_channel_destroy
     grpc_call_cancel
     grpc_call_cancel_with_status
-    grpc_call_destroy
+    grpc_call_unref
     grpc_server_request_call
     grpc_server_register_method
     grpc_server_request_registered_call
diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h
index 50bb399df6..dd65cf89d6 100644
--- a/include/grpc++/impl/codegen/async_unary_call.h
+++ b/include/grpc++/impl/codegen/async_unary_call.h
@@ -61,11 +61,6 @@ template <class R>
 class ClientAsyncResponseReader final
     : public ClientAsyncResponseReaderInterface<R> {
  public:
-  ~ClientAsyncResponseReader() {
-    if (collection_ != nullptr && collection_->Unref()) {
-      delete collection_;
-    }
-  }
   template <class W>
   static ClientAsyncResponseReader* Create(ChannelInterface* channel,
                                            CompletionQueue* cq,
@@ -77,18 +72,13 @@ class ClientAsyncResponseReader final
         grpc_call_arena_alloc(call.call(), sizeof(*reader)));
     new (&reader->call_) Call(std::move(call));
     reader->context_ = context;
-    reader->collection_ =
-        new (grpc_call_arena_alloc(call.call(), sizeof(CallOpSetCollection)))
-            CallOpSetCollection();
 
-    reader->collection_->init_buf_.SetCollection(reader->collection_);
-    reader->collection_->init_buf_.SendInitialMetadata(
-        context->send_initial_metadata_, context->initial_metadata_flags());
+    reader->init_buf_.SendInitialMetadata(context->send_initial_metadata_,
+                                          context->initial_metadata_flags());
     // TODO(ctiller): don't assert
-    GPR_CODEGEN_ASSERT(
-        reader->collection_->init_buf_.SendMessage(request).ok());
-    reader->collection_->init_buf_.ClientSendClose();
-    reader->call_.PerformOps(&reader->collection_->init_buf_);
+    GPR_CODEGEN_ASSERT(reader->init_buf_.SendMessage(request).ok());
+    reader->init_buf_.ClientSendClose();
+    reader->call_.PerformOps(&reader->init_buf_);
     return reader;
   }
 
@@ -100,22 +90,20 @@ class ClientAsyncResponseReader final
   void ReadInitialMetadata(void* tag) {
     GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
 
-    collection_->meta_buf_.SetCollection(collection_);
-    collection_->meta_buf_.set_output_tag(tag);
-    collection_->meta_buf_.RecvInitialMetadata(context_);
-    call_.PerformOps(&collection_->meta_buf_);
+    meta_buf_.set_output_tag(tag);
+    meta_buf_.RecvInitialMetadata(context_);
+    call_.PerformOps(&meta_buf_);
   }
 
   void Finish(R* msg, Status* status, void* tag) {
-    collection_->finish_buf_.SetCollection(collection_);
-    collection_->finish_buf_.set_output_tag(tag);
+    finish_buf_.set_output_tag(tag);
     if (!context_->initial_metadata_received_) {
-      collection_->finish_buf_.RecvInitialMetadata(context_);
+      finish_buf_.RecvInitialMetadata(context_);
     }
-    collection_->finish_buf_.RecvMessage(msg);
-    collection_->finish_buf_.AllowNoMessage();
-    collection_->finish_buf_.ClientRecvStatus(context_, status);
-    call_.PerformOps(&collection_->finish_buf_);
+    finish_buf_.RecvMessage(msg);
+    finish_buf_.AllowNoMessage();
+    finish_buf_.ClientRecvStatus(context_, status);
+    call_.PerformOps(&finish_buf_);
   }
 
  private:
@@ -125,26 +113,13 @@ class ClientAsyncResponseReader final
   // disable operator new
   static void* operator new(std::size_t size);
 
-  class CallOpSetCollection final : public CallOpSetCollectionInterface {
-   public:
-    SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
-                    CallOpClientSendClose>
-        init_buf_;
-    CallOpSet<CallOpRecvInitialMetadata> meta_buf_;
-    CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
-              CallOpClientRecvStatus>
-        finish_buf_;
-
-    static void* operator new(std::size_t size, void* p) { return p; }
-    static void operator delete(void* ptr, std::size_t size) {
-      assert(size == sizeof(CallOpSetCollection));
-    }
-
-   private:
-    // disable operator new
-    static void* operator new(std::size_t size);
-  };
-  CallOpSetCollection* collection_;
+  SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+                  CallOpClientSendClose>
+      init_buf_;
+  CallOpSet<CallOpRecvInitialMetadata> meta_buf_;
+  CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
+            CallOpClientRecvStatus>
+      finish_buf_;
 };
 
 template <class W>
@@ -214,4 +189,12 @@ class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface {
 
 }  // namespace grpc
 
+namespace std {
+template <class R>
+class default_delete<grpc::ClientAsyncResponseReader<R>> {
+ public:
+  void operator()(void* p) {}
+};
+}
+
 #endif  // GRPCXX_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index 9c8611a116..4a52c2cbcf 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -561,32 +561,6 @@ class CallOpClientRecvStatus {
   grpc_slice status_details_;
 };
 
-/// An abstract collection of CallOpSet's, to be used whenever
-/// CallOpSet objects must be thought of as a group. Each member
-/// of the group should reference the collection, as will the object
-/// that instantiates the collection, allowing for ref-counting.
-/// Any actual use should derive from this base class. This is specifically
-/// necessary if some of the CallOpSet's in the collection are "Sneaky" and
-/// don't report back to the C++ layer CQ operations
-class CallOpSetCollectionInterface {
- public:
-  CallOpSetCollectionInterface() {
-    gpr_atm_rel_store(&refs_, static_cast<gpr_atm>(1));
-  }
-  // always allocated against a call arena, no memory free required
-  static void operator delete(void* ptr, std::size_t size) {
-  }
-  void Ref() { gpr_atm_no_barrier_fetch_add(&refs_, static_cast<gpr_atm>(1)); }
-  bool Unref() {
-    gpr_atm old =
-        gpr_atm_full_fetch_add(&refs_, static_cast<gpr_atm>(-1));
-    return (old == static_cast<gpr_atm>(1));
-  }
-
- private:
-  gpr_atm refs_;
-};
-
 /// An abstract collection of call ops, used to generate the
 /// grpc_call_op structure to pass down to the lower layers,
 /// and as it is-a CompletionQueueTag, also massages the final
@@ -594,26 +568,9 @@ class CallOpSetCollectionInterface {
 /// API.
 class CallOpSetInterface : public CompletionQueueTag {
  public:
-  CallOpSetInterface() : collection_(nullptr) {}
-  ~CallOpSetInterface() { ResetCollection(); }
   /// Fills in grpc_op, starting from ops[*nops] and moving
   /// upwards.
   virtual void FillOps(grpc_op* ops, size_t* nops) = 0;
-
-  /// Mark this as belonging to a collection if needed
-  void SetCollection(CallOpSetCollectionInterface* collection) {
-    collection_ = collection;
-    collection->Ref();
-  }
-  void ResetCollection() {
-    if (collection_ != nullptr && collection_->Unref()) {
-      delete collection_;
-    }
-    collection_ = nullptr;
-  }
-
- protected:
-  CallOpSetCollectionInterface* collection_;
 };
 
 /// Primary implementaiton of CallOpSetInterface.
@@ -634,16 +591,17 @@ class CallOpSet : public CallOpSetInterface,
                   public Op6 {
  public:
   CallOpSet() : return_tag_(this) {}
-  void FillOps(grpc_op* ops, size_t* nops) override {
+  void FillOps(grpc_call* call, grpc_op* ops, size_t* nops) override {
     this->Op1::AddOp(ops, nops);
     this->Op2::AddOp(ops, nops);
     this->Op3::AddOp(ops, nops);
     this->Op4::AddOp(ops, nops);
     this->Op5::AddOp(ops, nops);
     this->Op6::AddOp(ops, nops);
+    grpc_call_ref(call);
   }
 
-  bool FinalizeResult(void** tag, bool* status) override {
+  bool FinalizeResult(grpc_call* call, void** tag, bool* status) override {
     this->Op1::FinishOp(status);
     this->Op2::FinishOp(status);
     this->Op3::FinishOp(status);
@@ -651,7 +609,7 @@ class CallOpSet : public CallOpSetInterface,
     this->Op5::FinishOp(status);
     this->Op6::FinishOp(status);
     *tag = return_tag_;
-    ResetCollection();  // drop the ref at this point
+    grpc_call_unref(call);
     return true;
   }
 
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 3430cd31e9..3af0ca25c9 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -349,7 +349,7 @@ GRPCAPI void grpc_channel_destroy(grpc_channel *channel);
 /** Called by clients to cancel an RPC on the server.
     Can be called multiple times, from any thread.
     THREAD-SAFETY grpc_call_cancel and grpc_call_cancel_with_status
-    are thread-safe, and can be called at any point before grpc_call_destroy
+    are thread-safe, and can be called at any point before grpc_call_unref
     is called.*/
 GRPCAPI grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved);
 
@@ -364,9 +364,13 @@ GRPCAPI grpc_call_error grpc_call_cancel_with_status(grpc_call *call,
                                                      const char *description,
                                                      void *reserved);
 
-/** Destroy a call.
-    THREAD SAFETY: grpc_call_destroy is thread-compatible */
-GRPCAPI void grpc_call_destroy(grpc_call *call);
+/** Ref a call.
+    THREAD SAFETY: grpc_call_unref is thread-compatible */
+GRPCAPI void grpc_call_ref(grpc_call *call);
+
+/** Unref a call.
+    THREAD SAFETY: grpc_call_unref is thread-compatible */
+GRPCAPI void grpc_call_unref(grpc_call *call);
 
 /** Request notification of a new call.
     Once a call is received, a notification tagged with \a tag_new is added to
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
index 601b0e643b..a86612c68b 100644
--- a/src/core/ext/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -1150,7 +1150,7 @@ static void lb_call_init_locked(grpc_exec_ctx *exec_ctx,
 static void lb_call_destroy_locked(grpc_exec_ctx *exec_ctx,
                                    glb_lb_policy *glb_policy) {
   GPR_ASSERT(glb_policy->lb_call != NULL);
-  grpc_call_destroy(glb_policy->lb_call);
+  grpc_call_unref(glb_policy->lb_call);
   glb_policy->lb_call = NULL;
 
   grpc_metadata_array_destroy(&glb_policy->lb_initial_metadata_recv);
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index 71c65d86ee..810bce44b9 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -139,6 +139,7 @@ typedef struct batch_control {
 } batch_control;
 
 struct grpc_call {
+  gpr_refcount ext_ref;
   gpr_arena *arena;
   grpc_completion_queue *cq;
   grpc_polling_entity pollent;
@@ -151,7 +152,7 @@ struct grpc_call {
 
   /* client or server call */
   bool is_client;
-  /** has grpc_call_destroy been called */
+  /** has grpc_call_unref been called */
   bool destroy_called;
   /** flag indicating that cancellation is inherited */
   bool cancellation_is_inherited;
@@ -285,6 +286,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
       gpr_arena_create(grpc_channel_get_call_size_estimate(args->channel));
   call = gpr_arena_alloc(arena,
                          sizeof(grpc_call) + channel_stack->call_stack_size);
+  gpr_ref_init(&call->ext_ref, 1);
   call->arena = arena;
   *out_call = call;
   gpr_mu_init(&call->child_list_mu);
@@ -375,7 +377,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
   call->send_deadline = send_deadline;
 
   GRPC_CHANNEL_INTERNAL_REF(args->channel, "call");
-  /* initial refcount dropped by grpc_call_destroy */
+  /* initial refcount dropped by grpc_call_unref */
   grpc_call_element_args call_args = {
       .call_stack = CALL_STACK_FROM_CALL(call),
       .server_transport_data = args->server_transport_data,
@@ -493,13 +495,17 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
   GPR_TIMER_END("destroy_call", 0);
 }
 
-void grpc_call_destroy(grpc_call *c) {
+void grpc_call_ref(grpc_call *c) { gpr_ref(&c->ext_ref); }
+
+void grpc_call_unref(grpc_call *c) {
+  if (!gpr_unref(&c->ext_ref)) return;
+
   int cancel;
   grpc_call *parent = c->parent;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
-  GPR_TIMER_BEGIN("grpc_call_destroy", 0);
-  GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c));
+  GPR_TIMER_BEGIN("grpc_call_unref", 0);
+  GRPC_API_TRACE("grpc_call_unref(c=%p)", 1, (c));
 
   if (parent) {
     gpr_mu_lock(&parent->child_list_mu);
@@ -525,7 +531,7 @@ void grpc_call_destroy(grpc_call *c) {
   }
   GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
   grpc_exec_ctx_finish(&exec_ctx);
-  GPR_TIMER_END("grpc_call_destroy", 0);
+  GPR_TIMER_END("grpc_call_unref", 0);
 }
 
 grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) {
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index a123c9ca43..1f92751b0f 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -340,7 +340,7 @@ static void request_matcher_destroy(request_matcher *rm) {
 
 static void kill_zombie(grpc_exec_ctx *exec_ctx, void *elem,
                         grpc_error *error) {
-  grpc_call_destroy(grpc_call_from_top_element(elem));
+  grpc_call_unref(grpc_call_from_top_element(elem));
 }
 
 static void request_matcher_zombify_all_pending_calls(grpc_exec_ctx *exec_ctx,
diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc
index 3d884cf62e..2516232840 100644
--- a/src/cpp/client/client_context.cc
+++ b/src/cpp/client/client_context.cc
@@ -74,7 +74,7 @@ ClientContext::ClientContext()
 
 ClientContext::~ClientContext() {
   if (call_) {
-    grpc_call_destroy(call_);
+    grpc_call_unref(call_);
   }
   g_client_callbacks->Destructor(this);
 }
diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc
index 3a408eb23e..c0c40fda7b 100644
--- a/src/cpp/server/server_context.cc
+++ b/src/cpp/server/server_context.cc
@@ -151,7 +151,7 @@ ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata_array* arr)
 
 ServerContext::~ServerContext() {
   if (call_) {
-    grpc_call_destroy(call_);
+    grpc_call_unref(call_);
   }
   if (completion_op_) {
     completion_op_->Unref();
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 491df4de6a..b6ac4e6eb2 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -517,7 +517,7 @@ GPR_EXPORT void GPR_CALLTYPE gprsharp_free(void *p) {
 }
 
 GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call *call) {
-  grpc_call_destroy(call);
+  grpc_call_unref(call);
 }
 
 GPR_EXPORT grpc_call_error GPR_CALLTYPE
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index 244546d3d7..88bcd6db0b 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -520,7 +520,7 @@ Call::Call(grpc_call *call) : wrapped_call(call),
 
 Call::~Call() {
   if (wrapped_call != NULL) {
-    grpc_call_destroy(wrapped_call);
+    grpc_call_unref(wrapped_call);
   }
 }
 
@@ -568,7 +568,7 @@ void Call::CompleteBatch(bool is_final_op) {
   }
   this->pending_batches--;
   if (this->has_final_op_completed && this->pending_batches == 0) {
-    grpc_call_destroy(this->wrapped_call);
+    grpc_call_unref(this->wrapped_call);
     this->wrapped_call = NULL;
   }
 }
diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
index 46e9fee7e1..1faba3e20b 100644
--- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
+++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
@@ -315,7 +315,7 @@
 }
 
 - (void)dealloc {
-  grpc_call_destroy(_call);
+  grpc_call_unref(_call);
 }
 
 @end
diff --git a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
index a76e45416b..93c648dc37 100644
--- a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
+++ b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
@@ -258,7 +258,7 @@ unsigned int parse_h2_length(const char *field) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 
@@ -437,7 +437,7 @@ unsigned int parse_h2_length(const char *field) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index 48a374fa08..d3fd88416b 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -65,7 +65,7 @@ static zend_object_handlers call_ce_handlers;
 /* Frees and destroys an instance of wrapped_grpc_call */
 PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_call)
   if (p->owned && p->wrapped != NULL) {
-    grpc_call_destroy(p->wrapped);
+    grpc_call_unref(p->wrapped);
   }
 PHP_GRPC_FREE_WRAPPED_FUNC_END()
 
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
index cc3bd7a067..aa3558b843 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/call.pyx.pxi
@@ -106,7 +106,7 @@ cdef class Call:
 
   def __dealloc__(self):
     if self.c_call != NULL:
-      grpc_call_destroy(self.c_call)
+      grpc_call_unref(self.c_call)
     grpc_shutdown()
 
   # The object *should* always be valid from Python. Used for debugging.
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index bbd72424b9..f100b65c76 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -328,7 +328,7 @@ cdef extern from "grpc/grpc.h":
                                                const char *description,
                                                void *reserved) nogil
   char *grpc_call_get_peer(grpc_call *call) nogil
-  void grpc_call_destroy(grpc_call *call) nogil
+  void grpc_call_unref(grpc_call *call) nogil
 
   grpc_channel *grpc_insecure_channel_create(const char *target,
                                              const grpc_channel_args *args,
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index 82d340b254..e4b2cfed00 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -101,7 +101,7 @@ typedef struct grpc_rb_call {
 static void destroy_call(grpc_rb_call *call) {
   /* Ensure that we only try to destroy the call once */
   if (call->wrapped != NULL) {
-    grpc_call_destroy(call->wrapped);
+    grpc_call_unref(call->wrapped);
     call->wrapped = NULL;
     grpc_rb_completion_queue_destroy(call->queue);
     call->queue = NULL;
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 294ca2c5a4..907bf908ad 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -121,7 +121,7 @@ grpc_lame_client_channel_create_type grpc_lame_client_channel_create_import;
 grpc_channel_destroy_type grpc_channel_destroy_import;
 grpc_call_cancel_type grpc_call_cancel_import;
 grpc_call_cancel_with_status_type grpc_call_cancel_with_status_import;
-grpc_call_destroy_type grpc_call_destroy_import;
+grpc_call_unref_type grpc_call_unref_import;
 grpc_server_request_call_type grpc_server_request_call_import;
 grpc_server_register_method_type grpc_server_register_method_import;
 grpc_server_request_registered_call_type grpc_server_request_registered_call_import;
@@ -419,7 +419,7 @@ void grpc_rb_load_imports(HMODULE library) {
   grpc_channel_destroy_import = (grpc_channel_destroy_type) GetProcAddress(library, "grpc_channel_destroy");
   grpc_call_cancel_import = (grpc_call_cancel_type) GetProcAddress(library, "grpc_call_cancel");
   grpc_call_cancel_with_status_import = (grpc_call_cancel_with_status_type) GetProcAddress(library, "grpc_call_cancel_with_status");
-  grpc_call_destroy_import = (grpc_call_destroy_type) GetProcAddress(library, "grpc_call_destroy");
+  grpc_call_unref_import = (grpc_call_unref_type) GetProcAddress(library, "grpc_call_unref");
   grpc_server_request_call_import = (grpc_server_request_call_type) GetProcAddress(library, "grpc_server_request_call");
   grpc_server_register_method_import = (grpc_server_register_method_type) GetProcAddress(library, "grpc_server_register_method");
   grpc_server_request_registered_call_import = (grpc_server_request_registered_call_type) GetProcAddress(library, "grpc_server_request_registered_call");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 7b40dd2f27..c5c416940e 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -314,9 +314,9 @@ extern grpc_call_cancel_type grpc_call_cancel_import;
 typedef grpc_call_error(*grpc_call_cancel_with_status_type)(grpc_call *call, grpc_status_code status, const char *description, void *reserved);
 extern grpc_call_cancel_with_status_type grpc_call_cancel_with_status_import;
 #define grpc_call_cancel_with_status grpc_call_cancel_with_status_import
-typedef void(*grpc_call_destroy_type)(grpc_call *call);
-extern grpc_call_destroy_type grpc_call_destroy_import;
-#define grpc_call_destroy grpc_call_destroy_import
+typedef void(*grpc_call_unref_type)(grpc_call *call);
+extern grpc_call_unref_type grpc_call_unref_import;
+#define grpc_call_unref grpc_call_unref_import
 typedef grpc_call_error(*grpc_server_request_call_type)(grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);
 extern grpc_server_request_call_type grpc_server_request_call_import;
 #define grpc_server_request_call grpc_server_request_call_import
diff --git a/test/core/bad_client/tests/head_of_line_blocking.c b/test/core/bad_client/tests/head_of_line_blocking.c
index 64cb79d82f..b0d788bf22 100644
--- a/test/core/bad_client/tests/head_of_line_blocking.c
+++ b/test/core/bad_client/tests/head_of_line_blocking.c
@@ -103,7 +103,7 @@ static void verifier(grpc_server *server, grpc_completion_queue *cq,
   GPR_ASSERT(payload != NULL);
 
   grpc_metadata_array_destroy(&request_metadata_recv);
-  grpc_call_destroy(s);
+  grpc_call_unref(s);
   grpc_byte_buffer_destroy(payload);
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/bad_client/tests/large_metadata.c b/test/core/bad_client/tests/large_metadata.c
index f672776a9f..d7a3ce9461 100644
--- a/test/core/bad_client/tests/large_metadata.c
+++ b/test/core/bad_client/tests/large_metadata.c
@@ -131,7 +131,7 @@ static void server_verifier(grpc_server *server, grpc_completion_queue *cq,
 
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
-  grpc_call_destroy(s);
+  grpc_call_unref(s);
   cq_verifier_destroy(cqv);
 }
 
@@ -177,7 +177,7 @@ static void server_verifier_sends_too_much_metadata(grpc_server *server,
   grpc_slice_unref(meta.value);
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
-  grpc_call_destroy(s);
+  grpc_call_unref(s);
   cq_verifier_destroy(cqv);
 }
 
diff --git a/test/core/bad_client/tests/server_registered_method.c b/test/core/bad_client/tests/server_registered_method.c
index e174af5931..c5af0bae76 100644
--- a/test/core/bad_client/tests/server_registered_method.c
+++ b/test/core/bad_client/tests/server_registered_method.c
@@ -76,7 +76,7 @@ static void verifier_succeeds(grpc_server *server, grpc_completion_queue *cq,
   GPR_ASSERT(payload != NULL);
 
   grpc_metadata_array_destroy(&request_metadata_recv);
-  grpc_call_destroy(s);
+  grpc_call_unref(s);
   grpc_byte_buffer_destroy(payload);
   cq_verifier_destroy(cqv);
 }
@@ -102,7 +102,7 @@ static void verifier_fails(grpc_server *server, grpc_completion_queue *cq,
   GPR_ASSERT(payload == NULL);
 
   grpc_metadata_array_destroy(&request_metadata_recv);
-  grpc_call_destroy(s);
+  grpc_call_unref(s);
   cq_verifier_destroy(cqv);
 }
 
diff --git a/test/core/bad_client/tests/simple_request.c b/test/core/bad_client/tests/simple_request.c
index 608b849d41..fb342f0881 100644
--- a/test/core/bad_client/tests/simple_request.c
+++ b/test/core/bad_client/tests/simple_request.c
@@ -122,7 +122,7 @@ static void verifier(grpc_server *server, grpc_completion_queue *cq,
 
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
-  grpc_call_destroy(s);
+  grpc_call_unref(s);
   cq_verifier_destroy(cqv);
 }
 
diff --git a/test/core/bad_ssl/bad_ssl_test.c b/test/core/bad_ssl/bad_ssl_test.c
index bd85585706..a8624c2b99 100644
--- a/test/core/bad_ssl/bad_ssl_test.c
+++ b/test/core/bad_ssl/bad_ssl_test.c
@@ -115,7 +115,7 @@ static void run_test(const char *target, size_t nops) {
 
   GPR_ASSERT(status != GRPC_STATUS_OK);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
   grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
diff --git a/test/core/client_channel/lb_policies_test.c b/test/core/client_channel/lb_policies_test.c
index 057b90ec84..751ca36587 100644
--- a/test/core/client_channel/lb_policies_test.c
+++ b/test/core/client_channel/lb_policies_test.c
@@ -391,7 +391,7 @@ static request_sequences perform_request(servers_fixture *f,
                                          "foo.test.google.fr"));
       GPR_ASSERT(was_cancelled == 1);
 
-      grpc_call_destroy(f->server_calls[s_idx]);
+      grpc_call_unref(f->server_calls[s_idx]);
 
       /* ask for the next request on this server */
       GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
@@ -417,7 +417,7 @@ static request_sequences perform_request(servers_fixture *f,
 
     cq_verifier_destroy(cqv);
 
-    grpc_call_destroy(c);
+    grpc_call_unref(c);
 
     for (i = 0; i < f->num_servers; i++) {
       grpc_call_details_destroy(&rdata->call_details[i]);
@@ -613,7 +613,7 @@ static void test_pending_calls(size_t concurrent_calls) {
   /* destroy the calls after the channel so that they are still around for the
    * LB's shutdown func to process */
   for (i = 0; i < concurrent_calls; i++) {
-    grpc_call_destroy(calls[i]);
+    grpc_call_unref(calls[i]);
   }
   gpr_free(calls);
   teardown_servers(f);
diff --git a/test/core/end2end/bad_server_response_test.c b/test/core/end2end/bad_server_response_test.c
index c37a292af9..c8a206f6f9 100644
--- a/test/core/end2end/bad_server_response_test.c
+++ b/test/core/end2end/bad_server_response_test.c
@@ -236,7 +236,7 @@ static void cleanup_rpc(grpc_exec_ctx *exec_ctx) {
   grpc_event ev;
   grpc_slice_buffer_destroy_internal(exec_ctx, &state.temp_incoming_buffer);
   grpc_slice_buffer_destroy_internal(exec_ctx, &state.outgoing_buffer);
-  grpc_call_destroy(state.call);
+  grpc_call_unref(state.call);
   grpc_completion_queue_shutdown(state.cq);
   do {
     ev = grpc_completion_queue_next(state.cq, n_sec_deadline(1), NULL);
diff --git a/test/core/end2end/connection_refused_test.c b/test/core/end2end/connection_refused_test.c
index 6ded12ad48..8ace280195 100644
--- a/test/core/end2end/connection_refused_test.c
+++ b/test/core/end2end/connection_refused_test.c
@@ -138,7 +138,7 @@ static void run_test(bool wait_for_ready, bool use_service_config) {
           .type != GRPC_QUEUE_SHUTDOWN)
     ;
   grpc_completion_queue_destroy(cq);
-  grpc_call_destroy(call);
+  grpc_call_unref(call);
   grpc_channel_destroy(chan);
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c
index 3623bd7be8..c4c3a0d5b5 100644
--- a/test/core/end2end/dualstack_socket_test.c
+++ b/test/core/end2end/dualstack_socket_test.c
@@ -242,7 +242,7 @@ void test_connect(const char *server_host, const char *client_host, int port,
                grpc_slice_str_cmp(call_details.host, "foo.test.google.fr"));
     GPR_ASSERT(was_cancelled == 1);
 
-    grpc_call_destroy(s);
+    grpc_call_unref(s);
   } else {
     /* Check for a failed connection. */
     CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
@@ -251,7 +251,7 @@ void test_connect(const char *server_host, const char *client_host, int port,
     GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
   }
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/fixtures/h2_ssl_cert.c b/test/core/end2end/fixtures/h2_ssl_cert.c
index f62331eea3..7b83183b7f 100644
--- a/test/core/end2end/fixtures/h2_ssl_cert.c
+++ b/test/core/end2end/fixtures/h2_ssl_cert.c
@@ -340,7 +340,7 @@ static void simple_request_body(grpc_end2end_test_fixture f,
   CQ_EXPECT_COMPLETION(cqv, tag(1), expected_result == SUCCESS);
   cq_verify(cqv);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
   cq_verifier_destroy(cqv);
 }
 
diff --git a/test/core/end2end/fixtures/proxy.c b/test/core/end2end/fixtures/proxy.c
index cee053e8c5..449f98813e 100644
--- a/test/core/end2end/fixtures/proxy.c
+++ b/test/core/end2end/fixtures/proxy.c
@@ -148,8 +148,8 @@ void grpc_end2end_proxy_destroy(grpc_end2end_proxy *proxy) {
 
 static void unrefpc(proxy_call *pc, const char *reason) {
   if (gpr_unref(&pc->refs)) {
-    grpc_call_destroy(pc->c2p);
-    grpc_call_destroy(pc->p2s);
+    grpc_call_unref(pc->c2p);
+    grpc_call_unref(pc->p2s);
     grpc_metadata_array_destroy(&pc->c2p_initial_metadata);
     grpc_metadata_array_destroy(&pc->p2s_initial_metadata);
     grpc_metadata_array_destroy(&pc->p2s_trailing_metadata);
diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c
index a0acf5bf60..430db2b5ba 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.c
+++ b/test/core/end2end/fuzzers/api_fuzzer.c
@@ -661,7 +661,7 @@ static void read_metadata(input_stream *inp, size_t *count,
 }
 
 static call_state *destroy_call(call_state *call) {
-  grpc_call_destroy(call->call);
+  grpc_call_unref(call->call);
   call->call = NULL;
   return maybe_delete_call_state(call);
 }
diff --git a/test/core/end2end/fuzzers/client_fuzzer.c b/test/core/end2end/fuzzers/client_fuzzer.c
index e7e7dbefd0..e686a15b2a 100644
--- a/test/core/end2end/fuzzers/client_fuzzer.c
+++ b/test/core/end2end/fuzzers/client_fuzzer.c
@@ -151,7 +151,7 @@ done:
     ev = grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL);
     GPR_ASSERT(ev.type == GRPC_QUEUE_SHUTDOWN);
   }
-  grpc_call_destroy(call);
+  grpc_call_unref(call);
   grpc_completion_queue_destroy(cq);
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
diff --git a/test/core/end2end/fuzzers/server_fuzzer.c b/test/core/end2end/fuzzers/server_fuzzer.c
index 186542d4b2..3bf7917f58 100644
--- a/test/core/end2end/fuzzers/server_fuzzer.c
+++ b/test/core/end2end/fuzzers/server_fuzzer.c
@@ -109,7 +109,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   }
 
 done:
-  if (call1 != NULL) grpc_call_destroy(call1);
+  if (call1 != NULL) grpc_call_unref(call1);
   grpc_call_details_destroy(&call_details1);
   grpc_metadata_array_destroy(&request_metadata1);
   grpc_server_shutdown_and_notify(server, cq, tag(0xdead));
diff --git a/test/core/end2end/goaway_server_test.c b/test/core/end2end/goaway_server_test.c
index 22d93b321a..0eafb73ed8 100644
--- a/test/core/end2end/goaway_server_test.c
+++ b/test/core/end2end/goaway_server_test.c
@@ -302,10 +302,10 @@ int main(int argc, char **argv) {
   CQ_EXPECT_COMPLETION(cqv, tag(0xdead2), 1);
   cq_verify(cqv);
 
-  grpc_call_destroy(call1);
-  grpc_call_destroy(call2);
-  grpc_call_destroy(server_call1);
-  grpc_call_destroy(server_call2);
+  grpc_call_unref(call1);
+  grpc_call_unref(call2);
+  grpc_call_unref(server_call1);
+  grpc_call_unref(server_call2);
   grpc_server_destroy(server1);
   grpc_server_destroy(server2);
   grpc_channel_destroy(chan);
diff --git a/test/core/end2end/invalid_call_argument_test.c b/test/core/end2end/invalid_call_argument_test.c
index 2a9072570d..c3030c6060 100644
--- a/test/core/end2end/invalid_call_argument_test.c
+++ b/test/core/end2end/invalid_call_argument_test.c
@@ -123,7 +123,7 @@ static void prepare_test(int is_client) {
 }
 
 static void cleanup_test() {
-  grpc_call_destroy(g_state.call);
+  grpc_call_unref(g_state.call);
   cq_verifier_destroy(g_state.cqv);
   grpc_channel_destroy(g_state.chan);
   grpc_slice_unref(g_state.details);
@@ -131,7 +131,7 @@ static void cleanup_test() {
   grpc_metadata_array_destroy(&g_state.trailing_metadata_recv);
 
   if (!g_state.is_client) {
-    grpc_call_destroy(g_state.server_call);
+    grpc_call_unref(g_state.server_call);
     grpc_server_shutdown_and_notify(g_state.server, g_state.cq, tag(1000));
     GPR_ASSERT(grpc_completion_queue_pluck(g_state.cq, tag(1000),
                                            grpc_timeout_seconds_to_deadline(5),
diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c
index 26d26d8f7a..e93993797c 100644
--- a/test/core/end2end/no_server_test.c
+++ b/test/core/end2end/no_server_test.c
@@ -97,7 +97,7 @@ int main(int argc, char **argv) {
           .type != GRPC_QUEUE_SHUTDOWN)
     ;
   grpc_completion_queue_destroy(cq);
-  grpc_call_destroy(call);
+  grpc_call_unref(call);
   grpc_channel_destroy(chan);
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/authority_not_supported.c b/test/core/end2end/tests/authority_not_supported.c
index 7db2fd6b27..921b3a0154 100644
--- a/test/core/end2end/tests/authority_not_supported.c
+++ b/test/core/end2end/tests/authority_not_supported.c
@@ -178,7 +178,7 @@ static void test_with_authority_header(grpc_end2end_test_config config) {
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/bad_hostname.c b/test/core/end2end/tests/bad_hostname.c
index f50a5805a2..a8cb987dd7 100644
--- a/test/core/end2end/tests/bad_hostname.c
+++ b/test/core/end2end/tests/bad_hostname.c
@@ -159,7 +159,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/binary_metadata.c b/test/core/end2end/tests/binary_metadata.c
index 7fb60f4495..b8e6b9bbc2 100644
--- a/test/core/end2end/tests/binary_metadata.c
+++ b/test/core/end2end/tests/binary_metadata.c
@@ -310,8 +310,8 @@ static void test_request_response_with_metadata_and_payload(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/call_creds.c b/test/core/end2end/tests/call_creds.c
index 38cba50e12..6ace0079e8 100644
--- a/test/core/end2end/tests/call_creds.c
+++ b/test/core/end2end/tests/call_creds.c
@@ -343,8 +343,8 @@ static void request_response_with_payload_and_call_creds(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
@@ -469,7 +469,7 @@ static void test_request_with_server_rejecting_client_creds(
   grpc_byte_buffer_destroy(response_payload_recv);
   grpc_slice_unref(details);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
   end_test(&f);
diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c
index 1a92aa4837..395d3a12f4 100644
--- a/test/core/end2end/tests/cancel_after_accept.c
+++ b/test/core/end2end/tests/cancel_after_accept.c
@@ -248,8 +248,8 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
   grpc_byte_buffer_destroy(response_payload_recv);
   grpc_slice_unref(details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   if (args != NULL) {
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
diff --git a/test/core/end2end/tests/cancel_after_client_done.c b/test/core/end2end/tests/cancel_after_client_done.c
index 0afeecb037..f92f5b971e 100644
--- a/test/core/end2end/tests/cancel_after_client_done.c
+++ b/test/core/end2end/tests/cancel_after_client_done.c
@@ -225,8 +225,8 @@ static void test_cancel_after_accept_and_writes_closed(
   grpc_byte_buffer_destroy(response_payload_recv);
   grpc_slice_unref(details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
   end_test(&f);
diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c
index 8a96ef2f89..61c9a18a6d 100644
--- a/test/core/end2end/tests/cancel_after_invoke.c
+++ b/test/core/end2end/tests/cancel_after_invoke.c
@@ -185,7 +185,7 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config,
   grpc_byte_buffer_destroy(response_payload_recv);
   grpc_slice_unref(details);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
   end_test(&f);
diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c
index 586aa7ead3..c1abf98350 100644
--- a/test/core/end2end/tests/cancel_before_invoke.c
+++ b/test/core/end2end/tests/cancel_before_invoke.c
@@ -182,7 +182,7 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config,
   grpc_byte_buffer_destroy(response_payload_recv);
   grpc_slice_unref(details);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
   end_test(&f);
diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c
index bc462ddcf5..c78192a890 100644
--- a/test/core/end2end/tests/cancel_in_a_vacuum.c
+++ b/test/core/end2end/tests/cancel_in_a_vacuum.c
@@ -114,7 +114,7 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config,
 
   GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL));
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(v_client);
   end_test(&f);
diff --git a/test/core/end2end/tests/cancel_with_status.c b/test/core/end2end/tests/cancel_with_status.c
index 7d03fe5580..3c7522bfe3 100644
--- a/test/core/end2end/tests/cancel_with_status.c
+++ b/test/core/end2end/tests/cancel_with_status.c
@@ -161,7 +161,7 @@ static void simple_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/compressed_payload.c b/test/core/end2end/tests/compressed_payload.c
index 7dd8c112d1..af88ce7311 100644
--- a/test/core/end2end/tests/compressed_payload.c
+++ b/test/core/end2end/tests/compressed_payload.c
@@ -257,8 +257,8 @@ static void request_for_disabled_algorithm(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
@@ -515,8 +515,8 @@ static void request_with_payload_template(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/default_host.c b/test/core/end2end/tests/default_host.c
index bc1829b24b..ceba1fb904 100644
--- a/test/core/end2end/tests/default_host.c
+++ b/test/core/end2end/tests/default_host.c
@@ -210,8 +210,8 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/disappearing_server.c b/test/core/end2end/tests/disappearing_server.c
index 05440a6f56..965e1bd20c 100644
--- a/test/core/end2end/tests/disappearing_server.c
+++ b/test/core/end2end/tests/disappearing_server.c
@@ -186,8 +186,8 @@ static void do_request_and_shutdown_server(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 }
 
 static void disappearing_server_test(grpc_end2end_test_config config) {
diff --git a/test/core/end2end/tests/empty_batch.c b/test/core/end2end/tests/empty_batch.c
index 50bb6b849e..c4789ef859 100644
--- a/test/core/end2end/tests/empty_batch.c
+++ b/test/core/end2end/tests/empty_batch.c
@@ -117,7 +117,7 @@ static void empty_batch_body(grpc_end2end_test_config config,
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/filter_call_init_fails.c b/test/core/end2end/tests/filter_call_init_fails.c
index ebfe3b03dc..74b832cd02 100644
--- a/test/core/end2end/tests/filter_call_init_fails.c
+++ b/test/core/end2end/tests/filter_call_init_fails.c
@@ -188,7 +188,7 @@ static void test_request(grpc_end2end_test_config config) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c
index e6b02eaeee..1aae5ea8c9 100644
--- a/test/core/end2end/tests/filter_causes_close.c
+++ b/test/core/end2end/tests/filter_causes_close.c
@@ -185,7 +185,7 @@ static void test_request(grpc_end2end_test_config config) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/filter_latency.c b/test/core/end2end/tests/filter_latency.c
index 2428c92a42..1607c9794f 100644
--- a/test/core/end2end/tests/filter_latency.c
+++ b/test/core/end2end/tests/filter_latency.c
@@ -224,8 +224,8 @@ static void test_request(grpc_end2end_test_config config) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(s);
-  grpc_call_destroy(c);
+  grpc_call_unref(s);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c
index a3ad260cc2..be006f30d7 100644
--- a/test/core/end2end/tests/graceful_server_shutdown.c
+++ b/test/core/end2end/tests/graceful_server_shutdown.c
@@ -188,7 +188,7 @@ static void test_early_server_shutdown_finishes_inflight_calls(
   CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
   cq_verify(cqv);
 
-  grpc_call_destroy(s);
+  grpc_call_unref(s);
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
@@ -202,7 +202,7 @@ static void test_early_server_shutdown_finishes_inflight_calls(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/high_initial_seqno.c b/test/core/end2end/tests/high_initial_seqno.c
index cca8532b0e..08e3fd3d67 100644
--- a/test/core/end2end/tests/high_initial_seqno.c
+++ b/test/core/end2end/tests/high_initial_seqno.c
@@ -201,8 +201,8 @@ static void simple_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   /* TODO(ctiller): this rate limits the test, and it should be removed when
                     retry has been implemented; until then cross-thread chatter
diff --git a/test/core/end2end/tests/hpack_size.c b/test/core/end2end/tests/hpack_size.c
index 7601722dee..95725b2e7c 100644
--- a/test/core/end2end/tests/hpack_size.c
+++ b/test/core/end2end/tests/hpack_size.c
@@ -354,8 +354,8 @@ static void simple_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/idempotent_request.c b/test/core/end2end/tests/idempotent_request.c
index cef2e100be..f5ed60138e 100644
--- a/test/core/end2end/tests/idempotent_request.c
+++ b/test/core/end2end/tests/idempotent_request.c
@@ -215,8 +215,8 @@ static void simple_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c
index d799bd8ccf..f907a3fd1c 100644
--- a/test/core/end2end/tests/invoke_large_request.c
+++ b/test/core/end2end/tests/invoke_large_request.c
@@ -256,8 +256,8 @@ static void test_invoke_large_request(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/keepalive_timeout.c b/test/core/end2end/tests/keepalive_timeout.c
index 44b6e12abc..f86e4c56a1 100644
--- a/test/core/end2end/tests/keepalive_timeout.c
+++ b/test/core/end2end/tests/keepalive_timeout.c
@@ -221,8 +221,8 @@ static void test_keepalive_timeout(grpc_end2end_test_config config) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/large_metadata.c b/test/core/end2end/tests/large_metadata.c
index ac4c0e7f3b..6f78b3b5c7 100644
--- a/test/core/end2end/tests/large_metadata.c
+++ b/test/core/end2end/tests/large_metadata.c
@@ -242,8 +242,8 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/load_reporting_hook.c b/test/core/end2end/tests/load_reporting_hook.c
index d1ee26fe50..3eb75de3a9 100644
--- a/test/core/end2end/tests/load_reporting_hook.c
+++ b/test/core/end2end/tests/load_reporting_hook.c
@@ -262,8 +262,8 @@ static void request_response_with_payload(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c
index e81a628944..b7221cb315 100644
--- a/test/core/end2end/tests/max_concurrent_streams.c
+++ b/test/core/end2end/tests/max_concurrent_streams.c
@@ -197,8 +197,8 @@ static void simple_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 }
@@ -429,10 +429,10 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
 
   cq_verifier_destroy(cqv);
 
-  grpc_call_destroy(c1);
-  grpc_call_destroy(s1);
-  grpc_call_destroy(c2);
-  grpc_call_destroy(s2);
+  grpc_call_unref(c1);
+  grpc_call_unref(s1);
+  grpc_call_unref(c2);
+  grpc_call_unref(s2);
 
   grpc_slice_unref(details1);
   grpc_slice_unref(details2);
@@ -624,10 +624,10 @@ static void test_max_concurrent_streams_with_timeout_on_first(
 
   cq_verifier_destroy(cqv);
 
-  grpc_call_destroy(c1);
-  grpc_call_destroy(s1);
-  grpc_call_destroy(c2);
-  grpc_call_destroy(s2);
+  grpc_call_unref(c1);
+  grpc_call_unref(s1);
+  grpc_call_unref(c2);
+  grpc_call_unref(s2);
 
   grpc_slice_unref(details1);
   grpc_slice_unref(details2);
@@ -785,7 +785,7 @@ static void test_max_concurrent_streams_with_timeout_on_second(
 
   /* second request is finished because of time out, so destroy the second call
    */
-  grpc_call_destroy(c2);
+  grpc_call_unref(c2);
 
   /* now reply the first call */
   memset(ops, 0, sizeof(ops));
@@ -817,8 +817,8 @@ static void test_max_concurrent_streams_with_timeout_on_second(
 
   cq_verifier_destroy(cqv);
 
-  grpc_call_destroy(c1);
-  grpc_call_destroy(s1);
+  grpc_call_unref(c1);
+  grpc_call_unref(s1);
 
   grpc_slice_unref(details1);
   grpc_slice_unref(details2);
diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c
index b15d30f58c..8fc49352c2 100644
--- a/test/core/end2end/tests/max_message_length.c
+++ b/test/core/end2end/tests/max_message_length.c
@@ -285,8 +285,8 @@ done:
   grpc_byte_buffer_destroy(request_payload);
   grpc_byte_buffer_destroy(recv_payload);
 
-  grpc_call_destroy(c);
-  if (s != NULL) grpc_call_destroy(s);
+  grpc_call_unref(c);
+  if (s != NULL) grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
@@ -479,8 +479,8 @@ static void test_max_message_length_on_response(grpc_end2end_test_config config,
   grpc_byte_buffer_destroy(response_payload);
   grpc_byte_buffer_destroy(recv_payload);
 
-  grpc_call_destroy(c);
-  if (s != NULL) grpc_call_destroy(s);
+  grpc_call_unref(c);
+  if (s != NULL) grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/negative_deadline.c b/test/core/end2end/tests/negative_deadline.c
index 0b61efbac9..04b09df749 100644
--- a/test/core/end2end/tests/negative_deadline.c
+++ b/test/core/end2end/tests/negative_deadline.c
@@ -158,7 +158,7 @@ static void simple_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&initial_metadata_recv);
   grpc_metadata_array_destroy(&trailing_metadata_recv);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/network_status_change.c b/test/core/end2end/tests/network_status_change.c
index d7a4106459..a5e6240cd2 100644
--- a/test/core/end2end/tests/network_status_change.c
+++ b/test/core/end2end/tests/network_status_change.c
@@ -227,8 +227,8 @@ static void test_invoke_network_status_change(grpc_end2end_test_config config) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/no_logging.c b/test/core/end2end/tests/no_logging.c
index 56e48a88a8..cb077921d1 100644
--- a/test/core/end2end/tests/no_logging.c
+++ b/test/core/end2end/tests/no_logging.c
@@ -240,8 +240,8 @@ static void simple_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/payload.c b/test/core/end2end/tests/payload.c
index b04ee5705c..9f2e0ffa61 100644
--- a/test/core/end2end/tests/payload.c
+++ b/test/core/end2end/tests/payload.c
@@ -257,8 +257,8 @@ static void request_response_with_payload(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c
index 848f76018d..62b01e60cd 100644
--- a/test/core/end2end/tests/ping_pong_streaming.c
+++ b/test/core/end2end/tests/ping_pong_streaming.c
@@ -261,8 +261,8 @@ static void test_pingpong_streaming(grpc_end2end_test_config config,
   CQ_EXPECT_COMPLETION(cqv, tag(104), 1);
   cq_verify(cqv);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/registered_call.c b/test/core/end2end/tests/registered_call.c
index 9c8ce89c83..cdcba07203 100644
--- a/test/core/end2end/tests/registered_call.c
+++ b/test/core/end2end/tests/registered_call.c
@@ -196,8 +196,8 @@ static void simple_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/request_with_flags.c b/test/core/end2end/tests/request_with_flags.c
index 329359e08b..a636d515a4 100644
--- a/test/core/end2end/tests/request_with_flags.c
+++ b/test/core/end2end/tests/request_with_flags.c
@@ -175,7 +175,7 @@ static void test_invoke_request_with_flags(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c
index f71f92bbb8..3d6e3f43d3 100644
--- a/test/core/end2end/tests/request_with_payload.c
+++ b/test/core/end2end/tests/request_with_payload.c
@@ -222,8 +222,8 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/resource_quota_server.c b/test/core/end2end/tests/resource_quota_server.c
index db26b4480e..6d4cb73d66 100644
--- a/test/core/end2end/tests/resource_quota_server.c
+++ b/test/core/end2end/tests/resource_quota_server.c
@@ -265,7 +265,7 @@ void resource_quota_server(grpc_end2end_test_config config) {
 
       grpc_metadata_array_destroy(&initial_metadata_recv[call_id]);
       grpc_metadata_array_destroy(&trailing_metadata_recv[call_id]);
-      grpc_call_destroy(client_calls[call_id]);
+      grpc_call_unref(client_calls[call_id]);
       grpc_slice_unref(details[call_id]);
 
       pending_client_calls--;
@@ -347,7 +347,7 @@ void resource_quota_server(grpc_end2end_test_config config) {
       GPR_ASSERT(pending_server_end_calls > 0);
       pending_server_end_calls--;
 
-      grpc_call_destroy(server_calls[call_id]);
+      grpc_call_unref(server_calls[call_id]);
     }
   }
 
diff --git a/test/core/end2end/tests/server_finishes_request.c b/test/core/end2end/tests/server_finishes_request.c
index b42d17002e..9463ed64ad 100644
--- a/test/core/end2end/tests/server_finishes_request.c
+++ b/test/core/end2end/tests/server_finishes_request.c
@@ -195,8 +195,8 @@ static void simple_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/shutdown_finishes_calls.c b/test/core/end2end/tests/shutdown_finishes_calls.c
index c019682ea6..245acbdce8 100644
--- a/test/core/end2end/tests/shutdown_finishes_calls.c
+++ b/test/core/end2end/tests/shutdown_finishes_calls.c
@@ -182,8 +182,8 @@ static void test_early_server_shutdown_finishes_inflight_calls(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/simple_cacheable_request.c b/test/core/end2end/tests/simple_cacheable_request.c
index 4eef02e9ee..915920b1b9 100644
--- a/test/core/end2end/tests/simple_cacheable_request.c
+++ b/test/core/end2end/tests/simple_cacheable_request.c
@@ -270,8 +270,8 @@ static void test_cacheable_request_response_with_metadata_and_payload(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c
index e3b6aee783..f4331e43dd 100644
--- a/test/core/end2end/tests/simple_delayed_request.c
+++ b/test/core/end2end/tests/simple_delayed_request.c
@@ -191,8 +191,8 @@ static void simple_delayed_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/simple_metadata.c b/test/core/end2end/tests/simple_metadata.c
index 7ab5563cfa..d151ea7040 100644
--- a/test/core/end2end/tests/simple_metadata.c
+++ b/test/core/end2end/tests/simple_metadata.c
@@ -262,8 +262,8 @@ static void test_request_response_with_metadata_and_payload(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c
index af5d74959e..5c81593859 100644
--- a/test/core/end2end/tests/simple_request.c
+++ b/test/core/end2end/tests/simple_request.c
@@ -215,8 +215,8 @@ static void simple_request_body(grpc_end2end_test_config config,
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 }
diff --git a/test/core/end2end/tests/streaming_error_response.c b/test/core/end2end/tests/streaming_error_response.c
index 2b9c404b15..a0ec2f6f91 100644
--- a/test/core/end2end/tests/streaming_error_response.c
+++ b/test/core/end2end/tests/streaming_error_response.c
@@ -259,8 +259,8 @@ static void test(grpc_end2end_test_config config, bool request_status_early) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/trailing_metadata.c b/test/core/end2end/tests/trailing_metadata.c
index dbbda505bc..d7a6adcd3e 100644
--- a/test/core/end2end/tests/trailing_metadata.c
+++ b/test/core/end2end/tests/trailing_metadata.c
@@ -272,8 +272,8 @@ static void test_request_response_with_metadata_and_payload(
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/write_buffering.c b/test/core/end2end/tests/write_buffering.c
index abf90ca6e0..c7ecd97a81 100644
--- a/test/core/end2end/tests/write_buffering.c
+++ b/test/core/end2end/tests/write_buffering.c
@@ -270,8 +270,8 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/end2end/tests/write_buffering_at_end.c b/test/core/end2end/tests/write_buffering_at_end.c
index 8c02b425ba..55bbab4ea2 100644
--- a/test/core/end2end/tests/write_buffering_at_end.c
+++ b/test/core/end2end/tests/write_buffering_at_end.c
@@ -261,8 +261,8 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
   grpc_metadata_array_destroy(&request_metadata_recv);
   grpc_call_details_destroy(&call_details);
 
-  grpc_call_destroy(c);
-  grpc_call_destroy(s);
+  grpc_call_unref(c);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
diff --git a/test/core/fling/client.c b/test/core/fling/client.c
index 85bab6d431..7fa7563b93 100644
--- a/test/core/fling/client.c
+++ b/test/core/fling/client.c
@@ -99,7 +99,7 @@ static void step_ping_pong_request(void) {
                                                    (size_t)(op - ops),
                                                    (void *)1, NULL));
   grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
-  grpc_call_destroy(call);
+  grpc_call_unref(call);
   grpc_byte_buffer_destroy(response_payload_recv);
   call = NULL;
   GPR_TIMER_END("ping_pong", 1);
@@ -233,7 +233,7 @@ int main(int argc, char **argv) {
   grpc_profiler_stop();
 
   if (call) {
-    grpc_call_destroy(call);
+    grpc_call_unref(call);
   }
 
   grpc_channel_destroy(channel);
diff --git a/test/core/fling/server.c b/test/core/fling/server.c
index 7ea54b1167..9488b0b5fc 100644
--- a/test/core/fling/server.c
+++ b/test/core/fling/server.c
@@ -294,7 +294,7 @@ int main(int argc, char **argv) {
             break;
           case FLING_SERVER_SEND_STATUS_FOR_STREAMING:
             /* Send status and close completed at server */
-            grpc_call_destroy(call);
+            grpc_call_unref(call);
             if (!shutdown_started) request_call();
             break;
           case FLING_SERVER_READ_FOR_UNARY:
@@ -307,7 +307,7 @@ int main(int argc, char **argv) {
             /* Finished unary call. */
             grpc_byte_buffer_destroy(payload_buffer);
             payload_buffer = NULL;
-            grpc_call_destroy(call);
+            grpc_call_unref(call);
             if (!shutdown_started) request_call();
             break;
         }
diff --git a/test/core/memory_usage/client.c b/test/core/memory_usage/client.c
index 51ea51bc12..78b9db9195 100644
--- a/test/core/memory_usage/client.c
+++ b/test/core/memory_usage/client.c
@@ -120,7 +120,7 @@ static void finish_ping_pong_request(int call_idx) {
   grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv);
   grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv);
   grpc_slice_unref(calls[call_idx].details);
-  grpc_call_destroy(calls[call_idx].call);
+  grpc_call_unref(calls[call_idx].call);
   calls[call_idx].call = NULL;
 }
 
@@ -187,7 +187,7 @@ static struct grpc_memory_counters send_snapshot_request(int call_idx,
   grpc_byte_buffer_destroy(response_payload_recv);
   grpc_slice_unref(calls[call_idx].details);
   calls[call_idx].details = grpc_empty_slice();
-  grpc_call_destroy(calls[call_idx].call);
+  grpc_call_unref(calls[call_idx].call);
   calls[call_idx].call = NULL;
 
   return snapshot;
diff --git a/test/core/memory_usage/server.c b/test/core/memory_usage/server.c
index ab059c25b8..cba2086a44 100644
--- a/test/core/memory_usage/server.c
+++ b/test/core/memory_usage/server.c
@@ -281,7 +281,7 @@ int main(int argc, char **argv) {
           case FLING_SERVER_WAIT_FOR_DESTROY:
             break;
           case FLING_SERVER_SEND_STATUS_FLING_CALL:
-            grpc_call_destroy(s->call);
+            grpc_call_unref(s->call);
             grpc_call_details_destroy(&s->call_details);
             grpc_metadata_array_destroy(&s->initial_metadata_send);
             grpc_metadata_array_destroy(&s->request_metadata_recv);
@@ -299,7 +299,7 @@ int main(int argc, char **argv) {
           case FLING_SERVER_SEND_STATUS_SNAPSHOT:
             grpc_byte_buffer_destroy(payload_buffer);
             grpc_byte_buffer_destroy(terminal_buffer);
-            grpc_call_destroy(s->call);
+            grpc_call_unref(s->call);
             grpc_call_details_destroy(&s->call_details);
             grpc_metadata_array_destroy(&s->initial_metadata_send);
             grpc_metadata_array_destroy(&s->request_metadata_recv);
diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c
index 9deb50bb04..664bcf0ca4 100644
--- a/test/core/surface/lame_client_test.c
+++ b/test/core/surface/lame_client_test.c
@@ -156,7 +156,7 @@ int main(int argc, char **argv) {
   GPR_ASSERT(strcmp(peer, "lampoon:national") == 0);
   gpr_free(peer);
 
-  grpc_call_destroy(call);
+  grpc_call_unref(call);
   grpc_channel_destroy(chan);
   cq_verifier_destroy(cqv);
   grpc_completion_queue_destroy(cq);
diff --git a/test/cpp/grpclb/grpclb_test.cc b/test/cpp/grpclb/grpclb_test.cc
index 89ed9249ad..65fa73c417 100644
--- a/test/cpp/grpclb/grpclb_test.cc
+++ b/test/cpp/grpclb/grpclb_test.cc
@@ -310,7 +310,7 @@ static void start_lb_server(server_fixture *sf, int *ports, size_t nports,
   gpr_log(GPR_INFO, "LB Server[%s](%s) after tag 204. All done. LB server out",
           sf->servers_hostport, sf->balancer_name);
 
-  grpc_call_destroy(s);
+  grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
 
@@ -457,7 +457,7 @@ static void start_backend_server(server_fixture *sf) {
     gpr_log(GPR_INFO, "Server[%s] DONE. After servicing %d calls",
             sf->servers_hostport, sf->num_calls_serviced);
 
-    grpc_call_destroy(s);
+    grpc_call_unref(s);
     cq_verifier_destroy(cqv);
     grpc_metadata_array_destroy(&request_metadata_recv);
     grpc_call_details_destroy(&call_details);
@@ -557,7 +557,7 @@ static void perform_request(client_fixture *cf) {
   peer = grpc_call_get_peer(c);
   gpr_log(GPR_INFO, "Client DONE WITH SERVER %s ", peer);
 
-  grpc_call_destroy(c);
+  grpc_call_unref(c);
 
   cq_verify_empty_timeout(cqv, 1 /* seconds */);
   cq_verifier_destroy(cqv);
diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc
index 4af2263e82..bcfcc703da 100644
--- a/test/cpp/microbenchmarks/bm_call_create.cc
+++ b/test/cpp/microbenchmarks/bm_call_create.cc
@@ -123,7 +123,7 @@ static void BM_CallCreateDestroy(benchmark::State &state) {
   void *method_hdl =
       grpc_channel_register_call(fixture.channel(), "/foo/bar", NULL, NULL);
   while (state.KeepRunning()) {
-    grpc_call_destroy(grpc_channel_create_registered_call(
+    grpc_call_unref(grpc_channel_create_registered_call(
         fixture.channel(), NULL, GRPC_PROPAGATE_DEFAULTS, cq, method_hdl,
         deadline, NULL));
   }
@@ -590,7 +590,7 @@ static void BM_IsolatedCall_NoOp(benchmark::State &state) {
   void *method_hdl =
       grpc_channel_register_call(fixture.channel(), "/foo/bar", NULL, NULL);
   while (state.KeepRunning()) {
-    grpc_call_destroy(grpc_channel_create_registered_call(
+    grpc_call_unref(grpc_channel_create_registered_call(
         fixture.channel(), nullptr, GRPC_PROPAGATE_DEFAULTS, fixture.cq(),
         method_hdl, deadline, NULL));
   }
@@ -634,7 +634,7 @@ static void BM_IsolatedCall_Unary(benchmark::State &state) {
     grpc_call_start_batch(call, ops, 6, tag(1), NULL);
     grpc_completion_queue_next(fixture.cq(),
                                gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL);
-    grpc_call_destroy(call);
+    grpc_call_unref(call);
   }
   fixture.Finish(state);
   grpc_metadata_array_destroy(&recv_initial_metadata);
@@ -674,7 +674,7 @@ static void BM_IsolatedCall_StreamingSend(benchmark::State &state) {
     grpc_completion_queue_next(fixture.cq(),
                                gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL);
   }
-  grpc_call_destroy(call);
+  grpc_call_unref(call);
   fixture.Finish(state);
   grpc_metadata_array_destroy(&recv_initial_metadata);
   grpc_metadata_array_destroy(&recv_trailing_metadata);
-- 
GitLab