diff --git a/.gitignore b/.gitignore
index 9a1dc008505d5c6a61b6c680a8fcd35085a85c3c..502483f45698907f47c72722070a33c58475f39b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@ coverage
 
 # cache for run_tests.py
 .run_tests_cache
+.preprocessed_build
 
 # emacs temp files
 *~
diff --git a/.gitmodules b/.gitmodules
index 008bc5fae809b9327614df4a432c2d3d894f2c61..c37d0abdf0bdf70f9b97f16bf7ae6010d16c6eb5 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -14,3 +14,6 @@
 [submodule "third_party/boringssl"]
 	path = third_party/boringssl
 	url = https://boringssl.googlesource.com/boringssl
+[submodule "third_party/nanopb"]
+	path = third_party/nanopb
+	url = https://github.com/nanopb/nanopb.git
diff --git a/.travis.yml b/.travis.yml
index d2d1c8ba63994226dc3401323252ca7364fa8951..004d44f3a557b817390803f865b1c813145e120c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,5 @@
 language: objective-c
-osx_image: xcode7.1
+osx_image: xcode7.2
 env:
   global:
     - CONFIG=opt
@@ -27,6 +27,6 @@ xcode_scheme:
   - InteropTestsLocalCleartext
   # TODO(jcanizales): Investigate why they time out:
   # - InteropTestsRemote
-xcode_sdk: iphonesimulator9.1
+xcode_sdk: iphonesimulator9.2
 notifications:
   email: false
diff --git a/BUILD b/BUILD
index f6c4338493aa8881d145b2a95702fe9ed54649ed..0e9f37a0e3fdadeb3a8eebcddfca9f7e70a6aaf6 100644
--- a/BUILD
+++ b/BUILD
@@ -47,13 +47,14 @@ cc_library(
     "src/core/profiling/timers.h",
     "src/core/support/block_annotate.h",
     "src/core/support/env.h",
-    "src/core/support/file.h",
+    "src/core/support/load_file.h",
     "src/core/support/murmur_hash.h",
     "src/core/support/stack_lockfree.h",
     "src/core/support/string.h",
     "src/core/support/string_win32.h",
     "src/core/support/thd_internal.h",
     "src/core/support/time_precise.h",
+    "src/core/support/tmpfile.h",
     "src/core/profiling/basic_timers.c",
     "src/core/profiling/stap_timers.c",
     "src/core/support/alloc.c",
@@ -66,11 +67,9 @@ cc_library(
     "src/core/support/env_linux.c",
     "src/core/support/env_posix.c",
     "src/core/support/env_win32.c",
-    "src/core/support/file.c",
-    "src/core/support/file_posix.c",
-    "src/core/support/file_win32.c",
     "src/core/support/histogram.c",
     "src/core/support/host_port.c",
+    "src/core/support/load_file.c",
     "src/core/support/log.c",
     "src/core/support/log_android.c",
     "src/core/support/log_linux.c",
@@ -96,6 +95,8 @@ cc_library(
     "src/core/support/time_precise.c",
     "src/core/support/time_win32.c",
     "src/core/support/tls_pthread.c",
+    "src/core/support/tmpfile_posix.c",
+    "src/core/support/tmpfile_win32.c",
     "src/core/support/wrap_memcpy.c",
   ],
   hdrs = [
@@ -168,6 +169,7 @@ cc_library(
     "src/core/client_config/client_config.h",
     "src/core/client_config/connector.h",
     "src/core/client_config/initial_connect_string.h",
+    "src/core/client_config/lb_policies/load_balancer_api.h",
     "src/core/client_config/lb_policies/pick_first.h",
     "src/core/client_config/lb_policies/round_robin.h",
     "src/core/client_config/lb_policy.h",
@@ -218,7 +220,6 @@ cc_library(
     "src/core/iomgr/time_averaged_stats.h",
     "src/core/iomgr/timer.h",
     "src/core/iomgr/timer_heap.h",
-    "src/core/iomgr/timer_internal.h",
     "src/core/iomgr/udp_server.h",
     "src/core/iomgr/wakeup_fd_pipe.h",
     "src/core/iomgr/wakeup_fd_posix.h",
@@ -229,6 +230,7 @@ cc_library(
     "src/core/json/json_common.h",
     "src/core/json/json_reader.h",
     "src/core/json/json_writer.h",
+    "src/core/proto/grpc/lb/v0/load_balancer.pb.h",
     "src/core/statistics/census_interface.h",
     "src/core/statistics/census_rpc_stats.h",
     "src/core/surface/api_trace.h",
@@ -269,7 +271,7 @@ cc_library(
     "src/core/transport/transport.h",
     "src/core/transport/transport_impl.h",
     "src/core/security/auth_filters.h",
-    "src/core/security/base64.h",
+    "src/core/security/b64.h",
     "src/core/security/credentials.h",
     "src/core/security/handshake.h",
     "src/core/security/json_token.h",
@@ -285,6 +287,10 @@ cc_library(
     "src/core/census/aggregation.h",
     "src/core/census/mlog.h",
     "src/core/census/rpc_metric_id.h",
+    "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/census/grpc_context.c",
     "src/core/census/grpc_filter.c",
     "src/core/channel/channel_args.c",
@@ -300,6 +306,7 @@ cc_library(
     "src/core/client_config/connector.c",
     "src/core/client_config/default_initial_connect_string.c",
     "src/core/client_config/initial_connect_string.c",
+    "src/core/client_config/lb_policies/load_balancer_api.c",
     "src/core/client_config/lb_policies/pick_first.c",
     "src/core/client_config/lb_policies/round_robin.c",
     "src/core/client_config/lb_policy.c",
@@ -314,7 +321,7 @@ cc_library(
     "src/core/client_config/subchannel_factory.c",
     "src/core/client_config/subchannel_index.c",
     "src/core/client_config/uri_parser.c",
-    "src/core/compression/algorithm.c",
+    "src/core/compression/compression_algorithm.c",
     "src/core/compression/message_compress.c",
     "src/core/debug/trace.c",
     "src/core/httpcli/format_request.c",
@@ -364,6 +371,7 @@ cc_library(
     "src/core/json/json_reader.c",
     "src/core/json/json_string.c",
     "src/core/json/json_writer.c",
+    "src/core/proto/grpc/lb/v0/load_balancer.pb.c",
     "src/core/surface/alarm.c",
     "src/core/surface/api_trace.c",
     "src/core/surface/byte_buffer.c",
@@ -414,7 +422,7 @@ cc_library(
     "src/core/transport/transport.c",
     "src/core/transport/transport_op_string.c",
     "src/core/httpcli/httpcli_security_connector.c",
-    "src/core/security/base64.c",
+    "src/core/security/b64.c",
     "src/core/security/client_auth_filter.c",
     "src/core/security/credentials.c",
     "src/core/security/credentials_metadata.c",
@@ -440,6 +448,9 @@ cc_library(
     "src/core/census/operation.c",
     "src/core/census/placeholders.c",
     "src/core/census/tracing.c",
+    "third_party/nanopb/pb_common.c",
+    "third_party/nanopb/pb_decode.c",
+    "third_party/nanopb/pb_encode.c",
   ],
   hdrs = [
     "include/grpc/grpc_security.h",
@@ -488,6 +499,7 @@ cc_library(
     "src/core/client_config/client_config.h",
     "src/core/client_config/connector.h",
     "src/core/client_config/initial_connect_string.h",
+    "src/core/client_config/lb_policies/load_balancer_api.h",
     "src/core/client_config/lb_policies/pick_first.h",
     "src/core/client_config/lb_policies/round_robin.h",
     "src/core/client_config/lb_policy.h",
@@ -538,7 +550,6 @@ cc_library(
     "src/core/iomgr/time_averaged_stats.h",
     "src/core/iomgr/timer.h",
     "src/core/iomgr/timer_heap.h",
-    "src/core/iomgr/timer_internal.h",
     "src/core/iomgr/udp_server.h",
     "src/core/iomgr/wakeup_fd_pipe.h",
     "src/core/iomgr/wakeup_fd_posix.h",
@@ -549,6 +560,7 @@ cc_library(
     "src/core/json/json_common.h",
     "src/core/json/json_reader.h",
     "src/core/json/json_writer.h",
+    "src/core/proto/grpc/lb/v0/load_balancer.pb.h",
     "src/core/statistics/census_interface.h",
     "src/core/statistics/census_rpc_stats.h",
     "src/core/surface/api_trace.h",
@@ -591,6 +603,10 @@ cc_library(
     "src/core/census/aggregation.h",
     "src/core/census/mlog.h",
     "src/core/census/rpc_metric_id.h",
+    "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/surface/init_unsecure.c",
     "src/core/census/grpc_context.c",
     "src/core/census/grpc_filter.c",
@@ -607,6 +623,7 @@ cc_library(
     "src/core/client_config/connector.c",
     "src/core/client_config/default_initial_connect_string.c",
     "src/core/client_config/initial_connect_string.c",
+    "src/core/client_config/lb_policies/load_balancer_api.c",
     "src/core/client_config/lb_policies/pick_first.c",
     "src/core/client_config/lb_policies/round_robin.c",
     "src/core/client_config/lb_policy.c",
@@ -621,7 +638,7 @@ cc_library(
     "src/core/client_config/subchannel_factory.c",
     "src/core/client_config/subchannel_index.c",
     "src/core/client_config/uri_parser.c",
-    "src/core/compression/algorithm.c",
+    "src/core/compression/compression_algorithm.c",
     "src/core/compression/message_compress.c",
     "src/core/debug/trace.c",
     "src/core/httpcli/format_request.c",
@@ -671,6 +688,7 @@ cc_library(
     "src/core/json/json_reader.c",
     "src/core/json/json_string.c",
     "src/core/json/json_writer.c",
+    "src/core/proto/grpc/lb/v0/load_balancer.pb.c",
     "src/core/surface/alarm.c",
     "src/core/surface/api_trace.c",
     "src/core/surface/byte_buffer.c",
@@ -726,6 +744,9 @@ cc_library(
     "src/core/census/operation.c",
     "src/core/census/placeholders.c",
     "src/core/census/tracing.c",
+    "third_party/nanopb/pb_common.c",
+    "third_party/nanopb/pb_decode.c",
+    "third_party/nanopb/pb_encode.c",
   ],
   hdrs = [
     "include/grpc/byte_buffer.h",
@@ -797,7 +818,6 @@ cc_library(
     "src/cpp/client/credentials.cc",
     "src/cpp/client/generic_stub.cc",
     "src/cpp/client/insecure_credentials.cc",
-    "src/cpp/common/alarm.cc",
     "src/cpp/common/call.cc",
     "src/cpp/common/channel_arguments.cc",
     "src/cpp/common/completion_queue.cc",
@@ -921,7 +941,6 @@ cc_library(
     "src/cpp/client/credentials.cc",
     "src/cpp/client/generic_stub.cc",
     "src/cpp/client/insecure_credentials.cc",
-    "src/cpp/common/alarm.cc",
     "src/cpp/common/call.cc",
     "src/cpp/common/channel_arguments.cc",
     "src/cpp/common/completion_queue.cc",
@@ -1151,11 +1170,9 @@ objc_library(
     "src/core/support/env_linux.c",
     "src/core/support/env_posix.c",
     "src/core/support/env_win32.c",
-    "src/core/support/file.c",
-    "src/core/support/file_posix.c",
-    "src/core/support/file_win32.c",
     "src/core/support/histogram.c",
     "src/core/support/host_port.c",
+    "src/core/support/load_file.c",
     "src/core/support/log.c",
     "src/core/support/log_android.c",
     "src/core/support/log_linux.c",
@@ -1181,6 +1198,8 @@ objc_library(
     "src/core/support/time_precise.c",
     "src/core/support/time_win32.c",
     "src/core/support/tls_pthread.c",
+    "src/core/support/tmpfile_posix.c",
+    "src/core/support/tmpfile_win32.c",
     "src/core/support/wrap_memcpy.c",
   ],
   hdrs = [
@@ -1229,13 +1248,14 @@ objc_library(
     "src/core/profiling/timers.h",
     "src/core/support/block_annotate.h",
     "src/core/support/env.h",
-    "src/core/support/file.h",
+    "src/core/support/load_file.h",
     "src/core/support/murmur_hash.h",
     "src/core/support/stack_lockfree.h",
     "src/core/support/string.h",
     "src/core/support/string_win32.h",
     "src/core/support/thd_internal.h",
     "src/core/support/time_precise.h",
+    "src/core/support/tmpfile.h",
   ],
   includes = [
     "include",
@@ -1264,6 +1284,7 @@ objc_library(
     "src/core/client_config/connector.c",
     "src/core/client_config/default_initial_connect_string.c",
     "src/core/client_config/initial_connect_string.c",
+    "src/core/client_config/lb_policies/load_balancer_api.c",
     "src/core/client_config/lb_policies/pick_first.c",
     "src/core/client_config/lb_policies/round_robin.c",
     "src/core/client_config/lb_policy.c",
@@ -1278,7 +1299,7 @@ objc_library(
     "src/core/client_config/subchannel_factory.c",
     "src/core/client_config/subchannel_index.c",
     "src/core/client_config/uri_parser.c",
-    "src/core/compression/algorithm.c",
+    "src/core/compression/compression_algorithm.c",
     "src/core/compression/message_compress.c",
     "src/core/debug/trace.c",
     "src/core/httpcli/format_request.c",
@@ -1328,6 +1349,7 @@ objc_library(
     "src/core/json/json_reader.c",
     "src/core/json/json_string.c",
     "src/core/json/json_writer.c",
+    "src/core/proto/grpc/lb/v0/load_balancer.pb.c",
     "src/core/surface/alarm.c",
     "src/core/surface/api_trace.c",
     "src/core/surface/byte_buffer.c",
@@ -1378,7 +1400,7 @@ objc_library(
     "src/core/transport/transport.c",
     "src/core/transport/transport_op_string.c",
     "src/core/httpcli/httpcli_security_connector.c",
-    "src/core/security/base64.c",
+    "src/core/security/b64.c",
     "src/core/security/client_auth_filter.c",
     "src/core/security/credentials.c",
     "src/core/security/credentials_metadata.c",
@@ -1404,6 +1426,9 @@ objc_library(
     "src/core/census/operation.c",
     "src/core/census/placeholders.c",
     "src/core/census/tracing.c",
+    "third_party/nanopb/pb_common.c",
+    "third_party/nanopb/pb_decode.c",
+    "third_party/nanopb/pb_encode.c",
   ],
   hdrs = [
     "include/grpc/grpc_security.h",
@@ -1433,6 +1458,7 @@ objc_library(
     "src/core/client_config/client_config.h",
     "src/core/client_config/connector.h",
     "src/core/client_config/initial_connect_string.h",
+    "src/core/client_config/lb_policies/load_balancer_api.h",
     "src/core/client_config/lb_policies/pick_first.h",
     "src/core/client_config/lb_policies/round_robin.h",
     "src/core/client_config/lb_policy.h",
@@ -1483,7 +1509,6 @@ objc_library(
     "src/core/iomgr/time_averaged_stats.h",
     "src/core/iomgr/timer.h",
     "src/core/iomgr/timer_heap.h",
-    "src/core/iomgr/timer_internal.h",
     "src/core/iomgr/udp_server.h",
     "src/core/iomgr/wakeup_fd_pipe.h",
     "src/core/iomgr/wakeup_fd_posix.h",
@@ -1494,6 +1519,7 @@ objc_library(
     "src/core/json/json_common.h",
     "src/core/json/json_reader.h",
     "src/core/json/json_writer.h",
+    "src/core/proto/grpc/lb/v0/load_balancer.pb.h",
     "src/core/statistics/census_interface.h",
     "src/core/statistics/census_rpc_stats.h",
     "src/core/surface/api_trace.h",
@@ -1534,7 +1560,7 @@ objc_library(
     "src/core/transport/transport.h",
     "src/core/transport/transport_impl.h",
     "src/core/security/auth_filters.h",
-    "src/core/security/base64.h",
+    "src/core/security/b64.h",
     "src/core/security/credentials.h",
     "src/core/security/handshake.h",
     "src/core/security/json_token.h",
@@ -1550,6 +1576,10 @@ objc_library(
     "src/core/census/aggregation.h",
     "src/core/census/mlog.h",
     "src/core/census/rpc_metric_id.h",
+    "third_party/nanopb/pb.h",
+    "third_party/nanopb/pb_common.h",
+    "third_party/nanopb/pb_decode.h",
+    "third_party/nanopb/pb_encode.h",
   ],
   includes = [
     "include",
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 03d2e276a825e33e9cc348b64f74afcf419731de..b4e958d3b2a841ae8a49c347c6159ad6b4ce697d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -21,6 +21,15 @@ In order to run all of the tests we provide, you will need valgrind and clang.
 More specifically, under debian, you will need the package libc++-dev to
 properly run all the tests.
 
+Compiling and running grpc C++ tests depend on protobuf 3.0.0, gtest and gflags.
+Although gflags is provided in third_party, you will need to manually install
+that dependency on your system to run these tests. Under a Debian or Ubuntu
+system, you can install the gtests and gflags packages using apt-get:
+
+```sh
+ $ [sudo] apt-get install libgflags-dev libgtest-dev
+```
+
 If you are planning to work on any of the languages other than C and C++, you
 will also need their appropriate development environments.
 
@@ -36,9 +45,13 @@ In order to run most of the available tests, one would need to run:
 
 `./tools/run_tests/run_tests.py`
 
-If you want to run all the possible tests for any of the languages {c, c++, node, php, python}, do this:
+If you want to run tests for any of the languages {c, c++, csharp, node, objc, php, python, ruby}, do this:
+
+`./tools/run_tests/run_tests.py -l <lang>`
+
+To know about the list of available commands, do this:
 
-`./tools/run_tests/run_tests.py -l <lang> -c all`
+`./tools/run_tests/run_tests.py -h`
 
 ## Adding or removing source code
 
diff --git a/INSTALL.md b/INSTALL.md
index d9411db021d5784771951d06fdd13070b7fcf449..454a8b7b2fdf68590fe77e15a9b3d1c6ea7ccc08 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -3,7 +3,7 @@
 For language-specific installation instructions for gRPC runtime, please
 refer to these documents
 
- * [C++](examples/cpp)
+ * [C++](examples/cpp): Currently to install gRPC for C++, you need to build from source as described below.
  * [C#](src/csharp): NuGet package `Grpc`
  * [Go](https://github.com/grpc/grpc-go): `go get google.golang.org/grpc`
  * [Java](https://github.com/grpc/grpc-java)
@@ -32,6 +32,17 @@ terminal:
  $ [sudo] xcode-select --install
 ```
 
+##Protoc
+
+By default gRPC uses [protocol buffers](https://github.com/google/protobuf),
+you will need the `protoc` compiler to generate stub server and client code.
+
+If you compile gRPC from source, as described below, the Makefile will
+automatically try and compile the `protoc` in third_party if you cloned the
+repository recursively and it detects that you don't already have it
+installed.
+
+
 #Build from Source
 
 For developers who are interested to contribute, here is how to compile the
diff --git a/Makefile b/Makefile
index f38ae19a26a24323d9391417f77d254b370478b9..371a06b8acdcbdfa5e49fbb01320f509d30f3946 100644
--- a/Makefile
+++ b/Makefile
@@ -121,7 +121,7 @@ LD_asan-noleaks = clang
 LDXX_asan-noleaks = clang++
 CPPFLAGS_asan-noleaks = -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
 LDFLAGS_asan-noleaks = -fsanitize=address
-DEFINES_asan-noleaks += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=1.5
+DEFINES_asan-noleaks += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
 
 VALID_CONFIG_ubsan = 1
 REQUIRE_CUSTOM_LIBRARIES_ubsan = 1
@@ -177,7 +177,7 @@ LD_asan = clang
 LDXX_asan = clang++
 CPPFLAGS_asan = -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument -DGPR_NO_DIRECT_SYSCALLS
 LDFLAGS_asan = -fsanitize=address
-DEFINES_asan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=1.5
+DEFINES_asan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=3
 
 VALID_CONFIG_tsan = 1
 REQUIRE_CUSTOM_LIBRARIES_tsan = 1
@@ -187,7 +187,7 @@ LD_tsan = clang
 LDXX_tsan = clang++
 CPPFLAGS_tsan = -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
 LDFLAGS_tsan = -fsanitize=thread -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
-DEFINES_tsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=2
+DEFINES_tsan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=5
 
 VALID_CONFIG_msan = 1
 REQUIRE_CUSTOM_LIBRARIES_msan = 1
@@ -198,7 +198,7 @@ LDXX_msan = clang++
 CPPFLAGS_msan = -O0 -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -Wno-unused-command-line-argument -fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
 LDFLAGS_msan = -fsanitize=memory -DGTEST_HAS_TR1_TUPLE=0 -DGTEST_USE_OWN_TR1_TUPLE=1 -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
 DEFINES_msan = NDEBUG
-DEFINES_msan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=2
+DEFINES_msan += GRPC_TEST_SLOWDOWN_BUILD_FACTOR=4
 
 VALID_CONFIG_mutrace = 1
 CC_mutrace = $(DEFAULT_CC)
@@ -275,6 +275,12 @@ endif
 CXX11_CHECK_CMD = $(CXX) -std=c++11 -o $(TMPOUT) -c test/build/c++11.cc
 HAS_CXX11 = $(shell $(CXX11_CHECK_CMD) 2> /dev/null && echo true || echo false)
 
+CHECK_SHADOW_WORKS_CMD = $(CC) -std=c99 -Werror -Wshadow -o $(TMPOUT) -c test/build/shadow.c
+HAS_WORKING_SHADOW = $(shell $(CHECK_SHADOW_WORKS_CMD) 2> /dev/null && echo true || echo false)
+ifeq ($(HAS_WORKING_SHADOW),true)
+W_SHADOW=-Wshadow
+endif
+
 CHECK_NO_SHIFT_NEGATIVE_VALUE_CMD = $(CC) -std=c99 -Werror -Wno-shift-negative-value -o $(TMPOUT) -c test/build/empty.c
 HAS_NO_SHIFT_NEGATIVE_VALUE = $(shell $(CHECK_NO_SHIFT_NEGATIVE_VALUE_CMD) 2> /dev/null && echo true || echo false)
 ifeq ($(HAS_NO_SHIFT_NEGATIVE_VALUE),true)
@@ -295,7 +301,7 @@ ifdef EXTRA_DEFINES
 DEFINES += $(EXTRA_DEFINES)
 endif
 
-CFLAGS += -std=c99 -Wsign-conversion -Wconversion -Wshadow
+CFLAGS += -std=c99 -Wsign-conversion -Wconversion $(W_SHADOW)
 ifeq ($(HAS_CXX11),true)
 CXXFLAGS += -std=c++11
 else
@@ -426,6 +432,7 @@ endif
 
 OPENSSL_ALPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
 OPENSSL_NPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-npn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
+BORINGSSL_COMPILE_CHECK_CMD = $(CC) $(CPPFLAGS) -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare -o $(TMPOUT) test/build/boringssl.c $(LDFLAGS)
 ZLIB_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS)
 PROTOBUF_CHECK_CMD = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS)
 
@@ -510,10 +517,13 @@ HAS_ZOOKEEPER = $(shell $(ZOOKEEPER_CHECK_CMD) 2> /dev/null && echo true || echo
 # Note that for testing purposes, one can do:
 #   make HAS_EMBEDDED_OPENSSL_ALPN=false
 # to emulate the fact we do not have OpenSSL in the third_party folder.
-ifeq ($(wildcard third_party/boringssl/include/openssl/ssl.h),)
+ifneq ($(wildcard third_party/openssl-1.0.2f/libssl.a),)
+HAS_EMBEDDED_OPENSSL_ALPN = third_party/openssl-1.0.2f
+else ifeq ($(wildcard third_party/boringssl/include/openssl/ssl.h),)
 HAS_EMBEDDED_OPENSSL_ALPN = false
 else
-HAS_EMBEDDED_OPENSSL_ALPN = true
+CAN_COMPILE_EMBEDDED_OPENSSL ?= $(shell $(BORINGSSL_COMPILE_CHECK_CMD) 2> /dev/null && echo true || echo false)
+HAS_EMBEDDED_OPENSSL_ALPN = $(CAN_COMPILE_EMBEDDED_OPENSSL)
 endif
 
 ifeq ($(wildcard third_party/zlib/zlib.h),)
@@ -572,8 +582,8 @@ ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true)
 EMBED_OPENSSL ?= false
 NO_SECURE ?= false
 else # HAS_SYSTEM_OPENSSL_ALPN=false
-ifeq ($(HAS_EMBEDDED_OPENSSL_ALPN),true)
-EMBED_OPENSSL ?= true
+ifneq ($(HAS_EMBEDDED_OPENSSL_ALPN),false)
+EMBED_OPENSSL ?= $(HAS_EMBEDDED_OPENSSL_ALPN)
 NO_SECURE ?= false
 else # HAS_EMBEDDED_OPENSSL_ALPN=false
 ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
@@ -594,6 +604,12 @@ OPENSSL_MERGE_LIBS += $(LIBDIR)/$(CONFIG)/libboringssl.a
 OPENSSL_MERGE_OBJS += $(LIBBORINGSSL_OBJS)
 # need to prefix these to ensure overriding system libraries
 CPPFLAGS := -Ithird_party/boringssl/include $(CPPFLAGS)
+else ifneq ($(EMBED_OPENSSL),false)
+OPENSSL_DEP += $(EMBED_OPENSSL)/libssl.a $(EMBED_OPENSSL)/libcrypto.a
+OPENSSL_MERGE_LIBS += $(EMBED_OPENSSL)/libssl.a $(EMBED_OPENSSL)/libcrypto.a
+OPENSSL_MERGE_OBJS += $(wildcard $(EMBED_OPENSSL)/grpc_obj/*.o)
+# need to prefix these to ensure overriding system libraries
+CPPFLAGS := -I$(EMBED_OPENSSL)/include $(CPPFLAGS)
 else # EMBED_OPENSSL=false
 ifeq ($(HAS_PKG_CONFIG),true)
 OPENSSL_PKG_CONFIG = true
@@ -768,8 +784,9 @@ openssl_dep_message:
 	@echo
 	@echo "DEPENDENCY ERROR"
 	@echo
-	@echo "The target you are trying to run requires OpenSSL."
-	@echo "Your system doesn't have it, and neither does the third_party directory."
+	@echo "The target you are trying to run requires an OpenSSL implementation."
+	@echo "Your system doesn't have one, and either the third_party directory"
+	@echo "doesn't have it, or your compiler can't build BoringSSL."
 	@echo
 	@echo "Please consult INSTALL to get more information."
 	@echo
@@ -826,7 +843,6 @@ alloc_test: $(BINDIR)/$(CONFIG)/alloc_test
 alpn_test: $(BINDIR)/$(CONFIG)/alpn_test
 bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
 census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
-census_log_test: $(BINDIR)/$(CONFIG)/census_log_test
 channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
 chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test
 chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
@@ -848,9 +864,9 @@ gpr_avl_test: $(BINDIR)/$(CONFIG)/gpr_avl_test
 gpr_cmdline_test: $(BINDIR)/$(CONFIG)/gpr_cmdline_test
 gpr_cpu_test: $(BINDIR)/$(CONFIG)/gpr_cpu_test
 gpr_env_test: $(BINDIR)/$(CONFIG)/gpr_env_test
-gpr_file_test: $(BINDIR)/$(CONFIG)/gpr_file_test
 gpr_histogram_test: $(BINDIR)/$(CONFIG)/gpr_histogram_test
 gpr_host_port_test: $(BINDIR)/$(CONFIG)/gpr_host_port_test
+gpr_load_file_test: $(BINDIR)/$(CONFIG)/gpr_load_file_test
 gpr_log_test: $(BINDIR)/$(CONFIG)/gpr_log_test
 gpr_slice_buffer_test: $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test
 gpr_slice_test: $(BINDIR)/$(CONFIG)/gpr_slice_test
@@ -862,7 +878,7 @@ gpr_time_test: $(BINDIR)/$(CONFIG)/gpr_time_test
 gpr_tls_test: $(BINDIR)/$(CONFIG)/gpr_tls_test
 gpr_useful_test: $(BINDIR)/$(CONFIG)/gpr_useful_test
 grpc_auth_context_test: $(BINDIR)/$(CONFIG)/grpc_auth_context_test
-grpc_base64_test: $(BINDIR)/$(CONFIG)/grpc_base64_test
+grpc_b64_test: $(BINDIR)/$(CONFIG)/grpc_b64_test
 grpc_byte_buffer_reader_test: $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test
 grpc_channel_args_test: $(BINDIR)/$(CONFIG)/grpc_channel_args_test
 grpc_channel_stack_test: $(BINDIR)/$(CONFIG)/grpc_channel_stack_test
@@ -892,6 +908,7 @@ lame_client_test: $(BINDIR)/$(CONFIG)/lame_client_test
 lb_policies_test: $(BINDIR)/$(CONFIG)/lb_policies_test
 low_level_ping_pong_benchmark: $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark
 message_compress_test: $(BINDIR)/$(CONFIG)/message_compress_test
+mlog_test: $(BINDIR)/$(CONFIG)/mlog_test
 multiple_server_queues_test: $(BINDIR)/$(CONFIG)/multiple_server_queues_test
 murmur_hash_test: $(BINDIR)/$(CONFIG)/murmur_hash_test
 no_server_test: $(BINDIR)/$(CONFIG)/no_server_test
@@ -941,6 +958,7 @@ grpc_csharp_plugin: $(BINDIR)/$(CONFIG)/grpc_csharp_plugin
 grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin
 grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin
 grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
+grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test
 hybrid_end2end_test: $(BINDIR)/$(CONFIG)/hybrid_end2end_test
 interop_client: $(BINDIR)/$(CONFIG)/interop_client
 interop_server: $(BINDIR)/$(CONFIG)/interop_server
@@ -1135,7 +1153,6 @@ buildtests_c: privatelibs_c \
   $(BINDIR)/$(CONFIG)/alpn_test \
   $(BINDIR)/$(CONFIG)/bin_encoder_test \
   $(BINDIR)/$(CONFIG)/census_context_test \
-  $(BINDIR)/$(CONFIG)/census_log_test \
   $(BINDIR)/$(CONFIG)/channel_create_test \
   $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \
   $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test \
@@ -1155,9 +1172,9 @@ buildtests_c: privatelibs_c \
   $(BINDIR)/$(CONFIG)/gpr_cmdline_test \
   $(BINDIR)/$(CONFIG)/gpr_cpu_test \
   $(BINDIR)/$(CONFIG)/gpr_env_test \
-  $(BINDIR)/$(CONFIG)/gpr_file_test \
   $(BINDIR)/$(CONFIG)/gpr_histogram_test \
   $(BINDIR)/$(CONFIG)/gpr_host_port_test \
+  $(BINDIR)/$(CONFIG)/gpr_load_file_test \
   $(BINDIR)/$(CONFIG)/gpr_log_test \
   $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test \
   $(BINDIR)/$(CONFIG)/gpr_slice_test \
@@ -1169,7 +1186,7 @@ buildtests_c: privatelibs_c \
   $(BINDIR)/$(CONFIG)/gpr_tls_test \
   $(BINDIR)/$(CONFIG)/gpr_useful_test \
   $(BINDIR)/$(CONFIG)/grpc_auth_context_test \
-  $(BINDIR)/$(CONFIG)/grpc_base64_test \
+  $(BINDIR)/$(CONFIG)/grpc_b64_test \
   $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test \
   $(BINDIR)/$(CONFIG)/grpc_channel_args_test \
   $(BINDIR)/$(CONFIG)/grpc_channel_stack_test \
@@ -1194,6 +1211,7 @@ buildtests_c: privatelibs_c \
   $(BINDIR)/$(CONFIG)/lame_client_test \
   $(BINDIR)/$(CONFIG)/lb_policies_test \
   $(BINDIR)/$(CONFIG)/message_compress_test \
+  $(BINDIR)/$(CONFIG)/mlog_test \
   $(BINDIR)/$(CONFIG)/multiple_server_queues_test \
   $(BINDIR)/$(CONFIG)/murmur_hash_test \
   $(BINDIR)/$(CONFIG)/no_server_test \
@@ -1285,6 +1303,7 @@ buildtests_cxx: buildtests_zookeeper privatelibs_cxx \
   $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test \
   $(BINDIR)/$(CONFIG)/generic_end2end_test \
   $(BINDIR)/$(CONFIG)/grpc_cli \
+  $(BINDIR)/$(CONFIG)/grpclb_api_test \
   $(BINDIR)/$(CONFIG)/hybrid_end2end_test \
   $(BINDIR)/$(CONFIG)/interop_client \
   $(BINDIR)/$(CONFIG)/interop_server \
@@ -1371,8 +1390,6 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 )
 	$(E) "[RUN]     Testing census_context_test"
 	$(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 )
-	$(E) "[RUN]     Testing census_log_test"
-	$(Q) $(BINDIR)/$(CONFIG)/census_log_test || ( echo test census_log_test failed ; exit 1 )
 	$(E) "[RUN]     Testing channel_create_test"
 	$(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 )
 	$(E) "[RUN]     Testing chttp2_hpack_encoder_test"
@@ -1407,12 +1424,12 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_cpu_test || ( echo test gpr_cpu_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_env_test"
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_env_test || ( echo test gpr_env_test failed ; exit 1 )
-	$(E) "[RUN]     Testing gpr_file_test"
-	$(Q) $(BINDIR)/$(CONFIG)/gpr_file_test || ( echo test gpr_file_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_histogram_test"
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_histogram_test || ( echo test gpr_histogram_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_host_port_test"
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_host_port_test || ( echo test gpr_host_port_test failed ; exit 1 )
+	$(E) "[RUN]     Testing gpr_load_file_test"
+	$(Q) $(BINDIR)/$(CONFIG)/gpr_load_file_test || ( echo test gpr_load_file_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_log_test"
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_log_test || ( echo test gpr_log_test failed ; exit 1 )
 	$(E) "[RUN]     Testing gpr_slice_buffer_test"
@@ -1435,8 +1452,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/gpr_useful_test || ( echo test gpr_useful_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpc_auth_context_test"
 	$(Q) $(BINDIR)/$(CONFIG)/grpc_auth_context_test || ( echo test grpc_auth_context_test failed ; exit 1 )
-	$(E) "[RUN]     Testing grpc_base64_test"
-	$(Q) $(BINDIR)/$(CONFIG)/grpc_base64_test || ( echo test grpc_base64_test failed ; exit 1 )
+	$(E) "[RUN]     Testing grpc_b64_test"
+	$(Q) $(BINDIR)/$(CONFIG)/grpc_b64_test || ( echo test grpc_b64_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpc_byte_buffer_reader_test"
 	$(Q) $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test || ( echo test grpc_byte_buffer_reader_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpc_channel_args_test"
@@ -1483,6 +1500,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/lb_policies_test || ( echo test lb_policies_test failed ; exit 1 )
 	$(E) "[RUN]     Testing message_compress_test"
 	$(Q) $(BINDIR)/$(CONFIG)/message_compress_test || ( echo test message_compress_test failed ; exit 1 )
+	$(E) "[RUN]     Testing mlog_test"
+	$(Q) $(BINDIR)/$(CONFIG)/mlog_test || ( echo test mlog_test failed ; exit 1 )
 	$(E) "[RUN]     Testing multiple_server_queues_test"
 	$(Q) $(BINDIR)/$(CONFIG)/multiple_server_queues_test || ( echo test multiple_server_queues_test failed ; exit 1 )
 	$(E) "[RUN]     Testing murmur_hash_test"
@@ -1595,6 +1614,8 @@ test_cxx: test_zookeeper buildtests_cxx
 	$(Q) $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test || ( echo test generic_async_streaming_ping_pong_test failed ; exit 1 )
 	$(E) "[RUN]     Testing generic_end2end_test"
 	$(Q) $(BINDIR)/$(CONFIG)/generic_end2end_test || ( echo test generic_end2end_test failed ; exit 1 )
+	$(E) "[RUN]     Testing grpclb_api_test"
+	$(Q) $(BINDIR)/$(CONFIG)/grpclb_api_test || ( echo test grpclb_api_test failed ; exit 1 )
 	$(E) "[RUN]     Testing hybrid_end2end_test"
 	$(Q) $(BINDIR)/$(CONFIG)/hybrid_end2end_test || ( echo test hybrid_end2end_test failed ; exit 1 )
 	$(E) "[RUN]     Testing interop_test"
@@ -1746,6 +1767,21 @@ $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc:
 	$(Q) mkdir -p $(@D)
 	$(Q) echo "$(GRPCXX_UNSECURE_PC_FILE)" | tr , '\n' >$@
 
+ifeq ($(NO_PROTOC),true)
+$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc: protoc_dep_error
+$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc: protoc_dep_error
+else
+$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc: src/proto/grpc/lb/v0/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+	$(E) "[PROTOC]  Generating protobuf CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
+
+$(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v0/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) 
+	$(E) "[GRPC]    Generating gRPC's protobuf service CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
+endif
+
 ifeq ($(NO_PROTOC),true)
 $(GENDIR)/src/proto/grpc/testing/control.pb.cc: protoc_dep_error
 $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc: protoc_dep_error
@@ -2180,11 +2216,9 @@ LIBGPR_SRC = \
     src/core/support/env_linux.c \
     src/core/support/env_posix.c \
     src/core/support/env_win32.c \
-    src/core/support/file.c \
-    src/core/support/file_posix.c \
-    src/core/support/file_win32.c \
     src/core/support/histogram.c \
     src/core/support/host_port.c \
+    src/core/support/load_file.c \
     src/core/support/log.c \
     src/core/support/log_android.c \
     src/core/support/log_linux.c \
@@ -2210,6 +2244,8 @@ LIBGPR_SRC = \
     src/core/support/time_precise.c \
     src/core/support/time_win32.c \
     src/core/support/tls_pthread.c \
+    src/core/support/tmpfile_posix.c \
+    src/core/support/tmpfile_win32.c \
     src/core/support/wrap_memcpy.c \
 
 PUBLIC_HEADERS_C += \
@@ -2333,6 +2369,7 @@ LIBGRPC_SRC = \
     src/core/client_config/connector.c \
     src/core/client_config/default_initial_connect_string.c \
     src/core/client_config/initial_connect_string.c \
+    src/core/client_config/lb_policies/load_balancer_api.c \
     src/core/client_config/lb_policies/pick_first.c \
     src/core/client_config/lb_policies/round_robin.c \
     src/core/client_config/lb_policy.c \
@@ -2347,7 +2384,7 @@ LIBGRPC_SRC = \
     src/core/client_config/subchannel_factory.c \
     src/core/client_config/subchannel_index.c \
     src/core/client_config/uri_parser.c \
-    src/core/compression/algorithm.c \
+    src/core/compression/compression_algorithm.c \
     src/core/compression/message_compress.c \
     src/core/debug/trace.c \
     src/core/httpcli/format_request.c \
@@ -2397,6 +2434,7 @@ LIBGRPC_SRC = \
     src/core/json/json_reader.c \
     src/core/json/json_string.c \
     src/core/json/json_writer.c \
+    src/core/proto/grpc/lb/v0/load_balancer.pb.c \
     src/core/surface/alarm.c \
     src/core/surface/api_trace.c \
     src/core/surface/byte_buffer.c \
@@ -2447,7 +2485,7 @@ LIBGRPC_SRC = \
     src/core/transport/transport.c \
     src/core/transport/transport_op_string.c \
     src/core/httpcli/httpcli_security_connector.c \
-    src/core/security/base64.c \
+    src/core/security/b64.c \
     src/core/security/client_auth_filter.c \
     src/core/security/credentials.c \
     src/core/security/credentials_metadata.c \
@@ -2473,6 +2511,9 @@ LIBGRPC_SRC = \
     src/core/census/operation.c \
     src/core/census/placeholders.c \
     src/core/census/tracing.c \
+    third_party/nanopb/pb_common.c \
+    third_party/nanopb/pb_decode.c \
+    third_party/nanopb/pb_encode.c \
 
 PUBLIC_HEADERS_C += \
     include/grpc/grpc_security.h \
@@ -2640,6 +2681,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/client_config/connector.c \
     src/core/client_config/default_initial_connect_string.c \
     src/core/client_config/initial_connect_string.c \
+    src/core/client_config/lb_policies/load_balancer_api.c \
     src/core/client_config/lb_policies/pick_first.c \
     src/core/client_config/lb_policies/round_robin.c \
     src/core/client_config/lb_policy.c \
@@ -2654,7 +2696,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/client_config/subchannel_factory.c \
     src/core/client_config/subchannel_index.c \
     src/core/client_config/uri_parser.c \
-    src/core/compression/algorithm.c \
+    src/core/compression/compression_algorithm.c \
     src/core/compression/message_compress.c \
     src/core/debug/trace.c \
     src/core/httpcli/format_request.c \
@@ -2704,6 +2746,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/json/json_reader.c \
     src/core/json/json_string.c \
     src/core/json/json_writer.c \
+    src/core/proto/grpc/lb/v0/load_balancer.pb.c \
     src/core/surface/alarm.c \
     src/core/surface/api_trace.c \
     src/core/surface/byte_buffer.c \
@@ -2759,6 +2802,9 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/census/operation.c \
     src/core/census/placeholders.c \
     src/core/census/tracing.c \
+    third_party/nanopb/pb_common.c \
+    third_party/nanopb/pb_decode.c \
+    third_party/nanopb/pb_encode.c \
 
 PUBLIC_HEADERS_C += \
     include/grpc/byte_buffer.h \
@@ -2944,7 +2990,6 @@ LIBGRPC++_SRC = \
     src/cpp/client/credentials.cc \
     src/cpp/client/generic_stub.cc \
     src/cpp/client/insecure_credentials.cc \
-    src/cpp/common/alarm.cc \
     src/cpp/common/call.cc \
     src/cpp/common/channel_arguments.cc \
     src/cpp/common/completion_queue.cc \
@@ -3225,7 +3270,6 @@ LIBGRPC++_UNSECURE_SRC = \
     src/cpp/client/credentials.cc \
     src/cpp/client/generic_stub.cc \
     src/cpp/client/insecure_credentials.cc \
-    src/cpp/common/alarm.cc \
     src/cpp/common/call.cc \
     src/cpp/common/channel_arguments.cc \
     src/cpp/common/completion_queue.cc \
@@ -3618,7 +3662,7 @@ LIBINTEROP_SERVER_MAIN_SRC = \
     $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \
-    test/cpp/interop/server.cc \
+    test/cpp/interop/server_main.cc \
 
 
 LIBINTEROP_SERVER_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_SERVER_MAIN_SRC))))
@@ -3663,7 +3707,7 @@ ifneq ($(NO_DEPS),true)
 -include $(LIBINTEROP_SERVER_MAIN_OBJS:.o=.dep)
 endif
 endif
-$(OBJDIR)/$(CONFIG)/test/cpp/interop/server.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/interop/server_main.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc
 
 
 LIBQPS_SRC = \
@@ -3682,7 +3726,7 @@ LIBQPS_SRC = \
     test/cpp/qps/report.cc \
     test/cpp/qps/server_async.cc \
     test/cpp/qps/server_sync.cc \
-    test/cpp/qps/timer.cc \
+    test/cpp/qps/usage_timer.cc \
     test/cpp/util/benchmark_config.cc \
 
 
@@ -3737,7 +3781,7 @@ $(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_worker.o: $(GENDIR)/src/proto/grpc/testing/
 $(OBJDIR)/$(CONFIG)/test/cpp/qps/report.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc
 $(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc
 $(OBJDIR)/$(CONFIG)/test/cpp/qps/server_sync.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/timer.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/usage_timer.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc
 $(OBJDIR)/$(CONFIG)/test/cpp/util/benchmark_config.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.pb.cc $(GENDIR)/src/proto/grpc/testing/perf_db.grpc.pb.cc
 
 
@@ -5433,7 +5477,7 @@ endif
 
 
 LIBBAD_SSL_TEST_SERVER_SRC = \
-    test/core/bad_ssl/server.c \
+    test/core/bad_ssl/server_common.c \
 
 
 LIBBAD_SSL_TEST_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBBAD_SSL_TEST_SERVER_SRC))))
@@ -5481,9 +5525,8 @@ LIBEND2END_TESTS_SRC = \
     test/core/end2end/tests/cancel_before_invoke.c \
     test/core/end2end/tests/cancel_in_a_vacuum.c \
     test/core/end2end/tests/cancel_with_status.c \
-    test/core/end2end/tests/channel_connectivity.c \
-    test/core/end2end/tests/channel_ping.c \
     test/core/end2end/tests/compressed_payload.c \
+    test/core/end2end/tests/connectivity.c \
     test/core/end2end/tests/default_host.c \
     test/core/end2end/tests/disappearing_server.c \
     test/core/end2end/tests/empty_batch.c \
@@ -5494,10 +5537,10 @@ LIBEND2END_TESTS_SRC = \
     test/core/end2end/tests/large_metadata.c \
     test/core/end2end/tests/max_concurrent_streams.c \
     test/core/end2end/tests/max_message_length.c \
-    test/core/end2end/tests/metadata.c \
     test/core/end2end/tests/negative_deadline.c \
     test/core/end2end/tests/no_op.c \
     test/core/end2end/tests/payload.c \
+    test/core/end2end/tests/ping.c \
     test/core/end2end/tests/ping_pong_streaming.c \
     test/core/end2end/tests/registered_call.c \
     test/core/end2end/tests/request_with_flags.c \
@@ -5506,6 +5549,7 @@ LIBEND2END_TESTS_SRC = \
     test/core/end2end/tests/shutdown_finishes_calls.c \
     test/core/end2end/tests/shutdown_finishes_tags.c \
     test/core/end2end/tests/simple_delayed_request.c \
+    test/core/end2end/tests/simple_metadata.c \
     test/core/end2end/tests/simple_request.c \
     test/core/end2end/tests/trailing_metadata.c \
 
@@ -5554,9 +5598,8 @@ LIBEND2END_NOSEC_TESTS_SRC = \
     test/core/end2end/tests/cancel_before_invoke.c \
     test/core/end2end/tests/cancel_in_a_vacuum.c \
     test/core/end2end/tests/cancel_with_status.c \
-    test/core/end2end/tests/channel_connectivity.c \
-    test/core/end2end/tests/channel_ping.c \
     test/core/end2end/tests/compressed_payload.c \
+    test/core/end2end/tests/connectivity.c \
     test/core/end2end/tests/default_host.c \
     test/core/end2end/tests/disappearing_server.c \
     test/core/end2end/tests/empty_batch.c \
@@ -5567,10 +5610,10 @@ LIBEND2END_NOSEC_TESTS_SRC = \
     test/core/end2end/tests/large_metadata.c \
     test/core/end2end/tests/max_concurrent_streams.c \
     test/core/end2end/tests/max_message_length.c \
-    test/core/end2end/tests/metadata.c \
     test/core/end2end/tests/negative_deadline.c \
     test/core/end2end/tests/no_op.c \
     test/core/end2end/tests/payload.c \
+    test/core/end2end/tests/ping.c \
     test/core/end2end/tests/ping_pong_streaming.c \
     test/core/end2end/tests/registered_call.c \
     test/core/end2end/tests/request_with_flags.c \
@@ -5579,6 +5622,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \
     test/core/end2end/tests/shutdown_finishes_calls.c \
     test/core/end2end/tests/shutdown_finishes_tags.c \
     test/core/end2end/tests/simple_delayed_request.c \
+    test/core/end2end/tests/simple_metadata.c \
     test/core/end2end/tests/simple_request.c \
     test/core/end2end/tests/trailing_metadata.c \
 
@@ -5839,38 +5883,6 @@ endif
 endif
 
 
-CENSUS_LOG_TEST_SRC = \
-    test/core/census/mlog_test.c \
-
-CENSUS_LOG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_LOG_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/census_log_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/census_log_test: $(CENSUS_LOG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(CENSUS_LOG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_log_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/census/mlog_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_census_log_test: $(CENSUS_LOG_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(CENSUS_LOG_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 CHANNEL_CREATE_TEST_SRC = \
     test/core/surface/channel_create_test.c \
 
@@ -6543,98 +6555,98 @@ endif
 endif
 
 
-GPR_FILE_TEST_SRC = \
-    test/core/support/file_test.c \
+GPR_HISTOGRAM_TEST_SRC = \
+    test/core/support/histogram_test.c \
 
-GPR_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_FILE_TEST_SRC))))
+GPR_HISTOGRAM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_HISTOGRAM_TEST_SRC))))
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
 
-$(BINDIR)/$(CONFIG)/gpr_file_test: openssl_dep_error
+$(BINDIR)/$(CONFIG)/gpr_histogram_test: openssl_dep_error
 
 else
 
 
 
-$(BINDIR)/$(CONFIG)/gpr_file_test: $(GPR_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/gpr_histogram_test: $(GPR_HISTOGRAM_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(GPR_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_file_test
+	$(Q) $(LD) $(LDFLAGS) $(GPR_HISTOGRAM_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_histogram_test
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/support/file_test.o:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/core/support/histogram_test.o:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-deps_gpr_file_test: $(GPR_FILE_TEST_OBJS:.o=.dep)
+deps_gpr_histogram_test: $(GPR_HISTOGRAM_TEST_OBJS:.o=.dep)
 
 ifneq ($(NO_SECURE),true)
 ifneq ($(NO_DEPS),true)
--include $(GPR_FILE_TEST_OBJS:.o=.dep)
+-include $(GPR_HISTOGRAM_TEST_OBJS:.o=.dep)
 endif
 endif
 
 
-GPR_HISTOGRAM_TEST_SRC = \
-    test/core/support/histogram_test.c \
+GPR_HOST_PORT_TEST_SRC = \
+    test/core/support/host_port_test.c \
 
-GPR_HISTOGRAM_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_HISTOGRAM_TEST_SRC))))
+GPR_HOST_PORT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_HOST_PORT_TEST_SRC))))
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
 
-$(BINDIR)/$(CONFIG)/gpr_histogram_test: openssl_dep_error
+$(BINDIR)/$(CONFIG)/gpr_host_port_test: openssl_dep_error
 
 else
 
 
 
-$(BINDIR)/$(CONFIG)/gpr_histogram_test: $(GPR_HISTOGRAM_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/gpr_host_port_test: $(GPR_HOST_PORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(GPR_HISTOGRAM_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_histogram_test
+	$(Q) $(LD) $(LDFLAGS) $(GPR_HOST_PORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_host_port_test
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/support/histogram_test.o:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/core/support/host_port_test.o:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-deps_gpr_histogram_test: $(GPR_HISTOGRAM_TEST_OBJS:.o=.dep)
+deps_gpr_host_port_test: $(GPR_HOST_PORT_TEST_OBJS:.o=.dep)
 
 ifneq ($(NO_SECURE),true)
 ifneq ($(NO_DEPS),true)
--include $(GPR_HISTOGRAM_TEST_OBJS:.o=.dep)
+-include $(GPR_HOST_PORT_TEST_OBJS:.o=.dep)
 endif
 endif
 
 
-GPR_HOST_PORT_TEST_SRC = \
-    test/core/support/host_port_test.c \
+GPR_LOAD_FILE_TEST_SRC = \
+    test/core/support/load_file_test.c \
 
-GPR_HOST_PORT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_HOST_PORT_TEST_SRC))))
+GPR_LOAD_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_LOAD_FILE_TEST_SRC))))
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
 
-$(BINDIR)/$(CONFIG)/gpr_host_port_test: openssl_dep_error
+$(BINDIR)/$(CONFIG)/gpr_load_file_test: openssl_dep_error
 
 else
 
 
 
-$(BINDIR)/$(CONFIG)/gpr_host_port_test: $(GPR_HOST_PORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/gpr_load_file_test: $(GPR_LOAD_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(GPR_HOST_PORT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_host_port_test
+	$(Q) $(LD) $(LDFLAGS) $(GPR_LOAD_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_load_file_test
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/support/host_port_test.o:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/core/support/load_file_test.o:  $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-deps_gpr_host_port_test: $(GPR_HOST_PORT_TEST_OBJS:.o=.dep)
+deps_gpr_load_file_test: $(GPR_LOAD_FILE_TEST_OBJS:.o=.dep)
 
 ifneq ($(NO_SECURE),true)
 ifneq ($(NO_DEPS),true)
--include $(GPR_HOST_PORT_TEST_OBJS:.o=.dep)
+-include $(GPR_LOAD_FILE_TEST_OBJS:.o=.dep)
 endif
 endif
 
@@ -6991,34 +7003,34 @@ endif
 endif
 
 
-GRPC_BASE64_TEST_SRC = \
-    test/core/security/base64_test.c \
+GRPC_B64_TEST_SRC = \
+    test/core/security/b64_test.c \
 
-GRPC_BASE64_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_BASE64_TEST_SRC))))
+GRPC_B64_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_B64_TEST_SRC))))
 ifeq ($(NO_SECURE),true)
 
 # You can't build secure targets if you don't have OpenSSL.
 
-$(BINDIR)/$(CONFIG)/grpc_base64_test: openssl_dep_error
+$(BINDIR)/$(CONFIG)/grpc_b64_test: openssl_dep_error
 
 else
 
 
 
-$(BINDIR)/$(CONFIG)/grpc_base64_test: $(GRPC_BASE64_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/grpc_b64_test: $(GRPC_B64_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(GRPC_BASE64_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_base64_test
+	$(Q) $(LD) $(LDFLAGS) $(GRPC_B64_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_b64_test
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/core/security/base64_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/core/security/b64_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-deps_grpc_base64_test: $(GRPC_BASE64_TEST_OBJS:.o=.dep)
+deps_grpc_b64_test: $(GRPC_B64_TEST_OBJS:.o=.dep)
 
 ifneq ($(NO_SECURE),true)
 ifneq ($(NO_DEPS),true)
--include $(GRPC_BASE64_TEST_OBJS:.o=.dep)
+-include $(GRPC_B64_TEST_OBJS:.o=.dep)
 endif
 endif
 
@@ -7951,6 +7963,38 @@ endif
 endif
 
 
+MLOG_TEST_SRC = \
+    test/core/census/mlog_test.c \
+
+MLOG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MLOG_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/mlog_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/mlog_test: $(MLOG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(MLOG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/mlog_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/census/mlog_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_mlog_test: $(MLOG_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(MLOG_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 MULTIPLE_SERVER_QUEUES_TEST_SRC = \
     test/core/end2end/multiple_server_queues_test.c \
 
@@ -9712,6 +9756,53 @@ ifneq ($(NO_DEPS),true)
 endif
 
 
+GRPCLB_API_TEST_SRC = \
+    $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc \
+    test/cpp/grpclb/grpclb_api_test.cc \
+
+GRPCLB_API_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPCLB_API_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/grpclb_api_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/grpclb_api_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/grpclb_api_test: $(PROTOBUF_DEP) $(GRPCLB_API_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(GRPCLB_API_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpclb_api_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v0/load_balancer.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a
+
+$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a
+
+deps_grpclb_api_test: $(GRPCLB_API_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GRPCLB_API_TEST_OBJS:.o=.dep)
+endif
+endif
+$(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc
+
+
 HYBRID_END2END_TEST_SRC = \
     test/cpp/end2end/hybrid_end2end_test.cc \
 
@@ -12957,7 +13048,7 @@ ifneq ($(OPENSSL_DEP),)
 # installing headers to their final destination on the drive. We need this
 # otherwise parallel compilation will fail if a source is compiled first.
 src/core/httpcli/httpcli_security_connector.c: $(OPENSSL_DEP)
-src/core/security/base64.c: $(OPENSSL_DEP)
+src/core/security/b64.c: $(OPENSSL_DEP)
 src/core/security/client_auth_filter.c: $(OPENSSL_DEP)
 src/core/security/credentials.c: $(OPENSSL_DEP)
 src/core/security/credentials_metadata.c: $(OPENSSL_DEP)
@@ -12985,7 +13076,7 @@ src/cpp/common/secure_create_auth_context.cc: $(OPENSSL_DEP)
 src/cpp/server/secure_server_credentials.cc: $(OPENSSL_DEP)
 src/csharp/ext/grpc_csharp_ext.c: $(OPENSSL_DEP)
 test/core/bad_client/bad_client.c: $(OPENSSL_DEP)
-test/core/bad_ssl/server.c: $(OPENSSL_DEP)
+test/core/bad_ssl/server_common.c: $(OPENSSL_DEP)
 test/core/end2end/data/server1_cert.c: $(OPENSSL_DEP)
 test/core/end2end/data/server1_key.c: $(OPENSSL_DEP)
 test/core/end2end/data/test_root_cert.c: $(OPENSSL_DEP)
@@ -12998,8 +13089,8 @@ test/cpp/end2end/test_service_impl.cc: $(OPENSSL_DEP)
 test/cpp/interop/client.cc: $(OPENSSL_DEP)
 test/cpp/interop/client_helper.cc: $(OPENSSL_DEP)
 test/cpp/interop/interop_client.cc: $(OPENSSL_DEP)
-test/cpp/interop/server.cc: $(OPENSSL_DEP)
 test/cpp/interop/server_helper.cc: $(OPENSSL_DEP)
+test/cpp/interop/server_main.cc: $(OPENSSL_DEP)
 test/cpp/qps/client_async.cc: $(OPENSSL_DEP)
 test/cpp/qps/client_sync.cc: $(OPENSSL_DEP)
 test/cpp/qps/driver.cc: $(OPENSSL_DEP)
@@ -13009,7 +13100,7 @@ test/cpp/qps/qps_worker.cc: $(OPENSSL_DEP)
 test/cpp/qps/report.cc: $(OPENSSL_DEP)
 test/cpp/qps/server_async.cc: $(OPENSSL_DEP)
 test/cpp/qps/server_sync.cc: $(OPENSSL_DEP)
-test/cpp/qps/timer.cc: $(OPENSSL_DEP)
+test/cpp/qps/usage_timer.cc: $(OPENSSL_DEP)
 test/cpp/util/benchmark_config.cc: $(OPENSSL_DEP)
 test/cpp/util/byte_buffer_proto_helper.cc: $(OPENSSL_DEP)
 test/cpp/util/cli_call.cc: $(OPENSSL_DEP)
@@ -13021,3 +13112,7 @@ test/cpp/util/test_credentials_provider.cc: $(OPENSSL_DEP)
 endif
 
 .PHONY: all strip tools dep_error openssl_dep_error openssl_dep_message git_update stop buildtests buildtests_c buildtests_cxx test test_c test_cxx install install_c install_cxx install-headers install-headers_c install-headers_cxx install-shared install-shared_c install-shared_cxx install-static install-static_c install-static_cxx strip strip-shared strip-static strip_c strip-shared_c strip-static_c strip_cxx strip-shared_cxx strip-static_cxx dep_c dep_cxx bins_dep_c bins_dep_cxx clean
+
+.PHONY: printvars
+printvars:
+	@$(foreach V,$(sort $(.VARIABLES)),                 	  $(if $(filter-out environment% default automatic, 	  $(origin $V)),$(warning $V=$($V) ($(value $V)))))
diff --git a/binding.gyp b/binding.gyp
index 0f5817e8dc2fa97bffa18a70f315106dc936247f..d1e086cfa088771fca325ffed80fdd7efb43d573 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -504,11 +504,9 @@
         'src/core/support/env_linux.c',
         'src/core/support/env_posix.c',
         'src/core/support/env_win32.c',
-        'src/core/support/file.c',
-        'src/core/support/file_posix.c',
-        'src/core/support/file_win32.c',
         'src/core/support/histogram.c',
         'src/core/support/host_port.c',
+        'src/core/support/load_file.c',
         'src/core/support/log.c',
         'src/core/support/log_android.c',
         'src/core/support/log_linux.c',
@@ -534,6 +532,8 @@
         'src/core/support/time_precise.c',
         'src/core/support/time_win32.c',
         'src/core/support/tls_pthread.c',
+        'src/core/support/tmpfile_posix.c',
+        'src/core/support/tmpfile_win32.c',
         'src/core/support/wrap_memcpy.c',
       ],
       "conditions": [
@@ -572,6 +572,7 @@
         'src/core/client_config/connector.c',
         'src/core/client_config/default_initial_connect_string.c',
         'src/core/client_config/initial_connect_string.c',
+        'src/core/client_config/lb_policies/load_balancer_api.c',
         'src/core/client_config/lb_policies/pick_first.c',
         'src/core/client_config/lb_policies/round_robin.c',
         'src/core/client_config/lb_policy.c',
@@ -586,7 +587,7 @@
         'src/core/client_config/subchannel_factory.c',
         'src/core/client_config/subchannel_index.c',
         'src/core/client_config/uri_parser.c',
-        'src/core/compression/algorithm.c',
+        'src/core/compression/compression_algorithm.c',
         'src/core/compression/message_compress.c',
         'src/core/debug/trace.c',
         'src/core/httpcli/format_request.c',
@@ -636,6 +637,7 @@
         'src/core/json/json_reader.c',
         'src/core/json/json_string.c',
         'src/core/json/json_writer.c',
+        'src/core/proto/grpc/lb/v0/load_balancer.pb.c',
         'src/core/surface/alarm.c',
         'src/core/surface/api_trace.c',
         'src/core/surface/byte_buffer.c',
@@ -686,7 +688,7 @@
         'src/core/transport/transport.c',
         'src/core/transport/transport_op_string.c',
         'src/core/httpcli/httpcli_security_connector.c',
-        'src/core/security/base64.c',
+        'src/core/security/b64.c',
         'src/core/security/client_auth_filter.c',
         'src/core/security/credentials.c',
         'src/core/security/credentials_metadata.c',
@@ -712,6 +714,9 @@
         'src/core/census/operation.c',
         'src/core/census/placeholders.c',
         'src/core/census/tracing.c',
+        'third_party/nanopb/pb_common.c',
+        'third_party/nanopb/pb_decode.c',
+        'third_party/nanopb/pb_encode.c',
       ],
       "conditions": [
         ['OS == "mac"', {
diff --git a/build.yaml b/build.yaml
index 68912fc07eaad9943b8bc4a73f2e3a352ac3f9e6..eaaa62238b142341d7dcad30a92ad502e8d314f4 100644
--- a/build.yaml
+++ b/build.yaml
@@ -57,13 +57,14 @@ filegroups:
   - src/core/profiling/timers.h
   - src/core/support/block_annotate.h
   - src/core/support/env.h
-  - src/core/support/file.h
+  - src/core/support/load_file.h
   - src/core/support/murmur_hash.h
   - src/core/support/stack_lockfree.h
   - src/core/support/string.h
   - src/core/support/string_win32.h
   - src/core/support/thd_internal.h
   - src/core/support/time_precise.h
+  - src/core/support/tmpfile.h
   src:
   - src/core/profiling/basic_timers.c
   - src/core/profiling/stap_timers.c
@@ -77,11 +78,9 @@ filegroups:
   - src/core/support/env_linux.c
   - src/core/support/env_posix.c
   - src/core/support/env_win32.c
-  - src/core/support/file.c
-  - src/core/support/file_posix.c
-  - src/core/support/file_win32.c
   - src/core/support/histogram.c
   - src/core/support/host_port.c
+  - src/core/support/load_file.c
   - src/core/support/log.c
   - src/core/support/log_android.c
   - src/core/support/log_linux.c
@@ -107,6 +106,8 @@ filegroups:
   - src/core/support/time_precise.c
   - src/core/support/time_win32.c
   - src/core/support/tls_pthread.c
+  - src/core/support/tmpfile_posix.c
+  - src/core/support/tmpfile_win32.c
   - src/core/support/wrap_memcpy.c
 - name: gpr_codegen
   public_headers:
@@ -183,7 +184,6 @@ filegroups:
   - src/cpp/client/credentials.cc
   - src/cpp/client/generic_stub.cc
   - src/cpp/client/insecure_credentials.cc
-  - src/cpp/common/alarm.cc
   - src/cpp/common/call.cc
   - src/cpp/common/channel_arguments.cc
   - src/cpp/common/completion_queue.cc
@@ -258,6 +258,7 @@ filegroups:
   - src/core/client_config/client_config.h
   - src/core/client_config/connector.h
   - src/core/client_config/initial_connect_string.h
+  - src/core/client_config/lb_policies/load_balancer_api.h
   - src/core/client_config/lb_policies/pick_first.h
   - src/core/client_config/lb_policies/round_robin.h
   - src/core/client_config/lb_policy.h
@@ -308,7 +309,6 @@ filegroups:
   - src/core/iomgr/time_averaged_stats.h
   - src/core/iomgr/timer.h
   - src/core/iomgr/timer_heap.h
-  - src/core/iomgr/timer_internal.h
   - src/core/iomgr/udp_server.h
   - src/core/iomgr/wakeup_fd_pipe.h
   - src/core/iomgr/wakeup_fd_posix.h
@@ -319,6 +319,7 @@ filegroups:
   - src/core/json/json_common.h
   - src/core/json/json_reader.h
   - src/core/json/json_writer.h
+  - src/core/proto/grpc/lb/v0/load_balancer.pb.h
   - src/core/statistics/census_interface.h
   - src/core/statistics/census_rpc_stats.h
   - src/core/surface/api_trace.h
@@ -374,6 +375,7 @@ filegroups:
   - src/core/client_config/connector.c
   - src/core/client_config/default_initial_connect_string.c
   - src/core/client_config/initial_connect_string.c
+  - src/core/client_config/lb_policies/load_balancer_api.c
   - src/core/client_config/lb_policies/pick_first.c
   - src/core/client_config/lb_policies/round_robin.c
   - src/core/client_config/lb_policy.c
@@ -388,7 +390,7 @@ filegroups:
   - src/core/client_config/subchannel_factory.c
   - src/core/client_config/subchannel_index.c
   - src/core/client_config/uri_parser.c
-  - src/core/compression/algorithm.c
+  - src/core/compression/compression_algorithm.c
   - src/core/compression/message_compress.c
   - src/core/debug/trace.c
   - src/core/httpcli/format_request.c
@@ -438,6 +440,7 @@ filegroups:
   - src/core/json/json_reader.c
   - src/core/json/json_string.c
   - src/core/json/json_writer.c
+  - src/core/proto/grpc/lb/v0/load_balancer.pb.c
   - src/core/surface/alarm.c
   - src/core/surface/api_trace.c
   - src/core/surface/byte_buffer.c
@@ -498,7 +501,7 @@ filegroups:
 - name: grpc_secure
   headers:
   - src/core/security/auth_filters.h
-  - src/core/security/base64.h
+  - src/core/security/b64.h
   - src/core/security/credentials.h
   - src/core/security/handshake.h
   - src/core/security/json_token.h
@@ -513,7 +516,7 @@ filegroups:
   - src/core/tsi/transport_security_interface.h
   src:
   - src/core/httpcli/httpcli_security_connector.c
-  - src/core/security/base64.c
+  - src/core/security/b64.c
   - src/core/security/client_auth_filter.c
   - src/core/security/credentials.c
   - src/core/security/credentials_metadata.c
@@ -551,6 +554,16 @@ filegroups:
   - test/core/util/port_posix.c
   - test/core/util/port_windows.c
   - test/core/util/slice_splitter.c
+- name: nanopb
+  headers:
+  - third_party/nanopb/pb.h
+  - third_party/nanopb/pb_common.h
+  - third_party/nanopb/pb_decode.h
+  - third_party/nanopb/pb_encode.h
+  src:
+  - third_party/nanopb/pb_common.c
+  - third_party/nanopb/pb_decode.c
+  - third_party/nanopb/pb_encode.c
 libs:
 - name: gpr
   build: all
@@ -586,6 +599,7 @@ libs:
   - grpc_base
   - grpc_secure
   - census
+  - nanopb
   secure: true
   vs_packages:
   - grpc.dependencies.openssl
@@ -655,6 +669,7 @@ libs:
   - grpc_base
   - grpc_codegen
   - census
+  - nanopb
   secure: false
   vs_project_guid: '{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}'
 - name: grpc_zookeeper
@@ -801,6 +816,8 @@ libs:
   - gpr_codegen
   secure: false
   vs_project_guid: '{B6E81D84-2ACB-41B8-8781-493A944C7817}'
+  vs_props:
+  - protoc
 - name: interop_client_helper
   build: private
   language: c++
@@ -854,7 +871,7 @@ libs:
   - src/proto/grpc/testing/empty.proto
   - src/proto/grpc/testing/messages.proto
   - src/proto/grpc/testing/test.proto
-  - test/cpp/interop/server.cc
+  - test/cpp/interop/server_main.cc
   deps:
   - interop_server_helper
   - grpc++_test_util
@@ -878,7 +895,7 @@ libs:
   - test/cpp/qps/report.h
   - test/cpp/qps/server.h
   - test/cpp/qps/stats.h
-  - test/cpp/qps/timer.h
+  - test/cpp/qps/usage_timer.h
   - test/cpp/util/benchmark_config.h
   src:
   - src/proto/grpc/testing/messages.proto
@@ -896,7 +913,7 @@ libs:
   - test/cpp/qps/report.cc
   - test/cpp/qps/server_async.cc
   - test/cpp/qps/server_sync.cc
-  - test/cpp/qps/timer.cc
+  - test/cpp/qps/usage_timer.cc
   - test/cpp/util/benchmark_config.cc
   deps:
   - grpc_test_util
@@ -980,16 +997,6 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
-- name: census_log_test
-  build: test
-  language: c
-  src:
-  - test/core/census/mlog_test.c
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr_test_util
-  - gpr
 - name: channel_create_test
   build: test
   language: c
@@ -1211,27 +1218,27 @@ targets:
   deps:
   - gpr_test_util
   - gpr
-- name: gpr_file_test
+- name: gpr_histogram_test
   build: test
   language: c
   src:
-  - test/core/support/file_test.c
+  - test/core/support/histogram_test.c
   deps:
   - gpr_test_util
   - gpr
-- name: gpr_histogram_test
+- name: gpr_host_port_test
   build: test
   language: c
   src:
-  - test/core/support/histogram_test.c
+  - test/core/support/host_port_test.c
   deps:
   - gpr_test_util
   - gpr
-- name: gpr_host_port_test
+- name: gpr_load_file_test
   build: test
   language: c
   src:
-  - test/core/support/host_port_test.c
+  - test/core/support/load_file_test.c
   deps:
   - gpr_test_util
   - gpr
@@ -1328,11 +1335,11 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
-- name: grpc_base64_test
+- name: grpc_b64_test
   build: test
   language: c
   src:
-  - test/core/security/base64_test.c
+  - test/core/security/b64_test.c
   deps:
   - grpc_test_util
   - grpc
@@ -1644,6 +1651,16 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: mlog_test
+  build: test
+  language: c
+  src:
+  - test/core/census/mlog_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: multiple_server_queues_test
   build: test
   language: c
@@ -1936,6 +1953,7 @@ targets:
   - linux
   - posix
 - name: alarm_cpp_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -1948,6 +1966,7 @@ targets:
   - gpr_test_util
   - gpr
 - name: async_end2end_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -1994,6 +2013,7 @@ targets:
   - linux
   - posix
 - name: auth_property_iterator_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2006,6 +2026,7 @@ targets:
   - gpr_test_util
   - gpr
 - name: channel_arguments_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2015,6 +2036,7 @@ targets:
   - grpc
   - gpr
 - name: cli_call_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2027,6 +2049,7 @@ targets:
   - gpr_test_util
   - gpr
 - name: client_crash_test
+  gtest: true
   cpu_cost: 0.1
   build: test
   language: c++
@@ -2057,6 +2080,7 @@ targets:
   - gpr_test_util
   - gpr
 - name: credentials_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2066,6 +2090,7 @@ targets:
   - grpc
   - gpr
 - name: cxx_byte_buffer_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2077,6 +2102,7 @@ targets:
   - gpr_test_util
   - gpr
 - name: cxx_slice_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2088,6 +2114,7 @@ targets:
   - gpr_test_util
   - gpr
 - name: cxx_string_ref_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2095,6 +2122,7 @@ targets:
   deps:
   - grpc++
 - name: cxx_time_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2106,6 +2134,7 @@ targets:
   - gpr_test_util
   - gpr
 - name: end2end_test
+  gtest: true
   cpu_cost: 0.5
   build: test
   language: c++
@@ -2136,6 +2165,7 @@ targets:
   - linux
   - posix
 - name: generic_end2end_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2211,7 +2241,20 @@ targets:
   secure: false
   vs_config_type: Application
   vs_project_guid: '{069E9D05-B78B-4751-9252-D21EBAE7DE8E}'
+- name: grpclb_api_test
+  gtest: true
+  build: test
+  language: c++
+  src:
+  - src/proto/grpc/lb/v0/load_balancer.proto
+  - test/cpp/grpclb/grpclb_api_test.cc
+  deps:
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
 - name: hybrid_end2end_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2291,6 +2334,7 @@ targets:
   - gpr
   - grpc++_test_config
 - name: mock_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2335,6 +2379,7 @@ targets:
   - linux
   - posix
 - name: qps_openloop_test
+  cpu_cost: 10
   build: test
   language: c++
   src:
@@ -2367,8 +2412,6 @@ targets:
   - gpr_test_util
   - gpr
   - grpc++_test_config
-  exclude_configs:
-  - tsan
   platforms:
   - mac
   - linux
@@ -2427,6 +2470,7 @@ targets:
   - gpr
   - grpc++_test_config
 - name: secure_auth_context_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2456,6 +2500,7 @@ targets:
   - linux
   - posix
 - name: server_crash_test
+  gtest: true
   cpu_cost: 0.1
   build: test
   language: c++
@@ -2486,6 +2531,7 @@ targets:
   - gpr_test_util
   - gpr
 - name: shutdown_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2509,6 +2555,7 @@ targets:
   - gpr_test_util
   - gpr
 - name: streaming_throughput_test
+  gtest: true
   build: test
   language: c++
   src:
@@ -2585,6 +2632,7 @@ targets:
   - linux
   - posix
 - name: thread_stress_test
+  gtest: true
   cpu_cost: 100
   build: test
   language: c++
@@ -2598,6 +2646,7 @@ targets:
   - gpr_test_util
   - gpr
 - name: zookeeper_test
+  gtest: true
   build: test
   run: false
   language: c++
@@ -2656,7 +2705,7 @@ configs:
     test_environ:
       ASAN_OPTIONS: detect_leaks=1:color=always
       LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
-    timeout_multiplier: 1.5
+    timeout_multiplier: 3
   asan-noleaks:
     CC: clang
     CPPFLAGS: -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument
@@ -2668,7 +2717,7 @@ configs:
     compile_the_world: true
     test_environ:
       ASAN_OPTIONS: detect_leaks=0:color=always
-    timeout_multiplier: 1.5
+    timeout_multiplier: 3
   basicprof:
     CPPFLAGS: -O2 -DGRPC_BASIC_PROFILER -DGRPC_TIMERS_RDTSC
     DEFINES: NDEBUG
@@ -2707,7 +2756,7 @@ configs:
       -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
     LDXX: clang++
     compile_the_world: true
-    timeout_multiplier: 2
+    timeout_multiplier: 4
   mutrace:
     CPPFLAGS: -O0
     DEFINES: _DEBUG DEBUG
@@ -2729,7 +2778,7 @@ configs:
     compile_the_world: true
     test_environ:
       TSAN_OPTIONS: suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
-    timeout_multiplier: 2
+    timeout_multiplier: 5
   ubsan:
     CC: clang
     CPPFLAGS: -O1 -fsanitize=undefined -fno-omit-frame-pointer -Wno-unused-command-line-argument
@@ -2788,6 +2837,10 @@ node_modules:
   - src/node/ext/server.cc
   - src/node/ext/server_credentials.cc
   - src/node/ext/timeval.cc
+openssl_fallback:
+  base_uri: http://openssl.org/source/
+  extraction_dir: openssl-1.0.2f
+  tarball: openssl-1.0.2f.tar.gz
 php_config_m4:
   deps:
   - grpc
diff --git a/config.m4 b/config.m4
index ab614d19ae5a8de69204f908d68404ca035062b5..8ab45e66037497824c90d62a0447412b525d17fb 100644
--- a/config.m4
+++ b/config.m4
@@ -48,11 +48,9 @@ if test "$PHP_GRPC" != "no"; then
     src/core/support/env_linux.c \
     src/core/support/env_posix.c \
     src/core/support/env_win32.c \
-    src/core/support/file.c \
-    src/core/support/file_posix.c \
-    src/core/support/file_win32.c \
     src/core/support/histogram.c \
     src/core/support/host_port.c \
+    src/core/support/load_file.c \
     src/core/support/log.c \
     src/core/support/log_android.c \
     src/core/support/log_linux.c \
@@ -78,6 +76,8 @@ if test "$PHP_GRPC" != "no"; then
     src/core/support/time_precise.c \
     src/core/support/time_win32.c \
     src/core/support/tls_pthread.c \
+    src/core/support/tmpfile_posix.c \
+    src/core/support/tmpfile_win32.c \
     src/core/support/wrap_memcpy.c \
     src/core/census/grpc_context.c \
     src/core/census/grpc_filter.c \
@@ -94,6 +94,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/client_config/connector.c \
     src/core/client_config/default_initial_connect_string.c \
     src/core/client_config/initial_connect_string.c \
+    src/core/client_config/lb_policies/load_balancer_api.c \
     src/core/client_config/lb_policies/pick_first.c \
     src/core/client_config/lb_policies/round_robin.c \
     src/core/client_config/lb_policy.c \
@@ -108,7 +109,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/client_config/subchannel_factory.c \
     src/core/client_config/subchannel_index.c \
     src/core/client_config/uri_parser.c \
-    src/core/compression/algorithm.c \
+    src/core/compression/compression_algorithm.c \
     src/core/compression/message_compress.c \
     src/core/debug/trace.c \
     src/core/httpcli/format_request.c \
@@ -158,6 +159,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/json/json_reader.c \
     src/core/json/json_string.c \
     src/core/json/json_writer.c \
+    src/core/proto/grpc/lb/v0/load_balancer.pb.c \
     src/core/surface/alarm.c \
     src/core/surface/api_trace.c \
     src/core/surface/byte_buffer.c \
@@ -208,7 +210,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/transport/transport.c \
     src/core/transport/transport_op_string.c \
     src/core/httpcli/httpcli_security_connector.c \
-    src/core/security/base64.c \
+    src/core/security/b64.c \
     src/core/security/client_auth_filter.c \
     src/core/security/credentials.c \
     src/core/security/credentials_metadata.c \
@@ -234,6 +236,9 @@ if test "$PHP_GRPC" != "no"; then
     src/core/census/operation.c \
     src/core/census/placeholders.c \
     src/core/census/tracing.c \
+    third_party/nanopb/pb_common.c \
+    third_party/nanopb/pb_decode.c \
+    third_party/nanopb/pb_encode.c \
     src/boringssl/err_data.c \
     third_party/boringssl/crypto/aes/aes.c \
     third_party/boringssl/crypto/aes/mode_wrappers.c \
@@ -547,6 +552,7 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/iomgr)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/json)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/profiling)
+  PHP_ADD_BUILD_DIR($ext_builddir/src/core/proto/grpc/lb/v0)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/security)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/support)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/surface)
@@ -596,4 +602,5 @@ if test "$PHP_GRPC" != "no"; then
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/x509v3)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/ssl)
   PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/ssl/pqueue)
+  PHP_ADD_BUILD_DIR($ext_builddir/third_party/nanopb)
 fi
diff --git a/doc/health-checking.md b/doc/health-checking.md
index 0b3f9c6a034c43e45859086b5a39d3acb12ab370..92512e942bd90f7d03bd1f3e6db4f48795f0a959 100644
--- a/doc/health-checking.md
+++ b/doc/health-checking.md
@@ -26,7 +26,7 @@ The server should export a service defined in the following proto:
 ```
 syntax = "proto3";
 
-package grpc.health.v1alpha;
+package grpc.health.v1;
 
 message HealthCheckRequest {
   string service = 1;
@@ -49,7 +49,7 @@ service Health {
 A client can query the server’s health status by calling the `Check` method, and
 a deadline should be set on the rpc. The client can optionally set the service
 name it wants to query for health status. The suggested format of service name
-is `package_names.ServiceName`, such as `grpc.health.v1alpha.Health`.
+is `package_names.ServiceName`, such as `grpc.health.v1.Health`.
 
 The server should register all the services manually and set
 the individual status, including an empty service name and its status. For each
diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md
index e618e967ee059c9aa88ad0f2d126354cc8d2a2e7..3beb1d11f4a8f2a28164376dadc704ada27f3030 100644
--- a/doc/interop-test-descriptions.md
+++ b/doc/interop-test-descriptions.md
@@ -2,9 +2,8 @@ Interoperability Test Case Descriptions
 =======================================
 
 Client and server use
-[test.proto](https://github.com/grpc/grpc/blob/master/test/proto/test.proto)
-and the [gRPC over HTTP/2 v2
-protocol](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md).
+[test.proto](../src/proto/grpc/testing/test.proto)
+and the [gRPC over HTTP/2 v2 protocol](./PROTOCOL-HTTP2.md).
 
 Client
 ------
diff --git a/examples/README.md b/examples/README.md
index 84ec80057e1620eb295503aba2977c5ec073b26b..287a80266c92d5de832d3fed34341110882e2468 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,450 +1,27 @@
+# Examples
 
-# Getting started
+This directory contains code examples for all the C-based gRPC implementations: C++, Node.js, Python, Ruby, Objective-C, PHP, and C#. You can find examples and instructions specific to your
+favourite language in the relevant subdirectory.
+
+Examples for Go and Java gRPC live in their own repositories:
 
-Welcome to the developer documentation for gRPC, a language-neutral,
-platform-neutral remote procedure call (RPC) system developed at Google.
+* [Java](https://github.com/grpc/grpc-java/tree/master/examples)
+* [Android Java](https://github.com/grpc/grpc-java/tree/master/examples/android)
+* [Go](https://github.com/grpc/grpc-go/tree/master/examples)
 
-This document introduces you to gRPC with a quick overview and a simple
-Hello World example. You'll find more tutorials and reference docs in this repository - more documentation is coming soon!
+For more comprehensive documentation, including an [overview](http://www.grpc.io/docs/) and tutorials that use this example code, visit [grpc.io](http://www.grpc.io/docs/).
 
-<a name="quickstart"></a>
 ## Quick start
-You can find quick start guides for each language, including installation instructions, examples, and tutorials here:
+
+Each example directory has quick start instructions for the appropriate language, including installation instructions and how to run our simplest Hello World example:
+
 * [C++](cpp)
-* [Java](https://github.com/grpc/grpc-java/tree/master/examples)
-* [Go](https://github.com/grpc/grpc-go/tree/master/examples)
 * [Ruby](ruby)
 * [Node.js](node)
-* [Android Java](https://github.com/grpc/grpc-java/tree/master/examples/android)
 * [Python](python/helloworld)
 * [C#](csharp)
 * [Objective-C](objective-c/helloworld)
 * [PHP](php)
 
-## What's in this repository?
-
-The `examples` directory contains documentation, resources, and examples
-for all gRPC users. You can find examples and instructions specific to your
-favourite language in the relevant subdirectory.
-
-You can find out about the gRPC source code repositories in
-[`grpc`](https://github.com/grpc/grpc). Each repository provides instructions
-for building the appropriate libraries for your language.
-
-
-## What is gRPC?
-
-In gRPC a *client* application can directly call
-methods on a *server* application on a different machine as if it was a
-local object, making it easier for you to create distributed applications and
-services. As in many RPC systems, gRPC is based around the idea of defining
-a *service*, specifying the methods that can be called remotely with their
-parameters and return types. On the server side, the server implements this
-interface and runs a gRPC server to handle client calls. On the client side,
-the client has a *stub* that provides exactly the same methods as the server.
-
-<!--TODO: diagram-->
-
-gRPC clients and servers can run and talk to each other in a variety of
-environments - from servers inside Google to your own desktop - and can
-be written in any of gRPC's [supported languages](#quickstart). So, for
-example, you can easily create a gRPC server in Java with clients in Go,
-Python, or Ruby. In addition, the latest Google APIs will have gRPC versions
-of their interfaces, letting you easily build Google functionality into
-your applications.
-
-<a name="protocolbuffers"></a>
-### Working with protocol buffers
-
-By default gRPC uses *protocol buffers*, Google’s
-mature open source mechanism for serializing structured data (although it
-can be used with other data formats such as JSON). As you'll
-see in our example below, you define gRPC services using *proto files*,
-with method parameters and return types specified as protocol buffer message
-types. You
-can find out lots more about protocol buffers in the [Protocol Buffers
-documentation](https://developers.google.com/protocol-buffers/docs/overview).
-
-#### Protocol buffer versions
-
-While protocol buffers have been available for open source users for some
-time, our examples use a new flavour of protocol buffers called proto3,
-which has a slightly simplified syntax, some useful new features, and supports
-lots more languages. This is currently available as an alpha release in
-Java, C++, Java_nano (Android Java), Python, and Ruby from [the protocol buffers Github
-repo](https://github.com/google/protobuf/releases), as well as a Go language
-generator from [the golang/protobuf Github repo](https://github.com/golang/protobuf), with more languages in development. You can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3), and see
-the major differences from the current default version in the [release notes](https://github.com/google/protobuf/releases). More proto3 documentation is coming soon.
-
-In general, while you *can* use proto2 (the current default protocol buffers version), we recommend that you use proto3 with gRPC as it lets you use the full range of gRPC-supported languages, as well as avoiding compatibility
-issues with proto2 clients talking to proto3 servers and vice versa.
-
-<a name="hello"></a>
-## Hello gRPC!
-
-Now that you know a bit more about gRPC, the easiest way to see how it
-works is to look at a simple example. Our Hello World walks you through the
-construction of a simple gRPC client-server application, showing you how to:
-
-- Create a protocol buffers schema that defines a simple RPC service with
-a single
-Hello World method.
-- Create a Java server that implements this interface.
-- Create a Java client that accesses the Java server.
-- Create a Go client that accesses
-the same Java server.
-
-The complete code for the example is available in the `examples`
-directory. We use the Git versioning system for source code management:
-however, you don't need to know anything about Git to follow along other
-than how to install and run a few git commands.
-
-This is an introductory example rather than a comprehensive tutorial, so
-don't worry if you're not a Go or
-Java developer - the concepts are similar for all languages, and you can
-find more implementations of our Hello World example in other languages (and full tutorials where available) in
-the [language-specific folders](#quickstart) in this repository. Complete tutorials and
-reference documentation for all gRPC languages are coming soon.
-
-<a name="setup"></a>
-### Setup
-
-This section explains how to set up your local machine to work with
-the example code. If you just want to read the example, you can go straight
-to the [next step](#servicedef).
-
-#### Install Git
-
-You can download and install Git from http://git-scm.com/download. Once
-installed you should have access to the git command line tool. The main
-commands that you will need to use are:
-
-- git clone ... : clone a remote repository onto your local machine
-- git checkout ... : check out a particular branch or a tagged version of
-the code to hack on
-
-#### Install gRPC
-
-To build and install gRPC plugins and related tools:
-- For Java, see the [Java quick start](https://github.com/grpc/grpc-java).
-- For Go, see the [Go quick start](https://github.com/grpc/grpc-go).
-
-#### Get the source code
-
-The example code for our Java example lives in the `grpc-java`
-GitHub repository. Clone this repository to your local machine by running the
-following command:
-
-
-```
-git clone https://github.com/grpc/grpc-java.git
-```
-
-Change your current directory to grpc-java/examples
-
-```
-cd grpc-java/examples
-```
-
-
-
-<a name="servicedef"></a>
-### Defining a service
-
-The first step in creating our example is to define a *service*: an RPC
-service specifies the methods that can be called remotely with their parameters
-and return types. As you saw in the
-[overview](#protocolbuffers) above, gRPC does this using [protocol
-buffers](https://developers.google.com/protocol-buffers/docs/overview). We
-use the protocol buffers interface definition language (IDL) to define our
-service methods, and define the parameters and return
-types as protocol buffer message types. Both the client and the
-server use interface code generated from the service definition.
-
-Here's our example service definition, defined using protocol buffers IDL in
-[helloworld.proto](https://github.com/grpc/grpc-java/tree/master/examples/src/main/proto). The `Greeter`
-service has one method, `SayHello`, that lets the server receive a single
-`HelloRequest`
-message from the remote client containing the user's name, then send back
-a greeting in a single `HelloReply`. This is the simplest type of RPC you
-can specify in gRPC - you can find out about other types in the tutorial for your chosen language.
-
-```proto
-syntax = "proto3";
-
-option java_package = "io.grpc.examples";
-
-package helloworld;
-
-// The greeter service definition.
-service Greeter {
-  // Sends a greeting
-  rpc SayHello (HelloRequest) returns (HelloReply) {}
-}
-
-// The request message containing the user's name.
-message HelloRequest {
-  string name = 1;
-}
-
-// The response message containing the greetings
-message HelloReply {
-  string message = 1;
-}
-
-```
-
-<a name="generating"></a>
-### Generating gRPC code
-
-Once we've defined our service, we use the protocol buffer compiler
-`protoc` to generate the special client and server code we need to create
-our application - right now we're going to generate Java code, though you
-can generate gRPC code in any gRPC-supported language (as you'll see later
-in this example). The generated code contains both stub code for clients to
-use and an abstract interface for servers to implement, both with the method
-defined in our `Greeter` service.
-
-(If you didn't install the gRPC plugins and protoc on your system and are just reading along with
-the example, you can skip this step and move
-onto the next one where we examine the generated code.)
-
-For simplicity, we've provided a [Gradle build file](https://github.com/grpc/grpc-java/blob/master/examples/build.gradle) with our Java examples that runs `protoc` for you with the appropriate plugin, input, and output:
-
-```shell
-../gradlew build
-```
-
-This generates the following classes from our .proto, which contain all the generated code
-we need to create our example:
-
-- `Helloworld.java`, which
-has all the protocol buffer code to populate, serialize, and retrieve our
-`HelloRequest` and `HelloReply` message types
-- `GreeterGrpc.java`, which contains (along with some other useful code):
-    - an interface for `Greeter` servers to implement
-
-    ```java
-  public static interface Greeter {
-      public void sayHello(io.grpc.examples.Helloworld.HelloRequest request,
-          io.grpc.stub.StreamObserver<io.grpc.examples.Helloworld.HelloReply> responseObserver);
-  }
-    ```
-
-    - _stub_ classes that clients can use to talk to a `Greeter` server. As you can see, they also implement the `Greeter` interface.
-
-  ```java
-  public static class GreeterStub extends
-      io.grpc.stub.AbstractStub<GreeterStub, GreeterServiceDescriptor>
-      implements Greeter {
-   ...
-  }
-  ```
-
-<a name="server"></a>
-### Writing a server
-
-Now let's write some code! First we'll create a server application to implement
-our service. Note that we're not going to go into a lot of detail about how
-to create a server in this section. More detailed information will be in the
-tutorial for your chosen language: check if there's one available yet in the relevant [quick start](#quickstart).
-
-Our server application has two classes:
-
-- a main server class that hosts the service implementation and allows access over the
-network: [HelloWorldServer.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java).
-
-
-- a simple service implementation class [GreeterImpl.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java#L51).
-
-
-#### Service implementation
-
-[GreeterImpl.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java#L51)
-actually implements our `Greeter` service's required behaviour.
-
-As you can see, the class `GreeterImpl` implements the interface
-`GreeterGrpc.Greeter` that we [generated](#generating) from our proto
-[IDL](https://github.com/grpc/grpc-java/tree/master/examples/src/main/proto) by implementing the method `sayHello`:
-
-```java
-    @Override
-    public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
-      HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
-      responseObserver.onValue(reply);
-      responseObserver.onCompleted();
-    }
-```
-- `sayHello` takes two parameters:
-    - `HelloRequest`: the request
-    - `StreamObserver<HelloReply>`: a response observer, which is
-    a special interface for the server to call with its response
-
-To return our response to the client and complete the call:
-
-1. We construct and populate a `HelloReply` response object with our exciting
-message, as specified in our interface definition.
-2. We return the `HelloReply` to the client and then specify that we've finished dealing with the RPC.
-
-
-#### Server implementation
-
-[HelloWorldServer.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java)
-shows the other main feature required to provide a gRPC service; making the service
-implementation available from the network.
-
-```java
-  /* The port on which the server should run */
-  private int port = 50051;
-  private ServerImpl server;
-
-  private void start() throws Exception {
-    server = NettyServerBuilder.forPort(port)
-        .addService(GreeterGrpc.bindService(new GreeterImpl()))
-        .build().start();
-    logger.info("Server started, listening on " + port);
-    Runtime.getRuntime().addShutdownHook(new Thread() {
-      @Override
-      public void run() {
-        // Use stderr here since the logger may have been reset by its JVM shutdown hook.
-        System.err.println("*** shutting down gRPC server since JVM is shutting down");
-        HelloWorldServer.this.stop();
-        System.err.println("*** server shut down");
-      }
-    });
-  }
-
-```
-
-Here we create an appropriate gRPC server, binding the `Greeter` service
-implementation that we created to a port. Then we start the server running: the server is now ready to receive
-requests from `Greeter` service clients on our specified port. We'll cover
-how all this works in a bit more detail in our language-specific documentation.
-
-<a name="client"></a>
-### Writing a client
-
-Client-side gRPC is pretty simple. In this step, we'll use the generated code
-to write a simple client that can access the `Greeter` server we created
-in the [previous section](#server). You can see the complete client code in
-[HelloWorldClient.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java).
-
-Again, we're not going to go into much detail about how to implement a client;
-we'll leave that for the tutorial.
-
-#### Connecting to the service
-
-First let's look at how we connect to the `Greeter` server. First we need
-to create a gRPC channel, specifying the hostname and port of the server we
-want to connect to. Then we use the channel to construct the stub instance.
-
-
-```java
-  private final ChannelImpl channel;
-  private final GreeterGrpc.GreeterBlockingStub blockingStub;
-
-  public HelloWorldClient(String host, int port) {
-    channel =
-        NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT)
-            .build();
-    blockingStub = GreeterGrpc.newBlockingStub(channel);
-  }
-
-```
-
-In this case, we create a blocking stub. This means that the RPC call waits
-for the server to respond, and will either return a response or raise an
-exception. gRPC Java has other kinds of stubs that make non-blocking calls
-to the server, where the response is returned asynchronously.
-
-#### Calling an RPC
-
-Now we can contact the service and obtain a greeting:
-
-1. We construct and fill in a `HelloRequest` to send to the service.
-2. We call the stub's `hello()` RPC with our request and get a `HelloReply`
-back, from which we can get our greeting.
-
-
-```java
-    HelloRequest req = HelloRequest.newBuilder().setName(name).build();
-    HelloReply reply = blockingStub.sayHello(req);
-
-```
-
-<a name="run"></a>
-### Try it out!
-
-Our [Gradle build file](https://github.com/grpc/grpc-java/blob/master/examples/build.gradle) simplifies building and running the examples.
-
-You can build and run the server from the `grpc-java` root folder with:
-
-```sh
-$ ./gradlew :grpc-examples:helloWorldServer
-```
-
-and in another terminal window confirm that it receives a message.
-
-```sh
-$  ./gradlew :grpc-examples:helloWorldClient
-```
-
-### Adding another client
-
-Finally, let's look at one of gRPC's most useful features - interoperability
-between code in different languages. So far, we've just looked at Java code
-generated from and implementing our `Greeter` service definition. However,
-as you'll see if you look at the language-specific subdirectories
-in this repository, we've also generated and implemented `Greeter`
-in some of gRPC's other supported languages. Each service
-and client uses interface code generated from the same proto
-that we used for the Java example.
-
-So, for example, if we visit the [`go` example
-directory](https://github.com/grpc/grpc-go/tree/master/examples) and look at the
-[`greeter_client`](https://github.com/grpc/grpc-go/blob/master/examples/greeter_client/main.go),
-we can see that like the Java client, it connects to a `Greeter` service
-at `localhost:50051` and uses a stub to call the `SayHello` method with a
-`HelloRequest`:
-
-```go
-const (
-	address = "localhost:50051"
-	defaultName = "world"
-)
-
-func main() {
-	// Set up a connection to the server.
-	conn, err := grpc.Dial(address)
-	if err != nil {
-		log.Fatalf("did not connect: %v", err)
-	}
-	defer conn.Close()
-	c := pb.NewGreeterClient(conn)
-
-	// Contact the server and print out its response.
-	name := defaultName
-	if len(os.Args) > 1 {
-		name = os.Args[1]
-	}
-	r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name:
-	name})
-	if err != nil {
-		log.Fatalf("could not greet: %v", err)
-	}
-	log.Printf("Greeting: %s", r.Message)
-}
-```
-
-
-If we run the Java server from earlier in another terminal window, we can
-run the Go client and connect to it just like the Java client, even though
-it's written in a different language.
 
-```
-$ greeter_client
-```
-## Read more!
 
-- You can find links to language-specific tutorials, examples, and other docs in each language's [quick start](#quickstart).
-- [gRPC Authentication Support](doc/grpc-auth-support.md) introduces authentication support in gRPC with supported mechanisms and examples.
diff --git a/examples/cpp/README.md b/examples/cpp/README.md
index 979ba55dbb5d1e51f698111e3f3a649f1398cb61..d93cbacf7b276c673f17595e62b64821c22b4236 100644
--- a/examples/cpp/README.md
+++ b/examples/cpp/README.md
@@ -2,7 +2,7 @@
 
 ## Installation
 
-To install gRPC on your system, follow the instructions [here](../../INSTALL.md).
+To install gRPC on your system, follow the instructions to build from source [here](../../INSTALL.md). This also installs the protocol buffer compiler `protoc` (if you don't have it already), and the C++ gRPC plugin for `protoc`.
 
 ## Hello C++ gRPC!
 
@@ -23,21 +23,6 @@ Change your current directory to examples/cpp/helloworld
 $ cd examples/cpp/helloworld/
 ```
 
-
-### Generating gRPC code
-
-To generate the client and server side interfaces:
-
-```sh
-$ make helloworld.grpc.pb.cc helloworld.pb.cc
-```
-Which internally invokes the proto-compiler as:
-
-```sh
-$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto
-$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
-```
-
 ### Client and server implementations
 
 The client implementation is at [greeter_client.cc](helloworld/greeter_client.cc).
diff --git a/examples/node/README.md b/examples/node/README.md
index 7a2bc9794f3a0e6458599d0c067fe538f603fd45..c1ef6b05ab0bd484c3f8b9f42098bf9f4796e163 100644
--- a/examples/node/README.md
+++ b/examples/node/README.md
@@ -20,7 +20,7 @@ TRY IT!
  - Run the server
 
    ```sh
-   $ # from this directory (grpc_common/node).
+   $ # from this directory
    $ node ./greeter_server.js &
    ```
 
diff --git a/examples/php/README.md b/examples/php/README.md
index 8fb060863a3f6077cd99aa3f653752081c80c028..ea9ccb679086a53587f6c9ef908310a8216441e5 100644
--- a/examples/php/README.md
+++ b/examples/php/README.md
@@ -4,16 +4,15 @@ gRPC in 3 minutes (PHP)
 PREREQUISITES
 -------------
 
-This requires PHP 5.5 or greater.
+This requires `php` >=5.5, `phpize`, `pecl`, `phpunit`
 
 INSTALL
 -------
- - On Mac OS X, install [homebrew][]. Run the following command to install gRPC.
+ - Install the gRPC PHP extension
 
    ```sh
-   $ curl -fsSL https://goo.gl/getgrpc | bash -s php
+   $ [sudo] pecl install grpc-beta
    ```
-   This will download and run the [gRPC install script][] and compile the gRPC PHP extension.
 
  - Clone this repository
 
@@ -37,6 +36,7 @@ TRY IT!
    Please follow the instruction in [Node][] to run the server
    ```
    $ cd examples/node
+   $ npm install
    $ nodejs greeter_server.js
    ```
 
@@ -58,7 +58,5 @@ TUTORIAL
 
 You can find a more detailed tutorial in [gRPC Basics: PHP][]
 
-[homebrew]:http://brew.sh
-[gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install
 [Node]:https://github.com/grpc/grpc/tree/master/examples/node
 [gRPC Basics: PHP]:http://www.grpc.io/docs/tutorials/basic/php.html
diff --git a/examples/python/route_guide/route_guide_server.py b/examples/python/route_guide/route_guide_server.py
index f23b98bf3673c191f2641f05e9adcaf7f127e228..f95b36b07366c9378d7730cbdf293be1ffcc6284 100644
--- a/examples/python/route_guide/route_guide_server.py
+++ b/examples/python/route_guide/route_guide_server.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -128,7 +128,7 @@ def serve():
     while True:
       time.sleep(_ONE_DAY_IN_SECONDS)
   except KeyboardInterrupt:
-    server.stop()
+    server.stop(0)
 
 if __name__ == '__main__':
   serve()
diff --git a/gRPC.podspec b/gRPC.podspec
index b40c80a0812579039cd6018bf47b3f634e05bc86..f3103ea79ad90c9ec741ef559630eee6bf6ba2b4 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -66,13 +66,14 @@ Pod::Spec.new do |s|
     ss.source_files = 'src/core/profiling/timers.h',
                       'src/core/support/block_annotate.h',
                       'src/core/support/env.h',
-                      'src/core/support/file.h',
+                      'src/core/support/load_file.h',
                       'src/core/support/murmur_hash.h',
                       'src/core/support/stack_lockfree.h',
                       'src/core/support/string.h',
                       'src/core/support/string_win32.h',
                       'src/core/support/thd_internal.h',
                       'src/core/support/time_precise.h',
+                      'src/core/support/tmpfile.h',
                       'include/grpc/support/alloc.h',
                       'include/grpc/support/atm.h',
                       'include/grpc/support/atm_gcc_atomic.h',
@@ -127,11 +128,9 @@ Pod::Spec.new do |s|
                       'src/core/support/env_linux.c',
                       'src/core/support/env_posix.c',
                       'src/core/support/env_win32.c',
-                      'src/core/support/file.c',
-                      'src/core/support/file_posix.c',
-                      'src/core/support/file_win32.c',
                       'src/core/support/histogram.c',
                       'src/core/support/host_port.c',
+                      'src/core/support/load_file.c',
                       'src/core/support/log.c',
                       'src/core/support/log_android.c',
                       'src/core/support/log_linux.c',
@@ -157,6 +156,8 @@ Pod::Spec.new do |s|
                       'src/core/support/time_precise.c',
                       'src/core/support/time_win32.c',
                       'src/core/support/tls_pthread.c',
+                      'src/core/support/tmpfile_posix.c',
+                      'src/core/support/tmpfile_win32.c',
                       'src/core/support/wrap_memcpy.c',
                       'src/core/census/grpc_filter.h',
                       'src/core/channel/channel_args.h',
@@ -172,6 +173,7 @@ Pod::Spec.new do |s|
                       'src/core/client_config/client_config.h',
                       'src/core/client_config/connector.h',
                       'src/core/client_config/initial_connect_string.h',
+                      'src/core/client_config/lb_policies/load_balancer_api.h',
                       'src/core/client_config/lb_policies/pick_first.h',
                       'src/core/client_config/lb_policies/round_robin.h',
                       'src/core/client_config/lb_policy.h',
@@ -222,7 +224,6 @@ Pod::Spec.new do |s|
                       'src/core/iomgr/time_averaged_stats.h',
                       'src/core/iomgr/timer.h',
                       'src/core/iomgr/timer_heap.h',
-                      'src/core/iomgr/timer_internal.h',
                       'src/core/iomgr/udp_server.h',
                       'src/core/iomgr/wakeup_fd_pipe.h',
                       'src/core/iomgr/wakeup_fd_posix.h',
@@ -233,6 +234,7 @@ Pod::Spec.new do |s|
                       'src/core/json/json_common.h',
                       'src/core/json/json_reader.h',
                       'src/core/json/json_writer.h',
+                      'src/core/proto/grpc/lb/v0/load_balancer.pb.h',
                       'src/core/statistics/census_interface.h',
                       'src/core/statistics/census_rpc_stats.h',
                       'src/core/surface/api_trace.h',
@@ -273,7 +275,7 @@ Pod::Spec.new do |s|
                       'src/core/transport/transport.h',
                       'src/core/transport/transport_impl.h',
                       'src/core/security/auth_filters.h',
-                      'src/core/security/base64.h',
+                      'src/core/security/b64.h',
                       'src/core/security/credentials.h',
                       'src/core/security/handshake.h',
                       'src/core/security/json_token.h',
@@ -289,6 +291,10 @@ Pod::Spec.new do |s|
                       'src/core/census/aggregation.h',
                       'src/core/census/mlog.h',
                       'src/core/census/rpc_metric_id.h',
+                      'third_party/nanopb/pb.h',
+                      'third_party/nanopb/pb_common.h',
+                      'third_party/nanopb/pb_decode.h',
+                      'third_party/nanopb/pb_encode.h',
                       'include/grpc/grpc_security.h',
                       'include/grpc/impl/codegen/byte_buffer.h',
                       'include/grpc/impl/codegen/compression_types.h',
@@ -317,6 +323,7 @@ Pod::Spec.new do |s|
                       'src/core/client_config/connector.c',
                       'src/core/client_config/default_initial_connect_string.c',
                       'src/core/client_config/initial_connect_string.c',
+                      'src/core/client_config/lb_policies/load_balancer_api.c',
                       'src/core/client_config/lb_policies/pick_first.c',
                       'src/core/client_config/lb_policies/round_robin.c',
                       'src/core/client_config/lb_policy.c',
@@ -331,7 +338,7 @@ Pod::Spec.new do |s|
                       'src/core/client_config/subchannel_factory.c',
                       'src/core/client_config/subchannel_index.c',
                       'src/core/client_config/uri_parser.c',
-                      'src/core/compression/algorithm.c',
+                      'src/core/compression/compression_algorithm.c',
                       'src/core/compression/message_compress.c',
                       'src/core/debug/trace.c',
                       'src/core/httpcli/format_request.c',
@@ -381,6 +388,7 @@ Pod::Spec.new do |s|
                       'src/core/json/json_reader.c',
                       'src/core/json/json_string.c',
                       'src/core/json/json_writer.c',
+                      'src/core/proto/grpc/lb/v0/load_balancer.pb.c',
                       'src/core/surface/alarm.c',
                       'src/core/surface/api_trace.c',
                       'src/core/surface/byte_buffer.c',
@@ -431,7 +439,7 @@ Pod::Spec.new do |s|
                       'src/core/transport/transport.c',
                       'src/core/transport/transport_op_string.c',
                       'src/core/httpcli/httpcli_security_connector.c',
-                      'src/core/security/base64.c',
+                      'src/core/security/b64.c',
                       'src/core/security/client_auth_filter.c',
                       'src/core/security/credentials.c',
                       'src/core/security/credentials_metadata.c',
@@ -456,18 +464,22 @@ Pod::Spec.new do |s|
                       'src/core/census/mlog.c',
                       'src/core/census/operation.c',
                       'src/core/census/placeholders.c',
-                      'src/core/census/tracing.c'
+                      'src/core/census/tracing.c',
+                      'third_party/nanopb/pb_common.c',
+                      'third_party/nanopb/pb_decode.c',
+                      'third_party/nanopb/pb_encode.c'
 
     ss.private_header_files = 'src/core/profiling/timers.h',
                               'src/core/support/block_annotate.h',
                               'src/core/support/env.h',
-                              'src/core/support/file.h',
+                              'src/core/support/load_file.h',
                               'src/core/support/murmur_hash.h',
                               'src/core/support/stack_lockfree.h',
                               'src/core/support/string.h',
                               'src/core/support/string_win32.h',
                               'src/core/support/thd_internal.h',
                               'src/core/support/time_precise.h',
+                              'src/core/support/tmpfile.h',
                               'src/core/census/grpc_filter.h',
                               'src/core/channel/channel_args.h',
                               'src/core/channel/channel_stack.h',
@@ -482,6 +494,7 @@ Pod::Spec.new do |s|
                               'src/core/client_config/client_config.h',
                               'src/core/client_config/connector.h',
                               'src/core/client_config/initial_connect_string.h',
+                              'src/core/client_config/lb_policies/load_balancer_api.h',
                               'src/core/client_config/lb_policies/pick_first.h',
                               'src/core/client_config/lb_policies/round_robin.h',
                               'src/core/client_config/lb_policy.h',
@@ -532,7 +545,6 @@ Pod::Spec.new do |s|
                               'src/core/iomgr/time_averaged_stats.h',
                               'src/core/iomgr/timer.h',
                               'src/core/iomgr/timer_heap.h',
-                              'src/core/iomgr/timer_internal.h',
                               'src/core/iomgr/udp_server.h',
                               'src/core/iomgr/wakeup_fd_pipe.h',
                               'src/core/iomgr/wakeup_fd_posix.h',
@@ -543,6 +555,7 @@ Pod::Spec.new do |s|
                               'src/core/json/json_common.h',
                               'src/core/json/json_reader.h',
                               'src/core/json/json_writer.h',
+                              'src/core/proto/grpc/lb/v0/load_balancer.pb.h',
                               'src/core/statistics/census_interface.h',
                               'src/core/statistics/census_rpc_stats.h',
                               'src/core/surface/api_trace.h',
@@ -583,7 +596,7 @@ Pod::Spec.new do |s|
                               'src/core/transport/transport.h',
                               'src/core/transport/transport_impl.h',
                               'src/core/security/auth_filters.h',
-                              'src/core/security/base64.h',
+                              'src/core/security/b64.h',
                               'src/core/security/credentials.h',
                               'src/core/security/handshake.h',
                               'src/core/security/json_token.h',
@@ -598,7 +611,11 @@ Pod::Spec.new do |s|
                               'src/core/tsi/transport_security_interface.h',
                               'src/core/census/aggregation.h',
                               'src/core/census/mlog.h',
-                              'src/core/census/rpc_metric_id.h'
+                              'src/core/census/rpc_metric_id.h',
+                              'third_party/nanopb/pb.h',
+                              'third_party/nanopb/pb_common.h',
+                              'third_party/nanopb/pb_decode.h',
+                              'third_party/nanopb/pb_encode.h'
 
     ss.header_mappings_dir = '.'
     # This isn't officially supported in Cocoapods. We've asked for an alternative:
diff --git a/grpc.def b/grpc.def
index bd0bc85a7c3bcfa21d3013a0d7c347675c9df009..f81aa1b05a6e84ee70aece13dd979058c8128638 100644
--- a/grpc.def
+++ b/grpc.def
@@ -182,6 +182,7 @@ EXPORTS
     gpr_event_wait
     gpr_ref_init
     gpr_ref
+    gpr_ref_non_zero
     gpr_refn
     gpr_unref
     gpr_stats_init
diff --git a/grpc.gemspec b/grpc.gemspec
index ae8cfaf7c905ba3f88e57287076a13688d84f3e4..1b3f15ecf3647e0f2005a028ec8302c531e5707e 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -91,13 +91,14 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/profiling/timers.h )
   s.files += %w( src/core/support/block_annotate.h )
   s.files += %w( src/core/support/env.h )
-  s.files += %w( src/core/support/file.h )
+  s.files += %w( src/core/support/load_file.h )
   s.files += %w( src/core/support/murmur_hash.h )
   s.files += %w( src/core/support/stack_lockfree.h )
   s.files += %w( src/core/support/string.h )
   s.files += %w( src/core/support/string_win32.h )
   s.files += %w( src/core/support/thd_internal.h )
   s.files += %w( src/core/support/time_precise.h )
+  s.files += %w( src/core/support/tmpfile.h )
   s.files += %w( src/core/profiling/basic_timers.c )
   s.files += %w( src/core/profiling/stap_timers.c )
   s.files += %w( src/core/support/alloc.c )
@@ -110,11 +111,9 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/support/env_linux.c )
   s.files += %w( src/core/support/env_posix.c )
   s.files += %w( src/core/support/env_win32.c )
-  s.files += %w( src/core/support/file.c )
-  s.files += %w( src/core/support/file_posix.c )
-  s.files += %w( src/core/support/file_win32.c )
   s.files += %w( src/core/support/histogram.c )
   s.files += %w( src/core/support/host_port.c )
+  s.files += %w( src/core/support/load_file.c )
   s.files += %w( src/core/support/log.c )
   s.files += %w( src/core/support/log_android.c )
   s.files += %w( src/core/support/log_linux.c )
@@ -140,6 +139,8 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/support/time_precise.c )
   s.files += %w( src/core/support/time_win32.c )
   s.files += %w( src/core/support/tls_pthread.c )
+  s.files += %w( src/core/support/tmpfile_posix.c )
+  s.files += %w( src/core/support/tmpfile_win32.c )
   s.files += %w( src/core/support/wrap_memcpy.c )
   s.files += %w( include/grpc/grpc_security.h )
   s.files += %w( include/grpc/impl/codegen/byte_buffer.h )
@@ -168,6 +169,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/client_config/client_config.h )
   s.files += %w( src/core/client_config/connector.h )
   s.files += %w( src/core/client_config/initial_connect_string.h )
+  s.files += %w( src/core/client_config/lb_policies/load_balancer_api.h )
   s.files += %w( src/core/client_config/lb_policies/pick_first.h )
   s.files += %w( src/core/client_config/lb_policies/round_robin.h )
   s.files += %w( src/core/client_config/lb_policy.h )
@@ -218,7 +220,6 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/iomgr/time_averaged_stats.h )
   s.files += %w( src/core/iomgr/timer.h )
   s.files += %w( src/core/iomgr/timer_heap.h )
-  s.files += %w( src/core/iomgr/timer_internal.h )
   s.files += %w( src/core/iomgr/udp_server.h )
   s.files += %w( src/core/iomgr/wakeup_fd_pipe.h )
   s.files += %w( src/core/iomgr/wakeup_fd_posix.h )
@@ -229,6 +230,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/json/json_common.h )
   s.files += %w( src/core/json/json_reader.h )
   s.files += %w( src/core/json/json_writer.h )
+  s.files += %w( src/core/proto/grpc/lb/v0/load_balancer.pb.h )
   s.files += %w( src/core/statistics/census_interface.h )
   s.files += %w( src/core/statistics/census_rpc_stats.h )
   s.files += %w( src/core/surface/api_trace.h )
@@ -269,7 +271,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/transport/transport.h )
   s.files += %w( src/core/transport/transport_impl.h )
   s.files += %w( src/core/security/auth_filters.h )
-  s.files += %w( src/core/security/base64.h )
+  s.files += %w( src/core/security/b64.h )
   s.files += %w( src/core/security/credentials.h )
   s.files += %w( src/core/security/handshake.h )
   s.files += %w( src/core/security/json_token.h )
@@ -285,6 +287,10 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/census/aggregation.h )
   s.files += %w( src/core/census/mlog.h )
   s.files += %w( src/core/census/rpc_metric_id.h )
+  s.files += %w( third_party/nanopb/pb.h )
+  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/census/grpc_context.c )
   s.files += %w( src/core/census/grpc_filter.c )
   s.files += %w( src/core/channel/channel_args.c )
@@ -300,6 +306,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/client_config/connector.c )
   s.files += %w( src/core/client_config/default_initial_connect_string.c )
   s.files += %w( src/core/client_config/initial_connect_string.c )
+  s.files += %w( src/core/client_config/lb_policies/load_balancer_api.c )
   s.files += %w( src/core/client_config/lb_policies/pick_first.c )
   s.files += %w( src/core/client_config/lb_policies/round_robin.c )
   s.files += %w( src/core/client_config/lb_policy.c )
@@ -314,7 +321,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/client_config/subchannel_factory.c )
   s.files += %w( src/core/client_config/subchannel_index.c )
   s.files += %w( src/core/client_config/uri_parser.c )
-  s.files += %w( src/core/compression/algorithm.c )
+  s.files += %w( src/core/compression/compression_algorithm.c )
   s.files += %w( src/core/compression/message_compress.c )
   s.files += %w( src/core/debug/trace.c )
   s.files += %w( src/core/httpcli/format_request.c )
@@ -364,6 +371,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/json/json_reader.c )
   s.files += %w( src/core/json/json_string.c )
   s.files += %w( src/core/json/json_writer.c )
+  s.files += %w( src/core/proto/grpc/lb/v0/load_balancer.pb.c )
   s.files += %w( src/core/surface/alarm.c )
   s.files += %w( src/core/surface/api_trace.c )
   s.files += %w( src/core/surface/byte_buffer.c )
@@ -414,7 +422,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/transport/transport.c )
   s.files += %w( src/core/transport/transport_op_string.c )
   s.files += %w( src/core/httpcli/httpcli_security_connector.c )
-  s.files += %w( src/core/security/base64.c )
+  s.files += %w( src/core/security/b64.c )
   s.files += %w( src/core/security/client_auth_filter.c )
   s.files += %w( src/core/security/credentials.c )
   s.files += %w( src/core/security/credentials_metadata.c )
@@ -440,6 +448,9 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/census/operation.c )
   s.files += %w( src/core/census/placeholders.c )
   s.files += %w( src/core/census/tracing.c )
+  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( third_party/boringssl/crypto/aes/internal.h )
   s.files += %w( third_party/boringssl/crypto/asn1/asn1_locl.h )
   s.files += %w( third_party/boringssl/crypto/bio/internal.h )
diff --git a/include/grpc++/alarm.h b/include/grpc++/alarm.h
index 9979c34e4f13190ea70333af35a80ad5aec2f6e3..3b8104d135700fc45bd8418eaa002f38ddf75fc8 100644
--- a/include/grpc++/alarm.h
+++ b/include/grpc++/alarm.h
@@ -36,9 +36,12 @@
 #ifndef GRPCXX_ALARM_H
 #define GRPCXX_ALARM_H
 
+#include <grpc++/impl/codegen/completion_queue.h>
 #include <grpc++/impl/codegen/completion_queue_tag.h>
 #include <grpc++/impl/codegen/grpc_library.h>
 #include <grpc++/impl/codegen/time.h>
+#include <grpc++/impl/grpc_library.h>
+#include <grpc/grpc.h>
 
 struct grpc_alarm;
 
@@ -54,14 +57,22 @@ class Alarm : private GrpcLibrary {
   /// Once the alarm expires (at \a deadline) or it's cancelled (see \a Cancel),
   /// an event with tag \a tag will be added to \a cq. If the alarm expired, the
   /// event's success bit will be true, false otherwise (ie, upon cancellation).
-  Alarm(CompletionQueue* cq, gpr_timespec deadline, void* tag);
+  /// \internal We rely on the presence of \a cq for grpc initialization. If \a
+  /// cq were ever to be removed, a reference to a static
+  /// internal::GrpcLibraryInitializer instance would need to be introduced
+  /// here. \endinternal.
+  template <typename T>
+  Alarm(CompletionQueue* cq, const T& deadline, void* tag)
+      : tag_(tag),
+        alarm_(grpc_alarm_create(cq->cq(), TimePoint<T>(deadline).raw_time(),
+                                 static_cast<void*>(&tag_))) {}
 
   /// Destroy the given completion queue alarm, cancelling it in the process.
-  ~Alarm();
+  ~Alarm() { grpc_alarm_destroy(alarm_); }
 
   /// Cancel a completion queue alarm. Calling this function over an alarm that
   /// has already fired has no effect.
-  void Cancel();
+  void Cancel() { grpc_alarm_cancel(alarm_); }
 
  private:
   class AlarmEntry : public CompletionQueueTag {
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index 2a71073a7e2f89852e6bc9342417420c702b6228..c177805236b62f50c50cdd31f56494ee5e682132 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -79,6 +79,8 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibrary {
   class GlobalCallbacks {
    public:
     virtual ~GlobalCallbacks() {}
+    /// Called before server is created.
+    virtual void UpdateArguments(ChannelArguments* args) {}
     /// Called before application callback for each synchronous server request
     virtual void PreSynchronousRequest(ServerContext* context) = 0;
     /// Called after application callback for each synchronous server request
@@ -108,7 +110,7 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibrary {
   /// \param max_message_size Maximum message length that the channel can
   /// receive.
   Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
-         int max_message_size, const ChannelArguments& args);
+         int max_message_size, ChannelArguments* args);
 
   /// Register a service. This call does not take ownership of the service.
   /// The service must exist for the lifetime of the Server instance.
@@ -177,7 +179,7 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibrary {
   bool has_generic_service_;
 
   // Pointer to the c grpc server.
-  grpc_server* const server_;
+  grpc_server* server_;
 
   ThreadPoolInterface* thread_pool_;
   // Whether the thread pool is created and owned by the server.
diff --git a/include/grpc/census.h b/include/grpc/census.h
index dfa3bd7e0df70d530f7607a3060865ef46806b42..442a754f0a45f32e09fb7ba25873077c9139b454 100644
--- a/include/grpc/census.h
+++ b/include/grpc/census.h
@@ -80,18 +80,18 @@ CENSUSAPI int census_enabled(void);
   metrics will be recorded. Keys are unique within a context. */
 typedef struct census_context census_context;
 
-/* A tag is a key:value pair. The key is a non-empty, printable (UTF-8
-   encoded), nil-terminated string. The value is a binary string, that may be
-   printable. There are limits on the sizes of both keys and values (see
-   CENSUS_MAX_TAG_KB_LEN definition below), and the number of tags that can be
-   propagated (CENSUS_MAX_PROPAGATED_TAGS). Users should also remember that
-   some systems may have limits on, e.g., the number of bytes that can be
-   transmitted as metadata, and that larger tags means more memory consumed
-   and time in processing. */
+/* A tag is a key:value pair. Both keys and values are nil-terminated strings,
+   containing printable ASCII characters (decimal 32-126). Keys must be at
+   least one character in length. Both keys and values can have at most
+   CENSUS_MAX_TAG_KB_LEN characters (including the terminating nil). The
+   maximum number of tags that can be propagated is
+   CENSUS_MAX_PROPAGATED_TAGS. Users should also remember that some systems
+   may have limits on, e.g., the number of bytes that can be transmitted as
+   metadata, and that larger tags means more memory consumed and time in
+   processing. */
 typedef struct {
   const char *key;
   const char *value;
-  size_t value_len;
   uint8_t flags;
 } census_tag;
 
@@ -103,28 +103,25 @@ typedef struct {
 /* Tag flags. */
 #define CENSUS_TAG_PROPAGATE 1 /* Tag should be propagated over RPC */
 #define CENSUS_TAG_STATS 2     /* Tag will be used for statistics aggregation */
-#define CENSUS_TAG_BINARY 4    /* Tag value is not printable */
-#define CENSUS_TAG_RESERVED 8  /* Reserved for internal use. */
-/* Flag values 8,16,32,64,128 are reserved for future/internal use. Clients
+#define CENSUS_TAG_RESERVED 4  /* Reserved for internal use. */
+/* Flag values 4,8,16,32,64,128 are reserved for future/internal use. Clients
    should not use or rely on their values. */
 
 #define CENSUS_TAG_IS_PROPAGATED(flags) (flags & CENSUS_TAG_PROPAGATE)
 #define CENSUS_TAG_IS_STATS(flags) (flags & CENSUS_TAG_STATS)
-#define CENSUS_TAG_IS_BINARY(flags) (flags & CENSUS_TAG_BINARY)
 
 /* An instance of this structure is kept by every context, and records the
    basic information associated with the creation of that context. */
 typedef struct {
-  int n_propagated_tags;        /* number of propagated printable tags */
-  int n_propagated_binary_tags; /* number of propagated binary tags */
-  int n_local_tags;             /* number of non-propagated (local) tags */
-  int n_deleted_tags;           /* number of tags that were deleted */
-  int n_added_tags;             /* number of tags that were added */
-  int n_modified_tags;          /* number of tags that were modified */
-  int n_invalid_tags;           /* number of tags with bad keys or values (e.g.
-                                   longer than CENSUS_MAX_TAG_KV_LEN) */
-  int n_ignored_tags;           /* number of tags ignored because of
-                                   CENSUS_MAX_PROPAGATED_TAGS limit. */
+  int n_propagated_tags; /* number of propagated tags */
+  int n_local_tags;      /* number of non-propagated (local) tags */
+  int n_deleted_tags;    /* number of tags that were deleted */
+  int n_added_tags;      /* number of tags that were added */
+  int n_modified_tags;   /* number of tags that were modified */
+  int n_invalid_tags;    /* number of tags with bad keys or values (e.g.
+                            longer than CENSUS_MAX_TAG_KV_LEN) */
+  int n_ignored_tags;    /* number of tags ignored because of
+                            CENSUS_MAX_PROPAGATED_TAGS limit. */
 } census_context_status;
 
 /* Create a new context, adding and removing tags from an existing context.
@@ -132,10 +129,10 @@ typedef struct {
    to add as many tags in a single operation as is practical for the client.
    @param base Base context to build upon. Can be NULL.
    @param tags A set of tags to be added/changed/deleted. Tags with keys that
-   are in 'tags', but not 'base', are added to the tag set. Keys that are in
+   are in 'tags', but not 'base', are added to the context. Keys that are in
    both 'tags' and 'base' will have their value/flags modified. Tags with keys
-   in both, but with NULL or zero-length values, will be deleted from the tag
-   set. Tags with invalid (too long or short) keys or values will be ignored.
+   in both, but with NULL values, will be deleted from the context. Tags with
+   invalid (too long or short) keys or values will be ignored.
    If adding a tag will result in more than CENSUS_MAX_PROPAGATED_TAGS in either
    binary or non-binary tags, they will be ignored, as will deletions of
    tags that don't exist.
@@ -185,32 +182,19 @@ CENSUSAPI int census_context_get_tag(const census_context *context,
    for use by RPC systems only, for purposes of transmitting/receiving contexts.
    */
 
-/* Encode a context into a buffer. The propagated tags are encoded into the
-   buffer in two regions: one for printable tags, and one for binary tags.
+/* Encode a context into a buffer.
    @param context context to be encoded
-   @param buffer pointer to buffer. This address will be used to encode the
-                 printable tags.
+   @param buffer buffer into which the context will be encoded.
    @param buf_size number of available bytes in buffer.
-   @param print_buf_size Will be set to the number of bytes consumed by
-                         printable tags.
-   @param bin_buf_size Will be set to the number of bytes used to encode the
-                       binary tags.
-   @return A pointer to the binary tag's encoded, or NULL if the buffer was
-           insufficiently large to hold the encoded tags. Thus, if successful,
-           printable tags are encoded into
-           [buffer, buffer + *print_buf_size) and binary tags into
-           [returned-ptr, returned-ptr + *bin_buf_size) (and the returned
-           pointer should be buffer + *print_buf_size) */
-CENSUSAPI char *census_context_encode(const census_context *context,
-                                      char *buffer, size_t buf_size,
-                                      size_t *print_buf_size,
-                                      size_t *bin_buf_size);
-
-/* Decode context buffers encoded with census_context_encode(). Returns NULL
+   @return The number of buffer bytes consumed for the encoded context, or
+           zero if the buffer was of insufficient size. */
+CENSUSAPI size_t census_context_encode(const census_context *context,
+                                       char *buffer, size_t buf_size);
+
+/* Decode context buffer encoded with census_context_encode(). Returns NULL
    if there is an error in parsing either buffer. */
-CENSUSAPI census_context *census_context_decode(const char *buffer, size_t size,
-                                                const char *bin_buffer,
-                                                size_t bin_size);
+CENSUSAPI census_context *census_context_decode(const char *buffer,
+                                                size_t size);
 
 /* Distributed traces can have a number of options. */
 enum census_trace_mask_values {
diff --git a/include/grpc/impl/codegen/sync.h b/include/grpc/impl/codegen/sync.h
index d2f19d37d66ebcc1ac706b499d38c76c54700421..6fd7d64b299ba46ded0f0ca9d35a817a038050ff 100644
--- a/include/grpc/impl/codegen/sync.h
+++ b/include/grpc/impl/codegen/sync.h
@@ -182,6 +182,10 @@ GPRAPI void gpr_ref_init(gpr_refcount *r, int n);
 /* Increment the reference count *r.  Requires *r initialized. */
 GPRAPI void gpr_ref(gpr_refcount *r);
 
+/* Increment the reference count *r.  Requires *r initialized.
+   Crashes if refcount is zero */
+GPRAPI void gpr_ref_non_zero(gpr_refcount *r);
+
 /* Increment the reference count *r by n.  Requires *r initialized, n > 0. */
 GPRAPI void gpr_refn(gpr_refcount *r, int n);
 
diff --git a/package.json b/package.json
index 3208f20cc7d11be285b07c445d5b0d00b7f6da02..2df2a7fbe30e3100866b1beb088ae82c6d772929 100644
--- a/package.json
+++ b/package.json
@@ -113,6 +113,7 @@
     "src/core/client_config/client_config.h",
     "src/core/client_config/connector.h",
     "src/core/client_config/initial_connect_string.h",
+    "src/core/client_config/lb_policies/load_balancer_api.h",
     "src/core/client_config/lb_policies/pick_first.h",
     "src/core/client_config/lb_policies/round_robin.h",
     "src/core/client_config/lb_policy.h",
@@ -163,7 +164,6 @@
     "src/core/iomgr/time_averaged_stats.h",
     "src/core/iomgr/timer.h",
     "src/core/iomgr/timer_heap.h",
-    "src/core/iomgr/timer_internal.h",
     "src/core/iomgr/udp_server.h",
     "src/core/iomgr/wakeup_fd_pipe.h",
     "src/core/iomgr/wakeup_fd_posix.h",
@@ -174,6 +174,7 @@
     "src/core/json/json_common.h",
     "src/core/json/json_reader.h",
     "src/core/json/json_writer.h",
+    "src/core/proto/grpc/lb/v0/load_balancer.pb.h",
     "src/core/statistics/census_interface.h",
     "src/core/statistics/census_rpc_stats.h",
     "src/core/surface/api_trace.h",
@@ -214,7 +215,7 @@
     "src/core/transport/transport.h",
     "src/core/transport/transport_impl.h",
     "src/core/security/auth_filters.h",
-    "src/core/security/base64.h",
+    "src/core/security/b64.h",
     "src/core/security/credentials.h",
     "src/core/security/handshake.h",
     "src/core/security/json_token.h",
@@ -230,6 +231,10 @@
     "src/core/census/aggregation.h",
     "src/core/census/mlog.h",
     "src/core/census/rpc_metric_id.h",
+    "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/census/grpc_context.c",
     "src/core/census/grpc_filter.c",
     "src/core/channel/channel_args.c",
@@ -245,6 +250,7 @@
     "src/core/client_config/connector.c",
     "src/core/client_config/default_initial_connect_string.c",
     "src/core/client_config/initial_connect_string.c",
+    "src/core/client_config/lb_policies/load_balancer_api.c",
     "src/core/client_config/lb_policies/pick_first.c",
     "src/core/client_config/lb_policies/round_robin.c",
     "src/core/client_config/lb_policy.c",
@@ -259,7 +265,7 @@
     "src/core/client_config/subchannel_factory.c",
     "src/core/client_config/subchannel_index.c",
     "src/core/client_config/uri_parser.c",
-    "src/core/compression/algorithm.c",
+    "src/core/compression/compression_algorithm.c",
     "src/core/compression/message_compress.c",
     "src/core/debug/trace.c",
     "src/core/httpcli/format_request.c",
@@ -309,6 +315,7 @@
     "src/core/json/json_reader.c",
     "src/core/json/json_string.c",
     "src/core/json/json_writer.c",
+    "src/core/proto/grpc/lb/v0/load_balancer.pb.c",
     "src/core/surface/alarm.c",
     "src/core/surface/api_trace.c",
     "src/core/surface/byte_buffer.c",
@@ -359,7 +366,7 @@
     "src/core/transport/transport.c",
     "src/core/transport/transport_op_string.c",
     "src/core/httpcli/httpcli_security_connector.c",
-    "src/core/security/base64.c",
+    "src/core/security/b64.c",
     "src/core/security/client_auth_filter.c",
     "src/core/security/credentials.c",
     "src/core/security/credentials_metadata.c",
@@ -385,6 +392,9 @@
     "src/core/census/operation.c",
     "src/core/census/placeholders.c",
     "src/core/census/tracing.c",
+    "third_party/nanopb/pb_common.c",
+    "third_party/nanopb/pb_decode.c",
+    "third_party/nanopb/pb_encode.c",
     "third_party/zlib/crc32.h",
     "third_party/zlib/deflate.h",
     "third_party/zlib/gzguts.h",
@@ -411,101 +421,6 @@
     "third_party/zlib/trees.c",
     "third_party/zlib/uncompr.c",
     "third_party/zlib/zutil.c",
-    "include/grpc/support/alloc.h",
-    "include/grpc/support/atm.h",
-    "include/grpc/support/atm_gcc_atomic.h",
-    "include/grpc/support/atm_gcc_sync.h",
-    "include/grpc/support/atm_win32.h",
-    "include/grpc/support/avl.h",
-    "include/grpc/support/cmdline.h",
-    "include/grpc/support/cpu.h",
-    "include/grpc/support/histogram.h",
-    "include/grpc/support/host_port.h",
-    "include/grpc/support/log.h",
-    "include/grpc/support/log_win32.h",
-    "include/grpc/support/port_platform.h",
-    "include/grpc/support/slice.h",
-    "include/grpc/support/slice_buffer.h",
-    "include/grpc/support/string_util.h",
-    "include/grpc/support/subprocess.h",
-    "include/grpc/support/sync.h",
-    "include/grpc/support/sync_generic.h",
-    "include/grpc/support/sync_posix.h",
-    "include/grpc/support/sync_win32.h",
-    "include/grpc/support/thd.h",
-    "include/grpc/support/time.h",
-    "include/grpc/support/tls.h",
-    "include/grpc/support/tls_gcc.h",
-    "include/grpc/support/tls_msvc.h",
-    "include/grpc/support/tls_pthread.h",
-    "include/grpc/support/useful.h",
-    "include/grpc/impl/codegen/alloc.h",
-    "include/grpc/impl/codegen/atm.h",
-    "include/grpc/impl/codegen/atm_gcc_atomic.h",
-    "include/grpc/impl/codegen/atm_gcc_sync.h",
-    "include/grpc/impl/codegen/atm_win32.h",
-    "include/grpc/impl/codegen/log.h",
-    "include/grpc/impl/codegen/port_platform.h",
-    "include/grpc/impl/codegen/slice.h",
-    "include/grpc/impl/codegen/slice_buffer.h",
-    "include/grpc/impl/codegen/sync.h",
-    "include/grpc/impl/codegen/sync_generic.h",
-    "include/grpc/impl/codegen/sync_posix.h",
-    "include/grpc/impl/codegen/sync_win32.h",
-    "include/grpc/impl/codegen/time.h",
-    "src/core/profiling/timers.h",
-    "src/core/support/block_annotate.h",
-    "src/core/support/env.h",
-    "src/core/support/file.h",
-    "src/core/support/murmur_hash.h",
-    "src/core/support/stack_lockfree.h",
-    "src/core/support/string.h",
-    "src/core/support/string_win32.h",
-    "src/core/support/thd_internal.h",
-    "src/core/support/time_precise.h",
-    "src/core/profiling/basic_timers.c",
-    "src/core/profiling/stap_timers.c",
-    "src/core/support/alloc.c",
-    "src/core/support/avl.c",
-    "src/core/support/cmdline.c",
-    "src/core/support/cpu_iphone.c",
-    "src/core/support/cpu_linux.c",
-    "src/core/support/cpu_posix.c",
-    "src/core/support/cpu_windows.c",
-    "src/core/support/env_linux.c",
-    "src/core/support/env_posix.c",
-    "src/core/support/env_win32.c",
-    "src/core/support/file.c",
-    "src/core/support/file_posix.c",
-    "src/core/support/file_win32.c",
-    "src/core/support/histogram.c",
-    "src/core/support/host_port.c",
-    "src/core/support/log.c",
-    "src/core/support/log_android.c",
-    "src/core/support/log_linux.c",
-    "src/core/support/log_posix.c",
-    "src/core/support/log_win32.c",
-    "src/core/support/murmur_hash.c",
-    "src/core/support/slice.c",
-    "src/core/support/slice_buffer.c",
-    "src/core/support/stack_lockfree.c",
-    "src/core/support/string.c",
-    "src/core/support/string_posix.c",
-    "src/core/support/string_win32.c",
-    "src/core/support/subprocess_posix.c",
-    "src/core/support/subprocess_windows.c",
-    "src/core/support/sync.c",
-    "src/core/support/sync_posix.c",
-    "src/core/support/sync_win32.c",
-    "src/core/support/thd.c",
-    "src/core/support/thd_posix.c",
-    "src/core/support/thd_win32.c",
-    "src/core/support/time.c",
-    "src/core/support/time_posix.c",
-    "src/core/support/time_precise.c",
-    "src/core/support/time_win32.c",
-    "src/core/support/tls_pthread.c",
-    "src/core/support/wrap_memcpy.c",
     "third_party/boringssl/crypto/aes/internal.h",
     "third_party/boringssl/crypto/asn1/asn1_locl.h",
     "third_party/boringssl/crypto/bio/internal.h",
@@ -907,6 +822,102 @@
     "third_party/boringssl/ssl/t1_enc.c",
     "third_party/boringssl/ssl/t1_lib.c",
     "third_party/boringssl/ssl/tls_record.c",
+    "include/grpc/support/alloc.h",
+    "include/grpc/support/atm.h",
+    "include/grpc/support/atm_gcc_atomic.h",
+    "include/grpc/support/atm_gcc_sync.h",
+    "include/grpc/support/atm_win32.h",
+    "include/grpc/support/avl.h",
+    "include/grpc/support/cmdline.h",
+    "include/grpc/support/cpu.h",
+    "include/grpc/support/histogram.h",
+    "include/grpc/support/host_port.h",
+    "include/grpc/support/log.h",
+    "include/grpc/support/log_win32.h",
+    "include/grpc/support/port_platform.h",
+    "include/grpc/support/slice.h",
+    "include/grpc/support/slice_buffer.h",
+    "include/grpc/support/string_util.h",
+    "include/grpc/support/subprocess.h",
+    "include/grpc/support/sync.h",
+    "include/grpc/support/sync_generic.h",
+    "include/grpc/support/sync_posix.h",
+    "include/grpc/support/sync_win32.h",
+    "include/grpc/support/thd.h",
+    "include/grpc/support/time.h",
+    "include/grpc/support/tls.h",
+    "include/grpc/support/tls_gcc.h",
+    "include/grpc/support/tls_msvc.h",
+    "include/grpc/support/tls_pthread.h",
+    "include/grpc/support/useful.h",
+    "include/grpc/impl/codegen/alloc.h",
+    "include/grpc/impl/codegen/atm.h",
+    "include/grpc/impl/codegen/atm_gcc_atomic.h",
+    "include/grpc/impl/codegen/atm_gcc_sync.h",
+    "include/grpc/impl/codegen/atm_win32.h",
+    "include/grpc/impl/codegen/log.h",
+    "include/grpc/impl/codegen/port_platform.h",
+    "include/grpc/impl/codegen/slice.h",
+    "include/grpc/impl/codegen/slice_buffer.h",
+    "include/grpc/impl/codegen/sync.h",
+    "include/grpc/impl/codegen/sync_generic.h",
+    "include/grpc/impl/codegen/sync_posix.h",
+    "include/grpc/impl/codegen/sync_win32.h",
+    "include/grpc/impl/codegen/time.h",
+    "src/core/profiling/timers.h",
+    "src/core/support/block_annotate.h",
+    "src/core/support/env.h",
+    "src/core/support/load_file.h",
+    "src/core/support/murmur_hash.h",
+    "src/core/support/stack_lockfree.h",
+    "src/core/support/string.h",
+    "src/core/support/string_win32.h",
+    "src/core/support/thd_internal.h",
+    "src/core/support/time_precise.h",
+    "src/core/support/tmpfile.h",
+    "src/core/profiling/basic_timers.c",
+    "src/core/profiling/stap_timers.c",
+    "src/core/support/alloc.c",
+    "src/core/support/avl.c",
+    "src/core/support/cmdline.c",
+    "src/core/support/cpu_iphone.c",
+    "src/core/support/cpu_linux.c",
+    "src/core/support/cpu_posix.c",
+    "src/core/support/cpu_windows.c",
+    "src/core/support/env_linux.c",
+    "src/core/support/env_posix.c",
+    "src/core/support/env_win32.c",
+    "src/core/support/histogram.c",
+    "src/core/support/host_port.c",
+    "src/core/support/load_file.c",
+    "src/core/support/log.c",
+    "src/core/support/log_android.c",
+    "src/core/support/log_linux.c",
+    "src/core/support/log_posix.c",
+    "src/core/support/log_win32.c",
+    "src/core/support/murmur_hash.c",
+    "src/core/support/slice.c",
+    "src/core/support/slice_buffer.c",
+    "src/core/support/stack_lockfree.c",
+    "src/core/support/string.c",
+    "src/core/support/string_posix.c",
+    "src/core/support/string_win32.c",
+    "src/core/support/subprocess_posix.c",
+    "src/core/support/subprocess_windows.c",
+    "src/core/support/sync.c",
+    "src/core/support/sync_posix.c",
+    "src/core/support/sync_win32.c",
+    "src/core/support/thd.c",
+    "src/core/support/thd_posix.c",
+    "src/core/support/thd_win32.c",
+    "src/core/support/time.c",
+    "src/core/support/time_posix.c",
+    "src/core/support/time_precise.c",
+    "src/core/support/time_win32.c",
+    "src/core/support/tls_pthread.c",
+    "src/core/support/tmpfile_posix.c",
+    "src/core/support/tmpfile_win32.c",
+    "src/core/support/wrap_memcpy.c",
     "binding.gyp"
   ],
   "main": "src/node/index.js",
diff --git a/package.xml b/package.xml
index 68d6dfb9402c1e380094adee40edf781fa0cbd57..e65ab73b54abcfd702aeaa87ea669a0a74694833 100644
--- a/package.xml
+++ b/package.xml
@@ -10,11 +10,11 @@
   <email>grpc-packages@google.com</email>
   <active>yes</active>
  </lead>
- <date>2016-02-24</date>
+ <date>2016-03-01</date>
  <time>16:06:07</time>
  <version>
-  <release>0.8.0</release>
-  <api>0.8.0</api>
+  <release>0.14.0</release>
+  <api>0.14.0</api>
  </version>
  <stability>
   <release>beta</release>
@@ -22,8 +22,7 @@
  </stability>
  <license>BSD</license>
  <notes>
-- Simplify gRPC PHP installation #4517
-- Wrap gRPC core library version 0.13
+- Increase unit test code coverage #5225
  </notes>
  <contents>
   <dir baseinstalldir="/" name="/">
@@ -96,13 +95,14 @@
     <file baseinstalldir="/" name="src/core/profiling/timers.h" role="src" />
     <file baseinstalldir="/" name="src/core/support/block_annotate.h" role="src" />
     <file baseinstalldir="/" name="src/core/support/env.h" role="src" />
-    <file baseinstalldir="/" name="src/core/support/file.h" role="src" />
+    <file baseinstalldir="/" name="src/core/support/load_file.h" role="src" />
     <file baseinstalldir="/" name="src/core/support/murmur_hash.h" role="src" />
     <file baseinstalldir="/" name="src/core/support/stack_lockfree.h" role="src" />
     <file baseinstalldir="/" name="src/core/support/string.h" role="src" />
     <file baseinstalldir="/" name="src/core/support/string_win32.h" role="src" />
     <file baseinstalldir="/" name="src/core/support/thd_internal.h" role="src" />
     <file baseinstalldir="/" name="src/core/support/time_precise.h" role="src" />
+    <file baseinstalldir="/" name="src/core/support/tmpfile.h" role="src" />
     <file baseinstalldir="/" name="src/core/profiling/basic_timers.c" role="src" />
     <file baseinstalldir="/" name="src/core/profiling/stap_timers.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/alloc.c" role="src" />
@@ -115,11 +115,9 @@
     <file baseinstalldir="/" name="src/core/support/env_linux.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/env_posix.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/env_win32.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/file.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/file_posix.c" role="src" />
-    <file baseinstalldir="/" name="src/core/support/file_win32.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/histogram.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/host_port.c" role="src" />
+    <file baseinstalldir="/" name="src/core/support/load_file.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/log.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/log_android.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/log_linux.c" role="src" />
@@ -145,6 +143,8 @@
     <file baseinstalldir="/" name="src/core/support/time_precise.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/time_win32.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/tls_pthread.c" role="src" />
+    <file baseinstalldir="/" name="src/core/support/tmpfile_posix.c" role="src" />
+    <file baseinstalldir="/" name="src/core/support/tmpfile_win32.c" role="src" />
     <file baseinstalldir="/" name="src/core/support/wrap_memcpy.c" role="src" />
     <file baseinstalldir="/" name="include/grpc/grpc_security.h" role="src" />
     <file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer.h" role="src" />
@@ -173,6 +173,7 @@
     <file baseinstalldir="/" name="src/core/client_config/client_config.h" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/connector.h" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/initial_connect_string.h" role="src" />
+    <file baseinstalldir="/" name="src/core/client_config/lb_policies/load_balancer_api.h" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/lb_policies/pick_first.h" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/lb_policies/round_robin.h" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/lb_policy.h" role="src" />
@@ -223,7 +224,6 @@
     <file baseinstalldir="/" name="src/core/iomgr/time_averaged_stats.h" role="src" />
     <file baseinstalldir="/" name="src/core/iomgr/timer.h" role="src" />
     <file baseinstalldir="/" name="src/core/iomgr/timer_heap.h" role="src" />
-    <file baseinstalldir="/" name="src/core/iomgr/timer_internal.h" role="src" />
     <file baseinstalldir="/" name="src/core/iomgr/udp_server.h" role="src" />
     <file baseinstalldir="/" name="src/core/iomgr/wakeup_fd_pipe.h" role="src" />
     <file baseinstalldir="/" name="src/core/iomgr/wakeup_fd_posix.h" role="src" />
@@ -234,6 +234,7 @@
     <file baseinstalldir="/" name="src/core/json/json_common.h" role="src" />
     <file baseinstalldir="/" name="src/core/json/json_reader.h" role="src" />
     <file baseinstalldir="/" name="src/core/json/json_writer.h" role="src" />
+    <file baseinstalldir="/" name="src/core/proto/grpc/lb/v0/load_balancer.pb.h" role="src" />
     <file baseinstalldir="/" name="src/core/statistics/census_interface.h" role="src" />
     <file baseinstalldir="/" name="src/core/statistics/census_rpc_stats.h" role="src" />
     <file baseinstalldir="/" name="src/core/surface/api_trace.h" role="src" />
@@ -274,7 +275,7 @@
     <file baseinstalldir="/" name="src/core/transport/transport.h" role="src" />
     <file baseinstalldir="/" name="src/core/transport/transport_impl.h" role="src" />
     <file baseinstalldir="/" name="src/core/security/auth_filters.h" role="src" />
-    <file baseinstalldir="/" name="src/core/security/base64.h" role="src" />
+    <file baseinstalldir="/" name="src/core/security/b64.h" role="src" />
     <file baseinstalldir="/" name="src/core/security/credentials.h" role="src" />
     <file baseinstalldir="/" name="src/core/security/handshake.h" role="src" />
     <file baseinstalldir="/" name="src/core/security/json_token.h" role="src" />
@@ -290,6 +291,10 @@
     <file baseinstalldir="/" name="src/core/census/aggregation.h" role="src" />
     <file baseinstalldir="/" name="src/core/census/mlog.h" role="src" />
     <file baseinstalldir="/" name="src/core/census/rpc_metric_id.h" role="src" />
+    <file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
+    <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/census/grpc_context.c" role="src" />
     <file baseinstalldir="/" name="src/core/census/grpc_filter.c" role="src" />
     <file baseinstalldir="/" name="src/core/channel/channel_args.c" role="src" />
@@ -305,6 +310,7 @@
     <file baseinstalldir="/" name="src/core/client_config/connector.c" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/default_initial_connect_string.c" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/initial_connect_string.c" role="src" />
+    <file baseinstalldir="/" name="src/core/client_config/lb_policies/load_balancer_api.c" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/lb_policies/pick_first.c" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/lb_policies/round_robin.c" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/lb_policy.c" role="src" />
@@ -319,7 +325,7 @@
     <file baseinstalldir="/" name="src/core/client_config/subchannel_factory.c" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/subchannel_index.c" role="src" />
     <file baseinstalldir="/" name="src/core/client_config/uri_parser.c" role="src" />
-    <file baseinstalldir="/" name="src/core/compression/algorithm.c" role="src" />
+    <file baseinstalldir="/" name="src/core/compression/compression_algorithm.c" role="src" />
     <file baseinstalldir="/" name="src/core/compression/message_compress.c" role="src" />
     <file baseinstalldir="/" name="src/core/debug/trace.c" role="src" />
     <file baseinstalldir="/" name="src/core/httpcli/format_request.c" role="src" />
@@ -369,6 +375,7 @@
     <file baseinstalldir="/" name="src/core/json/json_reader.c" role="src" />
     <file baseinstalldir="/" name="src/core/json/json_string.c" role="src" />
     <file baseinstalldir="/" name="src/core/json/json_writer.c" role="src" />
+    <file baseinstalldir="/" name="src/core/proto/grpc/lb/v0/load_balancer.pb.c" role="src" />
     <file baseinstalldir="/" name="src/core/surface/alarm.c" role="src" />
     <file baseinstalldir="/" name="src/core/surface/api_trace.c" role="src" />
     <file baseinstalldir="/" name="src/core/surface/byte_buffer.c" role="src" />
@@ -419,7 +426,7 @@
     <file baseinstalldir="/" name="src/core/transport/transport.c" role="src" />
     <file baseinstalldir="/" name="src/core/transport/transport_op_string.c" role="src" />
     <file baseinstalldir="/" name="src/core/httpcli/httpcli_security_connector.c" role="src" />
-    <file baseinstalldir="/" name="src/core/security/base64.c" role="src" />
+    <file baseinstalldir="/" name="src/core/security/b64.c" role="src" />
     <file baseinstalldir="/" name="src/core/security/client_auth_filter.c" role="src" />
     <file baseinstalldir="/" name="src/core/security/credentials.c" role="src" />
     <file baseinstalldir="/" name="src/core/security/credentials_metadata.c" role="src" />
@@ -445,6 +452,9 @@
     <file baseinstalldir="/" name="src/core/census/operation.c" role="src" />
     <file baseinstalldir="/" name="src/core/census/placeholders.c" role="src" />
     <file baseinstalldir="/" name="src/core/census/tracing.c" role="src" />
+    <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="third_party/boringssl/crypto/aes/internal.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/asn1/asn1_locl.h" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/bio/internal.h" role="src" />
@@ -957,7 +967,21 @@ Update to wrap gRPC C Core version 0.10.0
    <license>BSD</license>
    <notes>
 - Simplify gRPC PHP installation #4517
-- Wrap gRPC core library version 0.13
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>0.14.0</release>
+    <api>0.14.0</api>
+   </version>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <date>2016-03-01</date>
+   <license>BSD</license>
+   <notes>
+- Increase unit test code coverage #5225
    </notes>
   </release>
  </changelog>
diff --git a/setup.py b/setup.py
index cf5ab4920fb82dcdf736f52379cb2d275830dc1d..45ff2cec89b1f93007be535776e4d14f51c04451 100644
--- a/setup.py
+++ b/setup.py
@@ -108,8 +108,13 @@ if "linux" in sys.platform or "darwin" in sys.platform:
 
 def cython_extensions(package_names, module_names, extra_sources, include_dirs,
                       libraries, define_macros, build_with_cython=False):
+  # Set compiler directives linetrace argument only if we care about tracing;
+  # this is due to Cython having different behavior between linetrace being
+  # False and linetrace being unset. See issue #5689.
+  cython_compiler_directives = {}
   if ENABLE_CYTHON_TRACING:
     define_macros = define_macros + [('CYTHON_TRACE_NOGIL', 1)]
+    cython_compiler_directives['linetrace'] = True
   file_extension = 'pyx' if build_with_cython else 'c'
   module_files = [os.path.join(PYTHON_STEM,
                                name.replace('.', '/') + '.' + file_extension)
@@ -129,7 +134,7 @@ def cython_extensions(package_names, module_names, extra_sources, include_dirs,
     return Cython.Build.cythonize(
         extensions,
         include_path=include_dirs,
-        compiler_directives={'linetrace': bool(ENABLE_CYTHON_TRACING)})
+        compiler_directives=cython_compiler_directives)
   else:
     return extensions
 
@@ -166,6 +171,7 @@ COMMAND_CLASS = {
     'build_tagged_ext': precompiled.BuildTaggedExt,
     'gather': commands.Gather,
     'run_interop': commands.RunInterop,
+    'test_lite': commands.TestLite
 }
 
 # Ensure that package data is copied over before any commands have been run:
diff --git a/src/core/census/context.c b/src/core/census/context.c
index e60330de64036d3dac6953df8b91a3a861bccbb1..89b8ee0b399dbb7a403f07075b13b9da9664c545 100644
--- a/src/core/census/context.c
+++ b/src/core/census/context.c
@@ -60,10 +60,10 @@
 //   limit of 255 for both CENSUS_MAX_TAG_KV_LEN and CENSUS_MAX_PROPAGATED_TAGS.
 // * Keep all tag information (keys/values/flags) in a single memory buffer,
 //   that can be directly copied to the wire.
-// * Binary tags share the same structure as, but are encoded separately from,
-//   non-binary tags. This is primarily because non-binary tags are far more
-//   likely to be repeated across multiple RPC calls, so are more efficiently
-//   cached and compressed in any metadata schemes.
+
+// min and max valid chars in tag keys and values. All printable ASCII is OK.
+#define MIN_VALID_TAG_CHAR 32   // ' '
+#define MAX_VALID_TAG_CHAR 126  // '~'
 
 // Structure representing a set of tags. Essentially a count of number of tags
 // present, and pointer to a chunk of memory that contains the per-tag details.
@@ -77,7 +77,7 @@ struct tag_set {
   char *kvm;        // key/value memory. Consists of repeated entries of:
   //   Offset  Size  Description
   //     0      1    Key length, including trailing 0. (K)
-  //     1      1    Value length. (V)
+  //     1      1    Value length, including trailing 0 (V)
   //     2      1    Flags
   //     3      K    Key bytes
   //     3 + K  V    Value bytes
@@ -108,19 +108,36 @@ struct raw_tag {
 #define CENSUS_TAG_DELETED CENSUS_TAG_RESERVED
 #define CENSUS_TAG_IS_DELETED(flags) (flags & CENSUS_TAG_DELETED)
 
-// Primary (external) representation of a context. Composed of 3 underlying
-// tag_set structs, one for each of the binary/printable propagated tags, and
-// one for everything else. This is to efficiently support tag
-// encoding/decoding.
+// Primary representation of a context. Composed of 2 underlying tag_set
+// structs, one each for propagated and local (non-propagated) tags. This is
+// to efficiently support tag encoding/decoding.
+// TODO(aveitch): need to add tracing id's/structure.
 struct census_context {
-  struct tag_set tags[3];
+  struct tag_set tags[2];
   census_context_status status;
 };
 
 // Indices into the tags member of census_context
 #define PROPAGATED_TAGS 0
-#define PROPAGATED_BINARY_TAGS 1
-#define LOCAL_TAGS 2
+#define LOCAL_TAGS 1
+
+// Validate (check all characters are in range and size is less than limit) a
+// key or value string. Returns 0 if the string is invalid, or the length
+// (including terminator) if valid.
+static size_t validate_tag(const char *kv) {
+  size_t len = 1;
+  char ch;
+  while ((ch = *kv++) != 0) {
+    if (ch < MIN_VALID_TAG_CHAR || ch > MAX_VALID_TAG_CHAR) {
+      return 0;
+    }
+    len++;
+  }
+  if (len > CENSUS_MAX_TAG_KV_LEN) {
+    return 0;
+  }
+  return len;
+}
 
 // Extract a raw tag given a pointer (raw) to the tag header. Allow for some
 // extra bytes in the tag header (see encode/decode functions for usage: this
@@ -166,9 +183,7 @@ static bool context_delete_tag(census_context *context, const census_tag *tag,
                                size_t key_len) {
   return (
       tag_set_delete_tag(&context->tags[LOCAL_TAGS], tag->key, key_len) ||
-      tag_set_delete_tag(&context->tags[PROPAGATED_TAGS], tag->key, key_len) ||
-      tag_set_delete_tag(&context->tags[PROPAGATED_BINARY_TAGS], tag->key,
-                         key_len));
+      tag_set_delete_tag(&context->tags[PROPAGATED_TAGS], tag->key, key_len));
 }
 
 // Add a tag to a tag_set. Return true on success, false if the tag could
@@ -176,11 +191,11 @@ static bool context_delete_tag(census_context *context, const census_tag *tag,
 // not be called if the tag may already exist (in a non-deleted state) in
 // the tag_set, as that would result in two tags with the same key.
 static bool tag_set_add_tag(struct tag_set *tags, const census_tag *tag,
-                            size_t key_len) {
+                            size_t key_len, size_t value_len) {
   if (tags->ntags == CENSUS_MAX_PROPAGATED_TAGS) {
     return false;
   }
-  const size_t tag_size = key_len + tag->value_len + TAG_HEADER_SIZE;
+  const size_t tag_size = key_len + value_len + TAG_HEADER_SIZE;
   if (tags->kvm_used + tag_size > tags->kvm_size) {
     // allocate new memory if needed
     tags->kvm_size += 2 * CENSUS_MAX_TAG_KV_LEN + TAG_HEADER_SIZE;
@@ -191,13 +206,12 @@ static bool tag_set_add_tag(struct tag_set *tags, const census_tag *tag,
   }
   char *kvp = tags->kvm + tags->kvm_used;
   *kvp++ = (char)key_len;
-  *kvp++ = (char)tag->value_len;
+  *kvp++ = (char)value_len;
   // ensure reserved flags are not used.
-  *kvp++ = (char)(tag->flags & (CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS |
-                                CENSUS_TAG_BINARY));
+  *kvp++ = (char)(tag->flags & (CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS));
   memcpy(kvp, tag->key, key_len);
   kvp += key_len;
-  memcpy(kvp, tag->value, tag->value_len);
+  memcpy(kvp, tag->value, value_len);
   tags->kvm_used += tag_size;
   tags->ntags++;
   tags->ntags_alloc++;
@@ -207,30 +221,20 @@ static bool tag_set_add_tag(struct tag_set *tags, const census_tag *tag,
 // Add/modify/delete a tag to/in a context. Caller must validate that tag key
 // etc. are valid.
 static void context_modify_tag(census_context *context, const census_tag *tag,
-                               size_t key_len) {
+                               size_t key_len, size_t value_len) {
   // First delete the tag if it is already present.
   bool deleted = context_delete_tag(context, tag, key_len);
-  // Determine if we need to add it back.
-  bool call_add = tag->value != NULL && tag->value_len != 0;
   bool added = false;
-  if (call_add) {
-    if (CENSUS_TAG_IS_PROPAGATED(tag->flags)) {
-      if (CENSUS_TAG_IS_BINARY(tag->flags)) {
-        added = tag_set_add_tag(&context->tags[PROPAGATED_BINARY_TAGS], tag,
-                                key_len);
-      } else {
-        added = tag_set_add_tag(&context->tags[PROPAGATED_TAGS], tag, key_len);
-      }
-    } else {
-      added = tag_set_add_tag(&context->tags[LOCAL_TAGS], tag, key_len);
-    }
+  if (CENSUS_TAG_IS_PROPAGATED(tag->flags)) {
+    added = tag_set_add_tag(&context->tags[PROPAGATED_TAGS], tag, key_len,
+                            value_len);
+  } else {
+    added =
+        tag_set_add_tag(&context->tags[LOCAL_TAGS], tag, key_len, value_len);
   }
+
   if (deleted) {
-    if (call_add) {
-      context->status.n_modified_tags++;
-    } else {
-      context->status.n_deleted_tags++;
-    }
+    context->status.n_modified_tags++;
   } else {
     if (added) {
       context->status.n_added_tags++;
@@ -292,8 +296,6 @@ census_context *census_context_create(const census_context *base,
     memset(context, 0, sizeof(census_context));
   } else {
     tag_set_copy(&context->tags[PROPAGATED_TAGS], &base->tags[PROPAGATED_TAGS]);
-    tag_set_copy(&context->tags[PROPAGATED_BINARY_TAGS],
-                 &base->tags[PROPAGATED_BINARY_TAGS]);
     tag_set_copy(&context->tags[LOCAL_TAGS], &base->tags[LOCAL_TAGS]);
     memset(&context->status, 0, sizeof(context->status));
   }
@@ -301,22 +303,29 @@ census_context *census_context_create(const census_context *base,
   // the context to add/replace/delete as required.
   for (int i = 0; i < ntags; i++) {
     const census_tag *tag = &tags[i];
-    size_t key_len = strlen(tag->key) + 1;
-    // ignore the tag if it is too long/short.
-    if (key_len != 1 && key_len <= CENSUS_MAX_TAG_KV_LEN &&
-        tag->value_len <= CENSUS_MAX_TAG_KV_LEN) {
-      context_modify_tag(context, tag, key_len);
-    } else {
+    size_t key_len = validate_tag(tag->key);
+    // ignore the tag if it is invalid or too short.
+    if (key_len <= 1) {
       context->status.n_invalid_tags++;
+    } else {
+      if (tag->value != NULL) {
+        size_t value_len = validate_tag(tag->value);
+        if (value_len != 0) {
+          context_modify_tag(context, tag, key_len, value_len);
+        } else {
+          context->status.n_invalid_tags++;
+        }
+      } else {
+        if (context_delete_tag(context, tag, key_len)) {
+          context->status.n_deleted_tags++;
+        }
+      }
     }
   }
   // Remove any deleted tags, update status if needed, and return.
   tag_set_flatten(&context->tags[PROPAGATED_TAGS]);
-  tag_set_flatten(&context->tags[PROPAGATED_BINARY_TAGS]);
   tag_set_flatten(&context->tags[LOCAL_TAGS]);
   context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags;
-  context->status.n_propagated_binary_tags =
-      context->tags[PROPAGATED_BINARY_TAGS].ntags;
   context->status.n_local_tags = context->tags[LOCAL_TAGS].ntags;
   if (status) {
     *status = &context->status;
@@ -331,7 +340,6 @@ const census_context_status *census_context_get_status(
 
 void census_context_destroy(census_context *context) {
   gpr_free(context->tags[PROPAGATED_TAGS].kvm);
-  gpr_free(context->tags[PROPAGATED_BINARY_TAGS].kvm);
   gpr_free(context->tags[LOCAL_TAGS].kvm);
   gpr_free(context);
 }
@@ -343,9 +351,6 @@ void census_context_initialize_iterator(const census_context *context,
   if (context->tags[PROPAGATED_TAGS].ntags != 0) {
     iterator->base = PROPAGATED_TAGS;
     iterator->kvm = context->tags[PROPAGATED_TAGS].kvm;
-  } else if (context->tags[PROPAGATED_BINARY_TAGS].ntags != 0) {
-    iterator->base = PROPAGATED_BINARY_TAGS;
-    iterator->kvm = context->tags[PROPAGATED_BINARY_TAGS].kvm;
   } else if (context->tags[LOCAL_TAGS].ntags != 0) {
     iterator->base = LOCAL_TAGS;
     iterator->kvm = context->tags[LOCAL_TAGS].kvm;
@@ -363,7 +368,6 @@ int census_context_next_tag(census_context_iterator *iterator,
   iterator->kvm = decode_tag(&raw, iterator->kvm, 0);
   tag->key = raw.key;
   tag->value = raw.value;
-  tag->value_len = raw.value_len;
   tag->flags = raw.flags;
   if (++iterator->index == iterator->context->tags[iterator->base].ntags) {
     do {
@@ -388,7 +392,6 @@ static bool tag_set_get_tag(const struct tag_set *tags, const char *key,
     if (key_len == raw.key_len && memcmp(raw.key, key, key_len) == 0) {
       tag->key = raw.key;
       tag->value = raw.value;
-      tag->value_len = raw.value_len;
       tag->flags = raw.flags;
       return true;
     }
@@ -403,8 +406,6 @@ int census_context_get_tag(const census_context *context, const char *key,
     return 0;
   }
   if (tag_set_get_tag(&context->tags[PROPAGATED_TAGS], key, key_len, tag) ||
-      tag_set_get_tag(&context->tags[PROPAGATED_BINARY_TAGS], key, key_len,
-                      tag) ||
       tag_set_get_tag(&context->tags[LOCAL_TAGS], key, key_len, tag)) {
     return 1;
   }
@@ -447,21 +448,9 @@ static size_t tag_set_encode(const struct tag_set *tags, char *buffer,
   return ENCODED_HEADER_SIZE + tags->kvm_used;
 }
 
-char *census_context_encode(const census_context *context, char *buffer,
-                            size_t buf_size, size_t *print_buf_size,
-                            size_t *bin_buf_size) {
-  *print_buf_size =
-      tag_set_encode(&context->tags[PROPAGATED_TAGS], buffer, buf_size);
-  if (*print_buf_size == 0) {
-    return NULL;
-  }
-  char *b_buffer = buffer + *print_buf_size;
-  *bin_buf_size = tag_set_encode(&context->tags[PROPAGATED_BINARY_TAGS],
-                                 b_buffer, buf_size - *print_buf_size);
-  if (*bin_buf_size == 0) {
-    return NULL;
-  }
-  return b_buffer;
+size_t census_context_encode(const census_context *context, char *buffer,
+                             size_t buf_size) {
+  return tag_set_encode(&context->tags[PROPAGATED_TAGS], buffer, buf_size);
 }
 
 // Decode a tag set.
@@ -506,8 +495,7 @@ static void tag_set_decode(struct tag_set *tags, const char *buffer,
   }
 }
 
-census_context *census_context_decode(const char *buffer, size_t size,
-                                      const char *bin_buffer, size_t bin_size) {
+census_context *census_context_decode(const char *buffer, size_t size) {
   census_context *context = gpr_malloc(sizeof(census_context));
   memset(&context->tags[LOCAL_TAGS], 0, sizeof(struct tag_set));
   if (buffer == NULL) {
@@ -515,16 +503,7 @@ census_context *census_context_decode(const char *buffer, size_t size,
   } else {
     tag_set_decode(&context->tags[PROPAGATED_TAGS], buffer, size);
   }
-  if (bin_buffer == NULL) {
-    memset(&context->tags[PROPAGATED_BINARY_TAGS], 0, sizeof(struct tag_set));
-  } else {
-    tag_set_decode(&context->tags[PROPAGATED_BINARY_TAGS], bin_buffer,
-                   bin_size);
-  }
   memset(&context->status, 0, sizeof(context->status));
   context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags;
-  context->status.n_propagated_binary_tags =
-      context->tags[PROPAGATED_BINARY_TAGS].ntags;
-  // TODO(aveitch): check that BINARY flag is correct for each type.
   return context;
 }
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
index 7176c01b05f11f3ed8e46183e06348a9ff439a38..f021a8ae32920904441ef362c3ec30ebaae71944 100644
--- a/src/core/channel/client_channel.c
+++ b/src/core/channel/client_channel.c
@@ -78,8 +78,8 @@ typedef struct client_channel_channel_data {
   int exit_idle_when_lb_policy_arrives;
   /** owning stack */
   grpc_channel_stack *owning_stack;
-  /** interested parties */
-  grpc_pollset_set interested_parties;
+  /** interested parties (owned) */
+  grpc_pollset_set *interested_parties;
 } channel_data;
 
 /** We create one watcher for each new lb_policy that is returned from a
@@ -165,7 +165,6 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
   channel_data *chand = arg;
   grpc_lb_policy *lb_policy = NULL;
   grpc_lb_policy *old_lb_policy;
-  grpc_resolver *old_resolver;
   grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
   int exit_idle = 0;
 
@@ -183,8 +182,8 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
   chand->incoming_configuration = NULL;
 
   if (lb_policy != NULL) {
-    grpc_pollset_set_add_pollset_set(exec_ctx, &lb_policy->interested_parties,
-                                     &chand->interested_parties);
+    grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
+                                     chand->interested_parties);
   }
 
   gpr_mu_lock(&chand->mu_config);
@@ -201,28 +200,25 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
   }
 
   if (iomgr_success && chand->resolver) {
-    grpc_resolver *resolver = chand->resolver;
-    GRPC_RESOLVER_REF(resolver, "channel-next");
     grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state,
                                 "new_lb+resolver");
     if (lb_policy != NULL) {
       watch_lb_policy(exec_ctx, chand, lb_policy, state);
     }
-    gpr_mu_unlock(&chand->mu_config);
     GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
-    grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
+    grpc_resolver_next(exec_ctx, chand->resolver,
+                       &chand->incoming_configuration,
                        &chand->on_config_changed);
-    GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel-next");
+    gpr_mu_unlock(&chand->mu_config);
   } else {
-    old_resolver = chand->resolver;
-    chand->resolver = NULL;
+    if (chand->resolver != NULL) {
+      grpc_resolver_shutdown(exec_ctx, chand->resolver);
+      GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
+      chand->resolver = NULL;
+    }
     grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
                                 GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
     gpr_mu_unlock(&chand->mu_config);
-    if (old_resolver != NULL) {
-      grpc_resolver_shutdown(exec_ctx, old_resolver);
-      GRPC_RESOLVER_UNREF(exec_ctx, old_resolver, "channel");
-    }
   }
 
   if (exit_idle) {
@@ -231,9 +227,8 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
   }
 
   if (old_lb_policy != NULL) {
-    grpc_pollset_set_del_pollset_set(exec_ctx,
-                                     &old_lb_policy->interested_parties,
-                                     &chand->interested_parties);
+    grpc_pollset_set_del_pollset_set(
+        exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
     GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
   }
 
@@ -248,13 +243,12 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
                                   grpc_channel_element *elem,
                                   grpc_transport_op *op) {
   channel_data *chand = elem->channel_data;
-  grpc_resolver *destroy_resolver = NULL;
 
   grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
 
-  GPR_ASSERT(op->set_accept_stream == NULL);
+  GPR_ASSERT(op->set_accept_stream == false);
   if (op->bind_pollset != NULL) {
-    grpc_pollset_set_add_pollset(exec_ctx, &chand->interested_parties,
+    grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
                                  op->bind_pollset);
   }
 
@@ -280,22 +274,18 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
   if (op->disconnect && chand->resolver != NULL) {
     grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
                                 GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
-    destroy_resolver = chand->resolver;
+    grpc_resolver_shutdown(exec_ctx, chand->resolver);
+    GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
     chand->resolver = NULL;
     if (chand->lb_policy != NULL) {
       grpc_pollset_set_del_pollset_set(exec_ctx,
-                                       &chand->lb_policy->interested_parties,
-                                       &chand->interested_parties);
+                                       chand->lb_policy->interested_parties,
+                                       chand->interested_parties);
       GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
       chand->lb_policy = NULL;
     }
   }
   gpr_mu_unlock(&chand->mu_config);
-
-  if (destroy_resolver) {
-    grpc_resolver_shutdown(exec_ctx, destroy_resolver);
-    GRPC_RESOLVER_UNREF(exec_ctx, destroy_resolver, "channel");
-  }
 }
 
 typedef struct {
@@ -411,7 +401,7 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
 
   grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
                                "client_channel");
-  grpc_pollset_set_init(&chand->interested_parties);
+  chand->interested_parties = grpc_pollset_set_create();
 }
 
 /* Destructor for channel_data */
@@ -425,12 +415,12 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
   }
   if (chand->lb_policy != NULL) {
     grpc_pollset_set_del_pollset_set(exec_ctx,
-                                     &chand->lb_policy->interested_parties,
-                                     &chand->interested_parties);
+                                     chand->lb_policy->interested_parties,
+                                     chand->interested_parties);
     GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
   }
   grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
-  grpc_pollset_set_destroy(&chand->interested_parties);
+  grpc_pollset_set_destroy(chand->interested_parties);
   gpr_mu_destroy(&chand->mu_config);
 }
 
@@ -501,7 +491,7 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
                                        bool iomgr_success) {
   external_connectivity_watcher *w = arg;
   grpc_closure *follow_up = w->on_complete;
-  grpc_pollset_set_del_pollset(exec_ctx, &w->chand->interested_parties,
+  grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
                                w->pollset);
   GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
                            "external_connectivity_watcher");
@@ -517,7 +507,7 @@ void grpc_client_channel_watch_connectivity_state(
   w->chand = chand;
   w->pollset = pollset;
   w->on_complete = on_complete;
-  grpc_pollset_set_add_pollset(exec_ctx, &chand->interested_parties, pollset);
+  grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
   grpc_closure_init(&w->my_closure, on_external_watch_complete, w);
   GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
                          "external_connectivity_watcher");
diff --git a/src/core/channel/client_uchannel.c b/src/core/channel/client_uchannel.c
index b1e7155773fd68eda130e652cdadb87fba45e85d..83fcc3a87f52f644f81b6a801edf9eb3b7522fc9 100644
--- a/src/core/channel/client_uchannel.c
+++ b/src/core/channel/client_uchannel.c
@@ -107,7 +107,7 @@ static void cuc_start_transport_op(grpc_exec_ctx *exec_ctx,
 
   grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
 
-  GPR_ASSERT(op->set_accept_stream == NULL);
+  GPR_ASSERT(op->set_accept_stream == false);
   GPR_ASSERT(op->bind_pollset == NULL);
 
   if (op->on_connectivity_state_change != NULL) {
diff --git a/src/core/channel/subchannel_call_holder.c b/src/core/channel/subchannel_call_holder.c
index 81297c8d4490eff53d0015aa11ff3268b5ba8e46..9c087dc2a1d477d30e6a56aba7c7a952790a8800 100644
--- a/src/core/channel/subchannel_call_holder.c
+++ b/src/core/channel/subchannel_call_holder.c
@@ -168,15 +168,15 @@ retry:
 
 static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
   grpc_subchannel_call_holder *holder = arg;
-  grpc_subchannel_call *call;
   gpr_mu_lock(&holder->mu);
   GPR_ASSERT(holder->creation_phase ==
              GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
-  call = GET_CALL(holder);
-  GPR_ASSERT(call == NULL || call == CANCELLED_CALL);
   holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
   if (holder->connected_subchannel == NULL) {
     fail_locked(exec_ctx, holder);
+  } else if (1 == gpr_atm_acq_load(&holder->subchannel_call)) {
+    /* already cancelled before subchannel became ready */
+    fail_locked(exec_ctx, holder);
   } else {
     gpr_atm_rel_store(
         &holder->subchannel_call,
diff --git a/src/core/client_config/lb_policies/load_balancer_api.c b/src/core/client_config/lb_policies/load_balancer_api.c
new file mode 100644
index 0000000000000000000000000000000000000000..a6b5785fe4ed088eeacb0d19154facdf809760ba
--- /dev/null
+++ b/src/core/client_config/lb_policies/load_balancer_api.c
@@ -0,0 +1,163 @@
+/*
+ *
+ * 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 "src/core/client_config/lb_policies/load_balancer_api.h"
+#include "third_party/nanopb/pb_decode.h"
+#include "third_party/nanopb/pb_encode.h"
+
+#include <grpc/support/alloc.h>
+
+typedef struct decode_serverlist_arg {
+  int first_pass;
+  int i;
+  size_t num_servers;
+  grpc_grpclb_server **servers;
+} decode_serverlist_arg;
+
+/* invoked once for every Server in ServerList */
+static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field,
+                              void **arg) {
+  decode_serverlist_arg *dec_arg = *arg;
+  if (dec_arg->first_pass != 0) { /* first pass */
+    grpc_grpclb_server server;
+    if (!pb_decode(stream, grpc_lb_v0_Server_fields, &server)) {
+      return false;
+    }
+    dec_arg->num_servers++;
+  } else { /* second pass */
+    grpc_grpclb_server *server = gpr_malloc(sizeof(grpc_grpclb_server));
+    GPR_ASSERT(dec_arg->num_servers > 0);
+    if (dec_arg->i == 0) { /* first iteration of second pass */
+      dec_arg->servers =
+          gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers);
+    }
+    if (!pb_decode(stream, grpc_lb_v0_Server_fields, server)) {
+      return false;
+    }
+    dec_arg->servers[dec_arg->i++] = server;
+  }
+
+  return true;
+}
+
+grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name) {
+  grpc_grpclb_request *req = gpr_malloc(sizeof(grpc_grpclb_request));
+
+  req->has_client_stats = 0; /* TODO(dgq): add support for stats once defined */
+  req->has_initial_request = 1;
+  req->initial_request.has_name = 1;
+  strncpy(req->initial_request.name, lb_service_name,
+          GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH);
+  return req;
+}
+
+gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request) {
+  size_t encoded_length;
+  pb_ostream_t sizestream;
+  pb_ostream_t outputstream;
+  gpr_slice slice;
+  memset(&sizestream, 0, sizeof(pb_ostream_t));
+  pb_encode(&sizestream, grpc_lb_v0_LoadBalanceRequest_fields, request);
+  encoded_length = sizestream.bytes_written;
+
+  slice = gpr_slice_malloc(encoded_length);
+  outputstream =
+      pb_ostream_from_buffer(GPR_SLICE_START_PTR(slice), encoded_length);
+  GPR_ASSERT(pb_encode(&outputstream, grpc_lb_v0_LoadBalanceRequest_fields,
+                       request) != 0);
+  return slice;
+}
+
+void grpc_grpclb_request_destroy(grpc_grpclb_request *request) {
+  gpr_free(request);
+}
+
+grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response) {
+  bool status;
+  pb_istream_t stream =
+      pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
+                             GPR_SLICE_LENGTH(encoded_response));
+  grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
+  memset(res, 0, sizeof(*res));
+  status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res);
+  GPR_ASSERT(status == true);
+  return res;
+}
+
+grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
+    gpr_slice encoded_response) {
+  grpc_grpclb_serverlist *sl = gpr_malloc(sizeof(grpc_grpclb_serverlist));
+  bool status;
+  decode_serverlist_arg arg;
+  pb_istream_t stream =
+      pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
+                             GPR_SLICE_LENGTH(encoded_response));
+  pb_istream_t stream_at_start = stream;
+  grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
+  memset(res, 0, sizeof(*res));
+  memset(&arg, 0, sizeof(decode_serverlist_arg));
+
+  res->server_list.servers.funcs.decode = decode_serverlist;
+  res->server_list.servers.arg = &arg;
+  arg.first_pass = 1;
+  status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res);
+  GPR_ASSERT(status == true);
+  GPR_ASSERT(arg.num_servers > 0);
+
+  arg.first_pass = 0;
+  status =
+      pb_decode(&stream_at_start, grpc_lb_v0_LoadBalanceResponse_fields, res);
+  GPR_ASSERT(status == true);
+  GPR_ASSERT(arg.servers != NULL);
+
+  sl->num_servers = arg.num_servers;
+  sl->servers = arg.servers;
+  if (res->server_list.has_expiration_interval) {
+    sl->expiration_interval = res->server_list.expiration_interval;
+  }
+  grpc_grpclb_response_destroy(res);
+  return sl;
+}
+
+void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist) {
+  size_t i;
+  for (i = 0; i < serverlist->num_servers; i++) {
+    gpr_free(serverlist->servers[i]);
+  }
+  gpr_free(serverlist->servers);
+  gpr_free(serverlist);
+}
+
+void grpc_grpclb_response_destroy(grpc_grpclb_response *response) {
+  gpr_free(response);
+}
diff --git a/src/core/client_config/lb_policies/load_balancer_api.h b/src/core/client_config/lb_policies/load_balancer_api.h
new file mode 100644
index 0000000000000000000000000000000000000000..4dbe1d6c224ef595fe82cf3812c25f0293ae78c9
--- /dev/null
+++ b/src/core/client_config/lb_policies/load_balancer_api.h
@@ -0,0 +1,85 @@
+/*
+ *
+ * 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_INTERNAL_CORE_CLIENT_CONFIG_LB_POLICIES_LOAD_BALANCER_API_H
+#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_LB_POLICIES_LOAD_BALANCER_API_H
+
+#include <grpc/support/slice_buffer.h>
+
+#include "src/core/client_config/lb_policy_factory.h"
+#include "src/core/proto/grpc/lb/v0/load_balancer.pb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128
+
+typedef grpc_lb_v0_LoadBalanceRequest grpc_grpclb_request;
+typedef grpc_lb_v0_LoadBalanceResponse grpc_grpclb_response;
+typedef grpc_lb_v0_Server grpc_grpclb_server;
+typedef grpc_lb_v0_Duration grpc_grpclb_duration;
+typedef struct grpc_grpclb_serverlist {
+  grpc_grpclb_server **servers;
+  size_t num_servers;
+  grpc_grpclb_duration expiration_interval;
+} grpc_grpclb_serverlist;
+
+/** Create a request for a gRPC LB service under \a lb_service_name */
+grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name);
+
+/** Protocol Buffers v3-encode \a request */
+gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request);
+
+/** Destroy \a request */
+void grpc_grpclb_request_destroy(grpc_grpclb_request *request);
+
+/** Parse (ie, decode) the bytes in \a encoded_response as a \a
+ * grpc_grpclb_response */
+grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response);
+
+/** Destroy \a serverlist */
+void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist);
+
+/** Parse the list of servers from an encoded \a grpc_grpclb_response */
+grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
+    gpr_slice encoded_response);
+
+/** Destroy \a response */
+void grpc_grpclb_response_destroy(grpc_grpclb_response *response);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_LB_POLICIES_LOAD_BALANCER_API_H */
diff --git a/src/core/client_config/lb_policies/pick_first.c b/src/core/client_config/lb_policies/pick_first.c
index 459bbebb68acd06b14d475b3d233a00edd3d3779..81167b31c8c77b6116fa795bbcbaae3a39a48075 100644
--- a/src/core/client_config/lb_policies/pick_first.c
+++ b/src/core/client_config/lb_policies/pick_first.c
@@ -31,8 +31,8 @@
  *
  */
 
-#include "src/core/client_config/lb_policy_factory.h"
 #include "src/core/client_config/lb_policies/pick_first.h"
+#include "src/core/client_config/lb_policy_factory.h"
 
 #include <string.h>
 
@@ -119,7 +119,7 @@ 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(exec_ctx, &p->base.interested_parties,
+    grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
                                  pp->pollset);
     grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
     gpr_free(pp);
@@ -137,7 +137,7 @@ 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(exec_ctx, &p->base.interested_parties,
+      grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
                                    pp->pollset);
       *target = NULL;
       grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
@@ -158,7 +158,7 @@ static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
   GRPC_LB_POLICY_WEAK_REF(&p->base, "pick_first_connectivity");
   grpc_subchannel_notify_on_state_change(
       exec_ctx, p->subchannels[p->checking_subchannel],
-      &p->base.interested_parties, &p->checking_connectivity,
+      p->base.interested_parties, &p->checking_connectivity,
       &p->connectivity_changed);
 }
 
@@ -195,8 +195,7 @@ int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
     if (!p->started_picking) {
       start_picking(exec_ctx, p);
     }
-    grpc_pollset_set_add_pollset(exec_ctx, &p->base.interested_parties,
-                                 pollset);
+    grpc_pollset_set_add_pollset(exec_ctx, p->base.interested_parties, pollset);
     pp = gpr_malloc(sizeof(*pp));
     pp->next = p->pending_picks;
     pp->pollset = pollset;
@@ -253,7 +252,7 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
                                 p->checking_connectivity, "selected_changed");
     if (p->checking_connectivity != GRPC_CHANNEL_FATAL_FAILURE) {
       grpc_connected_subchannel_notify_on_state_change(
-          exec_ctx, selected, &p->base.interested_parties,
+          exec_ctx, selected, p->base.interested_parties,
           &p->checking_connectivity, &p->connectivity_changed);
     } else {
       GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
@@ -278,13 +277,13 @@ 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(exec_ctx, &p->base.interested_parties,
+          grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
                                        pp->pollset);
           grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
           gpr_free(pp);
         }
         grpc_connected_subchannel_notify_on_state_change(
-            exec_ctx, selected, &p->base.interested_parties,
+            exec_ctx, selected, p->base.interested_parties,
             &p->checking_connectivity, &p->connectivity_changed);
         break;
       case GRPC_CHANNEL_TRANSIENT_FAILURE:
@@ -298,7 +297,7 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
         if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
           grpc_subchannel_notify_on_state_change(
               exec_ctx, p->subchannels[p->checking_subchannel],
-              &p->base.interested_parties, &p->checking_connectivity,
+              p->base.interested_parties, &p->checking_connectivity,
               &p->connectivity_changed);
         } else {
           goto loop;
@@ -311,7 +310,7 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
                                     "connecting_changed");
         grpc_subchannel_notify_on_state_change(
             exec_ctx, p->subchannels[p->checking_subchannel],
-            &p->base.interested_parties, &p->checking_connectivity,
+            p->base.interested_parties, &p->checking_connectivity,
             &p->connectivity_changed);
         break;
       case GRPC_CHANNEL_FATAL_FAILURE:
diff --git a/src/core/client_config/lb_policies/round_robin.c b/src/core/client_config/lb_policies/round_robin.c
index b1171c45b007f2883ee758d11d78a5164630aaa3..98d9acc75bfd2ea0653ea3c4e2544c505d789a09 100644
--- a/src/core/client_config/lb_policies/round_robin.c
+++ b/src/core/client_config/lb_policies/round_robin.c
@@ -260,7 +260,7 @@ 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(exec_ctx, &p->base.interested_parties,
+      grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
                                    pp->pollset);
       *target = NULL;
       grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
@@ -285,7 +285,7 @@ static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) {
     subchannel_data *sd = p->subchannels[i];
     sd->connectivity_state = GRPC_CHANNEL_IDLE;
     grpc_subchannel_notify_on_state_change(
-        exec_ctx, sd->subchannel, &p->base.interested_parties,
+        exec_ctx, sd->subchannel, p->base.interested_parties,
         &sd->connectivity_state, &sd->connectivity_changed_closure);
     GRPC_LB_POLICY_WEAK_REF(&p->base, "round_robin_connectivity");
   }
@@ -322,8 +322,7 @@ int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
     if (!p->started_picking) {
       start_picking(exec_ctx, p);
     }
-    grpc_pollset_set_add_pollset(exec_ctx, &p->base.interested_parties,
-                                 pollset);
+    grpc_pollset_set_add_pollset(exec_ctx, p->base.interested_parties, pollset);
     pp = gpr_malloc(sizeof(*pp));
     pp->next = p->pending_picks;
     pp->pollset = pollset;
@@ -374,13 +373,13 @@ 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(exec_ctx, &p->base.interested_parties,
+          grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
                                        pp->pollset);
           grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
           gpr_free(pp);
         }
         grpc_subchannel_notify_on_state_change(
-            exec_ctx, sd->subchannel, &p->base.interested_parties,
+            exec_ctx, sd->subchannel, p->base.interested_parties,
             &sd->connectivity_state, &sd->connectivity_changed_closure);
         break;
       case GRPC_CHANNEL_CONNECTING:
@@ -389,13 +388,13 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
                                     sd->connectivity_state,
                                     "connecting_changed");
         grpc_subchannel_notify_on_state_change(
-            exec_ctx, sd->subchannel, &p->base.interested_parties,
+            exec_ctx, sd->subchannel, p->base.interested_parties,
             &sd->connectivity_state, &sd->connectivity_changed_closure);
         break;
       case GRPC_CHANNEL_TRANSIENT_FAILURE:
         /* renew state notification */
         grpc_subchannel_notify_on_state_change(
-            exec_ctx, sd->subchannel, &p->base.interested_parties,
+            exec_ctx, sd->subchannel, p->base.interested_parties,
             &sd->connectivity_state, &sd->connectivity_changed_closure);
 
         /* remove from ready list if still present */
diff --git a/src/core/client_config/lb_policy.c b/src/core/client_config/lb_policy.c
index d4672f6b25502aeda9b45588f059e3de34d5b671..0d8b0073369c32812ba64b0925ea34ecbfce141a 100644
--- a/src/core/client_config/lb_policy.c
+++ b/src/core/client_config/lb_policy.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@ void grpc_lb_policy_init(grpc_lb_policy *policy,
                          const grpc_lb_policy_vtable *vtable) {
   policy->vtable = vtable;
   gpr_atm_no_barrier_store(&policy->ref_pair, 1 << WEAK_REF_BITS);
-  grpc_pollset_set_init(&policy->interested_parties);
+  policy->interested_parties = grpc_pollset_set_create();
 }
 
 #ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
@@ -93,7 +93,7 @@ void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx,
   gpr_atm old_val =
       ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF"));
   if (old_val == 1) {
-    grpc_pollset_set_destroy(&policy->interested_parties);
+    grpc_pollset_set_destroy(policy->interested_parties);
     policy->vtable->destroy(exec_ctx, policy);
   }
 }
diff --git a/src/core/client_config/lb_policy.h b/src/core/client_config/lb_policy.h
index db5238c8ca09863c82ac8f17f1755daf7eba4990..345739060682c0fb96fbd7f41c81a00546ab84b2 100644
--- a/src/core/client_config/lb_policy.h
+++ b/src/core/client_config/lb_policy.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -48,7 +48,8 @@ typedef void (*grpc_lb_completion)(void *cb_arg, grpc_subchannel *subchannel,
 struct grpc_lb_policy {
   const grpc_lb_policy_vtable *vtable;
   gpr_atm ref_pair;
-  grpc_pollset_set interested_parties;
+  /* owned pointer to interested parties in load balancing decisions */
+  grpc_pollset_set *interested_parties;
 };
 
 struct grpc_lb_policy_vtable {
diff --git a/src/core/client_config/subchannel.c b/src/core/client_config/subchannel.c
index 6599c75dba7888798c9f633e296ad00b46e6239a..d91dd116b8c1bde802f6948bd5a9cf1ff7e510ad 100644
--- a/src/core/client_config/subchannel.c
+++ b/src/core/client_config/subchannel.c
@@ -108,7 +108,7 @@ struct grpc_subchannel {
 
   /** pollset_set tracking who's interested in a connection
       being setup */
-  grpc_pollset_set pollset_set;
+  grpc_pollset_set *pollset_set;
 
   /** active connection, or null; of type grpc_connected_subchannel */
   gpr_atm connected_subchannel;
@@ -209,7 +209,7 @@ static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
   gpr_slice_unref(c->initial_connect_string);
   grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
   grpc_connector_unref(exec_ctx, c->connector);
-  grpc_pollset_set_destroy(&c->pollset_set);
+  grpc_pollset_set_destroy(c->pollset_set);
   grpc_subchannel_key_destroy(exec_ctx, c->key);
   gpr_free(c);
 }
@@ -326,7 +326,7 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
   }
   c->addr = gpr_malloc(args->addr_len);
   memcpy(c->addr, args->addr, args->addr_len);
-  grpc_pollset_set_init(&c->pollset_set);
+  c->pollset_set = grpc_pollset_set_create();
   c->addr_len = args->addr_len;
   grpc_set_initial_connect_string(&c->addr, &c->addr_len,
                                   &c->initial_connect_string);
@@ -345,7 +345,7 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
 static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
   grpc_connect_in_args args;
 
-  args.interested_parties = &c->pollset_set;
+  args.interested_parties = c->pollset_set;
   args.addr = c->addr;
   args.addr_len = c->addr_len;
   args.deadline = compute_connect_deadline(c);
@@ -379,7 +379,7 @@ static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
   external_state_watcher *w = arg;
   grpc_closure *follow_up = w->notify;
   if (w->pollset_set != NULL) {
-    grpc_pollset_set_del_pollset_set(exec_ctx, &w->subchannel->pollset_set,
+    grpc_pollset_set_del_pollset_set(exec_ctx, w->subchannel->pollset_set,
                                      w->pollset_set);
   }
   gpr_mu_lock(&w->subchannel->mu);
@@ -395,7 +395,6 @@ void grpc_subchannel_notify_on_state_change(
     grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
     grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
     grpc_closure *notify) {
-  int do_connect = 0;
   external_state_watcher *w;
 
   if (state == NULL) {
@@ -415,7 +414,7 @@ void grpc_subchannel_notify_on_state_change(
     w->notify = notify;
     grpc_closure_init(&w->closure, on_external_state_watcher_done, w);
     if (interested_parties != NULL) {
-      grpc_pollset_set_add_pollset_set(exec_ctx, &c->pollset_set,
+      grpc_pollset_set_add_pollset_set(exec_ctx, c->pollset_set,
                                        interested_parties);
     }
     GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher");
@@ -425,17 +424,13 @@ void grpc_subchannel_notify_on_state_change(
     w->next->prev = w->prev->next = w;
     if (grpc_connectivity_state_notify_on_state_change(
             exec_ctx, &c->state_tracker, state, &w->closure)) {
-      do_connect = 1;
       c->connecting = 1;
       /* released by connection */
       GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
+      start_connect(exec_ctx, c);
     }
     gpr_mu_unlock(&c->mu);
   }
-
-  if (do_connect) {
-    start_connect(exec_ctx, c);
-  }
 }
 
 void grpc_connected_subchannel_process_transport_op(
@@ -573,7 +568,7 @@ static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
   GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
   GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
   grpc_connected_subchannel_notify_on_state_change(
-      exec_ctx, con, &c->pollset_set, &sw_subchannel->connectivity_state,
+      exec_ctx, con, c->pollset_set, &sw_subchannel->connectivity_state,
       &sw_subchannel->closure);
 
   /* signal completion */
@@ -635,11 +630,12 @@ static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
   if (c->disconnected) {
     iomgr_success = 0;
   }
-  gpr_mu_unlock(&c->mu);
   if (iomgr_success) {
     update_reconnect_parameters(c);
     continue_connect(exec_ctx, c);
+    gpr_mu_unlock(&c->mu);
   } else {
+    gpr_mu_unlock(&c->mu);
     GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
   }
 }
diff --git a/src/core/client_config/subchannel_index.c b/src/core/client_config/subchannel_index.c
index f78a7fd588c48640c8ffe15dc79a59205af07932..3f948998f9cae1f4f4d81ae46c2ce51ffdedcc7b 100644
--- a/src/core/client_config/subchannel_index.c
+++ b/src/core/client_config/subchannel_index.c
@@ -149,11 +149,13 @@ static const gpr_avl_vtable subchannel_avl_vtable = {
 void grpc_subchannel_index_init(void) {
   g_subchannel_index = gpr_avl_create(&subchannel_avl_vtable);
   gpr_mu_init(&g_mu);
+  gpr_tls_init(&subchannel_index_exec_ctx);
 }
 
 void grpc_subchannel_index_shutdown(void) {
   gpr_mu_destroy(&g_mu);
   gpr_avl_unref(g_subchannel_index);
+  gpr_tls_destroy(&subchannel_index_exec_ctx);
 }
 
 grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/compression/algorithm.c b/src/core/compression/compression_algorithm.c
similarity index 100%
rename from src/core/compression/algorithm.c
rename to src/core/compression/compression_algorithm.c
diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c
index 71237bb61406421b7240db0be4abb590667d13ba..1219c444c715ce99aebf82944c84cce3ba85df4d 100644
--- a/src/core/httpcli/httpcli.c
+++ b/src/core/httpcli/httpcli.c
@@ -31,20 +31,22 @@
  *
  */
 
-#include "src/core/iomgr/sockaddr.h"
 #include "src/core/httpcli/httpcli.h"
+#include "src/core/iomgr/sockaddr.h"
 
 #include <string.h>
 
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/httpcli/format_request.h"
+#include "src/core/httpcli/parser.h"
 #include "src/core/iomgr/endpoint.h"
+#include "src/core/iomgr/iomgr_internal.h"
 #include "src/core/iomgr/resolve_address.h"
 #include "src/core/iomgr/tcp_client.h"
-#include "src/core/httpcli/format_request.h"
-#include "src/core/httpcli/parser.h"
 #include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
 
 typedef struct {
   gpr_slice request_text;
@@ -84,18 +86,18 @@ const grpc_httpcli_handshaker grpc_httpcli_plaintext = {"http",
                                                         plaintext_handshake};
 
 void grpc_httpcli_context_init(grpc_httpcli_context *context) {
-  grpc_pollset_set_init(&context->pollset_set);
+  context->pollset_set = grpc_pollset_set_create();
 }
 
 void grpc_httpcli_context_destroy(grpc_httpcli_context *context) {
-  grpc_pollset_set_destroy(&context->pollset_set);
+  grpc_pollset_set_destroy(context->pollset_set);
 }
 
 static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req);
 
 static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
                    int success) {
-  grpc_pollset_set_del_pollset(exec_ctx, &req->context->pollset_set,
+  grpc_pollset_set_del_pollset(exec_ctx, req->context->pollset_set,
                                req->pollset);
   req->on_response(exec_ctx, req->user_data, success ? &req->parser.r : NULL);
   grpc_httpcli_parser_destroy(&req->parser);
@@ -197,7 +199,7 @@ static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
   addr = &req->addresses->addrs[req->next_address++];
   grpc_closure_init(&req->connected, on_connected, req);
   grpc_tcp_client_connect(
-      exec_ctx, &req->connected, &req->ep, &req->context->pollset_set,
+      exec_ctx, &req->connected, &req->ep, req->context->pollset_set,
       (struct sockaddr *)&addr->addr, addr->len, req->deadline);
 }
 
@@ -237,7 +239,7 @@ static void internal_request_begin(
   req->host = gpr_strdup(request->host);
   req->ssl_host_override = gpr_strdup(request->ssl_host_override);
 
-  grpc_pollset_set_add_pollset(exec_ctx, &req->context->pollset_set,
+  grpc_pollset_set_add_pollset(exec_ctx, req->context->pollset_set,
                                req->pollset);
   grpc_resolve_address(request->host, req->handshaker->default_port,
                        on_resolved, req);
diff --git a/src/core/httpcli/httpcli.h b/src/core/httpcli/httpcli.h
index 30875d71f13b7767f325e1d25ea39d0e7593a266..c9cd987c794f505dd8258a3af74a00dbad2e10aa 100644
--- a/src/core/httpcli/httpcli.h
+++ b/src/core/httpcli/httpcli.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@
 #include <grpc/support/time.h>
 
 #include "src/core/iomgr/endpoint.h"
+#include "src/core/iomgr/iomgr_internal.h"
 #include "src/core/iomgr/pollset_set.h"
 
 /* User agent this library reports */
@@ -56,7 +57,7 @@ typedef struct grpc_httpcli_header {
    TODO(ctiller): allow caching and capturing multiple requests for the
                   same content and combining them */
 typedef struct grpc_httpcli_context {
-  grpc_pollset_set pollset_set;
+  grpc_pollset_set *pollset_set;
 } grpc_httpcli_context;
 
 typedef struct {
diff --git a/src/core/httpcli/httpcli_security_connector.c b/src/core/httpcli/httpcli_security_connector.c
index 41ad1de6c00dba11c869a70ad71d4986e0ffc092..156961a377a5abced49e4d7e8dead5b8b1a857af 100644
--- a/src/core/httpcli/httpcli_security_connector.c
+++ b/src/core/httpcli/httpcli_security_connector.c
@@ -59,7 +59,7 @@ static void httpcli_ssl_destroy(grpc_security_connector *sc) {
 }
 
 static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
-                                     grpc_security_connector *sc,
+                                     grpc_channel_security_connector *sc,
                                      grpc_endpoint *nonsecure_endpoint,
                                      grpc_security_handshake_done_cb cb,
                                      void *user_data) {
@@ -78,8 +78,8 @@ static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
             tsi_result_to_string(result));
     cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
   } else {
-    grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
-                               user_data);
+    grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
+                               nonsecure_endpoint, cb, user_data);
   }
 }
 
@@ -103,7 +103,7 @@ static void httpcli_ssl_check_peer(grpc_exec_ctx *exec_ctx,
 }
 
 static grpc_security_connector_vtable httpcli_ssl_vtable = {
-    httpcli_ssl_destroy, httpcli_ssl_do_handshake, httpcli_ssl_check_peer};
+    httpcli_ssl_destroy, httpcli_ssl_check_peer};
 
 static grpc_security_status httpcli_ssl_channel_security_connector_create(
     const unsigned char *pem_root_certs, size_t pem_root_certs_size,
@@ -121,7 +121,6 @@ static grpc_security_status httpcli_ssl_channel_security_connector_create(
   memset(c, 0, sizeof(grpc_httpcli_ssl_channel_security_connector));
 
   gpr_ref_init(&c->base.base.refcount, 1);
-  c->base.base.is_client_side = 1;
   c->base.base.vtable = &httpcli_ssl_vtable;
   if (secure_peer_name != NULL) {
     c->secure_peer_name = gpr_strdup(secure_peer_name);
@@ -136,6 +135,7 @@ static grpc_security_status httpcli_ssl_channel_security_connector_create(
     *sc = NULL;
     return GRPC_SECURITY_ERROR;
   }
+  c->base.do_handshake = httpcli_ssl_do_handshake;
   *sc = &c->base;
   return GRPC_SECURITY_OK;
 }
@@ -180,8 +180,8 @@ static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
   GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
                  pem_root_certs, pem_root_certs_size, host, &sc) ==
              GRPC_SECURITY_OK);
-  grpc_security_connector_do_handshake(exec_ctx, &sc->base, tcp,
-                                       on_secure_transport_setup_done, c);
+  grpc_channel_security_connector_do_handshake(
+      exec_ctx, sc, tcp, on_secure_transport_setup_done, c);
   GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
 }
 
diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c
index 85eadd754b9fd8670f354aadd781f64350dac13c..4ba7c5df9435a9ea3af3c95819fc9228a287a584 100644
--- a/src/core/iomgr/fd_posix.c
+++ b/src/core/iomgr/fd_posix.c
@@ -46,6 +46,8 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/useful.h>
 
+#include "src/core/iomgr/pollset_posix.h"
+
 #define CLOSURE_NOT_READY ((grpc_closure *)0)
 #define CLOSURE_READY ((grpc_closure *)1)
 
@@ -175,11 +177,11 @@ int grpc_fd_is_orphaned(grpc_fd *fd) {
 }
 
 static void pollset_kick_locked(grpc_fd_watcher *watcher) {
-  gpr_mu_lock(GRPC_POLLSET_MU(watcher->pollset));
+  gpr_mu_lock(&watcher->pollset->mu);
   GPR_ASSERT(watcher->worker);
   grpc_pollset_kick_ext(watcher->pollset, watcher->worker,
                         GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP);
-  gpr_mu_unlock(GRPC_POLLSET_MU(watcher->pollset));
+  gpr_mu_unlock(&watcher->pollset->mu);
 }
 
 static void maybe_wake_one_watcher_locked(grpc_fd *fd) {
diff --git a/src/core/iomgr/iocp_windows.c b/src/core/iomgr/iocp_windows.c
index 759340e00ef9365f4a3893a50ad7a0bb7e8b25c3..807729708ea7e1cc726dcd4fa8c0028a83b6627a 100644
--- a/src/core/iomgr/iocp_windows.c
+++ b/src/core/iomgr/iocp_windows.c
@@ -42,7 +42,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/thd.h>
 
-#include "src/core/iomgr/timer_internal.h"
+#include "src/core/iomgr/timer.h"
 #include "src/core/iomgr/iocp_windows.h"
 #include "src/core/iomgr/iomgr_internal.h"
 #include "src/core/iomgr/socket_windows.h"
diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c
index 212ce5534dd9af5ea793c5361081771ee6731832..9c89c2c08a459eb51df983210db8d489cbddb17e 100644
--- a/src/core/iomgr/iomgr.c
+++ b/src/core/iomgr/iomgr.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,9 +41,11 @@
 #include <grpc/support/string_util.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
+#include <grpc/support/useful.h>
 
 #include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/timer_internal.h"
+#include "src/core/iomgr/timer.h"
+#include "src/core/support/env.h"
 #include "src/core/support/string.h"
 
 static gpr_mu g_mu;
@@ -116,6 +118,9 @@ void grpc_iomgr_shutdown(void) {
                     "memory leaks are likely",
                     count_objects());
             dump_objects("LEAKED");
+            if (grpc_iomgr_abort_on_leaks()) {
+              abort();
+            }
           }
           break;
         }
@@ -154,3 +159,14 @@ void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) {
   gpr_mu_unlock(&g_mu);
   gpr_free(obj->name);
 }
+
+bool grpc_iomgr_abort_on_leaks(void) {
+  char *env = gpr_getenv("GRPC_ABORT_ON_LEAKS");
+  if (env == NULL) return false;
+  static const char *truthy[] = {"yes",  "Yes",  "YES", "true",
+                                 "True", "TRUE", "1"};
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
+    if (0 == strcmp(env, truthy[i])) return true;
+  }
+  return false;
+}
diff --git a/src/core/iomgr/iomgr_internal.h b/src/core/iomgr/iomgr_internal.h
index e372c18e8a070cbba634bcea67ea7d80110b461c..ac2c46ebe6230df3242f4a8a3cb04ba7b3cf7dbf 100644
--- a/src/core/iomgr/iomgr_internal.h
+++ b/src/core/iomgr/iomgr_internal.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,8 @@
 #ifndef GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H
 #define GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H
 
+#include <stdbool.h>
+
 #include "src/core/iomgr/iomgr.h"
 #include <grpc/support/sync.h>
 
@@ -55,4 +57,6 @@ void grpc_iomgr_platform_flush(void);
 /** tear down all platform specific global iomgr structures */
 void grpc_iomgr_platform_shutdown(void);
 
+bool grpc_iomgr_abort_on_leaks(void);
+
 #endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H */
diff --git a/src/core/iomgr/pollset.h b/src/core/iomgr/pollset.h
index c6b0214dea2cb1e460c4cc6c8386087ac1db1451..92a0374ddd4067d1844300e960100aa40d72462d 100644
--- a/src/core/iomgr/pollset.h
+++ b/src/core/iomgr/pollset.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,8 +35,11 @@
 #define GRPC_INTERNAL_CORE_IOMGR_POLLSET_H
 
 #include <grpc/support/port_platform.h>
+#include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 
+#include "src/core/iomgr/exec_ctx.h"
+
 #define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1)
 
 /* A grpc_pollset is a set of file descriptors that a higher level item is
@@ -46,15 +49,11 @@
     - a completion queue might keep a pollset with an entry for each transport
       that is servicing a call that it's tracking */
 
-#ifdef GPR_POSIX_SOCKET
-#include "src/core/iomgr/pollset_posix.h"
-#endif
-
-#ifdef GPR_WIN32
-#include "src/core/iomgr/pollset_windows.h"
-#endif
+typedef struct grpc_pollset grpc_pollset;
+typedef struct grpc_pollset_worker grpc_pollset_worker;
 
-void grpc_pollset_init(grpc_pollset *pollset);
+size_t grpc_pollset_size(void);
+void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu);
 /* Begin shutting down the pollset, and call closure when done.
  * GRPC_POLLSET_MU(pollset) must be held */
 void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@@ -83,7 +82,7 @@ void grpc_pollset_destroy(grpc_pollset *pollset);
    pollset
    lock */
 void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                       grpc_pollset_worker *worker, gpr_timespec now,
+                       grpc_pollset_worker **worker, gpr_timespec now,
                        gpr_timespec deadline);
 
 /* Break one polling thread out of polling work for this pollset.
diff --git a/src/core/iomgr/pollset_multipoller_with_epoll.c b/src/core/iomgr/pollset_multipoller_with_epoll.c
index 4acae2bb7122ccefc755cbc9f34e62c97a2aabeb..2e0f27fab869ade272df0f1188726c5c7d4eab66 100644
--- a/src/core/iomgr/pollset_multipoller_with_epoll.c
+++ b/src/core/iomgr/pollset_multipoller_with_epoll.c
@@ -45,6 +45,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 #include "src/core/iomgr/fd_posix.h"
+#include "src/core/iomgr/pollset_posix.h"
 #include "src/core/profiling/timers.h"
 #include "src/core/support/block_annotate.h"
 
diff --git a/src/core/iomgr/pollset_multipoller_with_poll_posix.c b/src/core/iomgr/pollset_multipoller_with_poll_posix.c
index 809f8f39daababae2bfdf22a6f8bf93ce8c238a1..92d6fb724142a64f4b6553c3a2191e34db89991e 100644
--- a/src/core/iomgr/pollset_multipoller_with_poll_posix.c
+++ b/src/core/iomgr/pollset_multipoller_with_poll_posix.c
@@ -42,13 +42,15 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "src/core/iomgr/fd_posix.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/support/block_annotate.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
+#include "src/core/iomgr/fd_posix.h"
+#include "src/core/iomgr/iomgr_internal.h"
+#include "src/core/iomgr/pollset_posix.h"
+#include "src/core/support/block_annotate.h"
+
 typedef struct {
   /* all polled fds */
   size_t fd_count;
@@ -120,6 +122,7 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
     } else {
       h->fds[fd_count++] = h->fds[i];
       watchers[pfd_count].fd = h->fds[i];
+      GRPC_FD_REF(watchers[pfd_count].fd, "multipoller_start");
       pfds[pfd_count].fd = h->fds[i]->fd;
       pfds[pfd_count].revents = 0;
       pfd_count++;
@@ -133,8 +136,10 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
   gpr_mu_unlock(&pollset->mu);
 
   for (i = 2; i < pfd_count; i++) {
-    pfds[i].events = (short)grpc_fd_begin_poll(watchers[i].fd, pollset, worker,
-                                               POLLIN, POLLOUT, &watchers[i]);
+    grpc_fd *fd = watchers[i].fd;
+    pfds[i].events = (short)grpc_fd_begin_poll(fd, pollset, worker, POLLIN,
+                                               POLLOUT, &watchers[i]);
+    GRPC_FD_UNREF(fd, "multipoller_start");
   }
 
   /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid
diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c
index 19ee6650f006c25336d729964ae211b7820c372c..e895a7788491973fadef4650683683d0535a33fd 100644
--- a/src/core/iomgr/pollset_posix.c
+++ b/src/core/iomgr/pollset_posix.c
@@ -42,17 +42,16 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "src/core/iomgr/timer_internal.h"
-#include "src/core/iomgr/fd_posix.h"
-#include "src/core/iomgr/iomgr_internal.h"
-#include "src/core/iomgr/socket_utils_posix.h"
-#include "src/core/profiling/timers.h"
-#include "src/core/support/block_annotate.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/tls.h>
 #include <grpc/support/useful.h>
+#include "src/core/iomgr/fd_posix.h"
+#include "src/core/iomgr/iomgr_internal.h"
+#include "src/core/iomgr/socket_utils_posix.h"
+#include "src/core/profiling/timers.h"
+#include "src/core/support/block_annotate.h"
 
 GPR_TLS_DECL(g_current_thread_poller);
 GPR_TLS_DECL(g_current_thread_worker);
@@ -98,6 +97,8 @@ static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) {
   worker->prev->next = worker->next->prev = worker;
 }
 
+size_t grpc_pollset_size(void) { return sizeof(grpc_pollset); }
+
 void grpc_pollset_kick_ext(grpc_pollset *p,
                            grpc_pollset_worker *specific_worker,
                            uint32_t flags) {
@@ -187,8 +188,9 @@ void grpc_kick_poller(void) { grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); }
 
 static void become_basic_pollset(grpc_pollset *pollset, grpc_fd *fd_or_null);
 
-void grpc_pollset_init(grpc_pollset *pollset) {
+void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
   gpr_mu_init(&pollset->mu);
+  *mu = &pollset->mu;
   pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker;
   pollset->in_flight_cbs = 0;
   pollset->shutting_down = 0;
@@ -205,7 +207,6 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {
   GPR_ASSERT(!grpc_pollset_has_workers(pollset));
   GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail);
   pollset->vtable->destroy(pollset);
-  gpr_mu_destroy(&pollset->mu);
   while (pollset->local_wakeup_cache) {
     grpc_cached_wakeup_fd *next = pollset->local_wakeup_cache->next;
     grpc_wakeup_fd_destroy(&pollset->local_wakeup_cache->fd);
@@ -247,8 +248,11 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
 }
 
 void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                       grpc_pollset_worker *worker, gpr_timespec now,
+                       grpc_pollset_worker **worker_hdl, gpr_timespec now,
                        gpr_timespec deadline) {
+  grpc_pollset_worker worker;
+  *worker_hdl = &worker;
+
   /* pollset->mu already held */
   int added_worker = 0;
   int locked = 1;
@@ -256,16 +260,16 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
   int keep_polling = 0;
   GPR_TIMER_BEGIN("grpc_pollset_work", 0);
   /* this must happen before we (potentially) drop pollset->mu */
-  worker->next = worker->prev = NULL;
-  worker->reevaluate_polling_on_wakeup = 0;
+  worker.next = worker.prev = NULL;
+  worker.reevaluate_polling_on_wakeup = 0;
   if (pollset->local_wakeup_cache != NULL) {
-    worker->wakeup_fd = pollset->local_wakeup_cache;
-    pollset->local_wakeup_cache = worker->wakeup_fd->next;
+    worker.wakeup_fd = pollset->local_wakeup_cache;
+    pollset->local_wakeup_cache = worker.wakeup_fd->next;
   } else {
-    worker->wakeup_fd = gpr_malloc(sizeof(*worker->wakeup_fd));
-    grpc_wakeup_fd_init(&worker->wakeup_fd->fd);
+    worker.wakeup_fd = gpr_malloc(sizeof(*worker.wakeup_fd));
+    grpc_wakeup_fd_init(&worker.wakeup_fd->fd);
   }
-  worker->kicked_specifically = 0;
+  worker.kicked_specifically = 0;
   /* If there's work waiting for the pollset to be idle, and the
      pollset is idle, then do that work */
   if (!grpc_pollset_has_workers(pollset) &&
@@ -274,16 +278,6 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
     grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs, NULL);
     goto done;
   }
-  /* Check alarms - these are a global resource so we just ping
-     each time through on every pollset.
-     May update deadline to ensure timely wakeups.
-     TODO(ctiller): can this work be localized? */
-  if (grpc_timer_check(exec_ctx, now, &deadline)) {
-    GPR_TIMER_MARK("grpc_pollset_work.alarm_triggered", 0);
-    gpr_mu_unlock(&pollset->mu);
-    locked = 0;
-    goto done;
-  }
   /* If we're shutting down then we don't execute any extended work */
   if (pollset->shutting_down) {
     GPR_TIMER_MARK("grpc_pollset_work.shutting_down", 0);
@@ -304,13 +298,13 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
     keep_polling = 0;
     if (!pollset->kicked_without_pollers) {
       if (!added_worker) {
-        push_front_worker(pollset, worker);
+        push_front_worker(pollset, &worker);
         added_worker = 1;
-        gpr_tls_set(&g_current_thread_worker, (intptr_t)worker);
+        gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
       }
       gpr_tls_set(&g_current_thread_poller, (intptr_t)pollset);
       GPR_TIMER_BEGIN("maybe_work_and_unlock", 0);
-      pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, worker,
+      pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, &worker,
                                              deadline, now);
       GPR_TIMER_END("maybe_work_and_unlock", 0);
       locked = 0;
@@ -332,10 +326,10 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
     /* If we're forced to re-evaluate polling (via grpc_pollset_kick with
        GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP) then we land here and force
        a loop */
-    if (worker->reevaluate_polling_on_wakeup) {
-      worker->reevaluate_polling_on_wakeup = 0;
+    if (worker.reevaluate_polling_on_wakeup) {
+      worker.reevaluate_polling_on_wakeup = 0;
       pollset->kicked_without_pollers = 0;
-      if (queued_work || worker->kicked_specifically) {
+      if (queued_work || worker.kicked_specifically) {
         /* If there's queued work on the list, then set the deadline to be
            immediate so we get back out of the polling loop quickly */
         deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
@@ -344,12 +338,12 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
     }
   }
   if (added_worker) {
-    remove_worker(pollset, worker);
+    remove_worker(pollset, &worker);
     gpr_tls_set(&g_current_thread_worker, 0);
   }
   /* release wakeup fd to the local pool */
-  worker->wakeup_fd->next = pollset->local_wakeup_cache;
-  pollset->local_wakeup_cache = worker->wakeup_fd;
+  worker.wakeup_fd->next = pollset->local_wakeup_cache;
+  pollset->local_wakeup_cache = worker.wakeup_fd;
   /* check shutdown conditions */
   if (pollset->shutting_down) {
     if (grpc_pollset_has_workers(pollset)) {
@@ -371,6 +365,7 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
       gpr_mu_lock(&pollset->mu);
     }
   }
+  *worker_hdl = NULL;
   GPR_TIMER_END("grpc_pollset_work", 0);
 }
 
diff --git a/src/core/iomgr/pollset_posix.h b/src/core/iomgr/pollset_posix.h
index 5868b3fa21ce175ca99af42a8178c50ce479f959..bbedb66b0076dbbeaf8a94dab07a5de90da5e931 100644
--- a/src/core/iomgr/pollset_posix.h
+++ b/src/core/iomgr/pollset_posix.h
@@ -37,8 +37,10 @@
 #include <poll.h>
 
 #include <grpc/support/sync.h>
+
 #include "src/core/iomgr/exec_ctx.h"
 #include "src/core/iomgr/iomgr.h"
+#include "src/core/iomgr/pollset.h"
 #include "src/core/iomgr/wakeup_fd_posix.h"
 
 typedef struct grpc_pollset_vtable grpc_pollset_vtable;
@@ -53,15 +55,15 @@ typedef struct grpc_cached_wakeup_fd {
   struct grpc_cached_wakeup_fd *next;
 } grpc_cached_wakeup_fd;
 
-typedef struct grpc_pollset_worker {
+struct grpc_pollset_worker {
   grpc_cached_wakeup_fd *wakeup_fd;
   int reevaluate_polling_on_wakeup;
   int kicked_specifically;
   struct grpc_pollset_worker *next;
   struct grpc_pollset_worker *prev;
-} grpc_pollset_worker;
+};
 
-typedef struct grpc_pollset {
+struct grpc_pollset {
   /* pollsets under posix can mutate representation as fds are added and
      removed.
      For example, we may choose a poll() based implementation on linux for
@@ -81,7 +83,7 @@ typedef struct grpc_pollset {
   } data;
   /* Local cache of eventfds for workers */
   grpc_cached_wakeup_fd *local_wakeup_cache;
-} grpc_pollset;
+};
 
 struct grpc_pollset_vtable {
   void (*add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
@@ -93,8 +95,6 @@ struct grpc_pollset_vtable {
   void (*destroy)(grpc_pollset *pollset);
 };
 
-#define GRPC_POLLSET_MU(pollset) (&(pollset)->mu)
-
 /* Add an fd to a pollset */
 void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                          struct grpc_fd *fd);
diff --git a/src/core/iomgr/pollset_set.h b/src/core/iomgr/pollset_set.h
index 09c04438f71e5aa98f3aa6866fd796ed8debc6bf..dddcd8313f220a63ba0c934b69f2fd53b1026e33 100644
--- a/src/core/iomgr/pollset_set.h
+++ b/src/core/iomgr/pollset_set.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,15 +41,9 @@
    fd's (etc) that have been registered with the set_set to that pollset.
    Registering fd's automatically adds them to all current pollsets. */
 
-#ifdef GPR_POSIX_SOCKET
-#include "src/core/iomgr/pollset_set_posix.h"
-#endif
+typedef struct grpc_pollset_set grpc_pollset_set;
 
-#ifdef GPR_WIN32
-#include "src/core/iomgr/pollset_set_windows.h"
-#endif
-
-void grpc_pollset_set_init(grpc_pollset_set *pollset_set);
+grpc_pollset_set *grpc_pollset_set_create(void);
 void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set);
 void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
                                   grpc_pollset_set *pollset_set,
diff --git a/src/core/iomgr/pollset_set_posix.c b/src/core/iomgr/pollset_set_posix.c
index 4ec92202e30d3cc30bb3d69c21b026f58987934f..9dc9aff4a8d511b5ec6915c8c130dfa208243a26 100644
--- a/src/core/iomgr/pollset_set_posix.c
+++ b/src/core/iomgr/pollset_set_posix.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,11 +41,30 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/iomgr/pollset_set.h"
+#include "src/core/iomgr/pollset_posix.h"
+#include "src/core/iomgr/pollset_set_posix.h"
 
-void grpc_pollset_set_init(grpc_pollset_set *pollset_set) {
+struct grpc_pollset_set {
+  gpr_mu mu;
+
+  size_t pollset_count;
+  size_t pollset_capacity;
+  grpc_pollset **pollsets;
+
+  size_t pollset_set_count;
+  size_t pollset_set_capacity;
+  struct grpc_pollset_set **pollset_sets;
+
+  size_t fd_count;
+  size_t fd_capacity;
+  grpc_fd **fds;
+};
+
+grpc_pollset_set *grpc_pollset_set_create(void) {
+  grpc_pollset_set *pollset_set = gpr_malloc(sizeof(*pollset_set));
   memset(pollset_set, 0, sizeof(*pollset_set));
   gpr_mu_init(&pollset_set->mu);
+  return pollset_set;
 }
 
 void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) {
@@ -57,6 +76,7 @@ void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) {
   gpr_free(pollset_set->pollsets);
   gpr_free(pollset_set->pollset_sets);
   gpr_free(pollset_set->fds);
+  gpr_free(pollset_set);
 }
 
 void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/iomgr/pollset_set_posix.h b/src/core/iomgr/pollset_set_posix.h
index 4820a61e4b29d05140b5bba753e7c37cfcd4f437..7d1aaf41817fe3845c1697f44cd1025492992691 100644
--- a/src/core/iomgr/pollset_set_posix.h
+++ b/src/core/iomgr/pollset_set_posix.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,23 +35,7 @@
 #define GRPC_INTERNAL_CORE_IOMGR_POLLSET_SET_POSIX_H
 
 #include "src/core/iomgr/fd_posix.h"
-#include "src/core/iomgr/pollset_posix.h"
-
-typedef struct grpc_pollset_set {
-  gpr_mu mu;
-
-  size_t pollset_count;
-  size_t pollset_capacity;
-  grpc_pollset **pollsets;
-
-  size_t pollset_set_count;
-  size_t pollset_set_capacity;
-  struct grpc_pollset_set **pollset_sets;
-
-  size_t fd_count;
-  size_t fd_capacity;
-  grpc_fd **fds;
-} grpc_pollset_set;
+#include "src/core/iomgr/pollset_set.h"
 
 void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx,
                              grpc_pollset_set *pollset_set, grpc_fd *fd);
diff --git a/src/core/iomgr/pollset_set_windows.c b/src/core/iomgr/pollset_set_windows.c
index 157b46ec32a6a1b05c9546e61a88895b4f9365df..3b8eca28e61f75e09fb26ab73d37b04e083beb7f 100644
--- a/src/core/iomgr/pollset_set_windows.c
+++ b/src/core/iomgr/pollset_set_windows.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,9 +35,9 @@
 
 #ifdef GPR_WINSOCK_SOCKET
 
-#include "src/core/iomgr/pollset_set.h"
+#include "src/core/iomgr/pollset_set_windows.h"
 
-void grpc_pollset_set_init(grpc_pollset_set* pollset_set) {}
+grpc_pollset_set* grpc_pollset_set_create(pollset_set) { return NULL; }
 
 void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {}
 
diff --git a/src/core/iomgr/pollset_set_windows.h b/src/core/iomgr/pollset_set_windows.h
index cada0d2b61f213597018b8fc2f35662187ffc2a0..9661cd2c3987223efbbe44f0f5a0ff2abc4425c9 100644
--- a/src/core/iomgr/pollset_set_windows.h
+++ b/src/core/iomgr/pollset_set_windows.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,6 @@
 #ifndef GRPC_INTERNAL_CORE_IOMGR_POLLSET_SET_WINDOWS_H
 #define GRPC_INTERNAL_CORE_IOMGR_POLLSET_SET_WINDOWS_H
 
-typedef struct grpc_pollset_set { void *unused; } grpc_pollset_set;
+#include "src/core/iomgr/pollset_set.h"
 
 #endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_WINDOWS_H */
diff --git a/src/core/iomgr/pollset_windows.c b/src/core/iomgr/pollset_windows.c
index 02c667836316a41f4bff83197653ca5c6f4ca653..c7f30f435fab7ed5bb42b893f885a018b87bf09d 100644
--- a/src/core/iomgr/pollset_windows.c
+++ b/src/core/iomgr/pollset_windows.c
@@ -38,7 +38,6 @@
 #include <grpc/support/log.h>
 #include <grpc/support/thd.h>
 
-#include "src/core/iomgr/timer_internal.h"
 #include "src/core/iomgr/iomgr_internal.h"
 #include "src/core/iomgr/iocp_windows.h"
 #include "src/core/iomgr/pollset.h"
@@ -90,12 +89,15 @@ static void push_front_worker(grpc_pollset_worker *root,
       worker->links[type].next->links[type].prev = worker;
 }
 
+size_t grpc_pollset_size(void) { return sizeof(grpc_pollset); }
+
 /* There isn't really any such thing as a pollset under Windows, due to the
    nature of the IO completion ports. We're still going to provide a minimal
    set of features for the sake of the rest of grpc. But grpc_pollset_work
    won't actually do any polling, and return as quickly as possible. */
 
-void grpc_pollset_init(grpc_pollset *pollset) {
+void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
+  *mu = &grpc_polling_mu;
   memset(pollset, 0, sizeof(*pollset));
   pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next =
       pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev =
@@ -126,25 +128,25 @@ void grpc_pollset_reset(grpc_pollset *pollset) {
 }
 
 void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
-                       grpc_pollset_worker *worker, gpr_timespec now,
+                       grpc_pollset_worker **worker_hdl, gpr_timespec now,
                        gpr_timespec deadline) {
+  grpc_pollset_worker worker;
+  *worker_hdl = &worker;
+
   int added_worker = 0;
-  worker->links[GRPC_POLLSET_WORKER_LINK_POLLSET].next =
-      worker->links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev =
-          worker->links[GRPC_POLLSET_WORKER_LINK_GLOBAL].next =
-              worker->links[GRPC_POLLSET_WORKER_LINK_GLOBAL].prev = NULL;
-  worker->kicked = 0;
-  worker->pollset = pollset;
-  gpr_cv_init(&worker->cv);
-  if (grpc_timer_check(exec_ctx, now, &deadline)) {
-    goto done;
-  }
+  worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next =
+      worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev =
+          worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].next =
+              worker.links[GRPC_POLLSET_WORKER_LINK_GLOBAL].prev = NULL;
+  worker.kicked = 0;
+  worker.pollset = pollset;
+  gpr_cv_init(&worker.cv);
   if (!pollset->kicked_without_pollers && !pollset->shutting_down) {
     if (g_active_poller == NULL) {
       grpc_pollset_worker *next_worker;
       /* become poller */
       pollset->is_iocp_worker = 1;
-      g_active_poller = worker;
+      g_active_poller = &worker;
       gpr_mu_unlock(&grpc_polling_mu);
       grpc_iocp_work(exec_ctx, deadline);
       grpc_exec_ctx_flush(exec_ctx);
@@ -171,12 +173,12 @@ void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
       goto done;
     }
     push_front_worker(&g_global_root_worker, GRPC_POLLSET_WORKER_LINK_GLOBAL,
-                      worker);
+                      &worker);
     push_front_worker(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET,
-                      worker);
+                      &worker);
     added_worker = 1;
-    while (!worker->kicked) {
-      if (gpr_cv_wait(&worker->cv, &grpc_polling_mu, deadline)) {
+    while (!worker.kicked) {
+      if (gpr_cv_wait(&worker.cv, &grpc_polling_mu, deadline)) {
         break;
       }
     }
@@ -190,10 +192,11 @@ done:
     gpr_mu_lock(&grpc_polling_mu);
   }
   if (added_worker) {
-    remove_worker(worker, GRPC_POLLSET_WORKER_LINK_GLOBAL);
-    remove_worker(worker, GRPC_POLLSET_WORKER_LINK_POLLSET);
+    remove_worker(&worker, GRPC_POLLSET_WORKER_LINK_GLOBAL);
+    remove_worker(&worker, GRPC_POLLSET_WORKER_LINK_POLLSET);
   }
-  gpr_cv_destroy(&worker->cv);
+  gpr_cv_destroy(&worker.cv);
+  *worker_hdl = NULL;
 }
 
 void grpc_pollset_kick(grpc_pollset *p, grpc_pollset_worker *specific_worker) {
diff --git a/src/core/iomgr/pollset_windows.h b/src/core/iomgr/pollset_windows.h
index 65ba80619b77437fa8f263d2fb5bf9966c22449d..dc0b7a4104bd8ada3c4d0301044465d1e3e204fc 100644
--- a/src/core/iomgr/pollset_windows.h
+++ b/src/core/iomgr/pollset_windows.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -72,8 +72,4 @@ struct grpc_pollset {
   grpc_closure *on_shutdown;
 };
 
-extern gpr_mu grpc_polling_mu;
-
-#define GRPC_POLLSET_MU(pollset) (&grpc_polling_mu)
-
 #endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_WINDOWS_H */
diff --git a/src/core/iomgr/tcp_client_posix.c b/src/core/iomgr/tcp_client_posix.c
index c76c2e3b0f2cd7d836c0665523677ef293cf3db6..15727856abf918f031bc5594ac11bba157618e8b 100644
--- a/src/core/iomgr/tcp_client_posix.c
+++ b/src/core/iomgr/tcp_client_posix.c
@@ -42,17 +42,19 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "src/core/iomgr/timer.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
+
 #include "src/core/iomgr/iomgr_posix.h"
 #include "src/core/iomgr/pollset_posix.h"
+#include "src/core/iomgr/pollset_set_posix.h"
 #include "src/core/iomgr/sockaddr_utils.h"
 #include "src/core/iomgr/socket_utils_posix.h"
 #include "src/core/iomgr/tcp_posix.h"
+#include "src/core/iomgr/timer.h"
 #include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/time.h>
 
 extern int grpc_tcp_trace;
 
diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c
index 048e90744121fdb1470df7a9a1b059d9ab97a152..f74eb3fe5115110de299526f808245a02c9ead10 100644
--- a/src/core/iomgr/tcp_posix.c
+++ b/src/core/iomgr/tcp_posix.c
@@ -40,8 +40,8 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #include <grpc/support/alloc.h>
@@ -51,9 +51,11 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 
-#include "src/core/support/string.h"
 #include "src/core/debug/trace.h"
+#include "src/core/iomgr/pollset_posix.h"
+#include "src/core/iomgr/pollset_set_posix.h"
 #include "src/core/profiling/timers.h"
+#include "src/core/support/string.h"
 
 #ifdef GPR_HAVE_MSG_NOSIGNAL
 #define SENDMSG_FLAGS MSG_NOSIGNAL
diff --git a/src/core/iomgr/timer.c b/src/core/iomgr/timer.c
index a33d8f63a05bb1bf687407468d714b23a6de5fb1..8379fffad02342a9df2f14801ec6d9ef4acab053 100644
--- a/src/core/iomgr/timer.c
+++ b/src/core/iomgr/timer.c
@@ -34,7 +34,6 @@
 #include "src/core/iomgr/timer.h"
 
 #include "src/core/iomgr/timer_heap.h"
-#include "src/core/iomgr/timer_internal.h"
 #include "src/core/iomgr/time_averaged_stats.h"
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
@@ -336,8 +335,8 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
   return (int)n;
 }
 
-int grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
-                     gpr_timespec *next) {
+bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
+                      gpr_timespec *next) {
   GPR_ASSERT(now.clock_type == g_clock_type);
   return run_some_expired_timers(
       exec_ctx, now, next,
diff --git a/src/core/iomgr/timer.h b/src/core/iomgr/timer.h
index 720c9d5ab9444f886b34ed72bdff786faea7f8f3..9ad1e92f42e4cc16ee2404b850f65953d7b7a609 100644
--- a/src/core/iomgr/timer.h
+++ b/src/core/iomgr/timer.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -86,4 +86,24 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
    Requires:  cancel() must happen after add() on a given timer */
 void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer);
 
+/* iomgr internal api for dealing with timers */
+
+/* Check for timers to be run, and run them.
+   Return true if timer callbacks were executed.
+   Drops drop_mu if it is non-null before executing callbacks.
+   If next is non-null, TRY to update *next with the next running timer
+   IF that timer occurs before *next current value.
+   *next is never guaranteed to be updated on any given execution; however,
+   with high probability at least one thread in the system will see an update
+   at any time slice. */
+
+bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
+                      gpr_timespec *next);
+void grpc_timer_list_init(gpr_timespec now);
+void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx);
+
+/* the following must be implemented by each iomgr implementation */
+
+void grpc_kick_poller(void);
+
 #endif /* GRPC_INTERNAL_CORE_IOMGR_TIMER_H */
diff --git a/src/core/iomgr/timer_heap.c b/src/core/iomgr/timer_heap.c
index 9d8be5c1fcb56b7a0818081c5fd50e932ecbad83..b5df566c453d3ee606af96bc35f3d2e7fd8f185e 100644
--- a/src/core/iomgr/timer_heap.c
+++ b/src/core/iomgr/timer_heap.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,7 @@
 static void adjust_upwards(grpc_timer **first, uint32_t i, grpc_timer *t) {
   while (i > 0) {
     uint32_t parent = (uint32_t)(((int)i - 1) / 2);
-    if (gpr_time_cmp(first[parent]->deadline, t->deadline) >= 0) break;
+    if (gpr_time_cmp(first[parent]->deadline, t->deadline) <= 0) break;
     first[i] = first[parent];
     first[i]->heap_index = i;
     i = parent;
@@ -62,16 +62,14 @@ static void adjust_downwards(grpc_timer **first, uint32_t i, uint32_t length,
                              grpc_timer *t) {
   for (;;) {
     uint32_t left_child = 1u + 2u * i;
-    uint32_t right_child;
-    uint32_t next_i;
     if (left_child >= length) break;
-    right_child = left_child + 1;
-    next_i = right_child < length &&
-                     gpr_time_cmp(first[left_child]->deadline,
-                                  first[right_child]->deadline) < 0
-                 ? right_child
-                 : left_child;
-    if (gpr_time_cmp(t->deadline, first[next_i]->deadline) >= 0) break;
+    uint32_t right_child = left_child + 1;
+    uint32_t next_i = right_child < length &&
+                              gpr_time_cmp(first[left_child]->deadline,
+                                           first[right_child]->deadline) > 0
+                          ? right_child
+                          : left_child;
+    if (gpr_time_cmp(t->deadline, first[next_i]->deadline) <= 0) break;
     first[i] = first[next_i];
     first[i]->heap_index = i;
     i = next_i;
@@ -95,7 +93,7 @@ static void maybe_shrink(grpc_timer_heap *heap) {
 static void note_changed_priority(grpc_timer_heap *heap, grpc_timer *timer) {
   uint32_t i = timer->heap_index;
   uint32_t parent = (uint32_t)(((int)i - 1) / 2);
-  if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) < 0) {
+  if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) > 0) {
     adjust_upwards(heap->timers, i, timer);
   } else {
     adjust_downwards(heap->timers, i, heap->timer_count, timer);
diff --git a/src/core/iomgr/timer_internal.h b/src/core/iomgr/timer_internal.h
deleted file mode 100644
index f182e737646276dae0661b59b5b1e984e165c9bc..0000000000000000000000000000000000000000
--- a/src/core/iomgr/timer_internal.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *
- * Copyright 2015, 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_INTERNAL_CORE_IOMGR_TIMER_INTERNAL_H
-#define GRPC_INTERNAL_CORE_IOMGR_TIMER_INTERNAL_H
-
-#include "src/core/iomgr/exec_ctx.h"
-#include <grpc/support/sync.h>
-#include <grpc/support/time.h>
-
-/* iomgr internal api for dealing with timers */
-
-/* Check for timers to be run, and run them.
-   Return non zero if timer callbacks were executed.
-   Drops drop_mu if it is non-null before executing callbacks.
-   If next is non-null, TRY to update *next with the next running timer
-   IF that timer occurs before *next current value.
-   *next is never guaranteed to be updated on any given execution; however,
-   with high probability at least one thread in the system will see an update
-   at any time slice. */
-
-int grpc_timer_check(grpc_exec_ctx* exec_ctx, gpr_timespec now,
-                     gpr_timespec* next);
-void grpc_timer_list_init(gpr_timespec now);
-void grpc_timer_list_shutdown(grpc_exec_ctx* exec_ctx);
-
-/* the following must be implemented by each iomgr implementation */
-
-void grpc_kick_poller(void);
-
-#endif /* GRPC_INTERNAL_CORE_IOMGR_TIMER_INTERNAL_H */
diff --git a/src/core/iomgr/udp_server.h b/src/core/iomgr/udp_server.h
index 73a21c80ab46d990c4e34ade96cec51a088cec21..a9d0489edfd13b44cabfc11e7a111b6f7a01c26f 100644
--- a/src/core/iomgr/udp_server.h
+++ b/src/core/iomgr/udp_server.h
@@ -35,6 +35,7 @@
 #define GRPC_INTERNAL_CORE_IOMGR_UDP_SERVER_H
 
 #include "src/core/iomgr/endpoint.h"
+#include "src/core/iomgr/fd_posix.h"
 
 /* Forward decl of grpc_server */
 typedef struct grpc_server grpc_server;
diff --git a/src/core/iomgr/workqueue_posix.c b/src/core/iomgr/workqueue_posix.c
index da11df67efba9e83f5ad221cb1abc292c2e789e5..c096dbfb30caff8166ea24abd6779bcd809aa615 100644
--- a/src/core/iomgr/workqueue_posix.c
+++ b/src/core/iomgr/workqueue_posix.c
@@ -44,6 +44,7 @@
 #include <grpc/support/useful.h>
 
 #include "src/core/iomgr/fd_posix.h"
+#include "src/core/iomgr/pollset_posix.h"
 
 static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success);
 
diff --git a/src/core/iomgr/workqueue_posix.h b/src/core/iomgr/workqueue_posix.h
index 589034fe1bb502a6a9c352480707b11de8ec41a5..68f195ee0d266892e0a39836e2cf4a30644761f6 100644
--- a/src/core/iomgr/workqueue_posix.h
+++ b/src/core/iomgr/workqueue_posix.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,8 @@
 #ifndef GRPC_INTERNAL_CORE_IOMGR_WORKQUEUE_POSIX_H
 #define GRPC_INTERNAL_CORE_IOMGR_WORKQUEUE_POSIX_H
 
+#include "src/core/iomgr/wakeup_fd_posix.h"
+
 struct grpc_fd;
 
 struct grpc_workqueue {
diff --git a/src/core/proto/grpc/lb/v0/load_balancer.pb.c b/src/core/proto/grpc/lb/v0/load_balancer.pb.c
new file mode 100644
index 0000000000000000000000000000000000000000..59aae30cff97c35d1b98b7bb7613199b53c725f7
--- /dev/null
+++ b/src/core/proto/grpc/lb/v0/load_balancer.pb.c
@@ -0,0 +1,119 @@
+/*
+ *
+ * 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.
+ *
+ */
+/* Automatically generated nanopb constant definitions */
+/* Generated by nanopb-0.3.5-dev */
+
+#include "src/core/proto/grpc/lb/v0/load_balancer.pb.h"
+
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+
+
+const pb_field_t grpc_lb_v0_Duration_fields[3] = {
+    PB_FIELD(  1, INT64   , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_Duration, seconds, seconds, 0),
+    PB_FIELD(  2, INT32   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Duration, nanos, seconds, 0),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_LoadBalanceRequest_fields[3] = {
+    PB_FIELD(  1, MESSAGE , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_LoadBalanceRequest, initial_request, initial_request, &grpc_lb_v0_InitialLoadBalanceRequest_fields),
+    PB_FIELD(  2, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_LoadBalanceRequest, client_stats, initial_request, &grpc_lb_v0_ClientStats_fields),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_InitialLoadBalanceRequest_fields[2] = {
+    PB_FIELD(  1, STRING  , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_InitialLoadBalanceRequest, name, name, 0),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_ClientStats_fields[4] = {
+    PB_FIELD(  1, INT64   , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_ClientStats, total_requests, total_requests, 0),
+    PB_FIELD(  2, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_ClientStats, client_rpc_errors, total_requests, 0),
+    PB_FIELD(  3, INT64   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_ClientStats, dropped_requests, client_rpc_errors, 0),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_LoadBalanceResponse_fields[3] = {
+    PB_FIELD(  1, MESSAGE , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_LoadBalanceResponse, initial_response, initial_response, &grpc_lb_v0_InitialLoadBalanceResponse_fields),
+    PB_FIELD(  2, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_LoadBalanceResponse, server_list, initial_response, &grpc_lb_v0_ServerList_fields),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_InitialLoadBalanceResponse_fields[4] = {
+    PB_FIELD(  1, STRING  , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_InitialLoadBalanceResponse, client_config, client_config, 0),
+    PB_FIELD(  2, STRING  , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_InitialLoadBalanceResponse, load_balancer_delegate, client_config, 0),
+    PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval, load_balancer_delegate, &grpc_lb_v0_Duration_fields),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_ServerList_fields[3] = {
+    PB_FIELD(  1, MESSAGE , REPEATED, CALLBACK, FIRST, grpc_lb_v0_ServerList, servers, servers, &grpc_lb_v0_Server_fields),
+    PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_ServerList, expiration_interval, servers, &grpc_lb_v0_Duration_fields),
+    PB_LAST_FIELD
+};
+
+const pb_field_t grpc_lb_v0_Server_fields[5] = {
+    PB_FIELD(  1, STRING  , OPTIONAL, STATIC  , FIRST, grpc_lb_v0_Server, ip_address, ip_address, 0),
+    PB_FIELD(  2, INT32   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Server, port, ip_address, 0),
+    PB_FIELD(  3, BYTES   , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Server, load_balance_token, port, 0),
+    PB_FIELD(  4, BOOL    , OPTIONAL, STATIC  , OTHER, grpc_lb_v0_Server, drop_request, load_balance_token, 0),
+    PB_LAST_FIELD
+};
+
+
+/* Check that field information fits in pb_field_t */
+#if !defined(PB_FIELD_32BIT)
+/* If you get an error here, it means that you need to define PB_FIELD_32BIT
+ * compile-time option. You can do that in pb.h or on compiler command line.
+ * 
+ * The reason you need to do this is that some of your messages contain tag
+ * numbers or field sizes that are larger than what can fit in 8 or 16 bit
+ * field descriptors.
+ */
+PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 65536 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 65536 && pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval) < 65536 && pb_membersize(grpc_lb_v0_ServerList, servers) < 65536 && pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server)
+#endif
+
+#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
+/* If you get an error here, it means that you need to define PB_FIELD_16BIT
+ * compile-time option. You can do that in pb.h or on compiler command line.
+ * 
+ * The reason you need to do this is that some of your messages contain tag
+ * numbers or field sizes that are larger than what can fit in the default
+ * 8 bit descriptors.
+ */
+PB_STATIC_ASSERT((pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v0_ServerList, servers) < 256 && pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server)
+#endif
+
+
diff --git a/src/core/proto/grpc/lb/v0/load_balancer.pb.h b/src/core/proto/grpc/lb/v0/load_balancer.pb.h
new file mode 100644
index 0000000000000000000000000000000000000000..3599f881bb17e328389f01ce9493cd42f4184490
--- /dev/null
+++ b/src/core/proto/grpc/lb/v0/load_balancer.pb.h
@@ -0,0 +1,182 @@
+/*
+ *
+ * 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.
+ *
+ */
+/* Automatically generated nanopb header */
+/* Generated by nanopb-0.3.5-dev */
+
+#ifndef PB_LOAD_BALANCER_PB_H_INCLUDED
+#define PB_LOAD_BALANCER_PB_H_INCLUDED
+#include "third_party/nanopb/pb.h"
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Struct definitions */
+typedef struct _grpc_lb_v0_ClientStats {
+    bool has_total_requests;
+    int64_t total_requests;
+    bool has_client_rpc_errors;
+    int64_t client_rpc_errors;
+    bool has_dropped_requests;
+    int64_t dropped_requests;
+} grpc_lb_v0_ClientStats;
+
+typedef struct _grpc_lb_v0_Duration {
+    bool has_seconds;
+    int64_t seconds;
+    bool has_nanos;
+    int32_t nanos;
+} grpc_lb_v0_Duration;
+
+typedef struct _grpc_lb_v0_InitialLoadBalanceRequest {
+    bool has_name;
+    char name[128];
+} grpc_lb_v0_InitialLoadBalanceRequest;
+
+typedef PB_BYTES_ARRAY_T(64) grpc_lb_v0_Server_load_balance_token_t;
+typedef struct _grpc_lb_v0_Server {
+    bool has_ip_address;
+    char ip_address[46];
+    bool has_port;
+    int32_t port;
+    bool has_load_balance_token;
+    grpc_lb_v0_Server_load_balance_token_t load_balance_token;
+    bool has_drop_request;
+    bool drop_request;
+} grpc_lb_v0_Server;
+
+typedef struct _grpc_lb_v0_InitialLoadBalanceResponse {
+    bool has_client_config;
+    char client_config[64];
+    bool has_load_balancer_delegate;
+    char load_balancer_delegate[64];
+    bool has_client_stats_report_interval;
+    grpc_lb_v0_Duration client_stats_report_interval;
+} grpc_lb_v0_InitialLoadBalanceResponse;
+
+typedef struct _grpc_lb_v0_LoadBalanceRequest {
+    bool has_initial_request;
+    grpc_lb_v0_InitialLoadBalanceRequest initial_request;
+    bool has_client_stats;
+    grpc_lb_v0_ClientStats client_stats;
+} grpc_lb_v0_LoadBalanceRequest;
+
+typedef struct _grpc_lb_v0_ServerList {
+    pb_callback_t servers;
+    bool has_expiration_interval;
+    grpc_lb_v0_Duration expiration_interval;
+} grpc_lb_v0_ServerList;
+
+typedef struct _grpc_lb_v0_LoadBalanceResponse {
+    bool has_initial_response;
+    grpc_lb_v0_InitialLoadBalanceResponse initial_response;
+    bool has_server_list;
+    grpc_lb_v0_ServerList server_list;
+} grpc_lb_v0_LoadBalanceResponse;
+
+/* Default values for struct fields */
+
+/* Initializer values for message structs */
+#define grpc_lb_v0_Duration_init_default         {false, 0, false, 0}
+#define grpc_lb_v0_LoadBalanceRequest_init_default {false, grpc_lb_v0_InitialLoadBalanceRequest_init_default, false, grpc_lb_v0_ClientStats_init_default}
+#define grpc_lb_v0_InitialLoadBalanceRequest_init_default {false, ""}
+#define grpc_lb_v0_ClientStats_init_default      {false, 0, false, 0, false, 0}
+#define grpc_lb_v0_LoadBalanceResponse_init_default {false, grpc_lb_v0_InitialLoadBalanceResponse_init_default, false, grpc_lb_v0_ServerList_init_default}
+#define grpc_lb_v0_InitialLoadBalanceResponse_init_default {false, "", false, "", false, grpc_lb_v0_Duration_init_default}
+#define grpc_lb_v0_ServerList_init_default       {{{NULL}, NULL}, false, grpc_lb_v0_Duration_init_default}
+#define grpc_lb_v0_Server_init_default           {false, "", false, 0, false, {0, {0}}, false, 0}
+#define grpc_lb_v0_Duration_init_zero            {false, 0, false, 0}
+#define grpc_lb_v0_LoadBalanceRequest_init_zero  {false, grpc_lb_v0_InitialLoadBalanceRequest_init_zero, false, grpc_lb_v0_ClientStats_init_zero}
+#define grpc_lb_v0_InitialLoadBalanceRequest_init_zero {false, ""}
+#define grpc_lb_v0_ClientStats_init_zero         {false, 0, false, 0, false, 0}
+#define grpc_lb_v0_LoadBalanceResponse_init_zero {false, grpc_lb_v0_InitialLoadBalanceResponse_init_zero, false, grpc_lb_v0_ServerList_init_zero}
+#define grpc_lb_v0_InitialLoadBalanceResponse_init_zero {false, "", false, "", false, grpc_lb_v0_Duration_init_zero}
+#define grpc_lb_v0_ServerList_init_zero          {{{NULL}, NULL}, false, grpc_lb_v0_Duration_init_zero}
+#define grpc_lb_v0_Server_init_zero              {false, "", false, 0, false, {0, {0}}, false, 0}
+
+/* Field tags (for use in manual encoding/decoding) */
+#define grpc_lb_v0_ClientStats_total_requests_tag 1
+#define grpc_lb_v0_ClientStats_client_rpc_errors_tag 2
+#define grpc_lb_v0_ClientStats_dropped_requests_tag 3
+#define grpc_lb_v0_Duration_seconds_tag          1
+#define grpc_lb_v0_Duration_nanos_tag            2
+#define grpc_lb_v0_InitialLoadBalanceRequest_name_tag 1
+#define grpc_lb_v0_Server_ip_address_tag         1
+#define grpc_lb_v0_Server_port_tag               2
+#define grpc_lb_v0_Server_load_balance_token_tag 3
+#define grpc_lb_v0_Server_drop_request_tag       4
+#define grpc_lb_v0_InitialLoadBalanceResponse_client_config_tag 1
+#define grpc_lb_v0_InitialLoadBalanceResponse_load_balancer_delegate_tag 2
+#define grpc_lb_v0_InitialLoadBalanceResponse_client_stats_report_interval_tag 3
+#define grpc_lb_v0_LoadBalanceRequest_initial_request_tag 1
+#define grpc_lb_v0_LoadBalanceRequest_client_stats_tag 2
+#define grpc_lb_v0_ServerList_servers_tag        1
+#define grpc_lb_v0_ServerList_expiration_interval_tag 3
+#define grpc_lb_v0_LoadBalanceResponse_initial_response_tag 1
+#define grpc_lb_v0_LoadBalanceResponse_server_list_tag 2
+
+/* Struct field encoding specification for nanopb */
+extern const pb_field_t grpc_lb_v0_Duration_fields[3];
+extern const pb_field_t grpc_lb_v0_LoadBalanceRequest_fields[3];
+extern const pb_field_t grpc_lb_v0_InitialLoadBalanceRequest_fields[2];
+extern const pb_field_t grpc_lb_v0_ClientStats_fields[4];
+extern const pb_field_t grpc_lb_v0_LoadBalanceResponse_fields[3];
+extern const pb_field_t grpc_lb_v0_InitialLoadBalanceResponse_fields[4];
+extern const pb_field_t grpc_lb_v0_ServerList_fields[3];
+extern const pb_field_t grpc_lb_v0_Server_fields[5];
+
+/* Maximum encoded size of messages (where known) */
+#define grpc_lb_v0_Duration_size                 22
+#define grpc_lb_v0_LoadBalanceRequest_size       169
+#define grpc_lb_v0_InitialLoadBalanceRequest_size 131
+#define grpc_lb_v0_ClientStats_size              33
+#define grpc_lb_v0_LoadBalanceResponse_size      (165 + grpc_lb_v0_ServerList_size)
+#define grpc_lb_v0_InitialLoadBalanceResponse_size 156
+#define grpc_lb_v0_Server_size                   127
+
+/* Message IDs (where set with "msgid" option) */
+#ifdef PB_MSGID
+
+#define LOAD_BALANCER_MESSAGES \
+
+
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/src/core/security/base64.c b/src/core/security/b64.c
similarity index 99%
rename from src/core/security/base64.c
rename to src/core/security/b64.c
index 8367c160c3672f877033ddf195375a0109687623..c40b528e2f56650876d66e285b7be3acb5e6f606 100644
--- a/src/core/security/base64.c
+++ b/src/core/security/b64.c
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/security/base64.h"
+#include "src/core/security/b64.h"
 
 #include <stdint.h>
 #include <string.h>
diff --git a/src/core/security/base64.h b/src/core/security/b64.h
similarity index 98%
rename from src/core/security/base64.h
rename to src/core/security/b64.h
index 31ae982691affe1e2f01b35df1b89aea63ec8fdc..3e3b52112093c6fcc1426c982e31fbc646ff904f 100644
--- a/src/core/security/base64.h
+++ b/src/core/security/b64.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
index 57b367d00fffee7121de1207ce922155c3021e33..332d4259d2843fee3f8cf013339beb83f1859c6f 100644
--- a/src/core/security/client_auth_filter.c
+++ b/src/core/security/client_auth_filter.c
@@ -310,7 +310,6 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
   GPR_ASSERT(auth_context != NULL);
 
   /* initialize members */
-  GPR_ASSERT(sc->is_client_side);
   chand->security_connector =
       (grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF(
           sc, "client_auth_filter");
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index c58574bd6d86ba3f416124be6f38ac5f2a75fecc..b4fa616fa7ebe955ebd180f4f16e028bf9c44035 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -166,7 +166,7 @@ void grpc_server_credentials_release(grpc_server_credentials *creds) {
 }
 
 grpc_security_status grpc_server_credentials_create_security_connector(
-    grpc_server_credentials *creds, grpc_security_connector **sc) {
+    grpc_server_credentials *creds, grpc_server_security_connector **sc) {
   if (creds == NULL || creds->vtable->create_security_connector == NULL) {
     gpr_log(GPR_ERROR, "Server credentials cannot create security context.");
     return GRPC_SECURITY_ERROR;
@@ -298,7 +298,7 @@ static grpc_security_status ssl_create_security_connector(
 }
 
 static grpc_security_status ssl_server_create_security_connector(
-    grpc_server_credentials *creds, grpc_security_connector **sc) {
+    grpc_server_credentials *creds, grpc_server_security_connector **sc) {
   grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
   return grpc_ssl_server_security_connector_create(&c->config, sc);
 }
@@ -894,7 +894,7 @@ static grpc_security_status fake_transport_security_create_security_connector(
 
 static grpc_security_status
 fake_transport_security_server_create_security_connector(
-    grpc_server_credentials *c, grpc_security_connector **sc) {
+    grpc_server_credentials *c, grpc_server_security_connector **sc) {
   *sc = grpc_fake_server_security_connector_create();
   return GRPC_SECURITY_OK;
 }
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 3cd652cd574db505e471c7f229e1430e28715bbc..0de4cd94689b2fb69c377c6febe13838fbb09705 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -234,7 +234,7 @@ grpc_refresh_token_credentials_create_from_auth_refresh_token(
 typedef struct {
   void (*destruct)(grpc_server_credentials *c);
   grpc_security_status (*create_security_connector)(
-      grpc_server_credentials *c, grpc_security_connector **sc);
+      grpc_server_credentials *c, grpc_server_security_connector **sc);
 } grpc_server_credentials_vtable;
 
 struct grpc_server_credentials {
@@ -245,7 +245,7 @@ struct grpc_server_credentials {
 };
 
 grpc_security_status grpc_server_credentials_create_security_connector(
-    grpc_server_credentials *creds, grpc_security_connector **sc);
+    grpc_server_credentials *creds, grpc_server_security_connector **sc);
 
 grpc_server_credentials *grpc_server_credentials_ref(
     grpc_server_credentials *creds);
diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c
index f3ac14568a636657f3577bcf8dfc7b8fe8d2d1eb..1f4f3e4aa52ef8dc3758db6dac08097859ad5560 100644
--- a/src/core/security/google_default_credentials.c
+++ b/src/core/security/google_default_credentials.c
@@ -41,7 +41,7 @@
 
 #include "src/core/httpcli/httpcli.h"
 #include "src/core/support/env.h"
-#include "src/core/support/file.h"
+#include "src/core/support/load_file.h"
 #include "src/core/surface/api_trace.h"
 
 /* -- Constants. -- */
@@ -52,13 +52,14 @@
 
 static grpc_channel_credentials *default_credentials = NULL;
 static int compute_engine_detection_done = 0;
-static gpr_mu g_mu;
+static gpr_mu g_state_mu;
+static gpr_mu *g_polling_mu;
 static gpr_once g_once = GPR_ONCE_INIT;
 
-static void init_default_credentials(void) { gpr_mu_init(&g_mu); }
+static void init_default_credentials(void) { gpr_mu_init(&g_state_mu); }
 
 typedef struct {
-  grpc_pollset pollset;
+  grpc_pollset *pollset;
   int is_done;
   int success;
 } compute_engine_detector;
@@ -80,10 +81,10 @@ static void on_compute_engine_detection_http_response(
       }
     }
   }
-  gpr_mu_lock(GRPC_POLLSET_MU(&detector->pollset));
+  gpr_mu_lock(g_polling_mu);
   detector->is_done = 1;
-  grpc_pollset_kick(&detector->pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&detector->pollset));
+  grpc_pollset_kick(detector->pollset, NULL);
+  gpr_mu_unlock(g_polling_mu);
 }
 
 static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool s) {
@@ -101,7 +102,8 @@ static int is_stack_running_on_compute_engine(void) {
      on compute engine. */
   gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN);
 
-  grpc_pollset_init(&detector.pollset);
+  detector.pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(detector.pollset, &g_polling_mu);
   detector.is_done = 0;
   detector.success = 0;
 
@@ -112,7 +114,7 @@ static int is_stack_running_on_compute_engine(void) {
   grpc_httpcli_context_init(&context);
 
   grpc_httpcli_get(
-      &exec_ctx, &context, &detector.pollset, &request,
+      &exec_ctx, &context, detector.pollset, &request,
       gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
       on_compute_engine_detection_http_response, &detector);
 
@@ -120,19 +122,22 @@ static int is_stack_running_on_compute_engine(void) {
 
   /* Block until we get the response. This is not ideal but this should only be
      called once for the lifetime of the process by the default credentials. */
-  gpr_mu_lock(GRPC_POLLSET_MU(&detector.pollset));
+  gpr_mu_lock(g_polling_mu);
   while (!detector.is_done) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &detector.pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, detector.pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       gpr_inf_future(GPR_CLOCK_MONOTONIC));
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&detector.pollset));
+  gpr_mu_unlock(g_polling_mu);
 
   grpc_httpcli_context_destroy(&context);
-  grpc_closure_init(&destroy_closure, destroy_pollset, &detector.pollset);
-  grpc_pollset_shutdown(&exec_ctx, &detector.pollset, &destroy_closure);
+  grpc_closure_init(&destroy_closure, destroy_pollset, detector.pollset);
+  grpc_pollset_shutdown(&exec_ctx, detector.pollset, &destroy_closure);
   grpc_exec_ctx_finish(&exec_ctx);
+  g_polling_mu = NULL;
+
+  gpr_free(detector.pollset);
 
   return detector.success;
 }
@@ -184,7 +189,7 @@ grpc_channel_credentials *grpc_google_default_credentials_create(void) {
 
   gpr_once_init(&g_once, init_default_credentials);
 
-  gpr_mu_lock(&g_mu);
+  gpr_mu_lock(&g_state_mu);
 
   if (default_credentials != NULL) {
     result = grpc_channel_credentials_ref(default_credentials);
@@ -230,19 +235,19 @@ end:
       gpr_log(GPR_ERROR, "Could not create google default credentials.");
     }
   }
-  gpr_mu_unlock(&g_mu);
+  gpr_mu_unlock(&g_state_mu);
   return result;
 }
 
 void grpc_flush_cached_google_default_credentials(void) {
   gpr_once_init(&g_once, init_default_credentials);
-  gpr_mu_lock(&g_mu);
+  gpr_mu_lock(&g_state_mu);
   if (default_credentials != NULL) {
     grpc_channel_credentials_unref(default_credentials);
     default_credentials = NULL;
   }
   compute_engine_detection_done = 0;
-  gpr_mu_unlock(&g_mu);
+  gpr_mu_unlock(&g_state_mu);
 }
 
 /* -- Well known credentials path. -- */
diff --git a/src/core/security/handshake.c b/src/core/security/handshake.c
index a8b2fef6297035c3a998c7bebb4850cebbce84d3..b5bb6667a71f075a7ec5c37a08c9d056c4f0ccf1 100644
--- a/src/core/security/handshake.c
+++ b/src/core/security/handshake.c
@@ -33,6 +33,7 @@
 
 #include "src/core/security/handshake.h"
 
+#include <stdbool.h>
 #include <string.h>
 
 #include "src/core/security/security_context.h"
@@ -46,6 +47,7 @@
 typedef struct {
   grpc_security_connector *connector;
   tsi_handshaker *handshaker;
+  bool is_client_side;
   unsigned char *handshake_buffer;
   size_t handshake_buffer_size;
   grpc_endpoint *wrapped_endpoint;
@@ -67,9 +69,11 @@ static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup,
                                            bool success);
 
 static void security_connector_remove_handshake(grpc_security_handshake *h) {
+  GPR_ASSERT(!h->is_client_side);
   grpc_security_connector_handshake_list *node;
   grpc_security_connector_handshake_list *tmp;
-  grpc_security_connector *sc = h->connector;
+  grpc_server_security_connector *sc =
+      (grpc_server_security_connector *)h->connector;
   gpr_mu_lock(&sc->mu);
   node = sc->handshaking_handshakes;
   if (node && node->handshake == h) {
@@ -94,7 +98,7 @@ static void security_connector_remove_handshake(grpc_security_handshake *h) {
 static void security_handshake_done(grpc_exec_ctx *exec_ctx,
                                     grpc_security_handshake *h,
                                     int is_success) {
-  if (!h->connector->is_client_side) {
+  if (!h->is_client_side) {
     security_connector_remove_handshake(h);
   }
   if (is_success) {
@@ -290,6 +294,7 @@ static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx,
 void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
                                 tsi_handshaker *handshaker,
                                 grpc_security_connector *connector,
+                                bool is_client_side,
                                 grpc_endpoint *nonsecure_endpoint,
                                 grpc_security_handshake_done_cb cb,
                                 void *user_data) {
@@ -298,6 +303,7 @@ void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
   memset(h, 0, sizeof(grpc_security_handshake));
   h->handshaker = handshaker;
   h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake");
+  h->is_client_side = is_client_side;
   h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
   h->handshake_buffer = gpr_malloc(h->handshake_buffer_size);
   h->wrapped_endpoint = nonsecure_endpoint;
@@ -310,13 +316,15 @@ void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
   gpr_slice_buffer_init(&h->left_overs);
   gpr_slice_buffer_init(&h->outgoing);
   gpr_slice_buffer_init(&h->incoming);
-  if (!connector->is_client_side) {
+  if (!is_client_side) {
+    grpc_server_security_connector *server_connector =
+        (grpc_server_security_connector *)connector;
     handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list));
     handshake_node->handshake = h;
-    gpr_mu_lock(&connector->mu);
-    handshake_node->next = connector->handshaking_handshakes;
-    connector->handshaking_handshakes = handshake_node;
-    gpr_mu_unlock(&connector->mu);
+    gpr_mu_lock(&server_connector->mu);
+    handshake_node->next = server_connector->handshaking_handshakes;
+    server_connector->handshaking_handshakes = handshake_node;
+    gpr_mu_unlock(&server_connector->mu);
   }
   send_handshake_bytes_to_peer(exec_ctx, h);
 }
diff --git a/src/core/security/handshake.h b/src/core/security/handshake.h
index 44215d16ef0e005ea881f587b7b5569d92d081d7..db8b3749215b95a1a79b0775d1a6e15d8e2eb64f 100644
--- a/src/core/security/handshake.h
+++ b/src/core/security/handshake.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,7 @@
 void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
                                 tsi_handshaker *handshaker,
                                 grpc_security_connector *connector,
+                                bool is_client_side,
                                 grpc_endpoint *nonsecure_endpoint,
                                 grpc_security_handshake_done_cb cb,
                                 void *user_data);
diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c
index 762f02989acc50d3382f9f0b330c70d7404f15dc..372e5bfc5aba3dca48031fd18dde37bcb92ef9d4 100644
--- a/src/core/security/json_token.c
+++ b/src/core/security/json_token.c
@@ -39,7 +39,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/security/base64.h"
+#include "src/core/security/b64.h"
 #include "src/core/support/string.h"
 
 #include <openssl/bio.h>
diff --git a/src/core/security/jwt_verifier.c b/src/core/security/jwt_verifier.c
index 042a117f5d74813ccc46b0fce113fe51ff76e80f..928c6c148dedc24d25a6a51b44ff9e5d7ca2721d 100644
--- a/src/core/security/jwt_verifier.c
+++ b/src/core/security/jwt_verifier.c
@@ -37,7 +37,7 @@
 #include <string.h>
 
 #include "src/core/httpcli/httpcli.h"
-#include "src/core/security/base64.h"
+#include "src/core/security/b64.h"
 #include "src/core/tsi/ssl_types.h"
 
 #include <grpc/support/alloc.h>
diff --git a/src/core/security/security_connector.c b/src/core/security/security_connector.c
index b46205323bf7f0d8a5405d7f303c9f9d107ed12b..33c62a20c2094fba3c0446d9233f8818f311c088 100644
--- a/src/core/security/security_connector.c
+++ b/src/core/security/security_connector.c
@@ -33,22 +33,23 @@
 
 #include "src/core/security/security_connector.h"
 
+#include <stdbool.h>
 #include <string.h>
 
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice_buffer.h>
+#include <grpc/support/string_util.h>
+
 #include "src/core/security/credentials.h"
 #include "src/core/security/handshake.h"
 #include "src/core/security/secure_endpoint.h"
 #include "src/core/security/security_context.h"
 #include "src/core/support/env.h"
-#include "src/core/support/file.h"
+#include "src/core/support/load_file.h"
 #include "src/core/support/string.h"
 #include "src/core/transport/chttp2/alpn.h"
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/support/string_util.h>
 #include "src/core/tsi/fake_transport_security.h"
 #include "src/core/tsi/ssl_transport_security.h"
 
@@ -110,31 +111,39 @@ const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
   return NULL;
 }
 
-void grpc_security_connector_shutdown(grpc_exec_ctx *exec_ctx,
-                                      grpc_security_connector *connector) {
+void grpc_server_security_connector_shutdown(
+    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector) {
   grpc_security_connector_handshake_list *tmp;
-  if (!connector->is_client_side) {
-    gpr_mu_lock(&connector->mu);
-    while (connector->handshaking_handshakes) {
-      tmp = connector->handshaking_handshakes;
-      grpc_security_handshake_shutdown(
-          exec_ctx, connector->handshaking_handshakes->handshake);
-      connector->handshaking_handshakes = tmp->next;
-      gpr_free(tmp);
-    }
-    gpr_mu_unlock(&connector->mu);
+  gpr_mu_lock(&connector->mu);
+  while (connector->handshaking_handshakes) {
+    tmp = connector->handshaking_handshakes;
+    grpc_security_handshake_shutdown(
+        exec_ctx, connector->handshaking_handshakes->handshake);
+    connector->handshaking_handshakes = tmp->next;
+    gpr_free(tmp);
   }
+  gpr_mu_unlock(&connector->mu);
 }
 
-void grpc_security_connector_do_handshake(grpc_exec_ctx *exec_ctx,
-                                          grpc_security_connector *sc,
-                                          grpc_endpoint *nonsecure_endpoint,
-                                          grpc_security_handshake_done_cb cb,
-                                          void *user_data) {
+void grpc_channel_security_connector_do_handshake(
+    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *sc,
+    grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb,
+    void *user_data) {
+  if (sc == NULL || nonsecure_endpoint == NULL) {
+    cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
+  } else {
+    sc->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data);
+  }
+}
+
+void grpc_server_security_connector_do_handshake(
+    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
+    grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
+    grpc_security_handshake_done_cb cb, void *user_data) {
   if (sc == NULL || nonsecure_endpoint == NULL) {
     cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, NULL, NULL);
   } else {
-    sc->vtable->do_handshake(exec_ctx, sc, nonsecure_endpoint, cb, user_data);
+    sc->do_handshake(exec_ctx, sc, acceptor, nonsecure_endpoint, cb, user_data);
   }
 }
 
@@ -248,7 +257,8 @@ static void fake_channel_destroy(grpc_security_connector *sc) {
 }
 
 static void fake_server_destroy(grpc_security_connector *sc) {
-  gpr_mu_destroy(&sc->mu);
+  grpc_server_security_connector *c = (grpc_server_security_connector *)sc;
+  gpr_mu_destroy(&c->mu);
   gpr_free(sc);
 }
 
@@ -298,49 +308,52 @@ static void fake_channel_check_call_host(grpc_exec_ctx *exec_ctx,
 }
 
 static void fake_channel_do_handshake(grpc_exec_ctx *exec_ctx,
-                                      grpc_security_connector *sc,
+                                      grpc_channel_security_connector *sc,
                                       grpc_endpoint *nonsecure_endpoint,
                                       grpc_security_handshake_done_cb cb,
                                       void *user_data) {
-  grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), sc,
-                             nonsecure_endpoint, cb, user_data);
+  grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(1), &sc->base,
+                             true, nonsecure_endpoint, cb, user_data);
 }
 
 static void fake_server_do_handshake(grpc_exec_ctx *exec_ctx,
-                                     grpc_security_connector *sc,
+                                     grpc_server_security_connector *sc,
+                                     grpc_tcp_server_acceptor *acceptor,
                                      grpc_endpoint *nonsecure_endpoint,
                                      grpc_security_handshake_done_cb cb,
                                      void *user_data) {
-  grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), sc,
-                             nonsecure_endpoint, cb, user_data);
+  grpc_do_security_handshake(exec_ctx, tsi_create_fake_handshaker(0), &sc->base,
+                             false, nonsecure_endpoint, cb, user_data);
 }
 
 static grpc_security_connector_vtable fake_channel_vtable = {
-    fake_channel_destroy, fake_channel_do_handshake, fake_check_peer};
+    fake_channel_destroy, fake_check_peer};
 
-static grpc_security_connector_vtable fake_server_vtable = {
-    fake_server_destroy, fake_server_do_handshake, fake_check_peer};
+static grpc_security_connector_vtable fake_server_vtable = {fake_server_destroy,
+                                                            fake_check_peer};
 
 grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
     grpc_call_credentials *request_metadata_creds) {
   grpc_channel_security_connector *c = gpr_malloc(sizeof(*c));
   memset(c, 0, sizeof(*c));
   gpr_ref_init(&c->base.refcount, 1);
-  c->base.is_client_side = 1;
   c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
   c->base.vtable = &fake_channel_vtable;
   c->request_metadata_creds = grpc_call_credentials_ref(request_metadata_creds);
   c->check_call_host = fake_channel_check_call_host;
+  c->do_handshake = fake_channel_do_handshake;
   return c;
 }
 
-grpc_security_connector *grpc_fake_server_security_connector_create(void) {
-  grpc_security_connector *c = gpr_malloc(sizeof(grpc_security_connector));
-  memset(c, 0, sizeof(grpc_security_connector));
-  gpr_ref_init(&c->refcount, 1);
-  c->is_client_side = 0;
-  c->vtable = &fake_server_vtable;
-  c->url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
+grpc_server_security_connector *grpc_fake_server_security_connector_create(
+    void) {
+  grpc_server_security_connector *c =
+      gpr_malloc(sizeof(grpc_server_security_connector));
+  memset(c, 0, sizeof(*c));
+  gpr_ref_init(&c->base.refcount, 1);
+  c->base.vtable = &fake_server_vtable;
+  c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
+  c->do_handshake = fake_server_do_handshake;
   gpr_mu_init(&c->mu);
   return c;
 }
@@ -355,7 +368,7 @@ typedef struct {
 } grpc_ssl_channel_security_connector;
 
 typedef struct {
-  grpc_security_connector base;
+  grpc_server_security_connector base;
   tsi_ssl_handshaker_factory *handshaker_factory;
 } grpc_ssl_server_security_connector;
 
@@ -378,12 +391,12 @@ static void ssl_server_destroy(grpc_security_connector *sc) {
   if (c->handshaker_factory != NULL) {
     tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
   }
-  gpr_mu_destroy(&sc->mu);
+  gpr_mu_destroy(&c->base.mu);
   gpr_free(sc);
 }
 
 static grpc_security_status ssl_create_handshaker(
-    tsi_ssl_handshaker_factory *handshaker_factory, int is_client,
+    tsi_ssl_handshaker_factory *handshaker_factory, bool is_client,
     const char *peer_name, tsi_handshaker **handshaker) {
   tsi_result result = TSI_OK;
   if (handshaker_factory == NULL) return GRPC_SECURITY_ERROR;
@@ -398,7 +411,7 @@ static grpc_security_status ssl_create_handshaker(
 }
 
 static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
-                                     grpc_security_connector *sc,
+                                     grpc_channel_security_connector *sc,
                                      grpc_endpoint *nonsecure_endpoint,
                                      grpc_security_handshake_done_cb cb,
                                      void *user_data) {
@@ -406,20 +419,21 @@ static void ssl_channel_do_handshake(grpc_exec_ctx *exec_ctx,
       (grpc_ssl_channel_security_connector *)sc;
   tsi_handshaker *handshaker;
   grpc_security_status status = ssl_create_handshaker(
-      c->handshaker_factory, 1,
+      c->handshaker_factory, true,
       c->overridden_target_name != NULL ? c->overridden_target_name
                                         : c->target_name,
       &handshaker);
   if (status != GRPC_SECURITY_OK) {
     cb(exec_ctx, user_data, status, NULL, NULL);
   } else {
-    grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
-                               user_data);
+    grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, true,
+                               nonsecure_endpoint, cb, user_data);
   }
 }
 
 static void ssl_server_do_handshake(grpc_exec_ctx *exec_ctx,
-                                    grpc_security_connector *sc,
+                                    grpc_server_security_connector *sc,
+                                    grpc_tcp_server_acceptor *acceptor,
                                     grpc_endpoint *nonsecure_endpoint,
                                     grpc_security_handshake_done_cb cb,
                                     void *user_data) {
@@ -427,12 +441,12 @@ static void ssl_server_do_handshake(grpc_exec_ctx *exec_ctx,
       (grpc_ssl_server_security_connector *)sc;
   tsi_handshaker *handshaker;
   grpc_security_status status =
-      ssl_create_handshaker(c->handshaker_factory, 0, NULL, &handshaker);
+      ssl_create_handshaker(c->handshaker_factory, false, NULL, &handshaker);
   if (status != GRPC_SECURITY_OK) {
     cb(exec_ctx, user_data, status, NULL, NULL);
   } else {
-    grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
-                               user_data);
+    grpc_do_security_handshake(exec_ctx, handshaker, &sc->base, false,
+                               nonsecure_endpoint, cb, user_data);
   }
 }
 
@@ -603,10 +617,10 @@ static void ssl_channel_check_call_host(grpc_exec_ctx *exec_ctx,
 }
 
 static grpc_security_connector_vtable ssl_channel_vtable = {
-    ssl_channel_destroy, ssl_channel_do_handshake, ssl_channel_check_peer};
+    ssl_channel_destroy, ssl_channel_check_peer};
 
 static grpc_security_connector_vtable ssl_server_vtable = {
-    ssl_server_destroy, ssl_server_do_handshake, ssl_server_check_peer};
+    ssl_server_destroy, ssl_server_check_peer};
 
 static gpr_slice compute_default_pem_root_certs_once(void) {
   gpr_slice result = gpr_empty_slice();
@@ -700,11 +714,11 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
 
   gpr_ref_init(&c->base.base.refcount, 1);
   c->base.base.vtable = &ssl_channel_vtable;
-  c->base.base.is_client_side = 1;
   c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
   c->base.request_metadata_creds =
       grpc_call_credentials_ref(request_metadata_creds);
   c->base.check_call_host = ssl_channel_check_call_host;
+  c->base.do_handshake = ssl_channel_do_handshake;
   gpr_split_host_port(target_name, &c->target_name, &port);
   gpr_free(port);
   if (overridden_target_name != NULL) {
@@ -735,7 +749,7 @@ error:
 }
 
 grpc_security_status grpc_ssl_server_security_connector_create(
-    const grpc_ssl_server_config *config, grpc_security_connector **sc) {
+    const grpc_ssl_server_config *config, grpc_server_security_connector **sc) {
   size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
   const unsigned char **alpn_protocol_strings =
       gpr_malloc(sizeof(const char *) * num_alpn_protocols);
@@ -759,9 +773,9 @@ grpc_security_status grpc_ssl_server_security_connector_create(
   c = gpr_malloc(sizeof(grpc_ssl_server_security_connector));
   memset(c, 0, sizeof(grpc_ssl_server_security_connector));
 
-  gpr_ref_init(&c->base.refcount, 1);
-  c->base.url_scheme = GRPC_SSL_URL_SCHEME;
-  c->base.vtable = &ssl_server_vtable;
+  gpr_ref_init(&c->base.base.refcount, 1);
+  c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
+  c->base.base.vtable = &ssl_server_vtable;
   result = tsi_create_ssl_server_handshaker_factory(
       (const unsigned char **)config->pem_private_keys,
       config->pem_private_keys_sizes,
@@ -774,11 +788,12 @@ grpc_security_status grpc_ssl_server_security_connector_create(
   if (result != TSI_OK) {
     gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
             tsi_result_to_string(result));
-    ssl_server_destroy(&c->base);
+    ssl_server_destroy(&c->base.base);
     *sc = NULL;
     goto error;
   }
   gpr_mu_init(&c->base.mu);
+  c->base.do_handshake = ssl_server_do_handshake;
   *sc = &c->base;
   gpr_free((void *)alpn_protocol_strings);
   gpr_free(alpn_protocol_string_lengths);
diff --git a/src/core/security/security_connector.h b/src/core/security/security_connector.h
index 39df7821f0c72c79aab3f11e75d96773e809aeb2..1e35d3f9b7ce8f5f98ab1ff8b59bb04650159914 100644
--- a/src/core/security/security_connector.h
+++ b/src/core/security/security_connector.h
@@ -36,6 +36,7 @@
 
 #include <grpc/grpc_security.h>
 #include "src/core/iomgr/endpoint.h"
+#include "src/core/iomgr/tcp_server.h"
 #include "src/core/tsi/transport_security_interface.h"
 
 /* --- status enum. --- */
@@ -68,9 +69,6 @@ typedef void (*grpc_security_handshake_done_cb)(
 
 typedef struct {
   void (*destroy)(grpc_security_connector *sc);
-  void (*do_handshake)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc,
-                       grpc_endpoint *nonsecure_endpoint,
-                       grpc_security_handshake_done_cb cb, void *user_data);
   void (*check_peer)(grpc_exec_ctx *exec_ctx, grpc_security_connector *sc,
                      tsi_peer peer, grpc_security_peer_check_cb cb,
                      void *user_data);
@@ -84,13 +82,7 @@ typedef struct grpc_security_connector_handshake_list {
 struct grpc_security_connector {
   const grpc_security_connector_vtable *vtable;
   gpr_refcount refcount;
-  int is_client_side;
   const char *url_scheme;
-  /* Used on server side only. */
-  /* TODO(yangg): Create a grpc_server_security_connector with these. */
-  gpr_mu mu;
-  grpc_security_connector_handshake_list *handshaking_handshakes;
-  const grpc_channel_args *channel_args;
 };
 
 /* Refcounting. */
@@ -113,13 +105,6 @@ grpc_security_connector *grpc_security_connector_ref(
 void grpc_security_connector_unref(grpc_security_connector *policy);
 #endif
 
-/* Handshake. */
-void grpc_security_connector_do_handshake(grpc_exec_ctx *exec_ctx,
-                                          grpc_security_connector *connector,
-                                          grpc_endpoint *nonsecure_endpoint,
-                                          grpc_security_handshake_done_cb cb,
-                                          void *user_data);
-
 /* Check the peer. Callee takes ownership of the peer object.
    The callback will include the resulting auth_context. */
 void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx,
@@ -128,9 +113,6 @@ void grpc_security_connector_check_peer(grpc_exec_ctx *exec_ctx,
                                         grpc_security_peer_check_cb cb,
                                         void *user_data);
 
-void grpc_security_connector_shutdown(grpc_exec_ctx *exec_ctx,
-                                      grpc_security_connector *connector);
-
 /* Util to encapsulate the connector in a channel arg. */
 grpc_arg grpc_security_connector_to_arg(grpc_security_connector *sc);
 
@@ -153,12 +135,16 @@ typedef void (*grpc_security_call_host_check_cb)(grpc_exec_ctx *exec_ctx,
                                                  grpc_security_status status);
 
 struct grpc_channel_security_connector {
-  grpc_security_connector base; /* requires is_client_side to be non 0. */
+  grpc_security_connector base;
   grpc_call_credentials *request_metadata_creds;
   void (*check_call_host)(grpc_exec_ctx *exec_ctx,
                           grpc_channel_security_connector *sc, const char *host,
                           grpc_auth_context *auth_context,
                           grpc_security_call_host_check_cb cb, void *user_data);
+  void (*do_handshake)(grpc_exec_ctx *exec_ctx,
+                       grpc_channel_security_connector *sc,
+                       grpc_endpoint *nonsecure_endpoint,
+                       grpc_security_handshake_done_cb cb, void *user_data);
 };
 
 /* Checks that the host that will be set for a call is acceptable. */
@@ -167,6 +153,39 @@ void grpc_channel_security_connector_check_call_host(
     const char *host, grpc_auth_context *auth_context,
     grpc_security_call_host_check_cb cb, void *user_data);
 
+/* Handshake. */
+void grpc_channel_security_connector_do_handshake(
+    grpc_exec_ctx *exec_ctx, grpc_channel_security_connector *connector,
+    grpc_endpoint *nonsecure_endpoint, grpc_security_handshake_done_cb cb,
+    void *user_data);
+
+/* --- server_security_connector object. ---
+
+    A server security connector object represents away to configure the
+    underlying transport security mechanism on the server side.  */
+
+typedef struct grpc_server_security_connector grpc_server_security_connector;
+
+struct grpc_server_security_connector {
+  grpc_security_connector base;
+  gpr_mu mu;
+  grpc_security_connector_handshake_list *handshaking_handshakes;
+  const grpc_channel_args *channel_args;
+  void (*do_handshake)(grpc_exec_ctx *exec_ctx,
+                       grpc_server_security_connector *sc,
+                       grpc_tcp_server_acceptor *acceptor,
+                       grpc_endpoint *nonsecure_endpoint,
+                       grpc_security_handshake_done_cb cb, void *user_data);
+};
+
+void grpc_server_security_connector_do_handshake(
+    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *sc,
+    grpc_tcp_server_acceptor *acceptor, grpc_endpoint *nonsecure_endpoint,
+    grpc_security_handshake_done_cb cb, void *user_data);
+
+void grpc_server_security_connector_shutdown(
+    grpc_exec_ctx *exec_ctx, grpc_server_security_connector *connector);
+
 /* --- Creation security connectors. --- */
 
 /* For TESTING ONLY!
@@ -176,7 +195,8 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
 
 /* For TESTING ONLY!
    Creates a fake connector that emulates real server security.  */
-grpc_security_connector *grpc_fake_server_security_connector_create(void);
+grpc_server_security_connector *grpc_fake_server_security_connector_create(
+    void);
 
 /* Config for ssl clients. */
 typedef struct {
@@ -231,7 +251,7 @@ typedef struct {
   specific error code otherwise.
 */
 grpc_security_status grpc_ssl_server_security_connector_create(
-    const grpc_ssl_server_config *config, grpc_security_connector **sc);
+    const grpc_ssl_server_config *config, grpc_server_security_connector **sc);
 
 /* Util. */
 const tsi_peer_property *tsi_peer_get_property_by_name(const tsi_peer *peer,
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
index 84a883390c2a19a7fdb5d756501e9cd44ad8e540..91547eb26e91ce168aff8fb57b4ca71bd1ad5c69 100644
--- a/src/core/security/server_secure_chttp2.c
+++ b/src/core/security/server_secure_chttp2.c
@@ -55,7 +55,7 @@
 typedef struct grpc_server_secure_state {
   grpc_server *server;
   grpc_tcp_server *tcp;
-  grpc_security_connector *sc;
+  grpc_server_security_connector *sc;
   grpc_server_credentials *creds;
   int is_shutdown;
   gpr_mu mu;
@@ -74,7 +74,7 @@ static void state_unref(grpc_server_secure_state *state) {
     gpr_mu_lock(&state->mu);
     gpr_mu_unlock(&state->mu);
     /* clean up */
-    GRPC_SECURITY_CONNECTOR_UNREF(state->sc, "server");
+    GRPC_SECURITY_CONNECTOR_UNREF(&state->sc->base, "server");
     grpc_server_credentials_unref(state->creds);
     gpr_free(state);
   }
@@ -130,8 +130,8 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
                       grpc_tcp_server_acceptor *acceptor) {
   grpc_server_secure_state *state = statep;
   state_ref(state);
-  grpc_security_connector_do_handshake(exec_ctx, state->sc, tcp,
-                                       on_secure_handshake_done, state);
+  grpc_server_security_connector_do_handshake(
+      exec_ctx, state->sc, acceptor, tcp, on_secure_handshake_done, state);
 }
 
 /* Server callback: start listening on our ports */
@@ -148,7 +148,7 @@ static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep, bool success) {
     state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg,
                                 success);
   }
-  grpc_security_connector_shutdown(exec_ctx, state->sc);
+  grpc_server_security_connector_shutdown(exec_ctx, state->sc);
   state_unref(state);
 }
 
@@ -176,7 +176,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
   int port_num = -1;
   int port_temp;
   grpc_security_status status = GRPC_SECURITY_ERROR;
-  grpc_security_connector *sc = NULL;
+  grpc_server_security_connector *sc = NULL;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
   GRPC_API_TRACE(
@@ -256,7 +256,7 @@ error:
     grpc_tcp_server_unref(&exec_ctx, tcp);
   } else {
     if (sc) {
-      GRPC_SECURITY_CONNECTOR_UNREF(sc, "server");
+      GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server");
     }
     if (state) {
       gpr_free(state);
diff --git a/src/core/support/env_linux.c b/src/core/support/env_linux.c
index 1ca6fa1affe29a9d630afff58a262ff94504e9ee..fe51f846b710f65dfb8a5e5034f52b787cb729b4 100644
--- a/src/core/support/env_linux.c
+++ b/src/core/support/env_linux.c
@@ -43,7 +43,9 @@
 #include "src/core/support/env.h"
 
 #include <dlfcn.h>
+#include <features.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -60,12 +62,22 @@ char *gpr_getenv(const char *name) {
   const char *names[] = {"secure_getenv", "__secure_getenv", "getenv"};
   for (size_t i = 0; getenv_func == NULL && i < GPR_ARRAY_SIZE(names); i++) {
     getenv_func = (getenv_type)dlsym(RTLD_DEFAULT, names[i]);
+    if (getenv_func != NULL && strstr(names[i], "secure") == NULL) {
+      gpr_log(GPR_DEBUG,
+              "Warning: insecure environment read function '%s' used",
+              names[i]);
+    }
   }
   char *result = getenv_func(name);
   return result == NULL ? result : gpr_strdup(result);
-#else
+#elif __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17)
   char *result = secure_getenv(name);
   return result == NULL ? result : gpr_strdup(result);
+#else
+  gpr_log(GPR_DEBUG, "Warning: insecure environment read function '%s' used",
+          "getenv");
+  char *result = getenv(name);
+  return result == NULL ? result : gpr_strdup(result);
 #endif
 }
 
diff --git a/src/core/support/file.c b/src/core/support/load_file.c
similarity index 97%
rename from src/core/support/file.c
rename to src/core/support/load_file.c
index 8c673dbcc66ab6ade223bf82b1e6765cc17ea486..650bd62ccbe0e039deaa0e7873a3ecb5df49a65c 100644
--- a/src/core/support/file.c
+++ b/src/core/support/load_file.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/support/file.h"
+#include "src/core/support/load_file.h"
 
 #include <errno.h>
 #include <string.h>
diff --git a/src/core/support/file.h b/src/core/support/load_file.h
similarity index 79%
rename from src/core/support/file.h
rename to src/core/support/load_file.h
index d8b7cea44fd799ef0f2e86556865b49703057680..746319a50d22bbafa4fd685efa5cafd6c1920ebb 100644
--- a/src/core/support/file.h
+++ b/src/core/support/load_file.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,8 +31,8 @@
  *
  */
 
-#ifndef GRPC_INTERNAL_CORE_SUPPORT_FILE_H
-#define GRPC_INTERNAL_CORE_SUPPORT_FILE_H
+#ifndef GRPC_INTERNAL_CORE_SUPPORT_LOAD_FILE_H
+#define GRPC_INTERNAL_CORE_SUPPORT_LOAD_FILE_H
 
 #include <stdio.h>
 
@@ -42,22 +42,14 @@
 extern "C" {
 #endif
 
-/* File utility functions */
-
 /* Loads the content of a file into a slice. add_null_terminator will add
    a NULL terminator if non-zero. The success parameter, if not NULL,
    will be set to 1 in case of success and 0 in case of failure. */
 gpr_slice gpr_load_file(const char *filename, int add_null_terminator,
                         int *success);
 
-/* Creates a temporary file from a prefix.
-   If tmp_filename is not NULL, *tmp_filename is assigned the name of the
-   created file and it is the responsibility of the caller to gpr_free it
-   unless an error occurs in which case it will be set to NULL. */
-FILE *gpr_tmpfile(const char *prefix, char **tmp_filename);
-
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* GRPC_INTERNAL_CORE_SUPPORT_FILE_H */
+#endif /* GRPC_INTERNAL_CORE_SUPPORT_LOAD_FILE_H */
diff --git a/src/core/support/sync.c b/src/core/support/sync.c
index d368422d9eaf693da5f96494e3c134ffbc030a7e..69e3e39c5cef80d05ba9b2b6553c20bdfe75b271 100644
--- a/src/core/support/sync.c
+++ b/src/core/support/sync.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -98,6 +98,11 @@ void gpr_ref_init(gpr_refcount *r, int n) { gpr_atm_rel_store(&r->count, n); }
 
 void gpr_ref(gpr_refcount *r) { gpr_atm_no_barrier_fetch_add(&r->count, 1); }
 
+void gpr_ref_non_zero(gpr_refcount *r) {
+  gpr_atm prior = gpr_atm_no_barrier_fetch_add(&r->count, 1);
+  GPR_ASSERT(prior > 0);
+}
+
 void gpr_refn(gpr_refcount *r, int n) {
   gpr_atm_no_barrier_fetch_add(&r->count, n);
 }
diff --git a/src/core/support/tmpfile.h b/src/core/support/tmpfile.h
new file mode 100644
index 0000000000000000000000000000000000000000..cecc71e2429c520c53ee5efbcbfbcc826bcee113
--- /dev/null
+++ b/src/core/support/tmpfile.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright 2015-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_INTERNAL_CORE_SUPPORT_TMPFILE_H
+#define GRPC_INTERNAL_CORE_SUPPORT_TMPFILE_H
+
+#include <stdio.h>
+
+#include <grpc/support/slice.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Creates a temporary file from a prefix.
+   If tmp_filename is not NULL, *tmp_filename is assigned the name of the
+   created file and it is the responsibility of the caller to gpr_free it
+   unless an error occurs in which case it will be set to NULL. */
+FILE *gpr_tmpfile(const char *prefix, char **tmp_filename);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_INTERNAL_CORE_SUPPORT_TMPFILE_H */
diff --git a/src/core/support/file_posix.c b/src/core/support/tmpfile_posix.c
similarity index 97%
rename from src/core/support/file_posix.c
rename to src/core/support/tmpfile_posix.c
index c11c07148ab9c13beb70c0d6611699aec3d26096..b16eeacf9d4a9594060455ac07423cd8ba10748b 100644
--- a/src/core/support/file_posix.c
+++ b/src/core/support/tmpfile_posix.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,7 +35,7 @@
 
 #ifdef GPR_POSIX_FILE
 
-#include "src/core/support/file.h"
+#include "src/core/support/tmpfile.h"
 
 #include <errno.h>
 #include <stdlib.h>
diff --git a/src/core/support/file_win32.c b/src/core/support/tmpfile_win32.c
similarity index 97%
rename from src/core/support/file_win32.c
rename to src/core/support/tmpfile_win32.c
index 355744f79a537e0628a1f2d2be0aebc4b49be0ea..3000f0029fe7e55d2617572031977638bbcd0760 100644
--- a/src/core/support/file_win32.c
+++ b/src/core/support/tmpfile_win32.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,8 +44,8 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/support/file.h"
 #include "src/core/support/string_win32.h"
+#include "src/core/support/tmpfile.h"
 
 FILE *gpr_tmpfile(const char *prefix, char **tmp_filename_out) {
   FILE *result = NULL;
diff --git a/src/core/surface/alarm.c b/src/core/surface/alarm.c
index fb496f6c474ace029a792b43dada119c2d7b2706..8169ede065511111a326a992623e4eefccef947d 100644
--- a/src/core/surface/alarm.c
+++ b/src/core/surface/alarm.c
@@ -64,8 +64,9 @@ grpc_alarm *grpc_alarm_create(grpc_completion_queue *cq, gpr_timespec deadline,
   alarm->tag = tag;
 
   grpc_cq_begin_op(cq, tag);
-  grpc_timer_init(&exec_ctx, &alarm->alarm, deadline, alarm_cb, alarm,
-                  gpr_now(GPR_CLOCK_MONOTONIC));
+  grpc_timer_init(&exec_ctx, &alarm->alarm,
+                  gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
+                  alarm_cb, alarm, gpr_now(GPR_CLOCK_MONOTONIC));
   grpc_exec_ctx_finish(&exec_ctx);
   return alarm;
 }
diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c
index 75298eb795c4fb9d9d995ad6a4b43bb9f2b86ffc..f6a95ebbd3ffd23f38a50b88e851f0d99b96c8b8 100644
--- a/src/core/surface/completion_queue.c
+++ b/src/core/surface/completion_queue.c
@@ -36,26 +36,29 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/iomgr/timer.h"
+#include <grpc/support/alloc.h>
+#include <grpc/support/atm.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+
 #include "src/core/iomgr/pollset.h"
+#include "src/core/iomgr/timer.h"
+#include "src/core/profiling/timers.h"
 #include "src/core/support/string.h"
 #include "src/core/surface/api_trace.h"
 #include "src/core/surface/call.h"
 #include "src/core/surface/event_string.h"
 #include "src/core/surface/surface_trace.h"
-#include "src/core/profiling/timers.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/atm.h>
-#include <grpc/support/log.h>
-#include <grpc/support/time.h>
 
 typedef struct {
-  grpc_pollset_worker *worker;
+  grpc_pollset_worker **worker;
   void *tag;
 } plucker;
 
 /* Completion queue structure */
 struct grpc_completion_queue {
+  /** owned by pollset */
+  gpr_mu *mu;
   /** completed events */
   grpc_cq_completion completed_head;
   grpc_cq_completion *completed_tail;
@@ -63,8 +66,6 @@ struct grpc_completion_queue {
   gpr_refcount pending_events;
   /** Once owning_refs drops to zero, we will destroy the cq */
   gpr_refcount owning_refs;
-  /** the set of low level i/o things that concern this cq */
-  grpc_pollset pollset;
   /** 0 initially, 1 once we've begun shutting down */
   int shutdown;
   int shutdown_called;
@@ -82,6 +83,8 @@ struct grpc_completion_queue {
   grpc_completion_queue *next_free;
 };
 
+#define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1))
+
 static gpr_mu g_freelist_mu;
 grpc_completion_queue *g_freelist;
 
@@ -94,7 +97,7 @@ void grpc_cq_global_shutdown(void) {
   gpr_mu_destroy(&g_freelist_mu);
   while (g_freelist) {
     grpc_completion_queue *next = g_freelist->next_free;
-    grpc_pollset_destroy(&g_freelist->pollset);
+    grpc_pollset_destroy(POLLSET_FROM_CQ(g_freelist));
 #ifndef NDEBUG
     gpr_free(g_freelist->outstanding_tags);
 #endif
@@ -124,8 +127,8 @@ grpc_completion_queue *grpc_completion_queue_create(void *reserved) {
   if (g_freelist == NULL) {
     gpr_mu_unlock(&g_freelist_mu);
 
-    cc = gpr_malloc(sizeof(grpc_completion_queue));
-    grpc_pollset_init(&cc->pollset);
+    cc = gpr_malloc(sizeof(grpc_completion_queue) + grpc_pollset_size());
+    grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu);
 #ifndef NDEBUG
     cc->outstanding_tags = NULL;
     cc->outstanding_tag_capacity = 0;
@@ -184,7 +187,7 @@ void grpc_cq_internal_unref(grpc_completion_queue *cc) {
 #endif
   if (gpr_unref(&cc->owning_refs)) {
     GPR_ASSERT(cc->completed_head.next == (uintptr_t)&cc->completed_head);
-    grpc_pollset_reset(&cc->pollset);
+    grpc_pollset_reset(POLLSET_FROM_CQ(cc));
     gpr_mu_lock(&g_freelist_mu);
     cc->next_free = g_freelist;
     g_freelist = cc;
@@ -194,7 +197,7 @@ void grpc_cq_internal_unref(grpc_completion_queue *cc) {
 
 void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag) {
 #ifndef NDEBUG
-  gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
+  gpr_mu_lock(cc->mu);
   GPR_ASSERT(!cc->shutdown_called);
   if (cc->outstanding_tag_count == cc->outstanding_tag_capacity) {
     cc->outstanding_tag_capacity = GPR_MAX(4, 2 * cc->outstanding_tag_capacity);
@@ -203,7 +206,7 @@ void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag) {
                                               cc->outstanding_tag_capacity);
   }
   cc->outstanding_tags[cc->outstanding_tag_count++] = tag;
-  gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+  gpr_mu_unlock(cc->mu);
 #endif
   gpr_ref(&cc->pending_events);
 }
@@ -231,7 +234,7 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
   storage->next =
       ((uintptr_t)&cc->completed_head) | ((uintptr_t)(success != 0));
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
+  gpr_mu_lock(cc->mu);
 #ifndef NDEBUG
   for (i = 0; i < (int)cc->outstanding_tag_count; i++) {
     if (cc->outstanding_tags[i] == tag) {
@@ -252,12 +255,12 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
     pluck_worker = NULL;
     for (i = 0; i < cc->num_pluckers; i++) {
       if (cc->pluckers[i].tag == tag) {
-        pluck_worker = cc->pluckers[i].worker;
+        pluck_worker = *cc->pluckers[i].worker;
         break;
       }
     }
-    grpc_pollset_kick(&cc->pollset, pluck_worker);
-    gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+    grpc_pollset_kick(POLLSET_FROM_CQ(cc), pluck_worker);
+    gpr_mu_unlock(cc->mu);
   } else {
     cc->completed_tail->next =
         ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next);
@@ -265,8 +268,9 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
     GPR_ASSERT(!cc->shutdown);
     GPR_ASSERT(cc->shutdown_called);
     cc->shutdown = 1;
-    grpc_pollset_shutdown(exec_ctx, &cc->pollset, &cc->pollset_shutdown_done);
-    gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+    grpc_pollset_shutdown(exec_ctx, POLLSET_FROM_CQ(cc),
+                          &cc->pollset_shutdown_done);
+    gpr_mu_unlock(cc->mu);
   }
 
   GPR_TIMER_END("grpc_cq_end_op", 0);
@@ -275,7 +279,7 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
 grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
                                       gpr_timespec deadline, void *reserved) {
   grpc_event ret;
-  grpc_pollset_worker worker;
+  grpc_pollset_worker *worker = NULL;
   int first_loop = 1;
   gpr_timespec now;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -294,7 +298,7 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
   deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
 
   GRPC_CQ_INTERNAL_REF(cc, "next");
-  gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
+  gpr_mu_lock(cc->mu);
   for (;;) {
     if (cc->completed_tail != &cc->completed_head) {
       grpc_cq_completion *c = (grpc_cq_completion *)cc->completed_head.next;
@@ -302,7 +306,7 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
       if (c == cc->completed_tail) {
         cc->completed_tail = &cc->completed_head;
       }
-      gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+      gpr_mu_unlock(cc->mu);
       ret.type = GRPC_OP_COMPLETE;
       ret.success = c->next & 1u;
       ret.tag = c->tag;
@@ -310,20 +314,34 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
       break;
     }
     if (cc->shutdown) {
-      gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+      gpr_mu_unlock(cc->mu);
       memset(&ret, 0, sizeof(ret));
       ret.type = GRPC_QUEUE_SHUTDOWN;
       break;
     }
     now = gpr_now(GPR_CLOCK_MONOTONIC);
     if (!first_loop && gpr_time_cmp(now, deadline) >= 0) {
-      gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+      gpr_mu_unlock(cc->mu);
       memset(&ret, 0, sizeof(ret));
       ret.type = GRPC_QUEUE_TIMEOUT;
       break;
     }
     first_loop = 0;
-    grpc_pollset_work(&exec_ctx, &cc->pollset, &worker, now, deadline);
+    /* Check alarms - these are a global resource so we just ping
+       each time through on every pollset.
+       May update deadline to ensure timely wakeups.
+       TODO(ctiller): can this work be localized? */
+    gpr_timespec iteration_deadline = deadline;
+    if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) {
+      GPR_TIMER_MARK("alarm_triggered", 0);
+      gpr_mu_unlock(cc->mu);
+      grpc_exec_ctx_flush(&exec_ctx);
+      gpr_mu_lock(cc->mu);
+      continue;
+    } else {
+      grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), &worker, now,
+                        iteration_deadline);
+    }
   }
   GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
   GRPC_CQ_INTERNAL_UNREF(cc, "next");
@@ -335,7 +353,7 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
 }
 
 static int add_plucker(grpc_completion_queue *cc, void *tag,
-                       grpc_pollset_worker *worker) {
+                       grpc_pollset_worker **worker) {
   if (cc->num_pluckers == GRPC_MAX_COMPLETION_QUEUE_PLUCKERS) {
     return 0;
   }
@@ -346,7 +364,7 @@ static int add_plucker(grpc_completion_queue *cc, void *tag,
 }
 
 static void del_plucker(grpc_completion_queue *cc, void *tag,
-                        grpc_pollset_worker *worker) {
+                        grpc_pollset_worker **worker) {
   int i;
   for (i = 0; i < cc->num_pluckers; i++) {
     if (cc->pluckers[i].tag == tag && cc->pluckers[i].worker == worker) {
@@ -363,7 +381,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
   grpc_event ret;
   grpc_cq_completion *c;
   grpc_cq_completion *prev;
-  grpc_pollset_worker worker;
+  grpc_pollset_worker *worker = NULL;
   gpr_timespec now;
   int first_loop = 1;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -382,7 +400,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
   deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
 
   GRPC_CQ_INTERNAL_REF(cc, "pluck");
-  gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
+  gpr_mu_lock(cc->mu);
   for (;;) {
     prev = &cc->completed_head;
     while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) !=
@@ -392,7 +410,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
         if (c == cc->completed_tail) {
           cc->completed_tail = prev;
         }
-        gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+        gpr_mu_unlock(cc->mu);
         ret.type = GRPC_OP_COMPLETE;
         ret.success = c->next & 1u;
         ret.tag = c->tag;
@@ -402,7 +420,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
       prev = c;
     }
     if (cc->shutdown) {
-      gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+      gpr_mu_unlock(cc->mu);
       memset(&ret, 0, sizeof(ret));
       ret.type = GRPC_QUEUE_SHUTDOWN;
       break;
@@ -412,7 +430,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
               "Too many outstanding grpc_completion_queue_pluck calls: maximum "
               "is %d",
               GRPC_MAX_COMPLETION_QUEUE_PLUCKERS);
-      gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+      gpr_mu_unlock(cc->mu);
       memset(&ret, 0, sizeof(ret));
       /* TODO(ctiller): should we use a different result here */
       ret.type = GRPC_QUEUE_TIMEOUT;
@@ -421,13 +439,26 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
     now = gpr_now(GPR_CLOCK_MONOTONIC);
     if (!first_loop && gpr_time_cmp(now, deadline) >= 0) {
       del_plucker(cc, tag, &worker);
-      gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+      gpr_mu_unlock(cc->mu);
       memset(&ret, 0, sizeof(ret));
       ret.type = GRPC_QUEUE_TIMEOUT;
       break;
     }
     first_loop = 0;
-    grpc_pollset_work(&exec_ctx, &cc->pollset, &worker, now, deadline);
+    /* Check alarms - these are a global resource so we just ping
+       each time through on every pollset.
+       May update deadline to ensure timely wakeups.
+       TODO(ctiller): can this work be localized? */
+    gpr_timespec iteration_deadline = deadline;
+    if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) {
+      GPR_TIMER_MARK("alarm_triggered", 0);
+      gpr_mu_unlock(cc->mu);
+      grpc_exec_ctx_flush(&exec_ctx);
+      gpr_mu_lock(cc->mu);
+    } else {
+      grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), &worker, now,
+                        iteration_deadline);
+    }
     del_plucker(cc, tag, &worker);
   }
 done:
@@ -446,9 +477,9 @@ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   GPR_TIMER_BEGIN("grpc_completion_queue_shutdown", 0);
   GRPC_API_TRACE("grpc_completion_queue_shutdown(cc=%p)", 1, (cc));
-  gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
+  gpr_mu_lock(cc->mu);
   if (cc->shutdown_called) {
-    gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+    gpr_mu_unlock(cc->mu);
     GPR_TIMER_END("grpc_completion_queue_shutdown", 0);
     return;
   }
@@ -456,9 +487,10 @@ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
   if (gpr_unref(&cc->pending_events)) {
     GPR_ASSERT(!cc->shutdown);
     cc->shutdown = 1;
-    grpc_pollset_shutdown(&exec_ctx, &cc->pollset, &cc->pollset_shutdown_done);
+    grpc_pollset_shutdown(&exec_ctx, POLLSET_FROM_CQ(cc),
+                          &cc->pollset_shutdown_done);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
+  gpr_mu_unlock(cc->mu);
   grpc_exec_ctx_finish(&exec_ctx);
   GPR_TIMER_END("grpc_completion_queue_shutdown", 0);
 }
@@ -472,7 +504,7 @@ void grpc_completion_queue_destroy(grpc_completion_queue *cc) {
 }
 
 grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc) {
-  return &cc->pollset;
+  return POLLSET_FROM_CQ(cc);
 }
 
 void grpc_cq_mark_server_cq(grpc_completion_queue *cc) { cc->is_server_cq = 1; }
diff --git a/src/core/surface/secure_channel_create.c b/src/core/surface/secure_channel_create.c
index 9c04426d8720c990f134a3b283a719f0ea7c0669..aadfac4c91f6367b18177696399ec41649f7061a 100644
--- a/src/core/surface/secure_channel_create.c
+++ b/src/core/surface/secure_channel_create.c
@@ -130,9 +130,9 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
 static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
                                            bool success) {
   connector *c = arg;
-  grpc_security_connector_do_handshake(exec_ctx, &c->security_connector->base,
-                                       c->connecting_endpoint,
-                                       on_secure_handshake_done, c);
+  grpc_channel_security_connector_do_handshake(exec_ctx, c->security_connector,
+                                               c->connecting_endpoint,
+                                               on_secure_handshake_done, c);
 }
 
 static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
@@ -153,9 +153,8 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
       grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
                           &c->initial_string_sent);
     } else {
-      grpc_security_connector_do_handshake(exec_ctx,
-                                           &c->security_connector->base, tcp,
-                                           on_secure_handshake_done, c);
+      grpc_channel_security_connector_do_handshake(
+          exec_ctx, c->security_connector, tcp, on_secure_handshake_done, c);
     }
   } else {
     memset(c->result, 0, sizeof(*c->result));
diff --git a/src/core/surface/server.c b/src/core/surface/server.c
index fb5e0d4b9e70a471d9b2bfc4db2793476d2adc64..5b13d4ba526dc84fd070097704c9bbaef7ec9bbb 100644
--- a/src/core/surface/server.c
+++ b/src/core/surface/server.c
@@ -407,8 +407,15 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) {
   maybe_finish_shutdown(exec_ctx, chand->server);
   chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
   chand->finish_destroy_channel_closure.cb_arg = chand;
-  grpc_exec_ctx_enqueue(exec_ctx, &chand->finish_destroy_channel_closure, true,
-                        NULL);
+
+  grpc_transport_op op;
+  memset(&op, 0, sizeof(op));
+  op.set_accept_stream = true;
+  op.on_consumed = &chand->finish_destroy_channel_closure;
+  grpc_channel_next_op(exec_ctx,
+                       grpc_channel_stack_element(
+                           grpc_channel_get_channel_stack(chand->channel), 0),
+                       &op);
 }
 
 static void finish_start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_server *server,
@@ -971,7 +978,8 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
 
   GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
   memset(&op, 0, sizeof(op));
-  op.set_accept_stream = accept_stream;
+  op.set_accept_stream = true;
+  op.set_accept_stream_fn = accept_stream;
   op.set_accept_stream_user_data = chand;
   op.on_connectivity_state_change = &chand->channel_connectivity_changed;
   op.connectivity_state = &chand->connectivity_state;
diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h
index 0e1e2c42650f855f6d12b5b131cab3fc842d6221..b720d1ab3e5a64cdb369ac83fcc375f9bff56c4d 100644
--- a/src/core/transport/chttp2/internal.h
+++ b/src/core/transport/chttp2/internal.h
@@ -358,6 +358,9 @@ struct grpc_chttp2_transport {
     /** connectivity tracking */
     grpc_connectivity_state_tracker state_tracker;
   } channel_callback;
+
+  /** Transport op to be applied post-parsing */
+  grpc_transport_op *post_parsing_op;
 };
 
 typedef struct {
@@ -417,7 +420,7 @@ typedef struct {
   /** HTTP2 stream id for this stream, or zero if one has not been assigned */
   uint32_t id;
   uint8_t fetching;
-  uint8_t sent_initial_metadata;
+  bool sent_initial_metadata;
   uint8_t sent_message;
   uint8_t sent_trailing_metadata;
   uint8_t read_closed;
@@ -485,7 +488,8 @@ struct grpc_chttp2_stream {
 
 /** Someone is unlocking the transport mutex: check to see if writes
     are required, and schedule them if so */
-int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global,
+int grpc_chttp2_unlocking_check_writes(grpc_exec_ctx *exec_ctx,
+                                       grpc_chttp2_transport_global *global,
                                        grpc_chttp2_transport_writing *writing,
                                        int is_parsing);
 void grpc_chttp2_perform_writes(
@@ -508,7 +512,7 @@ void grpc_chttp2_publish_reads(grpc_exec_ctx *exec_ctx,
                                grpc_chttp2_transport_global *global,
                                grpc_chttp2_transport_parsing *parsing);
 
-void grpc_chttp2_list_add_writable_stream(
+bool grpc_chttp2_list_add_writable_stream(
     grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_stream_global *stream_global);
 /** Get a writable stream
@@ -518,14 +522,13 @@ int grpc_chttp2_list_pop_writable_stream(
     grpc_chttp2_transport_writing *transport_writing,
     grpc_chttp2_stream_global **stream_global,
     grpc_chttp2_stream_writing **stream_writing);
-void grpc_chttp2_list_remove_writable_stream(
+bool grpc_chttp2_list_remove_writable_stream(
     grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global);
+    grpc_chttp2_stream_global *stream_global) GRPC_MUST_USE_RESULT;
 
-/* returns 1 if stream added, 0 if it was already present */
-int grpc_chttp2_list_add_writing_stream(
+void grpc_chttp2_list_add_writing_stream(
     grpc_chttp2_transport_writing *transport_writing,
-    grpc_chttp2_stream_writing *stream_writing) GRPC_MUST_USE_RESULT;
+    grpc_chttp2_stream_writing *stream_writing);
 int grpc_chttp2_list_have_writing_streams(
     grpc_chttp2_transport_writing *transport_writing);
 int grpc_chttp2_list_pop_writing_stream(
@@ -568,8 +571,12 @@ void grpc_chttp2_list_add_writing_stalled_by_transport(
     grpc_chttp2_transport_writing *transport_writing,
     grpc_chttp2_stream_writing *stream_writing);
 void grpc_chttp2_list_flush_writing_stalled_by_transport(
-    grpc_chttp2_transport_writing *transport_writing, bool is_window_available);
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
+    bool is_window_available);
 
+void grpc_chttp2_list_add_stalled_by_transport(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing *stream_writing);
 int grpc_chttp2_list_pop_stalled_by_transport(
     grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_stream_global **stream_global);
@@ -765,4 +772,9 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
                           grpc_chttp2_transport_parsing *parsing,
                           const uint8_t *opaque_8bytes);
 
+/** add a ref to the stream and add it to the writable list;
+    ref will be dropped in writing.c */
+void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
+                                 grpc_chttp2_stream_global *stream_global);
+
 #endif
diff --git a/src/core/transport/chttp2/parsing.c b/src/core/transport/chttp2/parsing.c
index 8fdebd7f139857664cece6c5b27e12ca5cf57167..0516f39fa9ef83f84cf64a3e0e22c8cb839d7a14 100644
--- a/src/core/transport/chttp2/parsing.c
+++ b/src/core/transport/chttp2/parsing.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -149,7 +149,7 @@ void grpc_chttp2_publish_reads(
   if (was_zero && !is_zero) {
     while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
                                                      &stream_global)) {
-      grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+      grpc_chttp2_become_writable(transport_global, stream_global);
     }
   }
 
@@ -178,7 +178,7 @@ void grpc_chttp2_publish_reads(
                                  outgoing_window);
     is_zero = stream_global->outgoing_window <= 0;
     if (was_zero && !is_zero) {
-      grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+      grpc_chttp2_become_writable(transport_global, stream_global);
     }
 
     stream_global->max_recv_bytes -= (uint32_t)GPR_MIN(
diff --git a/src/core/transport/chttp2/stream_lists.c b/src/core/transport/chttp2/stream_lists.c
index 2f31a47cb3df6a177edcc567f618426532757fc4..60fe735cfce9aa7327c5b90267154321780056d2 100644
--- a/src/core/transport/chttp2/stream_lists.c
+++ b/src/core/transport/chttp2/stream_lists.c
@@ -100,11 +100,14 @@ static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
   }
 }
 
-static void stream_list_maybe_remove(grpc_chttp2_transport *t,
+static bool stream_list_maybe_remove(grpc_chttp2_transport *t,
                                      grpc_chttp2_stream *s,
                                      grpc_chttp2_stream_list_id id) {
   if (s->included[id]) {
     stream_list_remove(t, s, id);
+    return true;
+  } else {
+    return false;
   }
 }
 
@@ -125,23 +128,24 @@ static void stream_list_add_tail(grpc_chttp2_transport *t,
   s->included[id] = 1;
 }
 
-static int stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
-                           grpc_chttp2_stream_list_id id) {
+static bool stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
+                            grpc_chttp2_stream_list_id id) {
   if (s->included[id]) {
-    return 0;
+    return false;
   }
   stream_list_add_tail(t, s, id);
-  return 1;
+  return true;
 }
 
 /* wrappers for specializations */
 
-void grpc_chttp2_list_add_writable_stream(
+bool grpc_chttp2_list_add_writable_stream(
     grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_stream_global *stream_global) {
   GPR_ASSERT(stream_global->id != 0);
-  stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
-                  STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE);
+  return stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
+                         STREAM_FROM_GLOBAL(stream_global),
+                         GRPC_CHTTP2_LIST_WRITABLE);
 }
 
 int grpc_chttp2_list_pop_writable_stream(
@@ -159,20 +163,20 @@ int grpc_chttp2_list_pop_writable_stream(
   return r;
 }
 
-void grpc_chttp2_list_remove_writable_stream(
+bool grpc_chttp2_list_remove_writable_stream(
     grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_stream_global *stream_global) {
-  stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
-                           STREAM_FROM_GLOBAL(stream_global),
-                           GRPC_CHTTP2_LIST_WRITABLE);
+  return stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
+                                  STREAM_FROM_GLOBAL(stream_global),
+                                  GRPC_CHTTP2_LIST_WRITABLE);
 }
 
-int grpc_chttp2_list_add_writing_stream(
+void grpc_chttp2_list_add_writing_stream(
     grpc_chttp2_transport_writing *transport_writing,
     grpc_chttp2_stream_writing *stream_writing) {
-  return stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
-                         STREAM_FROM_WRITING(stream_writing),
-                         GRPC_CHTTP2_LIST_WRITING);
+  GPR_ASSERT(stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
+                             STREAM_FROM_WRITING(stream_writing),
+                             GRPC_CHTTP2_LIST_WRITING));
 }
 
 int grpc_chttp2_list_have_writing_streams(
@@ -316,26 +320,40 @@ int grpc_chttp2_list_pop_check_read_ops(
 void grpc_chttp2_list_add_writing_stalled_by_transport(
     grpc_chttp2_transport_writing *transport_writing,
     grpc_chttp2_stream_writing *stream_writing) {
-  stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
-                  STREAM_FROM_WRITING(stream_writing),
+  grpc_chttp2_stream *stream = STREAM_FROM_WRITING(stream_writing);
+  if (!stream->included[GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT]) {
+    GRPC_CHTTP2_STREAM_REF(&stream->global, "chttp2_writing_stalled");
+  }
+  stream_list_add(TRANSPORT_FROM_WRITING(transport_writing), stream,
                   GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT);
 }
 
 void grpc_chttp2_list_flush_writing_stalled_by_transport(
-    grpc_chttp2_transport_writing *transport_writing,
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
     bool is_window_available) {
   grpc_chttp2_stream *stream;
   grpc_chttp2_transport *transport = TRANSPORT_FROM_WRITING(transport_writing);
   while (stream_list_pop(transport, &stream,
                          GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT)) {
     if (is_window_available) {
-      grpc_chttp2_list_add_writable_stream(&transport->global, &stream->global);
+      grpc_chttp2_become_writable(&transport->global, &stream->global);
     } else {
-      stream_list_add(transport, stream, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
+      grpc_chttp2_list_add_stalled_by_transport(transport_writing,
+                                                &stream->writing);
     }
+    GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &stream->global,
+                             "chttp2_writing_stalled");
   }
 }
 
+void grpc_chttp2_list_add_stalled_by_transport(
+    grpc_chttp2_transport_writing *transport_writing,
+    grpc_chttp2_stream_writing *stream_writing) {
+  stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
+                  STREAM_FROM_WRITING(stream_writing),
+                  GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
+}
+
 int grpc_chttp2_list_pop_stalled_by_transport(
     grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_stream_global **stream_global) {
diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c
index cafecf10465818fd93c63e0cccd1fb4604b3f289..107725cbc797555d8e8d46d05f808faa84a1cc34 100644
--- a/src/core/transport/chttp2/writing.c
+++ b/src/core/transport/chttp2/writing.c
@@ -44,7 +44,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
                             grpc_chttp2_transport_writing *transport_writing);
 
 int grpc_chttp2_unlocking_check_writes(
-    grpc_chttp2_transport_global *transport_global,
+    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_transport_writing *transport_writing, int is_parsing) {
   grpc_chttp2_stream_global *stream_global;
   grpc_chttp2_stream_writing *stream_writing;
@@ -76,14 +76,15 @@ int grpc_chttp2_unlocking_check_writes(
   GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window,
                                   transport_global, outgoing_window);
   bool is_window_available = transport_writing->outgoing_window > 0;
-  grpc_chttp2_list_flush_writing_stalled_by_transport(transport_writing,
-                                                      is_window_available);
+  grpc_chttp2_list_flush_writing_stalled_by_transport(
+      exec_ctx, transport_writing, is_window_available);
 
   /* for each grpc_chttp2_stream that's become writable, frame it's data
      (according to available window sizes) and add to the output buffer */
   while (grpc_chttp2_list_pop_writable_stream(
       transport_global, transport_writing, &stream_global, &stream_writing)) {
-    uint8_t sent_initial_metadata;
+    bool sent_initial_metadata = stream_writing->sent_initial_metadata;
+    bool become_writable = false;
 
     stream_writing->id = stream_global->id;
     stream_writing->read_closed = stream_global->read_closed;
@@ -92,16 +93,12 @@ int grpc_chttp2_unlocking_check_writes(
                                  outgoing_window, stream_global,
                                  outgoing_window);
 
-    sent_initial_metadata = stream_writing->sent_initial_metadata;
     if (!sent_initial_metadata && stream_global->send_initial_metadata) {
       stream_writing->send_initial_metadata =
           stream_global->send_initial_metadata;
       stream_global->send_initial_metadata = NULL;
-      if (grpc_chttp2_list_add_writing_stream(transport_writing,
-                                              stream_writing)) {
-        GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
-      }
-      sent_initial_metadata = 1;
+      become_writable = true;
+      sent_initial_metadata = true;
     }
     if (sent_initial_metadata) {
       if (stream_global->send_message != NULL) {
@@ -128,23 +125,17 @@ int grpc_chttp2_unlocking_check_writes(
            stream_writing->flow_controlled_buffer.length > 0) &&
           stream_writing->outgoing_window > 0) {
         if (transport_writing->outgoing_window > 0) {
-          if (grpc_chttp2_list_add_writing_stream(transport_writing,
-                                                  stream_writing)) {
-            GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
-          }
+          become_writable = true;
         } else {
-          grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing,
-                                                            stream_writing);
+          grpc_chttp2_list_add_stalled_by_transport(transport_writing,
+                                                    stream_writing);
         }
       }
       if (stream_global->send_trailing_metadata) {
         stream_writing->send_trailing_metadata =
             stream_global->send_trailing_metadata;
         stream_global->send_trailing_metadata = NULL;
-        if (grpc_chttp2_list_add_writing_stream(transport_writing,
-                                                stream_writing)) {
-          GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
-        }
+        become_writable = true;
       }
     }
 
@@ -153,10 +144,13 @@ int grpc_chttp2_unlocking_check_writes(
       GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_global, stream_writing,
                                    announce_window, stream_global,
                                    unannounced_incoming_window_for_writing);
-      if (grpc_chttp2_list_add_writing_stream(transport_writing,
-                                              stream_writing)) {
-        GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
-      }
+      become_writable = true;
+    }
+
+    if (become_writable) {
+      grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
+    } else {
+      GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
     }
   }
 
@@ -310,10 +304,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
          (stream_writing->send_message && !stream_writing->fetching)) &&
         stream_writing->outgoing_window > 0) {
       if (transport_writing->outgoing_window > 0) {
-        if (grpc_chttp2_list_add_writing_stream(transport_writing,
-                                                stream_writing)) {
-          /* do nothing - already reffed */
-        }
+        grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
       } else {
         grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing,
                                                           stream_writing);
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index 617d98875c301e2eb5a381d9dc6cd3837b3a4d20..19265252ca36f7029a79784ea0bc763fc9a60cd4 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -142,7 +142,7 @@ static void incoming_byte_stream_update_flow_control(
 static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
                                 grpc_chttp2_stream_global *stream_global);
 
-/*
+/*******************************************************************************
  * CONSTRUCTION/DESTRUCTION/REFCOUNTING
  */
 
@@ -432,6 +432,14 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
     if (t->ep) {
       allow_endpoint_shutdown_locked(exec_ctx, t);
     }
+
+    /* flush writable stream list to avoid dangling references */
+    grpc_chttp2_stream_global *stream_global;
+    grpc_chttp2_stream_writing *stream_writing;
+    while (grpc_chttp2_list_pop_writable_stream(
+        &t->global, &t->writing, &stream_global, &stream_writing)) {
+      GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
+    }
   }
 }
 
@@ -521,7 +529,6 @@ static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
                                            s->global.id) == NULL);
   }
 
-  grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
   grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global,
                                                                 &s->global);
   grpc_chttp2_list_remove_stalled_by_transport(&t->global, &s->global);
@@ -583,7 +590,7 @@ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
   return &accepting->parsing;
 }
 
-/*
+/*******************************************************************************
  * LOCK MANAGEMENT
  */
 
@@ -598,7 +605,7 @@ static void lock(grpc_chttp2_transport *t) { gpr_mu_lock(&t->mu); }
 static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
   GPR_TIMER_BEGIN("unlock", 0);
   if (!t->writing_active && !t->closed &&
-      grpc_chttp2_unlocking_check_writes(&t->global, &t->writing,
+      grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing,
                                          t->parsing_active)) {
     t->writing_active = 1;
     REF_TRANSPORT(t, "writing");
@@ -611,10 +618,18 @@ static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
   GPR_TIMER_END("unlock", 0);
 }
 
-/*
+/*******************************************************************************
  * OUTPUT PROCESSING
  */
 
+void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
+                                 grpc_chttp2_stream_global *stream_global) {
+  if (!TRANSPORT_FROM_GLOBAL(transport_global)->closed &&
+      grpc_chttp2_list_add_writable_stream(transport_global, stream_global)) {
+    GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
+  }
+}
+
 static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
                          uint32_t value) {
   const grpc_chttp2_setting_parameters *sp =
@@ -732,7 +747,7 @@ static void maybe_start_some_streams(
         stream_global->id, STREAM_FROM_GLOBAL(stream_global));
     stream_global->in_stream_map = 1;
     transport_global->concurrent_stream_count++;
-    grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+    grpc_chttp2_become_writable(transport_global, stream_global);
   }
   /* cancel out streams that will never be started */
   while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID &&
@@ -821,7 +836,7 @@ static void perform_stream_op_locked(
         maybe_start_some_streams(exec_ctx, transport_global);
       } else {
         GPR_ASSERT(stream_global->id != 0);
-        grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+        grpc_chttp2_become_writable(transport_global, stream_global);
       }
     } else {
       grpc_chttp2_complete_closure_step(
@@ -838,7 +853,7 @@ static void perform_stream_op_locked(
           exec_ctx, &stream_global->send_message_finished, 0);
     } else if (stream_global->id != 0) {
       stream_global->send_message = op->send_message;
-      grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+      grpc_chttp2_become_writable(transport_global, stream_global);
     }
   }
 
@@ -858,7 +873,7 @@ static void perform_stream_op_locked(
     } else if (stream_global->id != 0) {
       /* TODO(ctiller): check if there's flow control for any outstanding
          bytes before going writable */
-      grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+      grpc_chttp2_become_writable(transport_global, stream_global);
     }
   }
 
@@ -944,12 +959,10 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
   unlock(exec_ctx, t);
 }
 
-static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
-                                 grpc_transport_op *op) {
-  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
-  int close_transport = 0;
-
-  lock(t);
+static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
+                                        grpc_chttp2_transport *t,
+                                        grpc_transport_op *op) {
+  bool close_transport = false;
 
   grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
 
@@ -968,8 +981,8 @@ static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
     close_transport = !grpc_chttp2_has_streams(t);
   }
 
-  if (op->set_accept_stream != NULL) {
-    t->channel_callback.accept_stream = op->set_accept_stream;
+  if (op->set_accept_stream) {
+    t->channel_callback.accept_stream = op->set_accept_stream_fn;
     t->channel_callback.accept_stream_user_data =
         op->set_accept_stream_user_data;
   }
@@ -990,16 +1003,31 @@ static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
     close_transport_locked(exec_ctx, t);
   }
 
-  unlock(exec_ctx, t);
-
   if (close_transport) {
-    lock(t);
     close_transport_locked(exec_ctx, t);
-    unlock(exec_ctx, t);
   }
 }
 
-/*
+static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+                                 grpc_transport_op *op) {
+  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
+
+  lock(t);
+
+  /* If there's a set_accept_stream ensure that we're not parsing
+     to avoid changing things out from underneath */
+  if (t->parsing_active && op->set_accept_stream) {
+    GPR_ASSERT(t->post_parsing_op == NULL);
+    t->post_parsing_op = gpr_malloc(sizeof(*op));
+    memcpy(t->post_parsing_op, op, sizeof(*op));
+  } else {
+    perform_transport_op_locked(exec_ctx, t, op);
+  }
+
+  unlock(exec_ctx, t);
+}
+
+/*******************************************************************************
  * INPUT PROCESSING
  */
 
@@ -1019,6 +1047,11 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
       stream_global->recv_initial_metadata_ready = NULL;
     }
     if (stream_global->recv_message_ready != NULL) {
+      while (stream_global->seen_error &&
+             (bs = grpc_chttp2_incoming_frame_queue_pop(
+                  &stream_global->incoming_frames)) != NULL) {
+        grpc_byte_stream_destroy(exec_ctx, bs);
+      }
       if (stream_global->incoming_frames.head != NULL) {
         *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop(
             &stream_global->incoming_frames);
@@ -1059,7 +1092,6 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
   if (!s) {
     s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
   }
-  grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
   GPR_ASSERT(s);
   s->global.in_stream_map = 0;
   if (t->parsing.incoming_stream == &s->parsing) {
@@ -1075,6 +1107,9 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
   if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
     close_transport_locked(exec_ctx, t);
   }
+  if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) {
+    GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing");
+  }
 
   new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
                      grpc_chttp2_stream_map_size(&t->new_stream_map);
@@ -1326,7 +1361,7 @@ static void update_global_window(void *args, uint32_t id, void *stream) {
   is_zero = stream_global->outgoing_window <= 0;
 
   if (was_zero && !is_zero) {
-    grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+    grpc_chttp2_become_writable(transport_global, stream_global);
   }
 }
 
@@ -1387,6 +1422,13 @@ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
     /* handle higher level things */
     grpc_chttp2_publish_reads(exec_ctx, transport_global, transport_parsing);
     t->parsing_active = 0;
+    /* handle delayed transport ops (if there is one) */
+    if (t->post_parsing_op) {
+      grpc_transport_op *op = t->post_parsing_op;
+      t->post_parsing_op = NULL;
+      perform_transport_op_locked(exec_ctx, t, op);
+      gpr_free(op);
+    }
     /* if a stream is in the stream map, and gets cancelled, we need to ensure
      * we are not parsing before continuing the cancellation to keep things in
      * a sane state */
@@ -1421,7 +1463,7 @@ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
   GPR_TIMER_END("recv_data", 0);
 }
 
-/*
+/*******************************************************************************
  * CALLBACK LOOP
  */
 
@@ -1435,7 +1477,7 @@ static void connectivity_state_set(
                               state, reason);
 }
 
-/*
+/*******************************************************************************
  * POLLSET STUFF
  */
 
@@ -1463,7 +1505,7 @@ static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
   unlock(exec_ctx, t);
 }
 
-/*
+/*******************************************************************************
  * BYTE STREAM
  */
 
@@ -1503,7 +1545,7 @@ static void incoming_byte_stream_update_flow_control(
                                    add_max_recv_bytes);
     grpc_chttp2_list_add_unannounced_incoming_window_available(transport_global,
                                                                stream_global);
-    grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
+    grpc_chttp2_become_writable(transport_global, stream_global);
   }
 }
 
@@ -1618,7 +1660,7 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
   return incoming_byte_stream;
 }
 
-/*
+/*******************************************************************************
  * TRACING
  */
 
@@ -1704,7 +1746,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
   gpr_free(prefix);
 }
 
-/*
+/*******************************************************************************
  * INTEGRATION GLUE
  */
 
diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c
index 14912af7df1cafddded3581dac73f1ba57d74ed0..807ae071a309627b16f73ccee0b48c893b6896bb 100644
--- a/src/core/transport/metadata.c
+++ b/src/core/transport/metadata.c
@@ -43,11 +43,13 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/time.h>
+
 #include "src/core/profiling/timers.h"
 #include "src/core/support/murmur_hash.h"
 #include "src/core/support/string.h"
 #include "src/core/transport/chttp2/bin_encoder.h"
 #include "src/core/transport/static_metadata.h"
+#include "src/core/iomgr/iomgr_internal.h"
 
 /* There are two kinds of mdelem and mdstr instances.
  * Static instances are declared in static_metadata.{h,c} and
@@ -227,6 +229,9 @@ void grpc_mdctx_global_shutdown(void) {
     if (shard->count != 0) {
       gpr_log(GPR_DEBUG, "WARNING: %d metadata elements were leaked",
               shard->count);
+      if (grpc_iomgr_abort_on_leaks()) {
+        abort();
+      }
     }
     gpr_free(shard->elems);
   }
@@ -237,6 +242,9 @@ void grpc_mdctx_global_shutdown(void) {
     if (shard->count != 0) {
       gpr_log(GPR_DEBUG, "WARNING: %d metadata strings were leaked",
               shard->count);
+      if (grpc_iomgr_abort_on_leaks()) {
+        abort();
+      }
     }
     gpr_free(shard->strs);
   }
diff --git a/src/core/transport/transport.c b/src/core/transport/transport.c
index 6e154b629ab872ab57a4561d822094cf8baa2982..3b555fa9338c3eb9c7f453f14efe45fe6212db5d 100644
--- a/src/core/transport/transport.c
+++ b/src/core/transport/transport.c
@@ -45,7 +45,7 @@ void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) {
 #else
 void grpc_stream_ref(grpc_stream_refcount *refcount) {
 #endif
-  gpr_ref(&refcount->refs);
+  gpr_ref_non_zero(&refcount->refs);
 }
 
 #ifdef GRPC_STREAM_REFCOUNT_DEBUG
diff --git a/src/core/transport/transport.h b/src/core/transport/transport.h
index 8902c5d2f65f886e5535bc2fe2edc2631aee2941..ed6e121c9cbb685e4b7e109a7f92110320f9c424 100644
--- a/src/core/transport/transport.h
+++ b/src/core/transport/transport.h
@@ -123,7 +123,7 @@ typedef struct grpc_transport_stream_op {
 
 /** Transport op: a set of operations to perform on a transport as a whole */
 typedef struct grpc_transport_op {
-  /** called when processing of this op is done */
+  /** Called when processing of this op is done. */
   grpc_closure *on_consumed;
   /** connectivity monitoring - set connectivity_state to NULL to unsubscribe */
   grpc_closure *on_connectivity_state_change;
@@ -138,9 +138,13 @@ typedef struct grpc_transport_op {
   grpc_status_code goaway_status;
   gpr_slice *goaway_message;
   /** set the callback for accepting new streams;
-      this is a permanent callback, unlike the other one-shot closures */
-  void (*set_accept_stream)(grpc_exec_ctx *exec_ctx, void *user_data,
-                            grpc_transport *transport, const void *server_data);
+      this is a permanent callback, unlike the other one-shot closures.
+      If true, the callback is set to set_accept_stream_fn, with its
+      user_data argument set to set_accept_stream_user_data */
+  bool set_accept_stream;
+  void (*set_accept_stream_fn)(grpc_exec_ctx *exec_ctx, void *user_data,
+                               grpc_transport *transport,
+                               const void *server_data);
   void *set_accept_stream_user_data;
   /** add this transport to a pollset */
   grpc_pollset *bind_pollset;
diff --git a/src/cpp/README.md b/src/cpp/README.md
index baeba0831555228bc6789a557511930e66082ce1..83d37aa2ed8b9459163d9993de985159273fd096 100644
--- a/src/cpp/README.md
+++ b/src/cpp/README.md
@@ -6,3 +6,77 @@ This directory contains source code for C++ implementation of gRPC.
 #Status
 
 Beta
+
+#Pre-requisites
+
+##Linux
+
+```sh
+ $ [sudo] apt-get install build-essential autoconf libtool
+```
+
+##Mac OSX
+
+For a Mac system, git is not available by default. You will first need to
+install Xcode from the Mac AppStore and then run the following command from a
+terminal:
+
+```sh
+ $ [sudo] xcode-select --install
+```
+
+##Protoc
+
+By default gRPC uses [protocol buffers](https://github.com/google/protobuf),
+you will need the `protoc` compiler to generate stub server and client code.
+
+If you compile gRPC from source, as described below, this also installs the
+`protoc` compiler.
+
+If it hasn't been installed, you can run the following commands to install it.
+
+```sh
+$ cd grpc/third_party/protobuf
+$ sudo make install   # 'make' should have been run by core grpc
+```
+
+Alternatively, you can download `protoc` binaries from
+[the protocol buffers Github repository](https://github.com/google/protobuf/releases).
+
+#Installation
+
+Currently to install gRPC for C++, you need to build from source as described
+below.
+
+#Build from Source
+
+```sh
+ $ git clone https://github.com/grpc/grpc.git
+ $ cd grpc
+ $ git submodule update --init
+ $ make
+ $ [sudo] make install
+```
+
+#Documentation
+
+You can find out how to build and run our simplest gRPC C++ example in our
+[C++ quick start](https://github.com/grpc/grpc/tree/{{ site.data.config.grpc_release_branch }}/examples/cpp).
+
+For more detailed documentation on using gRPC in C++ , see our main
+documentation site at [grpc.io](http://grpc.io), specifically:
+
+* [Overview](http://www.grpc.io/docs/): An introduction to gRPC with a simple
+  Hello World example in all our supported languages, including C++.
+* [gRPC Basics - C++](http://www.grpc.io/docs/tutorials/basic/c.html):
+  A tutorial that steps you through creating a simple gRPC C++ example
+  application.
+* [Asynchronous Basics - C++](http://www.grpc.io/docs/tutorials/async/helloasync-cpp.html):
+  A tutorial that shows you how to use gRPC C++'s asynchronous/non-blocking
+  APIs.
+
+
+# Examples
+
+Code examples for gRPC C++ live in this repository's
+[examples/cpp](https://github.com/grpc/grpc/tree/{{ site.data.config.grpc_release_branch }}/examples/cpp) directory.
diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc
index 0d31140924bfcc8286a0b5c9467f06cc89af7801..6d31a608c803ded3b473e1a9ba8e9fa60e277bf1 100644
--- a/src/cpp/server/server.cc
+++ b/src/cpp/server/server.cc
@@ -272,27 +272,25 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
   grpc_completion_queue* cq_;
 };
 
-static grpc_server* CreateServer(const ChannelArguments& args) {
-  grpc_channel_args channel_args;
-  args.SetChannelArgs(&channel_args);
-  return grpc_server_create(&channel_args, nullptr);
-}
-
 static internal::GrpcLibraryInitializer g_gli_initializer;
 Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
-               int max_message_size, const ChannelArguments& args)
+               int max_message_size, ChannelArguments* args)
     : max_message_size_(max_message_size),
       started_(false),
       shutdown_(false),
       num_running_cb_(0),
       sync_methods_(new std::list<SyncRequest>),
       has_generic_service_(false),
-      server_(CreateServer(args)),
+      server_(nullptr),
       thread_pool_(thread_pool),
       thread_pool_owned_(thread_pool_owned) {
   g_gli_initializer.summon();
   gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
   global_callbacks_ = g_callbacks;
+  global_callbacks_->UpdateArguments(args);
+  grpc_channel_args channel_args;
+  args->SetChannelArgs(&channel_args);
+  server_ = grpc_server_create(&channel_args, nullptr);
   grpc_server_register_completion_queue(server_, cq_.cq(), nullptr);
 }
 
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index c54cf6474f1af1116d6de72c305424d2559c948a..134e5f1d5ff2e4fd08029413a6e5c6a189583c76 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -103,7 +103,7 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
   args.SetInt(GRPC_COMPRESSION_ALGORITHM_STATE_ARG,
               compression_options_.enabled_algorithms_bitset);
   std::unique_ptr<Server> server(
-      new Server(thread_pool.release(), true, max_message_size_, args));
+      new Server(thread_pool.release(), true, max_message_size_, &args));
   for (auto cq = cqs_.begin(); cq != cqs_.end(); ++cq) {
     grpc_server_register_completion_queue(server->server_, (*cq)->cq(),
                                           nullptr);
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
index b72cbd795f639f5737eb941a792dc01aab59a271..9380c0d0ea9f51f7fff01e4533f159152cd1564b 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
@@ -193,16 +193,6 @@ namespace Grpc.Core.Internal
             lock (myLock)
             {
                 finished = true;
-
-                if (cancelled)
-                {
-                    // Once we cancel, we don't have to care that much 
-                    // about reads and writes.
-
-                    // TODO(jtattermusch): is this still necessary?
-                    Cancel();
-                }
-
                 ReleaseResourcesIfPossible();
             }
             // TODO(jtattermusch): handle error
diff --git a/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs b/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs
index eeaa7add81395e71939995ca85d44d48a10bd5e7..dfaee5d9d7cd207d52a28e2c4f2795bf82459402 100644
--- a/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs
+++ b/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs
@@ -56,7 +56,7 @@ namespace Grpc.Core.Internal
         {
             lock (staticLock)
             {
-                var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(RootsPemResourceName);
+                var stream = typeof(DefaultSslRootsOverride).GetTypeInfo().Assembly.GetManifestResourceStream(RootsPemResourceName);
                 if (stream == null)
                 {
                     throw new IOException(string.Format("Error loading the embedded resource \"{0}\"", RootsPemResourceName));   
diff --git a/src/csharp/Grpc.Core/Internal/PlatformApis.cs b/src/csharp/Grpc.Core/Internal/PlatformApis.cs
index f0c5b0f63f61e1d15d0d04137f279c64477d1e5d..fb1acfb607b23925900c2d211746fa0bed32e365 100644
--- a/src/csharp/Grpc.Core/Internal/PlatformApis.cs
+++ b/src/csharp/Grpc.Core/Internal/PlatformApis.cs
@@ -53,12 +53,18 @@ namespace Grpc.Core.Internal
 
         static PlatformApis()
         {
+#if DNXCORE50
+            isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
+            isMacOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
+            isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+#else
             var platform = Environment.OSVersion.Platform;
 
             // PlatformID.MacOSX is never returned, commonly used trick is to identify Mac is by using uname.
             isMacOSX = (platform == PlatformID.Unix && GetUname() == "Darwin");
             isLinux = (platform == PlatformID.Unix && !isMacOSX);
             isWindows = (platform == PlatformID.Win32NT || platform == PlatformID.Win32S || platform == PlatformID.Win32Windows);
+#endif
             isMono = Type.GetType("Mono.Runtime") != null;
         }
 
diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
index a8a76c749229468a56bd246d39ca2c7cdc19e087..c3fac05324c8245694c425eb88cab306dcc7f641 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
+++ b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
@@ -36,7 +36,7 @@ using System.Text;
 using System.Threading.Tasks;
 
 using Grpc.Core;
-using Grpc.Health.V1Alpha;
+using Grpc.Health.V1;
 using NUnit.Framework;
 
 namespace Grpc.HealthCheck.Tests
@@ -49,7 +49,7 @@ namespace Grpc.HealthCheck.Tests
         const string Host = "localhost";
         Server server;
         Channel channel;
-        Grpc.Health.V1Alpha.Health.IHealthClient client;
+        Grpc.Health.V1.Health.IHealthClient client;
         Grpc.HealthCheck.HealthServiceImpl serviceImpl;
 
         [TestFixtureSetUp]
@@ -59,13 +59,13 @@ namespace Grpc.HealthCheck.Tests
 
             server = new Server
             {
-                Services = { Grpc.Health.V1Alpha.Health.BindService(serviceImpl) },
+                Services = { Grpc.Health.V1.Health.BindService(serviceImpl) },
                 Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
             };
             server.Start();
             channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure);
 
-            client = Grpc.Health.V1Alpha.Health.NewClient(channel);
+            client = Grpc.Health.V1.Health.NewClient(channel);
         }
 
         [TestFixtureTearDown]
@@ -79,16 +79,16 @@ namespace Grpc.HealthCheck.Tests
         [Test]
         public void ServiceIsRunning()
         {
-            serviceImpl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.SERVING);
+            serviceImpl.SetStatus("", HealthCheckResponse.Types.ServingStatus.SERVING);
 
-            var response = client.Check(new HealthCheckRequest { Host = "", Service = "" });
+            var response = client.Check(new HealthCheckRequest { Service = "" });
             Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, response.Status);
         }
 
         [Test]
         public void ServiceDoesntExist()
         {
-            Assert.Throws(Is.TypeOf(typeof(RpcException)).And.Property("Status").Property("StatusCode").EqualTo(StatusCode.NotFound), () => client.Check(new HealthCheckRequest { Host = "", Service = "nonexistent.service" }));
+            Assert.Throws(Is.TypeOf(typeof(RpcException)).And.Property("Status").Property("StatusCode").EqualTo(StatusCode.NotFound), () => client.Check(new HealthCheckRequest { Service = "nonexistent.service" }));
         }
 
         // TODO(jtattermusch): add test with timeout once timeouts are supported
diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
index 2097c0dc8cf7daa2c79f72a4706299af0ee76d0d..47e4b7c2a70194bb84232f42db9588756c6dffca 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
+++ b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs
@@ -1,5 +1,5 @@
 #region Copyright notice and license
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,7 @@ using System.Text;
 using System.Threading.Tasks;
 
 using Grpc.Core;
-using Grpc.Health.V1Alpha;
+using Grpc.Health.V1;
 using NUnit.Framework;
 
 namespace Grpc.HealthCheck.Tests
@@ -50,58 +50,56 @@ namespace Grpc.HealthCheck.Tests
         public void SetStatus()
         {
             var impl = new HealthServiceImpl();
-            impl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.SERVING);
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, GetStatusHelper(impl, "", ""));
+            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.SERVING);
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, GetStatusHelper(impl, ""));
 
-            impl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.NOT_SERVING);
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NOT_SERVING, GetStatusHelper(impl, "", ""));
+            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.NOT_SERVING);
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NOT_SERVING, GetStatusHelper(impl, ""));
 
-            impl.SetStatus("virtual-host", "", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.UNKNOWN, GetStatusHelper(impl, "virtual-host", ""));
+            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.UNKNOWN, GetStatusHelper(impl, ""));
 
-            impl.SetStatus("virtual-host", "grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.SERVING);
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, GetStatusHelper(impl, "virtual-host", "grpc.test.TestService"));
+            impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.SERVING);
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, GetStatusHelper(impl, "grpc.test.TestService"));
         }
 
         [Test]
         public void ClearStatus()
         {
             var impl = new HealthServiceImpl();
-            impl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.SERVING);
-            impl.SetStatus("virtual-host", "", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
+            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.SERVING);
+            impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
 
-            impl.ClearStatus("", "");
+            impl.ClearStatus("");
 
-            Assert.Throws(Is.TypeOf(typeof(RpcException)).And.Property("Status").Property("StatusCode").EqualTo(StatusCode.NotFound), () => GetStatusHelper(impl, "", ""));
-            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.UNKNOWN, GetStatusHelper(impl, "virtual-host", ""));
+            Assert.Throws(Is.TypeOf(typeof(RpcException)).And.Property("Status").Property("StatusCode").EqualTo(StatusCode.NotFound), () => GetStatusHelper(impl, ""));
+            Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.UNKNOWN, GetStatusHelper(impl, "grpc.test.TestService"));
         }
 
         [Test]
         public void ClearAll()
         {
             var impl = new HealthServiceImpl();
-            impl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.SERVING);
-            impl.SetStatus("virtual-host", "", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
+            impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.SERVING);
+            impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.UNKNOWN);
 
             impl.ClearAll();
-            Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, "", ""));
-            Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, "virtual-host", ""));
+            Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, ""));
+            Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, "grpc.test.TestService"));
         }
 
         [Test]
         public void NullsRejected()
         {
             var impl = new HealthServiceImpl();
-            Assert.Throws(typeof(ArgumentNullException), () => impl.SetStatus(null, "", HealthCheckResponse.Types.ServingStatus.SERVING));
-            Assert.Throws(typeof(ArgumentNullException), () => impl.SetStatus("", null, HealthCheckResponse.Types.ServingStatus.SERVING));
+            Assert.Throws(typeof(ArgumentNullException), () => impl.SetStatus(null, HealthCheckResponse.Types.ServingStatus.SERVING));
 
-            Assert.Throws(typeof(ArgumentNullException), () => impl.ClearStatus(null, ""));
-            Assert.Throws(typeof(ArgumentNullException), () => impl.ClearStatus("", null));
+            Assert.Throws(typeof(ArgumentNullException), () => impl.ClearStatus(null));
         }
 
-        private static HealthCheckResponse.Types.ServingStatus GetStatusHelper(HealthServiceImpl impl, string host, string service)
+        private static HealthCheckResponse.Types.ServingStatus GetStatusHelper(HealthServiceImpl impl, string service)
         {
-            return impl.Check(new HealthCheckRequest { Host = host, Service = service }, null).Result.Status;
+            return impl.Check(new HealthCheckRequest { Service = service }, null).Result.Status;
         }
     }
 }
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
index 66386288df132f448b0dee70305b15ae41e0c824..7b3b391009eb05ca1ba9a85aceec8b829d22939b 100644
--- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
@@ -4,7 +4,7 @@
     <id>Grpc.HealthCheck</id>
     <title>gRPC C# Healthchecking</title>
     <summary>Implementation of gRPC health service</summary>
-    <description>Example implementation of grpc.health.v1alpha service that can be used for health-checking.</description>
+    <description>Example implementation of grpc.health.v1 service that can be used for health-checking.</description>
     <version>$version$</version>
     <authors>Google Inc.</authors>
     <owners>grpc-packages</owners>
diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs
index 56673f1adf699bef3998cae252799bcbe7d3bfe5..d0d0c0b519665376069e283e7ae90f347c4b127a 100644
--- a/src/csharp/Grpc.HealthCheck/Health.cs
+++ b/src/csharp/Grpc.HealthCheck/Health.cs
@@ -7,7 +7,7 @@ using pb = global::Google.Protobuf;
 using pbc = global::Google.Protobuf.Collections;
 using pbr = global::Google.Protobuf.Reflection;
 using scg = global::System.Collections.Generic;
-namespace Grpc.Health.V1Alpha {
+namespace Grpc.Health.V1 {
 
   /// <summary>Holder for reflection information generated from health.proto</summary>
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
@@ -23,20 +23,19 @@ namespace Grpc.Health.V1Alpha {
     static HealthReflection() {
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
-            "CgxoZWFsdGgucHJvdG8SE2dycGMuaGVhbHRoLnYxYWxwaGEiMwoSSGVhbHRo",
-            "Q2hlY2tSZXF1ZXN0EgwKBGhvc3QYASABKAkSDwoHc2VydmljZRgCIAEoCSKZ",
-            "AQoTSGVhbHRoQ2hlY2tSZXNwb25zZRJGCgZzdGF0dXMYASABKA4yNi5ncnBj",
-            "LmhlYWx0aC52MWFscGhhLkhlYWx0aENoZWNrUmVzcG9uc2UuU2VydmluZ1N0",
-            "YXR1cyI6Cg1TZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5H",
-            "EAESDwoLTk9UX1NFUlZJTkcQAjJkCgZIZWFsdGgSWgoFQ2hlY2sSJy5ncnBj",
-            "LmhlYWx0aC52MWFscGhhLkhlYWx0aENoZWNrUmVxdWVzdBooLmdycGMuaGVh",
-            "bHRoLnYxYWxwaGEuSGVhbHRoQ2hlY2tSZXNwb25zZUIWqgITR3JwYy5IZWFs",
-            "dGguVjFBbHBoYWIGcHJvdG8z"));
+            "CgxoZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYxIiUKEkhlYWx0aENoZWNr",
+            "UmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIpQBChNIZWFsdGhDaGVja1Jlc3Bv",
+            "bnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVhbHRoLnYxLkhlYWx0aENo",
+            "ZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyI6Cg1TZXJ2aW5nU3RhdHVzEgsK",
+            "B1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9UX1NFUlZJTkcQAjJaCgZI",
+            "ZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52MS5IZWFsdGhDaGVja1Jl",
+            "cXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhDaGVja1Jlc3BvbnNlQhGq",
+            "Ag5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Health.V1Alpha.HealthCheckRequest), global::Grpc.Health.V1Alpha.HealthCheckRequest.Parser, new[]{ "Host", "Service" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Health.V1Alpha.HealthCheckResponse), global::Grpc.Health.V1Alpha.HealthCheckResponse.Parser, new[]{ "Status" }, null, new[]{ typeof(global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus) }, null)
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Health.V1.HealthCheckRequest), global::Grpc.Health.V1.HealthCheckRequest.Parser, new[]{ "Service" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Health.V1.HealthCheckResponse), global::Grpc.Health.V1.HealthCheckResponse.Parser, new[]{ "Status" }, null, new[]{ typeof(global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) }, null)
           }));
     }
     #endregion
@@ -49,7 +48,7 @@ namespace Grpc.Health.V1Alpha {
     public static pb::MessageParser<HealthCheckRequest> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Health.V1Alpha.HealthReflection.Descriptor.MessageTypes[0]; }
+      get { return global::Grpc.Health.V1.HealthReflection.Descriptor.MessageTypes[0]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -63,7 +62,6 @@ namespace Grpc.Health.V1Alpha {
     partial void OnConstruction();
 
     public HealthCheckRequest(HealthCheckRequest other) : this() {
-      host_ = other.host_;
       service_ = other.service_;
     }
 
@@ -71,18 +69,8 @@ namespace Grpc.Health.V1Alpha {
       return new HealthCheckRequest(this);
     }
 
-    /// <summary>Field number for the "host" field.</summary>
-    public const int HostFieldNumber = 1;
-    private string host_ = "";
-    public string Host {
-      get { return host_; }
-      set {
-        host_ = pb::Preconditions.CheckNotNull(value, "value");
-      }
-    }
-
     /// <summary>Field number for the "service" field.</summary>
-    public const int ServiceFieldNumber = 2;
+    public const int ServiceFieldNumber = 1;
     private string service_ = "";
     public string Service {
       get { return service_; }
@@ -102,14 +90,12 @@ namespace Grpc.Health.V1Alpha {
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      if (Host != other.Host) return false;
       if (Service != other.Service) return false;
       return true;
     }
 
     public override int GetHashCode() {
       int hash = 1;
-      if (Host.Length != 0) hash ^= Host.GetHashCode();
       if (Service.Length != 0) hash ^= Service.GetHashCode();
       return hash;
     }
@@ -119,21 +105,14 @@ namespace Grpc.Health.V1Alpha {
     }
 
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Host.Length != 0) {
-        output.WriteRawTag(10);
-        output.WriteString(Host);
-      }
       if (Service.Length != 0) {
-        output.WriteRawTag(18);
+        output.WriteRawTag(10);
         output.WriteString(Service);
       }
     }
 
     public int CalculateSize() {
       int size = 0;
-      if (Host.Length != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeStringSize(Host);
-      }
       if (Service.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Service);
       }
@@ -144,9 +123,6 @@ namespace Grpc.Health.V1Alpha {
       if (other == null) {
         return;
       }
-      if (other.Host.Length != 0) {
-        Host = other.Host;
-      }
       if (other.Service.Length != 0) {
         Service = other.Service;
       }
@@ -160,10 +136,6 @@ namespace Grpc.Health.V1Alpha {
             input.SkipLastField();
             break;
           case 10: {
-            Host = input.ReadString();
-            break;
-          }
-          case 18: {
             Service = input.ReadString();
             break;
           }
@@ -179,7 +151,7 @@ namespace Grpc.Health.V1Alpha {
     public static pb::MessageParser<HealthCheckResponse> Parser { get { return _parser; } }
 
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Grpc.Health.V1Alpha.HealthReflection.Descriptor.MessageTypes[1]; }
+      get { return global::Grpc.Health.V1.HealthReflection.Descriptor.MessageTypes[1]; }
     }
 
     pbr::MessageDescriptor pb::IMessage.Descriptor {
@@ -202,8 +174,8 @@ namespace Grpc.Health.V1Alpha {
 
     /// <summary>Field number for the "status" field.</summary>
     public const int StatusFieldNumber = 1;
-    private global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus status_ = global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN;
-    public global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus Status {
+    private global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus status_ = global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.UNKNOWN;
+    public global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus Status {
       get { return status_; }
       set {
         status_ = value;
@@ -227,7 +199,7 @@ namespace Grpc.Health.V1Alpha {
 
     public override int GetHashCode() {
       int hash = 1;
-      if (Status != global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN) hash ^= Status.GetHashCode();
+      if (Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.UNKNOWN) hash ^= Status.GetHashCode();
       return hash;
     }
 
@@ -236,7 +208,7 @@ namespace Grpc.Health.V1Alpha {
     }
 
     public void WriteTo(pb::CodedOutputStream output) {
-      if (Status != global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN) {
+      if (Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.UNKNOWN) {
         output.WriteRawTag(8);
         output.WriteEnum((int) Status);
       }
@@ -244,7 +216,7 @@ namespace Grpc.Health.V1Alpha {
 
     public int CalculateSize() {
       int size = 0;
-      if (Status != global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN) {
+      if (Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.UNKNOWN) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status);
       }
       return size;
@@ -254,7 +226,7 @@ namespace Grpc.Health.V1Alpha {
       if (other == null) {
         return;
       }
-      if (other.Status != global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN) {
+      if (other.Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.UNKNOWN) {
         Status = other.Status;
       }
     }
@@ -267,7 +239,7 @@ namespace Grpc.Health.V1Alpha {
             input.SkipLastField();
             break;
           case 8: {
-            status_ = (global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus) input.ReadEnum();
+            status_ = (global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) input.ReadEnum();
             break;
           }
         }
diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
index 882edd56270b6fbb2173c5b6cfcf058a3dd7e8df..68320eb5c2effa410693eec82851005105a854b7 100644
--- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
+++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
@@ -7,15 +7,15 @@ using System.Threading;
 using System.Threading.Tasks;
 using Grpc.Core;
 
-namespace Grpc.Health.V1Alpha {
+namespace Grpc.Health.V1 {
   public static class Health
   {
-    static readonly string __ServiceName = "grpc.health.v1alpha.Health";
+    static readonly string __ServiceName = "grpc.health.v1.Health";
 
-    static readonly Marshaller<global::Grpc.Health.V1Alpha.HealthCheckRequest> __Marshaller_HealthCheckRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Health.V1Alpha.HealthCheckRequest.Parser.ParseFrom);
-    static readonly Marshaller<global::Grpc.Health.V1Alpha.HealthCheckResponse> __Marshaller_HealthCheckResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Health.V1Alpha.HealthCheckResponse.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Health.V1.HealthCheckRequest> __Marshaller_HealthCheckRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Health.V1.HealthCheckRequest.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Health.V1.HealthCheckResponse> __Marshaller_HealthCheckResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Health.V1.HealthCheckResponse.Parser.ParseFrom);
 
-    static readonly Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse> __Method_Check = new Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse>(
+    static readonly Method<global::Grpc.Health.V1.HealthCheckRequest, global::Grpc.Health.V1.HealthCheckResponse> __Method_Check = new Method<global::Grpc.Health.V1.HealthCheckRequest, global::Grpc.Health.V1.HealthCheckResponse>(
         MethodType.Unary,
         __ServiceName,
         "Check",
@@ -25,22 +25,22 @@ namespace Grpc.Health.V1Alpha {
     // service descriptor
     public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
     {
-      get { return global::Grpc.Health.V1Alpha.HealthReflection.Descriptor.Services[0]; }
+      get { return global::Grpc.Health.V1.HealthReflection.Descriptor.Services[0]; }
     }
 
     // client interface
     public interface IHealthClient
     {
-      global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
-      global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options);
-      AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
-      AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options);
+      global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options);
+      AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options);
     }
 
     // server-side interface
     public interface IHealth
     {
-      Task<global::Grpc.Health.V1Alpha.HealthCheckResponse> Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, ServerCallContext context);
+      Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context);
     }
 
     // client stub
@@ -49,22 +49,22 @@ namespace Grpc.Health.V1Alpha {
       public HealthClient(Channel channel) : base(channel)
       {
       }
-      public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
         return Calls.BlockingUnaryCall(call, request);
       }
-      public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options)
+      public global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
       {
         var call = CreateCall(__Method_Check, options);
         return Calls.BlockingUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      public AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
         return Calls.AsyncUnaryCall(call, request);
       }
-      public AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, CallOptions options)
+      public AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
       {
         var call = CreateCall(__Method_Check, options);
         return Calls.AsyncUnaryCall(call, request);
diff --git a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
index e2ad1a834bfd57c9943c369e8c7dd91e476f5802..21482b302b4dcc1659e5ea33cb2d08e52f0e1412 100644
--- a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
+++ b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
@@ -37,7 +37,7 @@ using System.Threading.Tasks;
 
 using Grpc.Core;
 using Grpc.Core.Utils;
-using Grpc.Health.V1Alpha;
+using Grpc.Health.V1;
 
 namespace Grpc.HealthCheck
 {
@@ -48,44 +48,42 @@ namespace Grpc.HealthCheck
     /// <code>
     /// var serviceImpl = new HealthServiceImpl();
     /// server = new Server();
-    /// server.AddServiceDefinition(Grpc.Health.V1Alpha.Health.BindService(serviceImpl));
+    /// server.AddServiceDefinition(Grpc.Health.V1.Health.BindService(serviceImpl));
     /// </code>
     /// </summary>
-    public class HealthServiceImpl : Grpc.Health.V1Alpha.Health.IHealth
+    public class HealthServiceImpl : Grpc.Health.V1.Health.IHealth
     {
         private readonly object myLock = new object();
-        private readonly Dictionary<Key, HealthCheckResponse.Types.ServingStatus> statusMap = 
-            new Dictionary<Key, HealthCheckResponse.Types.ServingStatus>();
+        private readonly Dictionary<string, HealthCheckResponse.Types.ServingStatus> statusMap = 
+            new Dictionary<string, HealthCheckResponse.Types.ServingStatus>();
 
         /// <summary>
-        /// Sets the health status for given host and service.
+        /// Sets the health status for given service.
         /// </summary>
-        /// <param name="host">The host. Cannot be null.</param>
         /// <param name="service">The service. Cannot be null.</param>
         /// <param name="status">the health status</param>
-        public void SetStatus(string host, string service, HealthCheckResponse.Types.ServingStatus status)
+        public void SetStatus(string service, HealthCheckResponse.Types.ServingStatus status)
         {
             lock (myLock)
             {
-                statusMap[CreateKey(host, service)] = status;
+                statusMap[service] = status;
             }
         }
 
         /// <summary>
-        /// Clears health status for given host and service.
+        /// Clears health status for given service.
         /// </summary>
-        /// <param name="host">The host. Cannot be null.</param>
         /// <param name="service">The service. Cannot be null.</param>
-        public void ClearStatus(string host, string service)
+        public void ClearStatus(string service)
         {
             lock (myLock)
             {
-                statusMap.Remove(CreateKey(host, service));
+                statusMap.Remove(service);
             }
         }
         
         /// <summary>
-        /// Clears statuses for all hosts and services.
+        /// Clears statuses for all services.
         /// </summary>
         public void ClearAll()
         {
@@ -105,11 +103,10 @@ namespace Grpc.HealthCheck
         {
             lock (myLock)
             {
-                var host = request.Host;
                 var service = request.Service;
 
                 HealthCheckResponse.Types.ServingStatus status;
-                if (!statusMap.TryGetValue(CreateKey(host, service), out status))
+                if (!statusMap.TryGetValue(service, out status))
                 {
                     // TODO(jtattermusch): returning specific status from server handler is not supported yet.
                     throw new RpcException(new Status(StatusCode.NotFound, ""));
@@ -117,22 +114,5 @@ namespace Grpc.HealthCheck
                 return Task.FromResult(new HealthCheckResponse { Status = status });
             }
         }
-
-        private static Key CreateKey(string host, string service)
-        {
-            return new Key(host, service);
-        }
-
-        private struct Key
-        {
-            public Key(string host, string service)
-            {
-                this.Host = GrpcPreconditions.CheckNotNull(host);
-                this.Service = GrpcPreconditions.CheckNotNull(service);
-            }
-
-            readonly string Host;
-            readonly string Service;
-        }
     }
 }
diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs
index b90243c2bd501c49c89e0d1e0b45d9bb131213c5..291bc753978b74a1466b9d97fb6bb32e5cb53c71 100644
--- a/src/csharp/Grpc.IntegrationTesting/Control.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Control.cs
@@ -38,7 +38,7 @@ namespace Grpc.Testing {
             "LmdycGMudGVzdGluZy5EZXRlcm1pbmlzdGljUGFyYW1zSAASLAoGcGFyZXRv",
             "GAUgASgLMhouZ3JwYy50ZXN0aW5nLlBhcmV0b1BhcmFtc0gAQgYKBGxvYWQi",
             "QwoOU2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2Vy",
-            "dmVyX2hvc3Rfb3ZlcnJpZGUYAiABKAkirwMKDENsaWVudENvbmZpZxIWCg5z",
+            "dmVyX2hvc3Rfb3ZlcnJpZGUYAiABKAki1gMKDENsaWVudENvbmZpZxIWCg5z",
             "ZXJ2ZXJfdGFyZ2V0cxgBIAMoCRItCgtjbGllbnRfdHlwZRgCIAEoDjIYLmdy",
             "cGMudGVzdGluZy5DbGllbnRUeXBlEjUKD3NlY3VyaXR5X3BhcmFtcxgDIAEo",
             "CzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIkChxvdXRzdGFuZGlu",
@@ -48,24 +48,27 @@ namespace Grpc.Testing {
             "GAogASgLMhguZ3JwYy50ZXN0aW5nLkxvYWRQYXJhbXMSMwoOcGF5bG9hZF9j",
             "b25maWcYCyABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxI3ChBo",
             "aXN0b2dyYW1fcGFyYW1zGAwgASgLMh0uZ3JwYy50ZXN0aW5nLkhpc3RvZ3Jh",
-            "bVBhcmFtcyI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBj",
-            "LnRlc3RpbmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNldBgBIAEoCCJo",
-            "CgpDbGllbnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50ZXN0aW5nLkNs",
-            "aWVudENvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRlc3RpbmcuTWFy",
-            "a0gAQgkKB2FyZ3R5cGUi9wEKDFNlcnZlckNvbmZpZxItCgtzZXJ2ZXJfdHlw",
-            "ZRgBIAEoDjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUKD3NlY3VyaXR5",
-            "X3BhcmFtcxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIM",
-            "CgRob3N0GAMgASgJEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVyX3Ro",
-            "cmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2FkX2Nv",
-            "bmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnImgKClNl",
-            "cnZlckFyZ3MSKwoFc2V0dXAYASABKAsyGi5ncnBjLnRlc3RpbmcuU2VydmVy",
-            "Q29uZmlnSAASIgoEbWFyaxgCIAEoCzISLmdycGMudGVzdGluZy5NYXJrSABC",
-            "CQoHYXJndHlwZSJVCgxTZXJ2ZXJTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5n",
-            "cnBjLnRlc3RpbmcuU2VydmVyU3RhdHMSDAoEcG9ydBgCIAEoBRINCgVjb3Jl",
-            "cxgDIAEoBSovCgpDbGllbnRUeXBlEg8KC1NZTkNfQ0xJRU5UEAASEAoMQVNZ",
-            "TkNfQ0xJRU5UEAEqLwoKU2VydmVyVHlwZRIPCgtTWU5DX1NFUlZFUhAAEhAK",
-            "DEFTWU5DX1NFUlZFUhABKiMKB1JwY1R5cGUSCQoFVU5BUlkQABINCglTVFJF",
-            "QU1JTkcQAWIGcHJvdG8z"));
+            "bVBhcmFtcxIRCgljb3JlX2xpc3QYDSADKAUSEgoKY29yZV9saW1pdBgOIAEo",
+            "BSI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBjLnRlc3Rp",
+            "bmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNldBgBIAEoCCJoCgpDbGll",
+            "bnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVudENv",
+            "bmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRlc3RpbmcuTWFya0gAQgkK",
+            "B2FyZ3R5cGUi/AEKDFNlcnZlckNvbmZpZxItCgtzZXJ2ZXJfdHlwZRgBIAEo",
+            "DjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUKD3NlY3VyaXR5X3BhcmFt",
+            "cxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIMCgRwb3J0",
+            "GAQgASgFEhwKFGFzeW5jX3NlcnZlcl90aHJlYWRzGAcgASgFEhIKCmNvcmVf",
+            "bGltaXQYCCABKAUSMwoOcGF5bG9hZF9jb25maWcYCSABKAsyGy5ncnBjLnRl",
+            "c3RpbmcuUGF5bG9hZENvbmZpZxIRCgljb3JlX2xpc3QYCiADKAUiaAoKU2Vy",
+            "dmVyQXJncxIrCgVzZXR1cBgBIAEoCzIaLmdycGMudGVzdGluZy5TZXJ2ZXJD",
+            "b25maWdIABIiCgRtYXJrGAIgASgLMhIuZ3JwYy50ZXN0aW5nLk1hcmtIAEIJ",
+            "Cgdhcmd0eXBlIlUKDFNlcnZlclN0YXR1cxIoCgVzdGF0cxgBIAEoCzIZLmdy",
+            "cGMudGVzdGluZy5TZXJ2ZXJTdGF0cxIMCgRwb3J0GAIgASgFEg0KBWNvcmVz",
+            "GAMgASgFIg0KC0NvcmVSZXF1ZXN0Ih0KDENvcmVSZXNwb25zZRINCgVjb3Jl",
+            "cxgBIAEoBSIGCgRWb2lkKi8KCkNsaWVudFR5cGUSDwoLU1lOQ19DTElFTlQQ",
+            "ABIQCgxBU1lOQ19DTElFTlQQASpJCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VS",
+            "VkVSEAASEAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJW",
+            "RVIQAiojCgdScGNUeXBlEgkKBVVOQVJZEAASDQoJU1RSRUFNSU5HEAFiBnBy",
+            "b3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
           new pbr::GeneratedCodeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedCodeInfo[] {
@@ -76,13 +79,16 @@ namespace Grpc.Testing {
             new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), global::Grpc.Testing.ClosedLoopParams.Parser, null, null, null, null),
             new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson", "Uniform", "Determ", "Pareto" }, new[]{ "Load" }, null, null),
             new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit" }, null, null, null),
             new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
             new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
             new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Host", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList" }, null, null, null),
             new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
-            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null)
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.CoreResponse), global::Grpc.Testing.CoreResponse.Parser, new[]{ "Cores" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null)
           }));
     }
     #endregion
@@ -97,6 +103,7 @@ namespace Grpc.Testing {
   public enum ServerType {
     SYNC_SERVER = 0,
     ASYNC_SERVER = 1,
+    ASYNC_GENERIC_SERVER = 2,
   }
 
   public enum RpcType {
@@ -1097,6 +1104,8 @@ namespace Grpc.Testing {
       LoadParams = other.loadParams_ != null ? other.LoadParams.Clone() : null;
       PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
       HistogramParams = other.histogramParams_ != null ? other.HistogramParams.Clone() : null;
+      coreList_ = other.coreList_.Clone();
+      coreLimit_ = other.coreLimit_;
     }
 
     public ClientConfig Clone() {
@@ -1219,6 +1228,28 @@ namespace Grpc.Testing {
       }
     }
 
+    /// <summary>Field number for the "core_list" field.</summary>
+    public const int CoreListFieldNumber = 13;
+    private static readonly pb::FieldCodec<int> _repeated_coreList_codec
+        = pb::FieldCodec.ForInt32(106);
+    private readonly pbc::RepeatedField<int> coreList_ = new pbc::RepeatedField<int>();
+    /// <summary>
+    ///  Specify the cores we should run the client on, if desired
+    /// </summary>
+    public pbc::RepeatedField<int> CoreList {
+      get { return coreList_; }
+    }
+
+    /// <summary>Field number for the "core_limit" field.</summary>
+    public const int CoreLimitFieldNumber = 14;
+    private int coreLimit_;
+    public int CoreLimit {
+      get { return coreLimit_; }
+      set {
+        coreLimit_ = value;
+      }
+    }
+
     public override bool Equals(object other) {
       return Equals(other as ClientConfig);
     }
@@ -1240,6 +1271,8 @@ namespace Grpc.Testing {
       if (!object.Equals(LoadParams, other.LoadParams)) return false;
       if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
       if (!object.Equals(HistogramParams, other.HistogramParams)) return false;
+      if(!coreList_.Equals(other.coreList_)) return false;
+      if (CoreLimit != other.CoreLimit) return false;
       return true;
     }
 
@@ -1255,6 +1288,8 @@ namespace Grpc.Testing {
       if (loadParams_ != null) hash ^= LoadParams.GetHashCode();
       if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
       if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode();
+      hash ^= coreList_.GetHashCode();
+      if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
       return hash;
     }
 
@@ -1300,6 +1335,11 @@ namespace Grpc.Testing {
         output.WriteRawTag(98);
         output.WriteMessage(HistogramParams);
       }
+      coreList_.WriteTo(output, _repeated_coreList_codec);
+      if (CoreLimit != 0) {
+        output.WriteRawTag(112);
+        output.WriteInt32(CoreLimit);
+      }
     }
 
     public int CalculateSize() {
@@ -1332,6 +1372,10 @@ namespace Grpc.Testing {
       if (histogramParams_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(HistogramParams);
       }
+      size += coreList_.CalculateSize(_repeated_coreList_codec);
+      if (CoreLimit != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit);
+      }
       return size;
     }
 
@@ -1379,6 +1423,10 @@ namespace Grpc.Testing {
         }
         HistogramParams.MergeFrom(other.HistogramParams);
       }
+      coreList_.Add(other.coreList_);
+      if (other.CoreLimit != 0) {
+        CoreLimit = other.CoreLimit;
+      }
     }
 
     public void MergeFrom(pb::CodedInputStream input) {
@@ -1440,6 +1488,15 @@ namespace Grpc.Testing {
             input.ReadMessage(histogramParams_);
             break;
           }
+          case 106:
+          case 104: {
+            coreList_.AddEntriesFrom(input, _repeated_coreList_codec);
+            break;
+          }
+          case 112: {
+            CoreLimit = input.ReadInt32();
+            break;
+          }
         }
       }
     }
@@ -1855,11 +1912,11 @@ namespace Grpc.Testing {
     public ServerConfig(ServerConfig other) : this() {
       serverType_ = other.serverType_;
       SecurityParams = other.securityParams_ != null ? other.SecurityParams.Clone() : null;
-      host_ = other.host_;
       port_ = other.port_;
       asyncServerThreads_ = other.asyncServerThreads_;
       coreLimit_ = other.coreLimit_;
       PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
+      coreList_ = other.coreList_.Clone();
     }
 
     public ServerConfig Clone() {
@@ -1886,19 +1943,6 @@ namespace Grpc.Testing {
       }
     }
 
-    /// <summary>Field number for the "host" field.</summary>
-    public const int HostFieldNumber = 3;
-    private string host_ = "";
-    /// <summary>
-    ///  Host on which to listen.
-    /// </summary>
-    public string Host {
-      get { return host_; }
-      set {
-        host_ = pb::Preconditions.CheckNotNull(value, "value");
-      }
-    }
-
     /// <summary>Field number for the "port" field.</summary>
     public const int PortFieldNumber = 4;
     private int port_;
@@ -1929,7 +1973,7 @@ namespace Grpc.Testing {
     public const int CoreLimitFieldNumber = 8;
     private int coreLimit_;
     /// <summary>
-    ///  restrict core usage, currently unused
+    ///  Specify the number of cores to limit server to, if desired
     /// </summary>
     public int CoreLimit {
       get { return coreLimit_; }
@@ -1941,6 +1985,9 @@ namespace Grpc.Testing {
     /// <summary>Field number for the "payload_config" field.</summary>
     public const int PayloadConfigFieldNumber = 9;
     private global::Grpc.Testing.PayloadConfig payloadConfig_;
+    /// <summary>
+    ///  payload config, used in generic server
+    /// </summary>
     public global::Grpc.Testing.PayloadConfig PayloadConfig {
       get { return payloadConfig_; }
       set {
@@ -1948,6 +1995,18 @@ namespace Grpc.Testing {
       }
     }
 
+    /// <summary>Field number for the "core_list" field.</summary>
+    public const int CoreListFieldNumber = 10;
+    private static readonly pb::FieldCodec<int> _repeated_coreList_codec
+        = pb::FieldCodec.ForInt32(82);
+    private readonly pbc::RepeatedField<int> coreList_ = new pbc::RepeatedField<int>();
+    /// <summary>
+    ///  Specify the cores we should run the server on, if desired
+    /// </summary>
+    public pbc::RepeatedField<int> CoreList {
+      get { return coreList_; }
+    }
+
     public override bool Equals(object other) {
       return Equals(other as ServerConfig);
     }
@@ -1961,11 +2020,11 @@ namespace Grpc.Testing {
       }
       if (ServerType != other.ServerType) return false;
       if (!object.Equals(SecurityParams, other.SecurityParams)) return false;
-      if (Host != other.Host) return false;
       if (Port != other.Port) return false;
       if (AsyncServerThreads != other.AsyncServerThreads) return false;
       if (CoreLimit != other.CoreLimit) return false;
       if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
+      if(!coreList_.Equals(other.coreList_)) return false;
       return true;
     }
 
@@ -1973,11 +2032,11 @@ namespace Grpc.Testing {
       int hash = 1;
       if (ServerType != global::Grpc.Testing.ServerType.SYNC_SERVER) hash ^= ServerType.GetHashCode();
       if (securityParams_ != null) hash ^= SecurityParams.GetHashCode();
-      if (Host.Length != 0) hash ^= Host.GetHashCode();
       if (Port != 0) hash ^= Port.GetHashCode();
       if (AsyncServerThreads != 0) hash ^= AsyncServerThreads.GetHashCode();
       if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
       if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
+      hash ^= coreList_.GetHashCode();
       return hash;
     }
 
@@ -1994,10 +2053,6 @@ namespace Grpc.Testing {
         output.WriteRawTag(18);
         output.WriteMessage(SecurityParams);
       }
-      if (Host.Length != 0) {
-        output.WriteRawTag(26);
-        output.WriteString(Host);
-      }
       if (Port != 0) {
         output.WriteRawTag(32);
         output.WriteInt32(Port);
@@ -2014,6 +2069,7 @@ namespace Grpc.Testing {
         output.WriteRawTag(74);
         output.WriteMessage(PayloadConfig);
       }
+      coreList_.WriteTo(output, _repeated_coreList_codec);
     }
 
     public int CalculateSize() {
@@ -2024,9 +2080,6 @@ namespace Grpc.Testing {
       if (securityParams_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams);
       }
-      if (Host.Length != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeStringSize(Host);
-      }
       if (Port != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port);
       }
@@ -2039,6 +2092,7 @@ namespace Grpc.Testing {
       if (payloadConfig_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig);
       }
+      size += coreList_.CalculateSize(_repeated_coreList_codec);
       return size;
     }
 
@@ -2055,9 +2109,6 @@ namespace Grpc.Testing {
         }
         SecurityParams.MergeFrom(other.SecurityParams);
       }
-      if (other.Host.Length != 0) {
-        Host = other.Host;
-      }
       if (other.Port != 0) {
         Port = other.Port;
       }
@@ -2073,6 +2124,7 @@ namespace Grpc.Testing {
         }
         PayloadConfig.MergeFrom(other.PayloadConfig);
       }
+      coreList_.Add(other.coreList_);
     }
 
     public void MergeFrom(pb::CodedInputStream input) {
@@ -2093,10 +2145,6 @@ namespace Grpc.Testing {
             input.ReadMessage(securityParams_);
             break;
           }
-          case 26: {
-            Host = input.ReadString();
-            break;
-          }
           case 32: {
             Port = input.ReadInt32();
             break;
@@ -2116,6 +2164,11 @@ namespace Grpc.Testing {
             input.ReadMessage(payloadConfig_);
             break;
           }
+          case 82:
+          case 80: {
+            coreList_.AddEntriesFrom(input, _repeated_coreList_codec);
+            break;
+          }
         }
       }
     }
@@ -2347,7 +2400,7 @@ namespace Grpc.Testing {
     public const int CoresFieldNumber = 3;
     private int cores_;
     /// <summary>
-    ///  Number of cores on the server. See gpr_cpu_num_cores.
+    ///  Number of cores available to the server
     /// </summary>
     public int Cores {
       get { return cores_; }
@@ -2460,6 +2513,264 @@ namespace Grpc.Testing {
 
   }
 
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class CoreRequest : pb::IMessage<CoreRequest> {
+    private static readonly pb::MessageParser<CoreRequest> _parser = new pb::MessageParser<CoreRequest>(() => new CoreRequest());
+    public static pb::MessageParser<CoreRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[14]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public CoreRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public CoreRequest(CoreRequest other) : this() {
+    }
+
+    public CoreRequest Clone() {
+      return new CoreRequest(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as CoreRequest);
+    }
+
+    public bool Equals(CoreRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(CoreRequest other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class CoreResponse : pb::IMessage<CoreResponse> {
+    private static readonly pb::MessageParser<CoreResponse> _parser = new pb::MessageParser<CoreResponse>(() => new CoreResponse());
+    public static pb::MessageParser<CoreResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[15]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public CoreResponse() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public CoreResponse(CoreResponse other) : this() {
+      cores_ = other.cores_;
+    }
+
+    public CoreResponse Clone() {
+      return new CoreResponse(this);
+    }
+
+    /// <summary>Field number for the "cores" field.</summary>
+    public const int CoresFieldNumber = 1;
+    private int cores_;
+    /// <summary>
+    ///  Number of cores available on the server
+    /// </summary>
+    public int Cores {
+      get { return cores_; }
+      set {
+        cores_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as CoreResponse);
+    }
+
+    public bool Equals(CoreResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Cores != other.Cores) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Cores != 0) hash ^= Cores.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Cores != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Cores);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Cores != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores);
+      }
+      return size;
+    }
+
+    public void MergeFrom(CoreResponse other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Cores != 0) {
+        Cores = other.Cores;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Cores = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Void : pb::IMessage<Void> {
+    private static readonly pb::MessageParser<Void> _parser = new pb::MessageParser<Void>(() => new Void());
+    public static pb::MessageParser<Void> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[16]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Void() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Void(Void other) : this() {
+    }
+
+    public Void Clone() {
+      return new Void(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Void);
+    }
+
+    public bool Equals(Void other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(Void other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
   #endregion
 
 }
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
index 18168f99704f4a076a3eddf2f8ba8e93f439214b..0d12c4168c9f37eabfe3aebed206201592ef8553 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -140,14 +140,12 @@ namespace Grpc.IntegrationTesting
         }
 
         [Test]
-        [Ignore("TODO: see #4427")]
         public async Task StatusCodeAndMessage()
         {
             await InteropClient.RunStatusCodeAndMessageAsync(client);
         }
 
         [Test]
-        [Ignore("TODO: see #4427")]
         public void UnimplementedMethod()
         {
             InteropClient.RunUnimplementedMethod(UnimplementedService.NewClient(channel));
diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
index 686b48434537ceef3967d121f0e27d989ad9f7cb..e407792c4b58ffa4f7d34e51c82212a8a2fd888e 100644
--- a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
+++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -85,24 +85,27 @@ namespace Grpc.IntegrationTesting
             }
 
             var workerServer = new QpsWorker(options);
-            workerServer.Run();
+            workerServer.RunAsync().Wait();
         }
 
-        private void Run()
+        private async Task RunAsync()
         {
             string host = "0.0.0.0";
             int port = options.DriverPort;
 
+            var tcs = new TaskCompletionSource<object>();
+            var workerServiceImpl = new WorkerServiceImpl(() => { Task.Run(() => tcs.SetResult(null)); });
+                
             var server = new Server
             {
-                Services = { WorkerService.BindService(new WorkerServiceImpl()) },
+                Services = { WorkerService.BindService(workerServiceImpl) },
                 Ports = { new ServerPort(host, options.DriverPort, ServerCredentials.Insecure )}
             };
             int boundPort = server.Ports.Single().BoundPort;
             Console.WriteLine("Running qps worker server on " + string.Format("{0}:{1}", host, boundPort));
             server.Start();
-
-            server.ShutdownTask.Wait();
+            await tcs.Task;
+            await server.ShutdownAsync();
         }
     }
 }
diff --git a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
index 3dd91b794851b325523ec544599fa5331a202300..06d5ee93d8843167a31728fbcc0ced1ff50a51cb 100644
--- a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -48,7 +48,6 @@ namespace Grpc.IntegrationTesting
     /// </summary>
     public class RunnerClientServerTest
     {
-        const string Host = "localhost";
         IServerRunner serverRunner;
 
         [TestFixtureSetUp]
@@ -57,7 +56,6 @@ namespace Grpc.IntegrationTesting
             var serverConfig = new ServerConfig
             {
                 ServerType = ServerType.ASYNC_SERVER,
-                Host = Host,
                 PayloadConfig = new PayloadConfig
                 {
                     SimpleParams = new SimpleProtoParams
@@ -83,7 +81,7 @@ namespace Grpc.IntegrationTesting
         {
             var config = new ClientConfig
             {
-                ServerTargets = { string.Format("{0}:{1}", Host, serverRunner.BoundPort) },
+                ServerTargets = { string.Format("{0}:{1}", "localhost", serverRunner.BoundPort) },
                 RpcType = RpcType.UNARY,
                 LoadParams = new LoadParams { ClosedLoop = new ClosedLoopParams() },
                 PayloadConfig = new PayloadConfig
diff --git a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
index 9b09b9bdd340d55e7c5286df8eccb51ac4624a67..4a73645e6ca85369770fccb68ee874ed4cb54954 100644
--- a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
@@ -65,7 +65,7 @@ namespace Grpc.IntegrationTesting
             var server = new Server
             {
                 Services = { BenchmarkService.BindService(new BenchmarkServiceImpl(responseSize)) },
-                Ports = { new ServerPort(config.Host, config.Port, credentials) }
+                Ports = { new ServerPort("[::]", config.Port, credentials) }
             };
 
             server.Start();
diff --git a/src/csharp/Grpc.IntegrationTesting/Services.cs b/src/csharp/Grpc.IntegrationTesting/Services.cs
index 04a092ccd79cb1a3c68c624ba5ce1ff8974b9fe6..a8475c181720de6e4014bd05598d5313a21028c3 100644
--- a/src/csharp/Grpc.IntegrationTesting/Services.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Services.cs
@@ -29,11 +29,14 @@ namespace Grpc.Testing {
             "QmVuY2htYXJrU2VydmljZRJGCglVbmFyeUNhbGwSGy5ncnBjLnRlc3Rpbmcu",
             "U2ltcGxlUmVxdWVzdBocLmdycGMudGVzdGluZy5TaW1wbGVSZXNwb25zZRJO",
             "Cg1TdHJlYW1pbmdDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3Qa",
-            "HC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2UoATABMp0BCg1Xb3JrZXJT",
+            "HC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2UoATABMpcCCg1Xb3JrZXJT",
             "ZXJ2aWNlEkUKCVJ1blNlcnZlchIYLmdycGMudGVzdGluZy5TZXJ2ZXJBcmdz",
             "GhouZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXR1cygBMAESRQoJUnVuQ2xpZW50",
             "EhguZ3JwYy50ZXN0aW5nLkNsaWVudEFyZ3MaGi5ncnBjLnRlc3RpbmcuQ2xp",
-            "ZW50U3RhdHVzKAEwAWIGcHJvdG8z"));
+            "ZW50U3RhdHVzKAEwARJCCglDb3JlQ291bnQSGS5ncnBjLnRlc3RpbmcuQ29y",
+            "ZVJlcXVlc3QaGi5ncnBjLnRlc3RpbmcuQ29yZVJlc3BvbnNlEjQKClF1aXRX",
+            "b3JrZXISEi5ncnBjLnRlc3RpbmcuVm9pZBoSLmdycGMudGVzdGluZy5Wb2lk",
+            "YgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Grpc.Testing.MessagesReflection.Descriptor, global::Grpc.Testing.ControlReflection.Descriptor, },
           new pbr::GeneratedCodeInfo(null, null));
diff --git a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
index dd30afb427f8c6eeb9c7cc43f3d039c3dc1e76b4..996439afbf1395f4d8f64ae3a47d20a43ef6998d 100644
--- a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
@@ -114,6 +114,9 @@ namespace Grpc.Testing {
     static readonly Marshaller<global::Grpc.Testing.ServerStatus> __Marshaller_ServerStatus = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerStatus.Parser.ParseFrom);
     static readonly Marshaller<global::Grpc.Testing.ClientArgs> __Marshaller_ClientArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientArgs.Parser.ParseFrom);
     static readonly Marshaller<global::Grpc.Testing.ClientStatus> __Marshaller_ClientStatus = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientStatus.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.CoreRequest> __Marshaller_CoreRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.CoreRequest.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.CoreResponse> __Marshaller_CoreResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.CoreResponse.Parser.ParseFrom);
+    static readonly Marshaller<global::Grpc.Testing.Void> __Marshaller_Void = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Void.Parser.ParseFrom);
 
     static readonly Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> __Method_RunServer = new Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus>(
         MethodType.DuplexStreaming,
@@ -129,6 +132,20 @@ namespace Grpc.Testing {
         __Marshaller_ClientArgs,
         __Marshaller_ClientStatus);
 
+    static readonly Method<global::Grpc.Testing.CoreRequest, global::Grpc.Testing.CoreResponse> __Method_CoreCount = new Method<global::Grpc.Testing.CoreRequest, global::Grpc.Testing.CoreResponse>(
+        MethodType.Unary,
+        __ServiceName,
+        "CoreCount",
+        __Marshaller_CoreRequest,
+        __Marshaller_CoreResponse);
+
+    static readonly Method<global::Grpc.Testing.Void, global::Grpc.Testing.Void> __Method_QuitWorker = new Method<global::Grpc.Testing.Void, global::Grpc.Testing.Void>(
+        MethodType.Unary,
+        __ServiceName,
+        "QuitWorker",
+        __Marshaller_Void,
+        __Marshaller_Void);
+
     // service descriptor
     public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
     {
@@ -142,6 +159,14 @@ namespace Grpc.Testing {
       AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options);
       AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
       AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options);
+      global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options);
+      AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options);
+      global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options);
+      AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
+      AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options);
     }
 
     // server-side interface
@@ -149,6 +174,8 @@ namespace Grpc.Testing {
     {
       Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context);
       Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context);
+      Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context);
+      Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context);
     }
 
     // client stub
@@ -177,6 +204,46 @@ namespace Grpc.Testing {
         var call = CreateCall(__Method_RunClient, options);
         return Calls.AsyncDuplexStreamingCall(call);
       }
+      public global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        var call = CreateCall(__Method_CoreCount, new CallOptions(headers, deadline, cancellationToken));
+        return Calls.BlockingUnaryCall(call, request);
+      }
+      public global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options)
+      {
+        var call = CreateCall(__Method_CoreCount, options);
+        return Calls.BlockingUnaryCall(call, request);
+      }
+      public AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        var call = CreateCall(__Method_CoreCount, new CallOptions(headers, deadline, cancellationToken));
+        return Calls.AsyncUnaryCall(call, request);
+      }
+      public AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options)
+      {
+        var call = CreateCall(__Method_CoreCount, options);
+        return Calls.AsyncUnaryCall(call, request);
+      }
+      public global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        var call = CreateCall(__Method_QuitWorker, new CallOptions(headers, deadline, cancellationToken));
+        return Calls.BlockingUnaryCall(call, request);
+      }
+      public global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options)
+      {
+        var call = CreateCall(__Method_QuitWorker, options);
+        return Calls.BlockingUnaryCall(call, request);
+      }
+      public AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+      {
+        var call = CreateCall(__Method_QuitWorker, new CallOptions(headers, deadline, cancellationToken));
+        return Calls.AsyncUnaryCall(call, request);
+      }
+      public AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options)
+      {
+        var call = CreateCall(__Method_QuitWorker, options);
+        return Calls.AsyncUnaryCall(call, request);
+      }
     }
 
     // creates service definition that can be registered with a server
@@ -184,7 +251,9 @@ namespace Grpc.Testing {
     {
       return ServerServiceDefinition.CreateBuilder(__ServiceName)
           .AddMethod(__Method_RunServer, serviceImpl.RunServer)
-          .AddMethod(__Method_RunClient, serviceImpl.RunClient).Build();
+          .AddMethod(__Method_RunClient, serviceImpl.RunClient)
+          .AddMethod(__Method_CoreCount, serviceImpl.CoreCount)
+          .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
     }
 
     // creates a new client
diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
index 59ecebf5a21ec42dcfbfdf29ed47788cf4de8036..cab299a137357a3b3506a1ff44bfc11402648a40 100644
--- a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
+++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
@@ -47,6 +47,13 @@ namespace Grpc.Testing
     /// </summary>
     public class WorkerServiceImpl : WorkerService.IWorkerService
     {
+        readonly Action stopRequestHandler;
+
+        public WorkerServiceImpl(Action stopRequestHandler)
+        {
+            this.stopRequestHandler = GrpcPreconditions.CheckNotNull(stopRequestHandler);
+        }
+        
         public async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context)
         {
             GrpcPreconditions.CheckState(await requestStream.MoveNext());
@@ -92,5 +99,16 @@ namespace Grpc.Testing
             }
             await runner.StopAsync();
         }
+
+        public Task<CoreResponse> CoreCount(CoreRequest request, ServerCallContext context)
+        {
+            return Task.FromResult(new CoreResponse { Cores = Environment.ProcessorCount });
+        }
+
+        public Task<Void> QuitWorker(Void request, ServerCallContext context)
+        {
+            stopRequestHandler();
+            return Task.FromResult(new Void());
+        }
     }
 }
diff --git a/src/csharp/Grpc.Tools.nuspec b/src/csharp/Grpc.Tools.nuspec
index 48a7b1f3af288d9469297e2273033fca4e166902..31d1bed647718cdfefafd8462969670c627f5dde 100644
--- a/src/csharp/Grpc.Tools.nuspec
+++ b/src/csharp/Grpc.Tools.nuspec
@@ -4,18 +4,29 @@
     <id>Grpc.Tools</id>
     <title>gRPC C# Tools</title>
     <summary>Tools for C# implementation of gRPC - an RPC library and framework</summary>
-    <description>Precompiled Windows binary for generating gRPC client/server code</description>
+    <description>Precompiled protobuf compiler and gRPC protobuf compiler plugin for generating gRPC client/server C# code. Binaries are available for Windows, Linux and MacOS.</description>
     <version>$version$</version>
     <authors>Google Inc.</authors>
     <owners>grpc-packages</owners>
     <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
     <projectUrl>https://github.com/grpc/grpc</projectUrl>
     <requireLicenseAcceptance>false</requireLicenseAcceptance>
-    <releaseNotes>grpc_csharp_plugin.exe - gRPC C# protoc plugin version $version$</releaseNotes>
+    <releaseNotes>Release $version$</releaseNotes>
     <copyright>Copyright 2015, Google Inc.</copyright>
     <tags>gRPC RPC Protocol HTTP/2</tags>
   </metadata>
   <files>
-    <file src="..\..\vsprojects\Release\grpc_csharp_plugin.exe" target="tools" />
+    <file src="protoc_plugins\windows_x86\protoc.exe" target="tools\windows_x86\protoc.exe" />
+    <file src="protoc_plugins\windows_x86\grpc_csharp_plugin.exe" target="tools\windows_x86\grpc_csharp_plugin.exe" />
+    <file src="protoc_plugins\windows_x64\protoc.exe" target="tools\windows_x64\protoc.exe" />
+    <file src="protoc_plugins\windows_x64\grpc_csharp_plugin.exe" target="tools\windows_x64\grpc_csharp_plugin.exe" />
+    <file src="protoc_plugins\linux_x86\protoc" target="tools\linux_x86\protoc" />
+    <file src="protoc_plugins\linux_x86\grpc_csharp_plugin" target="tools\linux_x86\grpc_csharp_plugin" />
+    <file src="protoc_plugins\linux_x64\protoc" target="tools\linux_x64\protoc" />
+    <file src="protoc_plugins\linux_x64\grpc_csharp_plugin" target="tools\linux_x64\grpc_csharp_plugin" />
+    <file src="protoc_plugins\macosx_x86\protoc" target="tools\macosx_x86\protoc" />
+    <file src="protoc_plugins\macosx_x86\grpc_csharp_plugin" target="tools\macosx_x86\grpc_csharp_plugin" />
+    <file src="protoc_plugins\macosx_x64\protoc" target="tools\macosx_x64\protoc" />
+    <file src="protoc_plugins\macosx_x64\grpc_csharp_plugin" target="tools\macosx_x64\grpc_csharp_plugin" />
   </files>
 </package>
diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat
index 7cf962bdc220638c1c648a9e45b0060f6a7874ee..ea9f0a3712bd161a81dfb7b5f4558399b2375c97 100644
--- a/src/csharp/build_packages.bat
+++ b/src/csharp/build_packages.bat
@@ -19,6 +19,14 @@ xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* gr
 xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x86\
 xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x64\
 
+@rem Collect protoc artifacts built by the previous build step
+xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x86\
+xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x64\
+xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x86\
+xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x64\
+xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x86\
+xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x64\
+
 @rem Fetch all dependencies
 %NUGET% restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error
 %NUGET% restore Grpc.sln || goto :error
@@ -27,24 +35,19 @@ setlocal
 
 @call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86
 
-@rem We won't use the native libraries from this step, but without this Grpc.sln will fail.  
+@rem We won't use the native libraries from this step, but without this Grpc.sln will fail.
 msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Release /p:PlatformToolset=v120 || goto :error
 
 msbuild Grpc.sln /p:Configuration=ReleaseSigned || goto :error
 
 endlocal
 
-@rem TODO(jtattermusch): re-enable protoc plugin building
-@rem @call ..\..\vsprojects\build_plugins.bat || goto :error
-
 %NUGET% pack grpc.native.csharp\grpc.native.csharp.nuspec -Version %VERSION% || goto :error
 %NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
 %NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error
 %NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION_WITH_BETA% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
 %NUGET% pack Grpc.nuspec -Version %VERSION% || goto :error
-
-@rem TODO(jtattermusch): re-enable building Grpc.Tools package
-@rem %NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error
+%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error
 
 @rem copy resulting nuget packages to artifacts directory
 xcopy /Y /I *.nupkg ..\..\artifacts\
diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh
index 0261a458af730dd3996a21e9f10d3e346fa68791..23e0540253a3ec226619959dbc8000a3bba741a1 100755
--- a/src/csharp/generate_proto_csharp.sh
+++ b/src/csharp/generate_proto_csharp.sh
@@ -42,7 +42,7 @@ $PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \
     -I src/proto/math src/proto/math/math.proto
 
 $PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_DIR \
-    -I src/proto/grpc/health/v1alpha src/proto/grpc/health/v1alpha/health.proto
+    -I src/proto/grpc/health/v1 src/proto/grpc/health/v1/health.proto
 
 $PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
     -I . src/proto/grpc/testing/{control,empty,messages,payloads,services,stats,test}.proto 
diff --git a/src/node/README.md b/src/node/README.md
index b46b98624327d3a6569fd73fa3b0d0d9306c340c..3501b54a6654d6ededd90c8f7de8da7771376d2a 100644
--- a/src/node/README.md
+++ b/src/node/README.md
@@ -5,7 +5,7 @@
 Beta
 
 ## PREREQUISITES
-- `node`: This requires `node` to be installed. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package.
+- `node`: This requires `node` to be installed, version `0.12` or above. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package.
 
 ## INSTALLATION
 
diff --git a/src/node/health_check/health.js b/src/node/health_check/health.js
index 1a2c0366875701b6b57cf52e0bbfabaf9137f2a2..6ab41571831b803f372fd7f32fd78a972d1ec2a3 100644
--- a/src/node/health_check/health.js
+++ b/src/node/health_check/health.js
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,9 +38,9 @@ var grpc = require('../');
 var _ = require('lodash');
 
 var health_proto = grpc.load(__dirname +
-    '/../../proto/grpc/health/v1alpha/health.proto');
+    '/../../proto/grpc/health/v1/health.proto');
 
-var HealthClient = health_proto.grpc.health.v1alpha.Health;
+var HealthClient = health_proto.grpc.health.v1.Health;
 
 function HealthImplementation(statusMap) {
   this.statusMap = _.clone(statusMap);
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index db383e4d0006d1cfad19e831eee1dd40eac3ca98..5602011a8e05407c87ebd04f3136f112434994cb 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -290,6 +290,7 @@ function timeoutOnSleepingServer(client, done) {
   call.write({
     payload: {body: zeroBuffer(27182)}
   });
+  call.on('data', function() {});
   call.on('error', function(error) {
 
     assert(error.code === grpc.status.DEADLINE_EXCEEDED ||
@@ -336,6 +337,7 @@ function customMetadata(client, done) {
                      ['test_initial_metadata_value']);
     done();
   });
+  stream.on('data', function() {});
   stream.on('status', function(status) {
     var echo_trailer = status.metadata.get(ECHO_TRAILING_KEY);
     assert(echo_trailer.length > 0);
@@ -361,6 +363,7 @@ function statusCodeAndMessage(client, done) {
     done();
   });
   var duplex = client.fullDuplexCall();
+  duplex.on('data', function() {});
   duplex.on('status', function(status) {
     assert(status);
     assert.strictEqual(status.code, 2);
diff --git a/src/node/src/client.js b/src/node/src/client.js
index d6aa999502c2f9b0f35cf11a476027cce9576cf3..9cc5a62bdbcafe486222a0f081f37111078c81b0 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -131,8 +131,68 @@ function ClientReadableStream(call, deserialize) {
   this.finished = false;
   this.reading = false;
   this.deserialize = common.wrapIgnoreNull(deserialize);
+  /* Status generated from reading messages from the server. Overrides the
+   * status from the server if not OK */
+  this.read_status = null;
+  /* Status received from the server. */
+  this.received_status = null;
 }
 
+/**
+ * Called when all messages from the server have been processed. The status
+ * parameter indicates that the call should end with that status. status
+ * defaults to OK if not provided.
+ * @param {Object!} status The status that the call should end with
+ */
+function _readsDone(status) {
+  /* jshint validthis: true */
+  if (!status) {
+    status = {code: grpc.status.OK, details: 'OK'};
+  }
+  this.finished = true;
+  this.read_status = status;
+  this._emitStatusIfDone();
+}
+
+ClientReadableStream.prototype._readsDone = _readsDone;
+
+/**
+ * Called to indicate that we have received a status from the server.
+ */
+function _receiveStatus(status) {
+  /* jshint validthis: true */
+  this.received_status = status;
+  this._emitStatusIfDone();
+}
+
+ClientReadableStream.prototype._receiveStatus = _receiveStatus;
+
+/**
+ * If we have both processed all incoming messages and received the status from
+ * the server, emit the status. Otherwise, do nothing.
+ */
+function _emitStatusIfDone() {
+  /* jshint validthis: true */
+  var status;
+  if (this.read_status && this.received_status) {
+    if (this.read_status.code !== grpc.status.OK) {
+      status = this.read_status;
+    } else {
+      status = this.received_status;
+    }
+    this.emit('status', status);
+    if (status.code !== grpc.status.OK) {
+      var error = new Error(status.details);
+      error.code = status.code;
+      error.metadata = status.metadata;
+      this.emit('error', error);
+      return;
+    }
+  }
+}
+
+ClientReadableStream.prototype._emitStatusIfDone = _emitStatusIfDone;
+
 /**
  * Read the next object from the stream.
  * @access private
@@ -150,6 +210,7 @@ function _read(size) {
     if (err) {
       // Something has gone wrong. Stop reading and wait for status
       self.finished = true;
+      self._readsDone();
       return;
     }
     var data = event.read;
@@ -157,8 +218,11 @@ function _read(size) {
     try {
       deserialized = self.deserialize(data);
     } catch (e) {
-      self.call.cancelWithStatus(grpc.status.INTERNAL,
-                                 'Failed to parse server response');
+      self._readsDone({code: grpc.status.INTERNAL,
+                       details: 'Failed to parse server response'});
+    }
+    if (data === null) {
+      self._readsDone();
     }
     if (self.push(deserialized) && data !== null) {
       var read_batch = {};
@@ -198,6 +262,11 @@ function ClientDuplexStream(call, serialize, deserialize) {
   this.serialize = common.wrapIgnoreNull(serialize);
   this.deserialize = common.wrapIgnoreNull(deserialize);
   this.call = call;
+  /* Status generated from reading messages from the server. Overrides the
+   * status from the server if not OK */
+  this.read_status = null;
+  /* Status received from the server. */
+  this.received_status = null;
   this.on('finish', function() {
     var batch = {};
     batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true;
@@ -205,6 +274,9 @@ function ClientDuplexStream(call, serialize, deserialize) {
   });
 }
 
+ClientDuplexStream.prototype._readsDone = _readsDone;
+ClientDuplexStream.prototype._receiveStatus = _receiveStatus;
+ClientDuplexStream.prototype._emitStatusIfDone = _emitStatusIfDone;
 ClientDuplexStream.prototype._read = _read;
 ClientDuplexStream.prototype._write = _write;
 
@@ -487,22 +559,13 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
     var status_batch = {};
     status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
     call.startBatch(status_batch, function(err, response) {
-      response.status.metadata = Metadata._fromCoreRepresentation(
-          response.status.metadata);
-      stream.emit('status', response.status);
-      if (response.status.code !== grpc.status.OK) {
-        var error = new Error(response.status.details);
-        error.code = response.status.code;
-        error.metadata = response.status.metadata;
-        stream.emit('error', error);
+      if (err) {
+        stream.emit('error', err);
         return;
-      } else {
-        if (err) {
-          // Got a batch error, but OK status. Something went wrong
-          stream.emit('error', err);
-          return;
-        }
       }
+      response.status.metadata = Metadata._fromCoreRepresentation(
+          response.status.metadata);
+      stream._receiveStatus(response.status);
     });
     return stream;
   }
@@ -552,22 +615,13 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
     var status_batch = {};
     status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
     call.startBatch(status_batch, function(err, response) {
-      response.status.metadata = Metadata._fromCoreRepresentation(
-          response.status.metadata);
-      stream.emit('status', response.status);
-      if (response.status.code !== grpc.status.OK) {
-        var error = new Error(response.status.details);
-        error.code = response.status.code;
-        error.metadata = response.status.metadata;
-        stream.emit('error', error);
+      if (err) {
+        stream.emit('error', err);
         return;
-      } else {
-        if (err) {
-          // Got a batch error, but OK status. Something went wrong
-          stream.emit('error', err);
-          return;
-        }
       }
+      response.status.metadata = Metadata._fromCoreRepresentation(
+          response.status.metadata);
+      stream._receiveStatus(response.status);
     });
     return stream;
   }
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index 530f1f774949e6fbb911205e0fb270a196cf471f..8a232d6fc44a1ba9c4e89df5891b0d87ce6832d8 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -1000,6 +1000,7 @@ describe('Call propagation', function() {
       proxy_impl.serverStream = function(parent) {
         var child = client.serverStream(parent.request, null,
                                         {parent: parent});
+        child.on('data', function() {});
         child.on('error', function(err) {
           assert(err);
           assert.strictEqual(err.code, grpc.status.CANCELLED);
@@ -1013,6 +1014,7 @@ describe('Call propagation', function() {
       var proxy_client = new Client('localhost:' + proxy_port,
                                     grpc.credentials.createInsecure());
       call = proxy_client.serverStream({});
+      call.on('data', function() {});
       call.on('error', function(err) {
         done();
       });
@@ -1022,6 +1024,7 @@ describe('Call propagation', function() {
       var call;
       proxy_impl.bidiStream = function(parent) {
         var child = client.bidiStream(null, {parent: parent});
+        child.on('data', function() {});
         child.on('error', function(err) {
           assert(err);
           assert.strictEqual(err.code, grpc.status.CANCELLED);
@@ -1035,6 +1038,7 @@ describe('Call propagation', function() {
       var proxy_client = new Client('localhost:' + proxy_port,
                                     grpc.credentials.createInsecure());
       call = proxy_client.bidiStream();
+      call.on('data', function() {});
       call.on('error', function(err) {
         done();
       });
@@ -1074,6 +1078,7 @@ describe('Call propagation', function() {
       proxy_impl.bidiStream = function(parent) {
         var child = client.bidiStream(
             null, {parent: parent, propagate_flags: deadline_flags});
+        child.on('data', function() {});
         child.on('error', function(err) {
           assert(err);
           assert(err.code === grpc.status.DEADLINE_EXCEEDED ||
@@ -1089,6 +1094,7 @@ describe('Call propagation', function() {
       var deadline = new Date();
       deadline.setSeconds(deadline.getSeconds() + 1);
       var call = proxy_client.bidiStream(null, {deadline: deadline});
+      call.on('data', function() {});
       call.on('error', function(err) {
         done();
       });
@@ -1130,6 +1136,7 @@ describe('Cancelling surface client', function() {
   });
   it('Should correctly cancel a server stream call', function(done) {
     var call = client.fib({'limit': 5});
+    call.on('data', function() {});
     call.on('error', function(error) {
       assert.strictEqual(error.code, surface_client.status.CANCELLED);
       done();
@@ -1138,6 +1145,7 @@ describe('Cancelling surface client', function() {
   });
   it('Should correctly cancel a bidi stream call', function(done) {
     var call = client.divMany();
+    call.on('data', function() {});
     call.on('error', function(error) {
       assert.strictEqual(error.code, surface_client.status.CANCELLED);
       done();
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
index fe3b8f39d1273da12f90c11f5937b1ef72df70ec..7b66cd4c32902fa43e1d2b1c9cd6574a429376d0 100644
--- a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
index ea2b01ee1d77fe182808dd35e17cd6a5cb39755d..ff3031678c5d72efe78243f1c0627cad8275f34a 100644
--- a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m
index 00c4b8830d344104648115f2180d4757235ef47e..7dd6873c8029bbd0e69fc9bafde988e85d8123cf 100644
--- a/src/objective-c/tests/GRPCClientTests.m
+++ b/src/objective-c/tests/GRPCClientTests.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
 #import <XCTest/XCTest.h>
 
 #import <GRPCClient/GRPCCall.h>
+#import <GRPCClient/GRPCCall+ChannelArg.h>
 #import <GRPCClient/GRPCCall+OAuth2.h>
 #import <GRPCClient/GRPCCall+Tests.h>
 #import <ProtoRPC/ProtoMethod.h>
@@ -45,6 +46,7 @@
 static NSString * const kHostAddress = @"localhost:5050";
 static NSString * const kPackage = @"grpc.testing";
 static NSString * const kService = @"TestService";
+static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
 
 static ProtoMethod *kInexistentMethod;
 static ProtoMethod *kEmptyCallMethod;
@@ -101,6 +103,8 @@ static ProtoMethod *kUnaryCallMethod;
 @implementation GRPCClientTests
 
 - (void)setUp {
+  // Add a custom user agent prefix that will be used in test
+  [GRPCCall setUserAgentPrefix:@"Foo" forHost:kHostAddress];
   // Register test server as non-SSL.
   [GRPCCall useInsecureConnectionsForHost:kHostAddress];
 
@@ -127,8 +131,7 @@ static ProtoMethod *kUnaryCallMethod;
     XCTFail(@"Received unexpected response: %@", value);
   } completionHandler:^(NSError *errorOrNil) {
     XCTAssertNotNil(errorOrNil, @"Finished without error!");
-    // TODO(jcanizales): The server should return code 12 UNIMPLEMENTED, not 5 NOT FOUND.
-    XCTAssertEqual(errorOrNil.code, 5, @"Finished with unexpected error: %@", errorOrNil);
+    XCTAssertEqual(errorOrNil.code, 12, @"Finished with unexpected error: %@", errorOrNil);
     [expectation fulfill];
   }];
 
@@ -191,7 +194,6 @@ static ProtoMethod *kUnaryCallMethod;
   [self waitForExpectationsWithTimeout:8 handler:nil];
 }
 
-// TODO(jcanizales): Activate this test against the remote server.
 - (void)testMetadata {
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"RPC unauthorized."];
 
@@ -200,7 +202,7 @@ static ProtoMethod *kUnaryCallMethod;
   request.fillOauthScope = YES;
   GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]];
 
-  GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
+  GRPCCall *call = [[GRPCCall alloc] initWithHost:kRemoteSSLHost
                                              path:kUnaryCallMethod.HTTPPath
                                    requestsWriter:requestsWriter];
 
@@ -257,4 +259,71 @@ static ProtoMethod *kUnaryCallMethod;
   [self waitForExpectationsWithTimeout:8 handler:nil];
 }
 
+- (void)testUserAgentPrefix {
+  __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."];
+  __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
+
+  GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
+                                             path:kEmptyCallMethod.HTTPPath
+                                   requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
+  // Setting this special key in the header will cause the interop server to echo back the
+  // user-agent value, which we confirm.
+  call.requestHeaders[@"x-grpc-test-echo-useragent"] = @"";
+
+  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+    XCTAssertNotNil(value, @"nil value received as response.");
+    XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
+    /* This test needs to be more clever in regards to changing the version of the core.
+    XCTAssertEqualObjects(call.responseHeaders[@"x-grpc-test-echo-useragent"],
+                          @"Foo grpc-objc/0.13.0 grpc-c/0.14.0-dev (ios)",
+                          @"Did not receive expected user agent %@",
+                          call.responseHeaders[@"x-grpc-test-echo-useragent"]);
+    */
+    [response fulfill];
+  } completionHandler:^(NSError *errorOrNil) {
+    XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
+    [completion fulfill];
+  }];
+
+  [call startWithWriteable:responsesWriteable];
+
+  [self waitForExpectationsWithTimeout:8 handler:nil];
+}
+
+// TODO(makarandd): Move to a different file that contains only unit tests
+- (void)testExceptions {
+  // Try to set userAgentPrefix for host that is nil. This should cause
+  // an exception.
+  @try {
+    [GRPCCall setUserAgentPrefix:@"Foo" forHost:nil];
+    XCTFail(@"Did not receive an exception when host is nil");
+  } @catch(NSException *theException) {
+    NSLog(@"Received exception as expected: %@", theException.name);
+  }
+
+  // Try to set parameters to nil for GRPCCall. This should cause an exception
+  @try {
+    GRPCCall *call = [[GRPCCall alloc] initWithHost:nil
+                                               path:nil
+                                     requestsWriter:nil];
+    XCTFail(@"Did not receive an exception when parameters are nil");
+  } @catch(NSException *theException) {
+    NSLog(@"Received exception as expected: %@", theException.name);
+  }
+
+
+  // Set state to Finished by force
+  GRXWriter *requestsWriter = [GRXWriter emptyWriter];
+  [requestsWriter finishWithError:nil];
+  @try {
+    GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
+                                               path:kUnaryCallMethod.HTTPPath
+                                     requestsWriter:requestsWriter];
+    XCTFail(@"Did not receive an exception when GRXWriter has incorrect state.");
+  } @catch(NSException *theException) {
+    NSLog(@"Received exception as expected: %@", theException.name);
+  }
+
+}
+
 @end
diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m
index 9d7afefbfe3cd37e4fa4f2940fbcab940375d1a0..155e334ecb2bec5ab0552293e7eb78e4c33b295f 100644
--- a/src/objective-c/tests/InteropTestsLocalSSL.m
+++ b/src/objective-c/tests/InteropTestsLocalSSL.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -57,4 +57,15 @@ static NSString * const kLocalSSLHost = @"localhost:5051";
   [super setUp];
 }
 
+- (void)testExceptions {
+  // Try to set userAgentPrefix for host that is nil. This should cause
+  // an exception.
+  @try {
+    [GRPCCall useTestCertsPath:nil testName:nil forHost:nil];
+    XCTFail(@"Did not receive an exception when parameters are nil");
+  } @catch(NSException *theException) {
+    NSLog(@"Received exception as expected: %@", theException.name);
+  }
+}
+
 @end
diff --git a/src/objective-c/tests/RxLibraryUnitTests.m b/src/objective-c/tests/RxLibraryUnitTests.m
index a67a4c6cd937a19ec486bba732e85401d30210fa..d34266281412d4dd24eff9a75db0b0cf0bc14a05 100644
--- a/src/objective-c/tests/RxLibraryUnitTests.m
+++ b/src/objective-c/tests/RxLibraryUnitTests.m
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -137,4 +137,24 @@
   XCTAssertEqualObjects(handler.errorOrNil, anyError);
 }
 
+- (void)testBufferedPipeFinishWriteWhilePaused {
+  // Given:
+  CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
+  id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
+  id anyValue = @7;
+
+  // If:
+  GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
+  // Write something, then finish
+  [pipe writeValue:anyValue];
+  [pipe writesFinishedWithError:nil];
+  // then start the writeable
+  [pipe startWithWriteable:writeable];
+
+  // Then:
+  XCTAssertEqual(handler.timesCalled, 1);
+  XCTAssertEqualObjects(handler.value, anyValue);
+  XCTAssertEqualObjects(handler.errorOrNil, nil);
+}
+
 @end
diff --git a/src/php/README.md b/src/php/README.md
index 08d0b413c954718cfd63d24f2a55315e4aa0da09..cf8f2c11b0fa5e1aca376ffd6f7212e94ce41095 100644
--- a/src/php/README.md
+++ b/src/php/README.md
@@ -9,14 +9,21 @@ Beta
 
 ## Environment
 
-Prerequisite: PHP 5.5 or later, `phpunit`, `pecl`
+Prerequisite: `php` >=5.5, `phpize`, `pecl`, `phpunit`
 
-**Linux:**
+**Linux (Debian):**
 
 ```sh
 $ sudo apt-get install php5 php5-dev php-pear
 ```
 
+**Linux (CentOS):**
+
+```sh
+$ yum install php55w
+$ yum --enablerepo=remi,remi-php55 install php-devel php-pear
+```
+
 **Mac OS X:**
 
 ```sh
@@ -24,11 +31,11 @@ $ curl -O http://pear.php.net/go-pear.phar
 $ sudo php -d detect_unicode=0 go-pear.phar
 ```
 
-**PHPUnit: (Both Linux and Mac OS X)**
+**PHPUnit:**
 ```sh
-$ curl https://phar.phpunit.de/phpunit.phar -o phpunit.phar
-$ chmod +x phpunit.phar
-$ sudo mv phpunit.phar /usr/local/bin/phpunit
+$ wget https://phar.phpunit.de/phpunit-old.phar
+$ chmod +x phpunit-old.phar
+$ sudo mv phpunit-old.phar /usr/bin/phpunit
 ```
 
 ## Quick Install
@@ -39,16 +46,22 @@ Install the gRPC PHP extension
 sudo pecl install grpc-beta
 ```
 
+This will compile and install the gRPC PHP extension into the standard PHP extension directory. You should be able to run the [unit tests](#unit-tests), with the PHP extension installed.
+
+To run tests with generated stub code from `.proto` files, you will also need the `composer`, `protoc` and `protoc-gen-php` binaries. You can find out how to get these [below](#generated-code-tests).
 
 ## Build from Source
 
+
+### gRPC C core library
+
 Clone this repository
 
 ```sh
 $ git clone https://github.com/grpc/grpc.git
 ```
 
-Build and install the gRPC C core libraries
+Build and install the gRPC C core library
 
 ```sh
 $ cd grpc
@@ -57,20 +70,15 @@ $ make
 $ sudo make install
 ```
 
-Note: you may encounter a warning about the Protobuf compiler `protoc` 3.0.0+ not being installed. The following might help, and will be useful later on when we need to compile the `protoc-gen-php` tool.
+### gRPC PHP extension
 
-```sh
-$ cd grpc/third_party/protobuf
-$ sudo make install   # 'make' should have been run by core grpc
-```
-
-Install the gRPC PHP extension
+Install the gRPC PHP extension from PECL
 
 ```sh
 $ sudo pecl install grpc-beta
 ```
 
-OR
+Or, compile from source
 
 ```sh
 $ cd grpc/src/php/ext/grpc
@@ -80,58 +88,98 @@ $ make
 $ sudo make install
 ```
 
+### Update php.ini
+
 Add this line to your `php.ini` file, e.g. `/etc/php5/cli/php.ini`
 
 ```sh
 extension=grpc.so
 ```
 
-Install Composer
+## Unit Tests
+
+You will need the source code to run tests
+
+```sh
+$ git clone https://github.com/grpc/grpc.git
+$ cd grpc
+$ git pull --recurse-submodules && git submodule update --init --recursive
+```
+
+Run unit tests
 
 ```sh
 $ cd grpc/src/php
+$ ./bin/run_tests.sh
+```
+
+## Generated Code Tests
+
+This section specifies the prerequisites for running the generated code tests, as well as how to run the tests themselves.
+
+### Composer
+
+If you don't have it already, install `composer` to pull in some runtime dependencies based on the `composer.json` file.
+
+```sh
 $ curl -sS https://getcomposer.org/installer | php
 $ sudo mv composer.phar /usr/local/bin/composer
+
+$ cd grpc/src/php
 $ composer install
 ```
 
-## Unit Tests
+### Protobuf compiler
 
-Run unit tests
+Again if you don't have it already, you need to install the protobuf compiler `protoc`, version 3.0.0+.
+
+If you compiled the gRPC C core library from source above, the `protoc` binary should have been installed as well. If it hasn't been installed, you can run the following commands to install it.
 
 ```sh
-$ cd grpc/src/php
-$ ./bin/run_tests.sh
+$ cd grpc/third_party/protobuf
+$ sudo make install   # 'make' should have been run by core grpc
 ```
 
-## Generated Code Tests
+Alternatively, you can download `protoc` binaries from [the protocol buffers Github repository](https://github.com/google/protobuf/releases).
+
 
-Install `protoc-gen-php`
+### PHP protobuf compiler
+
+You need to install `protoc-gen-php` to generate stub class `.php` files from service definition `.proto` files.
 
 ```sh
-$ cd grpc/src/php/vendor/datto/protobuf-php
+$ cd grpc/src/php/vendor/datto/protobuf-php # if you had run `composer install` in the previous step
+
+OR
+
+$ git clone https://github.com/stanley-cheung/Protobuf-PHP # clone from github repo
+
 $ gem install rake ronn
 $ rake pear:package version=1.0
 $ sudo pear install Protobuf-1.0.tgz
 ```
 
-Generate client stub code
+### Client Stub
+
+Generate client stub classes from `.proto` files
 
 ```sh
 $ cd grpc/src/php
 $ ./bin/generate_proto_php.sh
 ```
 
-Run a local server serving the math services
+### Run test server
 
- - Please see [Node][] on how to run an example server
+Run a local server serving the math services. Please see [Node][] for how to run an example server.
 
 ```sh
-$ cd grpc/src/node
+$ cd grpc
 $ npm install
-$ nodejs examples/math_server.js
+$ nodejs src/node/test/math/math_server.js
 ```
 
+### Run test client
+
 Run the generated code tests
 
 ```sh
@@ -162,13 +210,15 @@ $ sudo service apache2 restart
 Make sure the Node math server is still running, as above. 
 
 ```sh
-$ cd grpc/src/node
-$ nodejs examples/math_server.js
+$ cd grpc
+$ npm install
+$ nodejs src/node/test/math/math_server.js
 ```
 
 Make sure you have run `composer install` to generate the `vendor/autoload.php` file
 
 ```sh
+$ cd grpc/src/php
 $ composer install
 ```
 
@@ -230,13 +280,15 @@ $ sudo service php5-fpm restart
 Make sure the Node math server is still running, as above. 
 
 ```sh
-$ cd grpc/src/node
-$ nodejs examples/math_server.js
+$ cd grpc
+$ npm install
+$ nodejs src/node/test/math/math_server.js
 ```
 
 Make sure you have run `composer install` to generate the `vendor/autoload.php` file
 
 ```sh
+$ cd grpc/src/php
 $ composer install
 ```
 
@@ -265,7 +317,4 @@ Connect to `localhost/math_client.php` in your browser, or run this from command
 $ curl localhost/math_client.php
 ```
 
-[homebrew]:http://brew.sh
-[gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install
 [Node]:https://github.com/grpc/grpc/tree/master/src/node/examples
-[Debian jessie-backports]:http://backports.debian.org/Instructions/
diff --git a/src/proto/grpc/health/v1alpha/health.proto b/src/proto/grpc/health/v1/health.proto
similarity index 93%
rename from src/proto/grpc/health/v1alpha/health.proto
rename to src/proto/grpc/health/v1/health.proto
index 05f837dd9904ad7f9ea043abe59e1866dec7a99d..6e27606d1b6fdb4f3e658e0ff4b07d21f1bbc017 100644
--- a/src/proto/grpc/health/v1alpha/health.proto
+++ b/src/proto/grpc/health/v1/health.proto
@@ -29,12 +29,11 @@
 
 syntax = "proto3";
 
-package grpc.health.v1alpha;
-option csharp_namespace = "Grpc.Health.V1Alpha";
+package grpc.health.v1;
+option csharp_namespace = "Grpc.Health.V1";
 
 message HealthCheckRequest {
-  string host = 1;
-  string service = 2;
+  string service = 1;
 }
 
 message HealthCheckResponse {
diff --git a/src/proto/grpc/lb/v0/load_balancer.options b/src/proto/grpc/lb/v0/load_balancer.options
new file mode 100644
index 0000000000000000000000000000000000000000..6d4528f838a4c819c5b183bac9edb2db67200356
--- /dev/null
+++ b/src/proto/grpc/lb/v0/load_balancer.options
@@ -0,0 +1,6 @@
+grpc.lb.v0.InitialLoadBalanceRequest.name max_size:128
+grpc.lb.v0.InitialLoadBalanceResponse.client_config max_size:64
+grpc.lb.v0.InitialLoadBalanceResponse.load_balancer_delegate max_size:64
+grpc.lb.v0.Server.ip_address max_size:46
+grpc.lb.v0.Server.load_balance_token max_size:64
+load_balancer.proto no_unions:true
diff --git a/src/proto/grpc/lb/v0/load_balancer.proto b/src/proto/grpc/lb/v0/load_balancer.proto
new file mode 100644
index 0000000000000000000000000000000000000000..e88a4f8c4a7eb7e949daeadfc61becd108a41737
--- /dev/null
+++ b/src/proto/grpc/lb/v0/load_balancer.proto
@@ -0,0 +1,144 @@
+// 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.
+
+syntax = "proto3";
+
+package grpc.lb.v0;
+
+message Duration {
+
+  // Signed seconds of the span of time. Must be from -315,576,000,000
+  // to +315,576,000,000 inclusive.
+  int64 seconds = 1;
+
+  // Signed fractions of a second at nanosecond resolution of the span
+  // of time. Durations less than one second are represented with a 0
+  // `seconds` field and a positive or negative `nanos` field. For durations
+  // of one second or more, a non-zero value for the `nanos` field must be
+  // of the same sign as the `seconds` field. Must be from -999,999,999
+  // to +999,999,999 inclusive.
+  int32 nanos = 2;
+}
+
+service LoadBalancer {
+  // Bidirectional rpc to get a list of servers.
+  rpc BalanceLoad(stream LoadBalanceRequest)
+      returns (stream LoadBalanceResponse);
+}
+
+message LoadBalanceRequest {
+  oneof load_balance_request_type {
+    // This message should be sent on the first request to the load balancer.
+    InitialLoadBalanceRequest initial_request = 1;
+
+    // The client stats should be periodically reported to the load balancer
+    // based on the duration defined in the InitialLoadBalanceResponse.
+    ClientStats client_stats = 2;
+  }
+}
+
+message InitialLoadBalanceRequest {
+  // Name of load balanced service (IE, service.grpc.gslb.google.com)
+  string name = 1;
+}
+
+// Contains client level statistics that are useful to load balancing. Each
+// count should be reset to zero after reporting the stats.
+message ClientStats {
+  // The total number of requests sent by the client since the last report.
+  int64 total_requests = 1;
+
+  // The number of client rpc errors since the last report.
+  int64 client_rpc_errors = 2;
+
+  // The number of dropped requests since the last report.
+  int64 dropped_requests = 3;
+}
+
+message LoadBalanceResponse {
+  oneof load_balance_response_type {
+    // This message should be sent on the first response to the client.
+    InitialLoadBalanceResponse initial_response = 1;
+
+    // Contains the list of servers selected by the load balancer. The client
+    // should send requests to these servers in the specified order.
+    ServerList server_list = 2;
+  }
+}
+
+message InitialLoadBalanceResponse {
+  oneof initial_response_type {
+    // Contains gRPC config options like RPC deadline or flow control.
+    // TODO(yetianx): Change to ClientConfig after it is defined.
+    string client_config = 1;
+
+    // This is an application layer redirect that indicates the client should
+    // use the specified server for load balancing. When this field is set in
+    // the response, the client should open a separate connection to the
+    // load_balancer_delegate and call the BalanceLoad method.
+    string load_balancer_delegate = 2;
+  }
+
+  // This interval defines how often the client should send the client stats
+  // to the load balancer. Stats should only be reported when the duration is
+  // positive.
+  Duration client_stats_report_interval = 3;
+}
+
+message ServerList {
+  // Contains a list of servers selected by the load balancer. The list will
+  // be updated when server resolutions change or as needed to balance load
+  // across more servers. The client should consume the server list in order
+  // unless instructed otherwise via the client_config.
+  repeated Server servers = 1;
+
+  // Indicates the amount of time that the client should consider this server
+  // list as valid. It may be considered stale after waiting this interval of
+  // time after receiving the list. If the interval is not positive, the
+  // client can assume the list is valid until the next list is received.
+  Duration expiration_interval = 3;
+}
+
+message Server {
+  // A resolved address and port for the server. The IP address string may
+  // either be an IPv4 or IPv6 address.
+  string ip_address = 1;
+  int32 port = 2;
+
+  // An opaque token that is passed from the client to the server in metadata.
+  // The server may expect this token to indicate that the request from the
+  // client was load balanced.
+  // TODO(yetianx): Not used right now, and will be used after implementing
+  // load report.
+  bytes load_balance_token = 3;
+
+  // Indicates whether this particular request should be dropped by the client
+  // when this server is chosen from the list.
+  bool drop_request = 4;
+}
diff --git a/src/python/grpcio/README.rst b/src/python/grpcio/README.rst
index d491311886bf341d332f860e26450d1325e5ee98..3dfae50b4bc030b12bc401c75f52caabe3f6b2b4 100644
--- a/src/python/grpcio/README.rst
+++ b/src/python/grpcio/README.rst
@@ -42,3 +42,17 @@ package named :code:`python-dev`).
 
 Note that :code:`$REPO_ROOT` can be assigned to whatever directory name floats
 your fancy.
+
+Troubleshooting
+~~~~~~~~~~~~~~~
+
+Help, I ...
+
+* **... see a** :code:`pkg_resources.VersionConflict` **when I try to install
+  grpc!**
+
+  This is likely because :code:`pip` doesn't own the offending dependency,
+  which in turn is likely because your operating system's package manager owns
+  it. You'll need to force the installation of the dependency:
+
+  :code:`pip install --ignore-installed $OFFENDING_DEPENDENCY`
diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py
index 99ba41b614f0f3e3afc8c721ed3ba0319a18d597..c1f444f6f1f07911aa1c8d50acd84d3b8bd3e354 100644
--- a/src/python/grpcio/commands.py
+++ b/src/python/grpcio/commands.py
@@ -263,6 +263,42 @@ class Gather(setuptools.Command):
       self.distribution.fetch_build_eggs(self.distribution.tests_require)
 
 
+class TestLite(setuptools.Command):
+  """Command to run tests without fetching or building anything."""
+
+  description = 'run tests without fetching or building anything.'
+  user_options = []
+
+  def initialize_options(self):
+    pass
+
+  def finalize_options(self):
+    # distutils requires this override.
+    pass
+
+  def run(self):
+    self._add_eggs_to_path()
+
+    import tests
+    loader = tests.Loader()
+    loader.loadTestsFromNames(['tests'])
+    runner = tests.Runner()
+    result = runner.run(loader.suite)
+    if not result.wasSuccessful():
+      sys.exit('Test failure')
+
+  def _add_eggs_to_path(self):
+    """Adds all egg files under .eggs to sys.path"""
+    # TODO(jtattemusch): there has to be a cleaner way to do this
+    import pkg_resources
+    eggs_dir = os.path.join(PYTHON_STEM, '../../../.eggs')
+    eggs = [os.path.join(eggs_dir, filename)
+            for filename in os.listdir(eggs_dir)
+            if filename.endswith('.egg')]
+    for egg in eggs:
+      sys.path.insert(0, pkg_resources.normalize_path(egg))
+
+
 class RunInterop(test.test):
 
   description = 'run interop test client/server'
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
index ac67f32d923aee5bd597b4c73d9df6ec1362ae15..1f1833d5eccb26d9aa94ca550c953447588ee239 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -89,12 +89,13 @@ cdef class Channel:
 
   def check_connectivity_state(self, bint try_to_connect):
     return grpc_channel_check_connectivity_state(self.c_channel,
-                                                      try_to_connect)
+                                                 try_to_connect)
 
   def watch_connectivity_state(
-      self, last_observed_state, Timespec deadline not None,
-      CompletionQueue queue not None, tag):
+      self, grpc_connectivity_state last_observed_state,
+      Timespec deadline not None, CompletionQueue queue not None, tag):
     cdef OperationTag operation_tag = OperationTag(tag)
+    operation_tag.references = [self, queue]
     cpython.Py_INCREF(operation_tag)
     grpc_channel_watch_connectivity_state(
         self.c_channel, last_observed_state, deadline.c_time,
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
index 757f1245e85a18cc8f77e44579af35faf8acf740..305475c006074fc73bd83f829ce98fed8b72e593 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -31,8 +31,9 @@
 cdef class CompletionQueue:
 
   cdef grpc_completion_queue *c_completion_queue
-  cdef object poll_condition
-  cdef bint is_polling
+  cdef object pluck_condition
+  cdef int num_plucking
+  cdef int num_polling
   cdef bint is_shutting_down
   cdef bint is_shutdown
 
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
index bbf841329938c486da86b4dae9eba777c4bca35b..e11138b1cd8ac690256d47a227801f3a24ac48ae 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -39,8 +39,9 @@ cdef class CompletionQueue:
     self.c_completion_queue = grpc_completion_queue_create(NULL)
     self.is_shutting_down = False
     self.is_shutdown = False
-    self.poll_condition = threading.Condition()
-    self.is_polling = False
+    self.pluck_condition = threading.Condition()
+    self.num_plucking = 0
+    self.num_polling = 0
 
   cdef _interpret_event(self, grpc_event event):
     cdef OperationTag tag = None
@@ -87,19 +88,15 @@ cdef class CompletionQueue:
       c_deadline = deadline.c_time
     cdef grpc_event event
 
-    # Poll within a critical section
-    # TODO(atash) consider making queue polling contention a hard error to
-    # enable easier bug discovery
-    with self.poll_condition:
-      while self.is_polling:
-        self.poll_condition.wait(float(deadline) - time.time())
-      self.is_polling = True
+    # Poll within a critical section to detect contention
+    with self.pluck_condition:
+      assert self.num_plucking == 0, 'cannot simultaneously pluck and poll'
+      self.num_polling += 1
     with nogil:
       event = grpc_completion_queue_next(
           self.c_completion_queue, c_deadline, NULL)
-    with self.poll_condition:
-      self.is_polling = False
-      self.poll_condition.notify()
+    with self.pluck_condition:
+      self.num_polling -= 1
     return self._interpret_event(event)
 
   def pluck(self, OperationTag tag, Timespec deadline=None):
@@ -111,19 +108,18 @@ cdef class CompletionQueue:
       c_deadline = deadline.c_time
     cdef grpc_event event
 
-    # Poll within a critical section
-    # TODO(atash) consider making queue polling contention a hard error to
-    # enable easier bug discovery
-    with self.poll_condition:
-      while self.is_polling:
-        self.poll_condition.wait(float(deadline) - time.time())
-      self.is_polling = True
+    # Pluck within a critical section to detect contention
+    with self.pluck_condition:
+      assert self.num_polling == 0, 'cannot simultaneously pluck and poll'
+      assert self.num_plucking < GRPC_MAX_COMPLETION_QUEUE_PLUCKERS, (
+          'cannot pluck more than {} times simultaneously'.format(
+              GRPC_MAX_COMPLETION_QUEUE_PLUCKERS))
+      self.num_plucking += 1
     with nogil:
       event = grpc_completion_queue_pluck(
           self.c_completion_queue, <cpython.PyObject *>tag, c_deadline, NULL)
-    with self.poll_condition:
-      self.is_polling = False
-      self.poll_condition.notify()
+    with self.pluck_condition:
+      self.num_plucking -= 1
     return self._interpret_event(event)
 
   def shutdown(self):
@@ -137,10 +133,15 @@ cdef class CompletionQueue:
       pass
 
   def __dealloc__(self):
+    cdef gpr_timespec c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME)
     if self.c_completion_queue != NULL:
-      # Ensure shutdown, pump the queue
+      # Ensure shutdown
       if not self.is_shutting_down:
-        self.shutdown()
+        grpc_completion_queue_shutdown(self.c_completion_queue)
+      # Pump the queue
       while not self.is_shutdown:
-        self.poll()
+        with nogil:
+          event = grpc_completion_queue_next(
+              self.c_completion_queue, c_deadline, NULL)
+        self._interpret_event(event)
       grpc_completion_queue_destroy(self.c_completion_queue)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index 800d0ea2f6fbba3805f367bb3a449fed4c17e99b..dbf0045710e439bbe52b5d49000a8b1a81bb9be9 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -138,6 +138,8 @@ cdef extern from "grpc/_cython/loader.h":
   const int GRPC_WRITE_NO_COMPRESS
   const int GRPC_WRITE_USED_MASK
 
+  const int GRPC_MAX_COMPLETION_QUEUE_PLUCKERS
+
   ctypedef struct grpc_completion_queue:
     # We don't care about the internals (and in fact don't know them)
     pass
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi
index 9db49e4d307ae9f932836470b6448eb3a77b229c..a344230be408307f369ae7a109698eece2014498 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -39,4 +39,5 @@ cdef class Server:
   cdef list references
   cdef list registered_completion_queues
 
+  cdef _c_shutdown(self, CompletionQueue queue, tag)
   cdef notify_shutdown_complete(self)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
index 8b65935c3b9394c0f2d57bb4c7bb3eca39c9b82f..fe93da6c1244fd1a3528f6811be6c8d21d755252 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -102,6 +102,16 @@ cdef class Server:
     else:
       return grpc_server_add_insecure_http2_port(self.c_server, address)
 
+  cdef _c_shutdown(self, CompletionQueue queue, tag):
+    self.is_shutting_down = True
+    operation_tag = OperationTag(tag)
+    operation_tag.shutting_down_server = self
+    operation_tag.references.extend([self, queue])
+    cpython.Py_INCREF(operation_tag)
+    grpc_server_shutdown_and_notify(
+        self.c_server, queue.c_completion_queue,
+        <cpython.PyObject *>operation_tag)
+
   def shutdown(self, CompletionQueue queue not None, tag):
     cdef OperationTag operation_tag
     if queue.is_shutting_down:
@@ -113,14 +123,7 @@ cdef class Server:
     elif queue not in self.registered_completion_queues:
       raise ValueError("expected registered completion queue")
     else:
-      self.is_shutting_down = True
-      operation_tag = OperationTag(tag)
-      operation_tag.shutting_down_server = self
-      operation_tag.references.extend([self, queue])
-      cpython.Py_INCREF(operation_tag)
-      grpc_server_shutdown_and_notify(
-          self.c_server, queue.c_completion_queue,
-          <cpython.PyObject *>operation_tag)
+      self._c_shutdown(queue, tag)
 
   cdef notify_shutdown_complete(self):
     # called only by a completion queue on receiving our shutdown operation tag
@@ -142,7 +145,7 @@ cdef class Server:
         pass
       elif not self.is_shutting_down:
         # the user didn't call shutdown - use our backup queue
-        self.shutdown(self.backup_shutdown_queue, None)
+        self._c_shutdown(self.backup_shutdown_queue, None)
         # and now we wait
         while not self.is_shutdown:
           self.backup_shutdown_queue.poll()
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.c b/src/python/grpcio/grpc/_cython/imports.generated.c
index 4b1860ce8c9ef6ebe0d14534b0fa6ad7fcb53d3b..8bd6ae6372b02ff16257cc556123be1f322926ca 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.c
+++ b/src/python/grpcio/grpc/_cython/imports.generated.c
@@ -220,6 +220,7 @@ gpr_event_get_type gpr_event_get_import;
 gpr_event_wait_type gpr_event_wait_import;
 gpr_ref_init_type gpr_ref_init_import;
 gpr_ref_type gpr_ref_import;
+gpr_ref_non_zero_type gpr_ref_non_zero_import;
 gpr_refn_type gpr_refn_import;
 gpr_unref_type gpr_unref_import;
 gpr_stats_init_type gpr_stats_init_import;
@@ -485,6 +486,7 @@ void pygrpc_load_imports(HMODULE library) {
   gpr_event_wait_import = (gpr_event_wait_type) GetProcAddress(library, "gpr_event_wait");
   gpr_ref_init_import = (gpr_ref_init_type) GetProcAddress(library, "gpr_ref_init");
   gpr_ref_import = (gpr_ref_type) GetProcAddress(library, "gpr_ref");
+  gpr_ref_non_zero_import = (gpr_ref_non_zero_type) GetProcAddress(library, "gpr_ref_non_zero");
   gpr_refn_import = (gpr_refn_type) GetProcAddress(library, "gpr_refn");
   gpr_unref_import = (gpr_unref_type) GetProcAddress(library, "gpr_unref");
   gpr_stats_init_import = (gpr_stats_init_type) GetProcAddress(library, "gpr_stats_init");
diff --git a/src/python/grpcio/grpc/_cython/imports.generated.h b/src/python/grpcio/grpc/_cython/imports.generated.h
index ca30742abcb745059eb6efff058fb14297194f31..b70dcccd17a9f7a923bcf57a22e41301ff342469 100644
--- a/src/python/grpcio/grpc/_cython/imports.generated.h
+++ b/src/python/grpcio/grpc/_cython/imports.generated.h
@@ -91,10 +91,10 @@ extern census_context_next_tag_type census_context_next_tag_import;
 typedef int(*census_context_get_tag_type)(const census_context *context, const char *key, census_tag *tag);
 extern census_context_get_tag_type census_context_get_tag_import;
 #define census_context_get_tag census_context_get_tag_import
-typedef char *(*census_context_encode_type)(const census_context *context, char *buffer, size_t buf_size, size_t *print_buf_size, size_t *bin_buf_size);
+typedef size_t(*census_context_encode_type)(const census_context *context, char *buffer, size_t buf_size);
 extern census_context_encode_type census_context_encode_import;
 #define census_context_encode census_context_encode_import
-typedef census_context *(*census_context_decode_type)(const char *buffer, size_t size, const char *bin_buffer, size_t bin_size);
+typedef census_context *(*census_context_decode_type)(const char *buffer, size_t size);
 extern census_context_decode_type census_context_decode_import;
 #define census_context_decode census_context_decode_import
 typedef int(*census_trace_mask_type)(const census_context *context);
@@ -610,6 +610,9 @@ extern gpr_ref_init_type gpr_ref_init_import;
 typedef void(*gpr_ref_type)(gpr_refcount *r);
 extern gpr_ref_type gpr_ref_import;
 #define gpr_ref gpr_ref_import
+typedef void(*gpr_ref_non_zero_type)(gpr_refcount *r);
+extern gpr_ref_non_zero_type gpr_ref_non_zero_import;
+#define gpr_ref_non_zero gpr_ref_non_zero_import
 typedef void(*gpr_refn_type)(gpr_refcount *r, int n);
 extern gpr_refn_type gpr_refn_import;
 #define gpr_refn gpr_refn_import
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index a002a5a0a8d45d40ded2d094faeae8d811759748..a543791f5ce47c83b75b36416c70e644047e80d4 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -42,11 +42,9 @@ CORE_SOURCE_FILES = [
   'src/core/support/env_linux.c',
   'src/core/support/env_posix.c',
   'src/core/support/env_win32.c',
-  'src/core/support/file.c',
-  'src/core/support/file_posix.c',
-  'src/core/support/file_win32.c',
   'src/core/support/histogram.c',
   'src/core/support/host_port.c',
+  'src/core/support/load_file.c',
   'src/core/support/log.c',
   'src/core/support/log_android.c',
   'src/core/support/log_linux.c',
@@ -72,6 +70,8 @@ CORE_SOURCE_FILES = [
   'src/core/support/time_precise.c',
   'src/core/support/time_win32.c',
   'src/core/support/tls_pthread.c',
+  'src/core/support/tmpfile_posix.c',
+  'src/core/support/tmpfile_win32.c',
   'src/core/support/wrap_memcpy.c',
   'src/core/census/grpc_context.c',
   'src/core/census/grpc_filter.c',
@@ -88,6 +88,7 @@ CORE_SOURCE_FILES = [
   'src/core/client_config/connector.c',
   'src/core/client_config/default_initial_connect_string.c',
   'src/core/client_config/initial_connect_string.c',
+  'src/core/client_config/lb_policies/load_balancer_api.c',
   'src/core/client_config/lb_policies/pick_first.c',
   'src/core/client_config/lb_policies/round_robin.c',
   'src/core/client_config/lb_policy.c',
@@ -102,7 +103,7 @@ CORE_SOURCE_FILES = [
   'src/core/client_config/subchannel_factory.c',
   'src/core/client_config/subchannel_index.c',
   'src/core/client_config/uri_parser.c',
-  'src/core/compression/algorithm.c',
+  'src/core/compression/compression_algorithm.c',
   'src/core/compression/message_compress.c',
   'src/core/debug/trace.c',
   'src/core/httpcli/format_request.c',
@@ -152,6 +153,7 @@ CORE_SOURCE_FILES = [
   'src/core/json/json_reader.c',
   'src/core/json/json_string.c',
   'src/core/json/json_writer.c',
+  'src/core/proto/grpc/lb/v0/load_balancer.pb.c',
   'src/core/surface/alarm.c',
   'src/core/surface/api_trace.c',
   'src/core/surface/byte_buffer.c',
@@ -202,7 +204,7 @@ CORE_SOURCE_FILES = [
   'src/core/transport/transport.c',
   'src/core/transport/transport_op_string.c',
   'src/core/httpcli/httpcli_security_connector.c',
-  'src/core/security/base64.c',
+  'src/core/security/b64.c',
   'src/core/security/client_auth_filter.c',
   'src/core/security/credentials.c',
   'src/core/security/credentials_metadata.c',
@@ -228,6 +230,9 @@ CORE_SOURCE_FILES = [
   'src/core/census/operation.c',
   'src/core/census/placeholders.c',
   'src/core/census/tracing.c',
+  'third_party/nanopb/pb_common.c',
+  'third_party/nanopb/pb_decode.c',
+  'third_party/nanopb/pb_encode.c',
   'src/boringssl/err_data.c',
   'third_party/boringssl/crypto/aes/aes.c',
   'third_party/boringssl/crypto/aes/mode_wrappers.c',
diff --git a/src/python/grpcio/tests/_runner.py b/src/python/grpcio/tests/_runner.py
index 4f1ddb57fcfa0956c418314a075ff66c793ea9da..b0dbd92a4955e8a2e093ebb6b03348ec4d15a281 100644
--- a/src/python/grpcio/tests/_runner.py
+++ b/src/python/grpcio/tests/_runner.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -143,10 +143,17 @@ class Runner(object):
 
   def run(self, suite):
     """See setuptools' test_runner setup argument for information."""
+    # only run test cases with id starting with given prefix
+    testcase_filter = os.getenv('GRPC_PYTHON_TESTRUNNER_FILTER')
+    filtered_cases = []
+    for case in _loader.iterate_suite_cases(suite):
+      if not testcase_filter or case.id().startswith(testcase_filter):
+        filtered_cases.append(case)
+
     # Ensure that every test case has no collision with any other test case in
     # the augmented results.
     augmented_cases = [AugmentedCase(case, uuid.uuid4())
-                       for case in _loader.iterate_suite_cases(suite)]
+                       for case in filtered_cases]
     case_id_by_case = dict((augmented_case.case, augmented_case.id)
                            for augmented_case in augmented_cases)
     result_out = StringIO.StringIO()
diff --git a/src/python/grpcio/tests/tests.json b/src/python/grpcio/tests/tests.json
new file mode 100644
index 0000000000000000000000000000000000000000..388d040d5caa67c97da8352c2d1a4539b689c00a
--- /dev/null
+++ b/src/python/grpcio/tests/tests.json
@@ -0,0 +1,62 @@
+[
+  "_base_interface_test.AsyncEasyTest", 
+  "_base_interface_test.AsyncPeasyTest", 
+  "_base_interface_test.SyncEasyTest", 
+  "_base_interface_test.SyncPeasyTest", 
+  "_beta_features_test.BetaFeaturesTest", 
+  "_beta_features_test.ContextManagementAndLifecycleTest", 
+  "_channel_test.ChannelTest", 
+  "_connectivity_channel_test.ChannelConnectivityTest", 
+  "_core_over_links_base_interface_test.AsyncEasyTest", 
+  "_core_over_links_base_interface_test.AsyncPeasyTest", 
+  "_core_over_links_base_interface_test.SyncEasyTest", 
+  "_core_over_links_base_interface_test.SyncPeasyTest", 
+  "_crust_over_core_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest", 
+  "_crust_over_core_face_interface_test.DynamicInvokerEventInvocationSynchronousEventServiceTest", 
+  "_crust_over_core_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest", 
+  "_crust_over_core_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest", 
+  "_crust_over_core_face_interface_test.GenericInvokerEventInvocationSynchronousEventServiceTest", 
+  "_crust_over_core_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest", 
+  "_crust_over_core_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest", 
+  "_crust_over_core_face_interface_test.MultiCallableInvokerEventInvocationSynchronousEventServiceTest", 
+  "_crust_over_core_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest", 
+  "_crust_over_core_over_links_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest", 
+  "_crust_over_core_over_links_face_interface_test.DynamicInvokerEventInvocationSynchronousEventServiceTest", 
+  "_crust_over_core_over_links_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest", 
+  "_crust_over_core_over_links_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest", 
+  "_crust_over_core_over_links_face_interface_test.GenericInvokerEventInvocationSynchronousEventServiceTest", 
+  "_crust_over_core_over_links_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest", 
+  "_crust_over_core_over_links_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest", 
+  "_crust_over_core_over_links_face_interface_test.MultiCallableInvokerEventInvocationSynchronousEventServiceTest", 
+  "_crust_over_core_over_links_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest", 
+  "_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest", 
+  "_face_interface_test.DynamicInvokerEventInvocationSynchronousEventServiceTest", 
+  "_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest", 
+  "_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest", 
+  "_face_interface_test.GenericInvokerEventInvocationSynchronousEventServiceTest", 
+  "_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest", 
+  "_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest", 
+  "_face_interface_test.MultiCallableInvokerEventInvocationSynchronousEventServiceTest", 
+  "_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest", 
+  "_implementations_test.ChannelCredentialsTest", 
+  "_insecure_interop_test.InsecureInteropTest", 
+  "_intermediary_low_test.CancellationTest", 
+  "_intermediary_low_test.EchoTest", 
+  "_intermediary_low_test.ExpirationTest", 
+  "_intermediary_low_test.LonelyClientTest", 
+  "_later_test.LaterTest", 
+  "_logging_pool_test.LoggingPoolTest", 
+  "_lonely_invocation_link_test.LonelyInvocationLinkTest", 
+  "_low_test.HangingServerShutdown", 
+  "_low_test.InsecureServerInsecureClient", 
+  "_not_found_test.NotFoundTest", 
+  "_sanity_test.Sanity", 
+  "_secure_interop_test.SecureInteropTest", 
+  "_transmission_test.RoundTripTest", 
+  "_transmission_test.TransmissionTest", 
+  "_utilities_test.ChannelConnectivityTest", 
+  "beta_python_plugin_test.PythonPluginTest", 
+  "cygrpc_test.InsecureServerInsecureClient", 
+  "cygrpc_test.SecureServerSecureClient", 
+  "cygrpc_test.TypeSmokeTest"
+]
\ No newline at end of file
diff --git a/src/python/grpcio_health_checking/grpc/health/v1alpha/__init__.py b/src/python/grpcio/tests/unit/_sanity/__init__.py
similarity index 98%
rename from src/python/grpcio_health_checking/grpc/health/v1alpha/__init__.py
rename to src/python/grpcio/tests/unit/_sanity/__init__.py
index 708651910607ffb686d781713f6893567821b9fd..2f88fa04122d292e57bd1fa0da8d2a65dad35f61 100644
--- a/src/python/grpcio_health_checking/grpc/health/v1alpha/__init__.py
+++ b/src/python/grpcio/tests/unit/_sanity/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/src/python/grpcio/tests/unit/_sanity/_sanity_test.py b/src/python/grpcio/tests/unit/_sanity/_sanity_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..0a5a715c0e1c66bfcff7a05cbcb9238941e2e4aa
--- /dev/null
+++ b/src/python/grpcio/tests/unit/_sanity/_sanity_test.py
@@ -0,0 +1,53 @@
+# 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.
+
+import json
+import unittest
+
+import tests
+
+
+class Sanity(unittest.TestCase):
+
+  def testTestsJsonUpToDate(self):
+    """Autodiscovers all test suites and checks that tests.json is up to date"""
+    loader = tests.Loader()
+    loader.loadTestsFromNames(['tests'])
+    test_suite_names = [
+        test_case_class.id().rsplit('.', 1)[0]
+        for test_case_class in tests._loader.iterate_suite_cases(loader.suite)]
+    test_suite_names = sorted(set(test_suite_names))
+
+    with open('src/python/grpcio/tests/tests.json') as tests_json_file:
+      tests_json = json.load(tests_json_file)
+    self.assertListEqual(test_suite_names, tests_json)
+
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
diff --git a/src/python/grpcio_health_checking/grpc/health/v1/__init__.py b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..13aac79160b8db0fd6863590a4d044464b72dbcc
--- /dev/null
+++ b/src/python/grpcio_health_checking/grpc/health/v1/__init__.py
@@ -0,0 +1,30 @@
+# Copyright 2015-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.
+
+
diff --git a/src/python/grpcio_health_checking/grpc/health/v1alpha/health.proto b/src/python/grpcio_health_checking/grpc/health/v1/health.proto
similarity index 96%
rename from src/python/grpcio_health_checking/grpc/health/v1alpha/health.proto
rename to src/python/grpcio_health_checking/grpc/health/v1/health.proto
index 57f4aaa9c08d9bbc81aa755cf6b0b3efb76d8adb..de10719b6ced765117e2a4c5672af8a010fa2bd3 100644
--- a/src/python/grpcio_health_checking/grpc/health/v1alpha/health.proto
+++ b/src/python/grpcio_health_checking/grpc/health/v1/health.proto
@@ -1,4 +1,4 @@
-// Copyright 2015, Google Inc.
+// Copyright 2015-2016, Google Inc.
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
 
 syntax = "proto3";
 
-package grpc.health.v1alpha;
+package grpc.health.v1;
 
 message HealthCheckRequest {
   string service = 1;
diff --git a/src/python/grpcio_health_checking/grpc/health/v1alpha/health.py b/src/python/grpcio_health_checking/grpc/health/v1/health.py
similarity index 96%
rename from src/python/grpcio_health_checking/grpc/health/v1alpha/health.py
rename to src/python/grpcio_health_checking/grpc/health/v1/health.py
index 9dfcd962f06142a6f6f85dee8dde2338635d4c58..60cbd644330b2ac48126fed40c58768de087c007 100644
--- a/src/python/grpcio_health_checking/grpc/health/v1alpha/health.py
+++ b/src/python/grpcio_health_checking/grpc/health/v1/health.py
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,7 @@ import abc
 import enum
 import threading
 
-from grpc.health.v1alpha import health_pb2
+from grpc.health.v1 import health_pb2
 
 
 @enum.unique
@@ -64,7 +64,7 @@ class _HealthServicer(health_pb2.EarlyAdopterHealthServicer):
 
   def set(service, status):
     if not isinstance(status, HealthStatus):
-      raise TypeError('expected grpc.health.v1alpha.health.HealthStatus '
+      raise TypeError('expected grpc.health.v1.health.HealthStatus '
                       'for argument `status` but got {}'.format(status))
     with self._server_status_lock:
       self._server_status[service] = status
diff --git a/src/ruby/.rubocop.yml b/src/ruby/.rubocop.yml
index dd57ab60828bc0bf6902ae6ef571992feb4f957d..d13ce4265537732de5770455009f6008dc43c4e8 100644
--- a/src/ruby/.rubocop.yml
+++ b/src/ruby/.rubocop.yml
@@ -7,7 +7,7 @@ AllCops:
     - 'bin/apis/**/*'
     - 'bin/math.rb'
     - 'bin/math_services.rb'
-    - 'pb/grpc/health/v1alpha/*'
+    - 'pb/grpc/health/v1/*'
     - 'pb/test/**/*'
 
 Metrics/CyclomaticComplexity:
@@ -15,3 +15,6 @@ Metrics/CyclomaticComplexity:
 
 Metrics/PerceivedComplexity:
   Max: 8
+
+Metrics/ClassLength:
+  Max: 250
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index 1af34d97fbcd8239edbe26e595cef8d92ba59bfd..56db4ec686b5fb8ccecdcebf61bdd0bcfbf01b9c 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -220,6 +220,7 @@ gpr_event_get_type gpr_event_get_import;
 gpr_event_wait_type gpr_event_wait_import;
 gpr_ref_init_type gpr_ref_init_import;
 gpr_ref_type gpr_ref_import;
+gpr_ref_non_zero_type gpr_ref_non_zero_import;
 gpr_refn_type gpr_refn_import;
 gpr_unref_type gpr_unref_import;
 gpr_stats_init_type gpr_stats_init_import;
@@ -481,6 +482,7 @@ void grpc_rb_load_imports(HMODULE library) {
   gpr_event_wait_import = (gpr_event_wait_type) GetProcAddress(library, "gpr_event_wait");
   gpr_ref_init_import = (gpr_ref_init_type) GetProcAddress(library, "gpr_ref_init");
   gpr_ref_import = (gpr_ref_type) GetProcAddress(library, "gpr_ref");
+  gpr_ref_non_zero_import = (gpr_ref_non_zero_type) GetProcAddress(library, "gpr_ref_non_zero");
   gpr_refn_import = (gpr_refn_type) GetProcAddress(library, "gpr_refn");
   gpr_unref_import = (gpr_unref_type) GetProcAddress(library, "gpr_unref");
   gpr_stats_init_import = (gpr_stats_init_type) GetProcAddress(library, "gpr_stats_init");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index b61c5282b6d56aa0a9a30ed5dbd3fd3797a8dc79..b972f60fc3584dbed102d5b306f451b9ac14634a 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -91,10 +91,10 @@ extern census_context_next_tag_type census_context_next_tag_import;
 typedef int(*census_context_get_tag_type)(const census_context *context, const char *key, census_tag *tag);
 extern census_context_get_tag_type census_context_get_tag_import;
 #define census_context_get_tag census_context_get_tag_import
-typedef char *(*census_context_encode_type)(const census_context *context, char *buffer, size_t buf_size, size_t *print_buf_size, size_t *bin_buf_size);
+typedef size_t(*census_context_encode_type)(const census_context *context, char *buffer, size_t buf_size);
 extern census_context_encode_type census_context_encode_import;
 #define census_context_encode census_context_encode_import
-typedef census_context *(*census_context_decode_type)(const char *buffer, size_t size, const char *bin_buffer, size_t bin_size);
+typedef census_context *(*census_context_decode_type)(const char *buffer, size_t size);
 extern census_context_decode_type census_context_decode_import;
 #define census_context_decode census_context_decode_import
 typedef int(*census_trace_mask_type)(const census_context *context);
@@ -610,6 +610,9 @@ extern gpr_ref_init_type gpr_ref_init_import;
 typedef void(*gpr_ref_type)(gpr_refcount *r);
 extern gpr_ref_type gpr_ref_import;
 #define gpr_ref gpr_ref_import
+typedef void(*gpr_ref_non_zero_type)(gpr_refcount *r);
+extern gpr_ref_non_zero_type gpr_ref_non_zero_import;
+#define gpr_ref_non_zero gpr_ref_non_zero_import
 typedef void(*gpr_refn_type)(gpr_refcount *r, int n);
 extern gpr_refn_type gpr_refn_import;
 #define gpr_refn gpr_refn_import
diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb
index ef2997c991809acadc435df9242dc641a1096a2c..b30d19dd2bbb676ef989b460f500b3eeaad25754 100644
--- a/src/ruby/lib/grpc/generic/rpc_server.rb
+++ b/src/ruby/lib/grpc/generic/rpc_server.rb
@@ -107,7 +107,9 @@ module GRPC
 
     # Starts running the jobs in the thread pool.
     def start
-      fail 'already stopped' if @stopped
+      @stop_mutex.synchronize do
+        fail 'already stopped' if @stopped
+      end
       until @workers.size == @size.to_i
         next_thread = Thread.new do
           catch(:exit) do  # allows { throw :exit } to kill a thread
@@ -264,10 +266,10 @@ module GRPC
       @pool = Pool.new(@pool_size)
       @run_cond = ConditionVariable.new
       @run_mutex = Mutex.new
-      @running = false
+      # running_state can take 4 values: :not_started, :running, :stopping, and
+      # :stopped. State transitions can only proceed in that order.
+      @running_state = :not_started
       @server = RpcServer.setup_srv(server_override, @cq, **kw)
-      @stopped = false
-      @stop_mutex = Mutex.new
     end
 
     # stops a running server
@@ -275,27 +277,42 @@ module GRPC
     # the call has no impact if the server is already stopped, otherwise
     # server's current call loop is it's last.
     def stop
-      return unless @running
-      @stop_mutex.synchronize do
-        @stopped = true
+      @run_mutex.synchronize do
+        fail 'Cannot stop before starting' if @running_state == :not_started
+        return if @running_state != :running
+        transition_running_state(:stopping)
       end
       deadline = from_relative_time(@poll_period)
-      return if @server.close(@cq, deadline)
-      deadline = from_relative_time(@poll_period)
       @server.close(@cq, deadline)
       @pool.stop
     end
 
-    # determines if the server has been stopped
-    def stopped?
-      @stop_mutex.synchronize do
-        return @stopped
+    def running_state
+      @run_mutex.synchronize do
+        return @running_state
+      end
+    end
+
+    # Can only be called while holding @run_mutex
+    def transition_running_state(target_state)
+      state_transitions = {
+        not_started: :running,
+        running: :stopping,
+        stopping: :stopped
+      }
+      if state_transitions[@running_state] == target_state
+        @running_state = target_state
+      else
+        fail "Bad server state transition: #{@running_state}->#{target_state}"
       end
     end
 
-    # determines if the server is currently running
     def running?
-      @running
+      running_state == :running
+    end
+
+    def stopped?
+      running_state == :stopped
     end
 
     # Is called from other threads to wait for #run to start up the server.
@@ -304,13 +321,11 @@ module GRPC
     #
     # @param timeout [Numeric] number of seconds to wait
     # @result [true, false] true if the server is running, false otherwise
-    def wait_till_running(timeout = 0.1)
-      end_time, sleep_period = Time.now + timeout, (1.0 * timeout) / 100
-      while Time.now < end_time
-        @run_mutex.synchronize { @run_cond.wait(@run_mutex) } unless running?
-        sleep(sleep_period)
+    def wait_till_running(timeout = nil)
+      @run_mutex.synchronize do
+        @run_cond.wait(@run_mutex, timeout) if @running_state == :not_started
+        return @running_state == :running
       end
-      running?
     end
 
     # Runs the server in its own thread, then waits for signal INT or TERM on
@@ -360,11 +375,14 @@ module GRPC
     # @param service [Object|Class] a service class or object as described
     #        above
     def handle(service)
-      fail 'cannot add services if the server is running' if running?
-      fail 'cannot add services if the server is stopped' if stopped?
-      cls = service.is_a?(Class) ? service : service.class
-      assert_valid_service_class(cls)
-      add_rpc_descs_for(service)
+      @run_mutex.synchronize do
+        unless @running_state == :not_started
+          fail 'cannot add services if the server has been started'
+        end
+        cls = service.is_a?(Class) ? service : service.class
+        assert_valid_service_class(cls)
+        add_rpc_descs_for(service)
+      end
     end
 
     # runs the server
@@ -375,16 +393,13 @@ module GRPC
     # - #running? returns true after this is called, until #stop cause the
     #   the server to stop.
     def run
-      if rpc_descs.size.zero?
-        GRPC.logger.warn('did not run as no services were present')
-        return
-      end
       @run_mutex.synchronize do
-        @running = true
-        @run_cond.signal
+        fail 'cannot run without registering services' if rpc_descs.size.zero?
+        @pool.start
+        @server.start
+        transition_running_state(:running)
+        @run_cond.broadcast
       end
-      @pool.start
-      @server.start
       loop_handle_server_calls
     end
 
@@ -413,9 +428,9 @@ module GRPC
 
     # handles calls to the server
     def loop_handle_server_calls
-      fail 'not running' unless @running
+      fail 'not started' if running_state == :not_started
       loop_tag = Object.new
-      until stopped?
+      while running_state == :running
         begin
           an_rpc = @server.request_call(@cq, loop_tag, INFINITE_FUTURE)
           break if (!an_rpc.nil?) && an_rpc.call.nil?
@@ -430,11 +445,14 @@ module GRPC
         rescue Core::CallError, RuntimeError => e
           # these might happen for various reasonse.  The correct behaviour of
           # the server is to log them and continue, if it's not shutting down.
-          GRPC.logger.warn("server call failed: #{e}") unless stopped?
+          if running_state == :running
+            GRPC.logger.warn("server call failed: #{e}")
+          end
           next
         end
       end
-      @running = false
+      # @running_state should be :stopping here
+      @run_mutex.synchronize { transition_running_state(:stopped) }
       GRPC.logger.info("stopped: #{self}")
     end
 
@@ -484,9 +502,10 @@ module GRPC
       cls.assert_rpc_descs_have_methods
     end
 
+    # This should be called while holding @run_mutex
     def add_rpc_descs_for(service)
       cls = service.is_a?(Class) ? service : service.class
-      specs, handlers = rpc_descs, rpc_handlers
+      specs, handlers = (@rpc_descs ||= {}), (@rpc_handlers ||= {})
       cls.rpc_descs.each_pair do |name, spec|
         route = "/#{cls.service_name}/#{name}".to_sym
         fail "already registered: rpc #{route} from #{spec}" if specs.key? route
diff --git a/src/ruby/pb/README.md b/src/ruby/pb/README.md
index e04aef185caaa51720922dbd73e02c82da147450..d9e30bbc854434947bb9560d4115d448170ef64a 100644
--- a/src/ruby/pb/README.md
+++ b/src/ruby/pb/README.md
@@ -11,7 +11,7 @@ The code is is generated using the protoc (> 3.0.0.alpha.1) and the
 grpc_ruby_plugin.  These must be installed to regenerate the IDL defined
 classes, but that's not necessary just to use them.
 
-health_check/v1alpha
+health_check/v1
 --------------------
 
 This package defines the surface of a simple health check service that gRPC
@@ -20,7 +20,7 @@ re-generate the surface.
 
 ```bash
 $ # (from this directory)
-$ protoc -I ../../proto ../../proto/grpc/health/v1alpha/health.proto \
+$ protoc -I ../../proto ../../proto/grpc/health/v1/health.proto \
     --grpc_out=. \
     --ruby_out=. \
     --plugin=protoc-gen-grpc=`which grpc_ruby_plugin`
diff --git a/src/ruby/pb/generate_proto_ruby.sh b/src/ruby/pb/generate_proto_ruby.sh
index 576b1c08d300f0a1bf97388a38ae71e18b91524f..86c082099d98304859e4ab55f5a6512b0116f8ab 100755
--- a/src/ruby/pb/generate_proto_ruby.sh
+++ b/src/ruby/pb/generate_proto_ruby.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -35,7 +35,7 @@ cd $(dirname $0)/../../..
 PROTOC=bins/opt/protobuf/protoc
 PLUGIN=protoc-gen-grpc=bins/opt/grpc_ruby_plugin
 
-$PROTOC -I src/proto src/proto/grpc/health/v1alpha/health.proto \
+$PROTOC -I src/proto src/proto/grpc/health/v1/health.proto \
     --grpc_out=src/ruby/pb \
     --ruby_out=src/ruby/pb \
     --plugin=$PLUGIN
diff --git a/src/ruby/pb/grpc/health/checker.rb b/src/ruby/pb/grpc/health/checker.rb
index 8c692e74f900bbc78b15685e4df41274f358a8ba..9f1ee65c41935164c322cde79e7412265010df0e 100644
--- a/src/ruby/pb/grpc/health/checker.rb
+++ b/src/ruby/pb/grpc/health/checker.rb
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 require 'grpc'
-require 'grpc/health/v1alpha/health_services'
+require 'grpc/health/v1/health_services'
 require 'thread'
 
 module Grpc
@@ -36,9 +36,9 @@ module Grpc
   # service.
   module Health
     # Checker is implementation of the schema-specified health checking service.
-    class Checker < V1alpha::Health::Service
+    class Checker < V1::Health::Service
       StatusCodes = GRPC::Core::StatusCodes
-      HealthCheckResponse = V1alpha::HealthCheckResponse
+      HealthCheckResponse = V1::HealthCheckResponse
 
       # Initializes the statuses of participating services
       def initialize
@@ -50,20 +50,20 @@ module Grpc
       def check(req, _call)
         status = nil
         @status_mutex.synchronize do
-          status = @statuses["#{req.host}/#{req.service}"]
+          status = @statuses["#{req.service}"]
         end
         fail GRPC::BadStatus, StatusCodes::NOT_FOUND if status.nil?
         HealthCheckResponse.new(status: status)
       end
 
-      # Adds the health status for a given host and service.
-      def add_status(host, service, status)
-        @status_mutex.synchronize { @statuses["#{host}/#{service}"] = status }
+      # Adds the health status for a given service.
+      def add_status(service, status)
+        @status_mutex.synchronize { @statuses["#{service}"] = status }
       end
 
-      # Clears the status for the given host or service.
-      def clear_status(host, service)
-        @status_mutex.synchronize { @statuses.delete("#{host}/#{service}") }
+      # Clears the status for the given service.
+      def clear_status(service)
+        @status_mutex.synchronize { @statuses.delete("#{service}") }
       end
 
       # Clears alls the statuses.
diff --git a/src/ruby/pb/grpc/health/v1/health.rb b/src/ruby/pb/grpc/health/v1/health.rb
new file mode 100644
index 0000000000000000000000000000000000000000..aa87a93918b123f6af2f91f58fc7f004b91481b0
--- /dev/null
+++ b/src/ruby/pb/grpc/health/v1/health.rb
@@ -0,0 +1,28 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: grpc/health/v1/health.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+  add_message "grpc.health.v1.HealthCheckRequest" do
+    optional :service, :string, 1
+  end
+  add_message "grpc.health.v1.HealthCheckResponse" do
+    optional :status, :enum, 1, "grpc.health.v1.HealthCheckResponse.ServingStatus"
+  end
+  add_enum "grpc.health.v1.HealthCheckResponse.ServingStatus" do
+    value :UNKNOWN, 0
+    value :SERVING, 1
+    value :NOT_SERVING, 2
+  end
+end
+
+module Grpc
+  module Health
+    module V1
+      HealthCheckRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1.HealthCheckRequest").msgclass
+      HealthCheckResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1.HealthCheckResponse").msgclass
+      HealthCheckResponse::ServingStatus = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1.HealthCheckResponse.ServingStatus").enummodule
+    end
+  end
+end
diff --git a/src/ruby/pb/grpc/health/v1alpha/health_services.rb b/src/ruby/pb/grpc/health/v1/health_services.rb
similarity index 71%
rename from src/ruby/pb/grpc/health/v1alpha/health_services.rb
rename to src/ruby/pb/grpc/health/v1/health_services.rb
index d5cba2e9ec71c22555c3ebb7c4f739e6bb3c6ed8..cb79b20437f573b40f9c3f6265eec722db4e87c7 100644
--- a/src/ruby/pb/grpc/health/v1alpha/health_services.rb
+++ b/src/ruby/pb/grpc/health/v1/health_services.rb
@@ -1,12 +1,12 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
-# Source: grpc/health/v1alpha/health.proto for package 'grpc.health.v1alpha'
+# Source: grpc/health/v1/health.proto for package 'grpc.health.v1'
 
 require 'grpc'
-require 'grpc/health/v1alpha/health'
+require 'grpc/health/v1/health'
 
 module Grpc
   module Health
-    module V1alpha
+    module V1
       module Health
 
         # TODO: add proto service documentation here
@@ -16,7 +16,7 @@ module Grpc
 
           self.marshal_class_method = :encode
           self.unmarshal_class_method = :decode
-          self.service_name = 'grpc.health.v1alpha.Health'
+          self.service_name = 'grpc.health.v1.Health'
 
           rpc :Check, HealthCheckRequest, HealthCheckResponse
         end
diff --git a/src/ruby/pb/grpc/health/v1alpha/health.rb b/src/ruby/pb/grpc/health/v1alpha/health.rb
deleted file mode 100644
index 9c04298ea54394cda76b9953b15bfae08755f8ce..0000000000000000000000000000000000000000
--- a/src/ruby/pb/grpc/health/v1alpha/health.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: grpc/health/v1alpha/health.proto
-
-require 'google/protobuf'
-
-Google::Protobuf::DescriptorPool.generated_pool.build do
-  add_message "grpc.health.v1alpha.HealthCheckRequest" do
-    optional :host, :string, 1
-    optional :service, :string, 2
-  end
-  add_message "grpc.health.v1alpha.HealthCheckResponse" do
-    optional :status, :enum, 1, "grpc.health.v1alpha.HealthCheckResponse.ServingStatus"
-  end
-  add_enum "grpc.health.v1alpha.HealthCheckResponse.ServingStatus" do
-    value :UNKNOWN, 0
-    value :SERVING, 1
-    value :NOT_SERVING, 2
-  end
-end
-
-module Grpc
-  module Health
-    module V1alpha
-      HealthCheckRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1alpha.HealthCheckRequest").msgclass
-      HealthCheckResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1alpha.HealthCheckResponse").msgclass
-      HealthCheckResponse::ServingStatus = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.health.v1alpha.HealthCheckResponse.ServingStatus").enummodule
-    end
-  end
-end
diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb
index be6331d68bb9a392d773af59a8c3dceb53ca187a..dfaec6d6edc01dabb9be8b0b70a4a04e44a3c946 100644
--- a/src/ruby/spec/generic/rpc_server_spec.rb
+++ b/src/ruby/spec/generic/rpc_server_spec.rb
@@ -1,4 +1,4 @@
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -220,19 +220,10 @@ describe GRPC::RpcServer do
       @srv = RpcServer.new(**opts)
     end
 
-    after(:each) do
-      @srv.stop
-    end
-
     it 'starts out false' do
       expect(@srv.stopped?).to be(false)
     end
 
-    it 'stays false after a #stop is called before #run' do
-      @srv.stop
-      expect(@srv.stopped?).to be(false)
-    end
-
     it 'stays false after the server starts running', server: true do
       @srv.handle(EchoService)
       t = Thread.new { @srv.run }
@@ -247,8 +238,8 @@ describe GRPC::RpcServer do
       t = Thread.new { @srv.run }
       @srv.wait_till_running
       @srv.stop
-      expect(@srv.stopped?).to be(true)
       t.join
+      expect(@srv.stopped?).to be(true)
     end
   end
 
@@ -266,9 +257,7 @@ describe GRPC::RpcServer do
         server_override: @server
       }
       r = RpcServer.new(**opts)
-      r.run
-      expect(r.running?).to be(false)
-      r.stop
+      expect { r.run }.to raise_error(RuntimeError)
     end
 
     it 'is true after run is called with a registered service' do
@@ -293,10 +282,6 @@ describe GRPC::RpcServer do
       @srv = RpcServer.new(**@opts)
     end
 
-    after(:each) do
-      @srv.stop
-    end
-
     it 'raises if #run has already been called' do
       @srv.handle(EchoService)
       t = Thread.new { @srv.run }
@@ -528,10 +513,6 @@ describe GRPC::RpcServer do
         @srv = RpcServer.new(**server_opts)
       end
 
-      after(:each) do
-        @srv.stop
-      end
-
       it 'should be added to BadStatus when requests fail', server: true do
         service = FailingService.new
         @srv.handle(service)
diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb
index c1decd822a76062a58ea9dda0e83a18ec7776590..9bb79bb4cae057c8a5ebab92467570d570076e2d 100644
--- a/src/ruby/spec/pb/health/checker_spec.rb
+++ b/src/ruby/spec/pb/health/checker_spec.rb
@@ -28,7 +28,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 require 'grpc'
-require 'grpc/health/v1alpha/health'
+require 'grpc/health/v1/health'
 require 'grpc/health/checker'
 require 'open3'
 require 'tmpdir'
@@ -43,7 +43,7 @@ describe 'Health protobuf code generation' do
       skip 'protoc || grpc_ruby_plugin missing, cannot verify health code-gen'
     else
       it 'should already be loaded indirectly i.e, used by the other specs' do
-        expect(require('grpc/health/v1alpha/health_services')).to be(false)
+        expect(require('grpc/health/v1/health_services')).to be(false)
       end
 
       it 'should have the same content as created by code generation' do
@@ -52,7 +52,7 @@ describe 'Health protobuf code generation' do
 
         # Get the current content
         service_path = File.join(root_dir, 'ruby', 'pb', 'grpc',
-                                 'health', 'v1alpha', 'health_services.rb')
+                                 'health', 'v1', 'health_services.rb')
         want = nil
         File.open(service_path) { |f| want = f.read }
 
@@ -61,12 +61,12 @@ describe 'Health protobuf code generation' do
         plugin = plugin.strip
         got = nil
         Dir.mktmpdir do |tmp_dir|
-          gen_out = File.join(tmp_dir, 'grpc', 'health', 'v1alpha',
+          gen_out = File.join(tmp_dir, 'grpc', 'health', 'v1',
                               'health_services.rb')
           pid = spawn(
             'protoc',
             '-I.',
-            'grpc/health/v1alpha/health.proto',
+            'grpc/health/v1/health.proto',
             "--grpc_out=#{tmp_dir}",
             "--plugin=protoc-gen-grpc=#{plugin}",
             chdir: pb_dir)
@@ -81,27 +81,17 @@ end
 
 describe Grpc::Health::Checker do
   StatusCodes = GRPC::Core::StatusCodes
-  ServingStatus = Grpc::Health::V1alpha::HealthCheckResponse::ServingStatus
-  HCResp = Grpc::Health::V1alpha::HealthCheckResponse
-  HCReq = Grpc::Health::V1alpha::HealthCheckRequest
+  ServingStatus = Grpc::Health::V1::HealthCheckResponse::ServingStatus
+  HCResp = Grpc::Health::V1::HealthCheckResponse
+  HCReq = Grpc::Health::V1::HealthCheckRequest
   success_tests =
     [
       {
-        desc: 'neither host or service are specified',
-        host: '',
+        desc: 'the service is not specified',
         service: ''
       }, {
-        desc: 'only the host is specified',
-        host: 'test-fake-host',
-        service: ''
-      }, {
-        desc: 'the host and service are specified',
-        host: 'test-fake-host',
+        desc: 'the service is specified',
         service: 'fake-service-1'
-      }, {
-        desc: 'only the service is specified',
-        host: '',
-        service: 'fake-service-2'
       }
     ]
 
@@ -114,9 +104,8 @@ describe Grpc::Health::Checker do
   context 'method `add_status` and `check`' do
     success_tests.each do |t|
       it "should succeed when #{t[:desc]}" do
-        subject.add_status(t[:host], t[:service], ServingStatus::NOT_SERVING)
-        got = subject.check(HCReq.new(host: t[:host], service: t[:service]),
-                            nil)
+        subject.add_status(t[:service], ServingStatus::NOT_SERVING)
+        got = subject.check(HCReq.new(service: t[:service]), nil)
         want = HCResp.new(status: ServingStatus::NOT_SERVING)
         expect(got).to eq(want)
       end
@@ -127,7 +116,7 @@ describe Grpc::Health::Checker do
     success_tests.each do |t|
       it "should fail with NOT_FOUND when #{t[:desc]}" do
         blk = proc do
-          subject.check(HCReq.new(host: t[:host], service: t[:service]), nil)
+          subject.check(HCReq.new(service: t[:service]), nil)
         end
         expected_msg = /#{StatusCodes::NOT_FOUND}/
         expect(&blk).to raise_error GRPC::BadStatus, expected_msg
@@ -138,16 +127,14 @@ describe Grpc::Health::Checker do
   context 'method `clear_status`' do
     success_tests.each do |t|
       it "should fail after clearing status when #{t[:desc]}" do
-        subject.add_status(t[:host], t[:service], ServingStatus::NOT_SERVING)
-        got = subject.check(HCReq.new(host: t[:host], service: t[:service]),
-                            nil)
+        subject.add_status(t[:service], ServingStatus::NOT_SERVING)
+        got = subject.check(HCReq.new(service: t[:service]), nil)
         want = HCResp.new(status: ServingStatus::NOT_SERVING)
         expect(got).to eq(want)
 
-        subject.clear_status(t[:host], t[:service])
+        subject.clear_status(t[:service])
         blk = proc do
-          subject.check(HCReq.new(host: t[:host], service: t[:service]),
-                        nil)
+          subject.check(HCReq.new(service: t[:service]), nil)
         end
         expected_msg = /#{StatusCodes::NOT_FOUND}/
         expect(&blk).to raise_error GRPC::BadStatus, expected_msg
@@ -158,9 +145,8 @@ describe Grpc::Health::Checker do
   context 'method `clear_all`' do
     it 'should return NOT_FOUND after being invoked' do
       success_tests.each do |t|
-        subject.add_status(t[:host], t[:service], ServingStatus::NOT_SERVING)
-        got = subject.check(HCReq.new(host: t[:host], service: t[:service]),
-                            nil)
+        subject.add_status(t[:service], ServingStatus::NOT_SERVING)
+        got = subject.check(HCReq.new(service: t[:service]), nil)
         want = HCResp.new(status: ServingStatus::NOT_SERVING)
         expect(got).to eq(want)
       end
@@ -169,7 +155,7 @@ describe Grpc::Health::Checker do
 
       success_tests.each do |t|
         blk = proc do
-          subject.check(HCReq.new(host: t[:host], service: t[:service]), nil)
+          subject.check(HCReq.new(service: t[:service]), nil)
         end
         expected_msg = /#{StatusCodes::NOT_FOUND}/
         expect(&blk).to raise_error GRPC::BadStatus, expected_msg
@@ -203,7 +189,7 @@ describe Grpc::Health::Checker do
 
     it 'should receive the correct status', server: true do
       @srv.handle(subject)
-      subject.add_status('', '', ServingStatus::NOT_SERVING)
+      subject.add_status('', ServingStatus::NOT_SERVING)
       t = Thread.new { @srv.run }
       @srv.wait_till_running
 
@@ -221,7 +207,7 @@ describe Grpc::Health::Checker do
       @srv.wait_till_running
       blk = proc do
         stub = CheckerStub.new(@host, :this_channel_is_insecure, **@client_opts)
-        stub.check(HCReq.new(host: 'unknown', service: 'unknown'))
+        stub.check(HCReq.new(service: 'unknown'))
       end
       expected_msg = /#{StatusCodes::NOT_FOUND}/
       expect(&blk).to raise_error GRPC::BadStatus, expected_msg
diff --git a/summerofcode/ideas.md b/summerofcode/ideas.md
index 073262339b1df8c4bf282f5e926d5fbc30ef274b..83f2cecd48c508348ad5a691daf9e4d6a8f09f9b 100644
--- a/summerofcode/ideas.md
+++ b/summerofcode/ideas.md
@@ -1,4 +1,54 @@
-Google Summer of Code 2016 gRPC Ideas
-=====================================
+# gRPC Summer of Code Project Ideas
 
-(Skeleton for now.)
+Hello students!
+
+We want gRPC to be the universal remote procedure call protocol for all
+computing platforms and paradigms, so while these are our ideas of what we
+think would make good projects for the summer, we're eager to hear your ideas
+and proposals as well.
+[Try us out](https://github.com/grpc/grpc/blob/master/CONTRIBUTING.md) and get
+to know the gRPC code and team!
+
+**Required skills for all projects:** git version control, collaborative
+software development on github.com, and software development in at least one
+of gRPC's ten languages on at least one of Linux, Mac OS X, and Windows.
+
+-------------------------------------
+
+gRPC C Core:
+
+1. Port gRPC to  one of the major BSD platforms ([FreeBSD](https://freebsd.org), [NetBSD](https://netbsd.org), and [OpenBSD](https://openbsd.org)) and create packages for them. Add [kqueue](https://www.freebsd.org/cgi/man.cgi?query=kqueue) support in the process.
+ * **Required skills:** C programming language, BSD operating system.
+ * **Likely mentors:** [Craig Tiller](https://github.com/ctiller),
+ [Nicolas Noble](https://github.com/nicolasnoble),
+ [Vijay Pai](https://github.com/vjpai).
+1. Fix gRPC C-core's URI parser. The current parser does not qualify as a standard parser according to [RFC3986]( https://tools.ietf.org/html/rfc3986). Write test suites to verify this and make changes necessary to make the URI parser compliant.
+ * **Required skills:** C programming language, HTTP standard compliance.
+ * **Likely mentors:** [Craig Tiller](https://github.com/ctiller).
+1. HPACK compression efficiency evaluation - Figure out how to benchmark gRPC's compression efficiency (both in terms of bytes on the wire and cpu cycles). Implement benchmarks. Potentially extend this to other full-stack gRPC implementations (Java and Go).
+ * **Required skills:** C programming language, software performance benchmarking, potentially Java and Go.
+ * **Likely mentors:** [Craig Tiller](https://github.com/ctiller).
+
+
+gRPC Python:
+
+1. Port gRPC Python to [PyPy](http://pypy.org). Investigate the state of [Cython support](http://docs.cython.org/src/userguide/pypy.html) to do this or potentially explore [cffi](https://cffi.readthedocs.org/en/latest/).
+ * **Required skills:** Python programming language, PyPy Python interpreter.
+ * **Likely mentors:** [Nathaniel Manista](https://github.com/nathanielmanistaatgoogle), [Masood Malekghassemi](https://github.com/soltanmm).
+1. Develop and test Python 3.5 Support for gRPC. Make necessary changes to port gRPC and package it for supported platforms.
+ * **Required skills:** Python programming language, PyPy Python interpreter.
+ * **Likely mentors:** [Nathaniel Manista](https://github.com/nathanielmanistaatgoogle), [Masood Malekghassemi](https://github.com/soltanmm).
+ 
+gRPC Ruby/Java:
+
+1. [jRuby](http://jruby.org) support for gRPC. Develop a jRuby wrapper for gRPC based on grpc-java and ensure that it is API compatible with the existing Ruby implementation and passes all tests.
+ * **Required skills:** Java programming language, Ruby programming language.
+ * **Likely mentors:** [Michael Lumish](https://github.com/murgatroid99), [Eric Anderson](https://github.com/ejona86).
+
+
+gRPC Wire Protocol:
+
+1. Develop a [Wireshark](https://wireshark.org) plugin for the gRPC protocol. Provide documentation and tutorials for this plugin.
+ * **Bonus:** consider set-up and use with mobile clients.
+ * **Required skills:** Wireshark software.
+ * **Likely mentors:** [Nicolas Noble](https://github.com/nicolasnoble).
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 7aa6ad71e26a2e1a18c950f350ddcc20e75d7a65..c54c146620fb4e2d90fc8bd0f0f68f18cb08b51f 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -187,6 +187,12 @@
   CXX11_CHECK_CMD = $(CXX) -std=c++11 -o $(TMPOUT) -c test/build/c++11.cc
   HAS_CXX11 = $(shell $(CXX11_CHECK_CMD) 2> /dev/null && echo true || echo false)
 
+  CHECK_SHADOW_WORKS_CMD = $(CC) -std=c99 -Werror -Wshadow -o $(TMPOUT) -c test/build/shadow.c
+  HAS_WORKING_SHADOW = $(shell $(CHECK_SHADOW_WORKS_CMD) 2> /dev/null && echo true || echo false)
+  ifeq ($(HAS_WORKING_SHADOW),true)
+  W_SHADOW=-Wshadow
+  endif
+
   CHECK_NO_SHIFT_NEGATIVE_VALUE_CMD = $(CC) -std=c99 -Werror -Wno-shift-negative-value -o $(TMPOUT) -c test/build/empty.c
   HAS_NO_SHIFT_NEGATIVE_VALUE = $(shell $(CHECK_NO_SHIFT_NEGATIVE_VALUE_CMD) 2> /dev/null && echo true || echo false)
   ifeq ($(HAS_NO_SHIFT_NEGATIVE_VALUE),true)
@@ -207,7 +213,7 @@
   DEFINES += $(EXTRA_DEFINES)
   endif
 
-  CFLAGS += -std=c99 -Wsign-conversion -Wconversion -Wshadow
+  CFLAGS += -std=c99 -Wsign-conversion -Wconversion $(W_SHADOW)
   ifeq ($(HAS_CXX11),true)
   CXXFLAGS += -std=c++11
   else
@@ -352,6 +358,7 @@
 
   OPENSSL_ALPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
   OPENSSL_NPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-npn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
+  BORINGSSL_COMPILE_CHECK_CMD = $(CC) $(CPPFLAGS) ${defaults.boringssl.CPPFLAGS} $(CFLAGS) ${defaults.boringssl.CFLAGS} -o $(TMPOUT) test/build/boringssl.c $(LDFLAGS)
   ZLIB_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS)
   PROTOBUF_CHECK_CMD = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS)
 
@@ -436,10 +443,13 @@
   # Note that for testing purposes, one can do:
   #   make HAS_EMBEDDED_OPENSSL_ALPN=false
   # to emulate the fact we do not have OpenSSL in the third_party folder.
-  ifeq ($(wildcard third_party/boringssl/include/openssl/ssl.h),)
+  ifneq ($(wildcard third_party/${openssl_fallback.extraction_dir}/libssl.a),)
+  HAS_EMBEDDED_OPENSSL_ALPN = third_party/${openssl_fallback.extraction_dir}
+  else ifeq ($(wildcard third_party/boringssl/include/openssl/ssl.h),)
   HAS_EMBEDDED_OPENSSL_ALPN = false
   else
-  HAS_EMBEDDED_OPENSSL_ALPN = true
+  CAN_COMPILE_EMBEDDED_OPENSSL ?= $(shell $(BORINGSSL_COMPILE_CHECK_CMD) 2> /dev/null && echo true || echo false)
+  HAS_EMBEDDED_OPENSSL_ALPN = $(CAN_COMPILE_EMBEDDED_OPENSSL)
   endif
 
   ifeq ($(wildcard third_party/zlib/zlib.h),)
@@ -498,8 +508,8 @@
   EMBED_OPENSSL ?= false
   NO_SECURE ?= false
   else # HAS_SYSTEM_OPENSSL_ALPN=false
-  ifeq ($(HAS_EMBEDDED_OPENSSL_ALPN),true)
-  EMBED_OPENSSL ?= true
+  ifneq ($(HAS_EMBEDDED_OPENSSL_ALPN),false)
+  EMBED_OPENSSL ?= $(HAS_EMBEDDED_OPENSSL_ALPN)
   NO_SECURE ?= false
   else # HAS_EMBEDDED_OPENSSL_ALPN=false
   ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
@@ -520,6 +530,12 @@
   OPENSSL_MERGE_OBJS += $(LIBBORINGSSL_OBJS)
   # need to prefix these to ensure overriding system libraries
   CPPFLAGS := -Ithird_party/boringssl/include $(CPPFLAGS)
+  else ifneq ($(EMBED_OPENSSL),false)
+  OPENSSL_DEP += $(EMBED_OPENSSL)/libssl.a $(EMBED_OPENSSL)/libcrypto.a
+  OPENSSL_MERGE_LIBS += $(EMBED_OPENSSL)/libssl.a $(EMBED_OPENSSL)/libcrypto.a
+  OPENSSL_MERGE_OBJS += $(wildcard $(EMBED_OPENSSL)/grpc_obj/*.o)
+  # need to prefix these to ensure overriding system libraries
+  CPPFLAGS := -I$(EMBED_OPENSSL)/include $(CPPFLAGS)
   else # EMBED_OPENSSL=false
   ifeq ($(HAS_PKG_CONFIG),true)
   OPENSSL_PKG_CONFIG = true
@@ -706,8 +722,9 @@
   	@echo
   	@echo "DEPENDENCY ERROR"
   	@echo
-  	@echo "The target you are trying to run requires OpenSSL."
-  	@echo "Your system doesn't have it, and neither does the third_party directory."
+  	@echo "The target you are trying to run requires an OpenSSL implementation."
+  	@echo "Your system doesn't have one, and either the third_party directory"
+  	@echo "doesn't have it, or your compiler can't build BoringSSL."
   	@echo
   	@echo "Please consult INSTALL to get more information."
   	@echo
@@ -1846,3 +1863,9 @@
   strip_cxx strip-shared_cxx strip-static_cxx \
   dep_c dep_cxx bins_dep_c bins_dep_cxx \
   clean
+
+  .PHONY: printvars
+  printvars:
+  	@$(foreach V,$(sort $(.VARIABLES)),                 \
+  	  $(if $(filter-out environment% default automatic, \
+  	  $(origin $V)),$(warning $V=$($V) ($(value $V)))))
diff --git a/templates/README.md b/templates/README.md
index 6740972cfb6c40c47639fb12a46298504859c76a..eedc6e9c09fa50725f127a31958fc5d39e4fa392 100644
--- a/templates/README.md
+++ b/templates/README.md
@@ -6,78 +6,92 @@ was going to single handedly cover all of our usage cases.
 
 So instead we decided to work the following way:
 
-* A build.json file at the root is the source of truth for listing all of the
-target and files needed to build grpc and its tests, as well as basic system
-dependencies description.
+* A `build.yaml` file at the root is the source of truth for listing all the
+targets and files needed to build grpc and its tests, as well as a basic system
+for dependency description.
 
 * Each project file (Makefile, Visual Studio project files, Bazel's BUILD) is
-a plain-text template that uses the build.json file to generate the final
-output file.
+a [YAML](http://yaml.org) file used by the `build.yaml` file to generate the
+final output file.
 
 This way we can maintain as many project system as we see fit, without having
 to manually maintain them when we add or remove new code to the repository.
 Only the structure of the project file is relevant to the template. The actual
 list of source code and targets isn't.
 
-We currently have template files for GNU Make, Visual Studio 2010 to 2015,
-and Bazel. In the future, we would like to expand to generating gyp or cmake
-project files (or potentially both), XCode project files, and an Android.mk
-file to be able to compile gRPC using Android's NDK.
+We currently have template files for GNU Make, Visual Studio 2013,
+[Bazel](http://bazel.io) and [gyp](https://gyp.gsrc.io/) (albeit only for
+Node.js). In the future, we
+would like to expand to also generate [cmake](https://cmake.org)
+project files, XCode project files, and an Android.mk file allowing to compile
+gRPC using Android's NDK.
 
 We'll gladly accept contribution that'd create additional project files
 using that system.
 
-# Structure of build.json
+# Structure of `build.yaml`
 
-The build.json file has the following structure:
+The `build.yaml` file has the following structure:
 
 ```
-{
-  "settings": { ... },   # global settings, such as version number
-  "filegroups": [ ... ], # groups of file that is automatically expanded
-  "libs": [ ... ],       # list of libraries to build
-  "targets": [ ... ],    # list of targets to build
-}
+settings:  # global settings, such as version number
+  ...
+filegroups:  # groups of files that are automatically expanded
+  ...
+libs:  # list of libraries to build
+  ...
+target:   # list of targets to build
+  ...
 ```
 
 The `filegroups` are helpful to re-use a subset of files in multiple targets.
 One `filegroups` entry has the following structure:
 
 ```
-{
-  "name": "arbitrary string", # the name of the filegroup
-  "public_headers": [ ... ],  # list of public headers defined in that filegroup
-  "headers": [ ... ],         # list of headers defined in that filegroup
-  "src": [ ... ],             # list of source files defined in that filegroup
-}
+- name: "arbitrary string", # the name of the filegroup
+  public_headers: # list of public headers defined in that filegroup
+  - ...
+  headers: # list of headers defined in that filegroup
+  - ...
+  src: # list of source files defined in that filegroup
+  - ...
 ```
 
-The `libs` array contains the list of all the libraries we describe. Some may be
+The `libs` collection contains the list of all the libraries we describe. Some may be
 helper libraries for the tests. Some may be installable libraries. Some may be
 helper libraries for installable binaries.
 
 The `targets` array contains the list of all the binary targets we describe. Some may
 be installable binaries.
 
-One `libs` or `targets` entry has the following structure:
+One `libs` or `targets` entry has the following structure (see below for
+details):
 
 ```
-{
-  "name": "arbitrary string", # the name of the library
-  "build": "build type",      # in which situation we want that library to be
-                              # built and potentially installed
-  "language": "...",          # the language tag; "c" or "c++"
-  "public_headers": [ ... ],  # list of public headers to install
-  "headers": [ ... ],         # list of headers used by that target
-  "src": [ ... ],             # list of files to compile
-  "secure": "...",            # "yes", "no" or "check"
-  "baselib": boolean,         # this is a low level library that has system
-                              # dependencies
-  "vs_project_guid: "...",    # Visual Studio's unique guid for that project
-  "filegroups": [ ... ],      # list of filegroups to merge to that project
-                              # note that this will be expanded automatically
-  "deps": [ ... ],            # list of libraries this target depends on
-}
+name: "arbitrary string", # the name of the library
+build: "build type",      # in which situation we want that library to be
+                          # built and potentially installed (see below).
+language: "...",          # the language tag; "c" or "c++"
+public_headers:           # list of public headers to install
+headers:                  # list of headers used by that target
+src:                      # list of files to compile
+secure: boolean,          # see below
+baselib: boolean,         # this is a low level library that has system
+                          # dependencies
+vs_project_guid: '{...}', # Visual Studio's unique guid for that project
+filegroups:               # list of filegroups to merge to that project
+                          # note that this will be expanded automatically
+deps:                     # list of libraries this target depends on
+deps_linkage: "..."       # "static"  or "dynamic". Used by the Makefile only to
+                          # determine the way dependencies are linkned. Defaults
+                          # to "dynamic".
+dll: "..."                # see below.
+dll_def: "..."            # Visual Studio's dll definition file.
+vs_props:                 # List of property sheets to attach to that project.
+vs_config_type: "..."     # DynamicLibrary/StaticLibrary. Used only when
+                          # creating a library. Specifies if we're building a
+                          # static library or a dll. Use in conjunction with `dll_def`.
+vs_packages:              # List of nuget packages this project depends on.
 ```
 
 ## The `"build"` tag
@@ -86,8 +100,9 @@ Currently, the "`build`" tag have these meanings:
 
 * `"all"`: library to build on `"make all"`, and install on the system.
 * `"protoc"`: a protoc plugin to build on `"make all"` and install on the system.
-* `"priviate"`: a library to only build for tests.
+* `"private"`: a library to only build for tests.
 * `"test"`: a test binary to run on `"make test"`.
+* `"tool"`: a binary to be built upon `"make tools"`.
 
 All of the targets should always be present in the generated project file, if
 possible and applicable. But the build tag is what should group the targets
@@ -111,6 +126,18 @@ should merge OpenSSL, protobuf or zlib inside that library. That effect depends
 on the `"language"` tag. OpenSSL and zlib are for `"c"` libraries, while
 protobuf is for `"c++"` ones.
 
+## The `"dll"` tag
+
+Used only by Visual Studio's project files. "true" means the project will be
+built with both static and dynamic runtimes. "false" means it'll only be built
+with static runtime. "only" means it'll only be built with the dll runtime.
+
+## The `"dll_def"` tag
+
+Specifies the visual studio's dll definition file. When creating a DLL, you
+sometimes (not always) need a def file (see grpc.def).
+
+
 # The template system
 
 We're currently using the [mako templates](http://www.makotemplates.org/)
diff --git a/templates/package.xml.template b/templates/package.xml.template
index 058f50647152135aa3ab7442462bf71e7f35d742..d309bfddbc3199b9dcedfd14d2c415198bd21098 100644
--- a/templates/package.xml.template
+++ b/templates/package.xml.template
@@ -12,11 +12,11 @@
     <email>grpc-packages@google.com</email>
     <active>yes</active>
    </lead>
-   <date>2016-02-24</date>
+   <date>2016-03-01</date>
    <time>16:06:07</time>
    <version>
-    <release>0.8.0</release>
-    <api>0.8.0</api>
+    <release>0.14.0</release>
+    <api>0.14.0</api>
    </version>
    <stability>
     <release>beta</release>
@@ -24,8 +24,7 @@
    </stability>
    <license>BSD</license>
    <notes>
-  - Simplify gRPC PHP installation #4517
-  - Wrap gRPC core library version 0.13
+  - Increase unit test code coverage #5225
    </notes>
    <contents>
     <dir baseinstalldir="/" name="/">
@@ -154,7 +153,21 @@
      <license>BSD</license>
      <notes>
   - Simplify gRPC PHP installation #4517
-  - Wrap gRPC core library version 0.13
+     </notes>
+    </release>
+    <release>
+     <version>
+      <release>0.14.0</release>
+      <api>0.14.0</api>
+     </version>
+     <stability>
+      <release>beta</release>
+      <api>beta</api>
+     </stability>
+     <date>2016-03-01</date>
+     <license>BSD</license>
+     <notes>
+  - Increase unit test code coverage #5225
      </notes>
     </release>
    </changelog>
diff --git a/templates/src/csharp/build_packages.bat.template b/templates/src/csharp/build_packages.bat.template
index b855126ae60084fdb02d554a3a2b2bbb4e5602c3..32455683be8892dfbe2a4575ff0bac3a472363d5 100644
--- a/templates/src/csharp/build_packages.bat.template
+++ b/templates/src/csharp/build_packages.bat.template
@@ -21,6 +21,14 @@
   xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x86${"\\"}
   xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x64${"\\"}
   
+  @rem Collect protoc artifacts built by the previous build step
+  xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x86${"\\"}
+  xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x64${"\\"}
+  xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x86${"\\"}
+  xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x64${"\\"}
+  xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x86${"\\"}
+  xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x64${"\\"}
+  
   @rem Fetch all dependencies
   %%NUGET% restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error
   %%NUGET% restore Grpc.sln || goto :error
@@ -29,24 +37,19 @@
   
   @call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86
   
-  @rem We won't use the native libraries from this step, but without this Grpc.sln will fail.  
+  @rem We won't use the native libraries from this step, but without this Grpc.sln will fail.
   msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Release /p:PlatformToolset=v120 || goto :error
   
   msbuild Grpc.sln /p:Configuration=ReleaseSigned || goto :error
   
   endlocal
   
-  @rem TODO(jtattermusch): re-enable protoc plugin building
-  @rem @call ..\..\vsprojects\build_plugins.bat || goto :error
-  
   %%NUGET% pack grpc.native.csharp\grpc.native.csharp.nuspec -Version %VERSION% || goto :error
   %%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
   %%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error
   %%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION_WITH_BETA% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
   %%NUGET% pack Grpc.nuspec -Version %VERSION% || goto :error
-  
-  @rem TODO(jtattermusch): re-enable building Grpc.Tools package
-  @rem %NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error
+  %%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error
   
   @rem copy resulting nuget packages to artifacts directory
   xcopy /Y /I *.nupkg ..\..\artifacts${"\\"}
diff --git a/templates/tools/dockerfile/apt_get_basic.include b/templates/tools/dockerfile/apt_get_basic.include
index 9237e7dacef6bf786c53de2650e1a753c11b2584..547ce01a300902e06717f09be302a23e86f82cfd 100644
--- a/templates/tools/dockerfile/apt_get_basic.include
+++ b/templates/tools/dockerfile/apt_get_basic.include
@@ -1,3 +1,4 @@
+<%page args="skip_golang=False"/>\
 # Install Git and basic packages.
 RUN apt-get update && apt-get install -y ${'\\'}
   autoconf ${'\\'}
@@ -9,7 +10,9 @@ RUN apt-get update && apt-get install -y ${'\\'}
   gcc ${'\\'}
   gcc-multilib ${'\\'}
   git ${'\\'}
+% if not skip_golang:
   golang ${'\\'}
+% endif
   gyp ${'\\'}
   lcov ${'\\'}
   libc6 ${'\\'}
diff --git a/templates/tools/dockerfile/run_tests_addons.include b/templates/tools/dockerfile/run_tests_addons.include
index 27ac67f5d8feeec3023090c99d06dd7c5870c5a7..30d22be2980462f8f281f9ce011eae0223da0c28 100644
--- a/templates/tools/dockerfile/run_tests_addons.include
+++ b/templates/tools/dockerfile/run_tests_addons.include
@@ -1,7 +1,10 @@
+<%page args="skip_zookeeper=False"/>\
 <%include file="ccache_setup.include"/>
+% if not skip_zookeeper:
 #======================
 # Zookeeper dependencies
 # TODO(jtattermusch): is zookeeper still needed?
 RUN apt-get install -y libzookeeper-mt-dev
+% endif
 
 RUN mkdir /var/local/jenkins
diff --git a/templates/tools/dockerfile/test/cxx_squeeze_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_squeeze_x64/Dockerfile.template
new file mode 100644
index 0000000000000000000000000000000000000000..49371aaa3bbc6abbff53f510528304e81c2e22e2
--- /dev/null
+++ b/templates/tools/dockerfile/test/cxx_squeeze_x64/Dockerfile.template
@@ -0,0 +1,48 @@
+%YAML 1.2
+--- |
+  # 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.
+
+  FROM debian:squeeze
+
+  <%include file="../../apt_get_basic.include" args="skip_golang=True"/>
+
+  # libgflags-dev is not available on squeezy
+  RUN apt-get update && apt-get -y install libgtest-dev libc++-dev clang && apt-get clean
+
+  RUN apt-get update && apt-get -y install python-pip && apt-get clean
+  RUN pip install argparse
+
+  RUN wget ${openssl_fallback.base_uri + openssl_fallback.tarball}
+
+  ENV POST_GIT_STEP tools/dockerfile/test/cxx_squeeze_x64/post-git-setup.sh
+
+  <%include file="../../run_tests_addons.include" args="skip_zookeeper=True"/>
+  # Define the default command.
+  CMD ["bash"]
diff --git a/templates/tools/dockerfile/test/cxx_squeeze_x64/post-git-setup.sh.template b/templates/tools/dockerfile/test/cxx_squeeze_x64/post-git-setup.sh.template
new file mode 100644
index 0000000000000000000000000000000000000000..b885101748410804cef50dfc6aa7a7d2e5bfff64
--- /dev/null
+++ b/templates/tools/dockerfile/test/cxx_squeeze_x64/post-git-setup.sh.template
@@ -0,0 +1,37 @@
+%YAML 1.2
+--- |
+  #!/bin/bash
+  # 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.
+
+  set -ex
+
+  cd /var/local/git/grpc
+  cp /${openssl_fallback.tarball} third_party
+  ./tools/openssl/use_openssl.sh
diff --git a/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template
new file mode 100644
index 0000000000000000000000000000000000000000..6b302748925f2133c35744194d40478e7029ff15
--- /dev/null
+++ b/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template
@@ -0,0 +1,39 @@
+%YAML 1.2
+--- |
+  # Copyright 2015-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.
+  
+  FROM ubuntu:16.04
+  
+  <%include file="../../apt_get_basic.include"/>
+  <%include file="../../cxx_deps.include"/>
+  <%include file="../../run_tests_addons.include"/>
+  # Define the default command.
+  CMD ["bash"]
+  
\ No newline at end of file
diff --git a/templates/tools/openssl/use_openssl.sh.template b/templates/tools/openssl/use_openssl.sh.template
new file mode 100644
index 0000000000000000000000000000000000000000..5fb377154a1b18fbd14a9090f74e34cb9574dd1c
--- /dev/null
+++ b/templates/tools/openssl/use_openssl.sh.template
@@ -0,0 +1,63 @@
+%YAML 1.2
+--- |
+  #!/bin/bash
+
+  # Copyright 2015-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.
+
+  set -ex
+
+  cd $(dirname $0)/../..
+  set root=`pwd`
+  CC=${"${CC:-cc}"}
+
+  # allow openssl to be pre-downloaded
+  if [ ! -e third_party/${openssl_fallback.tarball} ]
+  then
+    echo "Downloading ${openssl_fallback.base_uri + openssl_fallback.tarball} to third_party/${openssl_fallback.tarball}"
+    wget ${openssl_fallback.base_uri + openssl_fallback.tarball} -O third_party/${openssl_fallback.tarball}
+  fi
+
+  # clean openssl directory
+  rm -rf third_party/${openssl_fallback.extraction_dir}
+
+  # extract archive
+  cd third_party
+  tar xfz ${openssl_fallback.tarball}
+
+  # build openssl
+  cd ${openssl_fallback.extraction_dir}
+  CC="$CC -fPIC -fvisibility=hidden" ./config no-asm
+  make
+
+  # generate the 'grpc_obj' directory needed by the makefile
+  mkdir grpc_obj
+  cd grpc_obj
+  ar x ../libcrypto.a
+  ar x ../libssl.a
diff --git a/templates/tools/run_tests/sources_and_headers.json.template b/templates/tools/run_tests/sources_and_headers.json.template
index 04802772af50d362554c6f1426aed04515506411..18b9bc26547ccf992de4b5a2058bba35a7f1615f 100644
--- a/templates/tools/run_tests/sources_and_headers.json.template
+++ b/templates/tools/run_tests/sources_and_headers.json.template
@@ -3,34 +3,48 @@
   <%!
   import json
   import os
-  
+
   def proto_headers(src):
+    out = []
+    for f in src:
+      name, ext = os.path.splitext(f)
+      if ext == '.proto':
+        out.extend(fmt % name for fmt in ['%s.grpc.pb.h', '%s.pb.h'])
+    return out
+
+  def all_targets(targets, libs):
+    for tgt in targets:
+      yield ('target', tgt)
+    for tgt in libs:
+      yield ('lib', tgt)
+
+  def no_protos_filter(src):
+  	return os.path.splitext(src)[1] != '.proto'
+
+  def no_third_party_filter(src):
+  	return not src.startswith('third_party/')
+
+  def filter_srcs(srcs, filters):
   	out = []
-  	for f in src:
-  		name, ext = os.path.splitext(f)
-  		if ext == '.proto':
-  			out.extend(fmt % name for fmt in ['%s.grpc.pb.h', '%s.pb.h'])
-  	return out
-  
-  def no_protos(src):
-  	out = []
-  	for f in src:
-  		if os.path.splitext(f)[1] != '.proto':
-  			out.append(f)
+  	for s in srcs:
+  		filter_passes = (f(s) for f in filters)
+  		if all(filter_passes):
+  			out.append(s)
   	return out
   %>
-  
+
   ${json.dumps([{"name": tgt.name,
+                 "type": typ,
                  "language": tgt.language,
+                 "third_party": tgt.boringssl or tgt.zlib,
                  "src": sorted(
-                     no_protos(tgt.src) + 
-                     tgt.get('public_headers', []) + 
-                     tgt.get('headers', [])),
+                     filter_srcs(tgt.src, (no_protos_filter, no_third_party_filter)) +
+                     filter_srcs(tgt.get('public_headers', []), (no_protos_filter, no_third_party_filter)) +
+                     filter_srcs(tgt.get('headers', []), (no_third_party_filter,))),
                  "headers": sorted(
-                     tgt.get('public_headers', []) + 
-                     tgt.get('headers', []) + 
+                     tgt.get('public_headers', []) +
+                     tgt.get('headers', []) +
                      proto_headers(tgt.src)),
                  "deps": sorted(tgt.get('deps', []))}
-                for tgt in (targets + libs)
-                if not tgt.boringssl and not tgt.zlib],
+                for typ, tgt in all_targets(targets, libs)],
                sort_keys=True, indent=2)}
diff --git a/templates/tools/run_tests/tests.json.template b/templates/tools/run_tests/tests.json.template
index 9a84783467ac3abe4b70e5ee301e98214234a4ab..5690874415a585fa70fbc557e7fc2e5070082cf2 100644
--- a/templates/tools/run_tests/tests.json.template
+++ b/templates/tools/run_tests/tests.json.template
@@ -3,11 +3,12 @@
   <%!
   import json
   %>
-  
+
   ${json.dumps([{"name": tgt.name,
                  "language": tgt.language,
                  "platforms": tgt.platforms,
                  "ci_platforms": tgt.ci_platforms,
+                 "gtest": tgt.gtest,
                  "exclude_configs": tgt.get("exclude_configs", []),
                  "args": [],
                  "flaky": tgt.flaky,
diff --git a/templates/vsprojects/protoc.props.template b/templates/vsprojects/protoc.props.template
index a869005daec4637d86cd2824d7dcd470e7e8e013..ced6028a4be1338517536ebe2ee56e94db08185a 100644
--- a/templates/vsprojects/protoc.props.template
+++ b/templates/vsprojects/protoc.props.template
@@ -4,6 +4,9 @@
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup />
   <ItemDefinitionGroup>
+    <ClCompile>
+      <DisableSpecificWarnings>4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+    </ClCompile>
     <Link>
       <AdditionalDependencies>libprotoc.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>$(SolutionDir)\..\third_party\protobuf\cmake\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
diff --git a/src/cpp/common/alarm.cc b/test/build/boringssl.c
similarity index 73%
rename from src/cpp/common/alarm.cc
rename to test/build/boringssl.c
index a2896887682aeea4e258ffe5a4dbcfca01b64052..a31d4bf3964df7d86cb73409aa543777712663c6 100644
--- a/src/cpp/common/alarm.cc
+++ b/test/build/boringssl.c
@@ -1,5 +1,6 @@
 /*
- * Copyright 2015-2016, Google Inc.
+ *
+ * Copyright 2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -30,22 +31,21 @@
  *
  */
 
-#include <grpc++/alarm.h>
-#include <grpc++/completion_queue.h>
-#include <grpc++/impl/grpc_library.h>
-#include <grpc/grpc.h>
-
-namespace grpc {
+// Check that boringssl is going to compile
 
-static internal::GrpcLibraryInitializer g_gli_initializer;
-Alarm::Alarm(CompletionQueue* cq, gpr_timespec deadline, void* tag)
-    : tag_(tag),
-      alarm_(grpc_alarm_create(cq->cq(), deadline, static_cast<void*>(&tag_))) {
-  g_gli_initializer.summon();
-}
+#include <stdio.h>
+#include <unistd.h>
 
-Alarm::~Alarm() { grpc_alarm_destroy(alarm_); }
+// boringssl uses anonymous unions
+struct foo {
+  union {
+    int a;
+    int b;
+  };
+};
 
-void Alarm::Cancel() { grpc_alarm_cancel(alarm_); }
-
-}  // namespace grpc
+int main(void) {
+  const char *close = "this should not shadow";
+  printf("%s\n", close);
+  return 0;
+}
diff --git a/test/build/shadow.c b/test/build/shadow.c
new file mode 100644
index 0000000000000000000000000000000000000000..51d4f9e3852bd0ca9ecf72f5d66d2d99c5f51b37
--- /dev/null
+++ b/test/build/shadow.c
@@ -0,0 +1,43 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+// Check that boringssl is going to compile
+
+#include <stdio.h>
+#include <unistd.h>
+
+int main(void) {
+  const char *close = "this should not shadow";
+  printf("%s\n", close);
+  return 0;
+}
diff --git a/test/core/bad_ssl/gen_build_yaml.py b/test/core/bad_ssl/gen_build_yaml.py
index cc097a8fdf61910ed7423d1ff6cc714682221e9c..e2a3febe5d9e801564c54f3436c660d1658087e5 100755
--- a/test/core/bad_ssl/gen_build_yaml.py
+++ b/test/core/bad_ssl/gen_build_yaml.py
@@ -52,8 +52,8 @@ def main():
               'name': 'bad_ssl_test_server',
               'build': 'private',
               'language': 'c',
-              'src': ['test/core/bad_ssl/server.c'],
-              'headers': ['test/core/bad_ssl/server.h'],
+              'src': ['test/core/bad_ssl/server_common.c'],
+              'headers': ['test/core/bad_ssl/server_common.h'],
               'vs_proj_dir': 'test',
               'platforms': ['linux', 'posix', 'mac'],
               'deps': [
diff --git a/test/core/bad_ssl/server.c b/test/core/bad_ssl/server_common.c
similarity index 98%
rename from test/core/bad_ssl/server.c
rename to test/core/bad_ssl/server_common.c
index 6113d364c9d0ad53118b644c40afc7c4858c82b9..cde844a55296b5de724a9d4a115443dbfc7a31e9 100644
--- a/test/core/bad_ssl/server.c
+++ b/test/core/bad_ssl/server_common.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,7 +35,7 @@
 #include <grpc/support/log.h>
 #include <signal.h>
 
-#include "test/core/bad_ssl/server.h"
+#include "test/core/bad_ssl/server_common.h"
 #include "test/core/util/test_config.h"
 
 /* Common server implementation details for all servers in servers/.
diff --git a/test/core/bad_ssl/server.h b/test/core/bad_ssl/server_common.h
similarity index 98%
rename from test/core/bad_ssl/server.h
rename to test/core/bad_ssl/server_common.h
index 8ec775550307ba90702d40bf4256322c969201d1..2566c2590594db86f5aaf875268f7b775c475115 100644
--- a/test/core/bad_ssl/server.h
+++ b/test/core/bad_ssl/server_common.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/core/bad_ssl/servers/alpn.c b/test/core/bad_ssl/servers/alpn.c
index 7d70690e52db39cd3dbdc91ab83ca643b94556e1..c8cc83b134e47acc688290056d896cdd9b8017cf 100644
--- a/test/core/bad_ssl/servers/alpn.c
+++ b/test/core/bad_ssl/servers/alpn.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@
 #include <grpc/support/useful.h>
 
 #include "src/core/transport/chttp2/alpn.h"
-#include "test/core/bad_ssl/server.h"
+#include "test/core/bad_ssl/server_common.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 
 /* This test starts a server that is configured to advertise (via alpn and npn)
diff --git a/test/core/bad_ssl/servers/cert.c b/test/core/bad_ssl/servers/cert.c
index d67a6ca1d4af37da47e5a34d7572ff01dbc46a3c..4edef50b67a90bbc67d23a43c78f55081c4eb168 100644
--- a/test/core/bad_ssl/servers/cert.c
+++ b/test/core/bad_ssl/servers/cert.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,9 +38,9 @@
 #include <grpc/support/log.h>
 #include <grpc/support/useful.h>
 
-#include "src/core/support/file.h"
+#include "src/core/support/load_file.h"
 
-#include "test/core/bad_ssl/server.h"
+#include "test/core/bad_ssl/server_common.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 
 /* This server will present an untrusted cert to the connecting client,
diff --git a/test/core/census/context_test.c b/test/core/census/context_test.c
index 63e7103ddceb12ca9a4954b390a60c5e8e32add8..ad4c337465cdfbe8973daee89dfbc8efda8face5 100644
--- a/test/core/census/context_test.c
+++ b/test/core/census/context_test.c
@@ -42,60 +42,48 @@
 #include <string.h>
 #include "test/core/util/test_config.h"
 
-static uint8_t one_byte_val = 7;
-static uint32_t four_byte_val = 0x12345678;
-static uint64_t eight_byte_val = 0x1234567890abcdef;
-
-// A set of tags Used to create a basic context for testing. Each tag has a
-// unique set of flags. Note that replace_add_delete_test() relies on specific
-// offsets into this array - if you add or delete entries, you will also need
-// to change the test.
+// A set of tags Used to create a basic context for testing. Note that
+// replace_add_delete_test() relies on specific offsets into this array - if
+// you add or delete entries, you will also need to change the test.
 #define BASIC_TAG_COUNT 8
 static census_tag basic_tags[BASIC_TAG_COUNT] = {
-    /* 0 */ {"key0", "printable", 10, 0},
-    /* 1 */ {"k1", "a", 2, CENSUS_TAG_PROPAGATE},
-    /* 2 */ {"k2", "longer printable string", 24, CENSUS_TAG_STATS},
-    /* 3 */ {"key_three", (char *)&one_byte_val, 1, CENSUS_TAG_BINARY},
-    /* 4 */ {"really_long_key_4", "random", 7,
+    /* 0 */ {"key0", "tag value", 0},
+    /* 1 */ {"k1", "a", CENSUS_TAG_PROPAGATE},
+    /* 2 */ {"k2", "a longer tag value supercalifragilisticexpialiadocious",
+             CENSUS_TAG_STATS},
+    /* 3 */ {"key_three", "", 0},
+    /* 4 */ {"a_really_really_really_really_long_key_4", "random",
              CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS},
-    /* 5 */ {"k5", (char *)&four_byte_val, 4,
-             CENSUS_TAG_PROPAGATE | CENSUS_TAG_BINARY},
-    /* 6 */ {"k6", (char *)&eight_byte_val, 8,
-             CENSUS_TAG_STATS | CENSUS_TAG_BINARY},
-    /* 7 */ {"k7", (char *)&four_byte_val, 4,
-             CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS | CENSUS_TAG_BINARY}};
+    /* 5 */ {"k5", "v5", CENSUS_TAG_PROPAGATE},
+    /* 6 */ {"k6", "v6", CENSUS_TAG_STATS},
+    /* 7 */ {"k7", "v7", CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS}};
 
 // Set of tags used to modify the basic context. Note that
 // replace_add_delete_test() relies on specific offsets into this array - if
 // you add or delete entries, you will also need to change the test. Other
 // tests that rely on specific instances have XXX_XXX_OFFSET definitions (also
 // change the defines below if you add/delete entires).
-#define MODIFY_TAG_COUNT 11
+#define MODIFY_TAG_COUNT 10
 static census_tag modify_tags[MODIFY_TAG_COUNT] = {
 #define REPLACE_VALUE_OFFSET 0
-    /* 0 */ {"key0", "replace printable", 18, 0},  // replaces tag value only
+    /* 0 */ {"key0", "replace key0", 0},  // replaces tag value only
 #define ADD_TAG_OFFSET 1
-    /* 1 */ {"new_key", "xyzzy", 6, CENSUS_TAG_STATS},  // new tag
+    /* 1 */ {"new_key", "xyzzy", CENSUS_TAG_STATS},  // new tag
 #define DELETE_TAG_OFFSET 2
-    /* 2 */ {"k5", NULL, 5,
-             0},  // should delete tag, despite bogus value length
-    /* 3 */ {"k6", "foo", 0, 0},  // should delete tag, despite bogus value
-    /* 4 */ {"k6", "foo", 0, 0},  // try deleting already-deleted tag
-    /* 5 */ {"non-existent", NULL, 0, 0},  // another non-existent tag
-#define REPLACE_FLAG_OFFSET 6
-    /* 6 */ {"k1", "a", 2, 0},                   // change flags only
-    /* 7 */ {"k7", "bar", 4, CENSUS_TAG_STATS},  // change flags and value
-    /* 8 */ {"k2", (char *)&eight_byte_val, 8,
-             CENSUS_TAG_BINARY | CENSUS_TAG_PROPAGATE},  // more flags change
-                                                         // non-binary -> binary
-    /* 9 */ {"k6", "bar", 4, 0},  // add back tag, with different value
-    /* 10 */ {"foo", "bar", 4, CENSUS_TAG_PROPAGATE},  // another new tag
+    /* 2 */ {"k5", NULL, 0},            // should delete tag
+    /* 3 */ {"k5", NULL, 0},            // try deleting already-deleted tag
+    /* 4 */ {"non-existent", NULL, 0},  // delete non-existent tag
+#define REPLACE_FLAG_OFFSET 5
+    /* 5 */ {"k1", "a", 0},                    // change flags only
+    /* 6 */ {"k7", "bar", CENSUS_TAG_STATS},   // change flags and value
+    /* 7 */ {"k2", "", CENSUS_TAG_PROPAGATE},  // more value and flags change
+    /* 8 */ {"k5", "bar", 0},  // add back tag, with different value
+    /* 9 */ {"foo", "bar", CENSUS_TAG_PROPAGATE},  // another new tag
 };
 
 // Utility function to compare tags. Returns true if all fields match.
 static bool compare_tag(const census_tag *t1, const census_tag *t2) {
-  return (strcmp(t1->key, t2->key) == 0 && t1->value_len == t2->value_len &&
-          memcmp(t1->value, t2->value, t1->value_len) == 0 &&
+  return (strcmp(t1->key, t2->key) == 0 && strcmp(t1->value, t2->value) == 0 &&
           t1->flags == t2->flags);
 }
 
@@ -111,7 +99,7 @@ static void empty_test(void) {
   struct census_context *context = census_context_create(NULL, NULL, 0, NULL);
   GPR_ASSERT(context != NULL);
   const census_context_status *status = census_context_get_status(context);
-  census_context_status expected = {0, 0, 0, 0, 0, 0, 0, 0};
+  census_context_status expected = {0, 0, 0, 0, 0, 0, 0};
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   census_context_destroy(context);
 }
@@ -121,7 +109,7 @@ static void basic_test(void) {
   const census_context_status *status;
   struct census_context *context =
       census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, &status);
-  census_context_status expected = {2, 2, 4, 0, 8, 0, 0, 0};
+  census_context_status expected = {4, 4, 0, 8, 0, 0, 0};
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   census_context_iterator it;
   census_context_initialize_iterator(context, &it);
@@ -161,15 +149,18 @@ static void invalid_test(void) {
   memset(key, 'k', 299);
   key[299] = 0;
   char value[300];
-  memset(value, 'v', 300);
-  census_tag tag = {key, value, 3, CENSUS_TAG_BINARY};
+  memset(value, 'v', 299);
+  value[299] = 0;
+  census_tag tag = {key, value, 0};
   // long keys, short value. Key lengths (including terminator) should be
   // <= 255 (CENSUS_MAX_TAG_KV_LEN)
+  value[3] = 0;
+  GPR_ASSERT(strlen(value) == 3);
   GPR_ASSERT(strlen(key) == 299);
   const census_context_status *status;
   struct census_context *context =
       census_context_create(NULL, &tag, 1, &status);
-  census_context_status expected = {0, 0, 0, 0, 0, 0, 1, 0};
+  census_context_status expected = {0, 0, 0, 0, 0, 1, 0};
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   census_context_destroy(context);
   key[CENSUS_MAX_TAG_KV_LEN] = 0;
@@ -180,24 +171,44 @@ static void invalid_test(void) {
   key[CENSUS_MAX_TAG_KV_LEN - 1] = 0;
   GPR_ASSERT(strlen(key) == CENSUS_MAX_TAG_KV_LEN - 1);
   context = census_context_create(NULL, &tag, 1, &status);
-  census_context_status expected2 = {0, 0, 1, 0, 1, 0, 0, 0};
+  census_context_status expected2 = {0, 1, 0, 1, 0, 0, 0};
   GPR_ASSERT(memcmp(status, &expected2, sizeof(expected2)) == 0);
   census_context_destroy(context);
   // now try with long values
-  tag.value_len = 300;
+  value[3] = 'v';
+  GPR_ASSERT(strlen(value) == 299);
   context = census_context_create(NULL, &tag, 1, &status);
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   census_context_destroy(context);
-  tag.value_len = CENSUS_MAX_TAG_KV_LEN + 1;
+  value[CENSUS_MAX_TAG_KV_LEN] = 0;
+  GPR_ASSERT(strlen(value) == CENSUS_MAX_TAG_KV_LEN);
   context = census_context_create(NULL, &tag, 1, &status);
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   census_context_destroy(context);
-  tag.value_len = CENSUS_MAX_TAG_KV_LEN;
+  value[CENSUS_MAX_TAG_KV_LEN - 1] = 0;
+  GPR_ASSERT(strlen(value) == CENSUS_MAX_TAG_KV_LEN - 1);
   context = census_context_create(NULL, &tag, 1, &status);
   GPR_ASSERT(memcmp(status, &expected2, sizeof(expected2)) == 0);
   census_context_destroy(context);
   // 0 length key.
   key[0] = 0;
+  GPR_ASSERT(strlen(key) == 0);
+  context = census_context_create(NULL, &tag, 1, &status);
+  GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
+  census_context_destroy(context);
+  // invalid key character
+  key[0] = 31;  // 32 (' ') is the first valid character value
+  key[1] = 0;
+  GPR_ASSERT(strlen(key) == 1);
+  context = census_context_create(NULL, &tag, 1, &status);
+  GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
+  census_context_destroy(context);
+  // invalid value character
+  key[0] = ' ';
+  value[5] = 127;  // 127 (DEL) is ('~' + 1)
+  value[8] = 0;
+  GPR_ASSERT(strlen(key) == 1);
+  GPR_ASSERT(strlen(value) == 8);
   context = census_context_create(NULL, &tag, 1, &status);
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   census_context_destroy(context);
@@ -210,7 +221,7 @@ static void copy_test(void) {
   const census_context_status *status;
   struct census_context *context2 =
       census_context_create(context, NULL, 0, &status);
-  census_context_status expected = {2, 2, 4, 0, 0, 0, 0, 0};
+  census_context_status expected = {4, 4, 0, 0, 0, 0, 0};
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   for (int i = 0; i < BASIC_TAG_COUNT; i++) {
     census_tag tag;
@@ -228,7 +239,7 @@ static void replace_value_test(void) {
   const census_context_status *status;
   struct census_context *context2 = census_context_create(
       context, modify_tags + REPLACE_VALUE_OFFSET, 1, &status);
-  census_context_status expected = {2, 2, 4, 0, 0, 1, 0, 0};
+  census_context_status expected = {4, 4, 0, 0, 1, 0, 0};
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   census_tag tag;
   GPR_ASSERT(census_context_get_tag(
@@ -245,7 +256,7 @@ static void replace_flags_test(void) {
   const census_context_status *status;
   struct census_context *context2 = census_context_create(
       context, modify_tags + REPLACE_FLAG_OFFSET, 1, &status);
-  census_context_status expected = {1, 2, 5, 0, 0, 1, 0, 0};
+  census_context_status expected = {3, 5, 0, 0, 1, 0, 0};
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   census_tag tag;
   GPR_ASSERT(census_context_get_tag(
@@ -262,7 +273,7 @@ static void delete_tag_test(void) {
   const census_context_status *status;
   struct census_context *context2 = census_context_create(
       context, modify_tags + DELETE_TAG_OFFSET, 1, &status);
-  census_context_status expected = {2, 1, 4, 1, 0, 0, 0, 0};
+  census_context_status expected = {3, 4, 1, 0, 0, 0, 0};
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   census_tag tag;
   GPR_ASSERT(census_context_get_tag(
@@ -278,7 +289,7 @@ static void add_tag_test(void) {
   const census_context_status *status;
   struct census_context *context2 =
       census_context_create(context, modify_tags + ADD_TAG_OFFSET, 1, &status);
-  census_context_status expected = {2, 2, 5, 0, 1, 0, 0, 0};
+  census_context_status expected = {4, 5, 0, 1, 0, 0, 0};
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   census_tag tag;
   GPR_ASSERT(census_context_get_tag(context2, modify_tags[ADD_TAG_OFFSET].key,
@@ -295,24 +306,24 @@ static void replace_add_delete_test(void) {
   const census_context_status *status;
   struct census_context *context2 =
       census_context_create(context, modify_tags, MODIFY_TAG_COUNT, &status);
-  census_context_status expected = {2, 1, 6, 2, 3, 4, 0, 2};
+  census_context_status expected = {3, 7, 1, 3, 4, 0, 0};
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   // validate context contents. Use specific indices into the two arrays
   // holding tag values.
   GPR_ASSERT(validate_tag(context2, &basic_tags[3]));
   GPR_ASSERT(validate_tag(context2, &basic_tags[4]));
+  GPR_ASSERT(validate_tag(context2, &basic_tags[6]));
   GPR_ASSERT(validate_tag(context2, &modify_tags[0]));
   GPR_ASSERT(validate_tag(context2, &modify_tags[1]));
+  GPR_ASSERT(validate_tag(context2, &modify_tags[5]));
   GPR_ASSERT(validate_tag(context2, &modify_tags[6]));
   GPR_ASSERT(validate_tag(context2, &modify_tags[7]));
   GPR_ASSERT(validate_tag(context2, &modify_tags[8]));
   GPR_ASSERT(validate_tag(context2, &modify_tags[9]));
-  GPR_ASSERT(validate_tag(context2, &modify_tags[10]));
   GPR_ASSERT(!validate_tag(context2, &basic_tags[0]));
   GPR_ASSERT(!validate_tag(context2, &basic_tags[1]));
   GPR_ASSERT(!validate_tag(context2, &basic_tags[2]));
   GPR_ASSERT(!validate_tag(context2, &basic_tags[5]));
-  GPR_ASSERT(!validate_tag(context2, &basic_tags[6]));
   GPR_ASSERT(!validate_tag(context2, &basic_tags[7]));
   census_context_destroy(context);
   census_context_destroy(context2);
@@ -325,21 +336,15 @@ static void encode_decode_test(void) {
   char buffer[BUF_SIZE];
   struct census_context *context =
       census_context_create(NULL, basic_tags, BASIC_TAG_COUNT, NULL);
-  size_t print_bsize;
-  size_t bin_bsize;
   // Test with too small a buffer
-  GPR_ASSERT(census_context_encode(context, buffer, 2, &print_bsize,
-                                   &bin_bsize) == NULL);
-  char *b_buffer = census_context_encode(context, buffer, BUF_SIZE,
-                                         &print_bsize, &bin_bsize);
-  GPR_ASSERT(b_buffer != NULL && print_bsize > 0 && bin_bsize > 0 &&
-             print_bsize + bin_bsize <= BUF_SIZE &&
-             b_buffer == buffer + print_bsize);
-  census_context *context2 =
-      census_context_decode(buffer, print_bsize, b_buffer, bin_bsize);
+  GPR_ASSERT(census_context_encode(context, buffer, 2) == 0);
+  // Test with sufficient buffer
+  size_t buf_used = census_context_encode(context, buffer, BUF_SIZE);
+  GPR_ASSERT(buf_used != 0);
+  census_context *context2 = census_context_decode(buffer, buf_used);
   GPR_ASSERT(context2 != NULL);
   const census_context_status *status = census_context_get_status(context2);
-  census_context_status expected = {2, 2, 0, 0, 0, 0, 0, 0};
+  census_context_status expected = {4, 0, 0, 0, 0, 0, 0};
   GPR_ASSERT(memcmp(status, &expected, sizeof(expected)) == 0);
   for (int i = 0; i < BASIC_TAG_COUNT; i++) {
     census_tag tag;
diff --git a/test/core/client_config/set_initial_connect_string_test.c b/test/core/client_config/set_initial_connect_string_test.c
index bcd1f261235eae70012f85ea206731a9e1f3befd..3cf267fb3bd4774631dc40182e51f87f340414d7 100644
--- a/test/core/client_config/set_initial_connect_string_test.c
+++ b/test/core/client_config/set_initial_connect_string_test.c
@@ -85,7 +85,7 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
   gpr_slice_buffer_init(&state.incoming_buffer);
   gpr_slice_buffer_init(&state.temp_incoming_buffer);
   state.tcp = tcp;
-  grpc_endpoint_add_to_pollset(exec_ctx, tcp, &server->pollset);
+  grpc_endpoint_add_to_pollset(exec_ctx, tcp, server->pollset);
   grpc_endpoint_read(exec_ctx, tcp, &state.temp_incoming_buffer, &on_read);
 }
 
diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c
index 9ff46d62e49e03b46e7242c9d04327f37dd391ee..17dc190d14fac732c7c4afcf148200a2960476c8 100644
--- a/test/core/end2end/end2end_nosec_tests.c
+++ b/test/core/end2end/end2end_nosec_tests.c
@@ -46,9 +46,8 @@ extern void cancel_after_invoke(grpc_end2end_test_config config);
 extern void cancel_before_invoke(grpc_end2end_test_config config);
 extern void cancel_in_a_vacuum(grpc_end2end_test_config config);
 extern void cancel_with_status(grpc_end2end_test_config config);
-extern void channel_connectivity(grpc_end2end_test_config config);
-extern void channel_ping(grpc_end2end_test_config config);
 extern void compressed_payload(grpc_end2end_test_config config);
+extern void connectivity(grpc_end2end_test_config config);
 extern void default_host(grpc_end2end_test_config config);
 extern void disappearing_server(grpc_end2end_test_config config);
 extern void empty_batch(grpc_end2end_test_config config);
@@ -59,10 +58,10 @@ extern void invoke_large_request(grpc_end2end_test_config config);
 extern void large_metadata(grpc_end2end_test_config config);
 extern void max_concurrent_streams(grpc_end2end_test_config config);
 extern void max_message_length(grpc_end2end_test_config config);
-extern void metadata(grpc_end2end_test_config config);
 extern void negative_deadline(grpc_end2end_test_config config);
 extern void no_op(grpc_end2end_test_config config);
 extern void payload(grpc_end2end_test_config config);
+extern void ping(grpc_end2end_test_config config);
 extern void ping_pong_streaming(grpc_end2end_test_config config);
 extern void registered_call(grpc_end2end_test_config config);
 extern void request_with_flags(grpc_end2end_test_config config);
@@ -71,6 +70,7 @@ extern void server_finishes_request(grpc_end2end_test_config config);
 extern void shutdown_finishes_calls(grpc_end2end_test_config config);
 extern void shutdown_finishes_tags(grpc_end2end_test_config config);
 extern void simple_delayed_request(grpc_end2end_test_config config);
+extern void simple_metadata(grpc_end2end_test_config config);
 extern void simple_request(grpc_end2end_test_config config);
 extern void trailing_metadata(grpc_end2end_test_config config);
 
@@ -87,9 +87,8 @@ void grpc_end2end_tests(int argc, char **argv,
     cancel_before_invoke(config);
     cancel_in_a_vacuum(config);
     cancel_with_status(config);
-    channel_connectivity(config);
-    channel_ping(config);
     compressed_payload(config);
+    connectivity(config);
     default_host(config);
     disappearing_server(config);
     empty_batch(config);
@@ -100,10 +99,10 @@ void grpc_end2end_tests(int argc, char **argv,
     large_metadata(config);
     max_concurrent_streams(config);
     max_message_length(config);
-    metadata(config);
     negative_deadline(config);
     no_op(config);
     payload(config);
+    ping(config);
     ping_pong_streaming(config);
     registered_call(config);
     request_with_flags(config);
@@ -112,6 +111,7 @@ void grpc_end2end_tests(int argc, char **argv,
     shutdown_finishes_calls(config);
     shutdown_finishes_tags(config);
     simple_delayed_request(config);
+    simple_metadata(config);
     simple_request(config);
     trailing_metadata(config);
     return;
@@ -150,18 +150,14 @@ void grpc_end2end_tests(int argc, char **argv,
       cancel_with_status(config);
       continue;
     }
-    if (0 == strcmp("channel_connectivity", argv[i])) {
-      channel_connectivity(config);
-      continue;
-    }
-    if (0 == strcmp("channel_ping", argv[i])) {
-      channel_ping(config);
-      continue;
-    }
     if (0 == strcmp("compressed_payload", argv[i])) {
       compressed_payload(config);
       continue;
     }
+    if (0 == strcmp("connectivity", argv[i])) {
+      connectivity(config);
+      continue;
+    }
     if (0 == strcmp("default_host", argv[i])) {
       default_host(config);
       continue;
@@ -202,10 +198,6 @@ void grpc_end2end_tests(int argc, char **argv,
       max_message_length(config);
       continue;
     }
-    if (0 == strcmp("metadata", argv[i])) {
-      metadata(config);
-      continue;
-    }
     if (0 == strcmp("negative_deadline", argv[i])) {
       negative_deadline(config);
       continue;
@@ -218,6 +210,10 @@ void grpc_end2end_tests(int argc, char **argv,
       payload(config);
       continue;
     }
+    if (0 == strcmp("ping", argv[i])) {
+      ping(config);
+      continue;
+    }
     if (0 == strcmp("ping_pong_streaming", argv[i])) {
       ping_pong_streaming(config);
       continue;
@@ -250,6 +246,10 @@ void grpc_end2end_tests(int argc, char **argv,
       simple_delayed_request(config);
       continue;
     }
+    if (0 == strcmp("simple_metadata", argv[i])) {
+      simple_metadata(config);
+      continue;
+    }
     if (0 == strcmp("simple_request", argv[i])) {
       simple_request(config);
       continue;
diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c
index 397ff446a9cff0f52d607a079bf59e3e1826808c..6f2f5aff78c34351c5bff6dcbd274de388bb5a7a 100644
--- a/test/core/end2end/end2end_tests.c
+++ b/test/core/end2end/end2end_tests.c
@@ -47,9 +47,8 @@ extern void cancel_after_invoke(grpc_end2end_test_config config);
 extern void cancel_before_invoke(grpc_end2end_test_config config);
 extern void cancel_in_a_vacuum(grpc_end2end_test_config config);
 extern void cancel_with_status(grpc_end2end_test_config config);
-extern void channel_connectivity(grpc_end2end_test_config config);
-extern void channel_ping(grpc_end2end_test_config config);
 extern void compressed_payload(grpc_end2end_test_config config);
+extern void connectivity(grpc_end2end_test_config config);
 extern void default_host(grpc_end2end_test_config config);
 extern void disappearing_server(grpc_end2end_test_config config);
 extern void empty_batch(grpc_end2end_test_config config);
@@ -60,10 +59,10 @@ extern void invoke_large_request(grpc_end2end_test_config config);
 extern void large_metadata(grpc_end2end_test_config config);
 extern void max_concurrent_streams(grpc_end2end_test_config config);
 extern void max_message_length(grpc_end2end_test_config config);
-extern void metadata(grpc_end2end_test_config config);
 extern void negative_deadline(grpc_end2end_test_config config);
 extern void no_op(grpc_end2end_test_config config);
 extern void payload(grpc_end2end_test_config config);
+extern void ping(grpc_end2end_test_config config);
 extern void ping_pong_streaming(grpc_end2end_test_config config);
 extern void registered_call(grpc_end2end_test_config config);
 extern void request_with_flags(grpc_end2end_test_config config);
@@ -72,6 +71,7 @@ extern void server_finishes_request(grpc_end2end_test_config config);
 extern void shutdown_finishes_calls(grpc_end2end_test_config config);
 extern void shutdown_finishes_tags(grpc_end2end_test_config config);
 extern void simple_delayed_request(grpc_end2end_test_config config);
+extern void simple_metadata(grpc_end2end_test_config config);
 extern void simple_request(grpc_end2end_test_config config);
 extern void trailing_metadata(grpc_end2end_test_config config);
 
@@ -89,9 +89,8 @@ void grpc_end2end_tests(int argc, char **argv,
     cancel_before_invoke(config);
     cancel_in_a_vacuum(config);
     cancel_with_status(config);
-    channel_connectivity(config);
-    channel_ping(config);
     compressed_payload(config);
+    connectivity(config);
     default_host(config);
     disappearing_server(config);
     empty_batch(config);
@@ -102,10 +101,10 @@ void grpc_end2end_tests(int argc, char **argv,
     large_metadata(config);
     max_concurrent_streams(config);
     max_message_length(config);
-    metadata(config);
     negative_deadline(config);
     no_op(config);
     payload(config);
+    ping(config);
     ping_pong_streaming(config);
     registered_call(config);
     request_with_flags(config);
@@ -114,6 +113,7 @@ void grpc_end2end_tests(int argc, char **argv,
     shutdown_finishes_calls(config);
     shutdown_finishes_tags(config);
     simple_delayed_request(config);
+    simple_metadata(config);
     simple_request(config);
     trailing_metadata(config);
     return;
@@ -156,18 +156,14 @@ void grpc_end2end_tests(int argc, char **argv,
       cancel_with_status(config);
       continue;
     }
-    if (0 == strcmp("channel_connectivity", argv[i])) {
-      channel_connectivity(config);
-      continue;
-    }
-    if (0 == strcmp("channel_ping", argv[i])) {
-      channel_ping(config);
-      continue;
-    }
     if (0 == strcmp("compressed_payload", argv[i])) {
       compressed_payload(config);
       continue;
     }
+    if (0 == strcmp("connectivity", argv[i])) {
+      connectivity(config);
+      continue;
+    }
     if (0 == strcmp("default_host", argv[i])) {
       default_host(config);
       continue;
@@ -208,10 +204,6 @@ void grpc_end2end_tests(int argc, char **argv,
       max_message_length(config);
       continue;
     }
-    if (0 == strcmp("metadata", argv[i])) {
-      metadata(config);
-      continue;
-    }
     if (0 == strcmp("negative_deadline", argv[i])) {
       negative_deadline(config);
       continue;
@@ -224,6 +216,10 @@ void grpc_end2end_tests(int argc, char **argv,
       payload(config);
       continue;
     }
+    if (0 == strcmp("ping", argv[i])) {
+      ping(config);
+      continue;
+    }
     if (0 == strcmp("ping_pong_streaming", argv[i])) {
       ping_pong_streaming(config);
       continue;
@@ -256,6 +252,10 @@ void grpc_end2end_tests(int argc, char **argv,
       simple_delayed_request(config);
       continue;
     }
+    if (0 == strcmp("simple_metadata", argv[i])) {
+      simple_metadata(config);
+      continue;
+    }
     if (0 == strcmp("simple_request", argv[i])) {
       simple_request(config);
       continue;
diff --git a/test/core/end2end/fixtures/h2_full+poll+pipe.c b/test/core/end2end/fixtures/h2_full+poll+pipe.c
index d475a7bb552e89ca35f37e123f4fe14880b55b8c..682598fbe2dbe7973a8e5c17bfa31126a42ba9b7 100644
--- a/test/core/end2end/fixtures/h2_full+poll+pipe.c
+++ b/test/core/end2end/fixtures/h2_full+poll+pipe.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,21 +35,23 @@
 
 #include <string.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+
+#include "src/core/channel/client_channel.h"
+#include "src/core/channel/connected_channel.h"
+#include "src/core/channel/http_server_filter.h"
+#include "src/core/iomgr/pollset_posix.h"
+#include "src/core/iomgr/wakeup_fd_posix.h"
+#include "src/core/surface/channel.h"
+#include "src/core/surface/server.h"
+#include "src/core/transport/chttp2_transport.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
-#include "src/core/iomgr/wakeup_fd_posix.h"
 
 typedef struct fullstack_fixture_data {
   char *localaddr;
diff --git a/test/core/end2end/fixtures/h2_full+poll.c b/test/core/end2end/fixtures/h2_full+poll.c
index 3f5e6096f6369c41d94e92f7764f1416321c5cc4..5a0b2ef495358095af59d9ed4539a2fd582900e8 100644
--- a/test/core/end2end/fixtures/h2_full+poll.c
+++ b/test/core/end2end/fixtures/h2_full+poll.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,18 +35,20 @@
 
 #include <string.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+
+#include "src/core/channel/client_channel.h"
+#include "src/core/channel/connected_channel.h"
+#include "src/core/channel/http_server_filter.h"
+#include "src/core/iomgr/pollset_posix.h"
+#include "src/core/surface/channel.h"
+#include "src/core/surface/server.h"
+#include "src/core/transport/chttp2_transport.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/end2end/fixtures/h2_ssl+poll.c b/test/core/end2end/fixtures/h2_ssl+poll.c
index 614654ed524e5602a4d07319416c20cc2953c5ce..66268c77d588f9e7be7f36ed24d3e9bb76107c38 100644
--- a/test/core/end2end/fixtures/h2_ssl+poll.c
+++ b/test/core/end2end/fixtures/h2_ssl+poll.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,17 +36,19 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+
 #include "src/core/channel/channel_args.h"
+#include "src/core/iomgr/pollset_posix.h"
 #include "src/core/security/credentials.h"
 #include "src/core/support/env.h"
-#include "src/core/support/file.h"
+#include "src/core/support/tmpfile.h"
 #include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include "test/core/util/test_config.h"
-#include "test/core/util/port.h"
 #include "test/core/end2end/data/ssl_test_data.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
 
 typedef struct fullstack_secure_fixture_data {
   char *localaddr;
diff --git a/test/core/end2end/fixtures/h2_ssl.c b/test/core/end2end/fixtures/h2_ssl.c
index 5c63dfb6aad488b6b7acae97a7e9a1a388abd29a..e21a3477df27eea706795392d79bf3ab170ccfec 100644
--- a/test/core/end2end/fixtures/h2_ssl.c
+++ b/test/core/end2end/fixtures/h2_ssl.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,17 +36,18 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+
 #include "src/core/channel/channel_args.h"
 #include "src/core/security/credentials.h"
 #include "src/core/support/env.h"
-#include "src/core/support/file.h"
+#include "src/core/support/tmpfile.h"
 #include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include "test/core/util/test_config.h"
-#include "test/core/util/port.h"
 #include "test/core/end2end/data/ssl_test_data.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
 
 typedef struct fullstack_secure_fixture_data {
   char *localaddr;
diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.c b/test/core/end2end/fixtures/h2_ssl_proxy.c
index a93bd83a1f1b602b5e1907c26337dec7241a1bf5..6340d3f4033ebeaa99378850ca9ba9216b388374 100644
--- a/test/core/end2end/fixtures/h2_ssl_proxy.c
+++ b/test/core/end2end/fixtures/h2_ssl_proxy.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,18 +36,19 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+
 #include "src/core/channel/channel_args.h"
 #include "src/core/security/credentials.h"
 #include "src/core/support/env.h"
-#include "src/core/support/file.h"
+#include "src/core/support/tmpfile.h"
 #include "src/core/support/string.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
 #include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/end2end/fixtures/proxy.h"
-#include "test/core/util/test_config.h"
 #include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
 
 typedef struct fullstack_secure_fixture_data {
   grpc_end2end_proxy *proxy;
diff --git a/test/core/end2end/fixtures/h2_uchannel.c b/test/core/end2end/fixtures/h2_uchannel.c
index dbdd3524ed0d7bf814d8410bd5dd65cef2509c26..87bbd64d09a937b66ab8637647e4b1445a2f16a8 100644
--- a/test/core/end2end/fixtures/h2_uchannel.c
+++ b/test/core/end2end/fixtures/h2_uchannel.c
@@ -35,6 +35,13 @@
 
 #include <string.h>
 
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/useful.h>
 #include "src/core/channel/channel_args.h"
 #include "src/core/channel/client_channel.h"
 #include "src/core/channel/client_uchannel.h"
@@ -46,13 +53,6 @@
 #include "src/core/surface/channel.h"
 #include "src/core/surface/server.h"
 #include "src/core/transport/chttp2_transport.h"
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/sync.h>
-#include <grpc/support/thd.h>
-#include <grpc/support/useful.h>
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
@@ -238,12 +238,12 @@ static grpc_end2end_test_fixture chttp2_create_fixture_micro_fullstack(
 }
 
 grpc_connectivity_state g_state = GRPC_CHANNEL_IDLE;
-grpc_pollset_set g_interested_parties;
+grpc_pollset_set *g_interested_parties;
 
 static void state_changed(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
   if (g_state != GRPC_CHANNEL_READY) {
     grpc_subchannel_notify_on_state_change(
-        exec_ctx, arg, &g_interested_parties, &g_state,
+        exec_ctx, arg, g_interested_parties, &g_state,
         grpc_closure_create(state_changed, arg));
   }
 }
@@ -253,30 +253,31 @@ static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
 }
 
 static grpc_connected_subchannel *connect_subchannel(grpc_subchannel *c) {
-  grpc_pollset pollset;
+  gpr_mu *mu;
+  grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_pollset_init(&pollset);
-  grpc_pollset_set_init(&g_interested_parties);
-  grpc_pollset_set_add_pollset(&exec_ctx, &g_interested_parties, &pollset);
-  grpc_subchannel_notify_on_state_change(&exec_ctx, c, &g_interested_parties,
+  grpc_pollset_init(pollset, &mu);
+  g_interested_parties = grpc_pollset_set_create();
+  grpc_pollset_set_add_pollset(&exec_ctx, g_interested_parties, pollset);
+  grpc_subchannel_notify_on_state_change(&exec_ctx, c, g_interested_parties,
                                          &g_state,
                                          grpc_closure_create(state_changed, c));
   grpc_exec_ctx_flush(&exec_ctx);
-  gpr_mu_lock(GRPC_POLLSET_MU(&pollset));
+  gpr_mu_lock(mu);
   while (g_state != GRPC_CHANNEL_READY) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC),
                       GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&pollset));
+    gpr_mu_unlock(mu);
     grpc_exec_ctx_flush(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&pollset));
+    gpr_mu_lock(mu);
   }
-  grpc_pollset_shutdown(&exec_ctx, &pollset,
-                        grpc_closure_create(destroy_pollset, &pollset));
-  grpc_pollset_set_destroy(&g_interested_parties);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&pollset));
+  grpc_pollset_shutdown(&exec_ctx, pollset,
+                        grpc_closure_create(destroy_pollset, pollset));
+  grpc_pollset_set_destroy(g_interested_parties);
+  gpr_mu_unlock(mu);
   grpc_exec_ctx_finish(&exec_ctx);
+  gpr_free(pollset);
   return grpc_subchannel_get_connected_subchannel(c);
 }
 
diff --git a/test/core/end2end/fixtures/h2_uds+poll.c b/test/core/end2end/fixtures/h2_uds+poll.c
index 155017c88755420a9ef5f1e9057769396820cd9d..c3a855ff883de16bd36636a2349efbaccb38f075 100644
--- a/test/core/end2end/fixtures/h2_uds+poll.c
+++ b/test/core/end2end/fixtures/h2_uds+poll.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,13 +37,6 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "src/core/channel/client_channel.h"
-#include "src/core/channel/connected_channel.h"
-#include "src/core/channel/http_server_filter.h"
-#include "src/core/support/string.h"
-#include "src/core/surface/channel.h"
-#include "src/core/surface/server.h"
-#include "src/core/transport/chttp2_transport.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
@@ -51,6 +44,15 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/useful.h>
+
+#include "src/core/channel/client_channel.h"
+#include "src/core/channel/connected_channel.h"
+#include "src/core/channel/http_server_filter.h"
+#include "src/core/iomgr/pollset_posix.h"
+#include "src/core/support/string.h"
+#include "src/core/surface/channel.h"
+#include "src/core/surface/server.h"
+#include "src/core/transport/chttp2_transport.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index f24dbe72cf55ee3a0bee9e68bfbcbd91280e9365..4dfafcea2431121cc26d0f0423443bab008c5b93 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -94,9 +94,8 @@ END2END_TESTS = {
     'cancel_before_invoke': default_test_options._replace(cpu_cost=LOWCPU),
     'cancel_in_a_vacuum': default_test_options._replace(cpu_cost=LOWCPU),
     'cancel_with_status': default_test_options._replace(cpu_cost=LOWCPU),
-    'channel_connectivity': connectivity_test_options._replace(proxyable=False, cpu_cost=LOWCPU),
-    'channel_ping': connectivity_test_options._replace(proxyable=False),
     'compressed_payload': default_test_options._replace(proxyable=False, cpu_cost=LOWCPU),
+    'connectivity': connectivity_test_options._replace(proxyable=False, cpu_cost=LOWCPU),
     'default_host': default_test_options._replace(needs_fullstack=True,
                                                   needs_dns=True),
     'disappearing_server': connectivity_test_options,
@@ -109,11 +108,11 @@ END2END_TESTS = {
     'large_metadata': default_test_options,
     'max_concurrent_streams': default_test_options._replace(proxyable=False),
     'max_message_length': default_test_options._replace(cpu_cost=LOWCPU),
-    'metadata': default_test_options,
     'negative_deadline': default_test_options,
     'no_op': default_test_options,
     'payload': default_test_options._replace(cpu_cost=LOWCPU),
     'ping_pong_streaming': default_test_options,
+    'ping': connectivity_test_options._replace(proxyable=False),
     'registered_call': default_test_options,
     'request_with_flags': default_test_options._replace(proxyable=False),
     'request_with_payload': default_test_options,
@@ -121,6 +120,7 @@ END2END_TESTS = {
     'shutdown_finishes_calls': default_test_options,
     'shutdown_finishes_tags': default_test_options,
     'simple_delayed_request': connectivity_test_options._replace(cpu_cost=LOWCPU),
+    'simple_metadata': default_test_options,
     'simple_request': default_test_options,
     'trailing_metadata': default_test_options,
 }
diff --git a/test/core/end2end/tests/channel_connectivity.c b/test/core/end2end/tests/connectivity.c
similarity index 98%
rename from test/core/end2end/tests/channel_connectivity.c
rename to test/core/end2end/tests/connectivity.c
index 0e21e655571f704fb6733a2013e584ed6c80341f..975c62073148f2abf33ad3c01230c1062af19f19 100644
--- a/test/core/end2end/tests/channel_connectivity.c
+++ b/test/core/end2end/tests/connectivity.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -168,7 +168,7 @@ static void test_connectivity(grpc_end2end_test_config config) {
   cq_verifier_destroy(cqv);
 }
 
-void channel_connectivity(grpc_end2end_test_config config) {
+void connectivity(grpc_end2end_test_config config) {
   GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION);
   test_connectivity(config);
 }
diff --git a/test/core/end2end/tests/channel_ping.c b/test/core/end2end/tests/ping.c
similarity index 97%
rename from test/core/end2end/tests/channel_ping.c
rename to test/core/end2end/tests/ping.c
index 73fab206fb4af64df1e723cbfcd1eab0b735074b..f85df63de7907db8b8ef9b6b7d5ac340b6a5edbf 100644
--- a/test/core/end2end/tests/channel_ping.c
+++ b/test/core/end2end/tests/ping.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -91,7 +91,7 @@ static void test_ping(grpc_end2end_test_config config) {
   cq_verifier_destroy(cqv);
 }
 
-void channel_ping(grpc_end2end_test_config config) {
+void ping(grpc_end2end_test_config config) {
   GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION);
   test_ping(config);
 }
diff --git a/test/core/end2end/tests/metadata.c b/test/core/end2end/tests/simple_metadata.c
similarity index 99%
rename from test/core/end2end/tests/metadata.c
rename to test/core/end2end/tests/simple_metadata.c
index 5e92091eb7b8e7e9841972f60ae8fce3c7135fe8..c5084a560ff354fdf2855a8887b62f97b556a65e 100644
--- a/test/core/end2end/tests/metadata.c
+++ b/test/core/end2end/tests/simple_metadata.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -260,6 +260,6 @@ static void test_request_response_with_metadata_and_payload(
   config.tear_down_data(&f);
 }
 
-void metadata(grpc_end2end_test_config config) {
+void simple_metadata(grpc_end2end_test_config config) {
   test_request_response_with_metadata_and_payload(config);
 }
diff --git a/test/core/httpcli/httpcli_test.c b/test/core/httpcli/httpcli_test.c
index 651ef1fa3b8bfa70d584514935eed39decd2434c..da1463329d4c731495a64351a4d19e860f2467b4 100644
--- a/test/core/httpcli/httpcli_test.c
+++ b/test/core/httpcli/httpcli_test.c
@@ -36,18 +36,19 @@
 #include <string.h>
 
 #include <grpc/grpc.h>
-#include "src/core/iomgr/iomgr.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/subprocess.h>
 #include <grpc/support/sync.h>
+#include "src/core/iomgr/iomgr.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
 static int g_done = 0;
 static grpc_httpcli_context g_context;
-static grpc_pollset g_pollset;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
 
 static gpr_timespec n_seconds_time(int seconds) {
   return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
@@ -63,10 +64,10 @@ static void on_finish(grpc_exec_ctx *exec_ctx, void *arg,
   GPR_ASSERT(response->status == 200);
   GPR_ASSERT(response->body_length == strlen(expect));
   GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length));
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   g_done = 1;
-  grpc_pollset_kick(&g_pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
 }
 
 static void test_get(int port) {
@@ -85,18 +86,18 @@ static void test_get(int port) {
   req.path = "/get";
   req.handshaker = &grpc_httpcli_plaintext;
 
-  grpc_httpcli_get(&exec_ctx, &g_context, &g_pollset, &req, n_seconds_time(15),
+  grpc_httpcli_get(&exec_ctx, &g_context, g_pollset, &req, n_seconds_time(15),
                    on_finish, (void *)42);
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (!g_done) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
   gpr_free(host);
 }
 
@@ -116,18 +117,18 @@ static void test_post(int port) {
   req.path = "/post";
   req.handshaker = &grpc_httpcli_plaintext;
 
-  grpc_httpcli_post(&exec_ctx, &g_context, &g_pollset, &req, "hello", 5,
+  grpc_httpcli_post(&exec_ctx, &g_context, g_pollset, &req, "hello", 5,
                     n_seconds_time(15), on_finish, (void *)42);
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (!g_done) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
   gpr_free(host);
 }
 
@@ -175,17 +176,20 @@ int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   grpc_init();
   grpc_httpcli_context_init(&g_context);
-  grpc_pollset_init(&g_pollset);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
 
   test_get(port);
   test_post(port);
 
   grpc_httpcli_context_destroy(&g_context);
-  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
 
+  gpr_free(g_pollset);
+
   gpr_subprocess_destroy(server);
 
   return 0;
diff --git a/test/core/httpcli/httpscli_test.c b/test/core/httpcli/httpscli_test.c
index db41be17e73b3cc86e269cb3b753256175c3b080..7f765bc614f2682c876acd03d83841b76eb19938 100644
--- a/test/core/httpcli/httpscli_test.c
+++ b/test/core/httpcli/httpscli_test.c
@@ -36,18 +36,19 @@
 #include <string.h>
 
 #include <grpc/grpc.h>
-#include "src/core/iomgr/iomgr.h"
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/subprocess.h>
 #include <grpc/support/sync.h>
+#include "src/core/iomgr/iomgr.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
 static int g_done = 0;
 static grpc_httpcli_context g_context;
-static grpc_pollset g_pollset;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
 
 static gpr_timespec n_seconds_time(int seconds) {
   return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(seconds);
@@ -63,10 +64,10 @@ static void on_finish(grpc_exec_ctx *exec_ctx, void *arg,
   GPR_ASSERT(response->status == 200);
   GPR_ASSERT(response->body_length == strlen(expect));
   GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length));
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   g_done = 1;
-  grpc_pollset_kick(&g_pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
 }
 
 static void test_get(int port) {
@@ -86,18 +87,18 @@ static void test_get(int port) {
   req.path = "/get";
   req.handshaker = &grpc_httpcli_ssl;
 
-  grpc_httpcli_get(&exec_ctx, &g_context, &g_pollset, &req, n_seconds_time(15),
+  grpc_httpcli_get(&exec_ctx, &g_context, g_pollset, &req, n_seconds_time(15),
                    on_finish, (void *)42);
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (!g_done) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
   gpr_free(host);
 }
 
@@ -118,18 +119,18 @@ static void test_post(int port) {
   req.path = "/post";
   req.handshaker = &grpc_httpcli_ssl;
 
-  grpc_httpcli_post(&exec_ctx, &g_context, &g_pollset, &req, "hello", 5,
+  grpc_httpcli_post(&exec_ctx, &g_context, g_pollset, &req, "hello", 5,
                     n_seconds_time(15), on_finish, (void *)42);
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (!g_done) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), n_seconds_time(20));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
   gpr_free(host);
 }
 
@@ -178,17 +179,20 @@ int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   grpc_init();
   grpc_httpcli_context_init(&g_context);
-  grpc_pollset_init(&g_pollset);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
 
   test_get(port);
   test_post(port);
 
   grpc_httpcli_context_destroy(&g_context);
-  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
 
+  gpr_free(g_pollset);
+
   gpr_subprocess_destroy(server);
 
   return 0;
diff --git a/test/core/iomgr/endpoint_pair_test.c b/test/core/iomgr/endpoint_pair_test.c
index 7e266ebfb99bc8bd583984668dd8eedbf53640d7..c3a91088a5737e0ab239841afd1fc9321c35a9cc 100644
--- a/test/core/iomgr/endpoint_pair_test.c
+++ b/test/core/iomgr/endpoint_pair_test.c
@@ -39,10 +39,11 @@
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
 #include "src/core/iomgr/endpoint_pair.h"
-#include "test/core/util/test_config.h"
 #include "test/core/iomgr/endpoint_tests.h"
+#include "test/core/util/test_config.h"
 
-static grpc_pollset g_pollset;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
 
 static void clean_up(void) {}
 
@@ -54,8 +55,8 @@ static grpc_endpoint_test_fixture create_fixture_endpoint_pair(
 
   f.client_ep = p.client;
   f.server_ep = p.server;
-  grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, &g_pollset);
-  grpc_endpoint_add_to_pollset(&exec_ctx, f.server_ep, &g_pollset);
+  grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset);
+  grpc_endpoint_add_to_pollset(&exec_ctx, f.server_ep, g_pollset);
   grpc_exec_ctx_finish(&exec_ctx);
 
   return f;
@@ -74,12 +75,14 @@ int main(int argc, char **argv) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_init();
-  grpc_pollset_init(&g_pollset);
-  grpc_endpoint_tests(configs[0], &g_pollset);
-  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
+  grpc_endpoint_tests(configs[0], g_pollset, g_mu);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
+  gpr_free(g_pollset);
 
   return 0;
 }
diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c
index 1b6a78da9ac68aa561d698f8a07350ef487006ef..f689e4ba7fb336daf3c40c68e44b4148436930ca 100644
--- a/test/core/iomgr/endpoint_tests.c
+++ b/test/core/iomgr/endpoint_tests.c
@@ -36,8 +36,8 @@
 #include <sys/types.h>
 
 #include <grpc/support/alloc.h>
-#include <grpc/support/slice.h>
 #include <grpc/support/log.h>
+#include <grpc/support/slice.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
 #include "test/core/util/test_config.h"
@@ -58,6 +58,7 @@
 
 */
 
+static gpr_mu *g_mu;
 static grpc_pollset *g_pollset;
 
 size_t count_slices(gpr_slice *slices, size_t nslices, int *current_data) {
@@ -134,10 +135,10 @@ static void read_and_write_test_read_handler(grpc_exec_ctx *exec_ctx,
       state->incoming.slices, state->incoming.count, &state->current_read_data);
   if (state->bytes_read == state->target_bytes || !success) {
     gpr_log(GPR_INFO, "Read handler done");
-    gpr_mu_lock(GRPC_POLLSET_MU(g_pollset));
+    gpr_mu_lock(g_mu);
     state->read_done = 1 + success;
     grpc_pollset_kick(g_pollset, NULL);
-    gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
+    gpr_mu_unlock(g_mu);
   } else if (success) {
     grpc_endpoint_read(exec_ctx, state->read_ep, &state->incoming,
                        &state->done_read);
@@ -169,10 +170,10 @@ static void read_and_write_test_write_handler(grpc_exec_ctx *exec_ctx,
   }
 
   gpr_log(GPR_INFO, "Write handler done");
-  gpr_mu_lock(GRPC_POLLSET_MU(g_pollset));
+  gpr_mu_lock(g_mu);
   state->write_done = 1 + success;
   grpc_pollset_kick(g_pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
+  gpr_mu_unlock(g_mu);
 }
 
 /* Do both reading and writing using the grpc_endpoint API.
@@ -232,14 +233,14 @@ static void read_and_write_test(grpc_endpoint_test_config config,
   }
   grpc_exec_ctx_finish(&exec_ctx);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(g_pollset));
+  gpr_mu_lock(g_mu);
   while (!state.read_done || !state.write_done) {
-    grpc_pollset_worker worker;
+    grpc_pollset_worker *worker = NULL;
     GPR_ASSERT(gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), deadline) < 0);
     grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), deadline);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset));
+  gpr_mu_unlock(g_mu);
   grpc_exec_ctx_finish(&exec_ctx);
 
   end_test(config);
@@ -251,9 +252,10 @@ static void read_and_write_test(grpc_endpoint_test_config config,
 }
 
 void grpc_endpoint_tests(grpc_endpoint_test_config config,
-                         grpc_pollset *pollset) {
+                         grpc_pollset *pollset, gpr_mu *mu) {
   size_t i;
   g_pollset = pollset;
+  g_mu = mu;
   read_and_write_test(config, 10000000, 100000, 8192, 0);
   read_and_write_test(config, 1000000, 100000, 1, 0);
   read_and_write_test(config, 100000000, 100000, 1, 1);
diff --git a/test/core/iomgr/endpoint_tests.h b/test/core/iomgr/endpoint_tests.h
index 700f854891e62384fe422cbf56b5f2e561d38422..8ea47e345cf5b9aacd51e5f972a1603a44a29b56 100644
--- a/test/core/iomgr/endpoint_tests.h
+++ b/test/core/iomgr/endpoint_tests.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -53,6 +53,6 @@ struct grpc_endpoint_test_config {
 };
 
 void grpc_endpoint_tests(grpc_endpoint_test_config config,
-                         grpc_pollset *pollset);
+                         grpc_pollset *pollset, gpr_mu *mu);
 
 #endif /* GRPC_TEST_CORE_IOMGR_ENDPOINT_TESTS_H */
diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c
index 347a86af1084b60b8dace536b6225eb776ffb5f9..99689ebcc3bfd50f5188cebca20dfc2893a3a252 100644
--- a/test/core/iomgr/fd_posix_test.c
+++ b/test/core/iomgr/fd_posix_test.c
@@ -49,9 +49,12 @@
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
+
+#include "src/core/iomgr/pollset_posix.h"
 #include "test/core/util/test_config.h"
 
-static grpc_pollset g_pollset;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
 
 /* buffer size used to send and receive data.
    1024 is the minimal value to set TCP send and receive buffer. */
@@ -179,10 +182,10 @@ static void listen_shutdown_cb(grpc_exec_ctx *exec_ctx, void *arg /*server */,
 
   grpc_fd_orphan(exec_ctx, sv->em_fd, NULL, NULL, "b");
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   sv->done = 1;
-  grpc_pollset_kick(&g_pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
 }
 
 /* Called when a new TCP connection request arrives in the listening port. */
@@ -209,7 +212,7 @@ static void listen_cb(grpc_exec_ctx *exec_ctx, void *arg, /*=sv_arg*/
   se = gpr_malloc(sizeof(*se));
   se->sv = sv;
   se->em_fd = grpc_fd_create(fd, "listener");
-  grpc_pollset_add_fd(exec_ctx, &g_pollset, se->em_fd);
+  grpc_pollset_add_fd(exec_ctx, g_pollset, se->em_fd);
   se->session_read_closure.cb = session_read_cb;
   se->session_read_closure.cb_arg = se;
   grpc_fd_notify_on_read(exec_ctx, se->em_fd, &se->session_read_closure);
@@ -238,7 +241,7 @@ static int server_start(grpc_exec_ctx *exec_ctx, server *sv) {
   GPR_ASSERT(listen(fd, MAX_NUM_FD) == 0);
 
   sv->em_fd = grpc_fd_create(fd, "server");
-  grpc_pollset_add_fd(exec_ctx, &g_pollset, sv->em_fd);
+  grpc_pollset_add_fd(exec_ctx, g_pollset, sv->em_fd);
   /* Register to be interested in reading from listen_fd. */
   sv->listen_closure.cb = listen_cb;
   sv->listen_closure.cb_arg = sv;
@@ -249,18 +252,18 @@ static int server_start(grpc_exec_ctx *exec_ctx, server *sv) {
 
 /* Wait and shutdown a sever. */
 static void server_wait_and_shutdown(server *sv) {
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (!sv->done) {
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       gpr_inf_future(GPR_CLOCK_MONOTONIC));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 }
 
 /* ===An upload client to test notify_on_write=== */
@@ -296,7 +299,7 @@ static void client_session_shutdown_cb(grpc_exec_ctx *exec_ctx,
   client *cl = arg;
   grpc_fd_orphan(exec_ctx, cl->em_fd, NULL, NULL, "c");
   cl->done = 1;
-  grpc_pollset_kick(&g_pollset, NULL);
+  grpc_pollset_kick(g_pollset, NULL);
 }
 
 /* Write as much as possible, then register notify_on_write. */
@@ -307,9 +310,9 @@ static void client_session_write(grpc_exec_ctx *exec_ctx, void *arg, /*client */
   ssize_t write_once = 0;
 
   if (!success) {
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
     client_session_shutdown_cb(exec_ctx, arg, 1);
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     return;
   }
 
@@ -319,7 +322,7 @@ static void client_session_write(grpc_exec_ctx *exec_ctx, void *arg, /*client */
   } while (write_once > 0);
 
   if (errno == EAGAIN) {
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
     if (cl->client_write_cnt < CLIENT_TOTAL_WRITE_CNT) {
       cl->write_closure.cb = client_session_write;
       cl->write_closure.cb_arg = cl;
@@ -328,7 +331,7 @@ static void client_session_write(grpc_exec_ctx *exec_ctx, void *arg, /*client */
     } else {
       client_session_shutdown_cb(exec_ctx, arg, 1);
     }
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
   } else {
     gpr_log(GPR_ERROR, "unknown errno %s", strerror(errno));
     abort();
@@ -357,25 +360,25 @@ static void client_start(grpc_exec_ctx *exec_ctx, client *cl, int port) {
   }
 
   cl->em_fd = grpc_fd_create(fd, "client");
-  grpc_pollset_add_fd(exec_ctx, &g_pollset, cl->em_fd);
+  grpc_pollset_add_fd(exec_ctx, g_pollset, cl->em_fd);
 
   client_session_write(exec_ctx, cl, 1);
 }
 
 /* Wait for the signal to shutdown a client. */
 static void client_wait_and_shutdown(client *cl) {
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (!cl->done) {
-    grpc_pollset_worker worker;
+    grpc_pollset_worker *worker = NULL;
     grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       gpr_inf_future(GPR_CLOCK_MONOTONIC));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 }
 
 /* Test grpc_fd. Start an upload server and client, upload a stream of
@@ -410,20 +413,20 @@ static void first_read_callback(grpc_exec_ctx *exec_ctx,
                                 void *arg /* fd_change_data */, bool success) {
   fd_change_data *fdc = arg;
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   fdc->cb_that_ran = first_read_callback;
-  grpc_pollset_kick(&g_pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
 }
 
 static void second_read_callback(grpc_exec_ctx *exec_ctx,
                                  void *arg /* fd_change_data */, bool success) {
   fd_change_data *fdc = arg;
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   fdc->cb_that_ran = second_read_callback;
-  grpc_pollset_kick(&g_pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
 }
 
 /* Test that changing the callback we use for notify_on_read actually works.
@@ -456,7 +459,7 @@ static void test_grpc_fd_change(void) {
   GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0);
 
   em_fd = grpc_fd_create(sv[0], "test_grpc_fd_change");
-  grpc_pollset_add_fd(&exec_ctx, &g_pollset, em_fd);
+  grpc_pollset_add_fd(&exec_ctx, g_pollset, em_fd);
 
   /* Register the first callback, then make its FD readable */
   grpc_fd_notify_on_read(&exec_ctx, em_fd, &first_closure);
@@ -465,18 +468,18 @@ static void test_grpc_fd_change(void) {
   GPR_ASSERT(result == 1);
 
   /* And now wait for it to run. */
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (a.cb_that_ran == NULL) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       gpr_inf_future(GPR_CLOCK_MONOTONIC));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
   GPR_ASSERT(a.cb_that_ran == first_read_callback);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 
   /* And drain the socket so we can generate a new read edge */
   result = read(sv[0], &data, 1);
@@ -489,19 +492,19 @@ static void test_grpc_fd_change(void) {
   result = write(sv[1], &data, 1);
   GPR_ASSERT(result == 1);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (b.cb_that_ran == NULL) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       gpr_inf_future(GPR_CLOCK_MONOTONIC));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
   /* Except now we verify that second_read_callback ran instead */
   GPR_ASSERT(b.cb_that_ran == second_read_callback);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 
   grpc_fd_orphan(&exec_ctx, em_fd, NULL, NULL, "d");
   grpc_exec_ctx_finish(&exec_ctx);
@@ -519,12 +522,14 @@ int main(int argc, char **argv) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_iomgr_init();
-  grpc_pollset_init(&g_pollset);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
   test_grpc_fd();
   test_grpc_fd_change();
-  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
+  gpr_free(g_pollset);
   grpc_iomgr_shutdown();
   return 0;
 }
diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c
index 9725d8a3b6411de5798efb0ee95d4fb24584f63f..746dfd85be670bf683eacdc962be7646a7f0c789 100644
--- a/test/core/iomgr/tcp_client_posix_test.c
+++ b/test/core/iomgr/tcp_client_posix_test.c
@@ -40,15 +40,18 @@
 #include <unistd.h>
 
 #include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 
 #include "src/core/iomgr/iomgr.h"
 #include "src/core/iomgr/socket_utils_posix.h"
+#include "src/core/iomgr/timer.h"
 #include "test/core/util/test_config.h"
 
-static grpc_pollset_set g_pollset_set;
-static grpc_pollset g_pollset;
+static grpc_pollset_set *g_pollset_set;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
 static int g_connections_complete = 0;
 static grpc_endpoint *g_connecting = NULL;
 
@@ -57,10 +60,10 @@ static gpr_timespec test_deadline(void) {
 }
 
 static void finish_connection() {
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   g_connections_complete++;
-  grpc_pollset_kick(&g_pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
 }
 
 static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
@@ -98,14 +101,14 @@ void test_succeeds(void) {
   GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len));
   GPR_ASSERT(0 == listen(svr_fd, 1));
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   connections_complete_before = g_connections_complete;
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 
   /* connect to it */
   GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0);
   grpc_closure_init(&done, must_succeed, NULL);
-  grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, &g_pollset_set,
+  grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, g_pollset_set,
                           (struct sockaddr *)&addr, addr_len,
                           gpr_inf_future(GPR_CLOCK_REALTIME));
 
@@ -117,19 +120,21 @@ void test_succeeds(void) {
   GPR_ASSERT(r >= 0);
   close(r);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
 
   while (g_connections_complete == connections_complete_before) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
-    grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
+    grpc_exec_ctx_flush(&exec_ctx);
+    gpr_mu_lock(g_mu);
   }
 
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
+
+  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 void test_fails(void) {
@@ -144,118 +149,33 @@ void test_fails(void) {
   memset(&addr, 0, sizeof(addr));
   addr.sin_family = AF_INET;
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   connections_complete_before = g_connections_complete;
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 
   /* connect to a broken address */
   grpc_closure_init(&done, must_fail, NULL);
-  grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, &g_pollset_set,
+  grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, g_pollset_set,
                           (struct sockaddr *)&addr, addr_len,
                           gpr_inf_future(GPR_CLOCK_REALTIME));
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
 
   /* wait for the connection callback to finish */
   while (g_connections_complete == connections_complete_before) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC), test_deadline());
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
-    grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
-  }
-
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
-}
-
-void test_times_out(void) {
-  struct sockaddr_in addr;
-  socklen_t addr_len = sizeof(addr);
-  int svr_fd;
-#define NUM_CLIENT_CONNECTS 100
-  int client_fd[NUM_CLIENT_CONNECTS];
-  int i;
-  int r;
-  int connections_complete_before;
-  gpr_timespec connect_deadline;
-  grpc_closure done;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  gpr_log(GPR_DEBUG, "test_times_out");
-
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-
-  /* create a dummy server */
-  svr_fd = socket(AF_INET, SOCK_STREAM, 0);
-  GPR_ASSERT(svr_fd >= 0);
-  GPR_ASSERT(0 == bind(svr_fd, (struct sockaddr *)&addr, addr_len));
-  GPR_ASSERT(0 == listen(svr_fd, 1));
-  /* Get its address */
-  GPR_ASSERT(getsockname(svr_fd, (struct sockaddr *)&addr, &addr_len) == 0);
-
-  /* tie up the listen buffer, which is somewhat arbitrarily sized. */
-  for (i = 0; i < NUM_CLIENT_CONNECTS; ++i) {
-    client_fd[i] = socket(AF_INET, SOCK_STREAM, 0);
-    grpc_set_socket_nonblocking(client_fd[i], 1);
-    do {
-      r = connect(client_fd[i], (struct sockaddr *)&addr, addr_len);
-    } while (r == -1 && errno == EINTR);
-    GPR_ASSERT(r < 0);
-    GPR_ASSERT(errno == EWOULDBLOCK || errno == EINPROGRESS);
-  }
-
-  /* connect to dummy server address */
-
-  connect_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1);
-
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
-  connections_complete_before = g_connections_complete;
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
-
-  grpc_closure_init(&done, must_fail, NULL);
-  grpc_tcp_client_connect(&exec_ctx, &done, &g_connecting, &g_pollset_set,
-                          (struct sockaddr *)&addr, addr_len, connect_deadline);
-
-  /* Make sure the event doesn't trigger early */
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
-  for (;;) {
-    grpc_pollset_worker worker;
-    gpr_timespec now = gpr_now(connect_deadline.clock_type);
-    gpr_timespec continue_verifying_time =
-        gpr_time_from_seconds(5, GPR_TIMESPAN);
-    gpr_timespec grace_time = gpr_time_from_seconds(3, GPR_TIMESPAN);
-    gpr_timespec finish_time =
-        gpr_time_add(connect_deadline, continue_verifying_time);
-    gpr_timespec restart_verifying_time =
-        gpr_time_add(connect_deadline, grace_time);
-    int is_after_deadline = gpr_time_cmp(now, connect_deadline) > 0;
-    if (gpr_time_cmp(now, finish_time) > 0) {
-      break;
+    grpc_pollset_worker *worker = NULL;
+    gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
+    gpr_timespec polling_deadline = test_deadline();
+    if (!grpc_timer_check(&exec_ctx, now, &polling_deadline)) {
+      grpc_pollset_work(&exec_ctx, g_pollset, &worker, now, polling_deadline);
     }
-    gpr_log(GPR_DEBUG, "now=%lld.%09d connect_deadline=%lld.%09d",
-            (long long)now.tv_sec, (int)now.tv_nsec,
-            (long long)connect_deadline.tv_sec, (int)connect_deadline.tv_nsec);
-    if (is_after_deadline && gpr_time_cmp(now, restart_verifying_time) <= 0) {
-      /* allow some slack before insisting that things be done */
-    } else {
-      GPR_ASSERT(g_connections_complete ==
-                 connections_complete_before + is_after_deadline);
-    }
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
-                      gpr_now(GPR_CLOCK_MONOTONIC),
-                      GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
-    grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
+    grpc_exec_ctx_flush(&exec_ctx);
+    gpr_mu_lock(g_mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
 
-  close(svr_fd);
-  for (i = 0; i < NUM_CLIENT_CONNECTS; ++i) {
-    close(client_fd[i]);
-  }
+  gpr_mu_unlock(g_mu);
+  grpc_exec_ctx_finish(&exec_ctx);
 }
 
 static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, bool success) {
@@ -267,18 +187,19 @@ int main(int argc, char **argv) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_init();
-  grpc_pollset_set_init(&g_pollset_set);
-  grpc_pollset_init(&g_pollset);
-  grpc_pollset_set_add_pollset(&exec_ctx, &g_pollset_set, &g_pollset);
+  g_pollset_set = grpc_pollset_set_create();
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
+  grpc_pollset_set_add_pollset(&exec_ctx, g_pollset_set, g_pollset);
   grpc_exec_ctx_finish(&exec_ctx);
   test_succeeds();
   gpr_log(GPR_ERROR, "End of first test");
   test_fails();
-  test_times_out();
-  grpc_pollset_set_destroy(&g_pollset_set);
-  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
+  grpc_pollset_set_destroy(g_pollset_set);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
+  gpr_free(g_pollset);
   return 0;
 }
diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c
index d290c6bc3ab30ee718ed2e1df95d413a9f3f7191..4351642ab6e3fb16593fa3c48093538e84446470 100644
--- a/test/core/iomgr/tcp_posix_test.c
+++ b/test/core/iomgr/tcp_posix_test.c
@@ -36,8 +36,8 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <string.h>
-#include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #include <grpc/grpc.h>
@@ -45,10 +45,11 @@
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
 #include <grpc/support/useful.h>
-#include "test/core/util/test_config.h"
 #include "test/core/iomgr/endpoint_tests.h"
+#include "test/core/util/test_config.h"
 
-static grpc_pollset g_pollset;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
 
 /*
    General test notes:
@@ -145,7 +146,7 @@ static void read_cb(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
 
   GPR_ASSERT(success);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   current_data = state->read_bytes % 256;
   read_bytes = count_slices(state->incoming.slices, state->incoming.count,
                             &current_data);
@@ -153,10 +154,10 @@ static void read_cb(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
   gpr_log(GPR_INFO, "Read %d bytes of %d", read_bytes,
           state->target_read_bytes);
   if (state->read_bytes >= state->target_read_bytes) {
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
   } else {
     grpc_endpoint_read(exec_ctx, state->ep, &state->incoming, &state->read_cb);
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
   }
 }
 
@@ -175,7 +176,7 @@ static void read_test(size_t num_bytes, size_t slice_size) {
   create_sockets(sv);
 
   ep = grpc_tcp_create(grpc_fd_create(sv[1], "read_test"), slice_size, "test");
-  grpc_endpoint_add_to_pollset(&exec_ctx, ep, &g_pollset);
+  grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset);
 
   written_bytes = fill_socket_partial(sv[0], num_bytes);
   gpr_log(GPR_INFO, "Wrote %d bytes", written_bytes);
@@ -188,17 +189,17 @@ static void read_test(size_t num_bytes, size_t slice_size) {
 
   grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (state.read_bytes < state.target_read_bytes) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), deadline);
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
   GPR_ASSERT(state.read_bytes == state.target_read_bytes);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 
   gpr_slice_buffer_destroy(&state.incoming);
   grpc_endpoint_destroy(&exec_ctx, ep);
@@ -221,7 +222,7 @@ static void large_read_test(size_t slice_size) {
 
   ep = grpc_tcp_create(grpc_fd_create(sv[1], "large_read_test"), slice_size,
                        "test");
-  grpc_endpoint_add_to_pollset(&exec_ctx, ep, &g_pollset);
+  grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset);
 
   written_bytes = fill_socket(sv[0]);
   gpr_log(GPR_INFO, "Wrote %d bytes", written_bytes);
@@ -234,17 +235,17 @@ static void large_read_test(size_t slice_size) {
 
   grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (state.read_bytes < state.target_read_bytes) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), deadline);
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
   GPR_ASSERT(state.read_bytes == state.target_read_bytes);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 
   gpr_slice_buffer_destroy(&state.incoming);
   grpc_endpoint_destroy(&exec_ctx, ep);
@@ -283,11 +284,11 @@ static void write_done(grpc_exec_ctx *exec_ctx,
                        void *user_data /* write_socket_state */, bool success) {
   struct write_socket_state *state = (struct write_socket_state *)user_data;
   gpr_log(GPR_INFO, "Write done callback called");
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   gpr_log(GPR_INFO, "Signalling write done");
   state->write_done = 1;
-  grpc_pollset_kick(&g_pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
 }
 
 void drain_socket_blocking(int fd, size_t num_bytes, size_t read_size) {
@@ -303,12 +304,12 @@ void drain_socket_blocking(int fd, size_t num_bytes, size_t read_size) {
   GPR_ASSERT(fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) == 0);
 
   for (;;) {
-    grpc_pollset_worker worker;
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    gpr_mu_lock(g_mu);
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
     do {
       bytes_read =
@@ -350,7 +351,7 @@ static void write_test(size_t num_bytes, size_t slice_size) {
 
   ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_test"),
                        GRPC_TCP_DEFAULT_READ_SLICE_SIZE, "test");
-  grpc_endpoint_add_to_pollset(&exec_ctx, ep, &g_pollset);
+  grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset);
 
   state.ep = ep;
   state.write_done = 0;
@@ -363,19 +364,19 @@ static void write_test(size_t num_bytes, size_t slice_size) {
 
   grpc_endpoint_write(&exec_ctx, ep, &outgoing, &write_done_closure);
   drain_socket_blocking(sv[0], num_bytes, num_bytes);
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   for (;;) {
-    grpc_pollset_worker worker;
+    grpc_pollset_worker *worker = NULL;
     if (state.write_done) {
       break;
     }
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), deadline);
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 
   gpr_slice_buffer_destroy(&outgoing);
   grpc_endpoint_destroy(&exec_ctx, ep);
@@ -386,7 +387,7 @@ static void write_test(size_t num_bytes, size_t slice_size) {
 void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
   int *done = arg;
   *done = 1;
-  grpc_pollset_kick(&g_pollset, NULL);
+  grpc_pollset_kick(g_pollset, NULL);
 }
 
 /* Do a read_test, then release fd and try to read/write again. Verify that
@@ -410,7 +411,7 @@ static void release_fd_test(size_t num_bytes, size_t slice_size) {
 
   ep = grpc_tcp_create(grpc_fd_create(sv[1], "read_test"), slice_size, "test");
   GPR_ASSERT(grpc_tcp_fd(ep) == sv[1] && sv[1] >= 0);
-  grpc_endpoint_add_to_pollset(&exec_ctx, ep, &g_pollset);
+  grpc_endpoint_add_to_pollset(&exec_ctx, ep, g_pollset);
 
   written_bytes = fill_socket_partial(sv[0], num_bytes);
   gpr_log(GPR_INFO, "Wrote %d bytes", written_bytes);
@@ -423,27 +424,27 @@ static void release_fd_test(size_t num_bytes, size_t slice_size) {
 
   grpc_endpoint_read(&exec_ctx, ep, &state.incoming, &state.read_cb);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (state.read_bytes < state.target_read_bytes) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), deadline);
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
   GPR_ASSERT(state.read_bytes == state.target_read_bytes);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 
   gpr_slice_buffer_destroy(&state.incoming);
   grpc_tcp_destroy_and_release_fd(&exec_ctx, ep, &fd, &fd_released_cb);
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   while (!fd_released_done) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), deadline);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
   GPR_ASSERT(fd_released_done == 1);
   GPR_ASSERT(fd == sv[1]);
   grpc_exec_ctx_finish(&exec_ctx);
@@ -491,8 +492,8 @@ static grpc_endpoint_test_fixture create_fixture_tcp_socketpair(
                                 slice_size, "test");
   f.server_ep = grpc_tcp_create(grpc_fd_create(sv[1], "fixture:server"),
                                 slice_size, "test");
-  grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, &g_pollset);
-  grpc_endpoint_add_to_pollset(&exec_ctx, f.server_ep, &g_pollset);
+  grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset);
+  grpc_endpoint_add_to_pollset(&exec_ctx, f.server_ep, g_pollset);
 
   grpc_exec_ctx_finish(&exec_ctx);
 
@@ -512,13 +513,15 @@ int main(int argc, char **argv) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_init();
-  grpc_pollset_init(&g_pollset);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
   run_tests();
-  grpc_endpoint_tests(configs[0], &g_pollset);
-  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
+  grpc_endpoint_tests(configs[0], g_pollset, g_mu);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
+  gpr_free(g_pollset);
 
   return 0;
 }
diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c
index 272d97bfcbdb4dba106ea0265ed0a3d28e437676..7933468355a77e06f778979a99052e26b139539d 100644
--- a/test/core/iomgr/tcp_server_posix_test.c
+++ b/test/core/iomgr/tcp_server_posix_test.c
@@ -32,24 +32,28 @@
  */
 
 #include "src/core/iomgr/tcp_server.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/iomgr/sockaddr_utils.h"
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
 #include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
+
+#include "src/core/iomgr/iomgr.h"
+#include "src/core/iomgr/sockaddr_utils.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <unistd.h>
-
 #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x)
 
-static grpc_pollset g_pollset;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
 static int g_nconnects = 0;
 
 typedef struct on_connect_result {
@@ -113,11 +117,11 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
   grpc_endpoint_shutdown(exec_ctx, tcp);
   grpc_endpoint_destroy(exec_ctx, tcp);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   on_connect_result_set(&g_result, acceptor);
   g_nconnects++;
-  grpc_pollset_kick(&g_pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
 }
 
 static void test_no_op(void) {
@@ -174,7 +178,7 @@ static void tcp_connect(grpc_exec_ctx *exec_ctx, const struct sockaddr *remote,
   int clifd = socket(remote->sa_family, SOCK_STREAM, 0);
   int nconnects_before;
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   nconnects_before = g_nconnects;
   on_connect_result_init(&g_result);
   GPR_ASSERT(clifd >= 0);
@@ -183,19 +187,19 @@ static void tcp_connect(grpc_exec_ctx *exec_ctx, const struct sockaddr *remote,
   gpr_log(GPR_DEBUG, "wait");
   while (g_nconnects == nconnects_before &&
          gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(exec_ctx, &g_pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(exec_ctx, g_pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC), deadline);
-    gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_unlock(g_mu);
     grpc_exec_ctx_finish(exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+    gpr_mu_lock(g_mu);
   }
   gpr_log(GPR_DEBUG, "wait done");
   GPR_ASSERT(g_nconnects == nconnects_before + 1);
   close(clifd);
   *result = g_result;
 
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_unlock(g_mu);
 }
 
 /* Tests a tcp server with multiple ports. TODO(daniel-j-born): Multiple fds for
@@ -210,7 +214,6 @@ static void test_connect(unsigned n) {
   unsigned svr1_fd_count;
   int svr1_port;
   grpc_tcp_server *s = grpc_tcp_server_create(NULL);
-  grpc_pollset *pollsets[1];
   unsigned i;
   server_weak_ref weak_ref;
   server_weak_ref_init(&weak_ref);
@@ -259,8 +262,7 @@ static void test_connect(unsigned n) {
     }
   }
 
-  pollsets[0] = &g_pollset;
-  grpc_tcp_server_start(&exec_ctx, s, pollsets, 1, on_connect, NULL);
+  grpc_tcp_server_start(&exec_ctx, s, &g_pollset, 1, on_connect, NULL);
 
   for (i = 0; i < n; i++) {
     on_connect_result result;
@@ -312,7 +314,8 @@ int main(int argc, char **argv) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_init();
-  grpc_pollset_init(&g_pollset);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
 
   test_no_op();
   test_no_op_with_start();
@@ -321,9 +324,10 @@ int main(int argc, char **argv) {
   test_connect(1);
   test_connect(10);
 
-  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
+  gpr_free(g_pollset);
   return 0;
 }
diff --git a/test/core/iomgr/timer_heap_test.c b/test/core/iomgr/timer_heap_test.c
index 077a9fd6bd87142847818f6604e6c6db29d446cd..cd34696f7ddeb15d8be27a90d48e21bb3a316dfd 100644
--- a/test/core/iomgr/timer_heap_test.c
+++ b/test/core/iomgr/timer_heap_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,8 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
 #include "test/core/util/test_config.h"
 
 static gpr_timespec random_deadline(void) {
@@ -57,79 +59,6 @@ static grpc_timer *create_test_elements(size_t num_elements) {
   return elems;
 }
 
-static int cmp_elem(const void *a, const void *b) {
-  int i = *(const int *)a;
-  int j = *(const int *)b;
-  return i - j;
-}
-
-static size_t *all_top(grpc_timer_heap *pq, size_t *n) {
-  size_t *vec = NULL;
-  size_t *need_to_check_children;
-  size_t num_need_to_check_children = 0;
-
-  *n = 0;
-  if (pq->timer_count == 0) return vec;
-  need_to_check_children =
-      gpr_malloc(pq->timer_count * sizeof(*need_to_check_children));
-  need_to_check_children[num_need_to_check_children++] = 0;
-  vec = gpr_malloc(pq->timer_count * sizeof(*vec));
-  while (num_need_to_check_children > 0) {
-    size_t ind = need_to_check_children[0];
-    size_t leftchild, rightchild;
-    num_need_to_check_children--;
-    memmove(need_to_check_children, need_to_check_children + 1,
-            num_need_to_check_children * sizeof(*need_to_check_children));
-    vec[(*n)++] = ind;
-    leftchild = 1u + 2u * ind;
-    if (leftchild < pq->timer_count) {
-      if (gpr_time_cmp(pq->timers[leftchild]->deadline,
-                       pq->timers[ind]->deadline) >= 0) {
-        need_to_check_children[num_need_to_check_children++] = leftchild;
-      }
-      rightchild = leftchild + 1;
-      if (rightchild < pq->timer_count &&
-          gpr_time_cmp(pq->timers[rightchild]->deadline,
-                       pq->timers[ind]->deadline) >= 0) {
-        need_to_check_children[num_need_to_check_children++] = rightchild;
-      }
-    }
-  }
-
-  gpr_free(need_to_check_children);
-
-  return vec;
-}
-
-static void check_pq_top(grpc_timer *elements, grpc_timer_heap *pq,
-                         uint8_t *inpq, size_t num_elements) {
-  gpr_timespec max_deadline = gpr_inf_past(GPR_CLOCK_REALTIME);
-  size_t *max_deadline_indices =
-      gpr_malloc(num_elements * sizeof(*max_deadline_indices));
-  size_t *top_elements;
-  size_t num_max_deadline_indices = 0;
-  size_t num_top_elements;
-  size_t i;
-  for (i = 0; i < num_elements; ++i) {
-    if (inpq[i] && gpr_time_cmp(elements[i].deadline, max_deadline) >= 0) {
-      if (gpr_time_cmp(elements[i].deadline, max_deadline) > 0) {
-        num_max_deadline_indices = 0;
-        max_deadline = elements[i].deadline;
-      }
-      max_deadline_indices[num_max_deadline_indices++] = elements[i].heap_index;
-    }
-  }
-  qsort(max_deadline_indices, num_max_deadline_indices,
-        sizeof(*max_deadline_indices), cmp_elem);
-  top_elements = all_top(pq, &num_top_elements);
-  GPR_ASSERT(num_top_elements == num_max_deadline_indices);
-  for (i = 0; i < num_top_elements; i++) {
-    GPR_ASSERT(max_deadline_indices[i] == top_elements[i]);
-  }
-  gpr_free(max_deadline_indices);
-  gpr_free(top_elements);
-}
-
 static int contains(grpc_timer_heap *pq, grpc_timer *el) {
   size_t i;
   for (i = 0; i < pq->timer_count; i++) {
@@ -145,15 +74,19 @@ static void check_valid(grpc_timer_heap *pq) {
     size_t right_child = left_child + 1u;
     if (left_child < pq->timer_count) {
       GPR_ASSERT(gpr_time_cmp(pq->timers[i]->deadline,
-                              pq->timers[left_child]->deadline) >= 0);
+                              pq->timers[left_child]->deadline) <= 0);
     }
     if (right_child < pq->timer_count) {
       GPR_ASSERT(gpr_time_cmp(pq->timers[i]->deadline,
-                              pq->timers[right_child]->deadline) >= 0);
+                              pq->timers[right_child]->deadline) <= 0);
     }
   }
 }
 
+/*******************************************************************************
+ * test1
+ */
+
 static void test1(void) {
   grpc_timer_heap pq;
   const size_t num_test_elements = 200;
@@ -162,6 +95,8 @@ static void test1(void) {
   grpc_timer *test_elements = create_test_elements(num_test_elements);
   uint8_t *inpq = gpr_malloc(num_test_elements);
 
+  gpr_log(GPR_INFO, "test1");
+
   grpc_timer_heap_init(&pq);
   memset(inpq, 0, num_test_elements);
   GPR_ASSERT(grpc_timer_heap_is_empty(&pq));
@@ -172,7 +107,6 @@ static void test1(void) {
     check_valid(&pq);
     GPR_ASSERT(contains(&pq, &test_elements[i]));
     inpq[i] = 1;
-    check_pq_top(test_elements, &pq, inpq, num_test_elements);
   }
   for (i = 0; i < num_test_elements; ++i) {
     /* Test that check still succeeds even for element that wasn't just
@@ -182,7 +116,7 @@ static void test1(void) {
 
   GPR_ASSERT(pq.timer_count == num_test_elements);
 
-  check_pq_top(test_elements, &pq, inpq, num_test_elements);
+  check_valid(&pq);
 
   for (i = 0; i < num_test_operations; ++i) {
     size_t elem_num = (size_t)rand() % num_test_elements;
@@ -193,14 +127,12 @@ static void test1(void) {
       grpc_timer_heap_add(&pq, el);
       GPR_ASSERT(contains(&pq, el));
       inpq[elem_num] = 1;
-      check_pq_top(test_elements, &pq, inpq, num_test_elements);
       check_valid(&pq);
     } else {
       GPR_ASSERT(contains(&pq, el));
       grpc_timer_heap_remove(&pq, el);
       GPR_ASSERT(!contains(&pq, el));
       inpq[elem_num] = 0;
-      check_pq_top(test_elements, &pq, inpq, num_test_elements);
       check_valid(&pq);
     }
   }
@@ -210,7 +142,108 @@ static void test1(void) {
   gpr_free(inpq);
 }
 
+/*******************************************************************************
+ * test2
+ */
+
+typedef struct {
+  grpc_timer elem;
+  bool inserted;
+} elem_struct;
+
+static elem_struct *search_elems(elem_struct *elems, size_t count,
+                                 bool inserted) {
+  size_t *search_order = gpr_malloc(count * sizeof(*search_order));
+  for (size_t i = 0; i < count; i++) {
+    search_order[i] = i;
+  }
+  for (size_t i = 0; i < count * 2; i++) {
+    size_t a = (size_t)rand() % count;
+    size_t b = (size_t)rand() % count;
+    GPR_SWAP(size_t, search_order[a], search_order[b]);
+  }
+  elem_struct *out = NULL;
+  for (size_t i = 0; out == NULL && i < count; i++) {
+    if (elems[search_order[i]].inserted == inserted) {
+      out = &elems[search_order[i]];
+    }
+  }
+  gpr_free(search_order);
+  return out;
+}
+
+static void test2(void) {
+  gpr_log(GPR_INFO, "test2");
+
+  grpc_timer_heap pq;
+
+  elem_struct elems[1000];
+  size_t num_inserted = 0;
+
+  grpc_timer_heap_init(&pq);
+  memset(elems, 0, sizeof(elems));
+
+  for (size_t round = 0; round < 10000; round++) {
+    int r = rand() % 1000;
+    if (r <= 550) {
+      /* 55% of the time we try to add something */
+      elem_struct *el = search_elems(elems, GPR_ARRAY_SIZE(elems), false);
+      if (el != NULL) {
+        el->elem.deadline = random_deadline();
+        grpc_timer_heap_add(&pq, &el->elem);
+        el->inserted = true;
+        num_inserted++;
+        check_valid(&pq);
+      }
+    } else if (r <= 650) {
+      /* 10% of the time we try to remove something */
+      elem_struct *el = search_elems(elems, GPR_ARRAY_SIZE(elems), true);
+      if (el != NULL) {
+        grpc_timer_heap_remove(&pq, &el->elem);
+        el->inserted = false;
+        num_inserted--;
+        check_valid(&pq);
+      }
+    } else {
+      /* the remaining times we pop */
+      if (num_inserted > 0) {
+        grpc_timer *top = grpc_timer_heap_top(&pq);
+        grpc_timer_heap_pop(&pq);
+        for (size_t i = 0; i < GPR_ARRAY_SIZE(elems); i++) {
+          if (top == &elems[i].elem) {
+            GPR_ASSERT(elems[i].inserted);
+            elems[i].inserted = false;
+          }
+        }
+        num_inserted--;
+        check_valid(&pq);
+      }
+    }
+
+    if (num_inserted) {
+      gpr_timespec *min_deadline = NULL;
+      for (size_t i = 0; i < GPR_ARRAY_SIZE(elems); i++) {
+        if (elems[i].inserted) {
+          if (min_deadline == NULL) {
+            min_deadline = &elems[i].elem.deadline;
+          } else {
+            if (gpr_time_cmp(elems[i].elem.deadline, *min_deadline) < 0) {
+              min_deadline = &elems[i].elem.deadline;
+            }
+          }
+        }
+      }
+      GPR_ASSERT(
+          0 == gpr_time_cmp(grpc_timer_heap_top(&pq)->deadline, *min_deadline));
+    }
+  }
+
+  grpc_timer_heap_destroy(&pq);
+}
+
 static void shrink_test(void) {
+  gpr_log(GPR_INFO, "shrink_test");
+
   grpc_timer_heap pq;
   size_t i;
   size_t expected_size;
@@ -274,6 +307,7 @@ int main(int argc, char **argv) {
 
   for (i = 0; i < 5; i++) {
     test1();
+    test2();
     shrink_test();
   }
 
diff --git a/test/core/iomgr/timer_list_test.c b/test/core/iomgr/timer_list_test.c
index 15de87c5a1a4452ea57eb98350e8033f4df42ba4..7a21fdd5c1084bb6c69475b07624974401589256 100644
--- a/test/core/iomgr/timer_list_test.c
+++ b/test/core/iomgr/timer_list_test.c
@@ -35,7 +35,6 @@
 
 #include <string.h>
 
-#include "src/core/iomgr/timer_internal.h"
 #include <grpc/support/log.h>
 #include "test/core/util/test_config.h"
 
@@ -72,20 +71,19 @@ static void add_test(void) {
   }
 
   /* collect timers.  Only the first batch should be ready. */
-  GPR_ASSERT(10 == grpc_timer_check(&exec_ctx,
-                                    gpr_time_add(start, gpr_time_from_millis(
-                                                            500, GPR_TIMESPAN)),
-                                    NULL));
+  GPR_ASSERT(grpc_timer_check(
+      &exec_ctx, gpr_time_add(start, gpr_time_from_millis(500, GPR_TIMESPAN)),
+      NULL));
   grpc_exec_ctx_finish(&exec_ctx);
   for (i = 0; i < 20; i++) {
     GPR_ASSERT(cb_called[i][1] == (i < 10));
     GPR_ASSERT(cb_called[i][0] == 0);
   }
 
-  GPR_ASSERT(0 == grpc_timer_check(&exec_ctx,
-                                   gpr_time_add(start, gpr_time_from_millis(
-                                                           600, GPR_TIMESPAN)),
-                                   NULL));
+  GPR_ASSERT(!grpc_timer_check(
+                 &exec_ctx,
+                 gpr_time_add(start, gpr_time_from_millis(600, GPR_TIMESPAN)),
+                 NULL));
   grpc_exec_ctx_finish(&exec_ctx);
   for (i = 0; i < 30; i++) {
     GPR_ASSERT(cb_called[i][1] == (i < 10));
@@ -93,20 +91,19 @@ static void add_test(void) {
   }
 
   /* collect the rest of the timers */
-  GPR_ASSERT(10 == grpc_timer_check(
-                       &exec_ctx, gpr_time_add(start, gpr_time_from_millis(
-                                                          1500, GPR_TIMESPAN)),
-                       NULL));
+  GPR_ASSERT(grpc_timer_check(
+      &exec_ctx, gpr_time_add(start, gpr_time_from_millis(1500, GPR_TIMESPAN)),
+      NULL));
   grpc_exec_ctx_finish(&exec_ctx);
   for (i = 0; i < 30; i++) {
     GPR_ASSERT(cb_called[i][1] == (i < 20));
     GPR_ASSERT(cb_called[i][0] == 0);
   }
 
-  GPR_ASSERT(0 == grpc_timer_check(&exec_ctx,
-                                   gpr_time_add(start, gpr_time_from_millis(
-                                                           1600, GPR_TIMESPAN)),
-                                   NULL));
+  GPR_ASSERT(!grpc_timer_check(
+                 &exec_ctx,
+                 gpr_time_add(start, gpr_time_from_millis(1600, GPR_TIMESPAN)),
+                 NULL));
   for (i = 0; i < 30; i++) {
     GPR_ASSERT(cb_called[i][1] == (i < 20));
     GPR_ASSERT(cb_called[i][0] == 0);
diff --git a/test/core/iomgr/workqueue_test.c b/test/core/iomgr/workqueue_test.c
index 500170b542ca325ff1eb9eb4e1b667678df0e04c..8a1faf6303ef626d89b76bbf98a9db587279d284 100644
--- a/test/core/iomgr/workqueue_test.c
+++ b/test/core/iomgr/workqueue_test.c
@@ -34,18 +34,20 @@
 #include "src/core/iomgr/workqueue.h"
 
 #include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 
 #include "test/core/util/test_config.h"
 
-static grpc_pollset g_pollset;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
 
 static void must_succeed(grpc_exec_ctx *exec_ctx, void *p, bool success) {
   GPR_ASSERT(success == 1);
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   *(int *)p = 1;
-  grpc_pollset_kick(&g_pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_kick(g_pollset, NULL);
+  gpr_mu_unlock(g_mu);
 }
 
 static void test_ref_unref(void) {
@@ -63,17 +65,17 @@ static void test_add_closure(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_workqueue *wq = grpc_workqueue_create(&exec_ctx);
   gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
-  grpc_pollset_worker worker;
+  grpc_pollset_worker *worker = NULL;
   grpc_closure_init(&c, must_succeed, &done);
 
   grpc_workqueue_push(wq, &c, 1);
-  grpc_workqueue_add_to_pollset(&exec_ctx, wq, &g_pollset);
+  grpc_workqueue_add_to_pollset(&exec_ctx, wq, g_pollset);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   GPR_ASSERT(!done);
-  grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
-                    gpr_now(deadline.clock_type), deadline);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_work(&exec_ctx, g_pollset, &worker, gpr_now(deadline.clock_type),
+                    deadline);
+  gpr_mu_unlock(g_mu);
   grpc_exec_ctx_finish(&exec_ctx);
   GPR_ASSERT(done);
 
@@ -87,18 +89,18 @@ static void test_flush(void) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_workqueue *wq = grpc_workqueue_create(&exec_ctx);
   gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
-  grpc_pollset_worker worker;
+  grpc_pollset_worker *worker = NULL;
   grpc_closure_init(&c, must_succeed, &done);
 
   grpc_exec_ctx_enqueue(&exec_ctx, &c, true, NULL);
   grpc_workqueue_flush(&exec_ctx, wq);
-  grpc_workqueue_add_to_pollset(&exec_ctx, wq, &g_pollset);
+  grpc_workqueue_add_to_pollset(&exec_ctx, wq, g_pollset);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset));
+  gpr_mu_lock(g_mu);
   GPR_ASSERT(!done);
-  grpc_pollset_work(&exec_ctx, &g_pollset, &worker,
-                    gpr_now(deadline.clock_type), deadline);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset));
+  grpc_pollset_work(&exec_ctx, g_pollset, &worker, gpr_now(deadline.clock_type),
+                    deadline);
+  gpr_mu_unlock(g_mu);
   grpc_exec_ctx_finish(&exec_ctx);
   GPR_ASSERT(done);
 
@@ -115,15 +117,18 @@ int main(int argc, char **argv) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_test_init(argc, argv);
   grpc_init();
-  grpc_pollset_init(&g_pollset);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
 
   test_ref_unref();
   test_add_closure();
   test_flush();
 
-  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
+
+  gpr_free(g_pollset);
   return 0;
 }
diff --git a/test/core/security/base64_test.c b/test/core/security/b64_test.c
similarity index 99%
rename from test/core/security/base64_test.c
rename to test/core/security/b64_test.c
index e656d4c947f7de2511b94cbaaa9c1aeb914073a5..772514e1fdad166e0281a27eca0c22d4de19df4b 100644
--- a/test/core/security/base64_test.c
+++ b/test/core/security/b64_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
  *
  */
 
-#include "src/core/security/base64.h"
+#include "src/core/security/b64.h"
 
 #include <string.h>
 
diff --git a/test/core/security/create_jwt.c b/test/core/security/create_jwt.c
index 237dc9aa3e240192acface8ac71aa889d8c3ae26..4c0cf436eeb2ff2e46ed2eb95a9354d355a80c50 100644
--- a/test/core/security/create_jwt.c
+++ b/test/core/security/create_jwt.c
@@ -36,7 +36,7 @@
 
 #include "src/core/security/credentials.h"
 #include "src/core/security/json_token.h"
-#include "src/core/support/file.h"
+#include "src/core/support/load_file.h"
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/cmdline.h>
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index 8a210bb3c37868c905fe845ba49d4fd0d794baf1..98133ef5e5fc3519c83e20bf514849495bb2a7f9 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -32,25 +32,24 @@
  */
 
 #include <grpc/support/port_platform.h>
+
 #include "src/core/security/credentials.h"
 
+#include <openssl/rsa.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "src/core/httpcli/httpcli.h"
-#include "src/core/security/json_token.h"
-#include "src/core/support/env.h"
-#include "src/core/support/file.h"
-#include "src/core/support/string.h"
-
-#include "test/core/util/test_config.h"
-
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 #include <grpc/support/time.h>
 
-#include <openssl/rsa.h>
+#include "src/core/httpcli/httpcli.h"
+#include "src/core/security/json_token.h"
+#include "src/core/support/env.h"
+#include "src/core/support/tmpfile.h"
+#include "src/core/support/string.h"
+#include "test/core/util/test_config.h"
 
 /* -- Mock channel credentials. -- */
 
diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c
index ee1178cbddf1d74f75b28e4407c02f27fc83042b..87b54f1a0c3a871184371c8f7deca22976a56e59 100644
--- a/test/core/security/fetch_oauth2.c
+++ b/test/core/security/fetch_oauth2.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,7 @@
 #include <grpc/support/sync.h>
 
 #include "src/core/security/credentials.h"
-#include "src/core/support/file.h"
+#include "src/core/support/load_file.h"
 #include "test/core/security/oauth2_utils.h"
 
 static grpc_call_credentials *create_refresh_token_creds(
diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c
index 7c01a9ce5c9059821431be40d65c4fa0e047059e..4d80c16fb987577d617611d025361a252623bbdf 100644
--- a/test/core/security/json_token_test.c
+++ b/test/core/security/json_token_test.c
@@ -33,16 +33,17 @@
 
 #include "src/core/security/json_token.h"
 
+#include <openssl/evp.h>
 #include <string.h>
 
-#include "src/core/security/base64.h"
 #include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/slice.h>
-#include "test/core/util/test_config.h"
+
 #include "src/core/json/json.h"
-#include <openssl/evp.h>
+#include "src/core/security/b64.h"
+#include "test/core/util/test_config.h"
 
 /* This JSON key was generated with the GCE console and revoked immediately.
    The identifiers have been changed as well.
diff --git a/test/core/security/jwt_verifier_test.c b/test/core/security/jwt_verifier_test.c
index f396398cefb424852a3bdc8cc25c6b88cb97aa27..f6ec9e12ef37753d95817d3cb17889cf888e3f0f 100644
--- a/test/core/security/jwt_verifier_test.c
+++ b/test/core/security/jwt_verifier_test.c
@@ -36,7 +36,7 @@
 #include <string.h>
 
 #include "src/core/httpcli/httpcli.h"
-#include "src/core/security/base64.h"
+#include "src/core/security/b64.h"
 #include "src/core/security/json_token.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c
index 55ac31e62ca7915964b67af77ecc348d832a04e5..9b70afffe1eebd4a20db36ed76d151f8b70e1a40 100644
--- a/test/core/security/oauth2_utils.c
+++ b/test/core/security/oauth2_utils.c
@@ -45,7 +45,8 @@
 #include "src/core/security/credentials.h"
 
 typedef struct {
-  grpc_pollset pollset;
+  gpr_mu *mu;
+  grpc_pollset *pollset;
   int is_done;
   char *token;
 } oauth2_request;
@@ -66,11 +67,11 @@ static void on_oauth2_response(grpc_exec_ctx *exec_ctx, void *user_data,
            GPR_SLICE_LENGTH(token_slice));
     token[GPR_SLICE_LENGTH(token_slice)] = '\0';
   }
-  gpr_mu_lock(GRPC_POLLSET_MU(&request->pollset));
+  gpr_mu_lock(request->mu);
   request->is_done = 1;
   request->token = token;
-  grpc_pollset_kick(&request->pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&request->pollset));
+  grpc_pollset_kick(request->pollset, NULL);
+  gpr_mu_unlock(request->mu);
 }
 
 static void do_nothing(grpc_exec_ctx *exec_ctx, void *unused, bool success) {}
@@ -82,28 +83,30 @@ char *grpc_test_fetch_oauth2_token_with_credentials(
   grpc_closure do_nothing_closure;
   grpc_auth_metadata_context null_ctx = {"", "", NULL, NULL};
 
-  grpc_pollset_init(&request.pollset);
+  request.pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(request.pollset, &request.mu);
   request.is_done = 0;
 
   grpc_closure_init(&do_nothing_closure, do_nothing, NULL);
 
-  grpc_call_credentials_get_request_metadata(&exec_ctx, creds, &request.pollset,
+  grpc_call_credentials_get_request_metadata(&exec_ctx, creds, request.pollset,
                                              null_ctx, on_oauth2_response,
                                              &request);
 
   grpc_exec_ctx_finish(&exec_ctx);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&request.pollset));
+  gpr_mu_lock(request.mu);
   while (!request.is_done) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &request.pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, request.pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       gpr_inf_future(GPR_CLOCK_MONOTONIC));
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&request.pollset));
+  gpr_mu_unlock(request.mu);
 
-  grpc_pollset_shutdown(&exec_ctx, &request.pollset, &do_nothing_closure);
+  grpc_pollset_shutdown(&exec_ctx, request.pollset, &do_nothing_closure);
   grpc_exec_ctx_finish(&exec_ctx);
-  grpc_pollset_destroy(&request.pollset);
+  grpc_pollset_destroy(request.pollset);
+  gpr_free(request.pollset);
   return request.token;
 }
diff --git a/test/core/security/print_google_default_creds_token.c b/test/core/security/print_google_default_creds_token.c
index 50fe61c9969ed35198bcc4781f2b9a97471985a6..09673f362cfcc87bfba608688ae052c7517af734 100644
--- a/test/core/security/print_google_default_creds_token.c
+++ b/test/core/security/print_google_default_creds_token.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,8 +34,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/security/credentials.h"
-#include "src/core/support/string.h"
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
@@ -44,8 +42,12 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
+#include "src/core/security/credentials.h"
+#include "src/core/support/string.h"
+
 typedef struct {
-  grpc_pollset pollset;
+  gpr_mu *mu;
+  grpc_pollset *pollset;
   int is_done;
 } synchronizer;
 
@@ -62,10 +64,10 @@ static void on_metadata_response(grpc_exec_ctx *exec_ctx, void *user_data,
     printf("\nGot token: %s\n\n", token);
     gpr_free(token);
   }
-  gpr_mu_lock(GRPC_POLLSET_MU(&sync->pollset));
+  gpr_mu_lock(sync->mu);
   sync->is_done = 1;
-  grpc_pollset_kick(&sync->pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&sync->pollset));
+  grpc_pollset_kick(sync->pollset, NULL);
+  gpr_mu_unlock(sync->mu);
 }
 
 int main(int argc, char **argv) {
@@ -91,26 +93,30 @@ int main(int argc, char **argv) {
     goto end;
   }
 
-  grpc_pollset_init(&sync.pollset);
+  sync.pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(sync.pollset, &sync.mu);
   sync.is_done = 0;
 
   grpc_call_credentials_get_request_metadata(
       &exec_ctx, ((grpc_composite_channel_credentials *)creds)->call_creds,
-      &sync.pollset, context, on_metadata_response, &sync);
+      sync.pollset, context, on_metadata_response, &sync);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
+  gpr_mu_lock(sync.mu);
   while (!sync.is_done) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &sync.pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, sync.pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       gpr_inf_future(GPR_CLOCK_MONOTONIC));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&sync.pollset));
-    grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
+    gpr_mu_unlock(sync.mu);
+    grpc_exec_ctx_flush(&exec_ctx);
+    gpr_mu_lock(sync.mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&sync.pollset));
+  gpr_mu_unlock(sync.mu);
+
+  grpc_exec_ctx_finish(&exec_ctx);
 
   grpc_channel_credentials_release(creds);
+  gpr_free(sync.pollset);
 
 end:
   gpr_cmdline_destroy(cl);
diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c
index fb4bd30e2dfe4c9144ddabb7eb879447d2bd03c9..0e8c38a53ec3cf8795cf9029626ca969c12e55c5 100644
--- a/test/core/security/secure_endpoint_test.c
+++ b/test/core/security/secure_endpoint_test.c
@@ -36,16 +36,17 @@
 #include <fcntl.h>
 #include <sys/types.h>
 
-#include "src/core/security/secure_endpoint.h"
-#include "src/core/iomgr/endpoint_pair.h"
-#include "src/core/iomgr/iomgr.h"
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
-#include "test/core/util/test_config.h"
+#include "src/core/iomgr/endpoint_pair.h"
+#include "src/core/iomgr/iomgr.h"
+#include "src/core/security/secure_endpoint.h"
 #include "src/core/tsi/fake_transport_security.h"
+#include "test/core/util/test_config.h"
 
-static grpc_pollset g_pollset;
+static gpr_mu *g_mu;
+static grpc_pollset *g_pollset;
 
 static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair(
     size_t slice_size, gpr_slice *leftover_slices, size_t leftover_nslices) {
@@ -56,8 +57,8 @@ static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair(
   grpc_endpoint_pair tcp;
 
   tcp = grpc_iomgr_create_endpoint_pair("fixture", slice_size);
-  grpc_endpoint_add_to_pollset(&exec_ctx, tcp.client, &g_pollset);
-  grpc_endpoint_add_to_pollset(&exec_ctx, tcp.server, &g_pollset);
+  grpc_endpoint_add_to_pollset(&exec_ctx, tcp.client, g_pollset);
+  grpc_endpoint_add_to_pollset(&exec_ctx, tcp.server, g_pollset);
 
   if (leftover_nslices == 0) {
     f.client_ep =
@@ -181,13 +182,16 @@ int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
 
   grpc_init();
-  grpc_pollset_init(&g_pollset);
-  grpc_endpoint_tests(configs[0], &g_pollset);
+  g_pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(g_pollset, &g_mu);
+  grpc_endpoint_tests(configs[0], g_pollset, g_mu);
   test_leftover(configs[1], 1);
-  grpc_closure_init(&destroyed, destroy_pollset, &g_pollset);
-  grpc_pollset_shutdown(&exec_ctx, &g_pollset, &destroyed);
+  grpc_closure_init(&destroyed, destroy_pollset, g_pollset);
+  grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
   grpc_exec_ctx_finish(&exec_ctx);
   grpc_shutdown();
 
+  gpr_free(g_pollset);
+
   return 0;
 }
diff --git a/test/core/security/security_connector_test.c b/test/core/security/security_connector_test.c
index ee5435f01ddccf287fdc3beee8dc119216541742..420e3a4c525d6d6f38da66ad9866f70a91d013a7 100644
--- a/test/core/security/security_connector_test.c
+++ b/test/core/security/security_connector_test.c
@@ -34,22 +34,21 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
+
 #include "src/core/security/security_connector.h"
 #include "src/core/security/security_context.h"
 #include "src/core/support/env.h"
-#include "src/core/support/file.h"
+#include "src/core/support/tmpfile.h"
 #include "src/core/support/string.h"
 #include "src/core/tsi/ssl_transport_security.h"
 #include "src/core/tsi/transport_security.h"
 #include "test/core/util/test_config.h"
 
-#include <grpc/grpc_security.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
-
 static int check_transport_security_type(const grpc_auth_context *ctx) {
   grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
       ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME);
diff --git a/test/core/security/verify_jwt.c b/test/core/security/verify_jwt.c
index 378a37f26c5e0a692fe562a2a405a4a60ca068c4..eb86589681d12644dffa7c3a09f2fcbfd948cb1b 100644
--- a/test/core/security/verify_jwt.c
+++ b/test/core/security/verify_jwt.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/security/jwt_verifier.h"
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
@@ -43,8 +42,11 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
+#include "src/core/security/jwt_verifier.h"
+
 typedef struct {
-  grpc_pollset pollset;
+  grpc_pollset *pollset;
+  gpr_mu *mu;
   int is_done;
   int success;
 } synchronizer;
@@ -77,10 +79,10 @@ static void on_jwt_verification_done(void *user_data,
             grpc_jwt_verifier_status_to_string(status));
   }
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&sync->pollset));
+  gpr_mu_lock(sync->mu);
   sync->is_done = 1;
-  grpc_pollset_kick(&sync->pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&sync->pollset));
+  grpc_pollset_kick(sync->pollset, NULL);
+  gpr_mu_unlock(sync->mu);
 }
 
 int main(int argc, char **argv) {
@@ -103,23 +105,26 @@ int main(int argc, char **argv) {
 
   grpc_init();
 
-  grpc_pollset_init(&sync.pollset);
+  sync.pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(sync.pollset, &sync.mu);
   sync.is_done = 0;
 
-  grpc_jwt_verifier_verify(&exec_ctx, verifier, &sync.pollset, jwt, aud,
+  grpc_jwt_verifier_verify(&exec_ctx, verifier, sync.pollset, jwt, aud,
                            on_jwt_verification_done, &sync);
 
-  gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
+  gpr_mu_lock(sync.mu);
   while (!sync.is_done) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &sync.pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, sync.pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       gpr_inf_future(GPR_CLOCK_MONOTONIC));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&sync.pollset));
+    gpr_mu_unlock(sync.mu);
     grpc_exec_ctx_finish(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&sync.pollset));
+    gpr_mu_lock(sync.mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&sync.pollset));
+  gpr_mu_unlock(sync.mu);
+
+  gpr_free(sync.pollset);
 
   grpc_jwt_verifier_destroy(verifier);
   gpr_cmdline_destroy(cl);
diff --git a/test/core/support/file_test.c b/test/core/support/load_file_test.c
similarity index 97%
rename from test/core/support/file_test.c
rename to test/core/support/load_file_test.c
index 330b2173ef966f5a40531ce6f71020c38eb7dae9..e6ba6174400a0c2c2f7d3406fbb4a0ac0189bc9d 100644
--- a/test/core/support/file_test.c
+++ b/test/core/support/load_file_test.c
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,8 @@
 #include <grpc/support/log.h>
 #include <grpc/support/slice.h>
 
-#include "src/core/support/file.h"
+#include "src/core/support/load_file.h"
+#include "src/core/support/tmpfile.h"
 #include "src/core/support/string.h"
 #include "test/core/util/test_config.h"
 
diff --git a/test/core/util/port_posix.c b/test/core/util/port_posix.c
index 4b31f810e59a4b177da27e4025071461faf7eb29..ba382d242a36878448ce799611e204421eeb2920 100644
--- a/test/core/util/port_posix.c
+++ b/test/core/util/port_posix.c
@@ -69,7 +69,8 @@ static int has_port_been_chosen(int port) {
 }
 
 typedef struct freereq {
-  grpc_pollset pollset;
+  gpr_mu *mu;
+  grpc_pollset *pollset;
   int done;
 } freereq;
 
@@ -82,10 +83,10 @@ static void destroy_pollset_and_shutdown(grpc_exec_ctx *exec_ctx, void *p,
 static void freed_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
                                    const grpc_httpcli_response *response) {
   freereq *pr = arg;
-  gpr_mu_lock(GRPC_POLLSET_MU(&pr->pollset));
+  gpr_mu_lock(pr->mu);
   pr->done = 1;
-  grpc_pollset_kick(&pr->pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&pr->pollset));
+  grpc_pollset_kick(pr->pollset, NULL);
+  gpr_mu_unlock(pr->mu);
 }
 
 static void free_port_using_server(char *server, int port) {
@@ -100,31 +101,34 @@ static void free_port_using_server(char *server, int port) {
 
   memset(&pr, 0, sizeof(pr));
   memset(&req, 0, sizeof(req));
-  grpc_pollset_init(&pr.pollset);
+
+  pr.pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(pr.pollset, &pr.mu);
   grpc_closure_init(&shutdown_closure, destroy_pollset_and_shutdown,
-                    &pr.pollset);
+                    pr.pollset);
 
   req.host = server;
   gpr_asprintf(&path, "/drop/%d", port);
   req.path = path;
 
   grpc_httpcli_context_init(&context);
-  grpc_httpcli_get(&exec_ctx, &context, &pr.pollset, &req,
+  grpc_httpcli_get(&exec_ctx, &context, pr.pollset, &req,
                    GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), freed_port_from_server,
                    &pr);
-  gpr_mu_lock(GRPC_POLLSET_MU(&pr.pollset));
+  gpr_mu_lock(pr.mu);
   while (!pr.done) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &pr.pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, pr.pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&pr.pollset));
+  gpr_mu_unlock(pr.mu);
 
   grpc_httpcli_context_destroy(&context);
   grpc_exec_ctx_finish(&exec_ctx);
-  grpc_pollset_shutdown(&exec_ctx, &pr.pollset, &shutdown_closure);
+  grpc_pollset_shutdown(&exec_ctx, pr.pollset, &shutdown_closure);
   grpc_exec_ctx_finish(&exec_ctx);
+  gpr_free(pr.pollset);
   gpr_free(path);
 }
 
@@ -202,7 +206,8 @@ static int is_port_available(int *port, int is_tcp) {
 }
 
 typedef struct portreq {
-  grpc_pollset pollset;
+  gpr_mu *mu;
+  grpc_pollset *pollset;
   int port;
   int retries;
   char *server;
@@ -234,7 +239,7 @@ static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
     pr->retries++;
     req.host = pr->server;
     req.path = "/get";
-    grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pollset, &req,
+    grpc_httpcli_get(exec_ctx, pr->ctx, pr->pollset, &req,
                      GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server,
                      pr);
     return;
@@ -246,10 +251,10 @@ static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
     port = port * 10 + response->body[i] - '0';
   }
   GPR_ASSERT(port > 1024);
-  gpr_mu_lock(GRPC_POLLSET_MU(&pr->pollset));
+  gpr_mu_lock(pr->mu);
   pr->port = port;
-  grpc_pollset_kick(&pr->pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&pr->pollset));
+  grpc_pollset_kick(pr->pollset, NULL);
+  gpr_mu_unlock(pr->mu);
 }
 
 static int pick_port_using_server(char *server) {
@@ -263,9 +268,10 @@ static int pick_port_using_server(char *server) {
 
   memset(&pr, 0, sizeof(pr));
   memset(&req, 0, sizeof(req));
-  grpc_pollset_init(&pr.pollset);
+  pr.pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(pr.pollset, &pr.mu);
   grpc_closure_init(&shutdown_closure, destroy_pollset_and_shutdown,
-                    &pr.pollset);
+                    pr.pollset);
   pr.port = -1;
   pr.server = server;
   pr.ctx = &context;
@@ -274,22 +280,23 @@ static int pick_port_using_server(char *server) {
   req.path = "/get";
 
   grpc_httpcli_context_init(&context);
-  grpc_httpcli_get(&exec_ctx, &context, &pr.pollset, &req,
+  grpc_httpcli_get(&exec_ctx, &context, pr.pollset, &req,
                    GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server,
                    &pr);
   grpc_exec_ctx_finish(&exec_ctx);
-  gpr_mu_lock(GRPC_POLLSET_MU(&pr.pollset));
+  gpr_mu_lock(pr.mu);
   while (pr.port == -1) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &pr.pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, pr.pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&pr.pollset));
+  gpr_mu_unlock(pr.mu);
 
   grpc_httpcli_context_destroy(&context);
-  grpc_pollset_shutdown(&exec_ctx, &pr.pollset, &shutdown_closure);
+  grpc_pollset_shutdown(&exec_ctx, pr.pollset, &shutdown_closure);
   grpc_exec_ctx_finish(&exec_ctx);
+  gpr_free(pr.pollset);
 
   return pr.port;
 }
diff --git a/test/core/util/port_windows.c b/test/core/util/port_windows.c
index 85d7c0ce07764f9670c0943dd11d7ef70fa3db7a..3b20aeb71827906aac51d470fdad3964076766a6 100644
--- a/test/core/util/port_windows.c
+++ b/test/core/util/port_windows.c
@@ -129,7 +129,8 @@ static int is_port_available(int *port, int is_tcp) {
 }
 
 typedef struct portreq {
-  grpc_pollset pollset;
+  grpc_pollset *pollset;
+  gpr_mu *mu;
   int port;
 } portreq;
 
@@ -145,10 +146,10 @@ static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
     port = port * 10 + response->body[i] - '0';
   }
   GPR_ASSERT(port > 1024);
-  gpr_mu_lock(GRPC_POLLSET_MU(&pr->pollset));
+  gpr_mu_lock(pr->mu);
   pr->port = port;
-  grpc_pollset_kick(&pr->pollset, NULL);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&pr->pollset));
+  grpc_pollset_kick(pr->pollset, NULL);
+  gpr_mu_unlock(pr->mu);
 }
 
 static void destroy_pollset_and_shutdown(grpc_exec_ctx *exec_ctx, void *p,
@@ -168,32 +169,34 @@ static int pick_port_using_server(char *server) {
 
   memset(&pr, 0, sizeof(pr));
   memset(&req, 0, sizeof(req));
-  grpc_pollset_init(&pr.pollset);
+  pr.pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(pr.pollset, &pr.mu);
   pr.port = -1;
 
   req.host = server;
   req.path = "/get";
 
   grpc_httpcli_context_init(&context);
-  grpc_httpcli_get(&exec_ctx, &context, &pr.pollset, &req,
+  grpc_httpcli_get(&exec_ctx, &context, pr.pollset, &req,
                    GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server,
                    &pr);
-  gpr_mu_lock(GRPC_POLLSET_MU(&pr.pollset));
+  gpr_mu_lock(pr.mu);
   while (pr.port == -1) {
-    grpc_pollset_worker worker;
-    grpc_pollset_work(&exec_ctx, &pr.pollset, &worker,
+    grpc_pollset_worker *worker = NULL;
+    grpc_pollset_work(&exec_ctx, pr.pollset, &worker,
                       gpr_now(GPR_CLOCK_MONOTONIC),
                       GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1));
-    gpr_mu_unlock(GRPC_POLLSET_MU(&pr.pollset));
+    gpr_mu_unlock(pr.mu);
     grpc_exec_ctx_flush(&exec_ctx);
-    gpr_mu_lock(GRPC_POLLSET_MU(&pr.pollset));
+    gpr_mu_lock(pr.mu);
   }
-  gpr_mu_unlock(GRPC_POLLSET_MU(&pr.pollset));
+  gpr_mu_unlock(pr.mu);
 
   grpc_httpcli_context_destroy(&context);
   grpc_closure_init(&destroy_pollset_closure, destroy_pollset_and_shutdown,
                     &pr.pollset);
-  grpc_pollset_shutdown(&exec_ctx, &pr.pollset, &destroy_pollset_closure);
+  grpc_pollset_shutdown(&exec_ctx, pr.pollset, &destroy_pollset_closure);
+  gpr_free(pr.pollset);
 
   grpc_exec_ctx_finish(&exec_ctx);
   return pr.port;
diff --git a/test/core/util/test_tcp_server.c b/test/core/util/test_tcp_server.c
index 66470c028869f0d31f531bed1428265f82a1e495..ab379441d8c6c57f8437566db7278225ac6a7f4f 100644
--- a/test/core/util/test_tcp_server.c
+++ b/test/core/util/test_tcp_server.c
@@ -57,8 +57,8 @@ void test_tcp_server_init(test_tcp_server *server,
   server->tcp_server = NULL;
   grpc_closure_init(&server->shutdown_complete, on_server_destroyed, server);
   server->shutdown = 0;
-  grpc_pollset_init(&server->pollset);
-  server->pollsets[0] = &server->pollset;
+  server->pollset = gpr_malloc(grpc_pollset_size());
+  grpc_pollset_init(server->pollset, &server->mu);
   server->on_connect = on_connect;
   server->cb_data = user_data;
 }
@@ -77,7 +77,7 @@ void test_tcp_server_start(test_tcp_server *server, int port) {
       grpc_tcp_server_add_port(server->tcp_server, &addr, sizeof(addr));
   GPR_ASSERT(port_added == port);
 
-  grpc_tcp_server_start(&exec_ctx, server->tcp_server, server->pollsets, 1,
+  grpc_tcp_server_start(&exec_ctx, server->tcp_server, &server->pollset, 1,
                         server->on_connect, server->cb_data);
   gpr_log(GPR_INFO, "test tcp server listening on 0.0.0.0:%d", port);
 
@@ -85,15 +85,15 @@ void test_tcp_server_start(test_tcp_server *server, int port) {
 }
 
 void test_tcp_server_poll(test_tcp_server *server, int seconds) {
-  grpc_pollset_worker worker;
+  grpc_pollset_worker *worker = NULL;
   gpr_timespec deadline =
       gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
                    gpr_time_from_seconds(seconds, GPR_TIMESPAN));
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  gpr_mu_lock(GRPC_POLLSET_MU(&server->pollset));
-  grpc_pollset_work(&exec_ctx, &server->pollset, &worker,
+  gpr_mu_lock(server->mu);
+  grpc_pollset_work(&exec_ctx, server->pollset, &worker,
                     gpr_now(GPR_CLOCK_MONOTONIC), deadline);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&server->pollset));
+  gpr_mu_unlock(server->mu);
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
@@ -111,8 +111,9 @@ void test_tcp_server_destroy(test_tcp_server *server) {
          gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), shutdown_deadline) < 0) {
     test_tcp_server_poll(server, 1);
   }
-  grpc_pollset_shutdown(&exec_ctx, &server->pollset, &do_nothing_cb);
+  grpc_pollset_shutdown(&exec_ctx, server->pollset, &do_nothing_cb);
   grpc_exec_ctx_finish(&exec_ctx);
-  grpc_pollset_destroy(&server->pollset);
+  grpc_pollset_destroy(server->pollset);
+  gpr_free(server->pollset);
   grpc_shutdown();
 }
diff --git a/test/core/util/test_tcp_server.h b/test/core/util/test_tcp_server.h
index 51119cf6c80a8cef59f5d1792073a9817079771d..15fcb4fb873ab3ccf1be390966d8bf19f86ff79b 100644
--- a/test/core/util/test_tcp_server.h
+++ b/test/core/util/test_tcp_server.h
@@ -41,8 +41,8 @@ typedef struct test_tcp_server {
   grpc_tcp_server *tcp_server;
   grpc_closure shutdown_complete;
   int shutdown;
-  grpc_pollset pollset;
-  grpc_pollset *pollsets[1];
+  gpr_mu *mu;
+  grpc_pollset *pollset;
   grpc_tcp_server_cb on_connect;
   void *cb_data;
 } test_tcp_server;
diff --git a/test/cpp/common/alarm_cpp_test.cc b/test/cpp/common/alarm_cpp_test.cc
index 4745ef14ec7893765a137d13795331b11f6f27f8..d4381c051589cd1477d9e05bd7922daadbc76412 100644
--- a/test/cpp/common/alarm_cpp_test.cc
+++ b/test/cpp/common/alarm_cpp_test.cc
@@ -55,6 +55,53 @@ TEST(AlarmTest, RegularExpiry) {
   EXPECT_EQ(junk, output_tag);
 }
 
+TEST(AlarmTest, RegularExpiryChrono) {
+  CompletionQueue cq;
+  void* junk = reinterpret_cast<void*>(1618033);
+  std::chrono::system_clock::time_point one_sec_deadline =
+      std::chrono::system_clock::now() + std::chrono::seconds(1);
+  Alarm alarm(&cq, one_sec_deadline, junk);
+
+  void* output_tag;
+  bool ok;
+  const CompletionQueue::NextStatus status = cq.AsyncNext(
+      (void**)&output_tag, &ok, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(2));
+
+  EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
+  EXPECT_TRUE(ok);
+  EXPECT_EQ(junk, output_tag);
+}
+
+TEST(AlarmTest, ZeroExpiry) {
+  CompletionQueue cq;
+  void* junk = reinterpret_cast<void*>(1618033);
+  Alarm alarm(&cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(0), junk);
+
+  void* output_tag;
+  bool ok;
+  const CompletionQueue::NextStatus status = cq.AsyncNext(
+      (void**)&output_tag, &ok, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(0));
+
+  EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
+  EXPECT_TRUE(ok);
+  EXPECT_EQ(junk, output_tag);
+}
+
+TEST(AlarmTest, NegativeExpiry) {
+  CompletionQueue cq;
+  void* junk = reinterpret_cast<void*>(1618033);
+  Alarm alarm(&cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(-1), junk);
+
+  void* output_tag;
+  bool ok;
+  const CompletionQueue::NextStatus status = cq.AsyncNext(
+      (void**)&output_tag, &ok, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(0));
+
+  EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
+  EXPECT_TRUE(ok);
+  EXPECT_EQ(junk, output_tag);
+}
+
 TEST(AlarmTest, Cancellation) {
   CompletionQueue cq;
   void* junk = reinterpret_cast<void*>(1618033);
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index a15cbd7ee2ec21edc7c98738616da27a896cb8a3..9ca3bf98f85c470abda4ef0482c0e16acac6922c 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -989,6 +989,10 @@ class AsyncEnd2endServerTryCancelTest : public AsyncEnd2endTest {
 
     if (server_try_cancel == CANCEL_AFTER_PROCESSING) {
       ServerTryCancel(&srv_ctx);
+
+      // Client reads may fail bacause it is notified that the stream is
+      // cancelled.
+      ignore_cq_result = true;
     }
 
     // Client attemts to read the three messages from the server
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index ce8e4d2a109762ac28c70135bfdd4200debda87f..dc2c4f6426ff48afae8d953d5b5691b95509ec85 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -437,9 +437,10 @@ class End2endServerTryCancelTest : public End2endTest {
         break;
 
       case CANCEL_AFTER_PROCESSING:
-        // Server cancelled after writing all messages. Client must have read
-        // all messages
-        EXPECT_EQ(num_msgs_read, kNumResponseStreamsMsgs);
+        // Even though the Server cancelled after writing all messages, the RPC
+        // may be cancelled before the Client got a chance to read all the
+        // messages.
+        EXPECT_LE(num_msgs_read, kNumResponseStreamsMsgs);
         break;
 
       default: {
@@ -519,7 +520,11 @@ class End2endServerTryCancelTest : public End2endTest {
 
       case CANCEL_AFTER_PROCESSING:
         EXPECT_EQ(num_msgs_sent, num_messages);
-        EXPECT_EQ(num_msgs_read, num_msgs_sent);
+
+        // The Server cancelled after reading the last message and after writing
+        // the message to the client. However, the RPC cancellation might have
+        // taken effect before the client actually read the response.
+        EXPECT_LE(num_msgs_read, num_msgs_sent);
         break;
 
       default:
@@ -904,9 +909,9 @@ TEST_P(End2endTest, SimultaneousReadWritesDone) {
   std::thread reader_thread(ReaderThreadFunc, stream.get(), &ev);
   gpr_event_wait(&ev, gpr_inf_future(GPR_CLOCK_REALTIME));
   stream->WritesDone();
+  reader_thread.join();
   Status s = stream->Finish();
   EXPECT_TRUE(s.ok());
-  reader_thread.join();
 }
 
 TEST_P(End2endTest, ChannelState) {
diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc
index 66d11d0dfcee1ef713d97954f63ad02c8a67e170..7c3e514effa5c31f8112cceb81e3d3943b10e6e3 100644
--- a/test/cpp/end2end/test_service_impl.cc
+++ b/test/cpp/end2end/test_service_impl.cc
@@ -326,7 +326,11 @@ void TestServiceImpl::ServerTryCancel(ServerContext* context) {
   EXPECT_FALSE(context->IsCancelled());
   context->TryCancel();
   gpr_log(GPR_INFO, "Server called TryCancel() to cancel the request");
-  EXPECT_TRUE(context->IsCancelled());
+  // Now wait until it's really canceled
+  while (!context->IsCancelled()) {
+    gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                                 gpr_time_from_micros(1000, GPR_TIMESPAN)));
+  }
 }
 
 }  // namespace testing
diff --git a/test/cpp/grpclb/grpclb_api_test.cc b/test/cpp/grpclb/grpclb_api_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bd4885fb4cd3659e2e0d85d6b263eb767f0ece6c
--- /dev/null
+++ b/test/cpp/grpclb/grpclb_api_test.cc
@@ -0,0 +1,133 @@
+/*
+ *
+ * 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 <gtest/gtest.h>
+#include <string>
+
+#include "src/core/client_config/lb_policies/load_balancer_api.h"
+#include "src/proto/grpc/lb/v0/load_balancer.pb.h"  // C++ version
+
+namespace grpc {
+namespace {
+
+using grpc::lb::v0::LoadBalanceRequest;
+using grpc::lb::v0::LoadBalanceResponse;
+
+class GrpclbTest : public ::testing::Test {};
+
+TEST_F(GrpclbTest, CreateRequest) {
+  const std::string service_name = "AServiceName";
+  LoadBalanceRequest request;
+  grpc_grpclb_request* c_req = grpc_grpclb_request_create(service_name.c_str());
+  gpr_slice slice = grpc_grpclb_request_encode(c_req);
+  const int num_bytes_written = GPR_SLICE_LENGTH(slice);
+  EXPECT_GT(num_bytes_written, 0);
+  request.ParseFromArray(GPR_SLICE_START_PTR(slice), num_bytes_written);
+  EXPECT_EQ(request.initial_request().name(), service_name);
+  gpr_slice_unref(slice);
+  grpc_grpclb_request_destroy(c_req);
+}
+
+TEST_F(GrpclbTest, ParseResponse) {
+  LoadBalanceResponse response;
+  const std::string client_config_str = "I'm a client config";
+  auto* initial_response = response.mutable_initial_response();
+  initial_response->set_client_config(client_config_str);
+  auto* client_stats_report_interval =
+      initial_response->mutable_client_stats_report_interval();
+  client_stats_report_interval->set_seconds(123);
+  client_stats_report_interval->set_nanos(456);
+
+  const std::string encoded_response = response.SerializeAsString();
+  gpr_slice encoded_slice =
+      gpr_slice_from_copied_string(encoded_response.c_str());
+  grpc_grpclb_response* c_response = grpc_grpclb_response_parse(encoded_slice);
+  EXPECT_TRUE(c_response->has_initial_response);
+  EXPECT_TRUE(c_response->initial_response.has_client_config);
+  EXPECT_FALSE(c_response->initial_response.has_load_balancer_delegate);
+  EXPECT_TRUE(strcmp(c_response->initial_response.client_config,
+                     client_config_str.c_str()) == 0);
+  EXPECT_EQ(c_response->initial_response.client_stats_report_interval.seconds,
+            123);
+  EXPECT_EQ(c_response->initial_response.client_stats_report_interval.nanos,
+            456);
+  gpr_slice_unref(encoded_slice);
+  grpc_grpclb_response_destroy(c_response);
+}
+
+TEST_F(GrpclbTest, ParseResponseServerList) {
+  LoadBalanceResponse response;
+  auto* serverlist = response.mutable_server_list();
+  auto* server = serverlist->add_servers();
+  server->set_ip_address("127.0.0.1");
+  server->set_port(12345);
+  server->set_drop_request(true);
+  server = response.mutable_server_list()->add_servers();
+  server->set_ip_address("10.0.0.1");
+  server->set_port(54321);
+  server->set_drop_request(false);
+  auto* expiration_interval = serverlist->mutable_expiration_interval();
+  expiration_interval->set_seconds(888);
+  expiration_interval->set_nanos(999);
+
+  const std::string encoded_response = response.SerializeAsString();
+  gpr_slice encoded_slice =
+      gpr_slice_from_copied_string(encoded_response.c_str());
+  grpc_grpclb_serverlist* c_serverlist =
+      grpc_grpclb_response_parse_serverlist(encoded_slice);
+  ASSERT_EQ(c_serverlist->num_servers, 2ul);
+  EXPECT_TRUE(c_serverlist->servers[0]->has_ip_address);
+  EXPECT_TRUE(strcmp(c_serverlist->servers[0]->ip_address, "127.0.0.1") == 0);
+  EXPECT_EQ(c_serverlist->servers[0]->port, 12345);
+  EXPECT_TRUE(c_serverlist->servers[0]->drop_request);
+  EXPECT_TRUE(c_serverlist->servers[1]->has_ip_address);
+  EXPECT_TRUE(strcmp(c_serverlist->servers[1]->ip_address, "10.0.0.1") == 0);
+  EXPECT_EQ(c_serverlist->servers[1]->port, 54321);
+  EXPECT_FALSE(c_serverlist->servers[1]->drop_request);
+
+  EXPECT_TRUE(c_serverlist->expiration_interval.has_seconds);
+  EXPECT_EQ(c_serverlist->expiration_interval.seconds, 888);
+  EXPECT_TRUE(c_serverlist->expiration_interval.has_nanos);
+  EXPECT_EQ(c_serverlist->expiration_interval.nanos, 999);
+
+  gpr_slice_unref(encoded_slice);
+  grpc_grpclb_destroy_serverlist(c_serverlist);
+}
+
+}  // namespace
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/interop/metrics_client.cc b/test/cpp/interop/metrics_client.cc
index 0c140ffd85ea42c90cc0db97f1bf55f4ce07ec94..bd48c7d4ef2b9d564cc295ae8ad08139a3fba213 100644
--- a/test/cpp/interop/metrics_client.cc
+++ b/test/cpp/interop/metrics_client.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,39 +37,45 @@
 #include <gflags/gflags.h>
 #include <grpc++/grpc++.h>
 
-#include "test/cpp/util/metrics_server.h"
-#include "test/cpp/util/test_config.h"
 #include "src/proto/grpc/testing/metrics.grpc.pb.h"
 #include "src/proto/grpc/testing/metrics.pb.h"
+#include "test/cpp/util/metrics_server.h"
+#include "test/cpp/util/test_config.h"
 
 DEFINE_string(metrics_server_address, "",
               "The metrics server addresses in the fomrat <hostname>:<port>");
+DEFINE_bool(total_only, false,
+            "If true, this prints only the total value of all gauges");
+
+int kDeadlineSecs = 10;
 
 using grpc::testing::EmptyMessage;
 using grpc::testing::GaugeResponse;
 using grpc::testing::MetricsService;
 using grpc::testing::MetricsServiceImpl;
 
-void PrintMetrics(const grpc::string& server_address) {
-  gpr_log(GPR_INFO, "creating a channel to %s", server_address.c_str());
-  std::shared_ptr<grpc::Channel> channel(
-      grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials()));
-
-  std::unique_ptr<MetricsService::Stub> stub(MetricsService::NewStub(channel));
-
+// Prints the values of all Gauges (unless total_only is set to 'true' in which
+// case this only prints the sum of all gauge values).
+bool PrintMetrics(std::unique_ptr<MetricsService::Stub> stub, bool total_only) {
   grpc::ClientContext context;
   EmptyMessage message;
 
+  std::chrono::system_clock::time_point deadline =
+      std::chrono::system_clock::now() + std::chrono::seconds(kDeadlineSecs);
+
+  context.set_deadline(deadline);
+
   std::unique_ptr<grpc::ClientReader<GaugeResponse>> reader(
       stub->GetAllGauges(&context, message));
 
   GaugeResponse gauge_response;
   long overall_qps = 0;
-  int idx = 0;
   while (reader->Read(&gauge_response)) {
     if (gauge_response.value_case() == GaugeResponse::kLongValue) {
-      gpr_log(GPR_INFO, "Gauge: %d (%s: %ld)", ++idx,
-              gauge_response.name().c_str(), gauge_response.long_value());
+      if (!total_only) {
+        gpr_log(GPR_INFO, "%s: %ld", gauge_response.name().c_str(),
+                gauge_response.long_value());
+      }
       overall_qps += gauge_response.long_value();
     } else {
       gpr_log(GPR_INFO, "Gauge %s is not a long value",
@@ -77,12 +83,14 @@ void PrintMetrics(const grpc::string& server_address) {
     }
   }
 
-  gpr_log(GPR_INFO, "OVERALL: %ld", overall_qps);
+  gpr_log(GPR_INFO, "%ld", overall_qps);
 
   const grpc::Status status = reader->Finish();
   if (!status.ok()) {
     gpr_log(GPR_ERROR, "Error in getting metrics from the client");
   }
+
+  return status.ok();
 }
 
 int main(int argc, char** argv) {
@@ -97,7 +105,12 @@ int main(int argc, char** argv) {
     return 1;
   }
 
-  PrintMetrics(FLAGS_metrics_server_address);
+  std::shared_ptr<grpc::Channel> channel(grpc::CreateChannel(
+      FLAGS_metrics_server_address, grpc::InsecureChannelCredentials()));
+
+  if (!PrintMetrics(MetricsService::NewStub(channel), FLAGS_total_only)) {
+    return 1;
+  }
 
   return 0;
 }
diff --git a/test/cpp/interop/reconnect_interop_client.cc b/test/cpp/interop/reconnect_interop_client.cc
index 1f6b352db17470a9910a4e96dc574849abbfe851..79a60cc8602f714983d0d421a53d391db3199147 100644
--- a/test/cpp/interop/reconnect_interop_client.cc
+++ b/test/cpp/interop/reconnect_interop_client.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server_main.cc
similarity index 100%
rename from test/cpp/interop/server.cc
rename to test/cpp/interop/server_main.cc
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index c94a523fa101e7d4154a2a138583873239d01d1d..2dc83f0f29292a0042201300b5fb26f1f16562e9 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -46,10 +46,10 @@
 #include "src/proto/grpc/testing/payloads.grpc.pb.h"
 #include "src/proto/grpc/testing/services.grpc.pb.h"
 
-#include "test/cpp/qps/limit_cores.h"
 #include "test/cpp/qps/histogram.h"
 #include "test/cpp/qps/interarrival.h"
-#include "test/cpp/qps/timer.h"
+#include "test/cpp/qps/limit_cores.h"
+#include "test/cpp/qps/usage_timer.h"
 #include "test/cpp/util/create_test_channel.h"
 
 namespace grpc {
@@ -112,12 +112,12 @@ class ClientRequestCreator<ByteBuffer> {
 
 class Client {
  public:
-  Client() : timer_(new Timer), interarrival_timer_() {}
+  Client() : timer_(new UsageTimer), interarrival_timer_() {}
   virtual ~Client() {}
 
   ClientStats Mark(bool reset) {
     Histogram latencies;
-    Timer::Result timer_result;
+    UsageTimer::Result timer_result;
 
     // avoid std::vector for old compilers that expect a copy constructor
     if (reset) {
@@ -125,7 +125,7 @@ class Client {
       for (size_t i = 0; i < threads_.size(); i++) {
         threads_[i]->BeginSwap(&to_merge[i]);
       }
-      std::unique_ptr<Timer> timer(new Timer);
+      std::unique_ptr<UsageTimer> timer(new UsageTimer);
       timer_.swap(timer);
       for (size_t i = 0; i < threads_.size(); i++) {
         threads_[i]->EndSwap();
@@ -294,7 +294,7 @@ class Client {
   };
 
   std::vector<std::unique_ptr<Thread>> threads_;
-  std::unique_ptr<Timer> timer_;
+  std::unique_ptr<UsageTimer> timer_;
 
   InterarrivalTimer interarrival_timer_;
   std::vector<gpr_timespec> next_time_;
diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc
index 9e8767d10338c0282ae726e5f714ff2901ed60e2..9e9da9909af54512ab75adc358d753b9fb4b3d5d 100644
--- a/test/cpp/qps/client_async.cc
+++ b/test/cpp/qps/client_async.cc
@@ -54,7 +54,7 @@
 
 #include "src/proto/grpc/testing/services.grpc.pb.h"
 #include "test/cpp/qps/client.h"
-#include "test/cpp/qps/timer.h"
+#include "test/cpp/qps/usage_timer.h"
 #include "test/cpp/util/create_test_channel.h"
 
 namespace grpc {
@@ -107,14 +107,14 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext {
   bool RunNextState(bool ok, Histogram* hist) GRPC_OVERRIDE {
     switch (next_state_) {
       case State::READY:
-        start_ = Timer::Now();
+        start_ = UsageTimer::Now();
         response_reader_ = start_req_(stub_, &context_, req_, cq_);
         response_reader_->Finish(&response_, &status_,
                                  ClientRpcContext::tag(this));
         next_state_ = State::RESP_DONE;
         return true;
       case State::RESP_DONE:
-        hist->Add((Timer::Now() - start_) * 1e9);
+        hist->Add((UsageTimer::Now() - start_) * 1e9);
         callback_(status_, &response_);
         next_state_ = State::INVALID;
         return false;
@@ -287,8 +287,7 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext {
         next_state_(State::INVALID),
         callback_(on_done),
         next_issue_(next_issue),
-        start_req_(start_req),
-        start_(Timer::Now()) {}
+        start_req_(start_req) {}
   ~ClientRpcContextStreamingImpl() GRPC_OVERRIDE {}
   void Start(CompletionQueue* cq) GRPC_OVERRIDE {
     cq_ = cq;
@@ -314,7 +313,7 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext {
           if (!ok) {
             return false;
           }
-          start_ = Timer::Now();
+          start_ = UsageTimer::Now();
           next_state_ = State::WRITE_DONE;
           stream_->Write(req_, ClientRpcContext::tag(this));
           return true;
@@ -327,7 +326,7 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext {
           return true;
           break;
         case State::READ_DONE:
-          hist->Add((Timer::Now() - start_) * 1e9);
+          hist->Add((UsageTimer::Now() - start_) * 1e9);
           callback_(status_, &response_);
           next_state_ = State::STREAM_IDLE;
           break;  // loop around
@@ -415,8 +414,7 @@ class ClientRpcContextGenericStreamingImpl : public ClientRpcContext {
         next_state_(State::INVALID),
         callback_(on_done),
         next_issue_(next_issue),
-        start_req_(start_req),
-        start_(Timer::Now()) {}
+        start_req_(start_req) {}
   ~ClientRpcContextGenericStreamingImpl() GRPC_OVERRIDE {}
   void Start(CompletionQueue* cq) GRPC_OVERRIDE {
     cq_ = cq;
@@ -445,7 +443,7 @@ class ClientRpcContextGenericStreamingImpl : public ClientRpcContext {
           if (!ok) {
             return false;
           }
-          start_ = Timer::Now();
+          start_ = UsageTimer::Now();
           next_state_ = State::WRITE_DONE;
           stream_->Write(req_, ClientRpcContext::tag(this));
           return true;
@@ -458,7 +456,7 @@ class ClientRpcContextGenericStreamingImpl : public ClientRpcContext {
           return true;
           break;
         case State::READ_DONE:
-          hist->Add((Timer::Now() - start_) * 1e9);
+          hist->Add((UsageTimer::Now() - start_) * 1e9);
           callback_(status_, &response_);
           next_state_ = State::STREAM_IDLE;
           break;  // loop around
diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc
index edfc246a25668c4483b0e39ea6fb3d2b86349871..4284e07bd4ca109ac62ef2e15fb1b41ad6e22135 100644
--- a/test/cpp/qps/client_sync.cc
+++ b/test/cpp/qps/client_sync.cc
@@ -58,7 +58,7 @@
 #include "test/cpp/qps/client.h"
 #include "test/cpp/qps/histogram.h"
 #include "test/cpp/qps/interarrival.h"
-#include "test/cpp/qps/timer.h"
+#include "test/cpp/qps/usage_timer.h"
 
 namespace grpc {
 namespace testing {
@@ -104,12 +104,12 @@ class SynchronousUnaryClient GRPC_FINAL : public SynchronousClient {
   bool ThreadFunc(Histogram* histogram, size_t thread_idx) GRPC_OVERRIDE {
     WaitToIssue(thread_idx);
     auto* stub = channels_[thread_idx % channels_.size()].get_stub();
-    double start = Timer::Now();
+    double start = UsageTimer::Now();
     GPR_TIMER_SCOPE("SynchronousUnaryClient::ThreadFunc", 0);
     grpc::ClientContext context;
     grpc::Status s =
         stub->UnaryCall(&context, request_, &responses_[thread_idx]);
-    histogram->Add((Timer::Now() - start) * 1e9);
+    histogram->Add((UsageTimer::Now() - start) * 1e9);
     return s.ok();
   }
 };
@@ -143,10 +143,10 @@ class SynchronousStreamingClient GRPC_FINAL : public SynchronousClient {
   bool ThreadFunc(Histogram* histogram, size_t thread_idx) GRPC_OVERRIDE {
     WaitToIssue(thread_idx);
     GPR_TIMER_SCOPE("SynchronousStreamingClient::ThreadFunc", 0);
-    double start = Timer::Now();
+    double start = UsageTimer::Now();
     if (stream_[thread_idx]->Write(request_) &&
         stream_[thread_idx]->Read(&responses_[thread_idx])) {
-      histogram->Add((Timer::Now() - start) * 1e9);
+      histogram->Add((UsageTimer::Now() - start) * 1e9);
       return true;
     }
     return false;
diff --git a/test/cpp/qps/qps-sweep.sh b/test/cpp/qps/qps-sweep.sh
index 7a357888497aadc899bb40618aefeb8384471118..9d3f053a7bee3847ccecbe580cce0544d5852d66 100755
--- a/test/cpp/qps/qps-sweep.sh
+++ b/test/cpp/qps/qps-sweep.sh
@@ -72,7 +72,7 @@ for secure in true false; do
     --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \
     --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \
     --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \
-    --num_servers=1 --num_clients=0 |& tee /tmp/qps-test.$$
+    --num_servers=1 --num_clients=0 2>&1 | tee /tmp/qps-test.$$
 
   # Scenario 2b: QPS with a single server core
   "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \
diff --git a/test/cpp/qps/qps_openloop_test.cc b/test/cpp/qps/qps_openloop_test.cc
index 0ac41d9f96337f7188c09195b2a35a0ec4629221..27f266b32be56f7bc2d72364b9e9b6a6ce9c2bde 100644
--- a/test/cpp/qps/qps_openloop_test.cc
+++ b/test/cpp/qps/qps_openloop_test.cc
@@ -35,6 +35,7 @@
 
 #include <grpc/support/log.h>
 
+#include "test/core/util/test_config.h"
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/report.h"
 #include "test/cpp/util/benchmark_config.h"
@@ -55,11 +56,11 @@ static void RunQPS() {
   client_config.set_async_client_threads(8);
   client_config.set_rpc_type(STREAMING);
   client_config.mutable_load_params()->mutable_poisson()->set_offered_load(
-      1000.0);
+      1000.0 / GRPC_TEST_SLOWDOWN_FACTOR);
 
   ServerConfig server_config;
   server_config.set_server_type(ASYNC_SERVER);
-  server_config.set_async_server_threads(4);
+  server_config.set_async_server_threads(8);
 
   const auto result =
       RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK, -2);
diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc
index 9442017ddf525bb3ecb886a90925dd2fa9587c2c..b83e9d1dd7f0337620b7a44ee8bc0cf913726a6e 100644
--- a/test/cpp/qps/qps_worker.cc
+++ b/test/cpp/qps/qps_worker.cc
@@ -101,6 +101,19 @@ static std::unique_ptr<Server> CreateServer(const ServerConfig& config) {
   abort();
 }
 
+class ScopedProfile GRPC_FINAL {
+ public:
+  ScopedProfile(const char* filename, bool enable) : enable_(enable) {
+    if (enable_) grpc_profiler_start(filename);
+  }
+  ~ScopedProfile() {
+    if (enable_) grpc_profiler_stop();
+  }
+
+ private:
+  const bool enable_;
+};
+
 class WorkerServiceImpl GRPC_FINAL : public WorkerService::Service {
  public:
   WorkerServiceImpl(int server_port, QpsWorker* worker)
@@ -114,9 +127,8 @@ class WorkerServiceImpl GRPC_FINAL : public WorkerService::Service {
       return Status(StatusCode::RESOURCE_EXHAUSTED, "");
     }
 
-    grpc_profiler_start("qps_client.prof");
+    ScopedProfile profile("qps_client.prof", false);
     Status ret = RunClientBody(ctx, stream);
-    grpc_profiler_stop();
     return ret;
   }
 
@@ -128,9 +140,8 @@ class WorkerServiceImpl GRPC_FINAL : public WorkerService::Service {
       return Status(StatusCode::RESOURCE_EXHAUSTED, "");
     }
 
-    grpc_profiler_start("qps_server.prof");
+    ScopedProfile profile("qps_server.prof", false);
     Status ret = RunServerBody(ctx, stream);
-    grpc_profiler_stop();
     return ret;
   }
 
diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h
index 94a6f8acfab9a99ab40d9eae92aec3c8f4bbbeff..de46452c3d8eb0161563abd8a41d305e3b108eb2 100644
--- a/test/cpp/qps/server.h
+++ b/test/cpp/qps/server.h
@@ -43,14 +43,14 @@
 #include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/util/port.h"
 #include "test/cpp/qps/limit_cores.h"
-#include "test/cpp/qps/timer.h"
+#include "test/cpp/qps/usage_timer.h"
 
 namespace grpc {
 namespace testing {
 
 class Server {
  public:
-  explicit Server(const ServerConfig& config) : timer_(new Timer) {
+  explicit Server(const ServerConfig& config) : timer_(new UsageTimer) {
     cores_ = LimitCores(config.core_list().data(), config.core_list_size());
     if (config.port()) {
       port_ = config.port();
@@ -62,9 +62,9 @@ class Server {
   virtual ~Server() {}
 
   ServerStats Mark(bool reset) {
-    Timer::Result timer_result;
+    UsageTimer::Result timer_result;
     if (reset) {
-      std::unique_ptr<Timer> timer(new Timer);
+      std::unique_ptr<UsageTimer> timer(new UsageTimer);
       timer.swap(timer_);
       timer_result = timer->Mark();
     } else {
@@ -108,7 +108,7 @@ class Server {
  private:
   int port_;
   int cores_;
-  std::unique_ptr<Timer> timer_;
+  std::unique_ptr<UsageTimer> timer_;
 };
 
 std::unique_ptr<Server> CreateSynchronousServer(const ServerConfig& config);
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index 4b778820d070436eda157cef5ca64f065d54f167..b7682f57635196226d2d4d46d016e386bc81d5af 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -34,18 +34,18 @@
 #include <thread>
 
 #include <gflags/gflags.h>
+#include <grpc++/security/server_credentials.h>
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+#include <grpc++/server_context.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
-#include <grpc++/server.h>
-#include <grpc++/server_builder.h>
-#include <grpc++/server_context.h>
-#include <grpc++/security/server_credentials.h>
 
-#include "test/cpp/qps/server.h"
-#include "test/cpp/qps/timer.h"
 #include "src/proto/grpc/testing/services.grpc.pb.h"
+#include "test/cpp/qps/server.h"
+#include "test/cpp/qps/usage_timer.h"
 
 namespace grpc {
 namespace testing {
diff --git a/test/cpp/qps/timer.cc b/test/cpp/qps/usage_timer.cc
similarity index 90%
rename from test/cpp/qps/timer.cc
rename to test/cpp/qps/usage_timer.cc
index 3ec7f49f8321d80b35b7195f7f3b4b12f06aa867..6663a9ac1036b65727dadaf491bd5823b03626ff 100644
--- a/test/cpp/qps/timer.cc
+++ b/test/cpp/qps/usage_timer.cc
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,15 +31,15 @@
  *
  */
 
-#include "test/cpp/qps/timer.h"
+#include "test/cpp/qps/usage_timer.h"
 
-#include <sys/time.h>
-#include <sys/resource.h>
 #include <grpc/support/time.h>
+#include <sys/resource.h>
+#include <sys/time.h>
 
-Timer::Timer() : start_(Sample()) {}
+UsageTimer::UsageTimer() : start_(Sample()) {}
 
-double Timer::Now() {
+double UsageTimer::Now() {
   auto ts = gpr_now(GPR_CLOCK_REALTIME);
   return ts.tv_sec + 1e-9 * ts.tv_nsec;
 }
@@ -48,7 +48,7 @@ static double time_double(struct timeval* tv) {
   return tv->tv_sec + 1e-6 * tv->tv_usec;
 }
 
-Timer::Result Timer::Sample() {
+UsageTimer::Result UsageTimer::Sample() {
   struct rusage usage;
   struct timeval tv;
   gettimeofday(&tv, NULL);
@@ -61,7 +61,7 @@ Timer::Result Timer::Sample() {
   return r;
 }
 
-Timer::Result Timer::Mark() const {
+UsageTimer::Result UsageTimer::Mark() const {
   Result s = Sample();
   Result r;
   r.wall = s.wall - start_.wall;
diff --git a/test/cpp/qps/timer.h b/test/cpp/qps/usage_timer.h
similarity index 93%
rename from test/cpp/qps/timer.h
rename to test/cpp/qps/usage_timer.h
index d1aee1a9d199ecb897eb91fae6657cbee6fdbcec..d19f8205649e0ef6db6844c8b646e852e53ef71f 100644
--- a/test/cpp/qps/timer.h
+++ b/test/cpp/qps/usage_timer.h
@@ -1,6 +1,6 @@
 /*
  *
- * Copyright 2015, Google Inc.
+ * Copyright 2015-2016, Google Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -31,12 +31,12 @@
  *
  */
 
-#ifndef TEST_QPS_TIMER_H
-#define TEST_QPS_TIMER_H
+#ifndef TEST_QPS_USAGE_TIMER_H
+#define TEST_QPS_USAGE_TIMER_H
 
-class Timer {
+class UsageTimer {
  public:
-  Timer();
+  UsageTimer();
 
   struct Result {
     double wall;
diff --git a/test/cpp/util/metrics_server.cc b/test/cpp/util/metrics_server.cc
index 07978d0bdbfb9e237bc73c8f2fab4b0d625ab9fd..34d51eb3169e4e5c2416dda753d33c1c9c94fc6b 100644
--- a/test/cpp/util/metrics_server.cc
+++ b/test/cpp/util/metrics_server.cc
@@ -57,7 +57,7 @@ long Gauge::Get() {
 grpc::Status MetricsServiceImpl::GetAllGauges(
     ServerContext* context, const EmptyMessage* request,
     ServerWriter<GaugeResponse>* writer) {
-  gpr_log(GPR_INFO, "GetAllGauges called");
+  gpr_log(GPR_DEBUG, "GetAllGauges called");
 
   std::lock_guard<std::mutex> lock(mu_);
   for (auto it = gauges_.begin(); it != gauges_.end(); it++) {
diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc
index 1086e14258b0c54c69a649a0507a0f655246227b..e314fd6d75a84db3f56a509c6b6fbe0a97af7af9 100644
--- a/test/cpp/util/test_credentials_provider.cc
+++ b/test/cpp/util/test_credentials_provider.cc
@@ -34,48 +34,140 @@
 
 #include "test/cpp/util/test_credentials_provider.h"
 
+#include <unordered_map>
+
+#include <grpc/support/sync.h>
+#include <grpc++/impl/sync.h>
+
 #include "test/core/end2end/data/ssl_test_data.h"
 
+namespace {
+
+using grpc::ChannelArguments;
+using grpc::ChannelCredentials;
+using grpc::InsecureChannelCredentials;
+using grpc::InsecureServerCredentials;
+using grpc::ServerCredentials;
+using grpc::SslCredentialsOptions;
+using grpc::SslServerCredentialsOptions;
+using grpc::testing::CredentialTypeProvider;
+
+// Provide test credentials. Thread-safe.
+class CredentialsProvider {
+ public:
+  virtual ~CredentialsProvider() {}
+
+  virtual void AddSecureType(
+      const grpc::string& type,
+      std::unique_ptr<CredentialTypeProvider> type_provider) = 0;
+  virtual std::shared_ptr<ChannelCredentials> GetChannelCredentials(
+      const grpc::string& type, ChannelArguments* args) = 0;
+  virtual std::shared_ptr<ServerCredentials> GetServerCredentials(
+      const grpc::string& type) = 0;
+  virtual std::vector<grpc::string> GetSecureCredentialsTypeList() = 0;
+};
+
+class DefaultCredentialsProvider : public CredentialsProvider {
+ public:
+  ~DefaultCredentialsProvider() override {}
+
+  void AddSecureType(
+      const grpc::string& type,
+      std::unique_ptr<CredentialTypeProvider> type_provider) override {
+    // This clobbers any existing entry for type, except the defaults, which
+    // can't be clobbered.
+    grpc::unique_lock<grpc::mutex> lock(mu_);
+    added_secure_types_[type] = std::move(type_provider);
+  }
+
+  std::shared_ptr<ChannelCredentials> GetChannelCredentials(
+      const grpc::string& type, ChannelArguments* args) override {
+    if (type == grpc::testing::kInsecureCredentialsType) {
+      return InsecureChannelCredentials();
+    } else if (type == grpc::testing::kTlsCredentialsType) {
+      SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
+      args->SetSslTargetNameOverride("foo.test.google.fr");
+      return SslCredentials(ssl_opts);
+    } else {
+      grpc::unique_lock<grpc::mutex> lock(mu_);
+      auto it(added_secure_types_.find(type));
+      if (it == added_secure_types_.end()) {
+        gpr_log(GPR_ERROR, "Unsupported credentials type %s.", type.c_str());
+        return nullptr;
+      }
+      return it->second->GetChannelCredentials(args);
+    }
+  }
+
+  std::shared_ptr<ServerCredentials> GetServerCredentials(
+      const grpc::string& type) override {
+    if (type == grpc::testing::kInsecureCredentialsType) {
+      return InsecureServerCredentials();
+    } else if (type == grpc::testing::kTlsCredentialsType) {
+      SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
+                                                          test_server1_cert};
+      SslServerCredentialsOptions ssl_opts;
+      ssl_opts.pem_root_certs = "";
+      ssl_opts.pem_key_cert_pairs.push_back(pkcp);
+      return SslServerCredentials(ssl_opts);
+    } else {
+      grpc::unique_lock<grpc::mutex> lock(mu_);
+      auto it(added_secure_types_.find(type));
+      if (it == added_secure_types_.end()) {
+        gpr_log(GPR_ERROR, "Unsupported credentials type %s.", type.c_str());
+        return nullptr;
+      }
+      return it->second->GetServerCredentials();
+    }
+  }
+  std::vector<grpc::string> GetSecureCredentialsTypeList() override {
+    std::vector<grpc::string> types;
+    types.push_back(grpc::testing::kTlsCredentialsType);
+    grpc::unique_lock<grpc::mutex> lock(mu_);
+    for (const auto& type_pair : added_secure_types_) {
+      types.push_back(type_pair.first);
+    }
+    return types;
+  }
+
+ private:
+  grpc::mutex mu_;
+  std::unordered_map<grpc::string, std::unique_ptr<CredentialTypeProvider> >
+      added_secure_types_;
+};
+
+gpr_once g_once_init_provider = GPR_ONCE_INIT;
+CredentialsProvider* g_provider = nullptr;
+
+void CreateDefaultProvider() { g_provider = new DefaultCredentialsProvider; }
+
+CredentialsProvider* GetProvider() {
+  gpr_once_init(&g_once_init_provider, &CreateDefaultProvider);
+  return g_provider;
+}
+
+}  // namespace
+
 namespace grpc {
 namespace testing {
 
-const char kTlsCredentialsType[] = "TLS_CREDENTIALS";
+void AddSecureType(const grpc::string& type,
+                   std::unique_ptr<CredentialTypeProvider> type_provider) {
+  GetProvider()->AddSecureType(type, std::move(type_provider));
+}
 
 std::shared_ptr<ChannelCredentials> GetChannelCredentials(
     const grpc::string& type, ChannelArguments* args) {
-  if (type == kInsecureCredentialsType) {
-    return InsecureChannelCredentials();
-  } else if (type == kTlsCredentialsType) {
-    SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
-    args->SetSslTargetNameOverride("foo.test.google.fr");
-    return SslCredentials(ssl_opts);
-  } else {
-    gpr_log(GPR_ERROR, "Unsupported credentials type %s.", type.c_str());
-  }
-  return nullptr;
+  return GetProvider()->GetChannelCredentials(type, args);
 }
 
 std::shared_ptr<ServerCredentials> GetServerCredentials(
     const grpc::string& type) {
-  if (type == kInsecureCredentialsType) {
-    return InsecureServerCredentials();
-  } else if (type == kTlsCredentialsType) {
-    SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
-                                                        test_server1_cert};
-    SslServerCredentialsOptions ssl_opts;
-    ssl_opts.pem_root_certs = "";
-    ssl_opts.pem_key_cert_pairs.push_back(pkcp);
-    return SslServerCredentials(ssl_opts);
-  } else {
-    gpr_log(GPR_ERROR, "Unsupported credentials type %s.", type.c_str());
-  }
-  return nullptr;
+  return GetProvider()->GetServerCredentials(type);
 }
 
 std::vector<grpc::string> GetSecureCredentialsTypeList() {
-  std::vector<grpc::string> types;
-  types.push_back(kTlsCredentialsType);
-  return types;
+  return GetProvider()->GetSecureCredentialsTypeList();
 }
 
 }  // namespace testing
diff --git a/test/cpp/util/test_credentials_provider.h b/test/cpp/util/test_credentials_provider.h
index f7253051a97dd7c3f6f296a0ee77ccaec717708e..50fadb53a24b1bd4d97716b3ee80a696a94eed78 100644
--- a/test/cpp/util/test_credentials_provider.h
+++ b/test/cpp/util/test_credentials_provider.h
@@ -44,6 +44,23 @@ namespace grpc {
 namespace testing {
 
 const char kInsecureCredentialsType[] = "INSECURE_CREDENTIALS";
+const char kTlsCredentialsType[] = "TLS_CREDENTIALS";
+
+// Provide test credentials of a particular type.
+class CredentialTypeProvider {
+ public:
+  virtual ~CredentialTypeProvider() {}
+
+  virtual std::shared_ptr<ChannelCredentials> GetChannelCredentials(
+      ChannelArguments* args) = 0;
+  virtual std::shared_ptr<ServerCredentials> GetServerCredentials() = 0;
+};
+
+// Add a secure type in addition to the defaults above
+// (kInsecureCredentialsType, kTlsCredentialsType) that can be returned from the
+// functions below.
+void AddSecureType(const grpc::string& type,
+                   std::unique_ptr<CredentialTypeProvider> type_provider);
 
 // Provide channel credentials according to the given type. Alter the channel
 // arguments if needed.
diff --git a/test/distrib/csharp/DistribTest.sln b/test/distrib/csharp/DistribTest.sln
index 0eca35c30fb55b2fccb09109a458a95785b723c9..78d5397ca97e512561372cfdafdfabc50f8960a9 100644
--- a/test/distrib/csharp/DistribTest.sln
+++ b/test/distrib/csharp/DistribTest.sln
@@ -8,13 +8,19 @@ EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
+		Debug|x64 = Debug|x64
 		Release|Any CPU = Release|Any CPU
+		Release|x64 = Release|x64
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{A3E61CC3-3710-49A3-A830-A0066EDBCE2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{A3E61CC3-3710-49A3-A830-A0066EDBCE2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A3E61CC3-3710-49A3-A830-A0066EDBCE2F}.Debug|x64.ActiveCfg = Debug|x64
+		{A3E61CC3-3710-49A3-A830-A0066EDBCE2F}.Debug|x64.Build.0 = Debug|x64
 		{A3E61CC3-3710-49A3-A830-A0066EDBCE2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{A3E61CC3-3710-49A3-A830-A0066EDBCE2F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A3E61CC3-3710-49A3-A830-A0066EDBCE2F}.Release|x64.ActiveCfg = Release|x64
+		{A3E61CC3-3710-49A3-A830-A0066EDBCE2F}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/test/distrib/csharp/DistribTest/DistribTest.csproj b/test/distrib/csharp/DistribTest/DistribTest.csproj
index 124fc1bdf0f9f121097a0111a2d455e7a2b0a2ae..7605495f0f6242385033675a2f9efd2ad293ab5b 100644
--- a/test/distrib/csharp/DistribTest/DistribTest.csproj
+++ b/test/distrib/csharp/DistribTest/DistribTest.csproj
@@ -32,6 +32,26 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="BouncyCastle.Crypto">
       <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
diff --git a/test/distrib/csharp/run_distrib_test.bat b/test/distrib/csharp/run_distrib_test.bat
new file mode 100644
index 0000000000000000000000000000000000000000..67bfc58ac8e49c2cd7e52e2287cfab70d35e3240
--- /dev/null
+++ b/test/distrib/csharp/run_distrib_test.bat
@@ -0,0 +1,49 @@
+@rem Copyright 2016, Google Inc.
+@rem All rights reserved.
+@rem
+@rem Redistribution and use in source and binary forms, with or without
+@rem modification, are permitted provided that the following conditions are
+@rem met:
+@rem
+@rem     * Redistributions of source code must retain the above copyright
+@rem notice, this list of conditions and the following disclaimer.
+@rem     * Redistributions in binary form must reproduce the above
+@rem copyright notice, this list of conditions and the following disclaimer
+@rem in the documentation and/or other materials provided with the
+@rem distribution.
+@rem     * Neither the name of Google Inc. nor the names of its
+@rem contributors may be used to endorse or promote products derived from
+@rem this software without specific prior written permission.
+@rem
+@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+@rem enter this directory
+cd /d %~dp0
+
+@rem extract input artifacts
+powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('../../../input_artifacts/csharp_nugets.zip', 'TestNugetFeed');"
+
+update_version.sh auto
+
+set NUGET=C:\nuget\nuget.exe
+%NUGET% restore || goto :error
+
+@call build_vs2015.bat DistribTest.sln %MSBUILD_EXTRA_ARGS% || goto :error
+
+%DISTRIBTEST_OUTPATH%\DistribTest.exe || goto :error
+
+goto :EOF
+
+:error
+echo Failed!
+exit /b %errorlevel%
diff --git a/test/distrib/csharp/run_distrib_test.sh b/test/distrib/csharp/run_distrib_test.sh
index 1de62041b3fb32895705774ba5875ccc87073ffc..934174a9a4e54a30607929867536695e248be424 100755
--- a/test/distrib/csharp/run_distrib_test.sh
+++ b/test/distrib/csharp/run_distrib_test.sh
@@ -34,9 +34,7 @@ cd $(dirname $0)
 
 unzip -o "$EXTERNAL_GIT_ROOT/input_artifacts/csharp_nugets.zip" -d TestNugetFeed
 
-# Extract the version number from Grpc nuget package name.
-CSHARP_VERSION=$(ls TestNugetFeed | grep '^Grpc\.[0-9].*\.nupkg$' | sed s/^Grpc\.// | sed s/\.nupkg$//)
-./update_version.sh $CSHARP_VERSION
+./update_version.sh auto
 
 nuget restore
 
diff --git a/test/distrib/csharp/update_version.sh b/test/distrib/csharp/update_version.sh
index f2554e89981c571b9e2b53b39b906aeb78177b7e..b0d07721f6ccbbf74468922e083a7c1d2b57056f 100755
--- a/test/distrib/csharp/update_version.sh
+++ b/test/distrib/csharp/update_version.sh
@@ -32,5 +32,13 @@ set -e
 
 cd $(dirname $0)
 
+CSHARP_VERSION="$1"
+if [ "$CSHARP_VERSION" == "auto" ]
+then
+  # autodetect C# version
+  CSHARP_VERSION=$(ls TestNugetFeed | grep '^Grpc\.[0-9].*\.nupkg$' | sed s/^Grpc\.// | sed s/\.nupkg$//)
+  echo "Autodetected nuget ${CSHARP_VERSION}"
+fi
+
 # Replaces version placeholder with value provided as first argument.
-sed -ibak "s/__GRPC_NUGET_VERSION__/$1/g" DistribTest/packages.config DistribTest/DistribTest.csproj
+sed -ibak "s/__GRPC_NUGET_VERSION__/${CSHARP_VERSION}/g" DistribTest/packages.config DistribTest/DistribTest.csproj
diff --git a/test/distrib/php/distribtest.php b/test/distrib/php/distribtest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4c34cd674b47a14db935d243cd3b450ccbef2b50
--- /dev/null
+++ b/test/distrib/php/distribtest.php
@@ -0,0 +1,45 @@
+<?php
+/*
+ *
+ * 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.
+ *
+ */
+
+$channel = new Grpc\Channel('localhost:1000', [
+    'credentials' => Grpc\ChannelCredentials::createInsecure()
+]);
+
+$deadline = Grpc\Timeval::infFuture();
+$call = new Grpc\Call($channel,
+                      'dummy_method',
+                      $deadline);
+
+$call->cancel();
+$channel->close();
diff --git a/test/distrib/php/run_distrib_test.sh b/test/distrib/php/run_distrib_test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..43b28d842903c1b9213975552ae3f91e59676926
--- /dev/null
+++ b/test/distrib/php/run_distrib_test.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# Copyright 2015-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.
+
+set -ex
+
+cd $(dirname $0)
+
+cp -r $EXTERNAL_GIT_ROOT/input_artifacts/grpc-php.tgz .
+
+pecl install grpc-php.tgz
+
+php -d extension=grpc.so -d max_execution_time=300 distribtest.php
diff --git a/third_party/nanopb b/third_party/nanopb
new file mode 160000
index 0000000000000000000000000000000000000000..f8ac463766281625ad710900479130c7fcb4d63b
--- /dev/null
+++ b/third_party/nanopb
@@ -0,0 +1 @@
+Subproject commit f8ac463766281625ad710900479130c7fcb4d63b
diff --git a/tools/README.md b/tools/README.md
index a0c41eb79ffcdfea58e15b1d35a18e8cb4ab3210..df4c6ef7d2527e7c4c3fe6a632815918e5d4f726 100644
--- a/tools/README.md
+++ b/tools/README.md
@@ -1,7 +1,5 @@
 buildgen: template renderer for our build system.
 
-distpackages: script to generate debian packages.
-
 distrib: scripts to distribute language-specific packages.
 
 dockerfile: Docker files to test gRPC.
@@ -12,6 +10,4 @@ gce: scripts to help setup testing infrastructure on GCE.
 
 jenkins: support for running tests on Jenkins.
 
-profile_analyzer: pretty printer for gRPC profiling data.
-
 run_tests: scripts to run gRPC tests in parallel.
diff --git a/tools/buildgen/build-cleaner.py b/tools/buildgen/build-cleaner.py
index 49a364412350c0aa6bb02e61c1b426ce9bc8fc29..12054da238eeb992ad5b67a9b23a4d3f1ac39387 100755
--- a/tools/buildgen/build-cleaner.py
+++ b/tools/buildgen/build-cleaner.py
@@ -40,6 +40,7 @@ TEST = (os.environ.get('TEST', 'false') == 'true')
 _TOP_LEVEL_KEYS = ['settings', 'proto_deps', 'filegroups', 'libs', 'targets', 'vspackages']
 _ELEM_KEYS = [
     'name',
+    'gtest',
     'cpu_cost',
     'flaky',
     'build',
@@ -98,4 +99,3 @@ for filename in sys.argv[1:]:
   else:
     with open(filename, 'w') as f:
       f.write(output)
-
diff --git a/tools/buildgen/generate_projects.py b/tools/buildgen/generate_projects.py
index 965dd292afbc88942e84ec6f165c9248d5454c92..0602d93e56347a9474d0266216d594467f3d1eed 100755
--- a/tools/buildgen/generate_projects.py
+++ b/tools/buildgen/generate_projects.py
@@ -45,12 +45,12 @@ import jobset
 os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '..', '..'))
 
 argp = argparse.ArgumentParser()
-argp.add_argument('json', nargs='+')
+argp.add_argument('build_files', nargs='+', default=[])
 argp.add_argument('--templates', nargs='+', default=[])
 argp.add_argument('--jobs', '-j', default=multiprocessing.cpu_count(), type=int)
 args = argp.parse_args()
 
-json = args.json
+json = args.build_files
 
 test = {} if 'TEST' in os.environ else None
 
@@ -62,21 +62,31 @@ if not templates:
     for f in files:
       templates.append(os.path.join(root, f))
 
+pre_jobs = []
+base_cmd = ['python2.7', 'tools/buildgen/mako_renderer.py']
+cmd = base_cmd[:]
+for plugin in plugins:
+  cmd.append('-p')
+  cmd.append(plugin)
+for js in json:
+  cmd.append('-d')
+  cmd.append(js)
+cmd.append('-w')
+preprocessed_build = '.preprocessed_build'
+cmd.append(preprocessed_build)
+pre_jobs.append(jobset.JobSpec(cmd, shortname='preprocess', timeout_seconds=None))
+
 jobs = []
-for template in templates:
+for template in reversed(sorted(templates)):
   root, f = os.path.split(template)
   if os.path.splitext(f)[1] == '.template':
     out_dir = '.' + root[len('templates'):]
     out = out_dir + '/' + os.path.splitext(f)[0]
     if not os.path.exists(out_dir):
       os.makedirs(out_dir)
-    cmd = ['python2.7', 'tools/buildgen/mako_renderer.py']
-    for plugin in plugins:
-      cmd.append('-p')
-      cmd.append(plugin)
-    for js in json:
-      cmd.append('-d')
-      cmd.append(js)
+    cmd = base_cmd[:]
+    cmd.append('-P')
+    cmd.append(preprocessed_build)
     cmd.append('-o')
     if test is None:
       cmd.append(out)
@@ -88,6 +98,7 @@ for template in templates:
     cmd.append(root + '/' + f)
     jobs.append(jobset.JobSpec(cmd, shortname=out, timeout_seconds=None))
 
+jobset.run(pre_jobs, maxjobs=args.jobs)
 jobset.run(jobs, maxjobs=args.jobs)
 
 if test is not None:
diff --git a/tools/buildgen/mako_renderer.py b/tools/buildgen/mako_renderer.py
index f1b28d352e7e34d56cbab43b39fed792063dd22d..5f23f123c2df11b39c15fe4f16e37d8e58701c24 100755
--- a/tools/buildgen/mako_renderer.py
+++ b/tools/buildgen/mako_renderer.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@ Just a wrapper around the mako rendering library.
 import getopt
 import imp
 import os
+import cPickle as pickle
 import shutil
 import sys
 
@@ -66,21 +67,23 @@ def out(msg):
 
 
 def showhelp():
-  out('mako-renderer.py [-o out] [-m cache] [-d dict] [-d dict...] template')
+  out('mako-renderer.py [-o out] [-m cache] [-P preprocessed_input] [-d dict] [-d dict...]'
+      ' [-t template] [-w preprocessed_output]')
 
 
 def main(argv):
   got_input = False
   module_directory = None
+  preprocessed_output = None
   dictionary = {}
   json_dict = {}
   got_output = False
-  output_file = sys.stdout
   plugins = []
   output_name = None
+  got_preprocessed_input = False
 
   try:
-    opts, args = getopt.getopt(argv, 'hm:d:o:p:')
+    opts, args = getopt.getopt(argv, 'hm:d:o:p:t:P:w:')
   except getopt.GetoptError:
     out('Unknown option')
     showhelp()
@@ -104,18 +107,31 @@ def main(argv):
         showhelp()
         sys.exit(4)
       module_directory = arg
+    elif opt == '-P':
+      assert not got_preprocessed_input
+      assert json_dict == {}
+      sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), 'plugins')))
+      with open(arg, 'r') as dict_file:
+        dictionary = pickle.load(dict_file)
+      got_preprocessed_input = True
     elif opt == '-d':
-      dict_file = open(arg, 'r')
-      bunch.merge_json(json_dict, yaml.load(dict_file.read()))
-      dict_file.close()
+      assert not got_preprocessed_input
+      with open(arg, 'r') as dict_file:
+        bunch.merge_json(json_dict, yaml.load(dict_file.read()))
     elif opt == '-p':
       plugins.append(import_plugin(arg))
+    elif opt == '-w':
+      preprocessed_output = arg
 
-  for plugin in plugins:
-    plugin.mako_plugin(json_dict)
+  if not got_preprocessed_input:
+    for plugin in plugins:
+      plugin.mako_plugin(json_dict)
+    for k, v in json_dict.items():
+      dictionary[k] = bunch.to_bunch(v)
 
-  for k, v in json_dict.items():
-    dictionary[k] = bunch.to_bunch(v)
+  if preprocessed_output:
+    with open(preprocessed_output, 'w') as dict_file:
+      pickle.dump(dictionary, dict_file)
 
   cleared_dir = False
   for arg in args:
@@ -168,11 +184,9 @@ def main(argv):
           with open(item_output_name, 'w') as output_file:
             template.render_context(Context(output_file, **args))
 
-  if not got_input:
+  if not got_input and not preprocessed_output:
     out('Got nothing to do')
     showhelp()
 
-  output_file.close()
-
 if __name__ == '__main__':
   main(sys.argv[1:])
diff --git a/tools/buildgen/plugins/expand_bin_attrs.py b/tools/buildgen/plugins/expand_bin_attrs.py
index 735c60ea9959a573c6192595567f5d237f2f8b3f..c30df2ad892753959bca62af17ef1710be903aa3 100755
--- a/tools/buildgen/plugins/expand_bin_attrs.py
+++ b/tools/buildgen/plugins/expand_bin_attrs.py
@@ -52,6 +52,7 @@ def mako_plugin(dictionary):
     tgt['ci_platforms'] = sorted(tgt.get('ci_platforms', tgt['platforms']))
     tgt['boringssl'] = tgt.get('boringssl', False)
     tgt['zlib'] = tgt.get('zlib', False)
+    tgt['gtest'] = tgt.get('gtest', False)
 
   libs = dictionary.get('libs')
   for lib in libs:
diff --git a/tools/codegen/core/gen_load_balancing_proto.sh b/tools/codegen/core/gen_load_balancing_proto.sh
new file mode 100755
index 0000000000000000000000000000000000000000..fb6a468ee0b68d376919750427e89f5f46b23ffb
--- /dev/null
+++ b/tools/codegen/core/gen_load_balancing_proto.sh
@@ -0,0 +1,138 @@
+#!/bin/bash
+
+# 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.
+
+#
+# Example usage:
+#   tools/codegen/core/gen_load_balancing_proto.sh \
+#     src/proto/grpc/lb/v0/load_balancer.proto
+
+read -r -d '' COPYRIGHT <<'EOF'
+/*
+ *
+ * Copyright <YEAR>, 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.
+ *
+ */
+
+EOF
+
+CURRENT_YEAR=$(date +%Y)
+COPYRIGHT_FILE=$(mktemp)
+echo "${COPYRIGHT/<YEAR>/$CURRENT_YEAR}" > $COPYRIGHT_FILE
+
+set -ex
+if [ $# -eq 0 ]; then
+  echo "Usage: $0 <load_balancer.proto> [output dir]"
+  exit 1
+fi
+
+readonly GRPC_ROOT=$PWD
+
+OUTPUT_DIR="$GRPC_ROOT/src/core/proto/grpc/lb/v0"
+if [ $# -eq 2 ]; then
+  mkdir -p "$2"
+  if [ $? != 0 ]; then
+    echo "Error creating output directory $2"
+    exit 2
+  fi
+  OUTPUT_DIR="$2"
+fi
+
+readonly EXPECTED_OPTIONS_FILE_PATH="${1%.*}.options"
+
+if [[ ! -f "$1" ]]; then
+  echo "Input proto file '$1' doesn't exist."
+  exit 3
+fi
+if [[ ! -f "${EXPECTED_OPTIONS_FILE_PATH}" ]]; then
+  echo "Expected nanopb options file '${EXPECTED_OPTIONS_FILE_PATH}' missing"
+  exit 4
+fi
+
+readonly VENV_DIR=$(mktemp -d)
+readonly VENV_NAME="nanopb-$(date '+%Y%m%d_%H%M%S_%N')"
+pushd $VENV_DIR
+virtualenv $VENV_NAME
+. $VENV_NAME/bin/activate
+popd
+
+# this should be the same version as the submodule we compile against
+# ideally we'd update this as a template to ensure that
+pip install protobuf==3.0.0b2
+
+pushd "$(dirname $1)" > /dev/null
+
+protoc \
+--plugin=protoc-gen-nanopb="$GRPC_ROOT/third_party/nanopb/generator/protoc-gen-nanopb" \
+--nanopb_out='-T -L#include\ \"third_party/nanopb/pb.h\"'":$OUTPUT_DIR" \
+"$(basename $1)"
+
+readonly PROTO_BASENAME=$(basename $1 .proto)
+sed -i "s:$PROTO_BASENAME.pb.h:src/core/proto/grpc/lb/v0/$PROTO_BASENAME.pb.h:g" \
+    "$OUTPUT_DIR/$PROTO_BASENAME.pb.c"
+
+# prepend copyright
+TMPFILE=$(mktemp)
+cat $COPYRIGHT_FILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.c" > $TMPFILE
+mv -v $TMPFILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.c"
+cat $COPYRIGHT_FILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.h" > $TMPFILE
+mv -v $TMPFILE "$OUTPUT_DIR/$PROTO_BASENAME.pb.h"
+
+deactivate
+rm -rf $VENV_DIR
+
+popd > /dev/null
diff --git a/tools/distrib/check_nanopb_output.sh b/tools/distrib/check_nanopb_output.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5f49ebb93e645981c3e15c2c624866eea2e7c1b9
--- /dev/null
+++ b/tools/distrib/check_nanopb_output.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+# Copyright 2015-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.
+
+set -ex
+
+apt-get install -y autoconf automake libtool curl python-virtualenv
+
+readonly NANOPB_TMP_OUTPUT="$(mktemp -d)"
+
+# install protoc version 3
+pushd third_party/protobuf
+./autogen.sh
+./configure
+make
+make install
+ldconfig
+popd
+
+if [ ! -x "/usr/local/bin/protoc" ]; then
+  echo "Error: protoc not found in path"
+  exit 1
+fi
+readonly PROTOC_PATH='/usr/local/bin'
+# stack up and change to nanopb's proto generator directory
+pushd third_party/nanopb/generator/proto
+PATH="$PROTOC_PATH:$PATH" make
+
+# back to the root directory
+popd
+
+
+# nanopb-compile the proto to a temp location
+PATH="$PROTOC_PATH:$PATH" ./tools/codegen/core/gen_load_balancing_proto.sh \
+  src/proto/grpc/lb/v0/load_balancer.proto \
+  $NANOPB_TMP_OUTPUT
+
+# compare outputs to checked compiled code
+if ! diff -r $NANOPB_TMP_OUTPUT src/core/proto/grpc/lb/v0; then
+  echo "Outputs differ: $NANOPB_TMP_OUTPUT vs src/core/proto/grpc/lb/v0"
+  exit 2
+fi
diff --git a/tools/dockerfile/distribtest/php_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/php_jessie_x64/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..d5d3fd626ff9398fed6e78085127cc932079321d
--- /dev/null
+++ b/tools/dockerfile/distribtest/php_jessie_x64/Dockerfile
@@ -0,0 +1,32 @@
+# Copyright 2015-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.
+
+FROM debian:jessie
+
+RUN apt-get update && apt-get install -y php5 php5-dev php-pear phpunit
diff --git a/tools/dockerfile/distribtest/python_fedora20_x64/Dockerfile b/tools/dockerfile/distribtest/python_fedora20_x64/Dockerfile
index d58036410f6de6f304afe3479f8a315a7903e1e5..5e6cb1576292412407c3cfae5cf892e85ef601e5 100644
--- a/tools/dockerfile/distribtest/python_fedora20_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_fedora20_x64/Dockerfile
@@ -30,3 +30,8 @@
 FROM fedora:20
 
 RUN yum clean all && yum update -y && yum install -y python python-pip
+
+# Upgrading six would fail because of docker issue when using overlay.
+# Trying twice makes it work fine.
+# https://github.com/docker/docker/issues/10180
+RUN pip install --upgrade six || pip install --upgrade six
diff --git a/tools/dockerfile/distribtest/python_fedora21_x64/Dockerfile b/tools/dockerfile/distribtest/python_fedora21_x64/Dockerfile
index 1eb4c1e77501639017b9d9e212145e2adfdcd900..f1b0e2f4b223634ee6ad232202fdbc71d4579989 100644
--- a/tools/dockerfile/distribtest/python_fedora21_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/python_fedora21_x64/Dockerfile
@@ -35,3 +35,8 @@ FROM fedora:21
 RUN yum install -y yum-plugin-ovl
 
 RUN yum clean all && yum update -y && yum install -y python python-pip
+
+# Upgrading six would fail because of docker issue when using overlay.
+# Trying twice makes it work fine.
+# https://github.com/docker/docker/issues/10180
+RUN pip2 install --upgrade six || pip2 install --upgrade six
diff --git a/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile
index f65b8690d7e9e69d9151fc54a1fc14bfabd0421a..b943b67e8a5441ddab3d909711236bc8d7507a80 100644
--- a/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile
@@ -35,7 +35,9 @@ RUN yum install -y tar which
 
 # Install rvm
 RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
-RUN \curl -sSL https://get.rvm.io | bash -s stable --ruby
+# Running the installation twice to work around docker issue when using overlay.
+# https://github.com/docker/docker/issues/10180
+RUN (curl -sSL https://get.rvm.io | bash -s stable --ruby) || (curl -sSL https://get.rvm.io | bash -s stable --ruby)
 
 RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc"
 RUN /bin/bash -l -c "gem install --update bundler"
diff --git a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile
index 41dc4274541e29df4892af423e6b70cd26e4f447..d048b725c85a249d18c25ca3323fab1713a47446 100644
--- a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile
+++ b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile
@@ -91,6 +91,13 @@ RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
 RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
 RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
 
+
+##################
+# PHP dependencies
+
+RUN apt-get update && apt-get install -y \
+    php5 php5-dev php-pear phpunit
+
 RUN mkdir /var/local/jenkins
 
 # Define the default command.
diff --git a/tools/dockerfile/grpc_artifact_protoc/Dockerfile b/tools/dockerfile/grpc_artifact_protoc/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..1bbc6e021bc67a6d2419bef498485704f86bcda3
--- /dev/null
+++ b/tools/dockerfile/grpc_artifact_protoc/Dockerfile
@@ -0,0 +1,63 @@
+# 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.
+
+# Docker file for building protoc and gRPC protoc plugin artifacts.
+# forked from https://github.com/google/protobuf/blob/master/protoc-artifacts/Dockerfile
+
+FROM centos:6.6
+
+RUN yum install -y git \
+                   tar \
+                   wget \
+                   make \
+                   autoconf \
+                   curl-devel \
+                   unzip \
+                   automake \
+                   libtool \
+                   glibc-static.i686 \
+                   glibc-devel \
+                   glibc-devel.i686
+
+# Install GCC 4.7 to support -static-libstdc++
+RUN wget http://people.centos.org/tru/devtools-1.1/devtools-1.1.repo -P /etc/yum.repos.d
+RUN bash -c 'echo "enabled=1" >> /etc/yum.repos.d/devtools-1.1.repo'
+RUN bash -c "sed -e 's/\$basearch/i386/g' /etc/yum.repos.d/devtools-1.1.repo > /etc/yum.repos.d/devtools-i386-1.1.repo"
+RUN sed -e 's/testing-/testing-i386-/g' -i /etc/yum.repos.d/devtools-i386-1.1.repo
+
+# We'll get and "Rpmdb checksum is invalid: dCDPT(pkg checksums)" error caused by
+# docker issue when using overlay storage driver, but all the stuff we need
+# will be installed, so for now we just ignore the error.
+# https://github.com/docker/docker/issues/10180
+RUN yum install -y devtoolset-1.1 \
+                   devtoolset-1.1-libstdc++-devel \
+                   devtoolset-1.1-libstdc++-devel.i686 || true
+
+# Start in devtoolset environment that uses GCC 4.7
+CMD ["scl", "enable", "devtoolset-1.1", "bash"]
diff --git a/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh b/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
index dd8ea1ac305a51ff356b64850e211483c77298bb..d56bc0183118c8016ad1845d9c8c1f19a144334f 100755
--- a/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
+++ b/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
@@ -44,7 +44,7 @@ for dir in $DIRS
 do
   for glob in $GLOB
   do
-    files="$files `find /local-code/$dir -name $glob -and -not -name *.generated.*`"
+    files="$files `find /local-code/$dir -name $glob -and -not -name *.generated.* -and -not -name *.pb.h -and -not -name *.pb.c`"
   done
 done
 
diff --git a/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile b/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile
index 58a8c32e344fa4944c62e233eeb05151279be998..4123cc1a26ad4580c429caa1e8bceb0423e476e3 100644
--- a/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile
+++ b/tools/dockerfile/grpc_interop_stress_cxx/Dockerfile
@@ -59,6 +59,8 @@ RUN apt-get update && apt-get install -y \
   wget \
   zip && apt-get clean
 
+RUN easy_install -U pip
+
 # Prepare ccache
 RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
 RUN ln -s /usr/bin/ccache /usr/local/bin/g++
@@ -71,5 +73,8 @@ RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
 # C++ dependencies
 RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang
 
+# Google Cloud platform API libraries (for BigQuery)
+RUN pip install --upgrade google-api-python-client
+
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh b/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh
index 6ed3ccb3fa08e175020edbb8e7f8bfbcedf036c8..392bdfccda07b7f8966ce674dce176c53d4c0a3c 100755
--- a/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh
+++ b/tools/dockerfile/grpc_interop_stress_cxx/build_interop_stress.sh
@@ -42,4 +42,4 @@ cd /var/local/git/grpc
 make install-certs
 
 # build C++ interop stress client, interop client and server
-make stress_test interop_client interop_server
+make stress_test metrics_client interop_client interop_server
diff --git a/tools/dockerfile/test/cxx_squeeze_x64/Dockerfile b/tools/dockerfile/test/cxx_squeeze_x64/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..b7f95aaa8d98a6a3f6f6bc18238fd72c01b2be8c
--- /dev/null
+++ b/tools/dockerfile/test/cxx_squeeze_x64/Dockerfile
@@ -0,0 +1,88 @@
+# 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.
+
+FROM debian:squeeze
+
+# Install Git and basic packages.
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  gcc-multilib \
+  git \
+  gyp \
+  lcov \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  perl \
+  strace \
+  python-dev \
+  python-setuptools \
+  python-yaml \
+  telnet \
+  unzip \
+  wget \
+  zip && apt-get clean
+
+#================
+# Build profiling
+RUN apt-get update && apt-get install -y time && apt-get clean
+
+
+# libgflags-dev is not available on squeezy
+RUN apt-get update && apt-get -y install libgtest-dev libc++-dev clang && apt-get clean
+
+RUN apt-get update && apt-get -y install python-pip && apt-get clean
+RUN pip install argparse
+
+RUN wget http://openssl.org/source/openssl-1.0.2f.tar.gz
+
+ENV POST_GIT_STEP tools/dockerfile/test/cxx_squeeze_x64/post-git-setup.sh
+
+# Prepare ccache
+RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
+RUN ln -s /usr/bin/ccache /usr/local/bin/g++
+RUN ln -s /usr/bin/ccache /usr/local/bin/cc
+RUN ln -s /usr/bin/ccache /usr/local/bin/c++
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
+
+
+RUN mkdir /var/local/jenkins
+
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/dockerfile/test/cxx_squeeze_x64/post-git-setup.sh b/tools/dockerfile/test/cxx_squeeze_x64/post-git-setup.sh
new file mode 100755
index 0000000000000000000000000000000000000000..dfde93b1bd253a619696551bb1f2d289733427e6
--- /dev/null
+++ b/tools/dockerfile/test/cxx_squeeze_x64/post-git-setup.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# 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.
+
+set -ex
+
+cd /var/local/git/grpc
+cp /openssl-1.0.2f.tar.gz third_party
+./tools/openssl/use_openssl.sh
diff --git a/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..c6fe79b42c064aa1cc29be1fde790531fa449b62
--- /dev/null
+++ b/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
@@ -0,0 +1,86 @@
+# Copyright 2015-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.
+
+FROM ubuntu:16.04
+
+# Install Git and basic packages.
+RUN apt-get update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  ccache \
+  curl \
+  gcc \
+  gcc-multilib \
+  git \
+  golang \
+  gyp \
+  lcov \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  perl \
+  strace \
+  python-dev \
+  python-setuptools \
+  python-yaml \
+  telnet \
+  unzip \
+  wget \
+  zip && apt-get clean
+
+#================
+# Build profiling
+RUN apt-get update && apt-get install -y time && apt-get clean
+
+#=================
+# C++ dependencies
+RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean
+
+# Prepare ccache
+RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
+RUN ln -s /usr/bin/ccache /usr/local/bin/g++
+RUN ln -s /usr/bin/ccache /usr/local/bin/cc
+RUN ln -s /usr/bin/ccache /usr/local/bin/c++
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang
+RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
+
+#======================
+# Zookeeper dependencies
+# TODO(jtattermusch): is zookeeper still needed?
+RUN apt-get install -y libzookeeper-mt-dev
+
+RUN mkdir /var/local/jenkins
+
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 3204451169bd139c1c152dc523b88706668f2267..9533fbc7662ccc5d3a312e6fd7315f75f03a7043 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -854,7 +854,6 @@ src/cpp/client/create_channel_internal.cc \
 src/cpp/client/credentials.cc \
 src/cpp/client/generic_stub.cc \
 src/cpp/client/insecure_credentials.cc \
-src/cpp/common/alarm.cc \
 src/cpp/common/call.cc \
 src/cpp/common/channel_arguments.cc \
 src/cpp/common/completion_queue.cc \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index af9f1cb69363952008f456d80ddf769e71ea636a..c94ae87fcee4c38c31be646b11ecfa6f7e0f9fce 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -787,6 +787,7 @@ src/core/channel/subchannel_call_holder.h \
 src/core/client_config/client_config.h \
 src/core/client_config/connector.h \
 src/core/client_config/initial_connect_string.h \
+src/core/client_config/lb_policies/load_balancer_api.h \
 src/core/client_config/lb_policies/pick_first.h \
 src/core/client_config/lb_policies/round_robin.h \
 src/core/client_config/lb_policy.h \
@@ -837,7 +838,6 @@ src/core/iomgr/tcp_windows.h \
 src/core/iomgr/time_averaged_stats.h \
 src/core/iomgr/timer.h \
 src/core/iomgr/timer_heap.h \
-src/core/iomgr/timer_internal.h \
 src/core/iomgr/udp_server.h \
 src/core/iomgr/wakeup_fd_pipe.h \
 src/core/iomgr/wakeup_fd_posix.h \
@@ -848,6 +848,7 @@ src/core/json/json.h \
 src/core/json/json_common.h \
 src/core/json/json_reader.h \
 src/core/json/json_writer.h \
+src/core/proto/grpc/lb/v0/load_balancer.pb.h \
 src/core/statistics/census_interface.h \
 src/core/statistics/census_rpc_stats.h \
 src/core/surface/api_trace.h \
@@ -888,7 +889,7 @@ src/core/transport/static_metadata.h \
 src/core/transport/transport.h \
 src/core/transport/transport_impl.h \
 src/core/security/auth_filters.h \
-src/core/security/base64.h \
+src/core/security/b64.h \
 src/core/security/credentials.h \
 src/core/security/handshake.h \
 src/core/security/json_token.h \
@@ -904,6 +905,10 @@ src/core/tsi/transport_security_interface.h \
 src/core/census/aggregation.h \
 src/core/census/mlog.h \
 src/core/census/rpc_metric_id.h \
+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/census/grpc_context.c \
 src/core/census/grpc_filter.c \
 src/core/channel/channel_args.c \
@@ -919,6 +924,7 @@ src/core/client_config/client_config.c \
 src/core/client_config/connector.c \
 src/core/client_config/default_initial_connect_string.c \
 src/core/client_config/initial_connect_string.c \
+src/core/client_config/lb_policies/load_balancer_api.c \
 src/core/client_config/lb_policies/pick_first.c \
 src/core/client_config/lb_policies/round_robin.c \
 src/core/client_config/lb_policy.c \
@@ -933,7 +939,7 @@ src/core/client_config/subchannel.c \
 src/core/client_config/subchannel_factory.c \
 src/core/client_config/subchannel_index.c \
 src/core/client_config/uri_parser.c \
-src/core/compression/algorithm.c \
+src/core/compression/compression_algorithm.c \
 src/core/compression/message_compress.c \
 src/core/debug/trace.c \
 src/core/httpcli/format_request.c \
@@ -983,6 +989,7 @@ src/core/json/json.c \
 src/core/json/json_reader.c \
 src/core/json/json_string.c \
 src/core/json/json_writer.c \
+src/core/proto/grpc/lb/v0/load_balancer.pb.c \
 src/core/surface/alarm.c \
 src/core/surface/api_trace.c \
 src/core/surface/byte_buffer.c \
@@ -1033,7 +1040,7 @@ src/core/transport/static_metadata.c \
 src/core/transport/transport.c \
 src/core/transport/transport_op_string.c \
 src/core/httpcli/httpcli_security_connector.c \
-src/core/security/base64.c \
+src/core/security/b64.c \
 src/core/security/client_auth_filter.c \
 src/core/security/credentials.c \
 src/core/security/credentials_metadata.c \
@@ -1059,6 +1066,9 @@ src/core/census/mlog.c \
 src/core/census/operation.c \
 src/core/census/placeholders.c \
 src/core/census/tracing.c \
+third_party/nanopb/pb_common.c \
+third_party/nanopb/pb_decode.c \
+third_party/nanopb/pb_encode.c \
 include/grpc/support/alloc.h \
 include/grpc/support/atm.h \
 include/grpc/support/atm_gcc_atomic.h \
@@ -1104,13 +1114,14 @@ include/grpc/impl/codegen/time.h \
 src/core/profiling/timers.h \
 src/core/support/block_annotate.h \
 src/core/support/env.h \
-src/core/support/file.h \
+src/core/support/load_file.h \
 src/core/support/murmur_hash.h \
 src/core/support/stack_lockfree.h \
 src/core/support/string.h \
 src/core/support/string_win32.h \
 src/core/support/thd_internal.h \
 src/core/support/time_precise.h \
+src/core/support/tmpfile.h \
 src/core/profiling/basic_timers.c \
 src/core/profiling/stap_timers.c \
 src/core/support/alloc.c \
@@ -1123,11 +1134,9 @@ src/core/support/cpu_windows.c \
 src/core/support/env_linux.c \
 src/core/support/env_posix.c \
 src/core/support/env_win32.c \
-src/core/support/file.c \
-src/core/support/file_posix.c \
-src/core/support/file_win32.c \
 src/core/support/histogram.c \
 src/core/support/host_port.c \
+src/core/support/load_file.c \
 src/core/support/log.c \
 src/core/support/log_android.c \
 src/core/support/log_linux.c \
@@ -1153,6 +1162,8 @@ src/core/support/time_posix.c \
 src/core/support/time_precise.c \
 src/core/support/time_win32.c \
 src/core/support/tls_pthread.c \
+src/core/support/tmpfile_posix.c \
+src/core/support/tmpfile_win32.c \
 src/core/support/wrap_memcpy.c
 
 # This tag can be used to specify the character encoding of the source files
diff --git a/tools/gcp/stress_test/run_client.py b/tools/gcp/stress_test/run_client.py
new file mode 100755
index 0000000000000000000000000000000000000000..0fa1bf1cb975d11cd75578ffeaab3142857aca14
--- /dev/null
+++ b/tools/gcp/stress_test/run_client.py
@@ -0,0 +1,187 @@
+#!/usr/bin/env python2.7
+# Copyright 2015-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.
+
+import datetime
+import os
+import re
+import select
+import subprocess
+import sys
+import time
+
+from stress_test_utils import EventType
+from stress_test_utils import BigQueryHelper
+
+
+# TODO (sree): Write a python grpc client to directly query the metrics instead
+# of calling metrics_client
+def _get_qps(metrics_cmd):
+  qps = 0
+  try:
+    # Note: gpr_log() writes even non-error messages to stderr stream. So it is 
+    # important that we set stderr=subprocess.STDOUT
+    p = subprocess.Popen(args=metrics_cmd,
+                         stdout=subprocess.PIPE,
+                         stderr=subprocess.STDOUT)
+    retcode = p.wait()
+    (out_str, err_str) = p.communicate()
+    if retcode != 0:
+      print 'Error in reading metrics information'
+      print 'Output: ', out_str
+    else:
+      # The overall qps is printed at the end of the line
+      m = re.search('\d+$', out_str)
+      qps = int(m.group()) if m else 0
+  except Exception as ex:
+    print 'Exception while reading metrics information: ' + str(ex)
+  return qps
+
+
+def run_client():
+  """This is a wrapper around the stress test client and performs the following:
+      1) Create the following two tables in Big Query:
+         (i) Summary table: To record events like the test started, completed
+                            successfully or failed
+        (ii) Qps table: To periodically record the QPS sent by this client
+      2) Start the stress test client and add a row in the Big Query summary
+         table
+      3) Once every few seconds (as specificed by the poll_interval_secs) poll
+         the status of the stress test client process and perform the
+         following:
+          3.1) If the process is still running, get the current qps by invoking
+               the metrics client program and add a row in the Big Query
+               Qps table. Sleep for a duration specified by poll_interval_secs
+          3.2) If the process exited successfully, add a row in the Big Query
+               Summary table and exit
+          3.3) If the process failed, add a row in Big Query summary table and
+               wait forever.
+               NOTE: This script typically runs inside a GKE pod which means
+               that the pod gets destroyed when the script exits. However, in
+               case the stress test client fails, we would not want the pod to
+               be destroyed (since we might want to connect to the pod for
+               examining logs). This is the reason why the script waits forever
+               in case of failures
+  """
+  env = dict(os.environ)
+  image_type = env['STRESS_TEST_IMAGE_TYPE']
+  image_name = env['STRESS_TEST_IMAGE']
+  args_str = env['STRESS_TEST_ARGS_STR']
+  metrics_client_image = env['METRICS_CLIENT_IMAGE']
+  metrics_client_args_str = env['METRICS_CLIENT_ARGS_STR']
+  run_id = env['RUN_ID']
+  pod_name = env['POD_NAME']
+  logfile_name = env.get('LOGFILE_NAME')
+  poll_interval_secs = float(env['POLL_INTERVAL_SECS'])
+  project_id = env['GCP_PROJECT_ID']
+  dataset_id = env['DATASET_ID']
+  summary_table_id = env['SUMMARY_TABLE_ID']
+  qps_table_id = env['QPS_TABLE_ID']
+
+  bq_helper = BigQueryHelper(run_id, image_type, pod_name, project_id,
+                             dataset_id, summary_table_id, qps_table_id)
+  bq_helper.initialize()
+
+  # Create BigQuery Dataset and Tables: Summary Table and Metrics Table
+  if not bq_helper.setup_tables():
+    print 'Error in creating BigQuery tables'
+    return
+
+  start_time = datetime.datetime.now()
+
+  logfile = None
+  details = 'Logging to stdout'
+  if logfile_name is not None:
+    print 'Opening logfile: %s ...' % logfile_name
+    details = 'Logfile: %s' % logfile_name
+    logfile = open(logfile_name, 'w')
+
+  # Update status that the test is starting (in the status table)
+  bq_helper.insert_summary_row(EventType.STARTING, details)
+
+  metrics_cmd = [metrics_client_image
+                ] + [x for x in metrics_client_args_str.split()]
+  stress_cmd = [image_name] + [x for x in args_str.split()]
+
+  print 'Launching process %s ...' % stress_cmd
+  stress_p = subprocess.Popen(args=stress_cmd,
+                              stdout=logfile,
+                              stderr=subprocess.STDOUT)
+
+  qps_history = [1, 1, 1]  # Maintain the last 3 qps readings
+  qps_history_idx = 0  # Index into the qps_history list
+
+  is_error = False
+  while True:
+    # Check if stress_client is still running. If so, collect metrics and upload
+    # to BigQuery status table
+    if stress_p.poll() is not None:
+      end_time = datetime.datetime.now().isoformat()
+      event_type = EventType.SUCCESS
+      details = 'End time: %s' % end_time
+      if stress_p.returncode != 0:
+        event_type = EventType.FAILURE
+        details = 'Return code = %d. End time: %s' % (stress_p.returncode,
+                                                      end_time)
+        is_error = True
+      bq_helper.insert_summary_row(event_type, details)
+      print details
+      break
+
+    # Stress client still running. Get metrics
+    qps = _get_qps(metrics_cmd)
+    qps_recorded_at = datetime.datetime.now().isoformat()
+    print 'qps: %d at %s' % (qps, qps_recorded_at)
+
+    # If QPS has been zero for the last 3 iterations, flag it as error and exit
+    qps_history[qps_history_idx] = qps
+    qps_history_idx = (qps_history_idx + 1) % len(qps_history)
+    if sum(qps_history) == 0:
+      details = 'QPS has been zero for the last %d seconds - as of : %s' % (
+          poll_interval_secs * 3, qps_recorded_at)
+      is_error = True
+      bq_helper.insert_summary_row(EventType.FAILURE, details)
+      print details
+      break
+
+    # Upload qps metrics to BiqQuery
+    bq_helper.insert_qps_row(qps, qps_recorded_at)
+
+    time.sleep(poll_interval_secs)
+
+  if is_error:
+    print 'Waiting indefinitely..'
+    select.select([], [], [])
+
+  print 'Completed'
+  return
+
+
+if __name__ == '__main__':
+  run_client()
diff --git a/tools/gcp/stress_test/run_server.py b/tools/gcp/stress_test/run_server.py
new file mode 100755
index 0000000000000000000000000000000000000000..64322f61004f22349c95dc25a8f22105159a0b95
--- /dev/null
+++ b/tools/gcp/stress_test/run_server.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python2.7
+# Copyright 2015-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.
+
+import datetime
+import os
+import select
+import subprocess
+import sys
+import time
+
+from stress_test_utils import BigQueryHelper
+from stress_test_utils import EventType
+
+
+def run_server():
+  """This is a wrapper around the interop server and performs the following:
+      1) Create a 'Summary table' in Big Query to record events like the server
+         started, completed successfully or failed. NOTE: This also creates
+         another table called the QPS table which is currently NOT needed on the
+         server (it is needed on the stress test clients)
+      2) Start the server process and add a row in Big Query summary table
+      3) Wait for the server process to terminate. The server process does not
+         terminate unless there is an error.
+         If the server process terminated with a failure, add a row in Big Query
+         and wait forever.
+         NOTE: This script typically runs inside a GKE pod which means that the
+         pod gets destroyed when the script exits. However, in case the server
+         process fails, we would not want the pod to be destroyed (since we
+         might want to connect to the pod for examining logs). This is the
+         reason why the script waits forever in case of failures.
+  """
+
+  # Read the parameters from environment variables
+  env = dict(os.environ)
+
+  run_id = env['RUN_ID']  # The unique run id for this test
+  image_type = env['STRESS_TEST_IMAGE_TYPE']
+  image_name = env['STRESS_TEST_IMAGE']
+  args_str = env['STRESS_TEST_ARGS_STR']
+  pod_name = env['POD_NAME']
+  project_id = env['GCP_PROJECT_ID']
+  dataset_id = env['DATASET_ID']
+  summary_table_id = env['SUMMARY_TABLE_ID']
+  qps_table_id = env['QPS_TABLE_ID']
+
+  logfile_name = env.get('LOGFILE_NAME')
+
+  print('pod_name: %s, project_id: %s, run_id: %s, dataset_id: %s, '
+        'summary_table_id: %s, qps_table_id: %s') % (
+            pod_name, project_id, run_id, dataset_id, summary_table_id,
+            qps_table_id)
+
+  bq_helper = BigQueryHelper(run_id, image_type, pod_name, project_id,
+                             dataset_id, summary_table_id, qps_table_id)
+  bq_helper.initialize()
+
+  # Create BigQuery Dataset and Tables: Summary Table and Metrics Table
+  if not bq_helper.setup_tables():
+    print 'Error in creating BigQuery tables'
+    return
+
+  start_time = datetime.datetime.now()
+
+  logfile = None
+  details = 'Logging to stdout'
+  if logfile_name is not None:
+    print 'Opening log file: ', logfile_name
+    logfile = open(logfile_name, 'w')
+    details = 'Logfile: %s' % logfile_name
+
+  # Update status that the test is starting (in the status table)
+  bq_helper.insert_summary_row(EventType.STARTING, details)
+
+  stress_cmd = [image_name] + [x for x in args_str.split()]
+
+  print 'Launching process %s ...' % stress_cmd
+  stress_p = subprocess.Popen(args=stress_cmd,
+                              stdout=logfile,
+                              stderr=subprocess.STDOUT)
+
+  returncode = stress_p.wait()
+  if returncode != 0:
+    end_time = datetime.datetime.now().isoformat()
+    event_type = EventType.FAILURE
+    details = 'Returncode: %d; End time: %s' % (returncode, end_time)
+    bq_helper.insert_summary_row(event_type, details)
+    print 'Waiting indefinitely..'
+    select.select([], [], [])
+  return returncode
+
+
+if __name__ == '__main__':
+  run_server()
diff --git a/tools/gcp/stress_test/stress_test_utils.py b/tools/gcp/stress_test/stress_test_utils.py
new file mode 100755
index 0000000000000000000000000000000000000000..c4b437e3459daf0d5314f21ac26caf4d37095e6f
--- /dev/null
+++ b/tools/gcp/stress_test/stress_test_utils.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python2.7
+# Copyright 2015-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.
+
+import datetime
+import json
+import os
+import re
+import select
+import subprocess
+import sys
+import time
+
+# Import big_query_utils module
+bq_utils_dir = os.path.abspath(os.path.join(
+    os.path.dirname(__file__), '../utils'))
+sys.path.append(bq_utils_dir)
+import big_query_utils as bq_utils
+
+
+class EventType:
+  STARTING = 'STARTING'
+  SUCCESS = 'SUCCESS'
+  FAILURE = 'FAILURE'
+
+
+class BigQueryHelper:
+  """Helper class for the stress test wrappers to interact with BigQuery.
+  """
+
+  def __init__(self, run_id, image_type, pod_name, project_id, dataset_id,
+               summary_table_id, qps_table_id):
+    self.run_id = run_id
+    self.image_type = image_type
+    self.pod_name = pod_name
+    self.project_id = project_id
+    self.dataset_id = dataset_id
+    self.summary_table_id = summary_table_id
+    self.qps_table_id = qps_table_id
+
+  def initialize(self):
+    self.bq = bq_utils.create_big_query()
+
+  def setup_tables(self):
+    return bq_utils.create_dataset(self.bq, self.project_id, self.dataset_id) \
+        and self.__create_summary_table() \
+        and self.__create_qps_table()
+
+  def insert_summary_row(self, event_type, details):
+    row_values_dict = {
+        'run_id': self.run_id,
+        'image_type': self.image_type,
+        'pod_name': self.pod_name,
+        'event_date': datetime.datetime.now().isoformat(),
+        'event_type': event_type,
+        'details': details
+    }
+    # row_unique_id is something that uniquely identifies the row (BigQuery uses
+    # it for duplicate detection).
+    row_unique_id = '%s_%s_%s' % (self.run_id, self.pod_name, event_type)
+    row = bq_utils.make_row(row_unique_id, row_values_dict)
+    return bq_utils.insert_rows(self.bq, self.project_id, self.dataset_id,
+                                self.summary_table_id, [row])
+
+  def insert_qps_row(self, qps, recorded_at):
+    row_values_dict = {
+        'run_id': self.run_id,
+        'pod_name': self.pod_name,
+        'recorded_at': recorded_at,
+        'qps': qps
+    }
+
+    # row_unique_id is something that uniquely identifies the row (BigQuery uses
+    # it for duplicate detection).
+    row_unique_id = '%s_%s_%s' % (self.run_id, self.pod_name, recorded_at)
+    row = bq_utils.make_row(row_unique_id, row_values_dict)
+    return bq_utils.insert_rows(self.bq, self.project_id, self.dataset_id,
+                                self.qps_table_id, [row])
+
+  def check_if_any_tests_failed(self, num_query_retries=3):
+    query = ('SELECT event_type FROM %s.%s WHERE run_id = \'%s\' AND '
+             'event_type="%s"') % (self.dataset_id, self.summary_table_id,
+                                   self.run_id, EventType.FAILURE)
+    query_job = bq_utils.sync_query_job(self.bq, self.project_id, query)
+    page = self.bq.jobs().getQueryResults(**query_job['jobReference']).execute(
+        num_retries=num_query_retries)
+    num_failures = int(page['totalRows'])
+    print 'num rows: ', num_failures
+    return num_failures > 0
+
+  def print_summary_records(self, num_query_retries=3):
+    line = '-' * 120
+    print line
+    print 'Summary records'
+    print 'Run Id: ', self.run_id
+    print 'Dataset Id: ', self.dataset_id
+    print line
+    query = ('SELECT pod_name, image_type, event_type, event_date, details'
+             ' FROM %s.%s WHERE run_id = \'%s\' ORDER by event_date;') % (
+                 self.dataset_id, self.summary_table_id, self.run_id)
+    query_job = bq_utils.sync_query_job(self.bq, self.project_id, query)
+
+    print '{:<25} {:<12} {:<12} {:<30} {}'.format(
+        'Pod name', 'Image type', 'Event type', 'Date', 'Details')
+    print line
+    page_token = None
+    while True:
+      page = self.bq.jobs().getQueryResults(
+          pageToken=page_token,
+          **query_job['jobReference']).execute(num_retries=num_query_retries)
+      rows = page.get('rows', [])
+      for row in rows:
+        print '{:<25} {:<12} {:<12} {:<30} {}'.format(
+            row['f'][0]['v'], row['f'][1]['v'], row['f'][2]['v'],
+            row['f'][3]['v'], row['f'][4]['v'])
+      page_token = page.get('pageToken')
+      if not page_token:
+        break
+
+  def print_qps_records(self, num_query_retries=3):
+    line = '-' * 80
+    print line
+    print 'QPS Summary'
+    print 'Run Id: ', self.run_id
+    print 'Dataset Id: ', self.dataset_id
+    print line
+    query = (
+        'SELECT pod_name, recorded_at, qps FROM %s.%s WHERE run_id = \'%s\' '
+        'ORDER by recorded_at;') % (self.dataset_id, self.qps_table_id,
+                                    self.run_id)
+    query_job = bq_utils.sync_query_job(self.bq, self.project_id, query)
+    print '{:<25} {:30} {}'.format('Pod name', 'Recorded at', 'Qps')
+    print line
+    page_token = None
+    while True:
+      page = self.bq.jobs().getQueryResults(
+          pageToken=page_token,
+          **query_job['jobReference']).execute(num_retries=num_query_retries)
+      rows = page.get('rows', [])
+      for row in rows:
+        print '{:<25} {:30} {}'.format(row['f'][0]['v'], row['f'][1]['v'],
+                                       row['f'][2]['v'])
+      page_token = page.get('pageToken')
+      if not page_token:
+        break
+
+  def __create_summary_table(self):
+    summary_table_schema = [
+        ('run_id', 'STRING', 'Test run id'),
+        ('image_type', 'STRING', 'Client or Server?'),
+        ('pod_name', 'STRING', 'GKE pod hosting this image'),
+        ('event_date', 'STRING', 'The date of this event'),
+        ('event_type', 'STRING', 'STARTED/SUCCESS/FAILURE'),
+        ('details', 'STRING', 'Any other relevant details')
+    ]
+    desc = ('The table that contains START/SUCCESS/FAILURE events for '
+            ' the stress test clients and servers')
+    return bq_utils.create_table(self.bq, self.project_id, self.dataset_id,
+                                 self.summary_table_id, summary_table_schema,
+                                 desc)
+
+  def __create_qps_table(self):
+    qps_table_schema = [
+        ('run_id', 'STRING', 'Test run id'),
+        ('pod_name', 'STRING', 'GKE pod hosting this image'),
+        ('recorded_at', 'STRING', 'Metrics recorded at time'),
+        ('qps', 'INTEGER', 'Queries per second')
+    ]
+    desc = 'The table that cointains the qps recorded at various intervals'
+    return bq_utils.create_table(self.bq, self.project_id, self.dataset_id,
+                                 self.qps_table_id, qps_table_schema, desc)
diff --git a/tools/gcp/utils/big_query_utils.py b/tools/gcp/utils/big_query_utils.py
new file mode 100755
index 0000000000000000000000000000000000000000..7bb1e143549154279e3e90b8b5d93871303ec0b6
--- /dev/null
+++ b/tools/gcp/utils/big_query_utils.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python2.7
+# Copyright 2015-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.
+
+import argparse
+import json
+import uuid
+import httplib2
+
+from apiclient import discovery
+from apiclient.errors import HttpError
+from oauth2client.client import GoogleCredentials
+
+NUM_RETRIES = 3
+
+
+def create_big_query():
+  """Authenticates with cloud platform and gets a BiqQuery service object
+  """
+  creds = GoogleCredentials.get_application_default()
+  return discovery.build('bigquery', 'v2', credentials=creds)
+
+
+def create_dataset(biq_query, project_id, dataset_id):
+  is_success = True
+  body = {
+      'datasetReference': {
+          'projectId': project_id,
+          'datasetId': dataset_id
+      }
+  }
+
+  try:
+    dataset_req = biq_query.datasets().insert(projectId=project_id, body=body)
+    dataset_req.execute(num_retries=NUM_RETRIES)
+  except HttpError as http_error:
+    if http_error.resp.status == 409:
+      print 'Warning: The dataset %s already exists' % dataset_id
+    else:
+      # Note: For more debugging info, print "http_error.content"
+      print 'Error in creating dataset: %s. Err: %s' % (dataset_id, http_error)
+      is_success = False
+  return is_success
+
+
+def create_table(big_query, project_id, dataset_id, table_id, table_schema,
+                 description):
+  is_success = True
+
+  body = {
+      'description': description,
+      'schema': {
+          'fields': [{
+              'name': field_name,
+              'type': field_type,
+              'description': field_description
+          } for (field_name, field_type, field_description) in table_schema]
+      },
+      'tableReference': {
+          'datasetId': dataset_id,
+          'projectId': project_id,
+          'tableId': table_id
+      }
+  }
+
+  try:
+    table_req = big_query.tables().insert(projectId=project_id,
+                                          datasetId=dataset_id,
+                                          body=body)
+    res = table_req.execute(num_retries=NUM_RETRIES)
+    print 'Successfully created %s "%s"' % (res['kind'], res['id'])
+  except HttpError as http_error:
+    if http_error.resp.status == 409:
+      print 'Warning: Table %s already exists' % table_id
+    else:
+      print 'Error in creating table: %s. Err: %s' % (table_id, http_error)
+      is_success = False
+  return is_success
+
+
+def insert_rows(big_query, project_id, dataset_id, table_id, rows_list):
+  is_success = True
+  body = {'rows': rows_list}
+  try:
+    insert_req = big_query.tabledata().insertAll(projectId=project_id,
+                                                 datasetId=dataset_id,
+                                                 tableId=table_id,
+                                                 body=body)
+    print body
+    res = insert_req.execute(num_retries=NUM_RETRIES)
+    print res
+  except HttpError as http_error:
+    print 'Error in inserting rows in the table %s' % table_id
+    is_success = False
+  return is_success
+
+
+def sync_query_job(big_query, project_id, query, timeout=5000):
+  query_data = {'query': query, 'timeoutMs': timeout}
+  query_job = None
+  try:
+    query_job = big_query.jobs().query(
+        projectId=project_id,
+        body=query_data).execute(num_retries=NUM_RETRIES)
+  except HttpError as http_error:
+    print 'Query execute job failed with error: %s' % http_error
+    print http_error.content
+  return query_job
+
+  # List of (column name, column type, description) tuples
+def make_row(unique_row_id, row_values_dict):
+  """row_values_dict is a dictionary of column name and column value.
+  """
+  return {'insertId': unique_row_id, 'json': row_values_dict}
diff --git a/tools/gke/kubernetes_api.py b/tools/gcp/utils/kubernetes_api.py
similarity index 74%
rename from tools/gke/kubernetes_api.py
rename to tools/gcp/utils/kubernetes_api.py
index 7dd30153650383a5669e07cb82283f226b7ec968..e8ddd2f1b3502dff664f61a1933833d6fc271108 100755
--- a/tools/gke/kubernetes_api.py
+++ b/tools/gcp/utils/kubernetes_api.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python2.7
-# Copyright 2015, Google Inc.
+# Copyright 2015-2016, Google Inc.
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,9 @@ import json
 
 _REQUEST_TIMEOUT_SECS = 10
 
+
 def _make_pod_config(pod_name, image_name, container_port_list, cmd_list,
-                    arg_list):
+                     arg_list, env_dict):
   """Creates a string containing the Pod defintion as required by the Kubernetes API"""
   body = {
       'kind': 'Pod',
@@ -48,20 +49,23 @@ def _make_pod_config(pod_name, image_name, container_port_list, cmd_list,
               {
                   'name': pod_name,
                   'image': image_name,
-                  'ports': []
+                  'ports': [{'containerPort': port,
+                             'protocol': 'TCP'}
+                            for port in container_port_list],
+                  'imagePullPolicy': 'Always'
               }
           ]
       }
   }
-  # Populate the 'ports' list
-  for port in container_port_list:
-    port_entry = {'containerPort': port, 'protocol': 'TCP'}
-    body['spec']['containers'][0]['ports'].append(port_entry)
+
+  env_list = [{'name': k, 'value': v} for (k, v) in env_dict.iteritems()]
+  if len(env_list) > 0:
+    body['spec']['containers'][0]['env'] = env_list
 
   # Add the 'Command' and 'Args' attributes if they are passed.
   # Note:
   #  - 'Command' overrides the ENTRYPOINT in the Docker Image
-  #  - 'Args' override the COMMAND in Docker image (yes, it is confusing!)
+  #  - 'Args' override the CMD in Docker image (yes, it is confusing!)
   if len(cmd_list) > 0:
     body['spec']['containers'][0]['command'] = cmd_list
   if len(arg_list) > 0:
@@ -70,7 +74,7 @@ def _make_pod_config(pod_name, image_name, container_port_list, cmd_list,
 
 
 def _make_service_config(service_name, pod_name, service_port_list,
-                        container_port_list, is_headless):
+                         container_port_list, is_headless):
   """Creates a string containing the Service definition as required by the Kubernetes API.
 
   NOTE:
@@ -124,6 +128,7 @@ def _print_connection_error(msg):
   print('ERROR: Connection failed. Did you remember to run Kubenetes proxy on '
         'localhost (i.e kubectl proxy --port=<proxy_port>) ?. Error: %s' % msg)
 
+
 def _do_post(post_url, api_name, request_body):
   """Helper to do HTTP POST.
 
@@ -135,7 +140,9 @@ def _do_post(post_url, api_name, request_body):
   """
   is_success = True
   try:
-    r = requests.post(post_url, data=request_body, timeout=_REQUEST_TIMEOUT_SECS)
+    r = requests.post(post_url,
+                      data=request_body,
+                      timeout=_REQUEST_TIMEOUT_SECS)
     if r.status_code == requests.codes.conflict:
       print('WARN: Looks like the resource already exists. Api: %s, url: %s' %
             (api_name, post_url))
@@ -143,7 +150,8 @@ def _do_post(post_url, api_name, request_body):
       print('ERROR: %s API returned error. HTTP response: (%d) %s' %
             (api_name, r.status_code, r.text))
       is_success = False
-  except(requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
+  except (requests.exceptions.Timeout,
+          requests.exceptions.ConnectionError) as e:
     is_success = False
     _print_connection_error(str(e))
   return is_success
@@ -165,7 +173,8 @@ def _do_delete(del_url, api_name):
       print('ERROR: %s API returned error. HTTP response: %s' %
             (api_name, r.text))
       is_success = False
-  except(requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
+  except (requests.exceptions.Timeout,
+          requests.exceptions.ConnectionError) as e:
     is_success = False
     _print_connection_error(str(e))
   return is_success
@@ -179,12 +188,12 @@ def create_service(kube_host, kube_port, namespace, service_name, pod_name,
   post_url = 'http://%s:%d/api/v1/namespaces/%s/services' % (
       kube_host, kube_port, namespace)
   request_body = _make_service_config(service_name, pod_name, service_port_list,
-                                     container_port_list, is_headless)
+                                      container_port_list, is_headless)
   return _do_post(post_url, 'Create Service', request_body)
 
 
 def create_pod(kube_host, kube_port, namespace, pod_name, image_name,
-               container_port_list, cmd_list, arg_list):
+               container_port_list, cmd_list, arg_list, env_dict):
   """Creates a Kubernetes Pod.
 
   Note that it is generally NOT considered a good practice to directly create
@@ -200,7 +209,7 @@ def create_pod(kube_host, kube_port, namespace, pod_name, image_name,
   post_url = 'http://%s:%d/api/v1/namespaces/%s/pods' % (kube_host, kube_port,
                                                          namespace)
   request_body = _make_pod_config(pod_name, image_name, container_port_list,
-                                 cmd_list, arg_list)
+                                  cmd_list, arg_list, env_dict)
   return _do_post(post_url, 'Create Pod', request_body)
 
 
@@ -214,3 +223,47 @@ def delete_pod(kube_host, kube_port, namespace, pod_name):
   del_url = 'http://%s:%d/api/v1/namespaces/%s/pods/%s' % (kube_host, kube_port,
                                                            namespace, pod_name)
   return _do_delete(del_url, 'Delete Pod')
+
+
+def create_pod_and_service(kube_host, kube_port, namespace, pod_name,
+                           image_name, container_port_list, cmd_list, arg_list,
+                           env_dict, is_headless_service):
+  """A helper function that creates a pod and a service (if pod creation was successful)."""
+  is_success = create_pod(kube_host, kube_port, namespace, pod_name, image_name,
+                          container_port_list, cmd_list, arg_list, env_dict)
+  if not is_success:
+    print 'Error in creating Pod'
+    return False
+
+  is_success = create_service(
+      kube_host,
+      kube_port,
+      namespace,
+      pod_name,  # Use pod_name for service
+      pod_name,
+      container_port_list,  # Service port list same as container port list
+      container_port_list,
+      is_headless_service)
+  if not is_success:
+    print 'Error in creating Service'
+    return False
+
+  print 'Successfully created the pod/service %s' % pod_name
+  return True
+
+
+def delete_pod_and_service(kube_host, kube_port, namespace, pod_name):
+  """ A helper function that calls delete_pod and delete_service """
+  is_success = delete_pod(kube_host, kube_port, namespace, pod_name)
+  if not is_success:
+    print 'Error in deleting pod %s' % pod_name
+    return False
+
+  # Note: service name assumed to the the same as pod name
+  is_success = delete_service(kube_host, kube_port, namespace, pod_name)
+  if not is_success:
+    print 'Error in deleting service %s' % pod_name
+    return False
+
+  print 'Successfully deleted the Pod/Service: %s' % pod_name
+  return True
diff --git a/tools/jenkins/build_docker_and_run_tests.sh b/tools/jenkins/build_docker_and_run_tests.sh
index e2ac7518f09992e9088852df21ca8cfe92d8fe75..458e8ca0c70b0dfa9e3f4d77e58d22b923e1e2e9 100755
--- a/tools/jenkins/build_docker_and_run_tests.sh
+++ b/tools/jenkins/build_docker_and_run_tests.sh
@@ -60,6 +60,9 @@ docker build -t $DOCKER_IMAGE_NAME $DOCKERFILE_DIR
 # Choose random name for docker container
 CONTAINER_NAME="run_tests_$(uuidgen)"
 
+# Git root as seen by the docker instance
+docker_instance_git_root=/var/local/jenkins/grpc
+
 # Run tests inside docker
 docker run \
   -e "RUN_TESTS_COMMAND=$RUN_TESTS_COMMAND" \
@@ -69,9 +72,10 @@ docker run \
   -e XDG_CACHE_HOME=/tmp/xdg-cache-home \
   -e THIS_IS_REALLY_NEEDED='see https://github.com/docker/docker/issues/14203 for why docker is awful' \
   -e HOST_GIT_ROOT=$git_root \
+  -e LOCAL_GIT_ROOT=$docker_instance_git_root \
   -e "BUILD_ID=$BUILD_ID" \
   -i $TTY_FLAG \
-  -v "$git_root:/var/local/jenkins/grpc" \
+  -v "$git_root:$docker_instance_git_root" \
   -v /tmp/ccache:/tmp/ccache \
   -v /tmp/npm-cache:/tmp/npm-cache \
   -v /tmp/xdg-cache-home:/tmp/xdg-cache-home \
@@ -82,11 +86,6 @@ docker run \
   $DOCKER_IMAGE_NAME \
   bash -l "/var/local/jenkins/grpc/$DOCKER_RUN_SCRIPT" || DOCKER_FAILED="true"
 
-if [ "$XML_REPORT" != "" ]
-then
-  docker cp "$CONTAINER_NAME:/var/local/git/grpc/$XML_REPORT" $git_root || true
-fi
-
 docker cp "$CONTAINER_NAME:/var/local/git/grpc/reports.zip" $git_root || true
 unzip -o $git_root/reports.zip -d $git_root || true
 rm -f reports.zip
diff --git a/tools/jenkins/build_interop_stress_image.sh b/tools/jenkins/build_interop_stress_image.sh
index 92f2dab5e34be0bc8012137e6d00527aeaffb1ef..501dc5b7ca4a41ff801c5bf6550426b652adb8e2 100755
--- a/tools/jenkins/build_interop_stress_image.sh
+++ b/tools/jenkins/build_interop_stress_image.sh
@@ -35,6 +35,8 @@ set -x
 
 # Params:
 #  INTEROP_IMAGE - name of tag of the final interop image
+#  INTEROP_IMAGE_TAG - Optional. If set, the created image will be tagged using
+#    the command: 'docker tag $INTEROP_IMAGE $INTEROP_IMAGE_REPOSITORY_TAG'
 #  BASE_NAME - base name used to locate the base Dockerfile and build script
 #  TTY_FLAG - optional -t flag to make docker allocate tty
 #  BUILD_INTEROP_DOCKER_EXTRA_ARGS - optional args to be passed to the
@@ -77,6 +79,7 @@ CONTAINER_NAME="build_${BASE_NAME}_$(uuidgen)"
   $BASE_IMAGE \
   bash -l /var/local/jenkins/grpc/tools/dockerfile/$BASE_NAME/build_interop_stress.sh \
   && docker commit $CONTAINER_NAME $INTEROP_IMAGE \
+  && ( if [ -n "$INTEROP_IMAGE_REPOSITORY_TAG" ]; then docker tag -f $INTEROP_IMAGE $INTEROP_IMAGE_REPOSITORY_TAG ; fi ) \
   && echo "Successfully built image $INTEROP_IMAGE")
 EXITCODE=$?
 
diff --git a/tools/jenkins/docker_run.sh b/tools/jenkins/docker_run.sh
index df7b6571d7a455a0a2f02498d300371a17579d0d..f04b1cfb55be69e017ec4b200fa9d6daf9b03207 100755
--- a/tools/jenkins/docker_run.sh
+++ b/tools/jenkins/docker_run.sh
@@ -42,6 +42,8 @@ else
   cp -r "$EXTERNAL_GIT_ROOT/$RELATIVE_COPY_PATH"/* "/var/local/git/grpc/$RELATIVE_COPY_PATH"
 fi
 
+$POST_GIT_STEP
+
 if [ -x "$(command -v rvm)" ]
 then
   rvm use ruby-2.1
diff --git a/tools/jenkins/docker_run_tests.sh b/tools/jenkins/docker_run_tests.sh
index 282b85735110284599540571f81b17607e9b48ca..8d6c42cd9bf4710524eb025456b455a8892c2c67 100755
--- a/tools/jenkins/docker_run_tests.sh
+++ b/tools/jenkins/docker_run_tests.sh
@@ -45,6 +45,8 @@ git clone --recursive /var/local/jenkins/grpc /var/local/git/grpc
 
 mkdir -p reports
 
+$POST_GIT_STEP
+
 exit_code=0
 
 $RUN_TESTS_COMMAND || exit_code=$?
@@ -60,5 +62,6 @@ echo '</body></html>' >> index.html
 cd ..
 
 zip -r reports.zip reports
+find . -name report.xml | xargs zip reports.zip
 
 exit $exit_code
diff --git a/tools/jenkins/run_performance.sh b/tools/jenkins/run_performance.sh
index c80685b23a09d51b9737b896838b988b08e155d7..fbc078330f72daf57a7e4e301488972ed4cfb0c4 100755
--- a/tools/jenkins/run_performance.sh
+++ b/tools/jenkins/run_performance.sh
@@ -47,6 +47,11 @@ PID1=$!
 bins/$config/qps_worker -driver_port 10010 &
 PID2=$!
 
+#
+# Put a timeout on these tests
+#
+((sleep 900; kill $$ && killall qps_worker && rm -f /tmp/qps-test.$$ )&)
+
 export QPS_WORKERS="localhost:10000,localhost:10010"
 
 # big is the size in bytes of large messages (0 is the size otherwise)
diff --git a/tools/openssl/use_openssl.sh b/tools/openssl/use_openssl.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3098217ec1b54a4cf2f677994fedcf03730b052d
--- /dev/null
+++ b/tools/openssl/use_openssl.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+# Copyright 2015-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.
+
+set -ex
+
+cd $(dirname $0)/../..
+set root=`pwd`
+CC=${CC:-cc}
+
+# allow openssl to be pre-downloaded
+if [ ! -e third_party/openssl-1.0.2f.tar.gz ]
+then
+  echo "Downloading http://openssl.org/source/openssl-1.0.2f.tar.gz to third_party/openssl-1.0.2f.tar.gz"
+  wget http://openssl.org/source/openssl-1.0.2f.tar.gz -O third_party/openssl-1.0.2f.tar.gz
+fi
+
+# clean openssl directory
+rm -rf third_party/openssl-1.0.2f
+
+# extract archive
+cd third_party
+tar xfz openssl-1.0.2f.tar.gz
+
+# build openssl
+cd openssl-1.0.2f
+CC="$CC -fPIC -fvisibility=hidden" ./config no-asm
+make
+
+# generate the 'grpc_obj' directory needed by the makefile
+mkdir grpc_obj
+cd grpc_obj
+ar x ../libcrypto.a
+ar x ../libssl.a
diff --git a/tools/run_tests/artifact_targets.py b/tools/run_tests/artifact_targets.py
index b565fbb3f0357145b870c838251e7add3cd1f605..e61c46d8b5aa2d9eba1ae427b947d6f45aabdc73 100644
--- a/tools/run_tests/artifact_targets.py
+++ b/tools/run_tests/artifact_targets.py
@@ -69,16 +69,12 @@ def create_jobspec(name, cmdline, environ=None, shell=False,
   return jobspec
 
 
-def macos_arch_env(arch):
-  """Returns environ specifying -arch arguments for make."""
-  if arch == 'x86':
-    arch_arg = '-arch i386'
-  elif arch == 'x64':
-    arch_arg = '-arch x86_64'
-  else:
-    raise Exception('Unsupported arch')
-  return {'CFLAGS': arch_arg, 'LDFLAGS': arch_arg}
+_MACOS_COMPAT_FLAG = '-mmacosx-version-min=10.7'
 
+_ARCH_FLAG_MAP = {
+  'x86': '-m32',
+  'x64': '-m64'
+}
 
 python_version_arch_map = {
   'x86': 'Python27_32bits',
@@ -185,13 +181,17 @@ class CSharpExtArtifact:
       environ = {'CONFIG': 'opt',
                  'EMBED_OPENSSL': 'true',
                  'EMBED_ZLIB': 'true',
-                 'CFLAGS': '-DGPR_BACKWARDS_COMPATIBILITY_MODE'}
+                 'CFLAGS': '-DGPR_BACKWARDS_COMPATIBILITY_MODE',
+                 'LDFLAGS': ''}
       if self.platform == 'linux':
         return create_docker_jobspec(self.name,
             'tools/dockerfile/grpc_artifact_linux_%s' % self.arch,
-            'tools/run_tests/build_artifact_csharp.sh')
+            'tools/run_tests/build_artifact_csharp.sh',
+            environ=environ)
       else:
-        environ.update(macos_arch_env(self.arch))
+        archflag = _ARCH_FLAG_MAP[self.arch]
+        environ['CFLAGS'] += ' %s %s' % (archflag, _MACOS_COMPAT_FLAG)
+        environ['LDFLAGS'] += ' %s' % archflag
         return create_jobspec(self.name,
                               ['tools/run_tests/build_artifact_csharp.sh'],
                               environ=environ)
@@ -199,6 +199,7 @@ class CSharpExtArtifact:
   def __str__(self):
     return self.name
 
+
 node_gyp_arch_map = {
   'x86': 'ia32',
   'x64': 'x64'
@@ -234,11 +235,76 @@ class NodeExtArtifact:
                               ['tools/run_tests/build_artifact_node.sh',
                                self.gyp_arch])
 
+class PHPArtifact:
+  """Builds PHP PECL package"""
+
+  def __init__(self, platform, arch):
+    self.name = 'php_pecl_package_{0}_{1}'.format(platform, arch)
+    self.platform = platform
+    self.arch = arch
+    self.labels = ['artifact', 'php', platform, arch]
+
+  def pre_build_jobspecs(self):
+    return []
+
+  def build_jobspec(self):
+    if self.platform == 'linux':
+      return create_docker_jobspec(
+          self.name,
+          'tools/dockerfile/grpc_artifact_linux_{}'.format(self.arch),
+          'tools/run_tests/build_artifact_php.sh')
+    else:
+      return create_jobspec(self.name,
+                            ['tools/run_tests/build_artifact_php.sh'])
+
+class ProtocArtifact:
+  """Builds protoc and protoc-plugin artifacts"""
+
+  def __init__(self, platform, arch):
+    self.name = 'protoc_%s_%s' % (platform, arch)
+    self.platform = platform
+    self.arch = arch
+    self.labels = ['artifact', 'protoc', platform, arch]
+
+  def pre_build_jobspecs(self):
+      return []
+
+  def build_jobspec(self):
+    if self.platform != 'windows':
+      cxxflags = '-DNDEBUG %s' % _ARCH_FLAG_MAP[self.arch]
+      ldflags = '%s' % _ARCH_FLAG_MAP[self.arch]
+      if self.platform != 'macos':
+        ldflags += '  -static-libgcc -static-libstdc++ -s'
+      environ={'CONFIG': 'opt',
+               'CXXFLAGS': cxxflags,
+               'LDFLAGS': ldflags,
+               'PROTOBUF_LDFLAGS_EXTRA': ldflags}
+      if self.platform == 'linux':
+        return create_docker_jobspec(self.name,
+            'tools/dockerfile/grpc_artifact_protoc',
+            'tools/run_tests/build_artifact_protoc.sh',
+            environ=environ)
+      else:
+        environ['CXXFLAGS'] += ' -std=c++11 -stdlib=libc++ %s' % _MACOS_COMPAT_FLAG
+        return create_jobspec(self.name,
+            ['tools/run_tests/build_artifact_protoc.sh'],
+            environ=environ)
+    else:
+      generator = 'Visual Studio 12 Win64' if self.arch == 'x64' else 'Visual Studio 12' 
+      vcplatform = 'x64' if self.arch == 'x64' else 'Win32'
+      return create_jobspec(self.name,
+                            ['tools\\run_tests\\build_artifact_protoc.bat'],
+                            environ={'generator': generator,
+                                     'Platform': vcplatform})
+
+  def __str__(self):
+    return self.name
+
 
 def targets():
   """Gets list of supported targets"""
   return ([Cls(platform, arch)
-           for Cls in (CSharpExtArtifact, NodeExtArtifact)
+           for Cls in (CSharpExtArtifact, NodeExtArtifact, ProtocArtifact)
            for platform in ('linux', 'macos', 'windows')
            for arch in ('x86', 'x64')] +
           [PythonArtifact('linux', 'x86'),
@@ -248,4 +314,6 @@ def targets():
            PythonArtifact('windows', 'x64'),
            RubyArtifact('linux', 'x86'),
            RubyArtifact('linux', 'x64'),
-           RubyArtifact('macos', 'x64')])
+           RubyArtifact('macos', 'x64'),
+           PHPArtifact('linux', 'x64'),
+           PHPArtifact('macos', 'x64')])
diff --git a/tools/run_tests/build_artifact_php.sh b/tools/run_tests/build_artifact_php.sh
new file mode 100755
index 0000000000000000000000000000000000000000..50bf0ea82159b15ee6f5b691dac0ddcf4147d8f5
--- /dev/null
+++ b/tools/run_tests/build_artifact_php.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# 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.
+
+PHP_TARGET_ARCH=$1
+set -ex
+
+cd $(dirname $0)/../..
+
+mkdir -p artifacts
+
+pear package
+
+cp -r grpc-*.tgz artifacts/grpc-php.tgz
diff --git a/tools/run_tests/build_artifact_protoc.bat b/tools/run_tests/build_artifact_protoc.bat
new file mode 100644
index 0000000000000000000000000000000000000000..e1dc032188f130e2cf3fee718ed511df69b73802
--- /dev/null
+++ b/tools/run_tests/build_artifact_protoc.bat
@@ -0,0 +1,51 @@
+@rem Copyright 2016, Google Inc.
+@rem All rights reserved.
+@rem
+@rem Redistribution and use in source and binary forms, with or without
+@rem modification, are permitted provided that the following conditions are
+@rem met:
+@rem
+@rem     * Redistributions of source code must retain the above copyright
+@rem notice, this list of conditions and the following disclaimer.
+@rem     * Redistributions in binary form must reproduce the above
+@rem copyright notice, this list of conditions and the following disclaimer
+@rem in the documentation and/or other materials provided with the
+@rem distribution.
+@rem     * Neither the name of Google Inc. nor the names of its
+@rem contributors may be used to endorse or promote products derived from
+@rem this software without specific prior written permission.
+@rem
+@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+mkdir artifacts
+
+setlocal
+cd third_party/protobuf
+
+powershell -Command "Invoke-WebRequest https://googlemock.googlecode.com/files/gmock-1.7.0.zip -OutFile gmock.zip"
+powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('gmock.zip', '.');"
+rename gmock-1.7.0 gmock
+
+cd cmake
+cmake -G "%generator%" || goto :error
+endlocal
+
+call vsprojects/build_plugins.bat || goto :error
+
+xcopy /Y third_party\protobuf\cmake\Release\protoc.exe artifacts\ || goto :error
+xcopy /Y vsprojects\Release\*_plugin.exe artifacts\ || xcopy /Y vsprojects\x64\Release\*_plugin.exe artifacts\ || goto :error
+
+goto :EOF
+
+:error
+exit /b 1
\ No newline at end of file
diff --git a/tools/run_tests/build_artifact_protoc.sh b/tools/run_tests/build_artifact_protoc.sh
new file mode 100755
index 0000000000000000000000000000000000000000..161d3a84d6edd81e8aaea1aac055ca381d81f0b3
--- /dev/null
+++ b/tools/run_tests/build_artifact_protoc.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# 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.
+
+# Use devtoolset environment that has GCC 4.7 before set -ex
+source scl_source enable devtoolset-1.1
+
+set -ex
+
+cd $(dirname $0)/../..
+
+make plugins
+
+mkdir -p artifacts
+cp bins/opt/protobuf/protoc bins/opt/*_plugin artifacts/
diff --git a/tools/run_tests/build_node.bat b/tools/run_tests/build_node.bat
index 6896bc1d1bb1480ea66c222390b9a5104168d367..82e82083486516eac751394ca2b9cea4aedb4db2 100644
--- a/tools/run_tests/build_node.bat
+++ b/tools/run_tests/build_node.bat
@@ -27,4 +27,16 @@
 @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-npm install --build-from-source
\ No newline at end of file
+set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm
+
+del /f /q BUILD || rmdir build /s /q
+
+call npm install --build-from-source
+
+@rem delete the redundant openssl headers
+for /f "delims=v" %%v in ('node --version') do (
+  rmdir "%USERPROFILE%\.node-gyp\%%v\include\node\openssl" /S /Q
+)
+
+@rem rebuild, because it probably failed the first time
+call npm install --build-from-source
\ No newline at end of file
diff --git a/tools/run_tests/build_package_php.sh b/tools/run_tests/build_package_php.sh
new file mode 100755
index 0000000000000000000000000000000000000000..56e3319ed9b9b56da0f3d552fc9609a238d8a72b
--- /dev/null
+++ b/tools/run_tests/build_package_php.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# 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.
+
+set -ex
+
+cd $(dirname $0)/../..
+
+mkdir -p artifacts/
+cp -r $EXTERNAL_GIT_ROOT/architecture={x86,x64},language=php,platform={windows,linux,macos}/artifacts/* artifacts/ || true
diff --git a/tools/run_tests/build_python.sh b/tools/run_tests/build_python.sh
index e0fcbb602d4bc276e3b7ccb6caa7ed1101634c73..79a148faf1bfcf215330e2f42519a365de46d95b 100755
--- a/tools/run_tests/build_python.sh
+++ b/tools/run_tests/build_python.sh
@@ -40,8 +40,15 @@ export PATH=$ROOT/bins/$CONFIG:$ROOT/bins/$CONFIG/protobuf:$PATH
 export CFLAGS="-I$ROOT/include -std=gnu99"
 export LDFLAGS="-L$ROOT/libs/$CONFIG"
 export GRPC_PYTHON_BUILD_WITH_CYTHON=1
-export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
+
+if [ "$CONFIG" = "gcov" ]
+then
+  export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
+fi
 
 tox --notest
 
 $ROOT/.tox/py27/bin/python $ROOT/setup.py build
+$ROOT/.tox/py27/bin/python $ROOT/setup.py build_py
+$ROOT/.tox/py27/bin/python $ROOT/setup.py build_ext --inplace
+$ROOT/.tox/py27/bin/python $ROOT/setup.py gather --test
diff --git a/tools/run_tests/configs.json b/tools/run_tests/configs.json
index 9d7b8a3c7253c47329ea02d8139ea8299fc0e367..cbb8ec57b6170579e303e3a82d657902c369c302 100644
--- a/tools/run_tests/configs.json
+++ b/tools/run_tests/configs.json
@@ -18,7 +18,7 @@
     "environ": {
       "ASAN_OPTIONS": "detect_leaks=0:color=always"
     }, 
-    "timeout_multiplier": 1.5
+    "timeout_multiplier": 3
   }, 
   {
     "config": "ubsan", 
@@ -48,18 +48,18 @@
       "ASAN_OPTIONS": "detect_leaks=1:color=always", 
       "LSAN_OPTIONS": "suppressions=tools/lsan_suppressions.txt:report_objects=1"
     }, 
-    "timeout_multiplier": 1.5
+    "timeout_multiplier": 3
   }, 
   {
     "config": "tsan", 
     "environ": {
       "TSAN_OPTIONS": "suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1"
     }, 
-    "timeout_multiplier": 2
+    "timeout_multiplier": 5
   }, 
   {
     "config": "msan", 
-    "timeout_multiplier": 2
+    "timeout_multiplier": 4
   }, 
   {
     "config": "mutrace"
diff --git a/tools/run_tests/distribtest_targets.py b/tools/run_tests/distribtest_targets.py
index 261f44bc6d991f50b029f326222ccbd5babf393e..34cc1cd71016c79d7c382eae83fd9afc0173f779 100644
--- a/tools/run_tests/distribtest_targets.py
+++ b/tools/run_tests/distribtest_targets.py
@@ -96,6 +96,15 @@ class CSharpDistribTest(object):
       return create_jobspec(self.name,
           ['test/distrib/csharp/run_distrib_test.sh'],
           environ={'EXTERNAL_GIT_ROOT': '../../..'})
+    elif self.platform == 'windows':
+      if self.arch == 'x64':
+        environ={'MSBUILD_EXTRA_ARGS': '/p:Platform=x64',
+                 'DISTRIBTEST_OUTPATH': 'DistribTest\\bin\\x64\\Debug'}
+      else:
+        environ={'DISTRIBTEST_OUTPATH': 'DistribTest\\bin\\\Debug'}
+      return create_jobspec(self.name,
+          ['test\\distrib\\csharp\\run_distrib_test.bat'],
+          environ=environ)
     else:
       raise Exception("Not supported yet.")
 
@@ -198,6 +207,37 @@ class RubyDistribTest(object):
     return self.name
 
 
+class PHPDistribTest(object):
+  """Tests PHP package"""
+
+  def __init__(self, platform, arch, docker_suffix=None):
+    self.name = 'php_%s_%s_%s' % (platform, arch, docker_suffix)
+    self.platform = platform
+    self.arch = arch
+    self.docker_suffix = docker_suffix
+    self.labels = ['distribtest', 'php', platform, arch, docker_suffix]
+
+  def pre_build_jobspecs(self):
+    return []
+
+  def build_jobspec(self):
+    if self.platform == 'linux':
+      return create_docker_jobspec(self.name,
+                                   'tools/dockerfile/distribtest/php_%s_%s' % (
+                                       self.docker_suffix,
+                                       self.arch),
+                                   'test/distrib/php/run_distrib_test.sh')
+    elif self.platform == 'macos':
+      return create_jobspec(self.name,
+          ['test/distrib/php/run_distrib_test.sh'],
+          environ={'EXTERNAL_GIT_ROOT': '../../..'})
+    else:
+      raise Exception("Not supported yet.")
+
+  def __str__(self):
+    return self.name
+
+
 def targets():
   """Gets list of supported targets"""
   return [CSharpDistribTest('linux', 'x64', 'wheezy'),
@@ -209,6 +249,8 @@ def targets():
           CSharpDistribTest('linux', 'x64', 'ubuntu1510'),
           CSharpDistribTest('linux', 'x64', 'ubuntu1604'),
           CSharpDistribTest('macos', 'x86'),
+          CSharpDistribTest('windows', 'x86'),
+          CSharpDistribTest('windows', 'x64'),
           PythonDistribTest('linux', 'x64', 'wheezy'),
           PythonDistribTest('linux', 'x64', 'jessie'),
           PythonDistribTest('linux', 'x86', 'jessie'),
@@ -241,7 +283,10 @@ def targets():
           RubyDistribTest('linux', 'x64', 'ubuntu1510'),
           RubyDistribTest('linux', 'x64', 'ubuntu1604'),
           NodeDistribTest('macos', 'x64', None, '4'),
-          NodeDistribTest('linux', 'x86', 'jessie', '4')
+          NodeDistribTest('macos', 'x64', None, '5'),
+          NodeDistribTest('linux', 'x86', 'jessie', '4'),
+          PHPDistribTest('linux', 'x64', 'jessie'),
+          PHPDistribTest('macos', 'x64'),
           ] + [
             NodeDistribTest('linux', 'x64', os, version)
             for os in ('wheezy', 'jessie', 'ubuntu1204', 'ubuntu1404',
diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py
index adf178bb3c359279afb2bfefdc70f752cfa6007c..a3b246dc084b295d17742d1e2b81d6caa4070a46 100755
--- a/tools/run_tests/jobset.py
+++ b/tools/run_tests/jobset.py
@@ -384,7 +384,8 @@ class Jobset(object):
                 self._travis,
                 self._add_env)
       self._running.add(job)
-      self.resultset[job.GetSpec().shortname] = []
+      if not self.resultset.has_key(job.GetSpec().shortname):
+        self.resultset[job.GetSpec().shortname] = []
     return True
 
   def reap(self):
diff --git a/tools/run_tests/package_targets.py b/tools/run_tests/package_targets.py
index 4ca8279f1bfa529783b2b2463e582cec7978c7dc..87bc4865ce34e5f8962f1b28e357c750e6351ac2 100644
--- a/tools/run_tests/package_targets.py
+++ b/tools/run_tests/package_targets.py
@@ -139,9 +139,27 @@ class PythonPackage:
         'tools/run_tests/build_package_python.sh')
 
 
+class PHPPackage:
+  """Copy PHP PECL package artifact"""
+
+  def __init__(self):
+    self.name = 'php_package'
+    self.labels = ['package', 'php', 'linux']
+
+  def pre_build_jobspecs(self):
+    return []
+
+  def build_jobspec(self):
+    return create_docker_jobspec(
+        self.name,
+        'tools/dockerfile/grpc_artifact_linux_x64',
+        'tools/run_tests/build_package_php.sh')
+
+
 def targets():
   """Gets list of supported targets"""
   return [CSharpPackage(),
           NodePackage(),
           RubyPackage(),
-          PythonPackage()]
+          PythonPackage(),
+          PHPPackage()]
diff --git a/tools/run_tests/pre_build_node.bat b/tools/run_tests/pre_build_node.bat
index 6e7cbe5d420d58060f8c26dbc9b5953f92e9ee1c..a29456f9ed95eecbca0e2b86b04168ff09ca989b 100644
--- a/tools/run_tests/pre_build_node.bat
+++ b/tools/run_tests/pre_build_node.bat
@@ -27,13 +27,8 @@
 @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-@rem Expire cache after 1 week
-npm update --cache-min 604800
+set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm
 
-npm install node-gyp-install
-.\node_modules\.bin\node-gyp-install.cmd
+@rem Expire cache after 1 week
+call npm update --cache-min 604800
 
-@rem delete the redundant openssl headers
-for /f "delims=v" %%v in ('node --version') do (
-  rmdir "%HOMEDRIVE%%HOMEPATH%\.node-gyp\%%v\include\node\openssl" /S /Q
-)
\ No newline at end of file
diff --git a/tools/run_tests/report_utils.py b/tools/run_tests/report_utils.py
index 0032a985232331f51c656626c6e7e8ff9bdd62fb..df114e5dae16cce8b36428a911435cc522cecf0e 100644
--- a/tools/run_tests/report_utils.py
+++ b/tools/run_tests/report_utils.py
@@ -47,7 +47,7 @@ def _filter_msg(msg, output_format):
     # that make XML report unparseable.
     filtered_msg = filter(
         lambda x: x in string.printable and x != '\f' and x != '\v',
-        msg.decode(errors='ignore'))
+        msg.decode('UTF-8', 'ignore'))
     if output_format == 'HTML':
       filtered_msg = filtered_msg.replace('"', '&quot;')
     return filtered_msg
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index df3ab90a839fad5e10d73847a2f12c3951841809..1dc772a85658157e6794793e16075719de655982 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -60,6 +60,8 @@ _SKIP_COMPRESSION = ['large_compressed_unary',
 _SKIP_ADVANCED = ['custom_metadata', 'status_code_and_message',
                   'unimplemented_method']
 
+_TEST_TIMEOUT = 3*60
+
 class CXXLanguage:
 
   def __init__(self):
@@ -459,7 +461,7 @@ def cloud_to_prod_jobspec(language, test_case, server_host_name,
           environ=environ,
           shortname='%s:%s:%s:%s' % (suite_name, server_host_name, language,
                                      test_case),
-          timeout_seconds=90,
+          timeout_seconds=_TEST_TIMEOUT,
           flake_retries=5 if args.allow_flakes else 0,
           timeout_retries=2 if args.allow_flakes else 0,
           kill_handler=_job_kill_handler)
@@ -495,7 +497,7 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host,
           environ=environ,
           shortname='cloud_to_cloud:%s:%s_server:%s' % (language, server_name,
                                                         test_case),
-          timeout_seconds=90,
+          timeout_seconds=_TEST_TIMEOUT,
           flake_retries=5 if args.allow_flakes else 0,
           timeout_retries=2 if args.allow_flakes else 0,
           kill_handler=_job_kill_handler)
diff --git a/tools/run_tests/run_node.bat b/tools/run_tests/run_node.bat
index ad9ca14b8b9d5474331bc34f95a6a0e51eb04c1c..0987fbee55992a1565a6462d07feeb1aa243699f 100644
--- a/tools/run_tests/run_node.bat
+++ b/tools/run_tests/run_node.bat
@@ -27,6 +27,7 @@
 @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-set JUNIT_REPORT_PATH=src\node\reports.xml
+set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm
+set JUNIT_REPORT_PATH=src\node\report.xml
 set JUNIT_REPORT_STACK=1
 .\node_modules\.bin\mocha.cmd --reporter mocha-jenkins-reporter --timeout 8000 src\node\test
\ No newline at end of file
diff --git a/tools/run_tests/run_node.sh b/tools/run_tests/run_node.sh
index 178584ae8ed59f035b92b409de1a9101fbf53fbc..d33890068ddce5917198c4cc3883cf33a1318c7d 100755
--- a/tools/run_tests/run_node.sh
+++ b/tools/run_tests/run_node.sh
@@ -58,7 +58,7 @@ then
   echo '<html><head><meta http-equiv="refresh" content="0;URL=lcov-report/index.html"></head></html>' > \
     ../reports/node_coverage/index.html
 else
-  JUNIT_REPORT_PATH=src/node/reports.xml JUNIT_REPORT_STACK=1 \
+  JUNIT_REPORT_PATH=src/node/report.xml JUNIT_REPORT_STACK=1 \
     ./node_modules/.bin/mocha --timeout $timeout \
     --reporter mocha-jenkins-reporter $test_directory
 fi
diff --git a/tools/run_tests/run_python.sh b/tools/run_tests/run_python.sh
index ffe9c12af1a2beefc6cf9773cd9f46412059fcba..d4b7250cbb7f22066aeb01f9c99b65630123a491 100755
--- a/tools/run_tests/run_python.sh
+++ b/tools/run_tests/run_python.sh
@@ -40,9 +40,14 @@ export PATH=$ROOT/bins/$CONFIG:$ROOT/bins/$CONFIG/protobuf:$PATH
 export CFLAGS="-I$ROOT/include -std=c89"
 export LDFLAGS="-L$ROOT/libs/$CONFIG"
 export GRPC_PYTHON_BUILD_WITH_CYTHON=1
-export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
 
-tox
+if [ "$CONFIG" = "gcov" ]
+then
+  export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
+  tox
+else
+  $ROOT/.tox/py27/bin/python $ROOT/setup.py test_lite
+fi
 
 mkdir -p $ROOT/reports
 rm -rf $ROOT/reports/python-coverage
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 0b3efa29e3a0bc027b1fd4a0a3ce47bbdeb1dff9..2df82adf0a7ed54a99ec3939d3ff371584848b0a 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -55,8 +55,8 @@ import report_utils
 import watch_dirs
 
 
-ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-os.chdir(ROOT)
+_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
+os.chdir(_ROOT)
 
 
 _FORCE_ENVIRON_FOR_WRAPPERS = {}
@@ -118,6 +118,16 @@ def get_c_tests(travis, test_lang) :
                 not (travis and tgt['flaky'])]
 
 
+def _check_compiler(compiler, supported_compilers):
+  if compiler not in supported_compilers:
+    raise Exception('Compiler %s not supported.' % compiler)
+
+
+def _is_use_docker_child():
+  """Returns True if running running as a --use_docker child."""
+  return True if os.getenv('RUN_TESTS_COMMAND') else False
+
+
 class CLanguage(object):
 
   def __init__(self, make_target, test_lang):
@@ -125,44 +135,81 @@ class CLanguage(object):
     self.platform = platform_string()
     self.test_lang = test_lang
 
-  def test_specs(self, config, args):
+  def configure(self, config, args):
+    self.config = config
+    self.args = args
+    if self.platform == 'windows':
+      self._make_options = [_windows_toolset_option(self.args.compiler),
+                            _windows_arch_option(self.args.arch)]
+    else:
+      self._make_options = []
+      self._docker_distro = self._get_docker_distro(self.args.use_docker,
+                                                    self.args.compiler)
+
+  def test_specs(self):
     out = []
-    binaries = get_c_tests(args.travis, self.test_lang)
+    binaries = get_c_tests(self.args.travis, self.test_lang)
     for target in binaries:
-      if config.build_config in target['exclude_configs']:
+      if self.config.build_config in target['exclude_configs']:
         continue
       if self.platform == 'windows':
         binary = 'vsprojects/%s%s/%s.exe' % (
-            'x64/' if args.arch == 'x64' else '',
-            _WINDOWS_CONFIG[config.build_config],
+            'x64/' if self.args.arch == 'x64' else '',
+            _MSBUILD_CONFIG[self.config.build_config],
             target['name'])
       else:
-        binary = 'bins/%s/%s' % (config.build_config, target['name'])
+        binary = 'bins/%s/%s' % (self.config.build_config, target['name'])
       if os.path.isfile(binary):
-        cmdline = [binary] + target['args']
-        out.append(config.job_spec(cmdline, [binary],
-                                   shortname=' '.join(cmdline),
-                                   cpu_cost=target['cpu_cost'],
-                                   environ={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
-                                            os.path.abspath(os.path.dirname(
-                                                sys.argv[0]) + '/../../src/core/tsi/test_creds/ca.pem')}))
-      elif args.regex == '.*' or platform_string() == 'windows':
+        if 'gtest' in target and target['gtest']:
+          # here we parse the output of --gtest_list_tests to build up a
+          # complete list of the tests contained in a binary
+          # for each test, we then add a job to run, filtering for just that
+          # test
+          with open(os.devnull, 'w') as fnull:
+            tests = subprocess.check_output([binary, '--gtest_list_tests'],
+                                            stderr=fnull)
+          base = None
+          for line in tests.split('\n'):
+            i = line.find('#')
+            if i >= 0: line = line[:i]
+            if not line: continue
+            if line[0] != ' ':
+              base = line.strip()
+            else:
+              assert base is not None
+              assert line[1] == ' '
+              test = base + line.strip()
+              cmdline = [binary] + ['--gtest_filter=%s' % test]
+              out.append(self.config.job_spec(cmdline, [binary],
+                                              shortname='%s:%s' % (binary, test),
+                                              cpu_cost=target['cpu_cost'],
+                                              environ={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
+                                                       _ROOT + '/src/core/tsi/test_creds/ca.pem'}))
+        else:
+          cmdline = [binary] + target['args']
+          out.append(self.config.job_spec(cmdline, [binary],
+                                          shortname=' '.join(cmdline),
+                                          cpu_cost=target['cpu_cost'],
+                                          environ={'GRPC_DEFAULT_SSL_ROOTS_FILE_PATH':
+                                                   _ROOT + '/src/core/tsi/test_creds/ca.pem'}))
+      elif self.args.regex == '.*' or self.platform == 'windows':
         print '\nWARNING: binary not found, skipping', binary
     return sorted(out)
 
-  def make_targets(self, test_regex):
-    if platform_string() != 'windows' and test_regex != '.*':
+  def make_targets(self):
+    test_regex = self.args.regex
+    if self.platform != 'windows' and self.args.regex != '.*':
       # use the regex to minimize the number of things to build
       return [os.path.basename(target['name'])
               for target in get_c_tests(False, self.test_lang)
               if re.search(test_regex, '/' + target['name'])]
-    if platform_string() == 'windows':
+    if self.platform == 'windows':
       # don't build tools on windows just yet
       return ['buildtests_%s' % self.make_target]
     return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target]
 
   def make_options(self):
-    return []
+    return self._make_options;
 
   def pre_build_steps(self):
     if self.platform == 'windows':
@@ -182,11 +229,24 @@ class CLanguage(object):
   def makefile_name(self):
     return 'Makefile'
 
-  def supports_multi_config(self):
-    return True
+  def _get_docker_distro(self, use_docker, compiler):
+    if _is_use_docker_child():
+      return "already_under_docker"
+    if not use_docker:
+      _check_compiler(compiler, ['default'])
+
+    if compiler == 'gcc4.9' or compiler == 'default':
+      return 'jessie'
+    elif compiler == 'gcc4.4':
+      return 'squeeze'
+    elif compiler == 'gcc5.3':
+      return 'ubuntu1604'
+    else:
+      raise Exception('Compiler %s not supported.' % compiler)
 
-  def dockerfile_dir(self, config, arch):
-    return 'tools/dockerfile/test/cxx_jessie_%s' % _docker_arch_suffix(arch)
+  def dockerfile_dir(self):
+    return 'tools/dockerfile/test/cxx_%s_%s' % (self._docker_distro,
+                                                _docker_arch_suffix(self.args.arch))
 
   def __str__(self):
     return self.make_target
@@ -198,13 +258,18 @@ class NodeLanguage(object):
     self.platform = platform_string()
     self.node_version = '0.12'
 
-  def test_specs(self, config, args):
+  def configure(self, config, args):
+    self.config = config
+    self.args = args
+    _check_compiler(self.args.compiler, ['default'])
+
+  def test_specs(self):
     if self.platform == 'windows':
-      return [config.job_spec(['tools\\run_tests\\run_node.bat'], None)]
+      return [self.config.job_spec(['tools\\run_tests\\run_node.bat'], None)]
     else:
-      return [config.job_spec(['tools/run_tests/run_node.sh', self.node_version],
-                              None,
-                              environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
+      return [self.config.job_spec(['tools/run_tests/run_node.sh', self.node_version],
+                                   None,
+                                   environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
 
   def pre_build_steps(self):
     if self.platform == 'windows':
@@ -212,7 +277,7 @@ class NodeLanguage(object):
     else:
       return [['tools/run_tests/pre_build_node.sh', self.node_version]]
 
-  def make_targets(self, test_regex):
+  def make_targets(self):
     return []
 
   def make_options(self):
@@ -230,11 +295,8 @@ class NodeLanguage(object):
   def makefile_name(self):
     return 'Makefile'
 
-  def supports_multi_config(self):
-    return False
-
-  def dockerfile_dir(self, config, arch):
-    return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(arch)
+  def dockerfile_dir(self):
+    return 'tools/dockerfile/test/node_jessie_%s' % _docker_arch_suffix(self.args.arch)
 
   def __str__(self):
     return 'node'
@@ -242,14 +304,19 @@ class NodeLanguage(object):
 
 class PhpLanguage(object):
 
-  def test_specs(self, config, args):
-    return [config.job_spec(['src/php/bin/run_tests.sh'], None,
-                            environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
+  def configure(self, config, args):
+    self.config = config
+    self.args = args
+    _check_compiler(self.args.compiler, ['default'])
+
+  def test_specs(self):
+    return [self.config.job_spec(['src/php/bin/run_tests.sh'], None,
+                                  environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
 
   def pre_build_steps(self):
     return []
 
-  def make_targets(self, test_regex):
+  def make_targets(self):
     return ['static_c', 'shared_c']
 
   def make_options(self):
@@ -264,11 +331,8 @@ class PhpLanguage(object):
   def makefile_name(self):
     return 'Makefile'
 
-  def supports_multi_config(self):
-    return False
-
-  def dockerfile_dir(self, config, arch):
-    return 'tools/dockerfile/test/php_jessie_%s' % _docker_arch_suffix(arch)
+  def dockerfile_dir(self):
+    return 'tools/dockerfile/test/php_jessie_%s' % _docker_arch_suffix(self.args.arch)
 
   def __str__(self):
     return 'php'
@@ -280,21 +344,38 @@ class PythonLanguage(object):
     self._build_python_versions = ['2.7']
     self._has_python_versions = []
 
-  def test_specs(self, config, args):
+  def configure(self, config, args):
+    self.config = config
+    self.args = args
+    _check_compiler(self.args.compiler, ['default'])
+
+  def test_specs(self):
+    # load list of known test suites
+    with open('src/python/grpcio/tests/tests.json') as tests_json_file:
+      tests_json = json.load(tests_json_file)
     environment = dict(_FORCE_ENVIRON_FOR_WRAPPERS)
     environment['PYVER'] = '2.7'
-    return [config.job_spec(
-        ['tools/run_tests/run_python.sh'],
-        None,
-        environ=environment,
-        shortname='py.test',
-        timeout_seconds=15*60
-    )]
+    if self.config.build_config != 'gcov':
+      return [self.config.job_spec(
+          ['tools/run_tests/run_python.sh'],
+          None,
+          environ=dict(environment.items() +
+                       [('GRPC_PYTHON_TESTRUNNER_FILTER', suite_name)]),
+          shortname='py.test.%s' % suite_name,
+          timeout_seconds=5*60)
+          for suite_name in tests_json]
+    else:
+      return [self.config.job_spec(['tools/run_tests/run_python.sh'],
+                                   None,
+                                   environ=environment,
+                                   shortname='py.test.coverage',
+                                   timeout_seconds=15*60)]
+
 
   def pre_build_steps(self):
     return []
 
-  def make_targets(self, test_regex):
+  def make_targets(self):
     return ['static_c', 'grpc_python_plugin', 'shared_c']
 
   def make_options(self):
@@ -320,11 +401,8 @@ class PythonLanguage(object):
   def makefile_name(self):
     return 'Makefile'
 
-  def supports_multi_config(self):
-    return False
-
-  def dockerfile_dir(self, config, arch):
-    return 'tools/dockerfile/test/python_jessie_%s' % _docker_arch_suffix(arch)
+  def dockerfile_dir(self):
+    return 'tools/dockerfile/test/python_jessie_%s' % _docker_arch_suffix(self.args.arch)
 
   def __str__(self):
     return 'python'
@@ -332,15 +410,20 @@ class PythonLanguage(object):
 
 class RubyLanguage(object):
 
-  def test_specs(self, config, args):
-    return [config.job_spec(['tools/run_tests/run_ruby.sh'], None,
-                            timeout_seconds=10*60,
-                            environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
+  def configure(self, config, args):
+    self.config = config
+    self.args = args
+    _check_compiler(self.args.compiler, ['default'])
+
+  def test_specs(self):
+    return [self.config.job_spec(['tools/run_tests/run_ruby.sh'], None,
+                                 timeout_seconds=10*60,
+                                 environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
 
   def pre_build_steps(self):
     return [['tools/run_tests/pre_build_ruby.sh']]
 
-  def make_targets(self, test_regex):
+  def make_targets(self):
     return []
 
   def make_options(self):
@@ -355,27 +438,30 @@ class RubyLanguage(object):
   def makefile_name(self):
     return 'Makefile'
 
-  def supports_multi_config(self):
-    return False
-
-  def dockerfile_dir(self, config, arch):
-    return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(arch)
+  def dockerfile_dir(self):
+    return 'tools/dockerfile/test/ruby_jessie_%s' % _docker_arch_suffix(self.args.arch)
 
   def __str__(self):
     return 'ruby'
 
 
 class CSharpLanguage(object):
+
   def __init__(self):
     self.platform = platform_string()
 
-  def test_specs(self, config, args):
+  def configure(self, config, args):
+    self.config = config
+    self.args = args
+    _check_compiler(self.args.compiler, ['default'])
+
+  def test_specs(self):
     with open('src/csharp/tests.json') as f:
       tests_json = json.load(f)
     assemblies = tests_json['assemblies']
     tests = tests_json['tests']
 
-    msbuild_config = _WINDOWS_CONFIG[config.build_config]
+    msbuild_config = _MSBUILD_CONFIG[self.config.build_config]
     assembly_files = ['%s/bin/%s/%s.dll' % (a, msbuild_config, a)
                       for a in assemblies]
 
@@ -387,13 +473,13 @@ class CSharpLanguage(object):
     else:
       script_name = 'tools/run_tests/run_csharp.sh'
 
-    if config.build_config == 'gcov':
+    if self.config.build_config == 'gcov':
       # On Windows, we only collect C# code coverage.
       # On Linux, we only collect coverage for native extension.
       # For code coverage all tests need to run as one suite.
-      return [config.job_spec([script_name] + extra_args, None,
-                              shortname='csharp.coverage',
-                              environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
+      return [self.config.job_spec([script_name] + extra_args, None,
+                                    shortname='csharp.coverage',
+                                    environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
     else:
       specs = []
       for test in tests:
@@ -402,9 +488,9 @@ class CSharpLanguage(object):
           # use different output directory for each test to prevent
           # TestResult.xml clash between parallel test runs.
           cmdline += ['-work=test-result/%s' % uuid.uuid4()]
-        specs.append(config.job_spec(cmdline, None,
-                                     shortname='csharp.%s' % test,
-                                     environ=_FORCE_ENVIRON_FOR_WRAPPERS))
+        specs.append(self.config.job_spec(cmdline, None,
+                                          shortname='csharp.%s' % test,
+                                          environ=_FORCE_ENVIRON_FOR_WRAPPERS))
       return specs
 
   def pre_build_steps(self):
@@ -413,7 +499,7 @@ class CSharpLanguage(object):
     else:
       return [['tools/run_tests/pre_build_csharp.sh']]
 
-  def make_targets(self, test_regex):
+  def make_targets(self):
     # For Windows, this target doesn't really build anything,
     # everything is build by buildall script later.
     if self.platform == 'windows':
@@ -440,11 +526,8 @@ class CSharpLanguage(object):
   def makefile_name(self):
     return 'Makefile'
 
-  def supports_multi_config(self):
-    return False
-
-  def dockerfile_dir(self, config, arch):
-    return 'tools/dockerfile/test/csharp_jessie_%s' % _docker_arch_suffix(arch)
+  def dockerfile_dir(self):
+    return 'tools/dockerfile/test/csharp_jessie_%s' % _docker_arch_suffix(self.args.arch)
 
   def __str__(self):
     return 'csharp'
@@ -452,14 +535,19 @@ class CSharpLanguage(object):
 
 class ObjCLanguage(object):
 
-  def test_specs(self, config, args):
-    return [config.job_spec(['src/objective-c/tests/run_tests.sh'], None,
-                            environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
+  def configure(self, config, args):
+    self.config = config
+    self.args = args
+    _check_compiler(self.args.compiler, ['default'])
+
+  def test_specs(self):
+    return [self.config.job_spec(['src/objective-c/tests/run_tests.sh'], None,
+                                  environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
 
   def pre_build_steps(self):
     return []
 
-  def make_targets(self, test_regex):
+  def make_targets(self):
     return ['grpc_objective_c_plugin', 'interop_server']
 
   def make_options(self):
@@ -474,10 +562,7 @@ class ObjCLanguage(object):
   def makefile_name(self):
     return 'Makefile'
 
-  def supports_multi_config(self):
-    return False
-
-  def dockerfile_dir(self, config, arch):
+  def dockerfile_dir(self):
     return None
 
   def __str__(self):
@@ -486,18 +571,23 @@ class ObjCLanguage(object):
 
 class Sanity(object):
 
-  def test_specs(self, config, args):
+  def configure(self, config, args):
+    self.config = config
+    self.args = args
+    _check_compiler(self.args.compiler, ['default'])
+
+  def test_specs(self):
     import yaml
     with open('tools/run_tests/sanity/sanity_tests.yaml', 'r') as f:
-      return [config.job_spec(cmd['script'].split(), None,
-                              timeout_seconds=None, environ={'TEST': 'true'},
-                              cpu_cost=cmd.get('cpu_cost', 1))
+      return [self.config.job_spec(cmd['script'].split(), None,
+                                   timeout_seconds=None, environ={'TEST': 'true'},
+                                   cpu_cost=cmd.get('cpu_cost', 1))
               for cmd in yaml.load(f)]
 
   def pre_build_steps(self):
     return []
 
-  def make_targets(self, test_regex):
+  def make_targets(self):
     return ['run_dep_checks']
 
   def make_options(self):
@@ -512,55 +602,18 @@ class Sanity(object):
   def makefile_name(self):
     return 'Makefile'
 
-  def supports_multi_config(self):
-    return False
-
-  def dockerfile_dir(self, config, arch):
+  def dockerfile_dir(self):
     return 'tools/dockerfile/test/sanity'
 
   def __str__(self):
     return 'sanity'
 
 
-class Build(object):
-
-  def test_specs(self, config, args):
-    return []
-
-  def pre_build_steps(self):
-    return []
-
-  def make_targets(self, test_regex):
-    return ['static']
-
-  def make_options(self):
-    return []
-
-  def build_steps(self):
-    return []
-
-  def post_tests_steps(self):
-    return []
-
-  def makefile_name(self):
-    return 'Makefile'
-
-  def supports_multi_config(self):
-    return True
-
-  def dockerfile_dir(self, config, arch):
-    return None
-
-  def __str__(self):
-    return self.make_target
-
-
 # different configurations we can run under
 with open('tools/run_tests/configs.json') as f:
   _CONFIGS = dict((cfg['config'], Config(**cfg)) for cfg in ast.literal_eval(f.read()))
 
 
-_DEFAULT = ['opt']
 _LANGUAGES = {
     'c++': CLanguage('cxx', 'c++'),
     'c': CLanguage('c', 'c'),
@@ -570,11 +623,11 @@ _LANGUAGES = {
     'ruby': RubyLanguage(),
     'csharp': CSharpLanguage(),
     'objc' : ObjCLanguage(),
-    'sanity': Sanity(),
-    'build': Build(),
+    'sanity': Sanity()
     }
 
-_WINDOWS_CONFIG = {
+
+_MSBUILD_CONFIG = {
     'dbg': 'Debug',
     'opt': 'Release',
     'gcov': 'Debug',
@@ -651,14 +704,6 @@ def _docker_arch_suffix(arch):
     sys.exit(1)
 
 
-def _get_dockerfile_dir(language, cfg, arch):
-  """Returns dockerfile to use"""
-  custom = language.dockerfile_dir(cfg, arch)
-  if custom:
-    return custom
-  else:
-    return 'tools/dockerfile/grpc_tests_multilang_%s' % _docker_arch_suffix(arch)
-
 def runs_per_test_type(arg_str):
     """Auxilary function to parse the "runs_per_test" flag.
 
@@ -682,9 +727,8 @@ def runs_per_test_type(arg_str):
 # parse command line
 argp = argparse.ArgumentParser(description='Run grpc tests.')
 argp.add_argument('-c', '--config',
-                  choices=['all'] + sorted(_CONFIGS.keys()),
-                  nargs='+',
-                  default=_DEFAULT)
+                  choices=sorted(_CONFIGS.keys()),
+                  default='opt')
 argp.add_argument('-n', '--runs_per_test', default=1, type=runs_per_test_type,
         help='A positive integer or "inf". If "inf", all tests will run in an '
              'infinite loop. Especially useful in combination with "-f"')
@@ -728,9 +772,11 @@ argp.add_argument('--arch',
                   default='default',
                   help='Selects architecture to target. For some platforms "default" is the only supported choice.')
 argp.add_argument('--compiler',
-                  choices=['default', 'vs2010', 'vs2013', 'vs2015'],
+                  choices=['default',
+                           'gcc4.4', 'gcc4.9', 'gcc5.3',
+                           'vs2010', 'vs2013', 'vs2015'],
                   default='default',
-                  help='Selects compiler to use. For some platforms "default" is the only supported choice.')
+                  help='Selects compiler to use. Allowed values depend on the platform and language.')
 argp.add_argument('--build_only',
                   default=False,
                   action='store_const',
@@ -776,11 +822,8 @@ if need_to_regenerate_projects:
 
 
 # grab config
-run_configs = set(_CONFIGS[cfg]
-                  for cfg in itertools.chain.from_iterable(
-                      _CONFIGS.iterkeys() if x == 'all' else [x]
-                      for x in args.config))
-build_configs = set(cfg.build_config for cfg in run_configs)
+run_config = _CONFIGS[args.config]
+build_config = run_config.build_config
 
 if args.travis:
   _FORCE_ENVIRON_FOR_WRAPPERS = {'GRPC_TRACE': 'api'}
@@ -791,17 +834,13 @@ else:
   lang_list = args.language
 # We don't support code coverage on some languages
 if 'gcov' in args.config:
-  for bad in ['objc', 'sanity', 'build']:
+  for bad in ['objc', 'sanity']:
     if bad in lang_list:
       lang_list.remove(bad)
 
 languages = set(_LANGUAGES[l] for l in lang_list)
-
-if len(build_configs) > 1:
-  for language in languages:
-    if not language.supports_multi_config():
-      print language, 'does not support multiple build configurations'
-      sys.exit(1)
+for l in languages:
+  l.configure(run_config, args)
 
 language_make_options=[]
 if any(language.make_options() for language in languages):
@@ -811,10 +850,6 @@ if any(language.make_options() for language in languages):
   else:
     language_make_options = next(iter(languages)).make_options()
 
-if len(languages) != 1 or len(build_configs) != 1:
-  print 'Multi-language and multi-config testing is not supported.'
-  sys.exit(1)
-
 if args.use_docker:
   if not args.travis:
     print 'Seen --use_docker flag, will run tests under docker.'
@@ -824,14 +859,18 @@ if args.use_docker:
     print 'copied to the docker environment.'
     time.sleep(5)
 
+  dockerfile_dirs = set([l.dockerfile_dir() for l in languages])
+  if len(dockerfile_dirs) > 1:
+    print 'Languages to be tested require running under different docker images.'
+    sys.exit(1)
+  dockerfile_dir = next(iter(dockerfile_dirs))
+
   child_argv = [ arg for arg in sys.argv if not arg == '--use_docker' ]
   run_tests_cmd = 'python tools/run_tests/run_tests.py %s' % ' '.join(child_argv[1:])
 
   env = os.environ.copy()
   env['RUN_TESTS_COMMAND'] = run_tests_cmd
-  env['DOCKERFILE_DIR'] = _get_dockerfile_dir(next(iter(languages)),
-                                              next(iter(build_configs)),
-                                              args.arch)
+  env['DOCKERFILE_DIR'] = dockerfile_dir
   env['DOCKER_RUN_SCRIPT'] = 'tools/jenkins/docker_run_tests.sh'
   if args.xml_report:
     env['XML_REPORT'] = args.xml_report
@@ -843,10 +882,6 @@ if args.use_docker:
                         env=env)
   sys.exit(0)
 
-if platform_string() != 'windows' and args.compiler != 'default':
-    print 'Compiler %s not supported on current platform.' % args.compiler
-    sys.exit(1)
-
 _check_arch_option(args.arch)
 
 def make_jobspec(cfg, targets, makefile='Makefile'):
@@ -861,9 +896,7 @@ def make_jobspec(cfg, targets, makefile='Makefile'):
     return [
       jobset.JobSpec([_windows_build_bat(args.compiler),
                       'vsprojects\\%s.sln' % target,
-                      '/p:Configuration=%s' % _WINDOWS_CONFIG[cfg],
-                      _windows_toolset_option(args.compiler),
-                      _windows_arch_option(args.arch)] +
+                      '/p:Configuration=%s' % _MSBUILD_CONFIG[cfg]] +
                       extra_args +
                       language_make_options,
                       shell=True, timeout_seconds=None)
@@ -886,32 +919,29 @@ make_targets = {}
 for l in languages:
   makefile = l.makefile_name()
   make_targets[makefile] = make_targets.get(makefile, set()).union(
-      set(l.make_targets(args.regex)))
+      set(l.make_targets()))
 
 def build_step_environ(cfg):
   environ = {'CONFIG': cfg}
-  msbuild_cfg = _WINDOWS_CONFIG.get(cfg)
+  msbuild_cfg = _MSBUILD_CONFIG.get(cfg)
   if msbuild_cfg:
     environ['MSBUILD_CONFIG'] = msbuild_cfg
   return environ
 
 build_steps = list(set(
-                   jobset.JobSpec(cmdline, environ=build_step_environ(cfg), flake_retries=5)
-                   for cfg in build_configs
+                   jobset.JobSpec(cmdline, environ=build_step_environ(build_config), flake_retries=5)
                    for l in languages
                    for cmdline in l.pre_build_steps()))
 if make_targets:
-  make_commands = itertools.chain.from_iterable(make_jobspec(cfg, list(targets), makefile) for cfg in build_configs for (makefile, targets) in make_targets.iteritems())
+  make_commands = itertools.chain.from_iterable(make_jobspec(build_config, list(targets), makefile) for (makefile, targets) in make_targets.iteritems())
   build_steps.extend(set(make_commands))
 build_steps.extend(set(
-                   jobset.JobSpec(cmdline, environ=build_step_environ(cfg), timeout_seconds=None)
-                   for cfg in build_configs
+                   jobset.JobSpec(cmdline, environ=build_step_environ(build_config), timeout_seconds=None)
                    for l in languages
                    for cmdline in l.build_steps()))
 
 post_tests_steps = list(set(
-                        jobset.JobSpec(cmdline, environ=build_step_environ(cfg))
-                        for cfg in build_configs
+                        jobset.JobSpec(cmdline, environ=build_step_environ(build_config))
                         for l in languages
                         for cmdline in l.post_tests_steps()))
 runs_per_test = args.runs_per_test
@@ -1024,7 +1054,7 @@ def _start_port_server(port_server_port):
           print 'last ditch attempt to contact port server succeeded'
           break
         except:
-          traceback.print_exc();
+          traceback.print_exc()
           port_log = open(logfile, 'r').read()
           print port_log
           sys.exit(1)
@@ -1044,7 +1074,7 @@ def _start_port_server(port_server_port):
         time.sleep(1)
         waits += 1
       except:
-        traceback.print_exc();
+        traceback.print_exc()
         port_server.kill()
         raise
 
@@ -1102,9 +1132,8 @@ def _build_and_run(
     infinite_runs = runs_per_test == 0
     one_run = set(
       spec
-      for config in run_configs
       for language in languages
-      for spec in language.test_specs(config, args)
+      for spec in language.test_specs()
       if re.search(args.regex, spec.shortname))
     # When running on travis, we want out test runs to be as similar as possible
     # for reproducibility purposes.
diff --git a/tools/run_tests/sanity/check_sources_and_headers.py b/tools/run_tests/sanity/check_sources_and_headers.py
index 3974af0032b07ded797b7bc9c14cb16fbe0cc713..44dc49bb06f7c33492045d5d4567efb3222cf477 100755
--- a/tools/run_tests/sanity/check_sources_and_headers.py
+++ b/tools/run_tests/sanity/check_sources_and_headers.py
@@ -59,25 +59,43 @@ def target_has_header(target, name):
     return True
   return False
 
+def produces_object(name):
+  return os.path.splitext(name)[1] in ['.c', '.cc']
+
+obj_producer_to_source = {'c': {}, 'c++': {}, 'csharp': {}}
+
 errors = 0
 for target in js:
-  for fn in target['src']:
-    with open(os.path.join(root, fn)) as f:
-      src = f.read().splitlines()
-    for line in src:
-      m = re_inc1.match(line)
-      if m:
-        if not target_has_header(target, m.group(1)):
-          print (
-            'target %s (%s) does not name header %s as a dependency' % (
-              target['name'], fn, m.group(1)))
-          errors += 1
-      m = re_inc2.match(line)
-      if m:
-        if not target_has_header(target, 'include/' + m.group(1)):
-          print (
-            'target %s (%s) does not name header %s as a dependency' % (
-              target['name'], fn, m.group(1)))
-          errors += 1
+  if not target['third_party']:
+    for fn in target['src']:
+      with open(os.path.join(root, fn)) as f:
+        src = f.read().splitlines()
+      for line in src:
+        m = re_inc1.match(line)
+        if m:
+          if not target_has_header(target, m.group(1)):
+            print (
+              'target %s (%s) does not name header %s as a dependency' % (
+                target['name'], fn, m.group(1)))
+            errors += 1
+        m = re_inc2.match(line)
+        if m:
+          if not target_has_header(target, 'include/' + m.group(1)):
+            print (
+              'target %s (%s) does not name header %s as a dependency' % (
+                target['name'], fn, m.group(1)))
+            errors += 1
+  if target['type'] == 'lib':
+    for fn in target['src']:
+      language = target['language']
+      if produces_object(fn):
+        obj_base = os.path.splitext(os.path.basename(fn))[0]
+        if obj_base in obj_producer_to_source[language]:
+          if obj_producer_to_source[language][obj_base] != fn:
+            print (
+              'target %s (%s) produces an aliased object file with %s' % (
+                target['name'], fn, obj_producer_to_source[language][obj_base]))
+        else:
+          obj_producer_to_source[language][obj_base] = fn
 
 assert errors == 0
diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh
index f49230e49aa44cc3de8ea83be8bb49bbe81240c0..3c6dbb9ea1f1a18f51b33c8d889c901496d12153 100755
--- a/tools/run_tests/sanity/check_submodules.sh
+++ b/tools/run_tests/sanity/check_submodules.sh
@@ -44,6 +44,7 @@ cat << EOF | awk '{ print $1 }' | sort > $want_submodules
  9f897b25800d2f54f5c442ef01a60721aeca6d87 third_party/boringssl (version_for_cocoapods_1.0-67-g9f897b2)
  05b155ff59114735ec8cd089f669c4c3d8f59029 third_party/gflags (v2.1.0-45-g05b155f)
  c99458533a9b4c743ed51537e25989ea55944908 third_party/googletest (release-1.7.0)
+ f8ac463766281625ad710900479130c7fcb4d63b third_party/nanopb (nanopb-0.3.4-29-gf8ac463)
  d5fb408ddc281ffcadeb08699e65bb694656d0bd third_party/protobuf (v3.0.0-beta-2)
  50893291621658f355bc5b4d450a8d06a563053d third_party/zlib (v1.2.8)
 EOF
diff --git a/tools/run_tests/sanity/check_version.py b/tools/run_tests/sanity/check_version.py
new file mode 100755
index 0000000000000000000000000000000000000000..41dd5efe3887fde41b69aa70e2add1d876ec4161
--- /dev/null
+++ b/tools/run_tests/sanity/check_version.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python2.7
+
+# 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.
+
+import sys
+import yaml
+import os
+import re
+import subprocess
+
+errors = 0
+
+os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
+
+# hack import paths to pick up extra code
+sys.path.insert(0, os.path.abspath('tools/buildgen/plugins'))
+from expand_version import Version
+
+try:
+  branch_name = subprocess.check_output(
+    'git rev-parse --abbrev-ref HEAD',
+    shell=True)
+except:
+  print 'WARNING: not a git repository'
+  branch_name = None
+
+if branch_name is not None:
+  m = re.match(r'^release-([0-9]+)_([0-9]+)$', branch_name)
+  if m:
+    print 'RELEASE branch'
+    # version number should align with the branched version
+    check_version = lambda version: (
+      version.major == int(m.group(1)) and
+      version.minor == int(m.group(2)))
+    warning = 'Version key "%%s" value "%%s" should have a major version %s and minor version %s' % (m.group(1), m.group(2))
+  elif re.match(r'^debian/.*$', branch_name):
+    # no additional version checks for debian branches
+    check_version = lambda version: True
+  else:
+    # all other branches should have a -dev tag
+    check_version = lambda version: version.tag == 'dev'
+    warning = 'Version key "%s" value "%s" should have a -dev tag'
+else:
+  check_version = lambda version: True
+
+with open('build.yaml', 'r') as f:
+  build_yaml = yaml.load(f.read())
+
+settings = build_yaml['settings']
+
+top_version = Version(settings['version'])
+if not check_version(top_version):
+  errors += 1
+  print warning % ('version', top_version)
+
+for tag, value in settings.iteritems():
+  if re.match(r'^[a-z]+_version$', tag):
+    value = Version(value)
+    if value.major != top_version.major:
+      errors += 1
+      print 'major version mismatch on %s: %d vs %d' % (tag, value.major, top_version.major)
+    if value.minor != top_version.minor:
+      errors += 1
+      print 'minor version mismatch on %s: %d vs %d' % (tag, value.minor, top_version.minor)
+    if not check_version(value):
+      errors += 1
+      print warning % (tag, value)
+
+sys.exit(errors)
+
diff --git a/tools/run_tests/sanity/sanity_tests.yaml b/tools/run_tests/sanity/sanity_tests.yaml
index 809e6ce645414fe527b9112c4dc1c5d715c1f592..3840f4d8df6a3a54b7bef81008fba93290cb78f7 100644
--- a/tools/run_tests/sanity/sanity_tests.yaml
+++ b/tools/run_tests/sanity/sanity_tests.yaml
@@ -1,9 +1,10 @@
 # a set of tests that are run in parallel for sanity tests
+- script: tools/run_tests/sanity/check_cache_mk.sh
 - script: tools/run_tests/sanity/check_sources_and_headers.py
 - script: tools/run_tests/sanity/check_submodules.sh
-- script: tools/run_tests/sanity/check_cache_mk.sh
 - script: tools/buildgen/generate_projects.sh -j 3
   cpu_cost: 3
 - script: tools/distrib/check_copyright.py
 - script: tools/distrib/clang_format_code.sh
 - script: tools/distrib/check_trailing_newlines.sh
+- script: tools/distrib/check_nanopb_output.sh
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index b22a5a135f83cf64f14ae4e7dc44fa3b5aa6861d..0c7a6c7b5f34f277870ef17db4f1d4843033f620 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -13,7 +13,9 @@
     "name": "alarm_test", 
     "src": [
       "test/core/surface/alarm_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -27,7 +29,9 @@
     "name": "algorithm_test", 
     "src": [
       "test/core/compression/algorithm_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -39,7 +43,9 @@
     "name": "alloc_test", 
     "src": [
       "test/core/support/alloc_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -53,7 +59,9 @@
     "name": "alpn_test", 
     "src": [
       "test/core/transport/chttp2/alpn_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -65,7 +73,9 @@
     "name": "bin_encoder_test", 
     "src": [
       "test/core/transport/chttp2/bin_encoder_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -79,21 +89,9 @@
     "name": "census_context_test", 
     "src": [
       "test/core/census/context_test.c"
-    ]
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
     ], 
-    "headers": [], 
-    "language": "c", 
-    "name": "census_log_test", 
-    "src": [
-      "test/core/census/mlog_test.c"
-    ]
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -107,7 +105,9 @@
     "name": "channel_create_test", 
     "src": [
       "test/core/surface/channel_create_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -121,7 +121,9 @@
     "name": "chttp2_hpack_encoder_test", 
     "src": [
       "test/core/transport/chttp2/hpack_encoder_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -135,7 +137,9 @@
     "name": "chttp2_status_conversion_test", 
     "src": [
       "test/core/transport/chttp2/status_conversion_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -149,7 +153,9 @@
     "name": "chttp2_stream_map_test", 
     "src": [
       "test/core/transport/chttp2/stream_map_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -163,7 +169,9 @@
     "name": "chttp2_varint_test", 
     "src": [
       "test/core/transport/chttp2/varint_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -177,7 +185,9 @@
     "name": "compression_test", 
     "src": [
       "test/core/compression/compression_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -191,7 +201,9 @@
     "name": "dns_resolver_test", 
     "src": [
       "test/core/client_config/resolvers/dns_resolver_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -205,7 +217,9 @@
     "name": "dualstack_socket_test", 
     "src": [
       "test/core/end2end/dualstack_socket_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -219,7 +233,9 @@
     "name": "endpoint_pair_test", 
     "src": [
       "test/core/iomgr/endpoint_pair_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -233,7 +249,9 @@
     "name": "fd_conservation_posix_test", 
     "src": [
       "test/core/iomgr/fd_conservation_posix_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -247,7 +265,9 @@
     "name": "fd_posix_test", 
     "src": [
       "test/core/iomgr/fd_posix_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -261,7 +281,9 @@
     "name": "fling_client", 
     "src": [
       "test/core/fling/client.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -275,7 +297,9 @@
     "name": "fling_server", 
     "src": [
       "test/core/fling/server.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -289,7 +313,9 @@
     "name": "fling_stream_test", 
     "src": [
       "test/core/fling/fling_stream_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -303,7 +329,9 @@
     "name": "fling_test", 
     "src": [
       "test/core/fling/fling_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -315,7 +343,9 @@
     "name": "gen_hpack_tables", 
     "src": [
       "tools/codegen/core/gen_hpack_tables.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [], 
@@ -324,7 +354,9 @@
     "name": "gen_legal_metadata_characters", 
     "src": [
       "tools/codegen/core/gen_legal_metadata_characters.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -336,7 +368,9 @@
     "name": "gpr_avl_test", 
     "src": [
       "test/core/support/avl_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -348,7 +382,9 @@
     "name": "gpr_cmdline_test", 
     "src": [
       "test/core/support/cmdline_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -360,7 +396,9 @@
     "name": "gpr_cpu_test", 
     "src": [
       "test/core/support/cpu_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -372,7 +410,9 @@
     "name": "gpr_env_test", 
     "src": [
       "test/core/support/env_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -381,10 +421,12 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "gpr_file_test", 
+    "name": "gpr_histogram_test", 
     "src": [
-      "test/core/support/file_test.c"
-    ]
+      "test/core/support/histogram_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -393,10 +435,12 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "gpr_histogram_test", 
+    "name": "gpr_host_port_test", 
     "src": [
-      "test/core/support/histogram_test.c"
-    ]
+      "test/core/support/host_port_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -405,10 +449,12 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "gpr_host_port_test", 
+    "name": "gpr_load_file_test", 
     "src": [
-      "test/core/support/host_port_test.c"
-    ]
+      "test/core/support/load_file_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -420,7 +466,9 @@
     "name": "gpr_log_test", 
     "src": [
       "test/core/support/log_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -432,7 +480,9 @@
     "name": "gpr_slice_buffer_test", 
     "src": [
       "test/core/support/slice_buffer_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -444,7 +494,9 @@
     "name": "gpr_slice_test", 
     "src": [
       "test/core/support/slice_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -456,7 +508,9 @@
     "name": "gpr_stack_lockfree_test", 
     "src": [
       "test/core/support/stack_lockfree_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -468,7 +522,9 @@
     "name": "gpr_string_test", 
     "src": [
       "test/core/support/string_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -480,7 +536,9 @@
     "name": "gpr_sync_test", 
     "src": [
       "test/core/support/sync_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -492,7 +550,9 @@
     "name": "gpr_thd_test", 
     "src": [
       "test/core/support/thd_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -504,7 +564,9 @@
     "name": "gpr_time_test", 
     "src": [
       "test/core/support/time_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -516,7 +578,9 @@
     "name": "gpr_tls_test", 
     "src": [
       "test/core/support/tls_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -528,7 +592,9 @@
     "name": "gpr_useful_test", 
     "src": [
       "test/core/support/useful_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -542,7 +608,9 @@
     "name": "grpc_auth_context_test", 
     "src": [
       "test/core/security/auth_context_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -553,10 +621,12 @@
     ], 
     "headers": [], 
     "language": "c", 
-    "name": "grpc_base64_test", 
+    "name": "grpc_b64_test", 
     "src": [
-      "test/core/security/base64_test.c"
-    ]
+      "test/core/security/b64_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -570,7 +640,9 @@
     "name": "grpc_byte_buffer_reader_test", 
     "src": [
       "test/core/surface/byte_buffer_reader_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -584,7 +656,9 @@
     "name": "grpc_channel_args_test", 
     "src": [
       "test/core/channel/channel_args_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -598,7 +672,9 @@
     "name": "grpc_channel_stack_test", 
     "src": [
       "test/core/channel/channel_stack_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -612,7 +688,9 @@
     "name": "grpc_completion_queue_test", 
     "src": [
       "test/core/surface/completion_queue_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -626,7 +704,9 @@
     "name": "grpc_create_jwt", 
     "src": [
       "test/core/security/create_jwt.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -640,7 +720,9 @@
     "name": "grpc_credentials_test", 
     "src": [
       "test/core/security/credentials_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -654,7 +736,9 @@
     "name": "grpc_fetch_oauth2", 
     "src": [
       "test/core/security/fetch_oauth2.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -668,7 +752,9 @@
     "name": "grpc_invalid_channel_args_test", 
     "src": [
       "test/core/surface/invalid_channel_args_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -682,7 +768,9 @@
     "name": "grpc_json_token_test", 
     "src": [
       "test/core/security/json_token_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -696,7 +784,9 @@
     "name": "grpc_jwt_verifier_test", 
     "src": [
       "test/core/security/jwt_verifier_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -710,7 +800,9 @@
     "name": "grpc_print_google_default_creds_token", 
     "src": [
       "test/core/security/print_google_default_creds_token.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -724,7 +816,9 @@
     "name": "grpc_security_connector_test", 
     "src": [
       "test/core/security/security_connector_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -738,7 +832,9 @@
     "name": "grpc_verify_jwt", 
     "src": [
       "test/core/security/verify_jwt.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -752,7 +848,9 @@
     "name": "hpack_parser_test", 
     "src": [
       "test/core/transport/chttp2/hpack_parser_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -766,7 +864,9 @@
     "name": "hpack_table_test", 
     "src": [
       "test/core/transport/chttp2/hpack_table_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -780,7 +880,9 @@
     "name": "httpcli_format_request_test", 
     "src": [
       "test/core/httpcli/format_request_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -794,7 +896,9 @@
     "name": "httpcli_parser_test", 
     "src": [
       "test/core/httpcli/parser_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -808,7 +912,9 @@
     "name": "httpcli_test", 
     "src": [
       "test/core/httpcli/httpcli_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -822,7 +928,9 @@
     "name": "httpscli_test", 
     "src": [
       "test/core/httpcli/httpscli_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -836,7 +944,9 @@
     "name": "init_test", 
     "src": [
       "test/core/surface/init_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -850,7 +960,9 @@
     "name": "invalid_call_argument_test", 
     "src": [
       "test/core/end2end/invalid_call_argument_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -862,7 +974,9 @@
     "name": "json_rewrite", 
     "src": [
       "test/core/json/json_rewrite.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -876,7 +990,9 @@
     "name": "json_rewrite_test", 
     "src": [
       "test/core/json/json_rewrite_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -890,7 +1006,9 @@
     "name": "json_stream_error_test", 
     "src": [
       "test/core/json/json_stream_error_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -904,7 +1022,9 @@
     "name": "json_test", 
     "src": [
       "test/core/json/json_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -918,7 +1038,9 @@
     "name": "lame_client_test", 
     "src": [
       "test/core/surface/lame_client_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -932,7 +1054,9 @@
     "name": "lb_policies_test", 
     "src": [
       "test/core/client_config/lb_policies_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -946,7 +1070,9 @@
     "name": "low_level_ping_pong_benchmark", 
     "src": [
       "test/core/network_benchmarks/low_level_ping_pong.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -960,7 +1086,25 @@
     "name": "message_compress_test", 
     "src": [
       "test/core/compression/message_compress_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "mlog_test", 
+    "src": [
+      "test/core/census/mlog_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -974,7 +1118,9 @@
     "name": "multiple_server_queues_test", 
     "src": [
       "test/core/end2end/multiple_server_queues_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -986,7 +1132,9 @@
     "name": "murmur_hash_test", 
     "src": [
       "test/core/support/murmur_hash_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1000,7 +1148,9 @@
     "name": "no_server_test", 
     "src": [
       "test/core/end2end/no_server_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1014,7 +1164,9 @@
     "name": "resolve_address_test", 
     "src": [
       "test/core/iomgr/resolve_address_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1028,7 +1180,9 @@
     "name": "secure_channel_create_test", 
     "src": [
       "test/core/surface/secure_channel_create_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1042,7 +1196,9 @@
     "name": "secure_endpoint_test", 
     "src": [
       "test/core/security/secure_endpoint_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1056,7 +1212,9 @@
     "name": "server_chttp2_test", 
     "src": [
       "test/core/surface/server_chttp2_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1070,7 +1228,9 @@
     "name": "server_test", 
     "src": [
       "test/core/surface/server_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1085,7 +1245,9 @@
     "name": "set_initial_connect_string_test", 
     "src": [
       "test/core/client_config/set_initial_connect_string_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1099,7 +1261,9 @@
     "name": "sockaddr_resolver_test", 
     "src": [
       "test/core/client_config/resolvers/sockaddr_resolver_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1113,7 +1277,9 @@
     "name": "sockaddr_utils_test", 
     "src": [
       "test/core/iomgr/sockaddr_utils_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1127,7 +1293,9 @@
     "name": "socket_utils_test", 
     "src": [
       "test/core/iomgr/socket_utils_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1141,7 +1309,9 @@
     "name": "tcp_client_posix_test", 
     "src": [
       "test/core/iomgr/tcp_client_posix_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1155,7 +1325,9 @@
     "name": "tcp_posix_test", 
     "src": [
       "test/core/iomgr/tcp_posix_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1169,7 +1341,9 @@
     "name": "tcp_server_posix_test", 
     "src": [
       "test/core/iomgr/tcp_server_posix_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1183,7 +1357,9 @@
     "name": "time_averaged_stats_test", 
     "src": [
       "test/core/iomgr/time_averaged_stats_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1197,7 +1373,9 @@
     "name": "timeout_encoding_test", 
     "src": [
       "test/core/transport/chttp2/timeout_encoding_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1211,7 +1389,9 @@
     "name": "timer_heap_test", 
     "src": [
       "test/core/iomgr/timer_heap_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1225,7 +1405,9 @@
     "name": "timer_list_test", 
     "src": [
       "test/core/iomgr/timer_list_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1239,7 +1421,9 @@
     "name": "timers_test", 
     "src": [
       "test/core/profiling/timers_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1253,7 +1437,9 @@
     "name": "transport_connectivity_state_test", 
     "src": [
       "test/core/transport/connectivity_state_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1267,7 +1453,9 @@
     "name": "transport_metadata_test", 
     "src": [
       "test/core/transport/metadata_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1281,7 +1469,9 @@
     "name": "transport_security_test", 
     "src": [
       "test/core/tsi/transport_security_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1295,7 +1485,9 @@
     "name": "udp_server_test", 
     "src": [
       "test/core/iomgr/udp_server_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1309,7 +1501,9 @@
     "name": "uri_parser_test", 
     "src": [
       "test/core/client_config/uri_parser_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1323,7 +1517,9 @@
     "name": "workqueue_test", 
     "src": [
       "test/core/iomgr/workqueue_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1339,7 +1535,9 @@
     "name": "alarm_cpp_test", 
     "src": [
       "test/cpp/common/alarm_cpp_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1355,7 +1553,9 @@
     "name": "async_end2end_test", 
     "src": [
       "test/cpp/end2end/async_end2end_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1372,7 +1572,9 @@
     "name": "async_streaming_ping_pong_test", 
     "src": [
       "test/cpp/qps/async_streaming_ping_pong_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1389,7 +1591,9 @@
     "name": "async_unary_ping_pong_test", 
     "src": [
       "test/cpp/qps/async_unary_ping_pong_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1405,7 +1609,9 @@
     "name": "auth_property_iterator_test", 
     "src": [
       "test/cpp/common/auth_property_iterator_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1418,7 +1624,9 @@
     "name": "channel_arguments_test", 
     "src": [
       "test/cpp/common/channel_arguments_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1434,7 +1642,9 @@
     "name": "cli_call_test", 
     "src": [
       "test/cpp/util/cli_call_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1450,7 +1660,9 @@
     "name": "client_crash_test", 
     "src": [
       "test/cpp/end2end/client_crash_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1466,7 +1678,9 @@
     "name": "client_crash_test_server", 
     "src": [
       "test/cpp/end2end/client_crash_test_server.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1479,7 +1693,9 @@
     "name": "credentials_test", 
     "src": [
       "test/cpp/client/credentials_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1494,7 +1710,9 @@
     "name": "cxx_byte_buffer_test", 
     "src": [
       "test/cpp/util/byte_buffer_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1509,7 +1727,9 @@
     "name": "cxx_slice_test", 
     "src": [
       "test/cpp/util/slice_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1520,7 +1740,9 @@
     "name": "cxx_string_ref_test", 
     "src": [
       "test/cpp/util/string_ref_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1535,7 +1757,9 @@
     "name": "cxx_time_test", 
     "src": [
       "test/cpp/util/time_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1551,7 +1775,9 @@
     "name": "end2end_test", 
     "src": [
       "test/cpp/end2end/end2end_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1568,7 +1794,9 @@
     "name": "generic_async_streaming_ping_pong_test", 
     "src": [
       "test/cpp/qps/generic_async_streaming_ping_pong_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1584,7 +1812,9 @@
     "name": "generic_end2end_test", 
     "src": [
       "test/cpp/end2end/generic_end2end_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1601,7 +1831,9 @@
     "name": "grpc_cli", 
     "src": [
       "test/cpp/util/grpc_cli.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1612,7 +1844,9 @@
     "name": "grpc_cpp_plugin", 
     "src": [
       "src/compiler/cpp_plugin.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1623,7 +1857,9 @@
     "name": "grpc_csharp_plugin", 
     "src": [
       "src/compiler/csharp_plugin.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1634,7 +1870,9 @@
     "name": "grpc_objective_c_plugin", 
     "src": [
       "src/compiler/objective_c_plugin.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1645,7 +1883,9 @@
     "name": "grpc_python_plugin", 
     "src": [
       "src/compiler/python_plugin.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1656,7 +1896,28 @@
     "name": "grpc_ruby_plugin", 
     "src": [
       "src/compiler/ruby_plugin.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
+      "grpc_test_util"
+    ], 
+    "headers": [
+      "src/proto/grpc/lb/v0/load_balancer.grpc.pb.h", 
+      "src/proto/grpc/lb/v0/load_balancer.pb.h"
+    ], 
+    "language": "c++", 
+    "name": "grpclb_api_test", 
+    "src": [
+      "test/cpp/grpclb/grpclb_api_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1672,7 +1933,9 @@
     "name": "hybrid_end2end_test", 
     "src": [
       "test/cpp/end2end/hybrid_end2end_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1689,7 +1952,9 @@
     "headers": [], 
     "language": "c++", 
     "name": "interop_client", 
-    "src": []
+    "src": [], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1706,7 +1971,9 @@
     "headers": [], 
     "language": "c++", 
     "name": "interop_server", 
-    "src": []
+    "src": [], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1720,7 +1987,9 @@
     "name": "interop_test", 
     "src": [
       "test/cpp/interop/interop_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1739,7 +2008,9 @@
     "src": [
       "test/cpp/interop/metrics_client.cc", 
       "test/cpp/util/metrics_server.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1755,7 +2026,9 @@
     "name": "mock_test", 
     "src": [
       "test/cpp/end2end/mock_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1773,7 +2046,9 @@
     "name": "qps_driver", 
     "src": [
       "test/cpp/qps/qps_driver.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1790,7 +2065,9 @@
     "name": "qps_interarrival_test", 
     "src": [
       "test/cpp/qps/qps_interarrival_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1808,7 +2085,9 @@
     "name": "qps_openloop_test", 
     "src": [
       "test/cpp/qps/qps_openloop_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1826,7 +2105,9 @@
     "name": "qps_test", 
     "src": [
       "test/cpp/qps/qps_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1849,7 +2130,9 @@
       "test/cpp/qps/client.h", 
       "test/cpp/qps/server.h", 
       "test/cpp/qps/worker.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1873,7 +2156,9 @@
     "name": "reconnect_interop_client", 
     "src": [
       "test/cpp/interop/reconnect_interop_client.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1899,7 +2184,9 @@
     "name": "reconnect_interop_server", 
     "src": [
       "test/cpp/interop/reconnect_interop_server.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1915,7 +2202,9 @@
     "name": "secure_auth_context_test", 
     "src": [
       "test/cpp/common/secure_auth_context_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1932,7 +2221,9 @@
     "name": "secure_sync_unary_ping_pong_test", 
     "src": [
       "test/cpp/qps/secure_sync_unary_ping_pong_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1948,7 +2239,9 @@
     "name": "server_crash_test", 
     "src": [
       "test/cpp/end2end/server_crash_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1964,7 +2257,9 @@
     "name": "server_crash_test_client", 
     "src": [
       "test/cpp/end2end/server_crash_test_client.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1980,7 +2275,9 @@
     "name": "shutdown_test", 
     "src": [
       "test/cpp/end2end/shutdown_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -1995,7 +2292,9 @@
     "name": "status_test", 
     "src": [
       "test/cpp/util/status_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2011,7 +2310,9 @@
     "name": "streaming_throughput_test", 
     "src": [
       "test/cpp/end2end/streaming_throughput_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2048,7 +2349,9 @@
       "test/cpp/interop/stress_test.cc", 
       "test/cpp/util/metrics_server.cc", 
       "test/cpp/util/metrics_server.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2065,7 +2368,9 @@
     "name": "sync_streaming_ping_pong_test", 
     "src": [
       "test/cpp/qps/sync_streaming_ping_pong_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2082,7 +2387,9 @@
     "name": "sync_unary_ping_pong_test", 
     "src": [
       "test/cpp/qps/sync_unary_ping_pong_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2098,7 +2405,9 @@
     "name": "thread_stress_test", 
     "src": [
       "test/cpp/end2end/thread_stress_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2118,7 +2427,9 @@
     "name": "zookeeper_test", 
     "src": [
       "test/cpp/end2end/zookeeper_test.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2130,112 +2441,596 @@
     "name": "public_headers_must_be_c89", 
     "src": [
       "test/core/surface/public_headers_must_be_c89.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
-      "bad_client_test", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
+      "boringssl", 
+      "boringssl_aes_test_lib", 
+      "boringssl_test_util"
     ], 
     "headers": [], 
-    "language": "c", 
-    "name": "badreq_bad_client_test", 
-    "src": [
-      "test/core/bad_client/tests/badreq.c"
-    ]
+    "language": "c++", 
+    "name": "boringssl_aes_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
   }, 
   {
     "deps": [
-      "bad_client_test", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
+      "boringssl", 
+      "boringssl_base64_test_lib", 
+      "boringssl_test_util"
     ], 
     "headers": [], 
-    "language": "c", 
-    "name": "connection_prefix_bad_client_test", 
-    "src": [
-      "test/core/bad_client/tests/connection_prefix.c"
-    ]
+    "language": "c++", 
+    "name": "boringssl_base64_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
   }, 
   {
     "deps": [
-      "bad_client_test", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
+      "boringssl", 
+      "boringssl_bio_test_lib", 
+      "boringssl_test_util"
     ], 
     "headers": [], 
-    "language": "c", 
-    "name": "headers_bad_client_test", 
-    "src": [
-      "test/core/bad_client/tests/headers.c"
-    ]
+    "language": "c++", 
+    "name": "boringssl_bio_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
   }, 
   {
     "deps": [
-      "bad_client_test", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
+      "boringssl", 
+      "boringssl_bn_test_lib", 
+      "boringssl_test_util"
     ], 
     "headers": [], 
-    "language": "c", 
-    "name": "initial_settings_frame_bad_client_test", 
-    "src": [
-      "test/core/bad_client/tests/initial_settings_frame.c"
-    ]
+    "language": "c++", 
+    "name": "boringssl_bn_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
   }, 
   {
     "deps": [
-      "bad_client_test", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
+      "boringssl", 
+      "boringssl_bytestring_test_lib", 
+      "boringssl_test_util"
     ], 
     "headers": [], 
-    "language": "c", 
-    "name": "server_registered_method_bad_client_test", 
-    "src": [
-      "test/core/bad_client/tests/server_registered_method.c"
-    ]
+    "language": "c++", 
+    "name": "boringssl_bytestring_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
   }, 
   {
     "deps": [
-      "bad_client_test", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
+      "boringssl", 
+      "boringssl_aead_test_lib", 
+      "boringssl_test_util"
     ], 
     "headers": [], 
-    "language": "c", 
-    "name": "simple_request_bad_client_test", 
-    "src": [
-      "test/core/bad_client/tests/simple_request.c"
-    ]
+    "language": "c++", 
+    "name": "boringssl_aead_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
   }, 
   {
     "deps": [
-      "bad_client_test", 
-      "gpr", 
-      "gpr_test_util", 
-      "grpc_test_util_unsecure", 
-      "grpc_unsecure"
+      "boringssl", 
+      "boringssl_cipher_test_lib", 
+      "boringssl_test_util"
     ], 
     "headers": [], 
-    "language": "c", 
-    "name": "unknown_frame_bad_client_test", 
-    "src": [
+    "language": "c++", 
+    "name": "boringssl_cipher_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_cmac_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_cmac_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_constant_time_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_constant_time_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_ed25519_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_ed25519_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util", 
+      "boringssl_x25519_test_lib"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_x25519_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_dh_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_dh_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_digest_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_digest_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_dsa_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_dsa_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_ec_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_ec_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_example_mul_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_example_mul", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_ecdsa_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_ecdsa_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_err_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_err_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_evp_extra_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_evp_extra_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_evp_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_evp_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_pbkdf_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_pbkdf_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_hkdf_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_hkdf_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_hmac_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_hmac_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_lhash_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_lhash_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_gcm_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_gcm_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_pkcs12_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_pkcs12_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_pkcs8_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_pkcs8_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_poly1305_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_poly1305_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_refcount_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_refcount_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_rsa_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_rsa_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util", 
+      "boringssl_thread_test_lib"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_thread_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_pkcs7_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_pkcs7_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_tab_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_tab_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util", 
+      "boringssl_v3name_test_lib"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_v3name_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_pqueue_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_pqueue_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_ssl_test_lib", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_ssl_test", 
+    "src": [], 
+    "third_party": true, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "bad_client_test", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "badreq_bad_client_test", 
+    "src": [
+      "test/core/bad_client/tests/badreq.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "bad_client_test", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "connection_prefix_bad_client_test", 
+    "src": [
+      "test/core/bad_client/tests/connection_prefix.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "bad_client_test", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "headers_bad_client_test", 
+    "src": [
+      "test/core/bad_client/tests/headers.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "bad_client_test", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "initial_settings_frame_bad_client_test", 
+    "src": [
+      "test/core/bad_client/tests/initial_settings_frame.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "bad_client_test", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "server_registered_method_bad_client_test", 
+    "src": [
+      "test/core/bad_client/tests/server_registered_method.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "bad_client_test", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "simple_request_bad_client_test", 
+    "src": [
+      "test/core/bad_client/tests/simple_request.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "bad_client_test", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "unknown_frame_bad_client_test", 
+    "src": [
       "test/core/bad_client/tests/unknown_frame.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2250,7 +3045,9 @@
     "name": "window_overflow_bad_client_test", 
     "src": [
       "test/core/bad_client/tests/window_overflow.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2265,7 +3062,9 @@
     "name": "bad_ssl_alpn_server", 
     "src": [
       "test/core/bad_ssl/servers/alpn.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2280,7 +3079,9 @@
     "name": "bad_ssl_cert_server", 
     "src": [
       "test/core/bad_ssl/servers/cert.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2294,7 +3095,9 @@
     "name": "bad_ssl_alpn_test", 
     "src": [
       "test/core/bad_ssl/bad_ssl_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2308,7 +3111,9 @@
     "name": "bad_ssl_cert_test", 
     "src": [
       "test/core/bad_ssl/bad_ssl_test.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2324,7 +3129,9 @@
     "name": "h2_census_test", 
     "src": [
       "test/core/end2end/fixtures/h2_census.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2340,7 +3147,9 @@
     "name": "h2_compress_test", 
     "src": [
       "test/core/end2end/fixtures/h2_compress.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2356,7 +3165,9 @@
     "name": "h2_fakesec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_fakesec.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2372,7 +3183,9 @@
     "name": "h2_full_test", 
     "src": [
       "test/core/end2end/fixtures/h2_full.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2388,7 +3201,9 @@
     "name": "h2_full+pipe_test", 
     "src": [
       "test/core/end2end/fixtures/h2_full+pipe.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2404,7 +3219,9 @@
     "name": "h2_full+poll_test", 
     "src": [
       "test/core/end2end/fixtures/h2_full+poll.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2420,7 +3237,9 @@
     "name": "h2_full+poll+pipe_test", 
     "src": [
       "test/core/end2end/fixtures/h2_full+poll+pipe.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2436,7 +3255,9 @@
     "name": "h2_oauth2_test", 
     "src": [
       "test/core/end2end/fixtures/h2_oauth2.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2452,7 +3273,9 @@
     "name": "h2_proxy_test", 
     "src": [
       "test/core/end2end/fixtures/h2_proxy.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2468,7 +3291,9 @@
     "name": "h2_sockpair_test", 
     "src": [
       "test/core/end2end/fixtures/h2_sockpair.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2484,7 +3309,9 @@
     "name": "h2_sockpair+trace_test", 
     "src": [
       "test/core/end2end/fixtures/h2_sockpair+trace.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2500,7 +3327,9 @@
     "name": "h2_sockpair_1byte_test", 
     "src": [
       "test/core/end2end/fixtures/h2_sockpair_1byte.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2516,7 +3345,9 @@
     "name": "h2_ssl_test", 
     "src": [
       "test/core/end2end/fixtures/h2_ssl.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2532,7 +3363,9 @@
     "name": "h2_ssl+poll_test", 
     "src": [
       "test/core/end2end/fixtures/h2_ssl+poll.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2548,7 +3381,9 @@
     "name": "h2_ssl_proxy_test", 
     "src": [
       "test/core/end2end/fixtures/h2_ssl_proxy.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2564,7 +3399,9 @@
     "name": "h2_uchannel_test", 
     "src": [
       "test/core/end2end/fixtures/h2_uchannel.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2580,7 +3417,9 @@
     "name": "h2_uds_test", 
     "src": [
       "test/core/end2end/fixtures/h2_uds.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2596,7 +3435,9 @@
     "name": "h2_uds+poll_test", 
     "src": [
       "test/core/end2end/fixtures/h2_uds+poll.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2611,7 +3452,9 @@
     "name": "h2_census_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_census.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2626,7 +3469,9 @@
     "name": "h2_compress_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_compress.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2641,7 +3486,9 @@
     "name": "h2_full_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_full.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2656,7 +3503,9 @@
     "name": "h2_full+pipe_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_full+pipe.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2671,7 +3520,9 @@
     "name": "h2_full+poll_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_full+poll.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2686,7 +3537,9 @@
     "name": "h2_full+poll+pipe_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_full+poll+pipe.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2701,7 +3554,9 @@
     "name": "h2_proxy_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_proxy.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2716,7 +3571,9 @@
     "name": "h2_sockpair_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_sockpair.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2731,7 +3588,9 @@
     "name": "h2_sockpair+trace_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_sockpair+trace.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2746,7 +3605,9 @@
     "name": "h2_sockpair_1byte_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_sockpair_1byte.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2761,7 +3622,9 @@
     "name": "h2_uchannel_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_uchannel.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2776,7 +3639,9 @@
     "name": "h2_uds_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_uds.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [
@@ -2791,7 +3656,9 @@
     "name": "h2_uds+poll_nosec_test", 
     "src": [
       "test/core/end2end/fixtures/h2_uds+poll.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "target"
   }, 
   {
     "deps": [], 
@@ -2841,13 +3708,14 @@
       "src/core/profiling/timers.h", 
       "src/core/support/block_annotate.h", 
       "src/core/support/env.h", 
-      "src/core/support/file.h", 
+      "src/core/support/load_file.h", 
       "src/core/support/murmur_hash.h", 
       "src/core/support/stack_lockfree.h", 
       "src/core/support/string.h", 
       "src/core/support/string_win32.h", 
       "src/core/support/thd_internal.h", 
-      "src/core/support/time_precise.h"
+      "src/core/support/time_precise.h", 
+      "src/core/support/tmpfile.h"
     ], 
     "language": "c", 
     "name": "gpr", 
@@ -2909,12 +3777,10 @@
       "src/core/support/env_linux.c", 
       "src/core/support/env_posix.c", 
       "src/core/support/env_win32.c", 
-      "src/core/support/file.c", 
-      "src/core/support/file.h", 
-      "src/core/support/file_posix.c", 
-      "src/core/support/file_win32.c", 
       "src/core/support/histogram.c", 
       "src/core/support/host_port.c", 
+      "src/core/support/load_file.c", 
+      "src/core/support/load_file.h", 
       "src/core/support/log.c", 
       "src/core/support/log_android.c", 
       "src/core/support/log_linux.c", 
@@ -2946,8 +3812,13 @@
       "src/core/support/time_precise.h", 
       "src/core/support/time_win32.c", 
       "src/core/support/tls_pthread.c", 
+      "src/core/support/tmpfile.h", 
+      "src/core/support/tmpfile_posix.c", 
+      "src/core/support/tmpfile_win32.c", 
       "src/core/support/wrap_memcpy.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -2961,7 +3832,9 @@
     "src": [
       "test/core/util/test_config.c", 
       "test/core/util/test_config.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -2998,6 +3871,7 @@
       "src/core/client_config/client_config.h", 
       "src/core/client_config/connector.h", 
       "src/core/client_config/initial_connect_string.h", 
+      "src/core/client_config/lb_policies/load_balancer_api.h", 
       "src/core/client_config/lb_policies/pick_first.h", 
       "src/core/client_config/lb_policies/round_robin.h", 
       "src/core/client_config/lb_policy.h", 
@@ -3048,7 +3922,6 @@
       "src/core/iomgr/time_averaged_stats.h", 
       "src/core/iomgr/timer.h", 
       "src/core/iomgr/timer_heap.h", 
-      "src/core/iomgr/timer_internal.h", 
       "src/core/iomgr/udp_server.h", 
       "src/core/iomgr/wakeup_fd_pipe.h", 
       "src/core/iomgr/wakeup_fd_posix.h", 
@@ -3059,8 +3932,9 @@
       "src/core/json/json_common.h", 
       "src/core/json/json_reader.h", 
       "src/core/json/json_writer.h", 
+      "src/core/proto/grpc/lb/v0/load_balancer.pb.h", 
       "src/core/security/auth_filters.h", 
-      "src/core/security/base64.h", 
+      "src/core/security/b64.h", 
       "src/core/security/credentials.h", 
       "src/core/security/handshake.h", 
       "src/core/security/json_token.h", 
@@ -3111,7 +3985,11 @@
       "src/core/tsi/ssl_transport_security.h", 
       "src/core/tsi/ssl_types.h", 
       "src/core/tsi/transport_security.h", 
-      "src/core/tsi/transport_security_interface.h"
+      "src/core/tsi/transport_security_interface.h", 
+      "third_party/nanopb/pb.h", 
+      "third_party/nanopb/pb_common.h", 
+      "third_party/nanopb/pb_decode.h", 
+      "third_party/nanopb/pb_encode.h"
     ], 
     "language": "c", 
     "name": "grpc", 
@@ -3167,6 +4045,8 @@
       "src/core/client_config/default_initial_connect_string.c", 
       "src/core/client_config/initial_connect_string.c", 
       "src/core/client_config/initial_connect_string.h", 
+      "src/core/client_config/lb_policies/load_balancer_api.c", 
+      "src/core/client_config/lb_policies/load_balancer_api.h", 
       "src/core/client_config/lb_policies/pick_first.c", 
       "src/core/client_config/lb_policies/pick_first.h", 
       "src/core/client_config/lb_policies/round_robin.c", 
@@ -3195,8 +4075,8 @@
       "src/core/client_config/subchannel_index.h", 
       "src/core/client_config/uri_parser.c", 
       "src/core/client_config/uri_parser.h", 
-      "src/core/compression/algorithm.c", 
       "src/core/compression/algorithm_metadata.h", 
+      "src/core/compression/compression_algorithm.c", 
       "src/core/compression/message_compress.c", 
       "src/core/compression/message_compress.h", 
       "src/core/debug/trace.c", 
@@ -3271,7 +4151,6 @@
       "src/core/iomgr/timer.h", 
       "src/core/iomgr/timer_heap.c", 
       "src/core/iomgr/timer_heap.h", 
-      "src/core/iomgr/timer_internal.h", 
       "src/core/iomgr/udp_server.c", 
       "src/core/iomgr/udp_server.h", 
       "src/core/iomgr/wakeup_fd_eventfd.c", 
@@ -3293,9 +4172,11 @@
       "src/core/json/json_string.c", 
       "src/core/json/json_writer.c", 
       "src/core/json/json_writer.h", 
+      "src/core/proto/grpc/lb/v0/load_balancer.pb.c", 
+      "src/core/proto/grpc/lb/v0/load_balancer.pb.h", 
       "src/core/security/auth_filters.h", 
-      "src/core/security/base64.c", 
-      "src/core/security/base64.h", 
+      "src/core/security/b64.c", 
+      "src/core/security/b64.h", 
       "src/core/security/client_auth_filter.c", 
       "src/core/security/credentials.c", 
       "src/core/security/credentials.h", 
@@ -3415,7 +4296,9 @@
       "src/core/tsi/transport_security.c", 
       "src/core/tsi/transport_security.h", 
       "src/core/tsi/transport_security_interface.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -3425,7 +4308,9 @@
     "headers": [], 
     "language": "c", 
     "name": "grpc_dll", 
-    "src": []
+    "src": [], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -3468,7 +4353,9 @@
       "test/core/util/port_windows.c", 
       "test/core/util/slice_splitter.c", 
       "test/core/util/slice_splitter.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -3503,7 +4390,9 @@
       "test/core/util/port_windows.c", 
       "test/core/util/slice_splitter.c", 
       "test/core/util/slice_splitter.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -3539,6 +4428,7 @@
       "src/core/client_config/client_config.h", 
       "src/core/client_config/connector.h", 
       "src/core/client_config/initial_connect_string.h", 
+      "src/core/client_config/lb_policies/load_balancer_api.h", 
       "src/core/client_config/lb_policies/pick_first.h", 
       "src/core/client_config/lb_policies/round_robin.h", 
       "src/core/client_config/lb_policy.h", 
@@ -3589,7 +4479,6 @@
       "src/core/iomgr/time_averaged_stats.h", 
       "src/core/iomgr/timer.h", 
       "src/core/iomgr/timer_heap.h", 
-      "src/core/iomgr/timer_internal.h", 
       "src/core/iomgr/udp_server.h", 
       "src/core/iomgr/wakeup_fd_pipe.h", 
       "src/core/iomgr/wakeup_fd_posix.h", 
@@ -3600,6 +4489,7 @@
       "src/core/json/json_common.h", 
       "src/core/json/json_reader.h", 
       "src/core/json/json_writer.h", 
+      "src/core/proto/grpc/lb/v0/load_balancer.pb.h", 
       "src/core/statistics/census_interface.h", 
       "src/core/statistics/census_rpc_stats.h", 
       "src/core/surface/api_trace.h", 
@@ -3638,7 +4528,11 @@
       "src/core/transport/metadata_batch.h", 
       "src/core/transport/static_metadata.h", 
       "src/core/transport/transport.h", 
-      "src/core/transport/transport_impl.h"
+      "src/core/transport/transport_impl.h", 
+      "third_party/nanopb/pb.h", 
+      "third_party/nanopb/pb_common.h", 
+      "third_party/nanopb/pb_decode.h", 
+      "third_party/nanopb/pb_encode.h"
     ], 
     "language": "c", 
     "name": "grpc_unsecure", 
@@ -3693,6 +4587,8 @@
       "src/core/client_config/default_initial_connect_string.c", 
       "src/core/client_config/initial_connect_string.c", 
       "src/core/client_config/initial_connect_string.h", 
+      "src/core/client_config/lb_policies/load_balancer_api.c", 
+      "src/core/client_config/lb_policies/load_balancer_api.h", 
       "src/core/client_config/lb_policies/pick_first.c", 
       "src/core/client_config/lb_policies/pick_first.h", 
       "src/core/client_config/lb_policies/round_robin.c", 
@@ -3721,8 +4617,8 @@
       "src/core/client_config/subchannel_index.h", 
       "src/core/client_config/uri_parser.c", 
       "src/core/client_config/uri_parser.h", 
-      "src/core/compression/algorithm.c", 
       "src/core/compression/algorithm_metadata.h", 
+      "src/core/compression/compression_algorithm.c", 
       "src/core/compression/message_compress.c", 
       "src/core/compression/message_compress.h", 
       "src/core/debug/trace.c", 
@@ -3796,7 +4692,6 @@
       "src/core/iomgr/timer.h", 
       "src/core/iomgr/timer_heap.c", 
       "src/core/iomgr/timer_heap.h", 
-      "src/core/iomgr/timer_internal.h", 
       "src/core/iomgr/udp_server.c", 
       "src/core/iomgr/udp_server.h", 
       "src/core/iomgr/wakeup_fd_eventfd.c", 
@@ -3818,6 +4713,8 @@
       "src/core/json/json_string.c", 
       "src/core/json/json_writer.c", 
       "src/core/json/json_writer.h", 
+      "src/core/proto/grpc/lb/v0/load_balancer.pb.c", 
+      "src/core/proto/grpc/lb/v0/load_balancer.pb.h", 
       "src/core/statistics/census_interface.h", 
       "src/core/statistics/census_rpc_stats.h", 
       "src/core/surface/alarm.c", 
@@ -3907,7 +4804,9 @@
       "src/core/transport/transport.h", 
       "src/core/transport/transport_impl.h", 
       "src/core/transport/transport_op_string.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -3924,7 +4823,9 @@
       "include/grpc/grpc_zookeeper.h", 
       "src/core/client_config/resolvers/zookeeper_resolver.c", 
       "src/core/client_config/resolvers/zookeeper_resolver.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -3942,7 +4843,9 @@
     "src": [
       "test/core/util/reconnect_server.c", 
       "test/core/util/reconnect_server.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -3959,7 +4862,9 @@
     "src": [
       "test/core/util/test_tcp_server.c", 
       "test/core/util/test_tcp_server.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4136,7 +5041,6 @@
       "src/cpp/client/secure_credentials.cc", 
       "src/cpp/client/secure_credentials.h", 
       "src/cpp/codegen/grpc_library.cc", 
-      "src/cpp/common/alarm.cc", 
       "src/cpp/common/auth_property_iterator.cc", 
       "src/cpp/common/call.cc", 
       "src/cpp/common/channel_arguments.cc", 
@@ -4165,7 +5069,9 @@
       "src/cpp/util/status.cc", 
       "src/cpp/util/string_ref.cc", 
       "src/cpp/util/time.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [], 
@@ -4177,7 +5083,9 @@
     "src": [
       "test/cpp/util/test_config.cc", 
       "test/cpp/util/test_config.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4216,7 +5124,9 @@
       "test/cpp/util/subprocess.h", 
       "test/cpp/util/test_credentials_provider.cc", 
       "test/cpp/util/test_credentials_provider.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4389,7 +5299,6 @@
       "src/cpp/client/generic_stub.cc", 
       "src/cpp/client/insecure_credentials.cc", 
       "src/cpp/codegen/grpc_library.cc", 
-      "src/cpp/common/alarm.cc", 
       "src/cpp/common/call.cc", 
       "src/cpp/common/channel_arguments.cc", 
       "src/cpp/common/completion_queue.cc", 
@@ -4412,7 +5321,9 @@
       "src/cpp/util/status.cc", 
       "src/cpp/util/string_ref.cc", 
       "src/cpp/util/time.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [], 
@@ -4557,7 +5468,9 @@
       "src/compiler/ruby_generator_map-inl.h", 
       "src/compiler/ruby_generator_string-inl.h", 
       "src/cpp/codegen/grpc_library.cc"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4577,7 +5490,9 @@
     "src": [
       "test/cpp/interop/client_helper.cc", 
       "test/cpp/interop/client_helper.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4605,7 +5520,9 @@
       "test/cpp/interop/client.cc", 
       "test/cpp/interop/interop_client.cc", 
       "test/cpp/interop/interop_client.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4622,7 +5539,9 @@
     "src": [
       "test/cpp/interop/server_helper.cc", 
       "test/cpp/interop/server_helper.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4646,8 +5565,10 @@
     "language": "c++", 
     "name": "interop_server_main", 
     "src": [
-      "test/cpp/interop/server.cc"
-    ]
+      "test/cpp/interop/server_main.cc"
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4678,7 +5599,7 @@
       "test/cpp/qps/report.h", 
       "test/cpp/qps/server.h", 
       "test/cpp/qps/stats.h", 
-      "test/cpp/qps/timer.h", 
+      "test/cpp/qps/usage_timer.h", 
       "test/cpp/util/benchmark_config.h"
     ], 
     "language": "c++", 
@@ -4703,11 +5624,13 @@
       "test/cpp/qps/server_async.cc", 
       "test/cpp/qps/server_sync.cc", 
       "test/cpp/qps/stats.h", 
-      "test/cpp/qps/timer.cc", 
-      "test/cpp/qps/timer.h", 
+      "test/cpp/qps/usage_timer.cc", 
+      "test/cpp/qps/usage_timer.h", 
       "test/cpp/util/benchmark_config.cc", 
       "test/cpp/util/benchmark_config.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4719,7 +5642,590 @@
     "name": "grpc_csharp_ext", 
     "src": [
       "src/csharp/ext/grpc_csharp_ext.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [], 
+    "headers": [
+      "third_party/boringssl/crypto/aes/internal.h", 
+      "third_party/boringssl/crypto/asn1/asn1_locl.h", 
+      "third_party/boringssl/crypto/bio/internal.h", 
+      "third_party/boringssl/crypto/bn/internal.h", 
+      "third_party/boringssl/crypto/bn/rsaz_exp.h", 
+      "third_party/boringssl/crypto/bytestring/internal.h", 
+      "third_party/boringssl/crypto/cipher/internal.h", 
+      "third_party/boringssl/crypto/conf/conf_def.h", 
+      "third_party/boringssl/crypto/conf/internal.h", 
+      "third_party/boringssl/crypto/des/internal.h", 
+      "third_party/boringssl/crypto/dh/internal.h", 
+      "third_party/boringssl/crypto/digest/internal.h", 
+      "third_party/boringssl/crypto/digest/md32_common.h", 
+      "third_party/boringssl/crypto/directory.h", 
+      "third_party/boringssl/crypto/dsa/internal.h", 
+      "third_party/boringssl/crypto/ec/internal.h", 
+      "third_party/boringssl/crypto/ec/p256-x86_64-table.h", 
+      "third_party/boringssl/crypto/evp/internal.h", 
+      "third_party/boringssl/crypto/internal.h", 
+      "third_party/boringssl/crypto/modes/internal.h", 
+      "third_party/boringssl/crypto/obj/obj_dat.h", 
+      "third_party/boringssl/crypto/obj/obj_xref.h", 
+      "third_party/boringssl/crypto/pkcs8/internal.h", 
+      "third_party/boringssl/crypto/rand/internal.h", 
+      "third_party/boringssl/crypto/rsa/internal.h", 
+      "third_party/boringssl/crypto/test/scoped_types.h", 
+      "third_party/boringssl/crypto/test/test_util.h", 
+      "third_party/boringssl/crypto/x509/charmap.h", 
+      "third_party/boringssl/crypto/x509/vpm_int.h", 
+      "third_party/boringssl/crypto/x509v3/ext_dat.h", 
+      "third_party/boringssl/crypto/x509v3/pcy_int.h", 
+      "third_party/boringssl/include/openssl/aead.h", 
+      "third_party/boringssl/include/openssl/aes.h", 
+      "third_party/boringssl/include/openssl/arm_arch.h", 
+      "third_party/boringssl/include/openssl/asn1.h", 
+      "third_party/boringssl/include/openssl/asn1_mac.h", 
+      "third_party/boringssl/include/openssl/asn1t.h", 
+      "third_party/boringssl/include/openssl/base.h", 
+      "third_party/boringssl/include/openssl/base64.h", 
+      "third_party/boringssl/include/openssl/bio.h", 
+      "third_party/boringssl/include/openssl/blowfish.h", 
+      "third_party/boringssl/include/openssl/bn.h", 
+      "third_party/boringssl/include/openssl/buf.h", 
+      "third_party/boringssl/include/openssl/buffer.h", 
+      "third_party/boringssl/include/openssl/bytestring.h", 
+      "third_party/boringssl/include/openssl/cast.h", 
+      "third_party/boringssl/include/openssl/chacha.h", 
+      "third_party/boringssl/include/openssl/cipher.h", 
+      "third_party/boringssl/include/openssl/cmac.h", 
+      "third_party/boringssl/include/openssl/conf.h", 
+      "third_party/boringssl/include/openssl/cpu.h", 
+      "third_party/boringssl/include/openssl/crypto.h", 
+      "third_party/boringssl/include/openssl/curve25519.h", 
+      "third_party/boringssl/include/openssl/des.h", 
+      "third_party/boringssl/include/openssl/dh.h", 
+      "third_party/boringssl/include/openssl/digest.h", 
+      "third_party/boringssl/include/openssl/dsa.h", 
+      "third_party/boringssl/include/openssl/dtls1.h", 
+      "third_party/boringssl/include/openssl/ec.h", 
+      "third_party/boringssl/include/openssl/ec_key.h", 
+      "third_party/boringssl/include/openssl/ecdh.h", 
+      "third_party/boringssl/include/openssl/ecdsa.h", 
+      "third_party/boringssl/include/openssl/engine.h", 
+      "third_party/boringssl/include/openssl/err.h", 
+      "third_party/boringssl/include/openssl/evp.h", 
+      "third_party/boringssl/include/openssl/ex_data.h", 
+      "third_party/boringssl/include/openssl/hkdf.h", 
+      "third_party/boringssl/include/openssl/hmac.h", 
+      "third_party/boringssl/include/openssl/lhash.h", 
+      "third_party/boringssl/include/openssl/lhash_macros.h", 
+      "third_party/boringssl/include/openssl/md4.h", 
+      "third_party/boringssl/include/openssl/md5.h", 
+      "third_party/boringssl/include/openssl/mem.h", 
+      "third_party/boringssl/include/openssl/obj.h", 
+      "third_party/boringssl/include/openssl/obj_mac.h", 
+      "third_party/boringssl/include/openssl/objects.h", 
+      "third_party/boringssl/include/openssl/opensslfeatures.h", 
+      "third_party/boringssl/include/openssl/opensslv.h", 
+      "third_party/boringssl/include/openssl/ossl_typ.h", 
+      "third_party/boringssl/include/openssl/pem.h", 
+      "third_party/boringssl/include/openssl/pkcs12.h", 
+      "third_party/boringssl/include/openssl/pkcs7.h", 
+      "third_party/boringssl/include/openssl/pkcs8.h", 
+      "third_party/boringssl/include/openssl/poly1305.h", 
+      "third_party/boringssl/include/openssl/pqueue.h", 
+      "third_party/boringssl/include/openssl/rand.h", 
+      "third_party/boringssl/include/openssl/rc4.h", 
+      "third_party/boringssl/include/openssl/rsa.h", 
+      "third_party/boringssl/include/openssl/safestack.h", 
+      "third_party/boringssl/include/openssl/sha.h", 
+      "third_party/boringssl/include/openssl/srtp.h", 
+      "third_party/boringssl/include/openssl/ssl.h", 
+      "third_party/boringssl/include/openssl/ssl3.h", 
+      "third_party/boringssl/include/openssl/stack.h", 
+      "third_party/boringssl/include/openssl/stack_macros.h", 
+      "third_party/boringssl/include/openssl/thread.h", 
+      "third_party/boringssl/include/openssl/time_support.h", 
+      "third_party/boringssl/include/openssl/tls1.h", 
+      "third_party/boringssl/include/openssl/type_check.h", 
+      "third_party/boringssl/include/openssl/x509.h", 
+      "third_party/boringssl/include/openssl/x509_vfy.h", 
+      "third_party/boringssl/include/openssl/x509v3.h", 
+      "third_party/boringssl/ssl/internal.h", 
+      "third_party/boringssl/ssl/test/async_bio.h", 
+      "third_party/boringssl/ssl/test/packeted_bio.h", 
+      "third_party/boringssl/ssl/test/scoped_types.h", 
+      "third_party/boringssl/ssl/test/test_config.h"
+    ], 
+    "language": "c", 
+    "name": "boringssl", 
+    "src": [
+      "src/boringssl/err_data.c"
+    ], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_test_util", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_aes_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_base64_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_bio_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_bn_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_bytestring_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_aead_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_cipher_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_cmac_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_constant_time_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_ed25519_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_x25519_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_dh_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_digest_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_dsa_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_ec_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_example_mul_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_ecdsa_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_err_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_evp_extra_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_evp_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_pbkdf_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_hkdf_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_hmac_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_lhash_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_gcm_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_pkcs12_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_pkcs8_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_poly1305_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_refcount_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_rsa_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_thread_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_pkcs7_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_tab_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_v3name_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "boringssl_pqueue_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
+      "boringssl", 
+      "boringssl_test_util"
+    ], 
+    "headers": [], 
+    "language": "c++", 
+    "name": "boringssl_ssl_test_lib", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [], 
+    "headers": [
+      "third_party/zlib/crc32.h", 
+      "third_party/zlib/deflate.h", 
+      "third_party/zlib/gzguts.h", 
+      "third_party/zlib/inffast.h", 
+      "third_party/zlib/inffixed.h", 
+      "third_party/zlib/inflate.h", 
+      "third_party/zlib/inftrees.h", 
+      "third_party/zlib/trees.h", 
+      "third_party/zlib/zconf.h", 
+      "third_party/zlib/zlib.h", 
+      "third_party/zlib/zutil.h"
+    ], 
+    "language": "c", 
+    "name": "z", 
+    "src": [], 
+    "third_party": true, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4736,7 +6242,9 @@
     "src": [
       "test/core/bad_client/bad_client.c", 
       "test/core/bad_client/bad_client.h"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4746,14 +6254,16 @@
       "grpc_test_util"
     ], 
     "headers": [
-      "test/core/bad_ssl/server.h"
+      "test/core/bad_ssl/server_common.h"
     ], 
     "language": "c", 
     "name": "bad_ssl_test_server", 
     "src": [
-      "test/core/bad_ssl/server.c", 
-      "test/core/bad_ssl/server.h"
-    ]
+      "test/core/bad_ssl/server_common.c", 
+      "test/core/bad_ssl/server_common.h"
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4782,9 +6292,8 @@
       "test/core/end2end/tests/cancel_in_a_vacuum.c", 
       "test/core/end2end/tests/cancel_test_helpers.h", 
       "test/core/end2end/tests/cancel_with_status.c", 
-      "test/core/end2end/tests/channel_connectivity.c", 
-      "test/core/end2end/tests/channel_ping.c", 
       "test/core/end2end/tests/compressed_payload.c", 
+      "test/core/end2end/tests/connectivity.c", 
       "test/core/end2end/tests/default_host.c", 
       "test/core/end2end/tests/disappearing_server.c", 
       "test/core/end2end/tests/empty_batch.c", 
@@ -4795,10 +6304,10 @@
       "test/core/end2end/tests/large_metadata.c", 
       "test/core/end2end/tests/max_concurrent_streams.c", 
       "test/core/end2end/tests/max_message_length.c", 
-      "test/core/end2end/tests/metadata.c", 
       "test/core/end2end/tests/negative_deadline.c", 
       "test/core/end2end/tests/no_op.c", 
       "test/core/end2end/tests/payload.c", 
+      "test/core/end2end/tests/ping.c", 
       "test/core/end2end/tests/ping_pong_streaming.c", 
       "test/core/end2end/tests/registered_call.c", 
       "test/core/end2end/tests/request_with_flags.c", 
@@ -4807,9 +6316,12 @@
       "test/core/end2end/tests/shutdown_finishes_calls.c", 
       "test/core/end2end/tests/shutdown_finishes_tags.c", 
       "test/core/end2end/tests/simple_delayed_request.c", 
+      "test/core/end2end/tests/simple_metadata.c", 
       "test/core/end2end/tests/simple_request.c", 
       "test/core/end2end/tests/trailing_metadata.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [
@@ -4836,9 +6348,8 @@
       "test/core/end2end/tests/cancel_in_a_vacuum.c", 
       "test/core/end2end/tests/cancel_test_helpers.h", 
       "test/core/end2end/tests/cancel_with_status.c", 
-      "test/core/end2end/tests/channel_connectivity.c", 
-      "test/core/end2end/tests/channel_ping.c", 
       "test/core/end2end/tests/compressed_payload.c", 
+      "test/core/end2end/tests/connectivity.c", 
       "test/core/end2end/tests/default_host.c", 
       "test/core/end2end/tests/disappearing_server.c", 
       "test/core/end2end/tests/empty_batch.c", 
@@ -4849,10 +6360,10 @@
       "test/core/end2end/tests/large_metadata.c", 
       "test/core/end2end/tests/max_concurrent_streams.c", 
       "test/core/end2end/tests/max_message_length.c", 
-      "test/core/end2end/tests/metadata.c", 
       "test/core/end2end/tests/negative_deadline.c", 
       "test/core/end2end/tests/no_op.c", 
       "test/core/end2end/tests/payload.c", 
+      "test/core/end2end/tests/ping.c", 
       "test/core/end2end/tests/ping_pong_streaming.c", 
       "test/core/end2end/tests/registered_call.c", 
       "test/core/end2end/tests/request_with_flags.c", 
@@ -4861,9 +6372,12 @@
       "test/core/end2end/tests/shutdown_finishes_calls.c", 
       "test/core/end2end/tests/shutdown_finishes_tags.c", 
       "test/core/end2end/tests/simple_delayed_request.c", 
+      "test/core/end2end/tests/simple_metadata.c", 
       "test/core/end2end/tests/simple_request.c", 
       "test/core/end2end/tests/trailing_metadata.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }, 
   {
     "deps": [], 
@@ -4874,6 +6388,8 @@
       "test/core/end2end/data/server1_cert.c", 
       "test/core/end2end/data/server1_key.c", 
       "test/core/end2end/data/test_root_cert.c"
-    ]
+    ], 
+    "third_party": false, 
+    "type": "lib"
   }
 ]
diff --git a/tools/run_tests/stress_test/run_stress_tests_on_gke.py b/tools/run_tests/stress_test/run_stress_tests_on_gke.py
new file mode 100755
index 0000000000000000000000000000000000000000..634eb1aca53265dc4fe6f2842f089d86c21b71bb
--- /dev/null
+++ b/tools/run_tests/stress_test/run_stress_tests_on_gke.py
@@ -0,0 +1,556 @@
+#!/usr/bin/env python2.7
+# Copyright 2015-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.
+import argparse
+import datetime
+import os
+import subprocess
+import sys
+import time
+
+stress_test_utils_dir = os.path.abspath(os.path.join(
+    os.path.dirname(__file__), '../../gcp/stress_test'))
+sys.path.append(stress_test_utils_dir)
+from stress_test_utils import BigQueryHelper
+
+kubernetes_api_dir = os.path.abspath(os.path.join(
+    os.path.dirname(__file__), '../../gcp/utils'))
+sys.path.append(kubernetes_api_dir)
+
+import kubernetes_api
+
+_GRPC_ROOT = os.path.abspath(os.path.join(
+    os.path.dirname(sys.argv[0]), '../../..'))
+os.chdir(_GRPC_ROOT)
+
+# num of seconds to wait for the GKE image to start and warmup
+_GKE_IMAGE_WARMUP_WAIT_SECS = 60
+
+_SERVER_POD_NAME = 'stress-server'
+_CLIENT_POD_NAME_PREFIX = 'stress-client'
+_DATASET_ID_PREFIX = 'stress_test'
+_SUMMARY_TABLE_ID = 'summary'
+_QPS_TABLE_ID = 'qps'
+
+_DEFAULT_DOCKER_IMAGE_NAME = 'grpc_stress_test'
+
+# The default port on which the kubernetes proxy server is started on localhost
+# (i.e kubectl proxy --port=<port>)
+_DEFAULT_KUBERNETES_PROXY_PORT = 8001
+
+# How frequently should the stress client wrapper script (running inside a GKE
+# container) poll the health of the stress client (also running inside the GKE
+# container) and upload metrics to BigQuery
+_DEFAULT_STRESS_CLIENT_POLL_INTERVAL_SECS = 60
+
+# The default setting for stress test server and client
+_DEFAULT_STRESS_SERVER_PORT = 8080
+_DEFAULT_METRICS_PORT = 8081
+_DEFAULT_TEST_CASES_STR = 'empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1'
+_DEFAULT_NUM_CHANNELS_PER_SERVER = 5
+_DEFAULT_NUM_STUBS_PER_CHANNEL = 10
+_DEFAULT_METRICS_COLLECTION_INTERVAL_SECS = 30
+
+# Number of stress client instances to launch
+_DEFAULT_NUM_CLIENTS = 3
+
+# How frequently should this test monitor the health of Stress clients and
+# Servers running in GKE
+_DEFAULT_TEST_POLL_INTERVAL_SECS = 60
+
+# Default run time for this test (2 hour)
+_DEFAULT_TEST_DURATION_SECS = 7200
+
+# The number of seconds it would take a GKE pod to warm up (i.e get to 'Running'
+# state from the time of creation). Ideally this is something the test should
+# automatically determine by using Kubernetes API to poll the pods status.
+_DEFAULT_GKE_WARMUP_SECS = 60
+
+
+class KubernetesProxy:
+  """ Class to start a proxy on localhost to the Kubernetes API server """
+
+  def __init__(self, api_port):
+    self.port = api_port
+    self.p = None
+    self.started = False
+
+  def start(self):
+    cmd = ['kubectl', 'proxy', '--port=%d' % self.port]
+    self.p = subprocess.Popen(args=cmd)
+    self.started = True
+    time.sleep(2)
+    print '..Started'
+
+  def get_port(self):
+    return self.port
+
+  def is_started(self):
+    return self.started
+
+  def __del__(self):
+    if self.p is not None:
+      print 'Shutting down Kubernetes proxy..'
+      self.p.kill()
+
+
+class TestSettings:
+
+  def __init__(self, build_docker_image, test_poll_interval_secs,
+               test_duration_secs, kubernetes_proxy_port):
+    self.build_docker_image = build_docker_image
+    self.test_poll_interval_secs = test_poll_interval_secs
+    self.test_duration_secs = test_duration_secs
+    self.kubernetes_proxy_port = kubernetes_proxy_port
+
+
+class GkeSettings:
+
+  def __init__(self, project_id, docker_image_name):
+    self.project_id = project_id
+    self.docker_image_name = docker_image_name
+    self.tag_name = 'gcr.io/%s/%s' % (project_id, docker_image_name)
+
+
+class BigQuerySettings:
+
+  def __init__(self, run_id, dataset_id, summary_table_id, qps_table_id):
+    self.run_id = run_id
+    self.dataset_id = dataset_id
+    self.summary_table_id = summary_table_id
+    self.qps_table_id = qps_table_id
+
+
+class StressServerSettings:
+
+  def __init__(self, server_pod_name, server_port):
+    self.server_pod_name = server_pod_name
+    self.server_port = server_port
+
+
+class StressClientSettings:
+
+  def __init__(self, num_clients, client_pod_name_prefix, server_pod_name,
+               server_port, metrics_port, metrics_collection_interval_secs,
+               stress_client_poll_interval_secs, num_channels_per_server,
+               num_stubs_per_channel, test_cases_str):
+    self.num_clients = num_clients
+    self.client_pod_name_prefix = client_pod_name_prefix
+    self.server_pod_name = server_pod_name
+    self.server_port = server_port
+    self.metrics_port = metrics_port
+    self.metrics_collection_interval_secs = metrics_collection_interval_secs
+    self.stress_client_poll_interval_secs = stress_client_poll_interval_secs
+    self.num_channels_per_server = num_channels_per_server
+    self.num_stubs_per_channel = num_stubs_per_channel
+    self.test_cases_str = test_cases_str
+
+    # == Derived properties ==
+    # Note: Client can accept a list of server addresses (a comma separated list
+    # of 'server_name:server_port'). In this case, we only have one server
+    # address to pass
+    self.server_addresses = '%s.default.svc.cluster.local:%d' % (
+        server_pod_name, server_port)
+    self.client_pod_names_list = ['%s-%d' % (client_pod_name_prefix, i)
+                                  for i in range(1, num_clients + 1)]
+
+
+def _build_docker_image(image_name, tag_name):
+  """ Build the docker image and add tag it to the GKE repository """
+  print 'Building docker image: %s' % image_name
+  os.environ['INTEROP_IMAGE'] = image_name
+  os.environ['INTEROP_IMAGE_REPOSITORY_TAG'] = tag_name
+  # Note that 'BASE_NAME' HAS to be 'grpc_interop_stress_cxx' since the script
+  # build_interop_stress_image.sh invokes the following script:
+  #   tools/dockerfile/$BASE_NAME/build_interop_stress.sh
+  os.environ['BASE_NAME'] = 'grpc_interop_stress_cxx'
+  cmd = ['tools/jenkins/build_interop_stress_image.sh']
+  retcode = subprocess.call(args=cmd)
+  if retcode != 0:
+    print 'Error in building docker image'
+    return False
+  return True
+
+
+def _push_docker_image_to_gke_registry(docker_tag_name):
+  """Executes 'gcloud docker push <docker_tag_name>' to push the image to GKE registry"""
+  cmd = ['gcloud', 'docker', 'push', docker_tag_name]
+  print 'Pushing %s to GKE registry..' % docker_tag_name
+  retcode = subprocess.call(args=cmd)
+  if retcode != 0:
+    print 'Error in pushing docker image %s to the GKE registry' % docker_tag_name
+    return False
+  return True
+
+
+def _launch_server(gke_settings, stress_server_settings, bq_settings,
+                   kubernetes_proxy):
+  """ Launches a stress test server instance in GKE cluster """
+  if not kubernetes_proxy.is_started:
+    print 'Kubernetes proxy must be started before calling this function'
+    return False
+
+  # This is the wrapper script that is run in the container. This script runs
+  # the actual stress test server
+  server_cmd_list = ['/var/local/git/grpc/tools/gcp/stress_test/run_server.py']
+
+  # run_server.py does not take any args from the command line. The args are
+  # instead passed via environment variables (see server_env below)
+  server_arg_list = []
+
+  # The parameters to the script run_server.py are injected into the container
+  # via environment variables
+  server_env = {
+      'STRESS_TEST_IMAGE_TYPE': 'SERVER',
+      'STRESS_TEST_IMAGE': '/var/local/git/grpc/bins/opt/interop_server',
+      'STRESS_TEST_ARGS_STR': '--port=%s' % stress_server_settings.server_port,
+      'RUN_ID': bq_settings.run_id,
+      'POD_NAME': stress_server_settings.server_pod_name,
+      'GCP_PROJECT_ID': gke_settings.project_id,
+      'DATASET_ID': bq_settings.dataset_id,
+      'SUMMARY_TABLE_ID': bq_settings.summary_table_id,
+      'QPS_TABLE_ID': bq_settings.qps_table_id
+  }
+
+  # Launch Server
+  is_success = kubernetes_api.create_pod_and_service(
+      'localhost',
+      kubernetes_proxy.get_port(),
+      'default',  # Use 'default' namespace
+      stress_server_settings.server_pod_name,
+      gke_settings.tag_name,
+      [stress_server_settings.server_port],  # Port that should be exposed
+      server_cmd_list,
+      server_arg_list,
+      server_env,
+      True  # Headless = True for server. Since we want DNS records to be created by GKE
+  )
+
+  return is_success
+
+
+def _launch_client(gke_settings, stress_server_settings, stress_client_settings,
+                   bq_settings, kubernetes_proxy):
+  """ Launches a configurable number of stress test clients on GKE cluster """
+  if not kubernetes_proxy.is_started:
+    print 'Kubernetes proxy must be started before calling this function'
+    return False
+
+  stress_client_arg_list = [
+      '--server_addresses=%s' % stress_client_settings.server_addresses,
+      '--test_cases=%s' % stress_client_settings.test_cases_str,
+      '--num_stubs_per_channel=%d' %
+      stress_client_settings.num_stubs_per_channel
+  ]
+
+  # This is the wrapper script that is run in the container. This script runs
+  # the actual stress client
+  client_cmd_list = ['/var/local/git/grpc/tools/gcp/stress_test/run_client.py']
+
+  # run_client.py takes no args. All args are passed as env variables (see
+  # client_env)
+  client_arg_list = []
+
+  metrics_server_address = 'localhost:%d' % stress_client_settings.metrics_port
+  metrics_client_arg_list = [
+      '--metrics_server_address=%s' % metrics_server_address,
+      '--total_only=true'
+  ]
+
+  # The parameters to the script run_client.py are injected into the container
+  # via environment variables
+  client_env = {
+      'STRESS_TEST_IMAGE_TYPE': 'CLIENT',
+      'STRESS_TEST_IMAGE': '/var/local/git/grpc/bins/opt/stress_test',
+      'STRESS_TEST_ARGS_STR': ' '.join(stress_client_arg_list),
+      'METRICS_CLIENT_IMAGE': '/var/local/git/grpc/bins/opt/metrics_client',
+      'METRICS_CLIENT_ARGS_STR': ' '.join(metrics_client_arg_list),
+      'RUN_ID': bq_settings.run_id,
+      'POLL_INTERVAL_SECS':
+          str(stress_client_settings.stress_client_poll_interval_secs),
+      'GCP_PROJECT_ID': gke_settings.project_id,
+      'DATASET_ID': bq_settings.dataset_id,
+      'SUMMARY_TABLE_ID': bq_settings.summary_table_id,
+      'QPS_TABLE_ID': bq_settings.qps_table_id
+  }
+
+  for pod_name in stress_client_settings.client_pod_names_list:
+    client_env['POD_NAME'] = pod_name
+    is_success = kubernetes_api.create_pod_and_service(
+        'localhost',  # Since proxy is running on localhost
+        kubernetes_proxy.get_port(),
+        'default',  # default namespace
+        pod_name,
+        gke_settings.tag_name,
+        [stress_client_settings.metrics_port
+        ],  # Client pods expose metrics port
+        client_cmd_list,
+        client_arg_list,
+        client_env,
+        False  # Client is not a headless service
+    )
+    if not is_success:
+      print 'Error in launching client %s' % pod_name
+      return False
+
+  return True
+
+
+def _launch_server_and_client(gke_settings, stress_server_settings,
+                              stress_client_settings, bq_settings,
+                              kubernetes_proxy_port):
+  # Start kubernetes proxy
+  print 'Kubernetes proxy'
+  kubernetes_proxy = KubernetesProxy(kubernetes_proxy_port)
+  kubernetes_proxy.start()
+
+  print 'Launching server..'
+  is_success = _launch_server(gke_settings, stress_server_settings, bq_settings,
+                              kubernetes_proxy)
+  if not is_success:
+    print 'Error in launching server'
+    return False
+
+  # Server takes a while to start.
+  # TODO(sree) Use Kubernetes API to query the status of the server instead of
+  # sleeping
+  print 'Waiting for %s seconds for the server to start...' % _GKE_IMAGE_WARMUP_WAIT_SECS
+  time.sleep(_GKE_IMAGE_WARMUP_WAIT_SECS)
+
+  # Launch client
+  client_pod_name_prefix = 'stress-client'
+  is_success = _launch_client(gke_settings, stress_server_settings,
+                              stress_client_settings, bq_settings,
+                              kubernetes_proxy)
+
+  if not is_success:
+    print 'Error in launching client(s)'
+    return False
+
+  print 'Waiting for %s seconds for the client images to start...' % _GKE_IMAGE_WARMUP_WAIT_SECS
+  time.sleep(_GKE_IMAGE_WARMUP_WAIT_SECS)
+  return True
+
+
+def _delete_server_and_client(stress_server_settings, stress_client_settings,
+                              kubernetes_proxy_port):
+  kubernetes_proxy = KubernetesProxy(kubernetes_proxy_port)
+  kubernetes_proxy.start()
+
+  # Delete clients first
+  is_success = True
+  for pod_name in stress_client_settings.client_pod_names_list:
+    is_success = kubernetes_api.delete_pod_and_service(
+        'localhost', kubernetes_proxy_port, 'default', pod_name)
+    if not is_success:
+      return False
+
+  # Delete server
+  is_success = kubernetes_api.delete_pod_and_service(
+      'localhost', kubernetes_proxy_port, 'default',
+      stress_server_settings.server_pod_name)
+  return is_success
+
+
+def run_test_main(test_settings, gke_settings, stress_server_settings,
+                  stress_client_clients):
+  is_success = True
+
+  if test_settings.build_docker_image:
+    is_success = _build_docker_image(gke_settings.docker_image_name,
+                                     gke_settings.tag_name)
+    if not is_success:
+      return False
+
+    is_success = _push_docker_image_to_gke_registry(gke_settings.tag_name)
+    if not is_success:
+      return False
+
+  # Create a unique id for this run (Note: Using timestamp instead of UUID to
+  # make it easier to deduce the date/time of the run just by looking at the run
+  # run id. This is useful in debugging when looking at records in Biq query)
+  run_id = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S')
+  dataset_id = '%s_%s' % (_DATASET_ID_PREFIX, run_id)
+
+  # Big Query settings (common for both Stress Server and Client)
+  bq_settings = BigQuerySettings(run_id, dataset_id, _SUMMARY_TABLE_ID,
+                                 _QPS_TABLE_ID)
+
+  bq_helper = BigQueryHelper(run_id, '', '', args.project_id, dataset_id,
+                             _SUMMARY_TABLE_ID, _QPS_TABLE_ID)
+  bq_helper.initialize()
+
+  try:
+    is_success = _launch_server_and_client(gke_settings, stress_server_settings,
+                                           stress_client_settings, bq_settings,
+                                           test_settings.kubernetes_proxy_port)
+    if not is_success:
+      return False
+
+    start_time = datetime.datetime.now()
+    end_time = start_time + datetime.timedelta(
+        seconds=test_settings.test_duration_secs)
+    print 'Running the test until %s' % end_time.isoformat()
+
+    while True:
+      if datetime.datetime.now() > end_time:
+        print 'Test was run for %d seconds' % test_settings.test_duration_secs
+        break
+
+      # Check if either stress server or clients have failed
+      if bq_helper.check_if_any_tests_failed():
+        is_success = False
+        print 'Some tests failed.'
+        break
+
+      # Things seem to be running fine. Wait until next poll time to check the
+      # status
+      print 'Sleeping for %d seconds..' % test_settings.test_poll_interval_secs
+      time.sleep(test_settings.test_poll_interval_secs)
+
+    # Print BiqQuery tables
+    bq_helper.print_summary_records()
+    bq_helper.print_qps_records()
+
+  finally:
+    # If is_success is False at this point, it means that the stress tests were
+    # started successfully but failed while running the tests. In this case we
+    # do should not delete the pods (since they contain all the failure
+    # information)
+    if is_success:
+      _delete_server_and_client(stress_server_settings, stress_client_settings,
+                                test_settings.kubernetes_proxy_port)
+
+  return is_success
+
+
+argp = argparse.ArgumentParser(
+    description='Launch stress tests in GKE',
+    formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+argp.add_argument('--project_id',
+                  required=True,
+                  help='The Google Cloud Platform Project Id')
+argp.add_argument('--num_clients',
+                  default=1,
+                  type=int,
+                  help='Number of client instances to start')
+argp.add_argument('--docker_image_name',
+                  default=_DEFAULT_DOCKER_IMAGE_NAME,
+                  help='The name of the docker image containing stress client '
+                  'and stress servers')
+argp.add_argument('--build_docker_image',
+                  dest='build_docker_image',
+                  action='store_true',
+                  help='Build a docker image and push to Google Container '
+                  'Registry')
+argp.add_argument('--do_not_build_docker_image',
+                  dest='build_docker_image',
+                  action='store_false',
+                  help='Do not build and push docker image to Google Container '
+                  'Registry')
+argp.set_defaults(build_docker_image=True)
+
+argp.add_argument('--test_poll_interval_secs',
+                  default=_DEFAULT_TEST_POLL_INTERVAL_SECS,
+                  type=int,
+                  help='How frequently should this script should monitor the '
+                  'health of stress clients and servers running in the GKE '
+                  'cluster')
+argp.add_argument('--test_duration_secs',
+                  default=_DEFAULT_TEST_DURATION_SECS,
+                  type=int,
+                  help='How long should this test be run')
+argp.add_argument('--kubernetes_proxy_port',
+                  default=_DEFAULT_KUBERNETES_PROXY_PORT,
+                  type=int,
+                  help='The port on which the kubernetes proxy (on localhost)'
+                  ' is started')
+argp.add_argument('--stress_server_port',
+                  default=_DEFAULT_STRESS_SERVER_PORT,
+                  type=int,
+                  help='The port on which the stress server (in GKE '
+                  'containers) listens')
+argp.add_argument('--stress_client_metrics_port',
+                  default=_DEFAULT_METRICS_PORT,
+                  type=int,
+                  help='The port on which the stress clients (in GKE '
+                  'containers) expose metrics')
+argp.add_argument('--stress_client_poll_interval_secs',
+                  default=_DEFAULT_STRESS_CLIENT_POLL_INTERVAL_SECS,
+                  type=int,
+                  help='How frequently should the stress client wrapper script'
+                  ' running inside GKE should monitor health of the actual '
+                  ' stress client process and upload the metrics to BigQuery')
+argp.add_argument('--stress_client_metrics_collection_interval_secs',
+                  default=_DEFAULT_METRICS_COLLECTION_INTERVAL_SECS,
+                  type=int,
+                  help='How frequently should metrics be collected in-memory on'
+                  ' the stress clients (running inside GKE containers). Note '
+                  'that this is NOT the same as the upload-to-BigQuery '
+                  'frequency. The metrics upload frequency is controlled by the'
+                  ' --stress_client_poll_interval_secs flag')
+argp.add_argument('--stress_client_num_channels_per_server',
+                  default=_DEFAULT_NUM_CHANNELS_PER_SERVER,
+                  type=int,
+                  help='The number of channels created to each server from a '
+                  'stress client')
+argp.add_argument('--stress_client_num_stubs_per_channel',
+                  default=_DEFAULT_NUM_STUBS_PER_CHANNEL,
+                  type=int,
+                  help='The number of stubs created per channel. This number '
+                  'indicates the max number of RPCs that can be made in '
+                  'parallel on each channel at any given time')
+argp.add_argument('--stress_client_test_cases',
+                  default=_DEFAULT_TEST_CASES_STR,
+                  help='List of test cases (with weights) to be executed by the'
+                  ' stress test client. The list is in the following format:\n'
+                  '  <testcase_1:w_1,<test_case2:w_2>..<testcase_n:w_n>\n'
+                  ' (Note: The weights do not have to add up to 100)')
+
+if __name__ == '__main__':
+  args = argp.parse_args()
+
+  test_settings = TestSettings(
+      args.build_docker_image, args.test_poll_interval_secs,
+      args.test_duration_secs, args.kubernetes_proxy_port)
+
+  gke_settings = GkeSettings(args.project_id, args.docker_image_name)
+
+  stress_server_settings = StressServerSettings(_SERVER_POD_NAME,
+                                                args.stress_server_port)
+  stress_client_settings = StressClientSettings(
+      args.num_clients, _CLIENT_POD_NAME_PREFIX, _SERVER_POD_NAME,
+      args.stress_server_port, args.stress_client_metrics_port,
+      args.stress_client_metrics_collection_interval_secs,
+      args.stress_client_poll_interval_secs,
+      args.stress_client_num_channels_per_server,
+      args.stress_client_num_stubs_per_channel, args.stress_client_test_cases)
+
+  run_test_main(test_settings, gke_settings, stress_server_settings,
+                stress_client_settings)
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index ea9c129101db84b9f5b5adcef61a455172025f1c..d91245cd06ae73b3baa319cc92cb61b4337e852d 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -12,6 +12,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "alarm_test", 
     "platforms": [
@@ -32,6 +33,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "algorithm_test", 
     "platforms": [
@@ -52,6 +54,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "alloc_test", 
     "platforms": [
@@ -72,6 +75,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "alpn_test", 
     "platforms": [
@@ -92,6 +96,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "bin_encoder_test", 
     "platforms": [
@@ -112,6 +117,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "census_context_test", 
     "platforms": [
@@ -132,26 +138,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
-    "language": "c", 
-    "name": "census_log_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ]
-  }, 
-  {
-    "args": [], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "channel_create_test", 
     "platforms": [
@@ -172,6 +159,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "chttp2_hpack_encoder_test", 
     "platforms": [
@@ -192,6 +180,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "chttp2_status_conversion_test", 
     "platforms": [
@@ -212,6 +201,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "chttp2_stream_map_test", 
     "platforms": [
@@ -232,6 +222,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "chttp2_varint_test", 
     "platforms": [
@@ -252,6 +243,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "compression_test", 
     "platforms": [
@@ -272,6 +264,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "dns_resolver_test", 
     "platforms": [
@@ -291,6 +284,7 @@
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "dualstack_socket_test", 
     "platforms": [
@@ -310,6 +304,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "endpoint_pair_test", 
     "platforms": [
@@ -329,6 +324,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "fd_conservation_posix_test", 
     "platforms": [
@@ -347,6 +343,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "fd_posix_test", 
     "platforms": [
@@ -365,6 +362,7 @@
     "cpu_cost": 2, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "fling_stream_test", 
     "platforms": [
@@ -383,6 +381,7 @@
     "cpu_cost": 2, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "fling_test", 
     "platforms": [
@@ -402,6 +401,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_avl_test", 
     "platforms": [
@@ -422,6 +422,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_cmdline_test", 
     "platforms": [
@@ -442,6 +443,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_cpu_test", 
     "platforms": [
@@ -462,6 +464,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_env_test", 
     "platforms": [
@@ -482,8 +485,9 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
-    "name": "gpr_file_test", 
+    "name": "gpr_histogram_test", 
     "platforms": [
       "linux", 
       "mac", 
@@ -502,8 +506,9 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
-    "name": "gpr_histogram_test", 
+    "name": "gpr_host_port_test", 
     "platforms": [
       "linux", 
       "mac", 
@@ -522,8 +527,9 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
-    "name": "gpr_host_port_test", 
+    "name": "gpr_load_file_test", 
     "platforms": [
       "linux", 
       "mac", 
@@ -542,6 +548,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_log_test", 
     "platforms": [
@@ -562,6 +569,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_slice_buffer_test", 
     "platforms": [
@@ -582,6 +590,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_slice_test", 
     "platforms": [
@@ -602,6 +611,7 @@
     "cpu_cost": 10, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_stack_lockfree_test", 
     "platforms": [
@@ -622,6 +632,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_string_test", 
     "platforms": [
@@ -642,6 +653,7 @@
     "cpu_cost": 10, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_sync_test", 
     "platforms": [
@@ -662,6 +674,7 @@
     "cpu_cost": 10, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_thd_test", 
     "platforms": [
@@ -682,6 +695,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_time_test", 
     "platforms": [
@@ -702,6 +716,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_tls_test", 
     "platforms": [
@@ -722,6 +737,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "gpr_useful_test", 
     "platforms": [
@@ -742,6 +758,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "grpc_auth_context_test", 
     "platforms": [
@@ -762,8 +779,9 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
-    "name": "grpc_base64_test", 
+    "name": "grpc_b64_test", 
     "platforms": [
       "linux", 
       "mac", 
@@ -782,6 +800,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "grpc_byte_buffer_reader_test", 
     "platforms": [
@@ -802,6 +821,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "grpc_channel_args_test", 
     "platforms": [
@@ -822,6 +842,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "grpc_channel_stack_test", 
     "platforms": [
@@ -842,6 +863,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "grpc_completion_queue_test", 
     "platforms": [
@@ -862,6 +884,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "grpc_credentials_test", 
     "platforms": [
@@ -882,6 +905,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "grpc_invalid_channel_args_test", 
     "platforms": [
@@ -901,6 +925,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "grpc_json_token_test", 
     "platforms": [
@@ -920,6 +945,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "grpc_jwt_verifier_test", 
     "platforms": [
@@ -940,6 +966,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "grpc_security_connector_test", 
     "platforms": [
@@ -960,6 +987,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "hpack_parser_test", 
     "platforms": [
@@ -980,6 +1008,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "hpack_table_test", 
     "platforms": [
@@ -1000,6 +1029,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "httpcli_format_request_test", 
     "platforms": [
@@ -1020,6 +1050,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "httpcli_parser_test", 
     "platforms": [
@@ -1039,6 +1070,7 @@
     "cpu_cost": 0.5, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "httpcli_test", 
     "platforms": [
@@ -1055,6 +1087,7 @@
     "cpu_cost": 0.5, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "httpscli_test", 
     "platforms": [
@@ -1072,6 +1105,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "init_test", 
     "platforms": [
@@ -1092,6 +1126,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "invalid_call_argument_test", 
     "platforms": [
@@ -1112,6 +1147,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "json_rewrite_test", 
     "platforms": [
@@ -1132,6 +1168,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "json_stream_error_test", 
     "platforms": [
@@ -1152,6 +1189,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "json_test", 
     "platforms": [
@@ -1172,6 +1210,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "lame_client_test", 
     "platforms": [
@@ -1192,6 +1231,7 @@
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "lb_policies_test", 
     "platforms": [
@@ -1212,6 +1252,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "message_compress_test", 
     "platforms": [
@@ -1232,6 +1273,28 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
+    "name": "mlog_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "multiple_server_queues_test", 
     "platforms": [
@@ -1252,6 +1315,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "murmur_hash_test", 
     "platforms": [
@@ -1272,6 +1336,7 @@
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "no_server_test", 
     "platforms": [
@@ -1292,6 +1357,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "resolve_address_test", 
     "platforms": [
@@ -1312,6 +1378,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "secure_channel_create_test", 
     "platforms": [
@@ -1332,6 +1399,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "secure_endpoint_test", 
     "platforms": [
@@ -1352,6 +1420,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "server_chttp2_test", 
     "platforms": [
@@ -1372,6 +1441,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "server_test", 
     "platforms": [
@@ -1392,6 +1462,7 @@
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "set_initial_connect_string_test", 
     "platforms": [
@@ -1412,6 +1483,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "sockaddr_resolver_test", 
     "platforms": [
@@ -1432,6 +1504,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "sockaddr_utils_test", 
     "platforms": [
@@ -1451,6 +1524,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "socket_utils_test", 
     "platforms": [
@@ -1469,6 +1543,7 @@
     "cpu_cost": 0.5, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "tcp_client_posix_test", 
     "platforms": [
@@ -1487,6 +1562,7 @@
     "cpu_cost": 0.5, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "tcp_posix_test", 
     "platforms": [
@@ -1505,6 +1581,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "tcp_server_posix_test", 
     "platforms": [
@@ -1524,6 +1601,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "time_averaged_stats_test", 
     "platforms": [
@@ -1544,6 +1622,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "timeout_encoding_test", 
     "platforms": [
@@ -1564,6 +1643,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "timer_heap_test", 
     "platforms": [
@@ -1584,6 +1664,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "timer_list_test", 
     "platforms": [
@@ -1604,6 +1685,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "timers_test", 
     "platforms": [
@@ -1624,6 +1706,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "transport_connectivity_state_test", 
     "platforms": [
@@ -1644,6 +1727,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "transport_metadata_test", 
     "platforms": [
@@ -1663,6 +1747,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "transport_security_test", 
     "platforms": [
@@ -1681,6 +1766,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "udp_server_test", 
     "platforms": [
@@ -1700,6 +1786,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "uri_parser_test", 
     "platforms": [
@@ -1719,6 +1806,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "workqueue_test", 
     "platforms": [
@@ -1738,6 +1826,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "alarm_cpp_test", 
     "platforms": [
@@ -1758,6 +1847,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "async_end2end_test", 
     "platforms": [
@@ -1777,6 +1867,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c++", 
     "name": "async_streaming_ping_pong_test", 
     "platforms": [
@@ -1795,6 +1886,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c++", 
     "name": "async_unary_ping_pong_test", 
     "platforms": [
@@ -1814,6 +1906,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "auth_property_iterator_test", 
     "platforms": [
@@ -1834,6 +1927,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "channel_arguments_test", 
     "platforms": [
@@ -1854,6 +1948,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "cli_call_test", 
     "platforms": [
@@ -1873,6 +1968,7 @@
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "client_crash_test", 
     "platforms": [
@@ -1892,6 +1988,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "credentials_test", 
     "platforms": [
@@ -1912,6 +2009,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "cxx_byte_buffer_test", 
     "platforms": [
@@ -1932,6 +2030,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "cxx_slice_test", 
     "platforms": [
@@ -1952,6 +2051,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "cxx_string_ref_test", 
     "platforms": [
@@ -1972,6 +2072,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "cxx_time_test", 
     "platforms": [
@@ -1992,6 +2093,7 @@
     "cpu_cost": 0.5, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "end2end_test", 
     "platforms": [
@@ -2011,6 +2113,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c++", 
     "name": "generic_async_streaming_ping_pong_test", 
     "platforms": [
@@ -2030,6 +2133,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "generic_end2end_test", 
     "platforms": [
@@ -2050,6 +2154,28 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
+    "name": "grpclb_api_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "hybrid_end2end_test", 
     "platforms": [
@@ -2069,6 +2195,7 @@
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c++", 
     "name": "interop_test", 
     "platforms": [
@@ -2088,6 +2215,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "mock_test", 
     "platforms": [
@@ -2104,9 +2232,10 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 10, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c++", 
     "name": "qps_openloop_test", 
     "platforms": [
@@ -2123,10 +2252,9 @@
       "posix"
     ], 
     "cpu_cost": 10, 
-    "exclude_configs": [
-      "tsan"
-    ], 
+    "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c++", 
     "name": "qps_test", 
     "platforms": [
@@ -2146,6 +2274,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "secure_auth_context_test", 
     "platforms": [
@@ -2165,6 +2294,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c++", 
     "name": "secure_sync_unary_ping_pong_test", 
     "platforms": [
@@ -2183,6 +2313,7 @@
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "server_crash_test", 
     "platforms": [
@@ -2202,6 +2333,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "shutdown_test", 
     "platforms": [
@@ -2222,6 +2354,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c++", 
     "name": "status_test", 
     "platforms": [
@@ -2241,6 +2374,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "streaming_throughput_test", 
     "platforms": [
@@ -2259,6 +2393,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c++", 
     "name": "sync_streaming_ping_pong_test", 
     "platforms": [
@@ -2277,6 +2412,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c++", 
     "name": "sync_unary_ping_pong_test", 
     "platforms": [
@@ -2296,6 +2432,7 @@
     "cpu_cost": 100, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": true, 
     "language": "c++", 
     "name": "thread_stress_test", 
     "platforms": [
@@ -2316,6 +2453,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c89", 
     "name": "public_headers_must_be_c89", 
     "platforms": [
@@ -2336,6 +2474,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "badreq_bad_client_test", 
     "platforms": [
@@ -2356,6 +2495,7 @@
     "cpu_cost": 0.2, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "connection_prefix_bad_client_test", 
     "platforms": [
@@ -2376,6 +2516,7 @@
     "cpu_cost": 0.2, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "headers_bad_client_test", 
     "platforms": [
@@ -2396,6 +2537,7 @@
     "cpu_cost": 0.2, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "initial_settings_frame_bad_client_test", 
     "platforms": [
@@ -2416,6 +2558,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "server_registered_method_bad_client_test", 
     "platforms": [
@@ -2436,6 +2579,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "simple_request_bad_client_test", 
     "platforms": [
@@ -2456,6 +2600,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "unknown_frame_bad_client_test", 
     "platforms": [
@@ -2476,6 +2621,7 @@
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "window_overflow_bad_client_test", 
     "platforms": [
@@ -2495,6 +2641,7 @@
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "bad_ssl_alpn_test", 
     "platforms": [
@@ -2513,6 +2660,7 @@
     "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
+    "gtest": false, 
     "language": "c", 
     "name": "bad_ssl_cert_test", 
     "platforms": [
@@ -4219,7 +4367,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4241,29 +4389,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_census_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4505,7 +4631,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4527,7 +4653,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4549,7 +4675,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4557,7 +4683,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -4571,7 +4697,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4579,7 +4705,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -4769,7 +4895,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4791,7 +4917,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4813,7 +4939,7 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4825,7 +4951,7 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_compress_test", 
+    "name": "h2_census_test", 
     "platforms": [
       "windows", 
       "linux", 
@@ -4835,7 +4961,7 @@
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4857,7 +4983,7 @@
   }, 
   {
     "args": [
-      "call_creds"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4879,7 +5005,7 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "call_creds"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4887,7 +5013,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -4901,7 +5027,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4923,7 +5049,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4945,7 +5071,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4967,7 +5093,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -4989,7 +5115,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5011,7 +5137,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5033,7 +5159,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5041,7 +5167,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -5055,7 +5181,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5297,7 +5423,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5319,7 +5445,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5341,7 +5467,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5349,7 +5475,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -5363,7 +5489,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5371,7 +5497,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -5561,7 +5687,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5583,7 +5709,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5605,18 +5731,19 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
+      "mac", 
       "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_fakesec_test", 
+    "name": "h2_compress_test", 
     "platforms": [
       "windows", 
       "linux", 
@@ -5626,7 +5753,7 @@
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5647,7 +5774,7 @@
   }, 
   {
     "args": [
-      "call_creds"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5668,14 +5795,14 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "call_creds"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -5689,7 +5816,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5710,7 +5837,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5731,7 +5858,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5752,7 +5879,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5773,7 +5900,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5794,7 +5921,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "windows", 
@@ -5815,14 +5942,14 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -5836,7 +5963,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6067,7 +6194,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6088,7 +6215,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6109,14 +6236,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -6130,14 +6257,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -6319,7 +6446,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6340,7 +6467,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6361,19 +6488,18 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
-      "mac", 
       "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_full_test", 
+    "name": "h2_fakesec_test", 
     "platforms": [
       "windows", 
       "linux", 
@@ -6383,7 +6509,7 @@
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6405,7 +6531,7 @@
   }, 
   {
     "args": [
-      "call_creds"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6427,7 +6553,7 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "call_creds"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6435,7 +6561,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -6449,7 +6575,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6471,7 +6597,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6493,7 +6619,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6515,7 +6641,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6537,7 +6663,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6559,7 +6685,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6581,7 +6707,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6589,7 +6715,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -6603,7 +6729,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6845,7 +6971,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6867,7 +6993,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6889,7 +7015,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6897,7 +7023,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -6911,7 +7037,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "windows", 
@@ -6919,7 +7045,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -7107,6 +7233,28 @@
       "posix"
     ]
   }, 
+  {
+    "args": [
+      "simple_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
   {
     "args": [
       "simple_request"
@@ -7297,7 +7445,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux"
@@ -7313,12 +7461,12 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -7329,12 +7477,12 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "default_host"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -7345,7 +7493,7 @@
   }, 
   {
     "args": [
-      "default_host"
+      "disappearing_server"
     ], 
     "ci_platforms": [
       "linux"
@@ -7361,7 +7509,7 @@
   }, 
   {
     "args": [
-      "disappearing_server"
+      "empty_batch"
     ], 
     "ci_platforms": [
       "linux"
@@ -7377,23 +7525,7 @@
   }, 
   {
     "args": [
-      "empty_batch"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_full+pipe_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "graceful_server_shutdown"
+      "graceful_server_shutdown"
     ], 
     "ci_platforms": [
       "linux"
@@ -7505,7 +7637,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux"
@@ -7521,7 +7653,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux"
@@ -7537,12 +7669,12 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -7553,12 +7685,12 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -7697,7 +7829,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -7713,7 +7845,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "linux"
@@ -7729,7 +7861,7 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -7738,14 +7870,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_full+poll_test", 
+    "name": "h2_full+pipe_test", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "linux"
@@ -7761,7 +7893,7 @@
   }, 
   {
     "args": [
-      "call_creds"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -7777,12 +7909,12 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "call_creds"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -7793,7 +7925,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "linux"
@@ -7809,7 +7941,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "linux"
@@ -7825,7 +7957,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -7841,7 +7973,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -7857,7 +7989,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "linux"
@@ -7873,7 +8005,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "linux"
@@ -7889,12 +8021,12 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -7905,7 +8037,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux"
@@ -8081,7 +8213,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux"
@@ -8097,7 +8229,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux"
@@ -8113,12 +8245,12 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -8129,12 +8261,12 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -8273,7 +8405,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -8289,7 +8421,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "linux"
@@ -8305,7 +8437,7 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -8314,14 +8446,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_full+poll+pipe_test", 
+    "name": "h2_full+poll_test", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "linux"
@@ -8337,7 +8469,7 @@
   }, 
   {
     "args": [
-      "call_creds"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -8353,12 +8485,12 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "call_creds"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -8369,7 +8501,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "linux"
@@ -8385,7 +8517,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "linux"
@@ -8401,7 +8533,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -8417,7 +8549,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -8433,7 +8565,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "linux"
@@ -8449,7 +8581,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "linux"
@@ -8465,12 +8597,12 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -8481,7 +8613,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux"
@@ -8657,7 +8789,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux"
@@ -8673,7 +8805,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux"
@@ -8689,12 +8821,12 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -8705,12 +8837,12 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -8847,6 +8979,22 @@
       "linux"
     ]
   }, 
+  {
+    "args": [
+      "simple_metadata"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+poll+pipe_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
   {
     "args": [
       "simple_request"
@@ -9070,7 +9218,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -9091,28 +9239,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_oauth2_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "windows", 
@@ -9343,7 +9470,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -9364,7 +9491,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -9385,14 +9512,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -9406,14 +9533,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -9593,6 +9720,27 @@
       "posix"
     ]
   }, 
+  {
+    "args": [
+      "simple_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_oauth2_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
   {
     "args": [
       "simple_request"
@@ -9994,7 +10142,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10015,7 +10163,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10036,14 +10184,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -10057,14 +10205,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -10078,7 +10226,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10099,7 +10247,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10120,7 +10268,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10141,7 +10289,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10162,7 +10310,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10183,14 +10331,14 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_delayed_request"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -10204,14 +10352,14 @@
   }, 
   {
     "args": [
-      "simple_delayed_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -10645,7 +10793,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10666,7 +10814,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10687,14 +10835,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -10708,14 +10856,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -10729,7 +10877,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10750,7 +10898,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_flags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10771,7 +10919,7 @@
   }, 
   {
     "args": [
-      "request_with_flags"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10792,7 +10940,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10813,7 +10961,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10834,7 +10982,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -10855,7 +11003,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11292,7 +11440,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11314,7 +11462,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11336,7 +11484,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11344,7 +11492,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -11358,7 +11506,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11366,7 +11514,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -11380,7 +11528,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11402,7 +11550,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_flags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11424,7 +11572,7 @@
   }, 
   {
     "args": [
-      "request_with_flags"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11446,7 +11594,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11468,7 +11616,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11490,7 +11638,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11512,7 +11660,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11956,7 +12104,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11977,7 +12125,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -11998,14 +12146,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -12019,14 +12167,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -12040,7 +12188,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12061,7 +12209,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_flags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12082,7 +12230,7 @@
   }, 
   {
     "args": [
-      "request_with_flags"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12103,7 +12251,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12124,7 +12272,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12145,7 +12293,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12166,7 +12314,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12427,7 +12575,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12449,29 +12597,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
-    ], 
-    "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl_test", 
-    "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12713,7 +12839,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12735,7 +12861,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12757,7 +12883,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12765,7 +12891,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -12779,7 +12905,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "windows", 
@@ -12787,7 +12913,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -12975,6 +13101,28 @@
       "posix"
     ]
   }, 
+  {
+    "args": [
+      "simple_metadata"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
   {
     "args": [
       "simple_request"
@@ -13165,7 +13313,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux"
@@ -13181,23 +13329,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_ssl+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux"
@@ -13373,7 +13505,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux"
@@ -13389,7 +13521,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux"
@@ -13405,12 +13537,12 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -13421,12 +13553,12 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -13563,6 +13695,22 @@
       "linux"
     ]
   }, 
+  {
+    "args": [
+      "simple_metadata"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl+poll_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
   {
     "args": [
       "simple_request"
@@ -13954,7 +14102,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -13975,7 +14123,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -13996,14 +14144,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -14017,14 +14165,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -14038,7 +14186,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14059,7 +14207,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14080,7 +14228,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14101,7 +14249,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14122,7 +14270,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14143,14 +14291,14 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_delayed_request"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -14164,14 +14312,14 @@
   }, 
   {
     "args": [
-      "simple_delayed_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -14623,7 +14771,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14645,7 +14793,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14667,7 +14815,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14675,7 +14823,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -14689,7 +14837,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14697,7 +14845,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -14711,7 +14859,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14733,7 +14881,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_flags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14755,7 +14903,7 @@
   }, 
   {
     "args": [
-      "request_with_flags"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14777,7 +14925,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14799,7 +14947,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14821,7 +14969,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -14843,7 +14991,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -15089,7 +15237,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux", 
@@ -15109,27 +15257,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
-    ], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux", 
@@ -15329,7 +15457,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux", 
@@ -15349,7 +15477,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux", 
@@ -15369,14 +15497,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux", 
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -15389,14 +15517,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux", 
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -15567,6 +15695,26 @@
       "posix"
     ]
   }, 
+  {
+    "args": [
+      "simple_metadata"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
   {
     "args": [
       "simple_request"
@@ -15753,7 +15901,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux"
@@ -15769,23 +15917,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
-    ], 
-    "ci_platforms": [
-      "linux"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds+poll_test", 
-    "platforms": [
-      "linux"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux"
@@ -15945,7 +16077,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux"
@@ -15961,7 +16093,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux"
@@ -15977,12 +16109,12 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -15993,12 +16125,12 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -16137,7 +16269,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -16153,7 +16285,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "linux"
@@ -16169,29 +16301,23 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
+      "linux"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_census_nosec_test", 
+    "name": "h2_uds+poll_test", 
     "platforms": [
-      "windows", 
-      "linux", 
-      "mac", 
-      "posix"
+      "linux"
     ]
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16213,7 +16339,7 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16221,7 +16347,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -16235,7 +16361,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16257,7 +16383,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16279,7 +16405,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16301,7 +16427,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16323,7 +16449,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16345,7 +16471,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16367,7 +16493,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16375,7 +16501,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -16389,7 +16515,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16631,7 +16757,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16653,7 +16779,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16675,7 +16801,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16683,7 +16809,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -16697,7 +16823,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16705,7 +16831,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -16895,7 +17021,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16917,7 +17043,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16939,7 +17065,7 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16951,7 +17077,7 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_compress_nosec_test", 
+    "name": "h2_census_nosec_test", 
     "platforms": [
       "windows", 
       "linux", 
@@ -16961,7 +17087,7 @@
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16983,7 +17109,7 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -16991,7 +17117,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -17005,7 +17131,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17027,7 +17153,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17049,7 +17175,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17071,7 +17197,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17093,7 +17219,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17115,7 +17241,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17137,7 +17263,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17145,7 +17271,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -17159,7 +17285,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17401,7 +17527,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17423,7 +17549,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17445,7 +17571,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17453,7 +17579,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -17467,7 +17593,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17475,7 +17601,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -17665,7 +17791,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17687,7 +17813,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17709,7 +17835,7 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17721,7 +17847,7 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_full_nosec_test", 
+    "name": "h2_compress_nosec_test", 
     "platforms": [
       "windows", 
       "linux", 
@@ -17731,7 +17857,7 @@
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17753,7 +17879,7 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17761,7 +17887,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -17775,7 +17901,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17797,7 +17923,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17819,7 +17945,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17841,7 +17967,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17863,7 +17989,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17885,7 +18011,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17907,7 +18033,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -17915,7 +18041,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -17929,7 +18055,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "windows", 
@@ -18171,7 +18297,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -18193,7 +18319,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -18215,7 +18341,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -18223,7 +18349,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -18237,7 +18363,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "windows", 
@@ -18245,7 +18371,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -18435,7 +18561,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -18457,7 +18583,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -18479,23 +18605,29 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_full+pipe_nosec_test", 
+    "name": "h2_full_nosec_test", 
     "platforms": [
-      "linux"
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "linux"
@@ -18511,12 +18643,12 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -18527,7 +18659,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "linux"
@@ -18543,7 +18675,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "linux"
@@ -18559,7 +18691,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -18575,7 +18707,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -18591,7 +18723,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "linux"
@@ -18607,7 +18739,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "linux"
@@ -18623,12 +18755,12 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -18639,7 +18771,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux"
@@ -18815,7 +18947,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux"
@@ -18831,7 +18963,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux"
@@ -18847,12 +18979,12 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -18863,12 +18995,12 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -19007,7 +19139,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -19023,7 +19155,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "linux"
@@ -19039,7 +19171,7 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -19048,14 +19180,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_full+poll_nosec_test", 
+    "name": "h2_full+pipe_nosec_test", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "linux"
@@ -19071,12 +19203,12 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -19087,7 +19219,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "linux"
@@ -19103,7 +19235,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "linux"
@@ -19119,7 +19251,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -19135,7 +19267,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -19151,7 +19283,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "linux"
@@ -19167,7 +19299,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "linux"
@@ -19183,12 +19315,12 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -19199,7 +19331,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux"
@@ -19375,7 +19507,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux"
@@ -19391,7 +19523,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux"
@@ -19407,12 +19539,12 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -19423,12 +19555,12 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -19567,7 +19699,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -19583,7 +19715,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "linux"
@@ -19599,7 +19731,7 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
       "linux"
@@ -19608,14 +19740,14 @@
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_full+poll+pipe_nosec_test", 
+    "name": "h2_full+poll_nosec_test", 
     "platforms": [
       "linux"
     ]
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "linux"
@@ -19631,12 +19763,12 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -19647,7 +19779,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "linux"
@@ -19663,7 +19795,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "linux"
@@ -19679,7 +19811,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -19695,7 +19827,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -19711,7 +19843,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "linux"
@@ -19727,7 +19859,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "linux"
@@ -19743,12 +19875,12 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -19759,7 +19891,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux"
@@ -19935,7 +20067,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux"
@@ -19951,7 +20083,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux"
@@ -19967,12 +20099,12 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -19983,12 +20115,12 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -20125,6 +20257,22 @@
       "linux"
     ]
   }, 
+  {
+    "args": [
+      "simple_metadata"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+poll+pipe_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
   {
     "args": [
       "simple_request"
@@ -20495,7 +20643,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -20516,7 +20664,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -20537,14 +20685,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -20558,14 +20706,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -20579,7 +20727,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -20600,7 +20748,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -20621,7 +20769,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -20642,7 +20790,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -20663,7 +20811,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -20684,14 +20832,14 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_delayed_request"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -20705,14 +20853,14 @@
   }, 
   {
     "args": [
-      "simple_delayed_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -21125,7 +21273,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21146,7 +21294,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21167,14 +21315,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -21188,14 +21336,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -21209,7 +21357,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21230,7 +21378,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_flags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21251,7 +21399,7 @@
   }, 
   {
     "args": [
-      "request_with_flags"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21272,7 +21420,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21293,7 +21441,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21314,7 +21462,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21335,7 +21483,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21750,7 +21898,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21772,7 +21920,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21794,7 +21942,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21802,7 +21950,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -21816,7 +21964,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21824,7 +21972,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -21838,7 +21986,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21860,7 +22008,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_flags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21882,7 +22030,7 @@
   }, 
   {
     "args": [
-      "request_with_flags"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21904,7 +22052,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21926,7 +22074,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21948,7 +22096,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -21970,7 +22118,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -22393,7 +22541,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -22414,7 +22562,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -22435,14 +22583,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -22456,14 +22604,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
       "linux", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -22477,7 +22625,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -22498,7 +22646,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_flags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -22519,7 +22667,7 @@
   }, 
   {
     "args": [
-      "request_with_flags"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -22540,7 +22688,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -22561,7 +22709,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -22582,7 +22730,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -22603,7 +22751,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23040,7 +23188,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23062,7 +23210,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23084,7 +23232,7 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23092,7 +23240,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -23106,7 +23254,7 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping_pong_streaming"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23114,7 +23262,7 @@
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -23128,7 +23276,7 @@
   }, 
   {
     "args": [
-      "ping_pong_streaming"
+      "registered_call"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23150,7 +23298,7 @@
   }, 
   {
     "args": [
-      "registered_call"
+      "request_with_flags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23172,7 +23320,7 @@
   }, 
   {
     "args": [
-      "request_with_flags"
+      "request_with_payload"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23194,7 +23342,7 @@
   }, 
   {
     "args": [
-      "request_with_payload"
+      "server_finishes_request"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23216,7 +23364,7 @@
   }, 
   {
     "args": [
-      "server_finishes_request"
+      "shutdown_finishes_calls"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23238,7 +23386,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_calls"
+      "shutdown_finishes_tags"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23260,7 +23408,7 @@
   }, 
   {
     "args": [
-      "shutdown_finishes_tags"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "windows", 
@@ -23486,7 +23634,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux", 
@@ -23506,27 +23654,7 @@
   }, 
   {
     "args": [
-      "channel_ping"
-    ], 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "flaky": false, 
-    "language": "c", 
-    "name": "h2_uds_nosec_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix"
-    ]
-  }, 
-  {
-    "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux", 
@@ -23726,7 +23854,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux", 
@@ -23746,7 +23874,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux", 
@@ -23766,14 +23894,14 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux", 
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -23786,14 +23914,14 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux", 
       "mac", 
       "posix"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -23966,7 +24094,7 @@
   }, 
   {
     "args": [
-      "simple_request"
+      "simple_metadata"
     ], 
     "ci_platforms": [
       "linux", 
@@ -23986,7 +24114,7 @@
   }, 
   {
     "args": [
-      "trailing_metadata"
+      "simple_request"
     ], 
     "ci_platforms": [
       "linux", 
@@ -24006,23 +24134,27 @@
   }, 
   {
     "args": [
-      "bad_hostname"
+      "trailing_metadata"
     ], 
     "ci_platforms": [
-      "linux"
+      "linux", 
+      "mac", 
+      "posix"
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
-    "name": "h2_uds+poll_nosec_test", 
+    "name": "h2_uds_nosec_test", 
     "platforms": [
-      "linux"
+      "linux", 
+      "mac", 
+      "posix"
     ]
   }, 
   {
     "args": [
-      "binary_metadata"
+      "bad_hostname"
     ], 
     "ci_platforms": [
       "linux"
@@ -24038,12 +24170,12 @@
   }, 
   {
     "args": [
-      "cancel_after_accept"
+      "binary_metadata"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -24054,7 +24186,7 @@
   }, 
   {
     "args": [
-      "cancel_after_client_done"
+      "cancel_after_accept"
     ], 
     "ci_platforms": [
       "linux"
@@ -24070,7 +24202,7 @@
   }, 
   {
     "args": [
-      "cancel_after_invoke"
+      "cancel_after_client_done"
     ], 
     "ci_platforms": [
       "linux"
@@ -24086,7 +24218,7 @@
   }, 
   {
     "args": [
-      "cancel_before_invoke"
+      "cancel_after_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -24102,7 +24234,7 @@
   }, 
   {
     "args": [
-      "cancel_in_a_vacuum"
+      "cancel_before_invoke"
     ], 
     "ci_platforms": [
       "linux"
@@ -24118,7 +24250,7 @@
   }, 
   {
     "args": [
-      "cancel_with_status"
+      "cancel_in_a_vacuum"
     ], 
     "ci_platforms": [
       "linux"
@@ -24134,7 +24266,7 @@
   }, 
   {
     "args": [
-      "channel_connectivity"
+      "cancel_with_status"
     ], 
     "ci_platforms": [
       "linux"
@@ -24150,12 +24282,12 @@
   }, 
   {
     "args": [
-      "channel_ping"
+      "compressed_payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -24166,7 +24298,7 @@
   }, 
   {
     "args": [
-      "compressed_payload"
+      "connectivity"
     ], 
     "ci_platforms": [
       "linux"
@@ -24326,7 +24458,7 @@
   }, 
   {
     "args": [
-      "metadata"
+      "negative_deadline"
     ], 
     "ci_platforms": [
       "linux"
@@ -24342,7 +24474,7 @@
   }, 
   {
     "args": [
-      "negative_deadline"
+      "no_op"
     ], 
     "ci_platforms": [
       "linux"
@@ -24358,12 +24490,12 @@
   }, 
   {
     "args": [
-      "no_op"
+      "payload"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 1.0, 
+    "cpu_cost": 0.1, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -24374,12 +24506,12 @@
   }, 
   {
     "args": [
-      "payload"
+      "ping"
     ], 
     "ci_platforms": [
       "linux"
     ], 
-    "cpu_cost": 0.1, 
+    "cpu_cost": 1.0, 
     "exclude_configs": [], 
     "flaky": false, 
     "language": "c", 
@@ -24516,6 +24648,22 @@
       "linux"
     ]
   }, 
+  {
+    "args": [
+      "simple_metadata"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds+poll_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
   {
     "args": [
       "simple_request"
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index 3a337576d1e023fe2b1455caee67b83c9202e00c..7cdc3b7ee8121c3ffc256cc89822bd93762e890d 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -185,17 +185,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_context_test", "vcxp
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_log_test", "vcxproj\test\census_log_test\census_log_test.vcxproj", "{C27CEE16-2BEC-5572-3956-677E9F6F8BED}"
-	ProjectSection(myProperties) = preProject
-        	lib = "False"
-	EndProjectSection
-	ProjectSection(ProjectDependencies) = postProject
-		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
-		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
-		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
-		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
-	EndProjectSection
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "channel_create_test", "vcxproj\test\channel_create_test\channel_create_test.vcxproj", "{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -356,7 +345,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_env_test", "vcxproj\tes
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_file_test", "vcxproj\test\gpr_file_test\gpr_file_test.vcxproj", "{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_histogram_test", "vcxproj\test\gpr_histogram_test\gpr_histogram_test.vcxproj", "{EEBDE4C3-0130-5BD1-E85F-527B3E68FE11}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
 	EndProjectSection
@@ -365,7 +354,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_file_test", "vcxproj\te
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_histogram_test", "vcxproj\test\gpr_histogram_test\gpr_histogram_test.vcxproj", "{EEBDE4C3-0130-5BD1-E85F-527B3E68FE11}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_host_port_test", "vcxproj\test\gpr_host_port_test\gpr_host_port_test.vcxproj", "{64728265-92F9-103E-6720-8935385458DF}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
 	EndProjectSection
@@ -374,7 +363,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_histogram_test", "vcxpr
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_host_port_test", "vcxproj\test\gpr_host_port_test\gpr_host_port_test.vcxproj", "{64728265-92F9-103E-6720-8935385458DF}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_load_file_test", "vcxproj\test\gpr_load_file_test\gpr_load_file_test.vcxproj", "{B36DE5B4-8B73-1194-7539-974D9524D609}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
 	EndProjectSection
@@ -484,7 +473,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_auth_context_test", "v
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_base64_test", "vcxproj\test\grpc_base64_test\grpc_base64_test.vcxproj", "{759A2BB1-DA1B-196C-94A3-98687BBC9F36}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_b64_test", "vcxproj\test\grpc_b64_test\grpc_b64_test.vcxproj", "{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
 	EndProjectSection
@@ -768,6 +757,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "message_compress_test", "vc
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mlog_test", "vcxproj\test\mlog_test\mlog_test.vcxproj", "{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multiple_server_queues_test", "vcxproj\test\multiple_server_queues_test\multiple_server_queues_test.vcxproj", "{88AF688E-E43C-5E20-6966-CF559F597D82}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1640,22 +1640,6 @@ Global
 		{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|Win32.Build.0 = Release|Win32
 		{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.ActiveCfg = Release|x64
 		{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.Build.0 = Release|x64
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug|Win32.ActiveCfg = Debug|Win32
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug|x64.ActiveCfg = Debug|x64
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release|Win32.ActiveCfg = Release|Win32
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release|x64.ActiveCfg = Release|x64
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug|Win32.Build.0 = Debug|Win32
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug|x64.Build.0 = Debug|x64
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release|Win32.Build.0 = Release|Win32
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release|x64.Build.0 = Release|x64
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug-DLL|x64.Build.0 = Debug|x64
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release-DLL|Win32.Build.0 = Release|Win32
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release-DLL|x64.ActiveCfg = Release|x64
-		{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release-DLL|x64.Build.0 = Release|x64
 		{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Debug|Win32.ActiveCfg = Debug|Win32
 		{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Debug|x64.ActiveCfg = Debug|x64
 		{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Release|Win32.ActiveCfg = Release|Win32
@@ -1912,22 +1896,6 @@ Global
 		{07149650-E8AF-B3D8-9D5B-BC34DC909DB8}.Release-DLL|Win32.Build.0 = Release|Win32
 		{07149650-E8AF-B3D8-9D5B-BC34DC909DB8}.Release-DLL|x64.ActiveCfg = Release|x64
 		{07149650-E8AF-B3D8-9D5B-BC34DC909DB8}.Release-DLL|x64.Build.0 = Release|x64
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Debug|Win32.ActiveCfg = Debug|Win32
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Debug|x64.ActiveCfg = Debug|x64
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Release|Win32.ActiveCfg = Release|Win32
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Release|x64.ActiveCfg = Release|x64
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Debug|Win32.Build.0 = Debug|Win32
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Debug|x64.Build.0 = Debug|x64
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Release|Win32.Build.0 = Release|Win32
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Release|x64.Build.0 = Release|x64
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Debug-DLL|x64.Build.0 = Debug|x64
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Release-DLL|Win32.Build.0 = Release|Win32
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Release-DLL|x64.ActiveCfg = Release|x64
-		{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}.Release-DLL|x64.Build.0 = Release|x64
 		{EEBDE4C3-0130-5BD1-E85F-527B3E68FE11}.Debug|Win32.ActiveCfg = Debug|Win32
 		{EEBDE4C3-0130-5BD1-E85F-527B3E68FE11}.Debug|x64.ActiveCfg = Debug|x64
 		{EEBDE4C3-0130-5BD1-E85F-527B3E68FE11}.Release|Win32.ActiveCfg = Release|Win32
@@ -1960,6 +1928,22 @@ Global
 		{64728265-92F9-103E-6720-8935385458DF}.Release-DLL|Win32.Build.0 = Release|Win32
 		{64728265-92F9-103E-6720-8935385458DF}.Release-DLL|x64.ActiveCfg = Release|x64
 		{64728265-92F9-103E-6720-8935385458DF}.Release-DLL|x64.Build.0 = Release|x64
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug|Win32.ActiveCfg = Debug|Win32
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug|x64.ActiveCfg = Debug|x64
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release|Win32.ActiveCfg = Release|Win32
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release|x64.ActiveCfg = Release|x64
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug|Win32.Build.0 = Debug|Win32
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug|x64.Build.0 = Debug|x64
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release|Win32.Build.0 = Release|Win32
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release|x64.Build.0 = Release|x64
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Debug-DLL|x64.Build.0 = Debug|x64
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release-DLL|Win32.Build.0 = Release|Win32
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release-DLL|x64.ActiveCfg = Release|x64
+		{B36DE5B4-8B73-1194-7539-974D9524D609}.Release-DLL|x64.Build.0 = Release|x64
 		{38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Debug|Win32.ActiveCfg = Debug|Win32
 		{38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Debug|x64.ActiveCfg = Debug|x64
 		{38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release|Win32.ActiveCfg = Release|Win32
@@ -2136,22 +2120,22 @@ Global
 		{C65A4336-92D6-D6A0-EB86-E3AA425222D0}.Release-DLL|Win32.Build.0 = Release|Win32
 		{C65A4336-92D6-D6A0-EB86-E3AA425222D0}.Release-DLL|x64.ActiveCfg = Release|x64
 		{C65A4336-92D6-D6A0-EB86-E3AA425222D0}.Release-DLL|x64.Build.0 = Release|x64
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Debug|Win32.ActiveCfg = Debug|Win32
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Debug|x64.ActiveCfg = Debug|x64
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Release|Win32.ActiveCfg = Release|Win32
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Release|x64.ActiveCfg = Release|x64
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Debug|Win32.Build.0 = Debug|Win32
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Debug|x64.Build.0 = Debug|x64
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Release|Win32.Build.0 = Release|Win32
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Release|x64.Build.0 = Release|x64
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Debug-DLL|Win32.Build.0 = Debug|Win32
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Debug-DLL|x64.ActiveCfg = Debug|x64
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Debug-DLL|x64.Build.0 = Debug|x64
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Release-DLL|Win32.ActiveCfg = Release|Win32
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Release-DLL|Win32.Build.0 = Release|Win32
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Release-DLL|x64.ActiveCfg = Release|x64
-		{759A2BB1-DA1B-196C-94A3-98687BBC9F36}.Release-DLL|x64.Build.0 = Release|x64
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Debug|Win32.ActiveCfg = Debug|Win32
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Debug|x64.ActiveCfg = Debug|x64
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Release|Win32.ActiveCfg = Release|Win32
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Release|x64.ActiveCfg = Release|x64
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Debug|Win32.Build.0 = Debug|Win32
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Debug|x64.Build.0 = Debug|x64
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Release|Win32.Build.0 = Release|Win32
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Release|x64.Build.0 = Release|x64
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Debug-DLL|x64.Build.0 = Debug|x64
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Release-DLL|Win32.Build.0 = Release|Win32
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Release-DLL|x64.ActiveCfg = Release|x64
+		{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}.Release-DLL|x64.Build.0 = Release|x64
 		{82124768-C986-6C10-8BCC-B255B7C84722}.Debug|Win32.ActiveCfg = Debug|Win32
 		{82124768-C986-6C10-8BCC-B255B7C84722}.Debug|x64.ActiveCfg = Debug|x64
 		{82124768-C986-6C10-8BCC-B255B7C84722}.Release|Win32.ActiveCfg = Release|Win32
@@ -2552,6 +2536,22 @@ Global
 		{07170557-CCB0-D23C-8018-C2909D115DF9}.Release-DLL|Win32.Build.0 = Release|Win32
 		{07170557-CCB0-D23C-8018-C2909D115DF9}.Release-DLL|x64.ActiveCfg = Release|x64
 		{07170557-CCB0-D23C-8018-C2909D115DF9}.Release-DLL|x64.Build.0 = Release|x64
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Debug|Win32.ActiveCfg = Debug|Win32
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Debug|x64.ActiveCfg = Debug|x64
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Release|Win32.ActiveCfg = Release|Win32
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Release|x64.ActiveCfg = Release|x64
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Debug|Win32.Build.0 = Debug|Win32
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Debug|x64.Build.0 = Debug|x64
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Release|Win32.Build.0 = Release|Win32
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Release|x64.Build.0 = Release|x64
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Debug-DLL|x64.Build.0 = Debug|x64
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Release-DLL|Win32.Build.0 = Release|Win32
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Release-DLL|x64.ActiveCfg = Release|x64
+		{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}.Release-DLL|x64.Build.0 = Release|x64
 		{88AF688E-E43C-5E20-6966-CF559F597D82}.Debug|Win32.ActiveCfg = Debug|Win32
 		{88AF688E-E43C-5E20-6966-CF559F597D82}.Debug|x64.ActiveCfg = Debug|x64
 		{88AF688E-E43C-5E20-6966-CF559F597D82}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/protoc.props b/vsprojects/protoc.props
index ecaf248446e1677515a2704300a4d9891bcf8a4e..1bdc07193bce01b5aad1e89616c79b55da335ddc 100644
--- a/vsprojects/protoc.props
+++ b/vsprojects/protoc.props
@@ -1 +1 @@
-<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ImportGroup Label="PropertySheets" /> <PropertyGroup Label="UserMacros" /> <PropertyGroup /> <ItemDefinitionGroup> <Link> <AdditionalDependencies>libprotoc.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(SolutionDir)\..\third_party\protobuf\cmake\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> </Link> </ItemDefinitionGroup> <ItemGroup /> </Project>
\ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ImportGroup Label="PropertySheets" /> <PropertyGroup Label="UserMacros" /> <PropertyGroup /> <ItemDefinitionGroup> <ClCompile> <DisableSpecificWarnings>4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings> </ClCompile> <Link> <AdditionalDependencies>libprotoc.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(SolutionDir)\..\third_party\protobuf\cmake\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> </Link> </ItemDefinitionGroup> <ItemGroup /> </Project>
\ No newline at end of file
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj
index e1b3963c911133075cc9a8f2e982fbea75012052..dae8e623d82238e8127bff924ac338ec5d3f64d9 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj
@@ -194,13 +194,14 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\profiling\timers.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\support\block_annotate.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\support\env.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\file.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\support\load_file.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\support\murmur_hash.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\support\stack_lockfree.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\support\string.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\support\string_win32.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\support\thd_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\support\time_precise.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\support\tmpfile.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\src\core\profiling\basic_timers.c">
@@ -227,16 +228,12 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\env_win32.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\file.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\file_posix.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\file_win32.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\histogram.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\host_port.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\support\load_file.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\log.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\log_android.c">
@@ -287,6 +284,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\tls_pthread.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\support\tmpfile_posix.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\support\tmpfile_win32.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\wrap_memcpy.c">
     </ClCompile>
   </ItemGroup>
diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
index aedba93e88b025a1d2c3d9acb22b3f5b8b0c61bc..055b29f64809ab6335f02e5961a55902b2780b12 100644
--- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
+++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters
@@ -37,21 +37,15 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\support\env_win32.c">
       <Filter>src\core\support</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\file.c">
-      <Filter>src\core\support</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\file_posix.c">
-      <Filter>src\core\support</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\support\file_win32.c">
-      <Filter>src\core\support</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\histogram.c">
       <Filter>src\core\support</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\host_port.c">
       <Filter>src\core\support</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\support\load_file.c">
+      <Filter>src\core\support</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\log.c">
       <Filter>src\core\support</Filter>
     </ClCompile>
@@ -127,6 +121,12 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\support\tls_pthread.c">
       <Filter>src\core\support</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\support\tmpfile_posix.c">
+      <Filter>src\core\support</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\support\tmpfile_win32.c">
+      <Filter>src\core\support</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\support\wrap_memcpy.c">
       <Filter>src\core\support</Filter>
     </ClCompile>
@@ -269,7 +269,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\support\env.h">
       <Filter>src\core\support</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\support\file.h">
+    <ClInclude Include="$(SolutionDir)\..\src\core\support\load_file.h">
       <Filter>src\core\support</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\support\murmur_hash.h">
@@ -290,6 +290,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\support\time_precise.h">
       <Filter>src\core\support</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\support\tmpfile.h">
+      <Filter>src\core\support</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
index c62faf33e6fc8e7098d19c42e6ed342f77edf91d..0b8c345196913fbfef1cb03f287699ddf37b7f7e 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
@@ -369,8 +369,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\client\insecure_credentials.cc">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\cpp\common\alarm.cc">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\common\call.cc">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\common\channel_arguments.cc">
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
index 5f9350e76a00a708caa25bb92aab62e1d5b9a06f..0f3dccf17c5dce96580269ebaaf2dbc7656254ba 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
@@ -40,9 +40,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\cpp\client\insecure_credentials.cc">
       <Filter>src\cpp\client</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\cpp\common\alarm.cc">
-      <Filter>src\cpp\common</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\common\call.cc">
       <Filter>src\cpp\common</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
index fb4246580fd57a136610c45e3eca81dac7f563e4..2dcadbaec0c56d3e99aae6635740277300b3a673 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
@@ -356,8 +356,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\client\insecure_credentials.cc">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\cpp\common\alarm.cc">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\common\call.cc">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\common\channel_arguments.cc">
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
index eeff7d3697c49bc168147e3ea53cde47f2ff0fc0..3572c651b6d117446fb032c194787c398d6d0b50 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
@@ -25,9 +25,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\cpp\client\insecure_credentials.cc">
       <Filter>src\cpp\client</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\cpp\common\alarm.cc">
-      <Filter>src\cpp\common</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\cpp\common\call.cc">
       <Filter>src\cpp\common</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index ebab196fcbf8b37125b06624383d6ccd7cca7c87..c2635c31a3d812b27d84f416ba1502f13ec19b8d 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -296,6 +296,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\client_config.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\connector.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\round_robin.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy.h" />
@@ -346,7 +347,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\time_averaged_stats.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\udp_server.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_pipe.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_posix.h" />
@@ -357,6 +357,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\json\json_common.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\json\json_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\json\json_writer.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_rpc_stats.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\surface\api_trace.h" />
@@ -397,7 +398,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\transport\transport.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\transport\transport_impl.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\security\auth_filters.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\base64.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\security\b64.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\security\credentials.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\security\handshake.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\security\json_token.h" />
@@ -413,6 +414,10 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\census\aggregation.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\census\mlog.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h" />
+    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
+    <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" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\src\core\census\grpc_context.c">
@@ -445,6 +450,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\round_robin.c">
@@ -473,7 +480,7 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\uri_parser.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\algorithm.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\compression\compression_algorithm.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\compression\message_compress.c">
     </ClCompile>
@@ -573,6 +580,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\json\json_writer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\surface\alarm.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\surface\api_trace.c">
@@ -673,7 +682,7 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\httpcli_security_connector.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\base64.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\security\b64.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\security\client_auth_filter.c">
     </ClCompile>
@@ -725,6 +734,12 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\census\tracing.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 68fc952fd624c3ed377e8fa787aba30966d54bda..6dd10d3dd347fdc07921b348f76b0b110a51cc52 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -46,6 +46,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.c">
       <Filter>src\core\client_config</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.c">
+      <Filter>src\core\client_config\lb_policies</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.c">
       <Filter>src\core\client_config\lb_policies</Filter>
     </ClCompile>
@@ -88,7 +91,7 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\uri_parser.c">
       <Filter>src\core\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\algorithm.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\compression\compression_algorithm.c">
       <Filter>src\core\compression</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\compression\message_compress.c">
@@ -238,6 +241,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\json\json_writer.c">
       <Filter>src\core\json</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.c">
+      <Filter>src\core\proto\grpc\lb\v0</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\surface\alarm.c">
       <Filter>src\core\surface</Filter>
     </ClCompile>
@@ -388,7 +394,7 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\httpcli\httpcli_security_connector.c">
       <Filter>src\core\httpcli</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\security\base64.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\security\b64.c">
       <Filter>src\core\security</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\security\client_auth_filter.c">
@@ -466,6 +472,15 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\census\tracing.c">
       <Filter>src\core\census</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
+      <Filter>third_party\nanopb</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.c">
+      <Filter>third_party\nanopb</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
+      <Filter>third_party\nanopb</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\grpc_security.h">
@@ -551,6 +566,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.h">
       <Filter>src\core\client_config</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.h">
+      <Filter>src\core\client_config\lb_policies</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.h">
       <Filter>src\core\client_config\lb_policies</Filter>
     </ClInclude>
@@ -701,9 +719,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.h">
       <Filter>src\core\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_internal.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\udp_server.h">
       <Filter>src\core\iomgr</Filter>
     </ClInclude>
@@ -734,6 +749,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\json\json_writer.h">
       <Filter>src\core\json</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.h">
+      <Filter>src\core\proto\grpc\lb\v0</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_interface.h">
       <Filter>src\core\statistics</Filter>
     </ClInclude>
@@ -854,7 +872,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\security\auth_filters.h">
       <Filter>src\core\security</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\security\base64.h">
+    <ClInclude Include="$(SolutionDir)\..\src\core\security\b64.h">
       <Filter>src\core\security</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\security\credentials.h">
@@ -902,6 +920,18 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h">
       <Filter>src\core\census</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h">
+      <Filter>third_party\nanopb</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h">
+      <Filter>third_party\nanopb</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h">
+      <Filter>third_party\nanopb</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h">
+      <Filter>third_party\nanopb</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
@@ -953,6 +983,18 @@
     <Filter Include="src\core\json">
       <UniqueIdentifier>{e665cc0e-b994-d7c5-cc18-2007392019f0}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\proto">
+      <UniqueIdentifier>{1ff04466-0905-8a5d-d6f4-7ff2df4c13b5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\proto\grpc">
+      <UniqueIdentifier>{7c7ad0b3-bf85-5bd3-e0c8-4f5468a8e2e6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\proto\grpc\lb">
+      <UniqueIdentifier>{3d533dad-8100-e8a3-b7c3-1fc13a4d60da}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\proto\grpc\lb\v0">
+      <UniqueIdentifier>{0ffcf868-7617-5fed-b6ce-2162d9d09148}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\security">
       <UniqueIdentifier>{1d850ac6-e639-4eab-5338-4ba40272fcc9}</UniqueIdentifier>
     </Filter>
@@ -971,6 +1013,12 @@
     <Filter Include="src\core\tsi">
       <UniqueIdentifier>{0b0f9ab1-efa4-7f03-e446-6fb9b5227e84}</UniqueIdentifier>
     </Filter>
+    <Filter Include="third_party">
+      <UniqueIdentifier>{aaab30a4-2a15-732e-c141-3fbc0f0f5a7a}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="third_party\nanopb">
+      <UniqueIdentifier>{93d6596d-330c-1d27-6f84-3c840e57869e}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
 </Project>
 
diff --git a/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj b/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj
index 89183902d74c09c0ae53e67555b91efcf6fdf5ee..a76c883903a6910c16761154904abd9b60c74874 100644
--- a/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj
+++ b/vsprojects/vcxproj/grpc_plugin_support/grpc_plugin_support.vcxproj
@@ -53,6 +53,7 @@
   <ImportGroup Label="PropertySheets">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
     <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protoc.props" />
     <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
   </ImportGroup>
   <PropertyGroup Label="UserMacros" />
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 5daa7900f8ff3112c3de15cc66dbea942e5df82f..f0d869ba9307f6388fce4949437e8534d4ad84a6 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -286,6 +286,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\client_config.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\connector.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\round_robin.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policy.h" />
@@ -336,7 +337,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\time_averaged_stats.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_internal.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\udp_server.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_pipe.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\wakeup_fd_posix.h" />
@@ -347,6 +347,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\json\json_common.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\json\json_reader.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\json\json_writer.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_interface.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_rpc_stats.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\surface\api_trace.h" />
@@ -389,6 +390,10 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\census\aggregation.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\census\mlog.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h" />
+    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
+    <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" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\src\core\surface\init_unsecure.c">
@@ -423,6 +428,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\round_robin.c">
@@ -451,7 +458,7 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\uri_parser.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\algorithm.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\compression\compression_algorithm.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\compression\message_compress.c">
     </ClCompile>
@@ -551,6 +558,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\json\json_writer.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\surface\alarm.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\surface\api_trace.c">
@@ -661,6 +670,12 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\census\tracing.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.c">
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 68f136398bd25c97af4f113585288fe143adaab3..1f240212a389df9256e808d5b6ec8d94f84a2cef 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -49,6 +49,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.c">
       <Filter>src\core\client_config</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.c">
+      <Filter>src\core\client_config\lb_policies</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.c">
       <Filter>src\core\client_config\lb_policies</Filter>
     </ClCompile>
@@ -91,7 +94,7 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\client_config\uri_parser.c">
       <Filter>src\core\client_config</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\compression\algorithm.c">
+    <ClCompile Include="$(SolutionDir)\..\src\core\compression\compression_algorithm.c">
       <Filter>src\core\compression</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\compression\message_compress.c">
@@ -241,6 +244,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\json\json_writer.c">
       <Filter>src\core\json</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.c">
+      <Filter>src\core\proto\grpc\lb\v0</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\surface\alarm.c">
       <Filter>src\core\surface</Filter>
     </ClCompile>
@@ -406,6 +412,15 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\census\tracing.c">
       <Filter>src\core\census</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c">
+      <Filter>third_party\nanopb</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.c">
+      <Filter>third_party\nanopb</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.c">
+      <Filter>third_party\nanopb</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h">
@@ -488,6 +503,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\initial_connect_string.h">
       <Filter>src\core\client_config</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\load_balancer_api.h">
+      <Filter>src\core\client_config\lb_policies</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\client_config\lb_policies\pick_first.h">
       <Filter>src\core\client_config\lb_policies</Filter>
     </ClInclude>
@@ -638,9 +656,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_heap.h">
       <Filter>src\core\iomgr</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\timer_internal.h">
-      <Filter>src\core\iomgr</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\iomgr\udp_server.h">
       <Filter>src\core\iomgr</Filter>
     </ClInclude>
@@ -671,6 +686,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\json\json_writer.h">
       <Filter>src\core\json</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\proto\grpc\lb\v0\load_balancer.pb.h">
+      <Filter>src\core\proto\grpc\lb\v0</Filter>
+    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\statistics\census_interface.h">
       <Filter>src\core\statistics</Filter>
     </ClInclude>
@@ -797,6 +815,18 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h">
       <Filter>src\core\census</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h">
+      <Filter>third_party\nanopb</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h">
+      <Filter>third_party\nanopb</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h">
+      <Filter>third_party\nanopb</Filter>
+    </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_encode.h">
+      <Filter>third_party\nanopb</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
@@ -848,6 +878,18 @@
     <Filter Include="src\core\json">
       <UniqueIdentifier>{443ffc61-1bea-2477-6e54-1ddf8c139264}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\proto">
+      <UniqueIdentifier>{7f4bb22a-65ba-0f8f-6387-66b1f6677a80}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\proto\grpc">
+      <UniqueIdentifier>{9c2bd164-c317-8a13-564d-3b28b0fd79cf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\proto\grpc\lb">
+      <UniqueIdentifier>{2bad8e10-4fc5-d8b3-e026-4abbd0c25cda}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\core\proto\grpc\lb\v0">
+      <UniqueIdentifier>{4475c8ed-e01b-8906-47d0-8a504189c0d5}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\statistics">
       <UniqueIdentifier>{e084164c-a069-00e3-db35-4e0b1cd6f0b7}</UniqueIdentifier>
     </Filter>
@@ -860,6 +902,12 @@
     <Filter Include="src\core\transport\chttp2">
       <UniqueIdentifier>{5fcd6206-f774-9ae6-4b85-305d6a723843}</UniqueIdentifier>
     </Filter>
+    <Filter Include="third_party">
+      <UniqueIdentifier>{025c051e-8eba-125b-67f9-173f95176eb2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="third_party\nanopb">
+      <UniqueIdentifier>{6511f77d-f28c-80e0-0889-8975e688e344}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
 </Project>
 
diff --git a/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj b/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj
index 69f80a8e5997fec6d1d33ec952b00ed7e41c4015..075750afc6d2cb3f76c4f6e78916bf257bd0eb03 100644
--- a/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj
+++ b/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj
@@ -171,7 +171,7 @@
     </ClCompile>
     <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\test.grpc.pb.h">
     </ClInclude>
-    <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\server.cc">
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\server_main.cc">
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
diff --git a/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj.filters b/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj.filters
index 8a9ff2704a54c6caad4bae487e87846062063309..51a6b9e73c32cfc0b3d3dfd4e160613a662e9c29 100644
--- a/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj.filters
+++ b/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj.filters
@@ -10,7 +10,7 @@
     <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.proto">
       <Filter>src\proto\grpc\testing</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\server.cc">
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\server_main.cc">
       <Filter>test\cpp\interop</Filter>
     </ClCompile>
   </ItemGroup>
diff --git a/vsprojects/vcxproj/qps/qps.vcxproj b/vsprojects/vcxproj/qps/qps.vcxproj
index 8306e2e235695d84b82adb36297e5e8683c16218..a57b7409b69098d22d8c99d59865a29a4d42faa8 100644
--- a/vsprojects/vcxproj/qps/qps.vcxproj
+++ b/vsprojects/vcxproj/qps/qps.vcxproj
@@ -157,7 +157,7 @@
     <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\report.h" />
     <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\server.h" />
     <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\stats.h" />
-    <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\timer.h" />
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\usage_timer.h" />
     <ClInclude Include="$(SolutionDir)\..\test\cpp\util\benchmark_config.h" />
   </ItemGroup>
   <ItemGroup>
@@ -227,7 +227,7 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\server_sync.cc">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\timer.cc">
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\usage_timer.cc">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\cpp\util\benchmark_config.cc">
     </ClCompile>
diff --git a/vsprojects/vcxproj/qps/qps.vcxproj.filters b/vsprojects/vcxproj/qps/qps.vcxproj.filters
index 650116a912ea0799ce8951b12ee52f8f7f1ae7cb..eeb9555a6af9b17afb2dbebfc38e274fa2ffb079 100644
--- a/vsprojects/vcxproj/qps/qps.vcxproj.filters
+++ b/vsprojects/vcxproj/qps/qps.vcxproj.filters
@@ -46,7 +46,7 @@
     <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\server_sync.cc">
       <Filter>test\cpp\qps</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\timer.cc">
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\qps\usage_timer.cc">
       <Filter>test\cpp\qps</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\cpp\util\benchmark_config.cc">
@@ -84,7 +84,7 @@
     <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\stats.h">
       <Filter>test\cpp\qps</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\timer.h">
+    <ClInclude Include="$(SolutionDir)\..\test\cpp\qps\usage_timer.h">
       <Filter>test\cpp\qps</Filter>
     </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\test\cpp\util\benchmark_config.h">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
index 50c1b61c43bca4dc208f61618f5f994b8dfae3b1..2f3b591dfc28f29c1089803adccfc5686c51ef24 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
@@ -169,12 +169,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_with_status.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\channel_connectivity.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\channel_ping.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\compressed_payload.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\connectivity.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\default_host.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\disappearing_server.c">
@@ -195,14 +193,14 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\max_message_length.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\metadata.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\negative_deadline.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\no_op.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\payload.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping_pong_streaming.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\registered_call.c">
@@ -219,6 +217,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_delayed_request.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_metadata.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_request.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\trailing_metadata.c">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
index a825a2d8caec8823eb20b058955ec54323520c53..c63ebe7d81bca7b3b00c27bc8266956979dc6b1d 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
@@ -28,13 +28,10 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_with_status.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\channel_connectivity.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\compressed_payload.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\channel_ping.c">
-      <Filter>test\core\end2end\tests</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\compressed_payload.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\connectivity.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\default_host.c">
@@ -67,9 +64,6 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\max_message_length.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\metadata.c">
-      <Filter>test\core\end2end\tests</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\negative_deadline.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
@@ -79,6 +73,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\payload.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping_pong_streaming.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
@@ -103,6 +100,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_delayed_request.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_metadata.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_request.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
index fa559e1af3875500ec76dfee1a74c5256e851db1..9d7bdc574cfd8f07ce6962026db50de05c45b207 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
@@ -171,12 +171,10 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_with_status.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\channel_connectivity.c">
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\channel_ping.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\compressed_payload.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\connectivity.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\default_host.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\disappearing_server.c">
@@ -197,14 +195,14 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\max_message_length.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\metadata.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\negative_deadline.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\no_op.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\payload.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping_pong_streaming.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\registered_call.c">
@@ -221,6 +219,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_delayed_request.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_metadata.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_request.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\trailing_metadata.c">
diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
index 61afa17e0666ef9aa49aa993b43822947df10b1f..c30054a17ba9d2acfb3914abec3416dae01527c8 100644
--- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
+++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters
@@ -31,13 +31,10 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_with_status.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\channel_connectivity.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\compressed_payload.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\channel_ping.c">
-      <Filter>test\core\end2end\tests</Filter>
-    </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\compressed_payload.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\connectivity.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\default_host.c">
@@ -70,9 +67,6 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\max_message_length.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\metadata.c">
-      <Filter>test\core\end2end\tests</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\negative_deadline.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
@@ -82,6 +76,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\payload.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\ping_pong_streaming.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
@@ -106,6 +103,9 @@
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_delayed_request.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_metadata.c">
+      <Filter>test\core\end2end\tests</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\simple_request.c">
       <Filter>test\core\end2end\tests</Filter>
     </ClCompile>
diff --git a/vsprojects/vcxproj/test/gpr_file_test/gpr_file_test.vcxproj b/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj
similarity index 98%
rename from vsprojects/vcxproj/test/gpr_file_test/gpr_file_test.vcxproj
rename to vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj
index 5a2fdee1236453f7859ecb33d682aabddb381107..4182969f5004bb9a37bb9226f4870ebfebde021e 100644
--- a/vsprojects/vcxproj/test/gpr_file_test/gpr_file_test.vcxproj
+++ b/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj
@@ -20,7 +20,7 @@
     </ProjectConfiguration>
   </ItemGroup>
   <PropertyGroup Label="Globals">
-    <ProjectGuid>{13B0BA63-A3A4-D0E7-1DF2-C73281EB0678}</ProjectGuid>
+    <ProjectGuid>{B36DE5B4-8B73-1194-7539-974D9524D609}</ProjectGuid>
     <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
     <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
   </PropertyGroup>
@@ -60,14 +60,14 @@
   </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>gpr_file_test</TargetName>
+    <TargetName>gpr_load_file_test</TargetName>
     <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
     <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
     <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
     <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>gpr_file_test</TargetName>
+    <TargetName>gpr_load_file_test</TargetName>
     <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
     <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
     <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
@@ -158,7 +158,7 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\support\file_test.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\support\load_file_test.c">
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
diff --git a/vsprojects/vcxproj/test/gpr_file_test/gpr_file_test.vcxproj.filters b/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj.filters
similarity index 62%
rename from vsprojects/vcxproj/test/gpr_file_test/gpr_file_test.vcxproj.filters
rename to vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj.filters
index ec225bd427937fbd6c9d9bccf7622b0071a3c345..0edd0fe299c9852097b16df0e88bc6286857e308 100644
--- a/vsprojects/vcxproj/test/gpr_file_test/gpr_file_test.vcxproj.filters
+++ b/vsprojects/vcxproj/test/gpr_load_file_test/gpr_load_file_test.vcxproj.filters
@@ -1,20 +1,20 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\support\file_test.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\support\load_file_test.c">
       <Filter>test\core\support</Filter>
     </ClCompile>
   </ItemGroup>
 
   <ItemGroup>
     <Filter Include="test">
-      <UniqueIdentifier>{ea0f8f5c-afe0-ed4b-ae64-d98a8f32a9e1}</UniqueIdentifier>
+      <UniqueIdentifier>{7defb822-a4cc-a221-8900-1041a6c2c134}</UniqueIdentifier>
     </Filter>
     <Filter Include="test\core">
-      <UniqueIdentifier>{2ac0488e-8ef6-c61d-96c0-9cf580283589}</UniqueIdentifier>
+      <UniqueIdentifier>{3f3cae49-1efd-7015-0fa1-5621168945d5}</UniqueIdentifier>
     </Filter>
     <Filter Include="test\core\support">
-      <UniqueIdentifier>{d2feffa9-e47c-ec2c-ecce-caf8ce85cb08}</UniqueIdentifier>
+      <UniqueIdentifier>{54e9b9b9-021a-139b-53f2-2f8b7173306c}</UniqueIdentifier>
     </Filter>
   </ItemGroup>
 </Project>
diff --git a/vsprojects/vcxproj/test/grpc_base64_test/grpc_base64_test.vcxproj b/vsprojects/vcxproj/test/grpc_b64_test/grpc_b64_test.vcxproj
similarity index 98%
rename from vsprojects/vcxproj/test/grpc_base64_test/grpc_base64_test.vcxproj
rename to vsprojects/vcxproj/test/grpc_b64_test/grpc_b64_test.vcxproj
index 3e49ac8ae264154787e92b8b81292938b14c98e2..7e6b4df961a34ba81752ecedae61287230acce2b 100644
--- a/vsprojects/vcxproj/test/grpc_base64_test/grpc_base64_test.vcxproj
+++ b/vsprojects/vcxproj/test/grpc_b64_test/grpc_b64_test.vcxproj
@@ -20,7 +20,7 @@
     </ProjectConfiguration>
   </ItemGroup>
   <PropertyGroup Label="Globals">
-    <ProjectGuid>{759A2BB1-DA1B-196C-94A3-98687BBC9F36}</ProjectGuid>
+    <ProjectGuid>{A19FD81D-DF19-B8A4-4A8A-6967217FEC85}</ProjectGuid>
     <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
     <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
   </PropertyGroup>
@@ -60,14 +60,14 @@
   </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>grpc_base64_test</TargetName>
+    <TargetName>grpc_b64_test</TargetName>
     <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
     <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
     <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
     <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>grpc_base64_test</TargetName>
+    <TargetName>grpc_b64_test</TargetName>
     <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
     <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
     <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
@@ -158,7 +158,7 @@
   </ItemDefinitionGroup>
 
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\security\base64_test.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\security\b64_test.c">
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
diff --git a/vsprojects/vcxproj/test/grpc_base64_test/grpc_base64_test.vcxproj.filters b/vsprojects/vcxproj/test/grpc_b64_test/grpc_b64_test.vcxproj.filters
similarity index 62%
rename from vsprojects/vcxproj/test/grpc_base64_test/grpc_base64_test.vcxproj.filters
rename to vsprojects/vcxproj/test/grpc_b64_test/grpc_b64_test.vcxproj.filters
index 6db15dfe2dc17ac7c243f1fda7fb425109a4944a..4335011fe35776bb2a4161770767b7099db39a26 100644
--- a/vsprojects/vcxproj/test/grpc_base64_test/grpc_base64_test.vcxproj.filters
+++ b/vsprojects/vcxproj/test/grpc_b64_test/grpc_b64_test.vcxproj.filters
@@ -1,20 +1,20 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <ClCompile Include="$(SolutionDir)\..\test\core\security\base64_test.c">
+    <ClCompile Include="$(SolutionDir)\..\test\core\security\b64_test.c">
       <Filter>test\core\security</Filter>
     </ClCompile>
   </ItemGroup>
 
   <ItemGroup>
     <Filter Include="test">
-      <UniqueIdentifier>{a996936d-cc5f-01b6-024a-8c48e97621a1}</UniqueIdentifier>
+      <UniqueIdentifier>{61d5c8e1-ac27-5bd0-d581-aeb585f0157e}</UniqueIdentifier>
     </Filter>
     <Filter Include="test\core">
-      <UniqueIdentifier>{f24de076-eae7-0bf0-1028-c08488419d68}</UniqueIdentifier>
+      <UniqueIdentifier>{409b4a57-584c-1dc5-db72-1e8d4c462e9d}</UniqueIdentifier>
     </Filter>
     <Filter Include="test\core\security">
-      <UniqueIdentifier>{4e36400d-5525-a04f-f6bf-4960c950aa00}</UniqueIdentifier>
+      <UniqueIdentifier>{0cb2c3ef-ed46-78ae-140c-29f21dc6fdb1}</UniqueIdentifier>
     </Filter>
   </ItemGroup>
 </Project>
diff --git a/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..1509ece9f96a82b1ac74129593f6c07794df1bb6
--- /dev/null
+++ b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{990AF023-17D7-8DBF-EB6E-14C7C016C77E}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>grpclb_api_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>grpclb_api_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\lb\v0\load_balancer.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\lb\v0\load_balancer.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\lb\v0\load_balancer.grpc.pb.cc">
+    </ClCompile>
+    <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\lb\v0\load_balancer.grpc.pb.h">
+    </ClInclude>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\grpclb\grpclb_api_test.cc">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
+      <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
+      <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..6c57b8c162a7e34d7ead3fbf32e691069a1f8b5e
--- /dev/null
+++ b/vsprojects/vcxproj/test/grpclb_api_test/grpclb_api_test.vcxproj.filters
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\lb\v0\load_balancer.proto">
+      <Filter>src\proto\grpc\lb\v0</Filter>
+    </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\test\cpp\grpclb\grpclb_api_test.cc">
+      <Filter>test\cpp\grpclb</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="src">
+      <UniqueIdentifier>{a31d21fb-c6ab-75ce-43dc-7d6f506765e6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto">
+      <UniqueIdentifier>{10d49c90-8503-9b10-6678-eed983bc25d9}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc">
+      <UniqueIdentifier>{8b6be783-e071-44cc-2096-f1c476012556}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\lb">
+      <UniqueIdentifier>{2981699e-c196-c599-bc17-c177770f89ee}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="src\proto\grpc\lb\v0">
+      <UniqueIdentifier>{3d04774a-1c2f-e100-435e-08af5d539250}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test">
+      <UniqueIdentifier>{64736e1d-eb77-664f-34ab-6cf41263d3d8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp">
+      <UniqueIdentifier>{c86e9cb1-bed4-3697-40f2-9ecff6297fa5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\cpp\grpclb">
+      <UniqueIdentifier>{6b5ba83a-6cf2-5a7b-0ab8-62de31882705}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/census_log_test/census_log_test.vcxproj b/vsprojects/vcxproj/test/mlog_test/mlog_test.vcxproj
similarity index 98%
rename from vsprojects/vcxproj/test/census_log_test/census_log_test.vcxproj
rename to vsprojects/vcxproj/test/mlog_test/mlog_test.vcxproj
index 9f2480085b54c6069b26e57f2c37bb2317593ca8..44b9a971f83d5f16458d7eec1aaeccf9562d11d3 100644
--- a/vsprojects/vcxproj/test/census_log_test/census_log_test.vcxproj
+++ b/vsprojects/vcxproj/test/mlog_test/mlog_test.vcxproj
@@ -20,7 +20,7 @@
     </ProjectConfiguration>
   </ItemGroup>
   <PropertyGroup Label="Globals">
-    <ProjectGuid>{C27CEE16-2BEC-5572-3956-677E9F6F8BED}</ProjectGuid>
+    <ProjectGuid>{9345E329-80F3-DED4-FDC3-BF63FCEA2C03}</ProjectGuid>
     <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
     <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
   </PropertyGroup>
@@ -60,14 +60,14 @@
   </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)'=='Debug'">
-    <TargetName>census_log_test</TargetName>
+    <TargetName>mlog_test</TargetName>
     <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
     <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
     <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
     <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)'=='Release'">
-    <TargetName>census_log_test</TargetName>
+    <TargetName>mlog_test</TargetName>
     <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
     <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
     <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
diff --git a/vsprojects/vcxproj/test/census_log_test/census_log_test.vcxproj.filters b/vsprojects/vcxproj/test/mlog_test/mlog_test.vcxproj.filters
similarity index 73%
rename from vsprojects/vcxproj/test/census_log_test/census_log_test.vcxproj.filters
rename to vsprojects/vcxproj/test/mlog_test/mlog_test.vcxproj.filters
index 8b70dcb2a41bec7e9e798620a9c10c40d3840d16..982deddf97b19d6e30b52095f246349a956d2ea6 100644
--- a/vsprojects/vcxproj/test/census_log_test/census_log_test.vcxproj.filters
+++ b/vsprojects/vcxproj/test/mlog_test/mlog_test.vcxproj.filters
@@ -8,13 +8,13 @@
 
   <ItemGroup>
     <Filter Include="test">
-      <UniqueIdentifier>{4d0aae38-6975-cafb-30a6-a7c2c87d22ff}</UniqueIdentifier>
+      <UniqueIdentifier>{cf4f3b02-7a43-f5b5-708a-938b179be26e}</UniqueIdentifier>
     </Filter>
     <Filter Include="test\core">
-      <UniqueIdentifier>{fb85321f-d3b5-ef2f-c5aa-34660a5e0c7b}</UniqueIdentifier>
+      <UniqueIdentifier>{74b31c41-bf60-9274-a718-f33cd7c659b4}</UniqueIdentifier>
     </Filter>
     <Filter Include="test\core\census">
-      <UniqueIdentifier>{f23141da-cbe2-70fa-8207-858af868eb18}</UniqueIdentifier>
+      <UniqueIdentifier>{2117a367-a751-9526-028f-07b5e88f7037}</UniqueIdentifier>
     </Filter>
   </ItemGroup>
 </Project>