diff --git a/BUILD b/BUILD
index f8e7661ad46f27fa5d127f65d679f310f6d0b208..f372fa797501c56fb129afd6c2b9ae90e23866a7 100644
--- a/BUILD
+++ b/BUILD
@@ -285,6 +285,7 @@ cc_library(
     "src/core/ext/client_config/uri_parser.h",
     "src/core/ext/lb_policy/grpclb/load_balancer_api.h",
     "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h",
+    "src/core/ext/lb_policy/common.h",
     "src/core/ext/census/aggregation.h",
     "src/core/ext/census/census_interface.h",
     "src/core/ext/census/census_rpc_stats.h",
@@ -439,6 +440,7 @@ cc_library(
     "src/core/ext/transport/chttp2/client/insecure/channel_create.c",
     "src/core/ext/lb_policy/grpclb/load_balancer_api.c",
     "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c",
+    "src/core/ext/lb_policy/common.c",
     "src/core/ext/lb_policy/pick_first/pick_first.c",
     "src/core/ext/lb_policy/round_robin/round_robin.c",
     "src/core/ext/resolver/dns/native/dns_resolver.c",
@@ -616,6 +618,7 @@ cc_library(
     "src/core/ext/client_config/uri_parser.h",
     "src/core/ext/lb_policy/grpclb/load_balancer_api.h",
     "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h",
+    "src/core/ext/lb_policy/common.h",
     "src/core/ext/census/aggregation.h",
     "src/core/ext/census/census_interface.h",
     "src/core/ext/census/census_rpc_stats.h",
@@ -752,6 +755,7 @@ cc_library(
     "src/core/ext/resolver/sockaddr/sockaddr_resolver.c",
     "src/core/ext/lb_policy/grpclb/load_balancer_api.c",
     "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c",
+    "src/core/ext/lb_policy/common.c",
     "src/core/ext/lb_policy/pick_first/pick_first.c",
     "src/core/ext/lb_policy/round_robin/round_robin.c",
     "src/core/ext/census/context.c",
@@ -1451,6 +1455,7 @@ objc_library(
     "src/core/ext/transport/chttp2/client/insecure/channel_create.c",
     "src/core/ext/lb_policy/grpclb/load_balancer_api.c",
     "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c",
+    "src/core/ext/lb_policy/common.c",
     "src/core/ext/lb_policy/pick_first/pick_first.c",
     "src/core/ext/lb_policy/round_robin/round_robin.c",
     "src/core/ext/resolver/dns/native/dns_resolver.c",
@@ -1621,6 +1626,7 @@ objc_library(
     "src/core/ext/client_config/uri_parser.h",
     "src/core/ext/lb_policy/grpclb/load_balancer_api.h",
     "src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h",
+    "src/core/ext/lb_policy/common.h",
     "src/core/ext/census/aggregation.h",
     "src/core/ext/census/census_interface.h",
     "src/core/ext/census/census_rpc_stats.h",
diff --git a/Makefile b/Makefile
index 12022c2dd952affd0fc605e82401a32f369f5c85..e8a98e71e57f6921e5f56f0130577f58d18a98b6 100644
--- a/Makefile
+++ b/Makefile
@@ -2601,6 +2601,7 @@ LIBGRPC_SRC = \
     third_party/nanopb/pb_common.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
+    src/core/ext/lb_policy/common.c \
     src/core/ext/lb_policy/pick_first/pick_first.c \
     src/core/ext/lb_policy/round_robin/round_robin.c \
     src/core/ext/resolver/dns/native/dns_resolver.c \
@@ -2921,6 +2922,7 @@ LIBGRPC_UNSECURE_SRC = \
     third_party/nanopb/pb_common.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
+    src/core/ext/lb_policy/common.c \
     src/core/ext/lb_policy/pick_first/pick_first.c \
     src/core/ext/lb_policy/round_robin/round_robin.c \
     src/core/ext/census/context.c \
diff --git a/binding.gyp b/binding.gyp
index 058743edbf84a237c9e181edf123a5a5cc1b70cf..95539e2a4724ee760954433535979c507d151dd6 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -712,6 +712,7 @@
         'third_party/nanopb/pb_common.c',
         'third_party/nanopb/pb_decode.c',
         'third_party/nanopb/pb_encode.c',
+        'src/core/ext/lb_policy/common.c',
         'src/core/ext/lb_policy/pick_first/pick_first.c',
         'src/core/ext/lb_policy/round_robin/round_robin.c',
         'src/core/ext/resolver/dns/native/dns_resolver.c',
diff --git a/build.yaml b/build.yaml
index 26308e8db5d17b5d0654693459b8f750b866476b..dddbdcfbfc8e5ee49a38337cf5fb0e4f9e63a586 100644
--- a/build.yaml
+++ b/build.yaml
@@ -356,6 +356,13 @@ filegroups:
   - include/grpc/impl/codegen/status.h
   uses:
   - gpr_codegen
+- name: grpc_lb_policy_common
+  headers:
+  - src/core/ext/lb_policy/common.h
+  src:
+  - src/core/ext/lb_policy/common.c
+  uses:
+  - grpc_base
 - name: grpc_lb_policy_grpclb
   headers:
   - src/core/ext/lb_policy/grpclb/load_balancer_api.h
@@ -367,6 +374,7 @@ filegroups:
   - grpc_base
   - grpc_client_config
   - nanopb
+  - grpc_lb_policy_common
 - name: grpc_lb_policy_pick_first
   src:
   - src/core/ext/lb_policy/pick_first/pick_first.c
@@ -374,6 +382,7 @@ filegroups:
   uses:
   - grpc_base
   - grpc_client_config
+  - grpc_lb_policy_common
 - name: grpc_lb_policy_round_robin
   src:
   - src/core/ext/lb_policy/round_robin/round_robin.c
@@ -381,6 +390,7 @@ filegroups:
   uses:
   - grpc_base
   - grpc_client_config
+  - grpc_lb_policy_common
 - name: grpc_resolver_dns_native
   src:
   - src/core/ext/resolver/dns/native/dns_resolver.c
diff --git a/config.m4 b/config.m4
index 2d930a648e17e4ee9c1673deee87cb98f1696a68..c4ff5dd1fa42c24cbf726cae6b9ce28f4c11e35f 100644
--- a/config.m4
+++ b/config.m4
@@ -231,6 +231,7 @@ if test "$PHP_GRPC" != "no"; then
     third_party/nanopb/pb_common.c \
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
+    src/core/ext/lb_policy/common.c \
     src/core/ext/lb_policy/pick_first/pick_first.c \
     src/core/ext/lb_policy/round_robin/round_robin.c \
     src/core/ext/resolver/dns/native/dns_resolver.c \
@@ -552,6 +553,7 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/src/boringssl)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/client_config)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/pick_first)
diff --git a/gRPC.podspec b/gRPC.podspec
index d66e03354bba976de83945eca008e26f81b265b7..b2c7d52cf4a04e6228cb64df3e53c055beb930f3 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -291,6 +291,7 @@ Pod::Spec.new do |s|
                       'third_party/nanopb/pb_common.h',
                       'third_party/nanopb/pb_decode.h',
                       'third_party/nanopb/pb_encode.h',
+                      'src/core/ext/lb_policy/common.h',
                       'src/core/ext/census/aggregation.h',
                       'src/core/ext/census/census_interface.h',
                       'src/core/ext/census/census_rpc_stats.h',
@@ -476,6 +477,7 @@ Pod::Spec.new do |s|
                       'third_party/nanopb/pb_common.c',
                       'third_party/nanopb/pb_decode.c',
                       'third_party/nanopb/pb_encode.c',
+                      'src/core/ext/lb_policy/common.c',
                       'src/core/ext/lb_policy/pick_first/pick_first.c',
                       'src/core/ext/lb_policy/round_robin/round_robin.c',
                       'src/core/ext/resolver/dns/native/dns_resolver.c',
@@ -633,6 +635,7 @@ Pod::Spec.new do |s|
                               'third_party/nanopb/pb_common.h',
                               'third_party/nanopb/pb_decode.h',
                               'third_party/nanopb/pb_encode.h',
+                              'src/core/ext/lb_policy/common.h',
                               'src/core/ext/census/aggregation.h',
                               'src/core/ext/census/census_interface.h',
                               'src/core/ext/census/census_rpc_stats.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index f83b7d3587219dc76033474a9af1c5c9858f9c0e..4a44d1a7a43156ab4d7bc0218b2a23bee35e0049 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -303,6 +303,7 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/nanopb/pb_common.h )
   s.files += %w( third_party/nanopb/pb_decode.h )
   s.files += %w( third_party/nanopb/pb_encode.h )
+  s.files += %w( src/core/ext/lb_policy/common.h )
   s.files += %w( src/core/ext/census/aggregation.h )
   s.files += %w( src/core/ext/census/census_interface.h )
   s.files += %w( src/core/ext/census/census_rpc_stats.h )
@@ -460,6 +461,7 @@ Gem::Specification.new do |s|
   s.files += %w( third_party/nanopb/pb_common.c )
   s.files += %w( third_party/nanopb/pb_decode.c )
   s.files += %w( third_party/nanopb/pb_encode.c )
+  s.files += %w( src/core/ext/lb_policy/common.c )
   s.files += %w( src/core/ext/lb_policy/pick_first/pick_first.c )
   s.files += %w( src/core/ext/lb_policy/round_robin/round_robin.c )
   s.files += %w( src/core/ext/resolver/dns/native/dns_resolver.c )
diff --git a/package.xml b/package.xml
index d192ebde2cc39817c51efc281c7d56b06d73b751..dbfe8289f1bdda68445cdbf4f0143db74e617f4a 100644
--- a/package.xml
+++ b/package.xml
@@ -306,6 +306,7 @@
     <file baseinstalldir="/" name="third_party/nanopb/pb_common.h" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_decode.h" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_encode.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/lb_policy/common.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/aggregation.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/census_interface.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/census_rpc_stats.h" role="src" />
@@ -463,6 +464,7 @@
     <file baseinstalldir="/" name="third_party/nanopb/pb_common.c" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_decode.c" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_encode.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/lb_policy/common.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/lb_policy/pick_first/pick_first.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/lb_policy/round_robin/round_robin.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/resolver/dns/native/dns_resolver.c" role="src" />
diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c
index 87abfea5ff34b5ec32704ebf5a88a0b33de23b12..68a203820bf05ce3b111fe51348e908108225a82 100644
--- a/src/core/ext/client_config/client_channel.c
+++ b/src/core/ext/client_config/client_channel.c
@@ -368,9 +368,11 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
     int r;
     GRPC_LB_POLICY_REF(lb_policy, "cc_pick_subchannel");
     gpr_mu_unlock(&chand->mu_config);
-    r = grpc_lb_policy_pick(exec_ctx, lb_policy, calld->pollset_set,
-                            initial_metadata, initial_metadata_flags,
-                            connected_subchannel, on_ready);
+    GPR_ASSERT((calld->pollset != NULL) + (calld->pollset_set != NULL) == 1);
+    r = grpc_lb_policy_pick(exec_ctx, lb_policy, calld->pollset,
+                            calld->pollset_set, initial_metadata,
+                            initial_metadata_flags, connected_subchannel,
+                            on_ready);
     GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "cc_pick_subchannel");
     return r;
   }
@@ -453,14 +455,8 @@ static void cc_set_pollset_or_pollset_set(
   GPR_ASSERT(pollset != NULL || pollset_set_alternative != NULL);
 
   call_data *calld = elem->call_data;
-  if (pollset != NULL) {
-    calld->pollset = pollset;
-    grpc_pollset_set_add_pollset(exec_ctx, calld->pollset_set, pollset);
-  } else if (pollset_set_alternative != NULL) {
-    calld->pollset = NULL;
-    grpc_pollset_set_add_pollset_set(exec_ctx, calld->pollset_set,
-                                     pollset_set_alternative);
-  }
+  calld->pollset = pollset;
+  calld->pollset_set = pollset_set_alternative;
 }
 
 const grpc_channel_filter grpc_client_channel_filter = {
diff --git a/src/core/ext/client_config/lb_policy.c b/src/core/ext/client_config/lb_policy.c
index 1e4e0077e6039c3dfb42d2ff0108c0c4142a66af..96342c7c7d841b3bc0802568fb4b29280ba512e1 100644
--- a/src/core/ext/client_config/lb_policy.c
+++ b/src/core/ext/client_config/lb_policy.c
@@ -99,12 +99,14 @@ void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx,
 }
 
 int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                        grpc_pollset_set *pollset_set,
+                        grpc_pollset *pollset,
+                        grpc_pollset_set *pollset_set_alternative,
                         grpc_metadata_batch *initial_metadata,
                         uint32_t initial_metadata_flags,
                         grpc_connected_subchannel **target,
                         grpc_closure *on_complete) {
-  return policy->vtable->pick(exec_ctx, policy, pollset_set, initial_metadata,
+  return policy->vtable->pick(exec_ctx, policy, pollset,
+                              pollset_set_alternative, initial_metadata,
                               initial_metadata_flags, target, on_complete);
 }
 
diff --git a/src/core/ext/client_config/lb_policy.h b/src/core/ext/client_config/lb_policy.h
index d5c578836b91628212879f8b1160c8646ac926a5..e9bb1850e79d76d8527e6ff182108c1d955ac6a3 100644
--- a/src/core/ext/client_config/lb_policy.h
+++ b/src/core/ext/client_config/lb_policy.h
@@ -59,7 +59,7 @@ struct grpc_lb_policy_vtable {
 
   /** implement grpc_lb_policy_pick */
   int (*pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-              grpc_pollset_set *pollset_set,
+              grpc_pollset *pollset, grpc_pollset_set *pollset_set_alternative,
               grpc_metadata_batch *initial_metadata,
               uint32_t initial_metadata_flags,
               grpc_connected_subchannel **target, grpc_closure *on_complete);
@@ -125,7 +125,8 @@ void grpc_lb_policy_init(grpc_lb_policy *policy,
     \a target.
     Picking can be asynchronous. Any IO should be done under \a pollset. */
 int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
-                        grpc_pollset_set *pollset_set,
+                        grpc_pollset *pollset,
+                        grpc_pollset_set *pollset_set_alternative,
                         grpc_metadata_batch *initial_metadata,
                         uint32_t initial_metadata_flags,
                         grpc_connected_subchannel **target,
diff --git a/src/core/ext/client_config/subchannel_call_holder.c b/src/core/ext/client_config/subchannel_call_holder.c
index c6f4b8f373c67bb0df8945ba2ff93ce43faf9809..e07dd1a6212540ac7f8a59bc7a92060eb155395d 100644
--- a/src/core/ext/client_config/subchannel_call_holder.c
+++ b/src/core/ext/client_config/subchannel_call_holder.c
@@ -68,7 +68,7 @@ void grpc_subchannel_call_holder_init(
   holder->waiting_ops_capacity = 0;
   holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
   holder->owning_call = owning_call;
-  holder->pollset_set = grpc_pollset_set_create();
+  holder->pollset_set = NULL;
 }
 
 void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx,
@@ -82,7 +82,6 @@ void grpc_subchannel_call_holder_destroy(grpc_exec_ctx *exec_ctx,
   gpr_mu_destroy(&holder->mu);
   GPR_ASSERT(holder->waiting_ops_count == 0);
   gpr_free(holder->waiting_ops);
-  grpc_pollset_set_destroy(holder->pollset_set);
 }
 
 void grpc_subchannel_call_holder_perform_op(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/ext/lb_policy/common.c b/src/core/ext/lb_policy/common.c
new file mode 100644
index 0000000000000000000000000000000000000000..bfb6aace8778ae526f3e40f41257d5b70ca7292e
--- /dev/null
+++ b/src/core/ext/lb_policy/common.c
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/log.h>
+
+#include "src/core/ext/lb_policy/common.h"
+
+void add_pollset_or_pollset_set_alternative(
+    grpc_exec_ctx *exec_ctx, grpc_pollset_set *interested_parties,
+    grpc_pollset *pollset, grpc_pollset_set *pollset_set_alternative) {
+  if (pollset != NULL) {
+    GPR_ASSERT(pollset_set_alternative == NULL);
+    grpc_pollset_set_add_pollset(exec_ctx, interested_parties, pollset);
+  } else {
+    GPR_ASSERT(pollset_set_alternative != NULL);
+    grpc_pollset_set_add_pollset_set(exec_ctx, interested_parties,
+                                     pollset_set_alternative);
+  }
+}
+
+void del_pollset_or_pollset_set_alternative(
+    grpc_exec_ctx *exec_ctx, grpc_pollset_set *interested_parties,
+    grpc_pollset *pollset, grpc_pollset_set *pollset_set_alternative) {
+  if (pollset != NULL) {
+    GPR_ASSERT(pollset_set_alternative == NULL);
+    grpc_pollset_set_del_pollset(exec_ctx, interested_parties, pollset);
+  } else {
+    GPR_ASSERT(pollset_set_alternative != NULL);
+    grpc_pollset_set_del_pollset_set(exec_ctx, interested_parties,
+                                     pollset_set_alternative);
+  }
+}
diff --git a/src/core/ext/lb_policy/common.h b/src/core/ext/lb_policy/common.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ace967328da6eedfb54f942818559cc7c491b78
--- /dev/null
+++ b/src/core/ext/lb_policy/common.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_LB_POLICY_COMMON_H
+#define GRPC_CORE_EXT_LB_POLICY_COMMON_H
+
+#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/iomgr/pollset_set.h"
+
+void add_pollset_or_pollset_set_alternative(
+    grpc_exec_ctx *exec_ctx, grpc_pollset_set *interested_parties,
+    grpc_pollset *pollset, grpc_pollset_set *pollset_set_alternative);
+
+void del_pollset_or_pollset_set_alternative(
+    grpc_exec_ctx *exec_ctx, grpc_pollset_set *interested_parties,
+    grpc_pollset *pollset, grpc_pollset_set *pollset_set_alternative);
+
+#endif /* GRPC_CORE_EXT_LB_POLICY_COMMON_H */
diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c
index 0ffa003946d6656c6f1117814c891714c46dfa06..f6613298be802cff4322b7a3749f21d6e0d751c6 100644
--- a/src/core/ext/lb_policy/pick_first/pick_first.c
+++ b/src/core/ext/lb_policy/pick_first/pick_first.c
@@ -35,11 +35,13 @@
 
 #include <grpc/support/alloc.h>
 #include "src/core/ext/client_config/lb_policy_registry.h"
+#include "src/core/ext/lb_policy/common.h"
 #include "src/core/lib/transport/connectivity_state.h"
 
 typedef struct pending_pick {
   struct pending_pick *next;
-  grpc_pollset_set *pollset_set;
+  grpc_pollset *pollset;
+  grpc_pollset_set *pollset_set_alternative;
   uint32_t initial_metadata_flags;
   grpc_connected_subchannel **target;
   grpc_closure *on_complete;
@@ -118,8 +120,9 @@ static void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
   while (pp != NULL) {
     pending_pick *next = pp->next;
     *pp->target = NULL;
-    grpc_pollset_set_del_pollset_set(exec_ctx, p->base.interested_parties,
-                                     pp->pollset_set);
+    del_pollset_or_pollset_set_alternative(exec_ctx, p->base.interested_parties,
+                                           pp->pollset,
+                                           pp->pollset_set_alternative);
     grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
     gpr_free(pp);
     pp = next;
@@ -136,8 +139,9 @@ static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
   while (pp != NULL) {
     pending_pick *next = pp->next;
     if (pp->target == target) {
-      grpc_pollset_set_del_pollset_set(exec_ctx, p->base.interested_parties,
-                                       pp->pollset_set);
+      del_pollset_or_pollset_set_alternative(
+          exec_ctx, p->base.interested_parties, pp->pollset,
+          pp->pollset_set_alternative);
       *target = NULL;
       grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
       gpr_free(pp);
@@ -162,8 +166,9 @@ static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
     pending_pick *next = pp->next;
     if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
         initial_metadata_flags_eq) {
-      grpc_pollset_set_del_pollset_set(exec_ctx, p->base.interested_parties,
-                                       pp->pollset_set);
+      del_pollset_or_pollset_set_alternative(
+          exec_ctx, p->base.interested_parties, pp->pollset,
+          pp->pollset_set_alternative);
       grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
       gpr_free(pp);
     } else {
@@ -196,7 +201,8 @@ static void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
 }
 
 static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                   grpc_pollset_set *pollset_set,
+                   grpc_pollset *pollset,
+                   grpc_pollset_set *pollset_set_alternative,
                    grpc_metadata_batch *initial_metadata,
                    uint32_t initial_metadata_flags,
                    grpc_connected_subchannel **target,
@@ -222,11 +228,12 @@ static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
     if (!p->started_picking) {
       start_picking(exec_ctx, p);
     }
-    grpc_pollset_set_add_pollset_set(exec_ctx, p->base.interested_parties,
-                                     pollset_set);
+    add_pollset_or_pollset_set_alternative(exec_ctx, p->base.interested_parties,
+                                           pollset, pollset_set_alternative);
     pp = gpr_malloc(sizeof(*pp));
     pp->next = p->pending_picks;
-    pp->pollset_set = pollset_set;
+    pp->pollset = pollset;
+    pp->pollset_set_alternative = pollset_set_alternative;
     pp->target = target;
     pp->initial_metadata_flags = initial_metadata_flags;
     pp->on_complete = on_complete;
@@ -306,8 +313,9 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
         while ((pp = p->pending_picks)) {
           p->pending_picks = pp->next;
           *pp->target = selected;
-          grpc_pollset_set_del_pollset_set(exec_ctx, p->base.interested_parties,
-                                           pp->pollset_set);
+          del_pollset_or_pollset_set_alternative(
+              exec_ctx, p->base.interested_parties, pp->pollset,
+              pp->pollset_set_alternative);
           grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
           gpr_free(pp);
         }
diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c
index 78ac61923f9caba691cd747d1ccfb7a9830ea328..f4e3d60a839cdfa37992a9e62e0c9aa5ddd4353e 100644
--- a/src/core/ext/lb_policy/round_robin/round_robin.c
+++ b/src/core/ext/lb_policy/round_robin/round_robin.c
@@ -36,6 +36,7 @@
 #include <grpc/support/alloc.h>
 
 #include "src/core/ext/client_config/lb_policy_registry.h"
+#include "src/core/ext/lb_policy/common.h"
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/transport/connectivity_state.h"
 
@@ -48,7 +49,8 @@ int grpc_lb_round_robin_trace = 0;
  * Once a pick is available, \a target is updated and \a on_complete called. */
 typedef struct pending_pick {
   struct pending_pick *next;
-  grpc_pollset_set *pollset_set;
+  grpc_pollset *pollset;
+  grpc_pollset_set *pollset_set_alternative;
   uint32_t initial_metadata_flags;
   grpc_connected_subchannel **target;
   grpc_closure *on_complete;
@@ -262,8 +264,9 @@ static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
   while (pp != NULL) {
     pending_pick *next = pp->next;
     if (pp->target == target) {
-      grpc_pollset_set_del_pollset_set(exec_ctx, p->base.interested_parties,
-                                       pp->pollset_set);
+      del_pollset_or_pollset_set_alternative(
+          exec_ctx, p->base.interested_parties, pp->pollset,
+          pp->pollset_set_alternative);
       *target = NULL;
       grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
       gpr_free(pp);
@@ -288,8 +291,9 @@ static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
     pending_pick *next = pp->next;
     if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
         initial_metadata_flags_eq) {
-      grpc_pollset_set_del_pollset_set(exec_ctx, p->base.interested_parties,
-                                       pp->pollset_set);
+      del_pollset_or_pollset_set_alternative(
+          exec_ctx, p->base.interested_parties, pp->pollset,
+          pp->pollset_set_alternative);
       *pp->target = NULL;
       grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
       gpr_free(pp);
@@ -329,7 +333,8 @@ static void rr_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
 }
 
 static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
-                   grpc_pollset_set *pollset_set,
+                   grpc_pollset *pollset,
+                   grpc_pollset_set *pollset_set_alternative,
                    grpc_metadata_batch *initial_metadata,
                    uint32_t initial_metadata_flags,
                    grpc_connected_subchannel **target,
@@ -353,11 +358,12 @@ static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
     if (!p->started_picking) {
       start_picking(exec_ctx, p);
     }
-    grpc_pollset_set_add_pollset_set(exec_ctx, p->base.interested_parties,
-                                     pollset_set);
+    add_pollset_or_pollset_set_alternative(exec_ctx, p->base.interested_parties,
+                                           pollset, pollset_set_alternative);
     pp = gpr_malloc(sizeof(*pp));
     pp->next = p->pending_picks;
-    pp->pollset_set = pollset_set;
+    pp->pollset = pollset;
+    pp->pollset_set_alternative = pollset_set_alternative;
     pp->target = target;
     pp->on_complete = on_complete;
     pp->initial_metadata_flags = initial_metadata_flags;
@@ -406,8 +412,9 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
                     "[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (NODE %p)",
                     selected->subchannel, selected);
           }
-          grpc_pollset_set_del_pollset_set(exec_ctx, p->base.interested_parties,
-                                           pp->pollset_set);
+          del_pollset_or_pollset_set_alternative(
+              exec_ctx, p->base.interested_parties, pp->pollset,
+              pp->pollset_set_alternative);
           grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
           gpr_free(pp);
         }
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index c5a0a398b43097cf06f65782589f982615403cce..90948efa555a48162b7997e78d242612975a7198 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -225,6 +225,7 @@ CORE_SOURCE_FILES = [
   'third_party/nanopb/pb_common.c',
   'third_party/nanopb/pb_decode.c',
   'third_party/nanopb/pb_encode.c',
+  'src/core/ext/lb_policy/common.c',
   'src/core/ext/lb_policy/pick_first/pick_first.c',
   'src/core/ext/lb_policy/round_robin/round_robin.c',
   'src/core/ext/resolver/dns/native/dns_resolver.c',
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 3a774a70d6bd7d95f09bf120ea291b9379bd3736..1de79858f596012255d7d910e4c856a317de72fd 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -918,6 +918,7 @@ third_party/nanopb/pb.h \
 third_party/nanopb/pb_common.h \
 third_party/nanopb/pb_decode.h \
 third_party/nanopb/pb_encode.h \
+src/core/ext/lb_policy/common.h \
 src/core/ext/census/aggregation.h \
 src/core/ext/census/census_interface.h \
 src/core/ext/census/census_rpc_stats.h \
@@ -1075,6 +1076,7 @@ src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \
 third_party/nanopb/pb_common.c \
 third_party/nanopb/pb_decode.c \
 third_party/nanopb/pb_encode.c \
+src/core/ext/lb_policy/common.c \
 src/core/ext/lb_policy/pick_first/pick_first.c \
 src/core/ext/lb_policy/round_robin/round_robin.c \
 src/core/ext/resolver/dns/native/dns_resolver.c \
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 38e68f3b1a1de6f715a867da4bb584e96f1ac384..8a8bf39dc2a452ebb7551ac92bf068a2059e1b0d 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -5851,11 +5851,29 @@
     "third_party": false, 
     "type": "filegroup"
   }, 
+  {
+    "deps": [
+      "gpr", 
+      "grpc_base"
+    ], 
+    "headers": [
+      "src/core/ext/lb_policy/common.h"
+    ], 
+    "language": "c", 
+    "name": "grpc_lb_policy_common", 
+    "src": [
+      "src/core/ext/lb_policy/common.c", 
+      "src/core/ext/lb_policy/common.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
   {
     "deps": [
       "gpr", 
       "grpc_base", 
       "grpc_client_config", 
+      "grpc_lb_policy_common", 
       "nanopb"
     ], 
     "headers": [
@@ -5877,7 +5895,8 @@
     "deps": [
       "gpr", 
       "grpc_base", 
-      "grpc_client_config"
+      "grpc_client_config", 
+      "grpc_lb_policy_common"
     ], 
     "headers": [], 
     "language": "c", 
@@ -5892,7 +5911,8 @@
     "deps": [
       "gpr", 
       "grpc_base", 
-      "grpc_client_config"
+      "grpc_client_config", 
+      "grpc_lb_policy_common"
     ], 
     "headers": [], 
     "language": "c", 
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 4eec05a3b1fc308de93052c0cca16e46c3b1872c..9eaad77ac7d43144ef4d80a602c6016ada074cc6 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -427,6 +427,7 @@
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\common.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_rpc_stats.h" />
@@ -737,6 +738,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\common.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\pick_first\pick_first.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\round_robin\round_robin.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 17c88c4805e0a8b30241d898adb0d5de7d73712c..0a61853f2971c483f5ab96dd17fea87ed087b458 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -454,6 +454,9 @@
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
       <Filter>third_party\nanopb</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\common.c">
+      <Filter>src\core\ext\lb_policy</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\pick_first\pick_first.c">
       <Filter>src\core\ext\lb_policy\pick_first</Filter>
     </ClCompile>
@@ -974,6 +977,9 @@
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h">
       <Filter>third_party\nanopb</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\common.h">
+      <Filter>src\core\ext\lb_policy</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 26050dcf74ed7e289c7413be3486bc8b264fb007..01214556ce984e9c08153a7d14d499a46813ef03 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -402,6 +402,7 @@
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" />
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\common.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\census_rpc_stats.h" />
@@ -676,6 +677,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\common.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\pick_first\pick_first.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\round_robin\round_robin.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index a4acf513bc192db5a9dacffc7c5536faa994d078..e2de5acd037a7ed9502d8eba5f1eabe558439d71 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -400,6 +400,9 @@
     <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
       <Filter>third_party\nanopb</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\common.c">
+      <Filter>src\core\ext\lb_policy</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\lb_policy\pick_first\pick_first.c">
       <Filter>src\core\ext\lb_policy\pick_first</Filter>
     </ClCompile>
@@ -866,6 +869,9 @@
     <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h">
       <Filter>third_party\nanopb</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\lb_policy\common.h">
+      <Filter>src\core\ext\lb_policy</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\aggregation.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>