From 5842a5b0895e8ee713991625d3066fa8e948a52a Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 12:38:57 -0700 Subject: Initial sketch of async execution lock --- src/core/lib/iomgr/async_execution_lock.c | 71 +++++++++++++++++++++++++++++++ src/core/lib/iomgr/async_execution_lock.h | 58 +++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 src/core/lib/iomgr/async_execution_lock.c create mode 100644 src/core/lib/iomgr/async_execution_lock.h (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c new file mode 100644 index 0000000000..20bdf3f9a9 --- /dev/null +++ b/src/core/lib/iomgr/async_execution_lock.c @@ -0,0 +1,71 @@ +#include "src/core/lib/iomgr/async_execution_lock.h" + +#define NO_CONSUMER ((gpr_atm)1) + +void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue) { + lock->optional_workqueue = optional_workqueue; + gpr_atm_no_barrier_store(&lock->head, NO_CONSUMER); + lock->tail = &lock->stub; + gpr_atm_no_barrier_store(&lock->next, 0); +} + +void grpc_aelock_destroy(grpc_aelock *lock) { + GPR_ASSERT(gpr_atm_no_barrier_load(&lock->head) == NO_CONSUMER); +} + +static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { + for (;;) { + grpc_aelock_qnode *tail = lock->tail; + grpc_aelock_qnode *next = + (grpc_aelock_qnode *)gpr_atm_acq_load(&tail->next); + if (next == NULL) { + if (gpr_atm_rel_cas(&lock->head, (gpr_atm)&lock->stub, NO_CONSUMER)) { + return; + } + } else { + lock->tail = next; + + next->action(exec_ctx, next->arg); + gpr_free(next); + } + } +} + +void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, + grpc_aelock_action action, void *arg, + size_t sizeof_arg) { +retry_top: + gpr_atm cur = gpr_atm_acq_load(&lock->head); + if (cur == NO_CONSUMER) { + if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, (gpr_atm)&lock->stub)) { + goto retry_top; + } + action(exec_ctx, arg); + finish(exec_ctx, lock); + return; // early out + } + + grpc_aelock_qnode *n = gpr_malloc(sizeof(*n) + sizeof_arg); + n->action = action; + gpr_atm_no_barrier_store(&n->next, 0); + if (sizeof_arg > 0) { + memcpy(n + 1, arg, sizeof_arg); + n->arg = n + 1; + } else { + n->arg = arg; + } + while (!gpr_atm_rel_cas(&lock->head, cur, (gpr_atm)n)) { + retry_queue_load: + cur = gpr_atm_acq_load(&lock->head); + if (cur == NO_CONSUMER) { + if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, (gpr_atm)&lock->stub)) { + goto retry_queue_load; + } + gpr_free(n); + action(exec_ctx, arg); + finish(exec_ctx, lock); + return; // early out + } + } + gpr_atm_no_barrier_store(&((grpc_aelock_qnode *)cur)->next, (gpr_atm)n); +} diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h new file mode 100644 index 0000000000..258e06db95 --- /dev/null +++ b/src/core/lib/iomgr/async_execution_lock.h @@ -0,0 +1,58 @@ +/* + * + * 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 AEL_H +#define AEL_H + +typedef void (*grpc_aelock_action)(grpc_exec_ctx *exec_ctx, void *arg); + +typedef struct grpc_aelock_qnode { + grpc_aelock_action action; + void *arg; + gpr_atm next; +} grpc_aelock_qnode; + +typedef struct grpc_aelock { + grpc_workqueue *optional_workqueue; + gpr_atm head; + struct grpc_aelock *tail; + grpc_aelock_qnode stub; +}; + +void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue); +void grpc_aelock_destroy(grpc_aelock *lock); +void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, + grpc_aelock_action action, void *arg, + size_t sizeof_arg); + +#endif -- cgit v1.2.3 From a26637fdca19a6981cf8ea7e1bb0193c6addd2a4 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 13:36:36 -0700 Subject: Add a test and make things compile --- BUILD | 6 + Makefile | 38 ++++ binding.gyp | 1 + build.yaml | 12 ++ config.m4 | 1 + gRPC.podspec | 3 + grpc.gemspec | 2 + package.xml | 2 + src/core/lib/iomgr/async_execution_lock.c | 43 ++++- src/core/lib/iomgr/async_execution_lock.h | 10 +- src/python/grpcio/grpc_core_dependencies.py | 1 + test/core/iomgr/async_execution_lock_test.c | 116 ++++++++++++ tools/doxygen/Doxyfile.core.internal | 2 + tools/run_tests/sources_and_headers.json | 19 ++ tools/run_tests/tests.json | 21 +++ vsprojects/buildtests_c.sln | 27 +++ vsprojects/vcxproj/grpc/grpc.vcxproj | 3 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 6 + .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 3 + .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 + .../async_execution_lock_test.vcxproj | 199 +++++++++++++++++++++ .../async_execution_lock_test.vcxproj.filters | 21 +++ 22 files changed, 538 insertions(+), 4 deletions(-) create mode 100644 test/core/iomgr/async_execution_lock_test.c create mode 100644 vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj create mode 100644 vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj.filters (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index b4b10b535e..ca152583a7 100644 --- a/BUILD +++ b/BUILD @@ -175,6 +175,7 @@ cc_library( "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", + "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", @@ -307,6 +308,7 @@ cc_library( "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", + "src/core/lib/iomgr/async_execution_lock.c", "src/core/lib/iomgr/closure.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", @@ -520,6 +522,7 @@ cc_library( "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", + "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", @@ -639,6 +642,7 @@ cc_library( "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", + "src/core/lib/iomgr/async_execution_lock.c", "src/core/lib/iomgr/closure.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", @@ -1324,6 +1328,7 @@ objc_library( "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", + "src/core/lib/iomgr/async_execution_lock.c", "src/core/lib/iomgr/closure.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", @@ -1516,6 +1521,7 @@ objc_library( "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", + "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", diff --git a/Makefile b/Makefile index 922e0b0568..52c27c97d6 100644 --- a/Makefile +++ b/Makefile @@ -882,6 +882,7 @@ algorithm_test: $(BINDIR)/$(CONFIG)/algorithm_test alloc_test: $(BINDIR)/$(CONFIG)/alloc_test alpn_test: $(BINDIR)/$(CONFIG)/alpn_test api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer +async_execution_lock_test: $(BINDIR)/$(CONFIG)/async_execution_lock_test bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test census_context_test: $(BINDIR)/$(CONFIG)/census_context_test channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test @@ -1218,6 +1219,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/algorithm_test \ $(BINDIR)/$(CONFIG)/alloc_test \ $(BINDIR)/$(CONFIG)/alpn_test \ + $(BINDIR)/$(CONFIG)/async_execution_lock_test \ $(BINDIR)/$(CONFIG)/bin_encoder_test \ $(BINDIR)/$(CONFIG)/census_context_test \ $(BINDIR)/$(CONFIG)/channel_create_test \ @@ -1472,6 +1474,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/alloc_test || ( echo test alloc_test failed ; exit 1 ) $(E) "[RUN] Testing alpn_test" $(Q) $(BINDIR)/$(CONFIG)/alpn_test || ( echo test alpn_test failed ; exit 1 ) + $(E) "[RUN] Testing async_execution_lock_test" + $(Q) $(BINDIR)/$(CONFIG)/async_execution_lock_test || ( echo test async_execution_lock_test failed ; exit 1 ) $(E) "[RUN] Testing bin_encoder_test" $(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 ) $(E) "[RUN] Testing census_context_test" @@ -2491,6 +2495,7 @@ LIBGRPC_SRC = \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ + src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ @@ -2832,6 +2837,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ + src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ @@ -6114,6 +6120,38 @@ endif endif +ASYNC_EXECUTION_LOCK_TEST_SRC = \ + test/core/iomgr/async_execution_lock_test.c \ + +ASYNC_EXECUTION_LOCK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ASYNC_EXECUTION_LOCK_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/async_execution_lock_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/async_execution_lock_test: $(ASYNC_EXECUTION_LOCK_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) $(ASYNC_EXECUTION_LOCK_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)/async_execution_lock_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/async_execution_lock_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_async_execution_lock_test: $(ASYNC_EXECUTION_LOCK_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(ASYNC_EXECUTION_LOCK_TEST_OBJS:.o=.dep) +endif +endif + + BIN_ENCODER_TEST_SRC = \ test/core/transport/chttp2/bin_encoder_test.c \ diff --git a/binding.gyp b/binding.gyp index 4314ab7243..fbec804f7a 100644 --- a/binding.gyp +++ b/binding.gyp @@ -577,6 +577,7 @@ 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', + 'src/core/lib/iomgr/async_execution_lock.c', 'src/core/lib/iomgr/closure.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', diff --git a/build.yaml b/build.yaml index 441752dc3d..aae3e5a242 100644 --- a/build.yaml +++ b/build.yaml @@ -162,6 +162,7 @@ filegroups: - src/core/lib/http/format_request.h - src/core/lib/http/httpcli.h - src/core/lib/http/parser.h + - src/core/lib/iomgr/async_execution_lock.h - src/core/lib/iomgr/closure.h - src/core/lib/iomgr/endpoint.h - src/core/lib/iomgr/endpoint_pair.h @@ -235,6 +236,7 @@ filegroups: - src/core/lib/http/format_request.c - src/core/lib/http/httpcli.c - src/core/lib/http/parser.c + - src/core/lib/iomgr/async_execution_lock.c - src/core/lib/iomgr/closure.c - src/core/lib/iomgr/endpoint.c - src/core/lib/iomgr/endpoint_pair_posix.c @@ -1137,6 +1139,16 @@ targets: - test/core/end2end/fuzzers/api_fuzzer_corpus dict: test/core/end2end/fuzzers/api_fuzzer.dictionary maxlen: 2048 +- name: async_execution_lock_test + build: test + language: c + src: + - test/core/iomgr/async_execution_lock_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr - name: bin_encoder_test build: test language: c diff --git a/config.m4 b/config.m4 index 74f9ad242a..30573cf920 100644 --- a/config.m4 +++ b/config.m4 @@ -96,6 +96,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ + src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ diff --git a/gRPC.podspec b/gRPC.podspec index 77d35bd2c7..a8744c8c70 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -177,6 +177,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/format_request.h', 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', + 'src/core/lib/iomgr/async_execution_lock.h', 'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', @@ -341,6 +342,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', + 'src/core/lib/iomgr/async_execution_lock.c', 'src/core/lib/iomgr/closure.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', @@ -519,6 +521,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/format_request.h', 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', + 'src/core/lib/iomgr/async_execution_lock.h', 'src/core/lib/iomgr/closure.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', diff --git a/grpc.gemspec b/grpc.gemspec index e68cd81da7..fca828ad10 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -185,6 +185,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/http/format_request.h ) s.files += %w( src/core/lib/http/httpcli.h ) s.files += %w( src/core/lib/http/parser.h ) + s.files += %w( src/core/lib/iomgr/async_execution_lock.h ) s.files += %w( src/core/lib/iomgr/closure.h ) s.files += %w( src/core/lib/iomgr/endpoint.h ) s.files += %w( src/core/lib/iomgr/endpoint_pair.h ) @@ -321,6 +322,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/http/format_request.c ) s.files += %w( src/core/lib/http/httpcli.c ) s.files += %w( src/core/lib/http/parser.c ) + s.files += %w( src/core/lib/iomgr/async_execution_lock.c ) s.files += %w( src/core/lib/iomgr/closure.c ) s.files += %w( src/core/lib/iomgr/endpoint.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_posix.c ) diff --git a/package.xml b/package.xml index ffb1c56ed6..d259dd043f 100644 --- a/package.xml +++ b/package.xml @@ -192,6 +192,7 @@ + @@ -328,6 +329,7 @@ + diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c index 20bdf3f9a9..62ece4cc8c 100644 --- a/src/core/lib/iomgr/async_execution_lock.c +++ b/src/core/lib/iomgr/async_execution_lock.c @@ -1,12 +1,50 @@ +/* + * + * 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. + * + */ + #include "src/core/lib/iomgr/async_execution_lock.h" +#include + +#include +#include + #define NO_CONSUMER ((gpr_atm)1) void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue) { lock->optional_workqueue = optional_workqueue; gpr_atm_no_barrier_store(&lock->head, NO_CONSUMER); lock->tail = &lock->stub; - gpr_atm_no_barrier_store(&lock->next, 0); + gpr_atm_no_barrier_store(&lock->stub.next, 0); } void grpc_aelock_destroy(grpc_aelock *lock) { @@ -34,8 +72,9 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, grpc_aelock_action action, void *arg, size_t sizeof_arg) { + gpr_atm cur; retry_top: - gpr_atm cur = gpr_atm_acq_load(&lock->head); + cur = gpr_atm_acq_load(&lock->head); if (cur == NO_CONSUMER) { if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, (gpr_atm)&lock->stub)) { goto retry_top; diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h index 258e06db95..cb4de61349 100644 --- a/src/core/lib/iomgr/async_execution_lock.h +++ b/src/core/lib/iomgr/async_execution_lock.h @@ -34,6 +34,11 @@ #ifndef AEL_H #define AEL_H +#include + +#include +#include "src/core/lib/iomgr/exec_ctx.h" + typedef void (*grpc_aelock_action)(grpc_exec_ctx *exec_ctx, void *arg); typedef struct grpc_aelock_qnode { @@ -44,10 +49,11 @@ typedef struct grpc_aelock_qnode { typedef struct grpc_aelock { grpc_workqueue *optional_workqueue; + // grpc_aelock_qnode* gpr_atm head; - struct grpc_aelock *tail; + grpc_aelock_qnode *tail; grpc_aelock_qnode stub; -}; +} grpc_aelock; void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue); void grpc_aelock_destroy(grpc_aelock *lock); diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index dab62530aa..88db62abb4 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -90,6 +90,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', + 'src/core/lib/iomgr/async_execution_lock.c', 'src/core/lib/iomgr/closure.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', diff --git a/test/core/iomgr/async_execution_lock_test.c b/test/core/iomgr/async_execution_lock_test.c new file mode 100644 index 0000000000..405f89362c --- /dev/null +++ b/test/core/iomgr/async_execution_lock_test.c @@ -0,0 +1,116 @@ +/* + * + * 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. + * + */ + +#include "src/core/lib/iomgr/async_execution_lock.h" + +#include +#include +#include +#include + +#include "test/core/util/test_config.h" + +static void test_no_op(void) { + gpr_log(GPR_DEBUG, "test_no_op"); + + grpc_aelock lock; + grpc_aelock_init(&lock, NULL); + grpc_aelock_destroy(&lock); +} + +static void set_bool_to_true(grpc_exec_ctx *exec_ctx, void *value) { + *(bool *)value = true; +} + +static void test_execute_one(void) { + gpr_log(GPR_DEBUG, "test_execute_one"); + + grpc_aelock lock; + grpc_aelock_init(&lock, NULL); + bool done = false; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_aelock_execute(&exec_ctx, &lock, set_bool_to_true, &done, 0); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(done); + grpc_aelock_destroy(&lock); +} + +typedef struct { + size_t *ctr; + size_t value; +} ex_args; + +static void check_one(grpc_exec_ctx *exec_ctx, void *a) { + ex_args *args = a; + GPR_ASSERT(*args->ctr == args->value - 1); + *args->ctr = args->value; +} + +static void execute_many_loop(void *lock) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + for (size_t i = 0; i < 100; i++) { + size_t ctr = 0; + for (size_t j = 1; j <= 1000; j++) { + ex_args args = {&ctr, j}; + grpc_aelock_execute(&exec_ctx, lock, check_one, &args, sizeof(args)); + grpc_exec_ctx_flush(&exec_ctx); + } + gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(1)); + } +} + +static void test_execute_many(void) { + grpc_aelock lock; + gpr_thd_id thds[100]; + grpc_aelock_init(&lock, NULL); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &lock, &options)); + } + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_join(thds[i]); + } + grpc_aelock_destroy(&lock); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_no_op(); + test_execute_one(); + test_execute_many(); + grpc_shutdown(); + + return 0; +} diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1b1453f7ea..5caaa5a867 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -802,6 +802,7 @@ src/core/lib/debug/trace.h \ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ src/core/lib/http/parser.h \ +src/core/lib/iomgr/async_execution_lock.h \ src/core/lib/iomgr/closure.h \ src/core/lib/iomgr/endpoint.h \ src/core/lib/iomgr/endpoint_pair.h \ @@ -938,6 +939,7 @@ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ +src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index f546f3b995..74c8cce127 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -79,6 +79,22 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "language": "c", + "name": "async_execution_lock_test", + "src": [ + "test/core/iomgr/async_execution_lock_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "grpc", @@ -5606,6 +5622,7 @@ "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", + "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", @@ -5701,6 +5718,8 @@ "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.c", "src/core/lib/http/parser.h", + "src/core/lib/iomgr/async_execution_lock.c", + "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.c", "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/endpoint.c", diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index 0fd77854d2..a07082d996 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -85,6 +85,27 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "async_execution_lock_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, { "args": [], "ci_platforms": [ diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index bdae447545..9c44e0a217 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -160,6 +160,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "alpn_test", "vcxproj\test\a {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "async_execution_lock_test", "vcxproj\test\async_execution_lock_test\async_execution_lock_test.vcxproj", "{5FC080AE-1FE8-2849-6481-E52ADBBC205C}" + 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}") = "bin_encoder_test", "vcxproj\test\bin_encoder_test\bin_encoder_test.vcxproj", "{D5C70922-D68E-0E9D-9988-995E0F9A79AE}" ProjectSection(myProperties) = preProject lib = "False" @@ -1663,6 +1674,22 @@ Global {5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|Win32.Build.0 = Release|Win32 {5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|x64.ActiveCfg = Release|x64 {5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|x64.Build.0 = Release|x64 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug|Win32.ActiveCfg = Debug|Win32 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug|x64.ActiveCfg = Debug|x64 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release|Win32.ActiveCfg = Release|Win32 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release|x64.ActiveCfg = Release|x64 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug|Win32.Build.0 = Debug|Win32 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug|x64.Build.0 = Debug|x64 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release|Win32.Build.0 = Release|Win32 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release|x64.Build.0 = Release|x64 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug-DLL|x64.Build.0 = Debug|x64 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release-DLL|Win32.Build.0 = Release|Win32 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release-DLL|x64.ActiveCfg = Release|x64 + {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release-DLL|x64.Build.0 = Release|x64 {D5C70922-D68E-0E9D-9988-995E0F9A79AE}.Debug|Win32.ActiveCfg = Debug|Win32 {D5C70922-D68E-0E9D-9988-995E0F9A79AE}.Debug|x64.ActiveCfg = Debug|x64 {D5C70922-D68E-0E9D-9988-995E0F9A79AE}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 4eec05a3b1..b977a7fc5f 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -311,6 +311,7 @@ + @@ -463,6 +464,8 @@ + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 17c88c4805..c1f2bd9a16 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -43,6 +43,9 @@ src\core\lib\http + + src\core\lib\iomgr + src\core\lib\iomgr @@ -626,6 +629,9 @@ src\core\lib\http + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 26050dcf74..93a2327841 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -300,6 +300,7 @@ + @@ -440,6 +441,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index a4acf513bc..f18700ca58 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -46,6 +46,9 @@ src\core\lib\http + + src\core\lib\iomgr + src\core\lib\iomgr @@ -560,6 +563,9 @@ src\core\lib\http + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj b/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj new file mode 100644 index 0000000000..92b277801e --- /dev/null +++ b/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj @@ -0,0 +1,199 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {5FC080AE-1FE8-2849-6481-E52ADBBC205C} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + async_execution_lock_test + static + Debug + static + Debug + + + async_execution_lock_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + 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}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj.filters b/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj.filters new file mode 100644 index 0000000000..ff116cb9b0 --- /dev/null +++ b/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\iomgr + + + + + + {1553c040-57a4-1c71-539f-06be026b4844} + + + {112c4757-8861-21ed-d535-83c90a22e14b} + + + {341d4313-1479-2a6a-8ba4-a44c4c15e0d7} + + + + -- cgit v1.2.3 From 2743ba94f978aacb0db4bf900bd048479a8806ac Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 16:44:20 -0700 Subject: Almost working... --- src/core/lib/iomgr/async_execution_lock.c | 64 ++++++++++++++++++++--------- src/core/lib/iomgr/async_execution_lock.h | 2 +- test/core/iomgr/async_execution_lock_test.c | 29 +++++++++---- 3 files changed, 67 insertions(+), 28 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c index 62ece4cc8c..71608b2bfe 100644 --- a/src/core/lib/iomgr/async_execution_lock.c +++ b/src/core/lib/iomgr/async_execution_lock.c @@ -40,11 +40,16 @@ #define NO_CONSUMER ((gpr_atm)1) +static void bad_action(grpc_exec_ctx *exec_ctx, void *arg) { + GPR_UNREACHABLE_CODE(return ); +} + void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue) { lock->optional_workqueue = optional_workqueue; gpr_atm_no_barrier_store(&lock->head, NO_CONSUMER); - lock->tail = &lock->stub; - gpr_atm_no_barrier_store(&lock->stub.next, 0); + gpr_atm_no_barrier_store(&lock->tombstone.next, 0); + lock->tombstone.action = bad_action; + lock->tail = &lock->tombstone; } void grpc_aelock_destroy(grpc_aelock *lock) { @@ -56,15 +61,35 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { grpc_aelock_qnode *tail = lock->tail; grpc_aelock_qnode *next = (grpc_aelock_qnode *)gpr_atm_acq_load(&tail->next); - if (next == NULL) { - if (gpr_atm_rel_cas(&lock->head, (gpr_atm)&lock->stub, NO_CONSUMER)) { - return; + if (tail == &lock->tombstone) { + if (next == NULL) { + if (gpr_atm_rel_cas(&lock->head, (gpr_atm)&lock->tombstone, + NO_CONSUMER)) { + return; + } + } else { + lock->tail = next; + tail = next; + next = (grpc_aelock_qnode *)gpr_atm_acq_load(&tail->next); } - } else { + } + if (next != NULL) { lock->tail = next; - - next->action(exec_ctx, next->arg); - gpr_free(next); + tail->action(exec_ctx, tail->arg); + gpr_free(tail); + } else { + grpc_aelock_qnode *head = + (grpc_aelock_qnode *)gpr_atm_acq_load(&lock->head); + if (head != tail) { + // TODO(ctiller): consider sleeping? + continue; + } + gpr_atm_no_barrier_store(&lock->tombstone.next, 0); + while (!gpr_atm_rel_cas(&lock->head, (gpr_atm)head, + (gpr_atm)&lock->tombstone)) { + head = (grpc_aelock_qnode *)gpr_atm_acq_load(&lock->head); + } + gpr_atm_rel_store(&head->next, (gpr_atm)&lock->tombstone); } } } @@ -72,11 +97,11 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, grpc_aelock_action action, void *arg, size_t sizeof_arg) { - gpr_atm cur; + gpr_atm head; retry_top: - cur = gpr_atm_acq_load(&lock->head); - if (cur == NO_CONSUMER) { - if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, (gpr_atm)&lock->stub)) { + head = gpr_atm_acq_load(&lock->head); + if (head == NO_CONSUMER) { + if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, (gpr_atm)&lock->tombstone)) { goto retry_top; } action(exec_ctx, arg); @@ -86,18 +111,19 @@ retry_top: grpc_aelock_qnode *n = gpr_malloc(sizeof(*n) + sizeof_arg); n->action = action; - gpr_atm_no_barrier_store(&n->next, 0); if (sizeof_arg > 0) { memcpy(n + 1, arg, sizeof_arg); n->arg = n + 1; } else { n->arg = arg; } - while (!gpr_atm_rel_cas(&lock->head, cur, (gpr_atm)n)) { + gpr_atm_no_barrier_store(&n->next, 0); + while (!gpr_atm_rel_cas(&lock->head, head, (gpr_atm)n)) { retry_queue_load: - cur = gpr_atm_acq_load(&lock->head); - if (cur == NO_CONSUMER) { - if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, (gpr_atm)&lock->stub)) { + head = gpr_atm_acq_load(&lock->head); + if (head == NO_CONSUMER) { + if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, + (gpr_atm)&lock->tombstone)) { goto retry_queue_load; } gpr_free(n); @@ -106,5 +132,5 @@ retry_top: return; // early out } } - gpr_atm_no_barrier_store(&((grpc_aelock_qnode *)cur)->next, (gpr_atm)n); + gpr_atm_rel_store(&((grpc_aelock_qnode *)head)->next, (gpr_atm)n); } diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h index cb4de61349..cd1c4811fe 100644 --- a/src/core/lib/iomgr/async_execution_lock.h +++ b/src/core/lib/iomgr/async_execution_lock.h @@ -52,7 +52,7 @@ typedef struct grpc_aelock { // grpc_aelock_qnode* gpr_atm head; grpc_aelock_qnode *tail; - grpc_aelock_qnode stub; + grpc_aelock_qnode tombstone; } grpc_aelock; void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue); diff --git a/test/core/iomgr/async_execution_lock_test.c b/test/core/iomgr/async_execution_lock_test.c index 405f89362c..d7f1823412 100644 --- a/test/core/iomgr/async_execution_lock_test.c +++ b/test/core/iomgr/async_execution_lock_test.c @@ -65,6 +65,11 @@ static void test_execute_one(void) { grpc_aelock_destroy(&lock); } +typedef struct { + size_t ctr; + grpc_aelock *lock; +} thd_args; + typedef struct { size_t *ctr; size_t value; @@ -72,31 +77,39 @@ typedef struct { static void check_one(grpc_exec_ctx *exec_ctx, void *a) { ex_args *args = a; + // gpr_log(GPR_DEBUG, "*%p=%d; step %d", args->ctr, *args->ctr, args->value); GPR_ASSERT(*args->ctr == args->value - 1); *args->ctr = args->value; } -static void execute_many_loop(void *lock) { +static void execute_many_loop(void *a) { + thd_args *args = a; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - for (size_t i = 0; i < 100; i++) { - size_t ctr = 0; - for (size_t j = 1; j <= 1000; j++) { - ex_args args = {&ctr, j}; - grpc_aelock_execute(&exec_ctx, lock, check_one, &args, sizeof(args)); + size_t n = 1; + for (size_t i = 0; i < 10; i++) { + for (size_t j = 0; j < 1000; j++) { + ex_args c = {&args->ctr, n++}; + grpc_aelock_execute(&exec_ctx, args->lock, check_one, &c, sizeof(c)); grpc_exec_ctx_flush(&exec_ctx); } - gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(1)); + gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); } + grpc_exec_ctx_finish(&exec_ctx); } static void test_execute_many(void) { + gpr_log(GPR_DEBUG, "test_execute_many"); + grpc_aelock lock; gpr_thd_id thds[100]; + thd_args ta[GPR_ARRAY_SIZE(thds)]; grpc_aelock_init(&lock, NULL); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); - GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &lock, &options)); + ta[i].ctr = 0; + ta[i].lock = &lock; + GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &ta[i], &options)); } for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_join(thds[i]); -- cgit v1.2.3 From dfbb1c080aa22e1f39cd934e1dc731ee4c74100b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 20:48:46 -0700 Subject: Almost working...... --- src/core/lib/iomgr/async_execution_lock.c | 12 ++++++++++-- test/core/iomgr/async_execution_lock_test.c | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c index 71608b2bfe..00cd27504b 100644 --- a/src/core/lib/iomgr/async_execution_lock.c +++ b/src/core/lib/iomgr/async_execution_lock.c @@ -67,23 +67,30 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { NO_CONSUMER)) { return; } + // TODO(ctiller): consider sleeping + continue; } else { + // skip the tombstone: we'll re-add it later lock->tail = next; tail = next; next = (grpc_aelock_qnode *)gpr_atm_acq_load(&tail->next); } } if (next != NULL) { + // found a node lock->tail = next; tail->action(exec_ctx, tail->arg); gpr_free(tail); } else { + // nothing there: might be in an incosistant state grpc_aelock_qnode *head = (grpc_aelock_qnode *)gpr_atm_acq_load(&lock->head); if (head != tail) { + // non-empty list: spin for a bit // TODO(ctiller): consider sleeping? continue; } + // must have swallowed tombstone above: re-add it gpr_atm_no_barrier_store(&lock->tombstone.next, 0); while (!gpr_atm_rel_cas(&lock->head, (gpr_atm)head, (gpr_atm)&lock->tombstone)) { @@ -117,7 +124,7 @@ retry_top: } else { n->arg = arg; } - gpr_atm_no_barrier_store(&n->next, 0); + gpr_atm_rel_store(&n->next, 0); while (!gpr_atm_rel_cas(&lock->head, head, (gpr_atm)n)) { retry_queue_load: head = gpr_atm_acq_load(&lock->head); @@ -132,5 +139,6 @@ retry_top: return; // early out } } - gpr_atm_rel_store(&((grpc_aelock_qnode *)head)->next, (gpr_atm)n); + GPR_ASSERT(gpr_atm_rel_cas(&((grpc_aelock_qnode *)head)->next, 0, (gpr_atm)n)); +// gpr_atm_rel_store(&((grpc_aelock_qnode *)head)->next, (gpr_atm)n); } diff --git a/test/core/iomgr/async_execution_lock_test.c b/test/core/iomgr/async_execution_lock_test.c index d7f1823412..8c9665a458 100644 --- a/test/core/iomgr/async_execution_lock_test.c +++ b/test/core/iomgr/async_execution_lock_test.c @@ -87,7 +87,7 @@ static void execute_many_loop(void *a) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; size_t n = 1; for (size_t i = 0; i < 10; i++) { - for (size_t j = 0; j < 1000; j++) { + for (size_t j = 0; j < 10000; j++) { ex_args c = {&args->ctr, n++}; grpc_aelock_execute(&exec_ctx, args->lock, check_one, &c, sizeof(c)); grpc_exec_ctx_flush(&exec_ctx); -- cgit v1.2.3 From 0bc11711b7f2f33bd4e399bda46e4c20ac4bc6ca Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 21:22:46 -0700 Subject: Direct translation of http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue --- BUILD | 6 ++- Makefile | 2 +- binding.gyp | 2 +- build.yaml | 3 +- config.m4 | 2 +- gRPC.podspec | 4 +- grpc.gemspec | 3 +- include/grpc/impl/codegen/atm.h | 3 ++ include/grpc/impl/codegen/atm_gcc_atomic.h | 2 + include/grpc/impl/codegen/atm_gcc_sync.h | 7 +++ include/grpc/impl/codegen/atm_win32.h | 4 ++ package.xml | 3 +- src/core/lib/support/mpscq.c | 80 +++++++++++++++++++++++++++++ src/core/lib/support/mpscq.h | 55 ++++++++++++++++++++ src/python/grpcio/grpc_core_dependencies.py | 2 +- tools/doxygen/Doxyfile.core.internal | 3 +- tools/run_tests/sources_and_headers.json | 4 +- vsprojects/vcxproj/gpr/gpr.vcxproj | 5 +- vsprojects/vcxproj/gpr/gpr.vcxproj.filters | 9 ++-- 19 files changed, 182 insertions(+), 17 deletions(-) create mode 100644 src/core/lib/support/mpscq.c create mode 100644 src/core/lib/support/mpscq.h (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index ca152583a7..bd00ff670f 100644 --- a/BUILD +++ b/BUILD @@ -50,6 +50,7 @@ cc_library( "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", "src/core/lib/support/load_file.h", + "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/stack_lockfree.h", "src/core/lib/support/string.h", @@ -78,10 +79,10 @@ cc_library( "src/core/lib/support/log_linux.c", "src/core/lib/support/log_posix.c", "src/core/lib/support/log_win32.c", + "src/core/lib/support/mpscq.c", "src/core/lib/support/murmur_hash.c", "src/core/lib/support/slice.c", "src/core/lib/support/slice_buffer.c", - "src/core/lib/support/stack_lockfree.c", "src/core/lib/support/string.c", "src/core/lib/support/string_posix.c", "src/core/lib/support/string_util_win32.c", @@ -1219,10 +1220,10 @@ objc_library( "src/core/lib/support/log_linux.c", "src/core/lib/support/log_posix.c", "src/core/lib/support/log_win32.c", + "src/core/lib/support/mpscq.c", "src/core/lib/support/murmur_hash.c", "src/core/lib/support/slice.c", "src/core/lib/support/slice_buffer.c", - "src/core/lib/support/stack_lockfree.c", "src/core/lib/support/string.c", "src/core/lib/support/string_posix.c", "src/core/lib/support/string_util_win32.c", @@ -1293,6 +1294,7 @@ objc_library( "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", "src/core/lib/support/load_file.h", + "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/stack_lockfree.h", "src/core/lib/support/string.h", diff --git a/Makefile b/Makefile index 52c27c97d6..50efcf349f 100644 --- a/Makefile +++ b/Makefile @@ -2348,10 +2348,10 @@ LIBGPR_SRC = \ src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_win32.c \ + src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/slice.c \ src/core/lib/support/slice_buffer.c \ - src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ src/core/lib/support/string_util_win32.c \ diff --git a/binding.gyp b/binding.gyp index fbec804f7a..ccd811a30b 100644 --- a/binding.gyp +++ b/binding.gyp @@ -516,10 +516,10 @@ 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_win32.c', + 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/slice.c', 'src/core/lib/support/slice_buffer.c', - 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_util_win32.c', diff --git a/build.yaml b/build.yaml index aae3e5a242..e6f263aef7 100644 --- a/build.yaml +++ b/build.yaml @@ -68,6 +68,7 @@ filegroups: - src/core/lib/support/block_annotate.h - src/core/lib/support/env.h - src/core/lib/support/load_file.h + - src/core/lib/support/mpscq.h - src/core/lib/support/murmur_hash.h - src/core/lib/support/stack_lockfree.h - src/core/lib/support/string.h @@ -97,10 +98,10 @@ filegroups: - src/core/lib/support/log_linux.c - src/core/lib/support/log_posix.c - src/core/lib/support/log_win32.c + - src/core/lib/support/mpscq.c - src/core/lib/support/murmur_hash.c - src/core/lib/support/slice.c - src/core/lib/support/slice_buffer.c - - src/core/lib/support/stack_lockfree.c - src/core/lib/support/string.c - src/core/lib/support/string_posix.c - src/core/lib/support/string_util_win32.c diff --git a/config.m4 b/config.m4 index 30573cf920..9ec7f493da 100644 --- a/config.m4 +++ b/config.m4 @@ -57,10 +57,10 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_win32.c \ + src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/slice.c \ src/core/lib/support/slice_buffer.c \ - src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ src/core/lib/support/string_util_win32.c \ diff --git a/gRPC.podspec b/gRPC.podspec index a8744c8c70..3df13f9f42 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -68,6 +68,7 @@ Pod::Spec.new do |s| 'src/core/lib/support/block_annotate.h', 'src/core/lib/support/env.h', 'src/core/lib/support/load_file.h', + 'src/core/lib/support/mpscq.h', 'src/core/lib/support/murmur_hash.h', 'src/core/lib/support/stack_lockfree.h', 'src/core/lib/support/string.h', @@ -138,10 +139,10 @@ Pod::Spec.new do |s| 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_win32.c', + 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/slice.c', 'src/core/lib/support/slice_buffer.c', - 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_util_win32.c', @@ -500,6 +501,7 @@ Pod::Spec.new do |s| 'src/core/lib/support/block_annotate.h', 'src/core/lib/support/env.h', 'src/core/lib/support/load_file.h', + 'src/core/lib/support/mpscq.h', 'src/core/lib/support/murmur_hash.h', 'src/core/lib/support/stack_lockfree.h', 'src/core/lib/support/string.h', diff --git a/grpc.gemspec b/grpc.gemspec index fca828ad10..2aad578a26 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -90,6 +90,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/support/block_annotate.h ) s.files += %w( src/core/lib/support/env.h ) s.files += %w( src/core/lib/support/load_file.h ) + s.files += %w( src/core/lib/support/mpscq.h ) s.files += %w( src/core/lib/support/murmur_hash.h ) s.files += %w( src/core/lib/support/stack_lockfree.h ) s.files += %w( src/core/lib/support/string.h ) @@ -118,10 +119,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/support/log_linux.c ) s.files += %w( src/core/lib/support/log_posix.c ) s.files += %w( src/core/lib/support/log_win32.c ) + s.files += %w( src/core/lib/support/mpscq.c ) s.files += %w( src/core/lib/support/murmur_hash.c ) s.files += %w( src/core/lib/support/slice.c ) s.files += %w( src/core/lib/support/slice_buffer.c ) - s.files += %w( src/core/lib/support/stack_lockfree.c ) s.files += %w( src/core/lib/support/string.c ) s.files += %w( src/core/lib/support/string_posix.c ) s.files += %w( src/core/lib/support/string_util_win32.c ) diff --git a/include/grpc/impl/codegen/atm.h b/include/grpc/impl/codegen/atm.h index 5376026dde..6f7618b800 100644 --- a/include/grpc/impl/codegen/atm.h +++ b/include/grpc/impl/codegen/atm.h @@ -75,6 +75,9 @@ int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n); int gpr_atm_acq_cas(gpr_atm *p, gpr_atm o, gpr_atm n); int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n); + + // Atomically, set *p=n and return the old value of *p + gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n); */ #include diff --git a/include/grpc/impl/codegen/atm_gcc_atomic.h b/include/grpc/impl/codegen/atm_gcc_atomic.h index 8caf7edbde..7d4ae98cf7 100644 --- a/include/grpc/impl/codegen/atm_gcc_atomic.h +++ b/include/grpc/impl/codegen/atm_gcc_atomic.h @@ -69,4 +69,6 @@ static __inline int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { __ATOMIC_RELAXED); } +#define gpr_atm_full_xchg(p, n) __atomic_exchange_n((p), (n), __ATOMIC_ACQ_REL) + #endif /* GRPC_IMPL_CODEGEN_ATM_GCC_ATOMIC_H */ diff --git a/include/grpc/impl/codegen/atm_gcc_sync.h b/include/grpc/impl/codegen/atm_gcc_sync.h index 915b09fb0c..86ce2f2548 100644 --- a/include/grpc/impl/codegen/atm_gcc_sync.h +++ b/include/grpc/impl/codegen/atm_gcc_sync.h @@ -84,4 +84,11 @@ static __inline void gpr_atm_no_barrier_store(gpr_atm *p, gpr_atm value) { #define gpr_atm_acq_cas(p, o, n) (__sync_bool_compare_and_swap((p), (o), (n))) #define gpr_atm_rel_cas(p, o, n) gpr_atm_acq_cas((p), (o), (n)) +static __inline gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n) { + gpr_atm cur; + do { + cur = gpr_atm_acq_load(p); + } while (!gpr_atm_rel_cas(p, cur, n)); +} + #endif /* GRPC_IMPL_CODEGEN_ATM_GCC_SYNC_H */ diff --git a/include/grpc/impl/codegen/atm_win32.h b/include/grpc/impl/codegen/atm_win32.h index 7c1ccaf8e2..2904007d63 100644 --- a/include/grpc/impl/codegen/atm_win32.h +++ b/include/grpc/impl/codegen/atm_win32.h @@ -122,4 +122,8 @@ static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm *p, gpr_atm delta) { return old; } +static __inline gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n) { + return (gpr_atm)InterlockedExchangePointer((PVOID*)p, (PVOID)n); +} + #endif /* GRPC_IMPL_CODEGEN_ATM_WIN32_H */ diff --git a/package.xml b/package.xml index d259dd043f..ee2468bc87 100644 --- a/package.xml +++ b/package.xml @@ -97,6 +97,7 @@ + @@ -125,10 +126,10 @@ + - diff --git a/src/core/lib/support/mpscq.c b/src/core/lib/support/mpscq.c new file mode 100644 index 0000000000..911fdd161c --- /dev/null +++ b/src/core/lib/support/mpscq.c @@ -0,0 +1,80 @@ +/* + * + * 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/lib/support/mpscq.h" + +#include + +void gpr_mpscq_init(gpr_mpscq *q) { + gpr_atm_no_barrier_store(&q->head, (gpr_atm)&q->stub); + q->tail = &q->stub; + gpr_atm_no_barrier_store(&q->stub.next, 0); +} + +void gpr_mpscq_destroy(gpr_mpscq *q) { + GPR_ASSERT(gpr_atm_no_barrier_load(&q->head) == (gpr_atm)&q->stub); + GPR_ASSERT(q->tail == &q->stub); +} + +void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n) { + gpr_atm_no_barrier_store(&n->next, 0); + gpr_mpscq_node *prev = (gpr_mpscq_node*)gpr_atm_full_xchg(&q->head, (gpr_atm)n); + gpr_atm_rel_store(&prev->next, (gpr_atm)n); +} + +gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { + gpr_mpscq_node *tail = q->tail; + gpr_mpscq_node *next = (gpr_mpscq_node*)gpr_atm_acq_load(&tail->next); + if (tail == &q->stub) { + if (next == NULL) return NULL; + q->tail = next; + tail = next; + next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); + } + if (next != NULL) { + q->tail = next; + return tail; + } + gpr_mpscq_node *head = (gpr_mpscq_node*)gpr_atm_acq_load(&q->head); + if (tail != head) { + return 0; + } + gpr_mpscq_push(q, &q->stub); + next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); + if (next != NULL) { + q->tail = next; + return tail; + } + return NULL; +} + diff --git a/src/core/lib/support/mpscq.h b/src/core/lib/support/mpscq.h new file mode 100644 index 0000000000..30b37a94a1 --- /dev/null +++ b/src/core/lib/support/mpscq.h @@ -0,0 +1,55 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SUPPORT_MPSCQ_H +#define GRPC_CORE_LIB_SUPPORT_MPSCQ_H + +#include +#include + +typedef struct gpr_mpscq_node { + gpr_atm next; +} gpr_mpscq_node; + +typedef struct gpr_mpscq { + gpr_atm head; + gpr_mpscq_node *tail; + gpr_mpscq_node stub; +} gpr_mpscq; + +void gpr_mpscq_init(gpr_mpscq *q); +void gpr_mpscq_destroy(gpr_mpscq *q); +void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n); +gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q); + +#endif /* GRPC_CORE_LIB_SUPPORT_MPSCQ_H */ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 88db62abb4..58425a7a29 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -51,10 +51,10 @@ CORE_SOURCE_FILES = [ 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_win32.c', + 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/slice.c', 'src/core/lib/support/slice_buffer.c', - 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_util_win32.c', diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 5caaa5a867..534775e6cd 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1138,6 +1138,7 @@ src/core/lib/support/backoff.h \ src/core/lib/support/block_annotate.h \ src/core/lib/support/env.h \ src/core/lib/support/load_file.h \ +src/core/lib/support/mpscq.h \ src/core/lib/support/murmur_hash.h \ src/core/lib/support/stack_lockfree.h \ src/core/lib/support/string.h \ @@ -1166,10 +1167,10 @@ src/core/lib/support/log_android.c \ src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_win32.c \ +src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/slice.c \ src/core/lib/support/slice_buffer.c \ -src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ src/core/lib/support/string_util_win32.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 74c8cce127..2b042b7e08 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -5457,6 +5457,7 @@ "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", "src/core/lib/support/load_file.h", + "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/stack_lockfree.h", "src/core/lib/support/string.h", @@ -5522,11 +5523,12 @@ "src/core/lib/support/log_linux.c", "src/core/lib/support/log_posix.c", "src/core/lib/support/log_win32.c", + "src/core/lib/support/mpscq.c", + "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.c", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/slice.c", "src/core/lib/support/slice_buffer.c", - "src/core/lib/support/stack_lockfree.c", "src/core/lib/support/stack_lockfree.h", "src/core/lib/support/string.c", "src/core/lib/support/string.h", diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index 26195bb541..43fa41324d 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -196,6 +196,7 @@ + @@ -247,14 +248,14 @@ + + - - diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index be15391b09..80c6ac7b55 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -64,6 +64,9 @@ src\core\lib\support + + src\core\lib\support + src\core\lib\support @@ -73,9 +76,6 @@ src\core\lib\support - - src\core\lib\support - src\core\lib\support @@ -284,6 +284,9 @@ src\core\lib\support + + src\core\lib\support + src\core\lib\support -- cgit v1.2.3 From ad3c8c1a5d56fac6b91d8f4fec50145d91721b63 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 21:47:30 -0700 Subject: Rewrite async_exec_lock using mpscq --- BUILD | 2 + Makefile | 1 + binding.gyp | 1 + build.yaml | 1 + config.m4 | 1 + gRPC.podspec | 1 + grpc.gemspec | 1 + package.xml | 1 + src/core/lib/iomgr/async_execution_lock.c | 103 ++++++---------------------- src/core/lib/iomgr/async_execution_lock.h | 11 ++- src/python/grpcio/grpc_core_dependencies.py | 1 + tools/doxygen/Doxyfile.core.internal | 1 + tools/run_tests/sources_and_headers.json | 1 + vsprojects/vcxproj/gpr/gpr.vcxproj | 2 + vsprojects/vcxproj/gpr/gpr.vcxproj.filters | 3 + 15 files changed, 43 insertions(+), 88 deletions(-) (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index bd00ff670f..5dc0d86abe 100644 --- a/BUILD +++ b/BUILD @@ -83,6 +83,7 @@ cc_library( "src/core/lib/support/murmur_hash.c", "src/core/lib/support/slice.c", "src/core/lib/support/slice_buffer.c", + "src/core/lib/support/stack_lockfree.c", "src/core/lib/support/string.c", "src/core/lib/support/string_posix.c", "src/core/lib/support/string_util_win32.c", @@ -1224,6 +1225,7 @@ objc_library( "src/core/lib/support/murmur_hash.c", "src/core/lib/support/slice.c", "src/core/lib/support/slice_buffer.c", + "src/core/lib/support/stack_lockfree.c", "src/core/lib/support/string.c", "src/core/lib/support/string_posix.c", "src/core/lib/support/string_util_win32.c", diff --git a/Makefile b/Makefile index 50efcf349f..319f483e75 100644 --- a/Makefile +++ b/Makefile @@ -2352,6 +2352,7 @@ LIBGPR_SRC = \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/slice.c \ src/core/lib/support/slice_buffer.c \ + src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ src/core/lib/support/string_util_win32.c \ diff --git a/binding.gyp b/binding.gyp index ccd811a30b..9d04eb971a 100644 --- a/binding.gyp +++ b/binding.gyp @@ -520,6 +520,7 @@ 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/slice.c', 'src/core/lib/support/slice_buffer.c', + 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_util_win32.c', diff --git a/build.yaml b/build.yaml index e6f263aef7..addb91fcce 100644 --- a/build.yaml +++ b/build.yaml @@ -102,6 +102,7 @@ filegroups: - src/core/lib/support/murmur_hash.c - src/core/lib/support/slice.c - src/core/lib/support/slice_buffer.c + - src/core/lib/support/stack_lockfree.c - src/core/lib/support/string.c - src/core/lib/support/string_posix.c - src/core/lib/support/string_util_win32.c diff --git a/config.m4 b/config.m4 index 9ec7f493da..67ce4944ef 100644 --- a/config.m4 +++ b/config.m4 @@ -61,6 +61,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/support/murmur_hash.c \ src/core/lib/support/slice.c \ src/core/lib/support/slice_buffer.c \ + src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ src/core/lib/support/string_util_win32.c \ diff --git a/gRPC.podspec b/gRPC.podspec index 3df13f9f42..f995e8ad65 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -143,6 +143,7 @@ Pod::Spec.new do |s| 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/slice.c', 'src/core/lib/support/slice_buffer.c', + 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_util_win32.c', diff --git a/grpc.gemspec b/grpc.gemspec index 2aad578a26..de488d6f44 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -123,6 +123,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/support/murmur_hash.c ) s.files += %w( src/core/lib/support/slice.c ) s.files += %w( src/core/lib/support/slice_buffer.c ) + s.files += %w( src/core/lib/support/stack_lockfree.c ) s.files += %w( src/core/lib/support/string.c ) s.files += %w( src/core/lib/support/string_posix.c ) s.files += %w( src/core/lib/support/string_util_win32.c ) diff --git a/package.xml b/package.xml index ee2468bc87..169d047a08 100644 --- a/package.xml +++ b/package.xml @@ -130,6 +130,7 @@ + diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c index 00cd27504b..b6b7e0d92c 100644 --- a/src/core/lib/iomgr/async_execution_lock.c +++ b/src/core/lib/iomgr/async_execution_lock.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,105 +40,44 @@ #define NO_CONSUMER ((gpr_atm)1) -static void bad_action(grpc_exec_ctx *exec_ctx, void *arg) { - GPR_UNREACHABLE_CODE(return ); -} - void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue) { lock->optional_workqueue = optional_workqueue; - gpr_atm_no_barrier_store(&lock->head, NO_CONSUMER); - gpr_atm_no_barrier_store(&lock->tombstone.next, 0); - lock->tombstone.action = bad_action; - lock->tail = &lock->tombstone; + gpr_atm_no_barrier_store(&lock->locked, 0); + gpr_mpscq_init(&lock->queue); } void grpc_aelock_destroy(grpc_aelock *lock) { - GPR_ASSERT(gpr_atm_no_barrier_load(&lock->head) == NO_CONSUMER); + GPR_ASSERT(gpr_atm_no_barrier_load(&lock->locked) == 0); + gpr_mpscq_destroy(&lock->queue); } static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { - for (;;) { - grpc_aelock_qnode *tail = lock->tail; - grpc_aelock_qnode *next = - (grpc_aelock_qnode *)gpr_atm_acq_load(&tail->next); - if (tail == &lock->tombstone) { - if (next == NULL) { - if (gpr_atm_rel_cas(&lock->head, (gpr_atm)&lock->tombstone, - NO_CONSUMER)) { - return; - } - // TODO(ctiller): consider sleeping - continue; - } else { - // skip the tombstone: we'll re-add it later - lock->tail = next; - tail = next; - next = (grpc_aelock_qnode *)gpr_atm_acq_load(&tail->next); - } - } - if (next != NULL) { - // found a node - lock->tail = next; - tail->action(exec_ctx, tail->arg); - gpr_free(tail); - } else { - // nothing there: might be in an incosistant state - grpc_aelock_qnode *head = - (grpc_aelock_qnode *)gpr_atm_acq_load(&lock->head); - if (head != tail) { - // non-empty list: spin for a bit - // TODO(ctiller): consider sleeping? - continue; - } - // must have swallowed tombstone above: re-add it - gpr_atm_no_barrier_store(&lock->tombstone.next, 0); - while (!gpr_atm_rel_cas(&lock->head, (gpr_atm)head, - (gpr_atm)&lock->tombstone)) { - head = (grpc_aelock_qnode *)gpr_atm_acq_load(&lock->head); - } - gpr_atm_rel_store(&head->next, (gpr_atm)&lock->tombstone); + while (gpr_atm_full_fetch_add(&lock->locked, -1) != 1) { + gpr_mpscq_node *n; + while ((n = gpr_mpscq_pop(&lock->queue)) == NULL) { + // TODO(ctiller): find something to fill in the time } + grpc_aelock_qnode *ln = (grpc_aelock_qnode*)n; + ln->action(exec_ctx, ln->arg); + gpr_free(ln); } } void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, grpc_aelock_action action, void *arg, size_t sizeof_arg) { - gpr_atm head; -retry_top: - head = gpr_atm_acq_load(&lock->head); - if (head == NO_CONSUMER) { - if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, (gpr_atm)&lock->tombstone)) { - goto retry_top; - } + if (gpr_atm_full_fetch_add(&lock->locked, 1) == 0) { action(exec_ctx, arg); finish(exec_ctx, lock); - return; // early out - } - - grpc_aelock_qnode *n = gpr_malloc(sizeof(*n) + sizeof_arg); - n->action = action; - if (sizeof_arg > 0) { - memcpy(n + 1, arg, sizeof_arg); - n->arg = n + 1; } else { - n->arg = arg; - } - gpr_atm_rel_store(&n->next, 0); - while (!gpr_atm_rel_cas(&lock->head, head, (gpr_atm)n)) { - retry_queue_load: - head = gpr_atm_acq_load(&lock->head); - if (head == NO_CONSUMER) { - if (!gpr_atm_rel_cas(&lock->head, NO_CONSUMER, - (gpr_atm)&lock->tombstone)) { - goto retry_queue_load; - } - gpr_free(n); - action(exec_ctx, arg); - finish(exec_ctx, lock); - return; // early out + grpc_aelock_qnode *n = gpr_malloc(sizeof(*n) + sizeof_arg); + n->action = action; + if (sizeof_arg > 0) { + memcpy(n + 1, arg, sizeof_arg); + n->arg = n + 1; + } else { + n->arg = arg; } + gpr_mpscq_push(&lock->queue, &n->mpscq_node); } - GPR_ASSERT(gpr_atm_rel_cas(&((grpc_aelock_qnode *)head)->next, 0, (gpr_atm)n)); -// gpr_atm_rel_store(&((grpc_aelock_qnode *)head)->next, (gpr_atm)n); } diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h index cd1c4811fe..20cbcaf2e1 100644 --- a/src/core/lib/iomgr/async_execution_lock.h +++ b/src/core/lib/iomgr/async_execution_lock.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,22 +37,21 @@ #include #include +#include "src/core/lib/support/mpscq.h" #include "src/core/lib/iomgr/exec_ctx.h" typedef void (*grpc_aelock_action)(grpc_exec_ctx *exec_ctx, void *arg); typedef struct grpc_aelock_qnode { + gpr_mpscq_node mpscq_node; grpc_aelock_action action; void *arg; - gpr_atm next; } grpc_aelock_qnode; typedef struct grpc_aelock { grpc_workqueue *optional_workqueue; - // grpc_aelock_qnode* - gpr_atm head; - grpc_aelock_qnode *tail; - grpc_aelock_qnode tombstone; + gpr_mpscq queue; + gpr_atm locked; } grpc_aelock; void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue); diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 58425a7a29..c843ed4062 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -55,6 +55,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/slice.c', 'src/core/lib/support/slice_buffer.c', + 'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/string.c', 'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_util_win32.c', diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 534775e6cd..4add517477 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1171,6 +1171,7 @@ src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/slice.c \ src/core/lib/support/slice_buffer.c \ +src/core/lib/support/stack_lockfree.c \ src/core/lib/support/string.c \ src/core/lib/support/string_posix.c \ src/core/lib/support/string_util_win32.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 2b042b7e08..4369771170 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -5529,6 +5529,7 @@ "src/core/lib/support/murmur_hash.h", "src/core/lib/support/slice.c", "src/core/lib/support/slice_buffer.c", + "src/core/lib/support/stack_lockfree.c", "src/core/lib/support/stack_lockfree.h", "src/core/lib/support/string.c", "src/core/lib/support/string.h", diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index 43fa41324d..1a67cb9f61 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -256,6 +256,8 @@ + + diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index 80c6ac7b55..c2d6b51c5b 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -76,6 +76,9 @@ src\core\lib\support + + src\core\lib\support + src\core\lib\support -- cgit v1.2.3 From e49429587bbf01ff741a218c86a11fe2b59a0b5c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 21:50:44 -0700 Subject: clang-format --- include/grpc/impl/codegen/atm_win32.h | 2 +- src/core/lib/iomgr/async_execution_lock.c | 2 +- src/core/lib/iomgr/async_execution_lock.h | 2 +- src/core/lib/support/mpscq.c | 8 ++++---- src/core/lib/support/mpscq.h | 6 ++---- 5 files changed, 9 insertions(+), 11 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc/impl/codegen/atm_win32.h b/include/grpc/impl/codegen/atm_win32.h index 2904007d63..f931f4509f 100644 --- a/include/grpc/impl/codegen/atm_win32.h +++ b/include/grpc/impl/codegen/atm_win32.h @@ -123,7 +123,7 @@ static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm *p, gpr_atm delta) { } static __inline gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n) { - return (gpr_atm)InterlockedExchangePointer((PVOID*)p, (PVOID)n); + return (gpr_atm)InterlockedExchangePointer((PVOID *)p, (PVOID)n); } #endif /* GRPC_IMPL_CODEGEN_ATM_WIN32_H */ diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c index b6b7e0d92c..595290f78c 100644 --- a/src/core/lib/iomgr/async_execution_lock.c +++ b/src/core/lib/iomgr/async_execution_lock.c @@ -57,7 +57,7 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { while ((n = gpr_mpscq_pop(&lock->queue)) == NULL) { // TODO(ctiller): find something to fill in the time } - grpc_aelock_qnode *ln = (grpc_aelock_qnode*)n; + grpc_aelock_qnode *ln = (grpc_aelock_qnode *)n; ln->action(exec_ctx, ln->arg); gpr_free(ln); } diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h index 20cbcaf2e1..66551f9398 100644 --- a/src/core/lib/iomgr/async_execution_lock.h +++ b/src/core/lib/iomgr/async_execution_lock.h @@ -37,8 +37,8 @@ #include #include -#include "src/core/lib/support/mpscq.h" #include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/support/mpscq.h" typedef void (*grpc_aelock_action)(grpc_exec_ctx *exec_ctx, void *arg); diff --git a/src/core/lib/support/mpscq.c b/src/core/lib/support/mpscq.c index 911fdd161c..25b055b172 100644 --- a/src/core/lib/support/mpscq.c +++ b/src/core/lib/support/mpscq.c @@ -48,13 +48,14 @@ void gpr_mpscq_destroy(gpr_mpscq *q) { void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n) { gpr_atm_no_barrier_store(&n->next, 0); - gpr_mpscq_node *prev = (gpr_mpscq_node*)gpr_atm_full_xchg(&q->head, (gpr_atm)n); + gpr_mpscq_node *prev = + (gpr_mpscq_node *)gpr_atm_full_xchg(&q->head, (gpr_atm)n); gpr_atm_rel_store(&prev->next, (gpr_atm)n); } gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { gpr_mpscq_node *tail = q->tail; - gpr_mpscq_node *next = (gpr_mpscq_node*)gpr_atm_acq_load(&tail->next); + gpr_mpscq_node *next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); if (tail == &q->stub) { if (next == NULL) return NULL; q->tail = next; @@ -65,7 +66,7 @@ gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { q->tail = next; return tail; } - gpr_mpscq_node *head = (gpr_mpscq_node*)gpr_atm_acq_load(&q->head); + gpr_mpscq_node *head = (gpr_mpscq_node *)gpr_atm_acq_load(&q->head); if (tail != head) { return 0; } @@ -77,4 +78,3 @@ gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { } return NULL; } - diff --git a/src/core/lib/support/mpscq.h b/src/core/lib/support/mpscq.h index 30b37a94a1..e7f4773258 100644 --- a/src/core/lib/support/mpscq.h +++ b/src/core/lib/support/mpscq.h @@ -34,12 +34,10 @@ #ifndef GRPC_CORE_LIB_SUPPORT_MPSCQ_H #define GRPC_CORE_LIB_SUPPORT_MPSCQ_H -#include #include +#include -typedef struct gpr_mpscq_node { - gpr_atm next; -} gpr_mpscq_node; +typedef struct gpr_mpscq_node { gpr_atm next; } gpr_mpscq_node; typedef struct gpr_mpscq { gpr_atm head; -- cgit v1.2.3 From 18879dcff91209abb0e5851b2e78efbecf341a6b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 22:13:48 -0700 Subject: Add cacheline padding, and a test --- Makefile | 36 ++++ build.yaml | 9 + src/core/lib/support/mpscq.h | 1 + test/core/support/mpscq_test.c | 124 +++++++++++++ tools/run_tests/sources_and_headers.json | 14 ++ tools/run_tests/tests.json | 21 +++ vsprojects/buildtests_c.sln | 25 +++ .../test/gpr_mpscq_test/gpr_mpscq_test.vcxproj | 193 +++++++++++++++++++++ .../gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters | 21 +++ 9 files changed, 444 insertions(+) create mode 100644 test/core/support/mpscq_test.c create mode 100644 vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj create mode 100644 vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters (limited to 'src/core/lib') diff --git a/Makefile b/Makefile index 319f483e75..a78910004a 100644 --- a/Makefile +++ b/Makefile @@ -915,6 +915,7 @@ 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_mpscq_test: $(BINDIR)/$(CONFIG)/gpr_mpscq_test gpr_slice_buffer_test: $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test gpr_slice_test: $(BINDIR)/$(CONFIG)/gpr_slice_test gpr_stack_lockfree_test: $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test @@ -1249,6 +1250,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/gpr_host_port_test \ $(BINDIR)/$(CONFIG)/gpr_load_file_test \ $(BINDIR)/$(CONFIG)/gpr_log_test \ + $(BINDIR)/$(CONFIG)/gpr_mpscq_test \ $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test \ $(BINDIR)/$(CONFIG)/gpr_slice_test \ $(BINDIR)/$(CONFIG)/gpr_stack_lockfree_test \ @@ -1530,6 +1532,8 @@ test_c: buildtests_c $(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_mpscq_test" + $(Q) $(BINDIR)/$(CONFIG)/gpr_mpscq_test || ( echo test gpr_mpscq_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_slice_buffer_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test || ( echo test gpr_slice_buffer_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_slice_test" @@ -7177,6 +7181,38 @@ endif endif +GPR_MPSCQ_TEST_SRC = \ + test/core/support/mpscq_test.c \ + +GPR_MPSCQ_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_MPSCQ_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/gpr_mpscq_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/gpr_mpscq_test: $(GPR_MPSCQ_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(GPR_MPSCQ_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_mpscq_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/support/mpscq_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_gpr_mpscq_test: $(GPR_MPSCQ_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(GPR_MPSCQ_TEST_OBJS:.o=.dep) +endif +endif + + GPR_SLICE_BUFFER_TEST_SRC = \ test/core/support/slice_buffer_test.c \ diff --git a/build.yaml b/build.yaml index addb91fcce..9cacc0e776 100644 --- a/build.yaml +++ b/build.yaml @@ -1480,6 +1480,15 @@ targets: deps: - gpr_test_util - gpr +- name: gpr_mpscq_test + cpu_cost: 10 + build: test + language: c + src: + - test/core/support/mpscq_test.c + deps: + - gpr_test_util + - gpr - name: gpr_slice_buffer_test build: test language: c diff --git a/src/core/lib/support/mpscq.h b/src/core/lib/support/mpscq.h index e7f4773258..2b8350be74 100644 --- a/src/core/lib/support/mpscq.h +++ b/src/core/lib/support/mpscq.h @@ -41,6 +41,7 @@ typedef struct gpr_mpscq_node { gpr_atm next; } gpr_mpscq_node; typedef struct gpr_mpscq { gpr_atm head; + char padding[GPR_CACHELINE_SIZE]; gpr_mpscq_node *tail; gpr_mpscq_node stub; } gpr_mpscq; diff --git a/test/core/support/mpscq_test.c b/test/core/support/mpscq_test.c new file mode 100644 index 0000000000..393949dc52 --- /dev/null +++ b/test/core/support/mpscq_test.c @@ -0,0 +1,124 @@ +/* + * + * 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/lib/support/mpscq.h" + +#include + +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +typedef struct test_node { + gpr_mpscq_node node; + size_t i; + size_t *ctr; +} test_node; + +static test_node *new_node(size_t i, size_t *ctr) { + test_node *n = gpr_malloc(sizeof(test_node)); + n->i = i; + n->ctr = ctr; + return n; +} + +static void test_serial(void) { + gpr_log(GPR_DEBUG, "test_serial"); + gpr_mpscq q; + gpr_mpscq_init(&q); + for (size_t i = 0; i < 10000000; i++) { + gpr_mpscq_push(&q, &new_node(i, NULL)->node); + } + for (size_t i = 0; i < 10000000; i++) { + test_node *n = (test_node *)gpr_mpscq_pop(&q); + GPR_ASSERT(n); + GPR_ASSERT(n->i == i); + gpr_free(n); + } +} + +typedef struct { + size_t ctr; + gpr_mpscq *q; +} thd_args; + +#define THREAD_ITERATIONS 1000000 + +static void test_thread(void *args) { + thd_args *a = args; + for (size_t i = 1; i <= THREAD_ITERATIONS; i++) { + gpr_mpscq_push(a->q, &new_node(i, &a->ctr)->node); + } +} + +static void test_mt(void) { + gpr_log(GPR_DEBUG, "test_mt"); + gpr_thd_id thds[100]; + thd_args ta[GPR_ARRAY_SIZE(thds)]; + gpr_mpscq q; + gpr_mpscq_init(&q); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + ta[i].ctr = 0; + ta[i].q = &q; + GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); + } + size_t num_done = 0; + size_t spins = 0; + while (num_done != GPR_ARRAY_SIZE(thds)) { + gpr_mpscq_node *n; + while ((n = gpr_mpscq_pop(&q)) == NULL) { + spins++; + } + test_node *tn = (test_node *)n; + GPR_ASSERT(*tn->ctr == tn->i - 1); + *tn->ctr = tn->i; + if (tn->i == THREAD_ITERATIONS) num_done++; + gpr_free(tn); + } + gpr_log(GPR_DEBUG, "spins: %d", spins); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_join(thds[i]); + } + gpr_mpscq_destroy(&q); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_serial(); + test_mt(); + return 0; +} diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 4369771170..ab08bdf55d 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -580,6 +580,20 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util" + ], + "headers": [], + "language": "c", + "name": "gpr_mpscq_test", + "src": [ + "test/core/support/mpscq_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index a07082d996..fcf03a4eca 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -661,6 +661,27 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 10, + "exclude_configs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "gpr_mpscq_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, { "args": [], "ci_platforms": [ diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index 9c44e0a217..356fabf930 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -418,6 +418,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_log_test", "vcxproj\tes {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_mpscq_test", "vcxproj\test\gpr_mpscq_test\gpr_mpscq_test.vcxproj", "{B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {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}") = "gpr_slice_buffer_test", "vcxproj\test\gpr_slice_buffer_test\gpr_slice_buffer_test.vcxproj", "{E679773D-DE89-AEBB-9787-59019989B825}" ProjectSection(myProperties) = preProject lib = "False" @@ -2090,6 +2099,22 @@ Global {38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release-DLL|Win32.Build.0 = Release|Win32 {38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release-DLL|x64.ActiveCfg = Release|x64 {38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release-DLL|x64.Build.0 = Release|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|Win32.ActiveCfg = Debug|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|x64.ActiveCfg = Debug|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|Win32.ActiveCfg = Release|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|x64.ActiveCfg = Release|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|Win32.Build.0 = Debug|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|x64.Build.0 = Debug|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|Win32.Build.0 = Release|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|x64.Build.0 = Release|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|x64.Build.0 = Debug|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|Win32.Build.0 = Release|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|x64.ActiveCfg = Release|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|x64.Build.0 = Release|x64 {E679773D-DE89-AEBB-9787-59019989B825}.Debug|Win32.ActiveCfg = Debug|Win32 {E679773D-DE89-AEBB-9787-59019989B825}.Debug|x64.ActiveCfg = Debug|x64 {E679773D-DE89-AEBB-9787-59019989B825}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj b/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj new file mode 100644 index 0000000000..01342868b0 --- /dev/null +++ b/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj @@ -0,0 +1,193 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + gpr_mpscq_test + static + Debug + static + Debug + + + gpr_mpscq_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + 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}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters b/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters new file mode 100644 index 0000000000..9cceb9f3e2 --- /dev/null +++ b/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\support + + + + + + {e82fb80c-10ba-2959-55d6-8653715f1e4f} + + + {32120233-25e6-f3e4-f828-c6408d47ec04} + + + {aa3a22bc-229a-c00a-dd4a-924c818c6a49} + + + + -- cgit v1.2.3 From 049a3a6392fd69cdc99fc6765a1a5ab2a1680bdc Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 22:17:23 -0700 Subject: Add some comments --- src/core/lib/support/mpscq.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/core/lib') diff --git a/src/core/lib/support/mpscq.h b/src/core/lib/support/mpscq.h index 2b8350be74..f7620fc5ed 100644 --- a/src/core/lib/support/mpscq.h +++ b/src/core/lib/support/mpscq.h @@ -37,10 +37,18 @@ #include #include +// Multiple-producer single-consumer lock free queue, based upon the +// implementation from Dmitry Vyukov here: +// http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue + +// List node (include this in a data structure and dangle the rest of the +// interesting bits off the end) typedef struct gpr_mpscq_node { gpr_atm next; } gpr_mpscq_node; +// Actual queue type typedef struct gpr_mpscq { gpr_atm head; + // make sure head & tail don't share a cacheline char padding[GPR_CACHELINE_SIZE]; gpr_mpscq_node *tail; gpr_mpscq_node stub; @@ -48,7 +56,11 @@ typedef struct gpr_mpscq { void gpr_mpscq_init(gpr_mpscq *q); void gpr_mpscq_destroy(gpr_mpscq *q); +// Push a node void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n); +// Pop a node (returns NULL if no node is ready - which doesn't indicate that +// the queue is empty!!) gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q); #endif /* GRPC_CORE_LIB_SUPPORT_MPSCQ_H */ + -- cgit v1.2.3 From 1df328fe30b64369f425d791b9d26dcd956339ff Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 22:17:35 -0700 Subject: clang-format --- src/core/lib/support/mpscq.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/support/mpscq.h b/src/core/lib/support/mpscq.h index f7620fc5ed..1201edceb1 100644 --- a/src/core/lib/support/mpscq.h +++ b/src/core/lib/support/mpscq.h @@ -63,4 +63,3 @@ void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n); gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q); #endif /* GRPC_CORE_LIB_SUPPORT_MPSCQ_H */ - -- cgit v1.2.3 From a729f60cd3a8fbf06d26f1665ac9b58f2e0b30e0 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 May 2016 22:24:32 -0700 Subject: Add some comments --- src/core/lib/iomgr/async_execution_lock.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h index 66551f9398..ba78f81cca 100644 --- a/src/core/lib/iomgr/async_execution_lock.h +++ b/src/core/lib/iomgr/async_execution_lock.h @@ -40,6 +40,11 @@ #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/support/mpscq.h" +// Provides serialized access to some resource. +// Each action queued on an aelock is executed serially in a borrowed thread. +// The actual thread executing actions may change over time (but there will only +// every be one at a time). + typedef void (*grpc_aelock_action)(grpc_exec_ctx *exec_ctx, void *arg); typedef struct grpc_aelock_qnode { @@ -54,8 +59,13 @@ typedef struct grpc_aelock { gpr_atm locked; } grpc_aelock; +// Initialize the lock, with an optional workqueue to shift load to when +// necessary void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue); +// Destroy the lock void grpc_aelock_destroy(grpc_aelock *lock); +// Execute \a action within the lock. \a arg is the argument to pass to \a +// action and sizeof_arg is the sizeof(*arg), or 0 if arg is non-copyable. void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, grpc_aelock_action action, void *arg, size_t sizeof_arg); -- cgit v1.2.3 From cf600c9f252d59f437fbcd81987115b30fb58896 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 May 2016 08:26:56 -0700 Subject: Refine async_execution_lock interface, implement exec_ctx based task switching on starvation --- src/core/ext/transport/chttp2/transport/internal.h | 2 +- src/core/lib/iomgr/async_execution_lock.c | 81 ++++++++++++++++++---- src/core/lib/iomgr/async_execution_lock.h | 16 +---- test/core/iomgr/async_execution_lock_test.c | 19 ++--- 4 files changed, 78 insertions(+), 40 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index a269338b49..d852965edb 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -291,7 +291,7 @@ struct grpc_chttp2_transport_parsing { int64_t outgoing_window; }; -typedef void (*grpc_chttp2_locked_action)(grpc_exec_ctx *ctx, +typedef void (*grpc_chttp2_locked_action)(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, void *arg); diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c index 595290f78c..3859f474bf 100644 --- a/src/core/lib/iomgr/async_execution_lock.c +++ b/src/core/lib/iomgr/async_execution_lock.c @@ -38,35 +38,88 @@ #include #include -#define NO_CONSUMER ((gpr_atm)1) +typedef struct grpc_aelock_qnode { + gpr_mpscq_node mpscq_node; + grpc_aelock_action action; + void *arg; +} grpc_aelock_qnode; -void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue) { +struct grpc_aelock { + grpc_workqueue *optional_workqueue; + gpr_mpscq queue; + // state is: + // lower bit - zero if orphaned + // other bits - number of items queued on the lock + gpr_atm state; + grpc_closure continue_finishing; +}; + +static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, + bool success); + +grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue) { + grpc_aelock *lock = gpr_malloc(sizeof(*lock)); lock->optional_workqueue = optional_workqueue; - gpr_atm_no_barrier_store(&lock->locked, 0); + gpr_atm_no_barrier_store(&lock->state, 1); gpr_mpscq_init(&lock->queue); + grpc_closure_init(&lock->continue_finishing, continue_finishing, lock); + return lock; } -void grpc_aelock_destroy(grpc_aelock *lock) { - GPR_ASSERT(gpr_atm_no_barrier_load(&lock->locked) == 0); +static void really_destroy(grpc_aelock *lock) { + GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); gpr_mpscq_destroy(&lock->queue); } +void grpc_aelock_destroy(grpc_aelock *lock) { + if (gpr_atm_full_fetch_add(&lock->state, -1) == 1) { + really_destroy(lock); + } +} + +static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { + gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); + if (n == NULL) { + // queue is in an inconsistant state: use this as a cue that we should + // go off and do something else for a while (and come back later) + grpc_exec_ctx_enqueue(exec_ctx, &lock->continue_finishing, true, + lock->optional_workqueue); + return false; + } + grpc_aelock_qnode *ln = (grpc_aelock_qnode *)n; + ln->action(exec_ctx, ln->arg); + gpr_free(ln); + return true; +} + static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { - while (gpr_atm_full_fetch_add(&lock->locked, -1) != 1) { - gpr_mpscq_node *n; - while ((n = gpr_mpscq_pop(&lock->queue)) == NULL) { - // TODO(ctiller): find something to fill in the time + do { + switch (gpr_atm_full_fetch_add(&lock->state, -2)) { + case 3: // had one count, one unorphaned --> unlocked unorphaned + return; + case 2: // and one count, one orphaned --> unlocked and orphaned + really_destroy(lock); + return; + case 1: + case 0: + // these values are illegal - representing an already unlocked or + // deleted lock + GPR_UNREACHABLE_CODE(return ); } - grpc_aelock_qnode *ln = (grpc_aelock_qnode *)n; - ln->action(exec_ctx, ln->arg); - gpr_free(ln); - } + } while (maybe_finish_one(exec_ctx, lock)); +} + +static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, + bool success) { + if (maybe_finish_one(exec_ctx, arg)) finish(exec_ctx, arg); } void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, grpc_aelock_action action, void *arg, size_t sizeof_arg) { - if (gpr_atm_full_fetch_add(&lock->locked, 1) == 0) { + gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); + GPR_ASSERT(last & 1); // ensure lock has not been destroyed + if (last == 1) { action(exec_ctx, arg); finish(exec_ctx, lock); } else { diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h index ba78f81cca..5ced82b08d 100644 --- a/src/core/lib/iomgr/async_execution_lock.h +++ b/src/core/lib/iomgr/async_execution_lock.h @@ -40,6 +40,8 @@ #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/support/mpscq.h" +typedef struct grpc_aelock grpc_aelock; + // Provides serialized access to some resource. // Each action queued on an aelock is executed serially in a borrowed thread. // The actual thread executing actions may change over time (but there will only @@ -47,21 +49,9 @@ typedef void (*grpc_aelock_action)(grpc_exec_ctx *exec_ctx, void *arg); -typedef struct grpc_aelock_qnode { - gpr_mpscq_node mpscq_node; - grpc_aelock_action action; - void *arg; -} grpc_aelock_qnode; - -typedef struct grpc_aelock { - grpc_workqueue *optional_workqueue; - gpr_mpscq queue; - gpr_atm locked; -} grpc_aelock; - // Initialize the lock, with an optional workqueue to shift load to when // necessary -void grpc_aelock_init(grpc_aelock *lock, grpc_workqueue *optional_workqueue); +grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue); // Destroy the lock void grpc_aelock_destroy(grpc_aelock *lock); // Execute \a action within the lock. \a arg is the argument to pass to \a diff --git a/test/core/iomgr/async_execution_lock_test.c b/test/core/iomgr/async_execution_lock_test.c index 8c9665a458..526913bc3a 100644 --- a/test/core/iomgr/async_execution_lock_test.c +++ b/test/core/iomgr/async_execution_lock_test.c @@ -42,10 +42,7 @@ static void test_no_op(void) { gpr_log(GPR_DEBUG, "test_no_op"); - - grpc_aelock lock; - grpc_aelock_init(&lock, NULL); - grpc_aelock_destroy(&lock); + grpc_aelock_destroy(grpc_aelock_create(NULL)); } static void set_bool_to_true(grpc_exec_ctx *exec_ctx, void *value) { @@ -55,14 +52,13 @@ static void set_bool_to_true(grpc_exec_ctx *exec_ctx, void *value) { static void test_execute_one(void) { gpr_log(GPR_DEBUG, "test_execute_one"); - grpc_aelock lock; - grpc_aelock_init(&lock, NULL); + grpc_aelock *lock = grpc_aelock_create(NULL); bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_aelock_execute(&exec_ctx, &lock, set_bool_to_true, &done, 0); + grpc_aelock_execute(&exec_ctx, lock, set_bool_to_true, &done, 0); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(done); - grpc_aelock_destroy(&lock); + grpc_aelock_destroy(lock); } typedef struct { @@ -100,21 +96,20 @@ static void execute_many_loop(void *a) { static void test_execute_many(void) { gpr_log(GPR_DEBUG, "test_execute_many"); - grpc_aelock lock; + grpc_aelock *lock = grpc_aelock_create(NULL); gpr_thd_id thds[100]; thd_args ta[GPR_ARRAY_SIZE(thds)]; - grpc_aelock_init(&lock, NULL); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_options options = gpr_thd_options_default(); gpr_thd_options_set_joinable(&options); ta[i].ctr = 0; - ta[i].lock = &lock; + ta[i].lock = lock; GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &ta[i], &options)); } for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_join(thds[i]); } - grpc_aelock_destroy(&lock); + grpc_aelock_destroy(lock); } int main(int argc, char **argv) { -- cgit v1.2.3 From 14e3d9bf5b5be4ae78d679213777bd68903d33a7 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 May 2016 08:33:56 -0700 Subject: Fix leak --- src/core/lib/iomgr/async_execution_lock.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c index 3859f474bf..96ba175a5a 100644 --- a/src/core/lib/iomgr/async_execution_lock.c +++ b/src/core/lib/iomgr/async_execution_lock.c @@ -69,6 +69,7 @@ grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue) { static void really_destroy(grpc_aelock *lock) { GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); gpr_mpscq_destroy(&lock->queue); + gpr_free(lock); } void grpc_aelock_destroy(grpc_aelock *lock) { -- cgit v1.2.3 From 5774a469c029fed88a98283129fd61cd5c78e78f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 May 2016 09:24:35 -0700 Subject: Fix header guards --- src/core/lib/iomgr/async_execution_lock.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h index 5ced82b08d..e52762f443 100644 --- a/src/core/lib/iomgr/async_execution_lock.h +++ b/src/core/lib/iomgr/async_execution_lock.h @@ -31,8 +31,8 @@ * */ -#ifndef AEL_H -#define AEL_H +#ifndef GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H +#define GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H #include @@ -60,4 +60,4 @@ void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, grpc_aelock_action action, void *arg, size_t sizeof_arg); -#endif +#endif /* GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H */ -- cgit v1.2.3 From c9d4b81dabf4dc2c262fc771c31790f2d60fe551 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 24 May 2016 10:50:40 -0700 Subject: Add the ability to run some action when the lock becomes idle --- src/core/lib/iomgr/async_execution_lock.c | 94 +++++++++++++++++++++++------ src/core/lib/iomgr/async_execution_lock.h | 4 +- test/core/iomgr/async_execution_lock_test.c | 22 +++++-- 3 files changed, 98 insertions(+), 22 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c index 96ba175a5a..c656e7c940 100644 --- a/src/core/lib/iomgr/async_execution_lock.c +++ b/src/core/lib/iomgr/async_execution_lock.c @@ -38,6 +38,9 @@ #include #include +#define STATE_BIT_ALIVE 1 +#define STATE_BIT_REFS 2 + typedef struct grpc_aelock_qnode { gpr_mpscq_node mpscq_node; grpc_aelock_action action; @@ -50,17 +53,24 @@ struct grpc_aelock { // state is: // lower bit - zero if orphaned // other bits - number of items queued on the lock + // see: STATE_BIT_xxx gpr_atm state; + grpc_aelock_action before_idle_action; + void *before_idle_action_arg; grpc_closure continue_finishing; }; static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, bool success); -grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue) { +grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue, + grpc_aelock_action before_idle_action, + void *before_idle_action_arg) { grpc_aelock *lock = gpr_malloc(sizeof(*lock)); + lock->before_idle_action = before_idle_action; + lock->before_idle_action_arg = before_idle_action_arg; lock->optional_workqueue = optional_workqueue; - gpr_atm_no_barrier_store(&lock->state, 1); + gpr_atm_no_barrier_store(&lock->state, STATE_BIT_ALIVE); gpr_mpscq_init(&lock->queue); grpc_closure_init(&lock->continue_finishing, continue_finishing, lock); return lock; @@ -73,7 +83,8 @@ static void really_destroy(grpc_aelock *lock) { } void grpc_aelock_destroy(grpc_aelock *lock) { - if (gpr_atm_full_fetch_add(&lock->state, -1) == 1) { + if (gpr_atm_full_fetch_add(&lock->state, -STATE_BIT_ALIVE) == + STATE_BIT_ALIVE) { really_destroy(lock); } } @@ -81,10 +92,6 @@ void grpc_aelock_destroy(grpc_aelock *lock) { static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); if (n == NULL) { - // queue is in an inconsistant state: use this as a cue that we should - // go off and do something else for a while (and come back later) - grpc_exec_ctx_enqueue(exec_ctx, &lock->continue_finishing, true, - lock->optional_workqueue); return false; } grpc_aelock_qnode *ln = (grpc_aelock_qnode *)n; @@ -94,36 +101,89 @@ static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { } static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { - do { - switch (gpr_atm_full_fetch_add(&lock->state, -2)) { - case 3: // had one count, one unorphaned --> unlocked unorphaned + for (;;) { + gpr_atm last_state = gpr_atm_full_fetch_add(&lock->state, -STATE_BIT_REFS); + switch (last_state) { + default: + perform_one_step: + gpr_log(GPR_DEBUG, "ls=%d execute", last_state); + if (!maybe_finish_one(exec_ctx, lock)) { + // perform the idle action before going off to do something else + lock->before_idle_action(exec_ctx, lock->before_idle_action_arg); + // quick peek to see if we can immediately resume + if (!maybe_finish_one(exec_ctx, lock)) { + // queue is in an inconsistant state: use this as a cue that we + // should + // go off and do something else for a while (and come back later) + grpc_exec_ctx_enqueue(exec_ctx, &lock->continue_finishing, true, + lock->optional_workqueue); + return; + } + } + break; + case STATE_BIT_ALIVE | (2 * STATE_BIT_REFS): + gpr_log(GPR_DEBUG, "ls=%d final", last_state); + lock->before_idle_action(exec_ctx, lock->before_idle_action_arg); + switch (gpr_atm_full_fetch_add(&lock->state, -STATE_BIT_REFS)) { + case STATE_BIT_ALIVE | STATE_BIT_REFS: + return; + case STATE_BIT_REFS: + really_destroy(lock); + return; + default: + gpr_log(GPR_DEBUG, "retry"); + // oops: did the before action, but something else came in + // better add another ref so we remember to do this again + gpr_atm_full_fetch_add(&lock->state, STATE_BIT_REFS); + goto perform_one_step; + } + break; + case STATE_BIT_ALIVE | STATE_BIT_REFS: + gpr_log(GPR_DEBUG, "ls=%d unlock", last_state); return; - case 2: // and one count, one orphaned --> unlocked and orphaned + case 2 * STATE_BIT_REFS: + gpr_log(GPR_DEBUG, "ls=%d idle", last_state); + lock->before_idle_action(exec_ctx, lock->before_idle_action_arg); + GPR_ASSERT(gpr_atm_full_fetch_add(&lock->state, -STATE_BIT_REFS) == + STATE_BIT_REFS); + case STATE_BIT_REFS: + gpr_log(GPR_DEBUG, "ls=%d destroy", last_state); really_destroy(lock); return; - case 1: + case STATE_BIT_ALIVE: case 0: // these values are illegal - representing an already unlocked or // deleted lock GPR_UNREACHABLE_CODE(return ); } - } while (maybe_finish_one(exec_ctx, lock)); + } + + // while (maybe_finish_one(exec_ctx, lock)); } static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, bool success) { - if (maybe_finish_one(exec_ctx, arg)) finish(exec_ctx, arg); + grpc_aelock *lock = arg; + if (maybe_finish_one(exec_ctx, lock)) { + finish(exec_ctx, lock); + } else { + // queue is in an inconsistant state: use this as a cue that we should + // go off and do something else for a while (and come back later) + grpc_exec_ctx_enqueue(exec_ctx, &lock->continue_finishing, true, + lock->optional_workqueue); + } } void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, grpc_aelock_action action, void *arg, size_t sizeof_arg) { - gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); - GPR_ASSERT(last & 1); // ensure lock has not been destroyed - if (last == 1) { + gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2 * STATE_BIT_REFS); + GPR_ASSERT(last & STATE_BIT_ALIVE); // ensure lock has not been destroyed + if (last == STATE_BIT_ALIVE) { action(exec_ctx, arg); finish(exec_ctx, lock); } else { + gpr_atm_full_fetch_add(&lock->state, -STATE_BIT_REFS); grpc_aelock_qnode *n = gpr_malloc(sizeof(*n) + sizeof_arg); n->action = action; if (sizeof_arg > 0) { diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h index e52762f443..ea7a322fae 100644 --- a/src/core/lib/iomgr/async_execution_lock.h +++ b/src/core/lib/iomgr/async_execution_lock.h @@ -51,7 +51,9 @@ typedef void (*grpc_aelock_action)(grpc_exec_ctx *exec_ctx, void *arg); // Initialize the lock, with an optional workqueue to shift load to when // necessary -grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue); +grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue, + grpc_aelock_action before_idle_action, + void *before_idle_action_arg); // Destroy the lock void grpc_aelock_destroy(grpc_aelock *lock); // Execute \a action within the lock. \a arg is the argument to pass to \a diff --git a/test/core/iomgr/async_execution_lock_test.c b/test/core/iomgr/async_execution_lock_test.c index 526913bc3a..0ce0183562 100644 --- a/test/core/iomgr/async_execution_lock_test.c +++ b/test/core/iomgr/async_execution_lock_test.c @@ -40,25 +40,34 @@ #include "test/core/util/test_config.h" +static void do_nothing_action(grpc_exec_ctx *exec_ctx, void *ignored) {} + static void test_no_op(void) { gpr_log(GPR_DEBUG, "test_no_op"); - grpc_aelock_destroy(grpc_aelock_create(NULL)); + grpc_aelock_destroy(grpc_aelock_create(NULL, do_nothing_action, NULL)); } static void set_bool_to_true(grpc_exec_ctx *exec_ctx, void *value) { *(bool *)value = true; } +static void increment_atomic(grpc_exec_ctx *exec_ctx, void *value) { + gpr_atm_full_fetch_add((gpr_atm *)value, 1); +} + static void test_execute_one(void) { gpr_log(GPR_DEBUG, "test_execute_one"); - grpc_aelock *lock = grpc_aelock_create(NULL); + gpr_atm idles; + gpr_atm_no_barrier_store(&idles, 0); + grpc_aelock *lock = grpc_aelock_create(NULL, increment_atomic, &idles); bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_aelock_execute(&exec_ctx, lock, set_bool_to_true, &done, 0); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(done); grpc_aelock_destroy(lock); + GPR_ASSERT(gpr_atm_no_barrier_load(&idles) == 1); } typedef struct { @@ -83,7 +92,7 @@ static void execute_many_loop(void *a) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; size_t n = 1; for (size_t i = 0; i < 10; i++) { - for (size_t j = 0; j < 10000; j++) { + for (size_t j = 0; j < 100; j++) { ex_args c = {&args->ctr, n++}; grpc_aelock_execute(&exec_ctx, args->lock, check_one, &c, sizeof(c)); grpc_exec_ctx_flush(&exec_ctx); @@ -96,7 +105,10 @@ static void execute_many_loop(void *a) { static void test_execute_many(void) { gpr_log(GPR_DEBUG, "test_execute_many"); - grpc_aelock *lock = grpc_aelock_create(NULL); + gpr_atm idles; + gpr_atm_no_barrier_store(&idles, 0); + + grpc_aelock *lock = grpc_aelock_create(NULL, increment_atomic, &idles); gpr_thd_id thds[100]; thd_args ta[GPR_ARRAY_SIZE(thds)]; for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { @@ -110,6 +122,8 @@ static void test_execute_many(void) { gpr_thd_join(thds[i]); } grpc_aelock_destroy(lock); + + gpr_log(GPR_DEBUG, "idles: %d", gpr_atm_no_barrier_load(&idles)); } int main(int argc, char **argv) { -- cgit v1.2.3 From 765c538d72572b9317661d4a6697d9547fb026a9 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 7 Jul 2016 21:25:04 -0700 Subject: Revert "Add the ability to run some action when the lock becomes idle" This reverts commit c9d4b81dabf4dc2c262fc771c31790f2d60fe551. --- src/core/lib/iomgr/async_execution_lock.c | 94 ++++++----------------------- src/core/lib/iomgr/async_execution_lock.h | 4 +- test/core/iomgr/async_execution_lock_test.c | 22 ++----- 3 files changed, 22 insertions(+), 98 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c index c656e7c940..96ba175a5a 100644 --- a/src/core/lib/iomgr/async_execution_lock.c +++ b/src/core/lib/iomgr/async_execution_lock.c @@ -38,9 +38,6 @@ #include #include -#define STATE_BIT_ALIVE 1 -#define STATE_BIT_REFS 2 - typedef struct grpc_aelock_qnode { gpr_mpscq_node mpscq_node; grpc_aelock_action action; @@ -53,24 +50,17 @@ struct grpc_aelock { // state is: // lower bit - zero if orphaned // other bits - number of items queued on the lock - // see: STATE_BIT_xxx gpr_atm state; - grpc_aelock_action before_idle_action; - void *before_idle_action_arg; grpc_closure continue_finishing; }; static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, bool success); -grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue, - grpc_aelock_action before_idle_action, - void *before_idle_action_arg) { +grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue) { grpc_aelock *lock = gpr_malloc(sizeof(*lock)); - lock->before_idle_action = before_idle_action; - lock->before_idle_action_arg = before_idle_action_arg; lock->optional_workqueue = optional_workqueue; - gpr_atm_no_barrier_store(&lock->state, STATE_BIT_ALIVE); + gpr_atm_no_barrier_store(&lock->state, 1); gpr_mpscq_init(&lock->queue); grpc_closure_init(&lock->continue_finishing, continue_finishing, lock); return lock; @@ -83,8 +73,7 @@ static void really_destroy(grpc_aelock *lock) { } void grpc_aelock_destroy(grpc_aelock *lock) { - if (gpr_atm_full_fetch_add(&lock->state, -STATE_BIT_ALIVE) == - STATE_BIT_ALIVE) { + if (gpr_atm_full_fetch_add(&lock->state, -1) == 1) { really_destroy(lock); } } @@ -92,6 +81,10 @@ void grpc_aelock_destroy(grpc_aelock *lock) { static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); if (n == NULL) { + // queue is in an inconsistant state: use this as a cue that we should + // go off and do something else for a while (and come back later) + grpc_exec_ctx_enqueue(exec_ctx, &lock->continue_finishing, true, + lock->optional_workqueue); return false; } grpc_aelock_qnode *ln = (grpc_aelock_qnode *)n; @@ -101,89 +94,36 @@ static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { } static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { - for (;;) { - gpr_atm last_state = gpr_atm_full_fetch_add(&lock->state, -STATE_BIT_REFS); - switch (last_state) { - default: - perform_one_step: - gpr_log(GPR_DEBUG, "ls=%d execute", last_state); - if (!maybe_finish_one(exec_ctx, lock)) { - // perform the idle action before going off to do something else - lock->before_idle_action(exec_ctx, lock->before_idle_action_arg); - // quick peek to see if we can immediately resume - if (!maybe_finish_one(exec_ctx, lock)) { - // queue is in an inconsistant state: use this as a cue that we - // should - // go off and do something else for a while (and come back later) - grpc_exec_ctx_enqueue(exec_ctx, &lock->continue_finishing, true, - lock->optional_workqueue); - return; - } - } - break; - case STATE_BIT_ALIVE | (2 * STATE_BIT_REFS): - gpr_log(GPR_DEBUG, "ls=%d final", last_state); - lock->before_idle_action(exec_ctx, lock->before_idle_action_arg); - switch (gpr_atm_full_fetch_add(&lock->state, -STATE_BIT_REFS)) { - case STATE_BIT_ALIVE | STATE_BIT_REFS: - return; - case STATE_BIT_REFS: - really_destroy(lock); - return; - default: - gpr_log(GPR_DEBUG, "retry"); - // oops: did the before action, but something else came in - // better add another ref so we remember to do this again - gpr_atm_full_fetch_add(&lock->state, STATE_BIT_REFS); - goto perform_one_step; - } - break; - case STATE_BIT_ALIVE | STATE_BIT_REFS: - gpr_log(GPR_DEBUG, "ls=%d unlock", last_state); + do { + switch (gpr_atm_full_fetch_add(&lock->state, -2)) { + case 3: // had one count, one unorphaned --> unlocked unorphaned return; - case 2 * STATE_BIT_REFS: - gpr_log(GPR_DEBUG, "ls=%d idle", last_state); - lock->before_idle_action(exec_ctx, lock->before_idle_action_arg); - GPR_ASSERT(gpr_atm_full_fetch_add(&lock->state, -STATE_BIT_REFS) == - STATE_BIT_REFS); - case STATE_BIT_REFS: - gpr_log(GPR_DEBUG, "ls=%d destroy", last_state); + case 2: // and one count, one orphaned --> unlocked and orphaned really_destroy(lock); return; - case STATE_BIT_ALIVE: + case 1: case 0: // these values are illegal - representing an already unlocked or // deleted lock GPR_UNREACHABLE_CODE(return ); } - } - - // while (maybe_finish_one(exec_ctx, lock)); + } while (maybe_finish_one(exec_ctx, lock)); } static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, bool success) { - grpc_aelock *lock = arg; - if (maybe_finish_one(exec_ctx, lock)) { - finish(exec_ctx, lock); - } else { - // queue is in an inconsistant state: use this as a cue that we should - // go off and do something else for a while (and come back later) - grpc_exec_ctx_enqueue(exec_ctx, &lock->continue_finishing, true, - lock->optional_workqueue); - } + if (maybe_finish_one(exec_ctx, arg)) finish(exec_ctx, arg); } void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, grpc_aelock_action action, void *arg, size_t sizeof_arg) { - gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2 * STATE_BIT_REFS); - GPR_ASSERT(last & STATE_BIT_ALIVE); // ensure lock has not been destroyed - if (last == STATE_BIT_ALIVE) { + gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); + GPR_ASSERT(last & 1); // ensure lock has not been destroyed + if (last == 1) { action(exec_ctx, arg); finish(exec_ctx, lock); } else { - gpr_atm_full_fetch_add(&lock->state, -STATE_BIT_REFS); grpc_aelock_qnode *n = gpr_malloc(sizeof(*n) + sizeof_arg); n->action = action; if (sizeof_arg > 0) { diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h index ea7a322fae..e52762f443 100644 --- a/src/core/lib/iomgr/async_execution_lock.h +++ b/src/core/lib/iomgr/async_execution_lock.h @@ -51,9 +51,7 @@ typedef void (*grpc_aelock_action)(grpc_exec_ctx *exec_ctx, void *arg); // Initialize the lock, with an optional workqueue to shift load to when // necessary -grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue, - grpc_aelock_action before_idle_action, - void *before_idle_action_arg); +grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue); // Destroy the lock void grpc_aelock_destroy(grpc_aelock *lock); // Execute \a action within the lock. \a arg is the argument to pass to \a diff --git a/test/core/iomgr/async_execution_lock_test.c b/test/core/iomgr/async_execution_lock_test.c index 0ce0183562..526913bc3a 100644 --- a/test/core/iomgr/async_execution_lock_test.c +++ b/test/core/iomgr/async_execution_lock_test.c @@ -40,34 +40,25 @@ #include "test/core/util/test_config.h" -static void do_nothing_action(grpc_exec_ctx *exec_ctx, void *ignored) {} - static void test_no_op(void) { gpr_log(GPR_DEBUG, "test_no_op"); - grpc_aelock_destroy(grpc_aelock_create(NULL, do_nothing_action, NULL)); + grpc_aelock_destroy(grpc_aelock_create(NULL)); } static void set_bool_to_true(grpc_exec_ctx *exec_ctx, void *value) { *(bool *)value = true; } -static void increment_atomic(grpc_exec_ctx *exec_ctx, void *value) { - gpr_atm_full_fetch_add((gpr_atm *)value, 1); -} - static void test_execute_one(void) { gpr_log(GPR_DEBUG, "test_execute_one"); - gpr_atm idles; - gpr_atm_no_barrier_store(&idles, 0); - grpc_aelock *lock = grpc_aelock_create(NULL, increment_atomic, &idles); + grpc_aelock *lock = grpc_aelock_create(NULL); bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_aelock_execute(&exec_ctx, lock, set_bool_to_true, &done, 0); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(done); grpc_aelock_destroy(lock); - GPR_ASSERT(gpr_atm_no_barrier_load(&idles) == 1); } typedef struct { @@ -92,7 +83,7 @@ static void execute_many_loop(void *a) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; size_t n = 1; for (size_t i = 0; i < 10; i++) { - for (size_t j = 0; j < 100; j++) { + for (size_t j = 0; j < 10000; j++) { ex_args c = {&args->ctr, n++}; grpc_aelock_execute(&exec_ctx, args->lock, check_one, &c, sizeof(c)); grpc_exec_ctx_flush(&exec_ctx); @@ -105,10 +96,7 @@ static void execute_many_loop(void *a) { static void test_execute_many(void) { gpr_log(GPR_DEBUG, "test_execute_many"); - gpr_atm idles; - gpr_atm_no_barrier_store(&idles, 0); - - grpc_aelock *lock = grpc_aelock_create(NULL, increment_atomic, &idles); + grpc_aelock *lock = grpc_aelock_create(NULL); gpr_thd_id thds[100]; thd_args ta[GPR_ARRAY_SIZE(thds)]; for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { @@ -122,8 +110,6 @@ static void test_execute_many(void) { gpr_thd_join(thds[i]); } grpc_aelock_destroy(lock); - - gpr_log(GPR_DEBUG, "idles: %d", gpr_atm_no_barrier_load(&idles)); } int main(int argc, char **argv) { -- cgit v1.2.3 From f7cade1b4fee90abb0fabe48426e95357465c976 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 7 Jul 2016 21:41:10 -0700 Subject: Rename async_execution_lock --> combiner, make it use closures, unroll previous changes for idleness --- BUILD | 24 +-- CMakeLists.txt | 10 +- Makefile | 82 ++++----- binding.gyp | 2 +- build.yaml | 26 +-- config.m4 | 2 +- gRPC.podspec | 6 +- grpc.gemspec | 4 +- package.xml | 4 +- src/core/lib/iomgr/async_execution_lock.c | 137 -------------- src/core/lib/iomgr/async_execution_lock.h | 63 ------- src/core/lib/iomgr/closure.h | 16 +- src/core/lib/iomgr/combiner.c | 125 +++++++++++++ src/core/lib/iomgr/combiner.h | 60 +++++++ src/python/grpcio/grpc_core_dependencies.py | 2 +- test/core/iomgr/async_execution_lock_test.c | 124 ------------- test/core/iomgr/combiner_test.c | 129 +++++++++++++ test/core/support/mpscq_test.c | 2 +- third_party/protobuf | 2 +- tools/doxygen/Doxyfile.c++.internal | 4 +- tools/doxygen/Doxyfile.core.internal | 4 +- tools/run_tests/sources_and_headers.json | 38 ++-- tools/run_tests/tests.json | 24 +-- vsprojects/buildtests_c.sln | 54 +++--- vsprojects/vcxproj/grpc++/grpc++.vcxproj | 6 +- vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters | 8 +- .../grpc++_unsecure/grpc++_unsecure.vcxproj | 6 +- .../grpc++_unsecure.vcxproj.filters | 8 +- vsprojects/vcxproj/grpc/grpc.vcxproj | 6 +- vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 8 +- .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 6 +- .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 8 +- .../async_execution_lock_test.vcxproj | 199 --------------------- .../async_execution_lock_test.vcxproj.filters | 21 --- .../test/combiner_test/combiner_test.vcxproj | 199 +++++++++++++++++++++ .../combiner_test/combiner_test.vcxproj.filters | 21 +++ 36 files changed, 716 insertions(+), 724 deletions(-) delete mode 100644 src/core/lib/iomgr/async_execution_lock.c delete mode 100644 src/core/lib/iomgr/async_execution_lock.h create mode 100644 src/core/lib/iomgr/combiner.c create mode 100644 src/core/lib/iomgr/combiner.h delete mode 100644 test/core/iomgr/async_execution_lock_test.c create mode 100644 test/core/iomgr/combiner_test.c delete mode 100644 vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj delete mode 100644 vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj.filters create mode 100644 vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj create mode 100644 vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index 0b090fa81c..957c153f8e 100644 --- a/BUILD +++ b/BUILD @@ -175,8 +175,8 @@ cc_library( "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", - "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -327,8 +327,8 @@ cc_library( "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", - "src/core/lib/iomgr/async_execution_lock.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -564,8 +564,8 @@ cc_library( "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", - "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -706,8 +706,8 @@ cc_library( "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", - "src/core/lib/iomgr/async_execution_lock.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -918,8 +918,8 @@ cc_library( "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", - "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -1047,8 +1047,8 @@ cc_library( "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", - "src/core/lib/iomgr/async_execution_lock.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -1257,8 +1257,8 @@ cc_library( "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", - "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -1392,8 +1392,8 @@ cc_library( "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", - "src/core/lib/iomgr/async_execution_lock.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -1718,8 +1718,8 @@ cc_library( "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", - "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -1848,8 +1848,8 @@ cc_library( "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", - "src/core/lib/iomgr/async_execution_lock.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -2267,8 +2267,8 @@ objc_library( "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", - "src/core/lib/iomgr/async_execution_lock.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -2483,8 +2483,8 @@ objc_library( "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", - "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index ec4f75bab0..36d0727735 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,8 +141,8 @@ add_library(grpc src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c - src/core/lib/iomgr/async_execution_lock.c src/core/lib/iomgr/closure.c + src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -347,8 +347,8 @@ add_library(grpc_cronet src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c - src/core/lib/iomgr/async_execution_lock.c src/core/lib/iomgr/closure.c + src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -530,8 +530,8 @@ add_library(grpc_unsecure src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c - src/core/lib/iomgr/async_execution_lock.c src/core/lib/iomgr/closure.c + src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -735,8 +735,8 @@ add_library(grpc++ src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c - src/core/lib/iomgr/async_execution_lock.c src/core/lib/iomgr/closure.c + src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -921,8 +921,8 @@ add_library(grpc++_unsecure src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c - src/core/lib/iomgr/async_execution_lock.c src/core/lib/iomgr/closure.c + src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c diff --git a/Makefile b/Makefile index 41d5bfa47c..710fd941fe 100644 --- a/Makefile +++ b/Makefile @@ -879,7 +879,6 @@ algorithm_test: $(BINDIR)/$(CONFIG)/algorithm_test alloc_test: $(BINDIR)/$(CONFIG)/alloc_test alpn_test: $(BINDIR)/$(CONFIG)/alpn_test api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer -async_execution_lock_test: $(BINDIR)/$(CONFIG)/async_execution_lock_test bad_server_response_test: $(BINDIR)/$(CONFIG)/bad_server_response_test bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test @@ -890,6 +889,7 @@ chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test client_fuzzer: $(BINDIR)/$(CONFIG)/client_fuzzer +combiner_test: $(BINDIR)/$(CONFIG)/combiner_test compression_test: $(BINDIR)/$(CONFIG)/compression_test concurrent_connectivity_test: $(BINDIR)/$(CONFIG)/concurrent_connectivity_test dns_resolver_connectivity_test: $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test @@ -1199,7 +1199,6 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/algorithm_test \ $(BINDIR)/$(CONFIG)/alloc_test \ $(BINDIR)/$(CONFIG)/alpn_test \ - $(BINDIR)/$(CONFIG)/async_execution_lock_test \ $(BINDIR)/$(CONFIG)/bad_server_response_test \ $(BINDIR)/$(CONFIG)/bin_decoder_test \ $(BINDIR)/$(CONFIG)/bin_encoder_test \ @@ -1209,6 +1208,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test \ $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \ $(BINDIR)/$(CONFIG)/chttp2_varint_test \ + $(BINDIR)/$(CONFIG)/combiner_test \ $(BINDIR)/$(CONFIG)/compression_test \ $(BINDIR)/$(CONFIG)/concurrent_connectivity_test \ $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test \ @@ -1500,8 +1500,6 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/alloc_test || ( echo test alloc_test failed ; exit 1 ) $(E) "[RUN] Testing alpn_test" $(Q) $(BINDIR)/$(CONFIG)/alpn_test || ( echo test alpn_test failed ; exit 1 ) - $(E) "[RUN] Testing async_execution_lock_test" - $(Q) $(BINDIR)/$(CONFIG)/async_execution_lock_test || ( echo test async_execution_lock_test failed ; exit 1 ) $(E) "[RUN] Testing bad_server_response_test" $(Q) $(BINDIR)/$(CONFIG)/bad_server_response_test || ( echo test bad_server_response_test failed ; exit 1 ) $(E) "[RUN] Testing bin_decoder_test" @@ -1520,6 +1518,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_stream_map_test || ( echo test chttp2_stream_map_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_varint_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_varint_test || ( echo test chttp2_varint_test failed ; exit 1 ) + $(E) "[RUN] Testing combiner_test" + $(Q) $(BINDIR)/$(CONFIG)/combiner_test || ( echo test combiner_test failed ; exit 1 ) $(E) "[RUN] Testing compression_test" $(Q) $(BINDIR)/$(CONFIG)/compression_test || ( echo test compression_test failed ; exit 1 ) $(E) "[RUN] Testing concurrent_connectivity_test" @@ -2492,8 +2492,8 @@ LIBGRPC_SRC = \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ - src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -2765,8 +2765,8 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ - src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -3107,8 +3107,8 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ - src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -3442,8 +3442,8 @@ LIBGRPC++_SRC = \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ - src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -4054,8 +4054,8 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ - src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -6849,38 +6849,6 @@ endif endif -ASYNC_EXECUTION_LOCK_TEST_SRC = \ - test/core/iomgr/async_execution_lock_test.c \ - -ASYNC_EXECUTION_LOCK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ASYNC_EXECUTION_LOCK_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL. - -$(BINDIR)/$(CONFIG)/async_execution_lock_test: openssl_dep_error - -else - - - -$(BINDIR)/$(CONFIG)/async_execution_lock_test: $(ASYNC_EXECUTION_LOCK_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) $(ASYNC_EXECUTION_LOCK_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)/async_execution_lock_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/iomgr/async_execution_lock_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - -deps_async_execution_lock_test: $(ASYNC_EXECUTION_LOCK_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(ASYNC_EXECUTION_LOCK_TEST_OBJS:.o=.dep) -endif -endif - - BAD_SERVER_RESPONSE_TEST_SRC = \ test/core/end2end/bad_server_response_test.c \ @@ -7201,6 +7169,38 @@ endif endif +COMBINER_TEST_SRC = \ + test/core/iomgr/combiner_test.c \ + +COMBINER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(COMBINER_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/combiner_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/combiner_test: $(COMBINER_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) $(COMBINER_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)/combiner_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/combiner_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_combiner_test: $(COMBINER_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(COMBINER_TEST_OBJS:.o=.dep) +endif +endif + + COMPRESSION_TEST_SRC = \ test/core/compression/compression_test.c \ diff --git a/binding.gyp b/binding.gyp index efd76616c4..86e819a480 100644 --- a/binding.gyp +++ b/binding.gyp @@ -577,8 +577,8 @@ 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', - 'src/core/lib/iomgr/async_execution_lock.c', 'src/core/lib/iomgr/closure.c', + 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', diff --git a/build.yaml b/build.yaml index 3c3a9209d3..5daad9d948 100644 --- a/build.yaml +++ b/build.yaml @@ -166,8 +166,8 @@ filegroups: - src/core/lib/http/format_request.h - src/core/lib/http/httpcli.h - src/core/lib/http/parser.h - - src/core/lib/iomgr/async_execution_lock.h - src/core/lib/iomgr/closure.h + - src/core/lib/iomgr/combiner.h - src/core/lib/iomgr/endpoint.h - src/core/lib/iomgr/endpoint_pair.h - src/core/lib/iomgr/error.h @@ -245,8 +245,8 @@ filegroups: - src/core/lib/http/format_request.c - src/core/lib/http/httpcli.c - src/core/lib/http/parser.c - - src/core/lib/iomgr/async_execution_lock.c - src/core/lib/iomgr/closure.c + - src/core/lib/iomgr/combiner.c - src/core/lib/iomgr/endpoint.c - src/core/lib/iomgr/endpoint_pair_posix.c - src/core/lib/iomgr/endpoint_pair_windows.c @@ -1246,17 +1246,6 @@ targets: - test/core/end2end/fuzzers/api_fuzzer_corpus dict: test/core/end2end/fuzzers/api_fuzzer.dictionary maxlen: 2048 -- name: async_execution_lock_test - cpu_cost: 30 - build: test - language: c - src: - - test/core/iomgr/async_execution_lock_test.c - deps: - - grpc_test_util - - grpc - - gpr_test_util - - gpr - name: bad_server_response_test build: test language: c @@ -1358,6 +1347,17 @@ targets: - test/core/end2end/fuzzers/client_fuzzer_corpus dict: test/core/end2end/fuzzers/hpack.dictionary maxlen: 2048 +- name: combiner_test + cpu_cost: 30 + build: test + language: c + src: + - test/core/iomgr/combiner_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr - name: compression_test build: test language: c diff --git a/config.m4 b/config.m4 index 2974d2ed8d..6ecacb9173 100644 --- a/config.m4 +++ b/config.m4 @@ -96,8 +96,8 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ - src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ diff --git a/gRPC.podspec b/gRPC.podspec index e6105b9603..4f2203c7a5 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -178,8 +178,8 @@ Pod::Spec.new do |s| 'src/core/lib/http/format_request.h', 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', - 'src/core/lib/iomgr/async_execution_lock.h', 'src/core/lib/iomgr/closure.h', + 'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/error.h', @@ -364,8 +364,8 @@ Pod::Spec.new do |s| 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', - 'src/core/lib/iomgr/async_execution_lock.c', 'src/core/lib/iomgr/closure.c', + 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', @@ -564,8 +564,8 @@ Pod::Spec.new do |s| 'src/core/lib/http/format_request.h', 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', - 'src/core/lib/iomgr/async_execution_lock.h', 'src/core/lib/iomgr/closure.h', + 'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/error.h', diff --git a/grpc.gemspec b/grpc.gemspec index a4e0182131..b9f858284a 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -187,8 +187,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/http/format_request.h ) s.files += %w( src/core/lib/http/httpcli.h ) s.files += %w( src/core/lib/http/parser.h ) - s.files += %w( src/core/lib/iomgr/async_execution_lock.h ) s.files += %w( src/core/lib/iomgr/closure.h ) + s.files += %w( src/core/lib/iomgr/combiner.h ) s.files += %w( src/core/lib/iomgr/endpoint.h ) s.files += %w( src/core/lib/iomgr/endpoint_pair.h ) s.files += %w( src/core/lib/iomgr/error.h ) @@ -343,8 +343,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/http/format_request.c ) s.files += %w( src/core/lib/http/httpcli.c ) s.files += %w( src/core/lib/http/parser.c ) - s.files += %w( src/core/lib/iomgr/async_execution_lock.c ) s.files += %w( src/core/lib/iomgr/closure.c ) + s.files += %w( src/core/lib/iomgr/combiner.c ) s.files += %w( src/core/lib/iomgr/endpoint.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_posix.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c ) diff --git a/package.xml b/package.xml index 3631a1d682..91e5b05291 100644 --- a/package.xml +++ b/package.xml @@ -194,8 +194,8 @@ - + @@ -350,8 +350,8 @@ - + diff --git a/src/core/lib/iomgr/async_execution_lock.c b/src/core/lib/iomgr/async_execution_lock.c deleted file mode 100644 index 96ba175a5a..0000000000 --- a/src/core/lib/iomgr/async_execution_lock.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * - * 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/lib/iomgr/async_execution_lock.h" - -#include - -#include -#include - -typedef struct grpc_aelock_qnode { - gpr_mpscq_node mpscq_node; - grpc_aelock_action action; - void *arg; -} grpc_aelock_qnode; - -struct grpc_aelock { - grpc_workqueue *optional_workqueue; - gpr_mpscq queue; - // state is: - // lower bit - zero if orphaned - // other bits - number of items queued on the lock - gpr_atm state; - grpc_closure continue_finishing; -}; - -static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, - bool success); - -grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue) { - grpc_aelock *lock = gpr_malloc(sizeof(*lock)); - lock->optional_workqueue = optional_workqueue; - gpr_atm_no_barrier_store(&lock->state, 1); - gpr_mpscq_init(&lock->queue); - grpc_closure_init(&lock->continue_finishing, continue_finishing, lock); - return lock; -} - -static void really_destroy(grpc_aelock *lock) { - GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); - gpr_mpscq_destroy(&lock->queue); - gpr_free(lock); -} - -void grpc_aelock_destroy(grpc_aelock *lock) { - if (gpr_atm_full_fetch_add(&lock->state, -1) == 1) { - really_destroy(lock); - } -} - -static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { - gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); - if (n == NULL) { - // queue is in an inconsistant state: use this as a cue that we should - // go off and do something else for a while (and come back later) - grpc_exec_ctx_enqueue(exec_ctx, &lock->continue_finishing, true, - lock->optional_workqueue); - return false; - } - grpc_aelock_qnode *ln = (grpc_aelock_qnode *)n; - ln->action(exec_ctx, ln->arg); - gpr_free(ln); - return true; -} - -static void finish(grpc_exec_ctx *exec_ctx, grpc_aelock *lock) { - do { - switch (gpr_atm_full_fetch_add(&lock->state, -2)) { - case 3: // had one count, one unorphaned --> unlocked unorphaned - return; - case 2: // and one count, one orphaned --> unlocked and orphaned - really_destroy(lock); - return; - case 1: - case 0: - // these values are illegal - representing an already unlocked or - // deleted lock - GPR_UNREACHABLE_CODE(return ); - } - } while (maybe_finish_one(exec_ctx, lock)); -} - -static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, - bool success) { - if (maybe_finish_one(exec_ctx, arg)) finish(exec_ctx, arg); -} - -void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, - grpc_aelock_action action, void *arg, - size_t sizeof_arg) { - gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); - GPR_ASSERT(last & 1); // ensure lock has not been destroyed - if (last == 1) { - action(exec_ctx, arg); - finish(exec_ctx, lock); - } else { - grpc_aelock_qnode *n = gpr_malloc(sizeof(*n) + sizeof_arg); - n->action = action; - if (sizeof_arg > 0) { - memcpy(n + 1, arg, sizeof_arg); - n->arg = n + 1; - } else { - n->arg = arg; - } - gpr_mpscq_push(&lock->queue, &n->mpscq_node); - } -} diff --git a/src/core/lib/iomgr/async_execution_lock.h b/src/core/lib/iomgr/async_execution_lock.h deleted file mode 100644 index e52762f443..0000000000 --- a/src/core/lib/iomgr/async_execution_lock.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H -#define GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H - -#include - -#include -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/support/mpscq.h" - -typedef struct grpc_aelock grpc_aelock; - -// Provides serialized access to some resource. -// Each action queued on an aelock is executed serially in a borrowed thread. -// The actual thread executing actions may change over time (but there will only -// every be one at a time). - -typedef void (*grpc_aelock_action)(grpc_exec_ctx *exec_ctx, void *arg); - -// Initialize the lock, with an optional workqueue to shift load to when -// necessary -grpc_aelock *grpc_aelock_create(grpc_workqueue *optional_workqueue); -// Destroy the lock -void grpc_aelock_destroy(grpc_aelock *lock); -// Execute \a action within the lock. \a arg is the argument to pass to \a -// action and sizeof_arg is the sizeof(*arg), or 0 if arg is non-copyable. -void grpc_aelock_execute(grpc_exec_ctx *exec_ctx, grpc_aelock *lock, - grpc_aelock_action action, void *arg, - size_t sizeof_arg); - -#endif /* GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H */ diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h index 08e59a168e..310fcb1b86 100644 --- a/src/core/lib/iomgr/closure.h +++ b/src/core/lib/iomgr/closure.h @@ -37,6 +37,7 @@ #include #include #include "src/core/lib/iomgr/error.h" +#include "src/core/lib/support/mpscq.h" struct grpc_closure; typedef struct grpc_closure grpc_closure; @@ -60,6 +61,14 @@ typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg, /** A closure over a grpc_iomgr_cb_func. */ struct grpc_closure { + /** Once queued, next indicates the next queued closure; before then, scratch + * space */ + union { + grpc_closure *next; + gpr_mpscq_node atm_next; + uintptr_t scratch; + } next_data; + /** Bound callback. */ grpc_iomgr_cb_func cb; @@ -68,13 +77,6 @@ struct grpc_closure { /** Once queued, the result of the closure. Before then: scratch space */ grpc_error *error; - - /** Once queued, next indicates the next queued closure; before then, scratch - * space */ - union { - grpc_closure *next; - uintptr_t scratch; - } next_data; }; /** Initializes \a closure with \a cb and \a cb_arg. */ diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c new file mode 100644 index 0000000000..72e4d0edcb --- /dev/null +++ b/src/core/lib/iomgr/combiner.c @@ -0,0 +1,125 @@ +/* + * + * 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/lib/iomgr/combiner.h" + +#include + +#include +#include + +struct grpc_combiner { + grpc_workqueue *optional_workqueue; + gpr_mpscq queue; + // state is: + // lower bit - zero if orphaned + // other bits - number of items queued on the lock + gpr_atm state; + grpc_closure continue_finishing; +}; + +static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); + +grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { + grpc_combiner *lock = gpr_malloc(sizeof(*lock)); + lock->optional_workqueue = optional_workqueue; + gpr_atm_no_barrier_store(&lock->state, 1); + gpr_mpscq_init(&lock->queue); + grpc_closure_init(&lock->continue_finishing, continue_finishing, lock); + return lock; +} + +static void really_destroy(grpc_combiner *lock) { + GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); + gpr_mpscq_destroy(&lock->queue); + gpr_free(lock); +} + +void grpc_combiner_destroy(grpc_combiner *lock) { + if (gpr_atm_full_fetch_add(&lock->state, -1) == 1) { + really_destroy(lock); + } +} + +static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); + if (n == NULL) { + // queue is in an inconsistant state: use this as a cue that we should + // go off and do something else for a while (and come back later) + grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, + lock->optional_workqueue); + return false; + } + grpc_closure *cl = (grpc_closure *)n; + grpc_error *error = cl->error; + cl->cb(exec_ctx, cl->cb_arg, error); + GRPC_ERROR_UNREF(error); + return true; +} + +static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + do { + switch (gpr_atm_full_fetch_add(&lock->state, -2)) { + case 3: // had one count, one unorphaned --> unlocked unorphaned + return; + case 2: // and one count, one orphaned --> unlocked and orphaned + really_destroy(lock); + return; + case 1: + case 0: + // these values are illegal - representing an already unlocked or + // deleted lock + GPR_UNREACHABLE_CODE(return ); + } + } while (maybe_finish_one(exec_ctx, lock)); +} + +static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + if (maybe_finish_one(exec_ctx, arg)) finish(exec_ctx, arg); +} + +void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, + grpc_closure *cl, grpc_error *error) { + gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); + GPR_ASSERT(last & 1); // ensure lock has not been destroyed + if (last == 1) { + cl->cb(exec_ctx, cl->cb_arg, error); + GRPC_ERROR_UNREF(error); + finish(exec_ctx, lock); + } else { + cl->error = error; + gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); + } +} diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h new file mode 100644 index 0000000000..cef1611acc --- /dev/null +++ b/src/core/lib/iomgr/combiner.h @@ -0,0 +1,60 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H +#define GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H + +#include + +#include +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/support/mpscq.h" + +typedef struct grpc_combiner grpc_combiner; + +// Provides serialized access to some resource. +// Each action queued on an aelock is executed serially in a borrowed thread. +// The actual thread executing actions may change over time (but there will only +// every be one at a time). + +// Initialize the lock, with an optional workqueue to shift load to when +// necessary +grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue); +// Destroy the lock +void grpc_combiner_destroy(grpc_combiner *lock); +// Execute \a action within the lock. \a arg is the argument to pass to \a +// action and sizeof_arg is the sizeof(*arg), or 0 if arg is non-copyable. +void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, + grpc_closure *closure, grpc_error *error); + +#endif /* GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H */ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 310851c583..5441af4c66 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -90,8 +90,8 @@ CORE_SOURCE_FILES = [ 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', - 'src/core/lib/iomgr/async_execution_lock.c', 'src/core/lib/iomgr/closure.c', + 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', diff --git a/test/core/iomgr/async_execution_lock_test.c b/test/core/iomgr/async_execution_lock_test.c deleted file mode 100644 index 526913bc3a..0000000000 --- a/test/core/iomgr/async_execution_lock_test.c +++ /dev/null @@ -1,124 +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. - * - */ - -#include "src/core/lib/iomgr/async_execution_lock.h" - -#include -#include -#include -#include - -#include "test/core/util/test_config.h" - -static void test_no_op(void) { - gpr_log(GPR_DEBUG, "test_no_op"); - grpc_aelock_destroy(grpc_aelock_create(NULL)); -} - -static void set_bool_to_true(grpc_exec_ctx *exec_ctx, void *value) { - *(bool *)value = true; -} - -static void test_execute_one(void) { - gpr_log(GPR_DEBUG, "test_execute_one"); - - grpc_aelock *lock = grpc_aelock_create(NULL); - bool done = false; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_aelock_execute(&exec_ctx, lock, set_bool_to_true, &done, 0); - grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(done); - grpc_aelock_destroy(lock); -} - -typedef struct { - size_t ctr; - grpc_aelock *lock; -} thd_args; - -typedef struct { - size_t *ctr; - size_t value; -} ex_args; - -static void check_one(grpc_exec_ctx *exec_ctx, void *a) { - ex_args *args = a; - // gpr_log(GPR_DEBUG, "*%p=%d; step %d", args->ctr, *args->ctr, args->value); - GPR_ASSERT(*args->ctr == args->value - 1); - *args->ctr = args->value; -} - -static void execute_many_loop(void *a) { - thd_args *args = a; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - size_t n = 1; - for (size_t i = 0; i < 10; i++) { - for (size_t j = 0; j < 10000; j++) { - ex_args c = {&args->ctr, n++}; - grpc_aelock_execute(&exec_ctx, args->lock, check_one, &c, sizeof(c)); - grpc_exec_ctx_flush(&exec_ctx); - } - gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); - } - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_execute_many(void) { - gpr_log(GPR_DEBUG, "test_execute_many"); - - grpc_aelock *lock = grpc_aelock_create(NULL); - gpr_thd_id thds[100]; - thd_args ta[GPR_ARRAY_SIZE(thds)]; - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - ta[i].ctr = 0; - ta[i].lock = lock; - GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &ta[i], &options)); - } - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_join(thds[i]); - } - grpc_aelock_destroy(lock); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_no_op(); - test_execute_one(); - test_execute_many(); - grpc_shutdown(); - - return 0; -} diff --git a/test/core/iomgr/combiner_test.c b/test/core/iomgr/combiner_test.c new file mode 100644 index 0000000000..090f7be832 --- /dev/null +++ b/test/core/iomgr/combiner_test.c @@ -0,0 +1,129 @@ +/* + * + * 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. + * + */ + +#include "src/core/lib/iomgr/combiner.h" + +#include +#include +#include +#include + +#include "test/core/util/test_config.h" + +static void test_no_op(void) { + gpr_log(GPR_DEBUG, "test_no_op"); + grpc_combiner_destroy(grpc_combiner_create(NULL)); +} + +static void set_bool_to_true(grpc_exec_ctx *exec_ctx, void *value, + grpc_error *error) { + *(bool *)value = true; +} + +static void test_execute_one(void) { + gpr_log(GPR_DEBUG, "test_execute_one"); + + grpc_combiner *lock = grpc_combiner_create(NULL); + bool done = false; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_combiner_execute(&exec_ctx, lock, + grpc_closure_create(set_bool_to_true, &done), + GRPC_ERROR_NONE); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(done); + grpc_combiner_destroy(lock); +} + +typedef struct { + size_t ctr; + grpc_combiner *lock; +} thd_args; + +typedef struct { + size_t *ctr; + size_t value; +} ex_args; + +static void check_one(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) { + ex_args *args = a; + // gpr_log(GPR_DEBUG, "*%p=%d; step %d", args->ctr, *args->ctr, args->value); + GPR_ASSERT(*args->ctr == args->value - 1); + *args->ctr = args->value; +} + +static void execute_many_loop(void *a) { + thd_args *args = a; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + size_t n = 1; + for (size_t i = 0; i < 10; i++) { + for (size_t j = 0; j < 10000; j++) { + ex_args c = {&args->ctr, n++}; + grpc_combiner_execute(&exec_ctx, args->lock, + grpc_closure_create(check_one, &c), + GRPC_ERROR_NONE); + grpc_exec_ctx_flush(&exec_ctx); + } + gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); + } + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_execute_many(void) { + gpr_log(GPR_DEBUG, "test_execute_many"); + + grpc_combiner *lock = grpc_combiner_create(NULL); + gpr_thd_id thds[100]; + thd_args ta[GPR_ARRAY_SIZE(thds)]; + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + ta[i].ctr = 0; + ta[i].lock = lock; + GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &ta[i], &options)); + } + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_join(thds[i]); + } + grpc_combiner_destroy(lock); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_no_op(); + test_execute_one(); + test_execute_many(); + grpc_shutdown(); + + return 0; +} diff --git a/test/core/support/mpscq_test.c b/test/core/support/mpscq_test.c index 4357a7c353..0b4bc254e2 100644 --- a/test/core/support/mpscq_test.c +++ b/test/core/support/mpscq_test.c @@ -109,7 +109,7 @@ static void test_mt(void) { if (tn->i == THREAD_ITERATIONS) num_done++; gpr_free(tn); } - gpr_log(GPR_DEBUG, "spins: %d", spins); + gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, spins); for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_join(thds[i]); } diff --git a/third_party/protobuf b/third_party/protobuf index d4d13a4349..3470b6895a 160000 --- a/third_party/protobuf +++ b/third_party/protobuf @@ -1 +1 @@ -Subproject commit d4d13a4349e4e59d67f311185ddcc1890d956d7a +Subproject commit 3470b6895aa659b7559ed678e029a5338e535f14 diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 8e78adf70f..afae199610 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -887,8 +887,8 @@ src/core/lib/debug/trace.h \ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ src/core/lib/http/parser.h \ -src/core/lib/iomgr/async_execution_lock.h \ src/core/lib/iomgr/closure.h \ +src/core/lib/iomgr/combiner.h \ src/core/lib/iomgr/endpoint.h \ src/core/lib/iomgr/endpoint_pair.h \ src/core/lib/iomgr/error.h \ @@ -1022,8 +1022,8 @@ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ -src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ +src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 9360febf8b..1a6bca9a4d 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -804,8 +804,8 @@ src/core/lib/debug/trace.h \ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ src/core/lib/http/parser.h \ -src/core/lib/iomgr/async_execution_lock.h \ src/core/lib/iomgr/closure.h \ +src/core/lib/iomgr/combiner.h \ src/core/lib/iomgr/endpoint.h \ src/core/lib/iomgr/endpoint_pair.h \ src/core/lib/iomgr/error.h \ @@ -960,8 +960,8 @@ src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ -src/core/lib/iomgr/async_execution_lock.c \ src/core/lib/iomgr/closure.c \ +src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 322d3f3451..0fde7ba084 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -79,22 +79,6 @@ "third_party": false, "type": "target" }, - { - "deps": [ - "gpr", - "gpr_test_util", - "grpc", - "grpc_test_util" - ], - "headers": [], - "language": "c", - "name": "async_execution_lock_test", - "src": [ - "test/core/iomgr/async_execution_lock_test.c" - ], - "third_party": false, - "type": "target" - }, { "deps": [ "gpr", @@ -252,6 +236,22 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "language": "c", + "name": "combiner_test", + "src": [ + "test/core/iomgr/combiner_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -5737,8 +5737,8 @@ "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", - "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -5839,10 +5839,10 @@ "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.c", "src/core/lib/http/parser.h", - "src/core/lib/iomgr/async_execution_lock.c", - "src/core/lib/iomgr/async_execution_lock.h", "src/core/lib/iomgr/closure.c", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.c", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index f654a7ba8e..fd5ff37389 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -93,12 +93,12 @@ "posix", "windows" ], - "cpu_cost": 30, + "cpu_cost": 1.0, "exclude_configs": [], "flaky": false, "gtest": false, "language": "c", - "name": "async_execution_lock_test", + "name": "bad_server_response_test", "platforms": [ "linux", "mac", @@ -119,7 +119,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "bad_server_response_test", + "name": "bin_decoder_test", "platforms": [ "linux", "mac", @@ -140,7 +140,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "bin_decoder_test", + "name": "bin_encoder_test", "platforms": [ "linux", "mac", @@ -161,7 +161,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "bin_encoder_test", + "name": "census_context_test", "platforms": [ "linux", "mac", @@ -182,7 +182,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "census_context_test", + "name": "channel_create_test", "platforms": [ "linux", "mac", @@ -203,7 +203,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "channel_create_test", + "name": "chttp2_hpack_encoder_test", "platforms": [ "linux", "mac", @@ -224,7 +224,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "chttp2_hpack_encoder_test", + "name": "chttp2_status_conversion_test", "platforms": [ "linux", "mac", @@ -245,7 +245,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "chttp2_status_conversion_test", + "name": "chttp2_stream_map_test", "platforms": [ "linux", "mac", @@ -266,7 +266,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "chttp2_stream_map_test", + "name": "chttp2_varint_test", "platforms": [ "linux", "mac", @@ -282,12 +282,12 @@ "posix", "windows" ], - "cpu_cost": 1.0, + "cpu_cost": 30, "exclude_configs": [], "flaky": false, "gtest": false, "language": "c", - "name": "chttp2_varint_test", + "name": "combiner_test", "platforms": [ "linux", "mac", diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index c3638685a8..c28ad2fc31 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -45,17 +45,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "alpn_test", "vcxproj\test\a {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "async_execution_lock_test", "vcxproj\test\async_execution_lock_test\async_execution_lock_test.vcxproj", "{5FC080AE-1FE8-2849-6481-E52ADBBC205C}" - 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}") = "bad_client_test", "vcxproj\test/bad_client\bad_client_test\bad_client_test.vcxproj", "{BA67B418-B699-E41A-9CC4-0279C49481A5}" ProjectSection(myProperties) = preProject lib = "True" @@ -175,6 +164,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chttp2_varint_test", "vcxpr {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "combiner_test", "vcxproj\test\combiner_test\combiner_test.vcxproj", "{C237D1E4-8825-80BA-1FC3-5E147E53E96E}" + 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}") = "compression_test", "vcxproj\test\compression_test\compression_test.vcxproj", "{5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}" ProjectSection(myProperties) = preProject lib = "False" @@ -1523,22 +1523,6 @@ Global {5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|Win32.Build.0 = Release|Win32 {5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|x64.ActiveCfg = Release|x64 {5BAAE7EA-A972-DD80-F190-29B9E3110BB3}.Release-DLL|x64.Build.0 = Release|x64 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug|Win32.ActiveCfg = Debug|Win32 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug|x64.ActiveCfg = Debug|x64 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release|Win32.ActiveCfg = Release|Win32 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release|x64.ActiveCfg = Release|x64 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug|Win32.Build.0 = Debug|Win32 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug|x64.Build.0 = Debug|x64 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release|Win32.Build.0 = Release|Win32 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release|x64.Build.0 = Release|x64 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug-DLL|Win32.Build.0 = Debug|Win32 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug-DLL|x64.ActiveCfg = Debug|x64 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Debug-DLL|x64.Build.0 = Debug|x64 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release-DLL|Win32.ActiveCfg = Release|Win32 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release-DLL|Win32.Build.0 = Release|Win32 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release-DLL|x64.ActiveCfg = Release|x64 - {5FC080AE-1FE8-2849-6481-E52ADBBC205C}.Release-DLL|x64.Build.0 = Release|x64 {BA67B418-B699-E41A-9CC4-0279C49481A5}.Debug|Win32.ActiveCfg = Debug|Win32 {BA67B418-B699-E41A-9CC4-0279C49481A5}.Debug|x64.ActiveCfg = Debug|x64 {BA67B418-B699-E41A-9CC4-0279C49481A5}.Release|Win32.ActiveCfg = Release|Win32 @@ -1715,6 +1699,22 @@ Global {6B29F634-1277-74B8-47F6-78756190BA7B}.Release-DLL|Win32.Build.0 = Release|Win32 {6B29F634-1277-74B8-47F6-78756190BA7B}.Release-DLL|x64.ActiveCfg = Release|x64 {6B29F634-1277-74B8-47F6-78756190BA7B}.Release-DLL|x64.Build.0 = Release|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|Win32.ActiveCfg = Debug|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|x64.ActiveCfg = Debug|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|Win32.ActiveCfg = Release|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|x64.ActiveCfg = Release|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|Win32.Build.0 = Debug|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|x64.Build.0 = Debug|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|Win32.Build.0 = Release|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|x64.Build.0 = Release|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|x64.Build.0 = Debug|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|Win32.Build.0 = Release|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|x64.ActiveCfg = Release|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|x64.Build.0 = Release|x64 {5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Debug|Win32.ActiveCfg = Debug|Win32 {5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Debug|x64.ActiveCfg = Debug|x64 {5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index d299686eae..bc6642bdb1 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -387,8 +387,8 @@ - + @@ -569,10 +569,10 @@ - - + + diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index 0a13d21893..2354d68748 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -136,10 +136,10 @@ src\core\lib\http - + src\core\lib\iomgr - + src\core\lib\iomgr @@ -836,10 +836,10 @@ src\core\lib\http - + src\core\lib\iomgr - + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index b20d46475b..6af4759449 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -383,8 +383,8 @@ - + @@ -555,10 +555,10 @@ - - + + diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index d12e3c7306..6985a1562c 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -121,10 +121,10 @@ src\core\lib\http - + src\core\lib\iomgr - + src\core\lib\iomgr @@ -809,10 +809,10 @@ src\core\lib\http - + src\core\lib\iomgr - + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 55f8fe85e2..e44299007e 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -313,8 +313,8 @@ - + @@ -485,10 +485,10 @@ - - + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 46b5710305..82a8ffb40a 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -43,10 +43,10 @@ src\core\lib\http - + src\core\lib\iomgr - + src\core\lib\iomgr @@ -698,10 +698,10 @@ src\core\lib\http - + src\core\lib\iomgr - + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 3e0aac4622..b993c9bdf7 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -302,8 +302,8 @@ - + @@ -452,10 +452,10 @@ - - + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index c922e48f61..4b0a7a01cd 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -46,10 +46,10 @@ src\core\lib\http - + src\core\lib\iomgr - + src\core\lib\iomgr @@ -605,10 +605,10 @@ src\core\lib\http - + src\core\lib\iomgr - + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj b/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj deleted file mode 100644 index 92b277801e..0000000000 --- a/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {5FC080AE-1FE8-2849-6481-E52ADBBC205C} - true - $(SolutionDir)IntDir\$(MSBuildProjectName)\ - - - - v100 - - - v110 - - - v120 - - - v140 - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - async_execution_lock_test - static - Debug - static - Debug - - - async_execution_lock_test - static - Release - static - Release - - - - NotUsing - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDebug - true - None - false - - - Console - true - false - - - - - - NotUsing - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDebug - true - None - false - - - Console - true - false - - - - - - NotUsing - Level3 - MaxSpeed - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - true - true - MultiThreaded - true - None - false - - - Console - true - false - true - true - - - - - - NotUsing - Level3 - MaxSpeed - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - true - true - MultiThreaded - true - None - false - - - Console - true - false - true - true - - - - - - - - - - {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} - - - {29D16885-7228-4C31-81ED-5F9187C7F2A9} - - - {EAB0A629-17A9-44DB-B5FF-E91A721FE037} - - - {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} - - - - - - - - - - - - - - - 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}. - - - - - - - - - diff --git a/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj.filters b/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj.filters deleted file mode 100644 index ff116cb9b0..0000000000 --- a/vsprojects/vcxproj/test/async_execution_lock_test/async_execution_lock_test.vcxproj.filters +++ /dev/null @@ -1,21 +0,0 @@ - - - - - test\core\iomgr - - - - - - {1553c040-57a4-1c71-539f-06be026b4844} - - - {112c4757-8861-21ed-d535-83c90a22e14b} - - - {341d4313-1479-2a6a-8ba4-a44c4c15e0d7} - - - - diff --git a/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj b/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj new file mode 100644 index 0000000000..f889d21e2d --- /dev/null +++ b/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj @@ -0,0 +1,199 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {C237D1E4-8825-80BA-1FC3-5E147E53E96E} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + combiner_test + static + Debug + static + Debug + + + combiner_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + 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}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters b/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters new file mode 100644 index 0000000000..e8ebb09898 --- /dev/null +++ b/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\iomgr + + + + + + {82bca2af-d499-b405-fd05-4d345372496c} + + + {c32d8e20-b719-532d-ba23-bd9d523fac15} + + + {b4fa8ca1-e6c7-dec5-6d62-8a62396825c6} + + + + -- cgit v1.2.3 From 09df1d6e6591edadd8346f56267ced5211ddde7d Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 7 Jul 2016 22:33:23 -0700 Subject: Make workqueue lockfree, and distributing --- src/core/lib/iomgr/combiner.h | 3 +- src/core/lib/iomgr/workqueue.h | 2 - src/core/lib/iomgr/workqueue_posix.c | 74 +++++++++++++++++++++++----------- src/core/lib/iomgr/workqueue_posix.h | 9 +++-- src/core/lib/iomgr/workqueue_windows.c | 2 - 5 files changed, 57 insertions(+), 33 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index cef1611acc..d16ce3d0f6 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -52,8 +52,7 @@ typedef struct grpc_combiner grpc_combiner; grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue); // Destroy the lock void grpc_combiner_destroy(grpc_combiner *lock); -// Execute \a action within the lock. \a arg is the argument to pass to \a -// action and sizeof_arg is the sizeof(*arg), or 0 if arg is non-copyable. +// Execute \a action within the lock. void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error); diff --git a/src/core/lib/iomgr/workqueue.h b/src/core/lib/iomgr/workqueue.h index 9f7219ebf1..416618e258 100644 --- a/src/core/lib/iomgr/workqueue.h +++ b/src/core/lib/iomgr/workqueue.h @@ -50,8 +50,6 @@ /* grpc_workqueue is forward declared in exec_ctx.h */ -void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue); - //#define GRPC_WORKQUEUE_REFCOUNT_DEBUG #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG #define GRPC_WORKQUEUE_REF(p, r) \ diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c index e0d6dac230..1d52a91694 100644 --- a/src/core/lib/iomgr/workqueue_posix.c +++ b/src/core/lib/iomgr/workqueue_posix.c @@ -52,8 +52,7 @@ grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, char name[32]; *workqueue = gpr_malloc(sizeof(grpc_workqueue)); gpr_ref_init(&(*workqueue)->refs, 1); - gpr_mu_init(&(*workqueue)->mu); - (*workqueue)->closure_list.head = (*workqueue)->closure_list.tail = NULL; + gpr_atm_no_barrier_store(&(*workqueue)->state, 1); grpc_error *err = grpc_wakeup_fd_init(&(*workqueue)->wakeup_fd); if (err != GRPC_ERROR_NONE) { gpr_free(*workqueue); @@ -62,6 +61,7 @@ grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, sprintf(name, "workqueue:%p", (void *)(*workqueue)); (*workqueue)->wakeup_read_fd = grpc_fd_create( GRPC_WAKEUP_FD_GET_READ_FD(&(*workqueue)->wakeup_fd), name); + gpr_mpscq_init(&(*workqueue)->queue); grpc_closure_init(&(*workqueue)->read_closure, on_readable, *workqueue); grpc_fd_notify_on_read(exec_ctx, (*workqueue)->wakeup_read_fd, &(*workqueue)->read_closure); @@ -70,10 +70,16 @@ grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, static void workqueue_destroy(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { - grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); grpc_fd_shutdown(exec_ctx, workqueue->wakeup_read_fd); } +static void workqueue_orphan(grpc_exec_ctx *exec_ctx, + grpc_workqueue *workqueue) { + if (gpr_atm_full_fetch_add(&workqueue->state, -1) == 1) { + workqueue_destroy(exec_ctx, workqueue); + } +} + #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) { @@ -96,31 +102,34 @@ void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { #endif if (gpr_unref(&workqueue->refs)) { - workqueue_destroy(exec_ctx, workqueue); + workqueue_orphan(exec_ctx, workqueue); } } -void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { - gpr_mu_lock(&workqueue->mu); - grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); - gpr_mu_unlock(&workqueue->mu); +static void drain(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { + abort(); +} + +static void wakeup(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { + grpc_error *err = grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd); + if (!GRPC_LOG_IF_ERROR("wakeupfd_wakeup", err)) { + drain(exec_ctx, workqueue); + } } static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_workqueue *workqueue = arg; if (error != GRPC_ERROR_NONE) { - gpr_mu_destroy(&workqueue->mu); /* HACK: let wakeup_fd code know that we stole the fd */ workqueue->wakeup_fd.read_fd = 0; grpc_wakeup_fd_destroy(&workqueue->wakeup_fd); grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy"); + drain(exec_ctx, workqueue); gpr_free(workqueue); } else { - gpr_mu_lock(&workqueue->mu); - grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); error = grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd); - gpr_mu_unlock(&workqueue->mu); + gpr_mpscq_node *n = gpr_mpscq_pop(&workqueue->queue); if (error == GRPC_ERROR_NONE) { grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd, &workqueue->read_closure); @@ -128,24 +137,41 @@ static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { /* recurse to get error handling */ on_readable(exec_ctx, arg, error); } + if (n == NULL) { + /* try again - queue in an inconsistant state */ + wakeup(exec_ctx, workqueue); + } else { + switch (gpr_atm_full_fetch_add(&workqueue->state, -2)) { + case 3: // had one count, one unorphaned --> done, unorphaned + break; + case 2: // had one count, one orphaned --> done, orphaned + workqueue_destroy(exec_ctx, workqueue); + break; + case 1: + case 0: + // these values are illegal - representing an already done or + // deleted workqueue + GPR_UNREACHABLE_CODE(break); + default: + // schedule a wakeup since there's more to do + wakeup(exec_ctx, workqueue); + } + grpc_closure *cl = (grpc_closure *)n; + grpc_error *clerr = cl->error; + cl->cb(exec_ctx, cl->cb_arg, clerr); + GRPC_ERROR_UNREF(clerr); + } } } void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, grpc_closure *closure, grpc_error *error) { - grpc_error *push_error = GRPC_ERROR_NONE; - gpr_mu_lock(&workqueue->mu); - if (grpc_closure_list_empty(workqueue->closure_list)) { - push_error = grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd); - } - grpc_closure_list_append(&workqueue->closure_list, closure, error); - if (push_error != GRPC_ERROR_NONE) { - const char *msg = grpc_error_string(push_error); - gpr_log(GPR_ERROR, "Failed to push to workqueue: %s", msg); - grpc_error_free_string(msg); - grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); + gpr_atm last = gpr_atm_full_fetch_add(&workqueue->state, 2); + GPR_ASSERT(last & 1); + gpr_mpscq_push(&workqueue->queue, &closure->next_data.atm_next); + if (last == 1) { + wakeup(exec_ctx, workqueue); } - gpr_mu_unlock(&workqueue->mu); } #endif /* GPR_POSIX_SOCKET */ diff --git a/src/core/lib/iomgr/workqueue_posix.h b/src/core/lib/iomgr/workqueue_posix.h index 2e8aca1816..c69ae8a941 100644 --- a/src/core/lib/iomgr/workqueue_posix.h +++ b/src/core/lib/iomgr/workqueue_posix.h @@ -35,14 +35,17 @@ #define GRPC_CORE_LIB_IOMGR_WORKQUEUE_POSIX_H #include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include "src/core/lib/support/mpscq.h" struct grpc_fd; struct grpc_workqueue { gpr_refcount refs; - - gpr_mu mu; - grpc_closure_list closure_list; + gpr_mpscq queue; + // state is: + // lower bit - zero if orphaned + // other bits - number of items enqueued + gpr_atm state; grpc_wakeup_fd wakeup_fd; struct grpc_fd *wakeup_read_fd; diff --git a/src/core/lib/iomgr/workqueue_windows.c b/src/core/lib/iomgr/workqueue_windows.c index 23e2dea185..ee81dc248e 100644 --- a/src/core/lib/iomgr/workqueue_windows.c +++ b/src/core/lib/iomgr/workqueue_windows.c @@ -42,8 +42,6 @@ // context, which is at least correct, if not performant or in the spirit of // workqueues. -void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} - #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) {} -- cgit v1.2.3 From ece4aaf578ac61e07b0a9a30a50b88425cdb7e25 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 7 Jul 2016 22:35:23 -0700 Subject: Fix header --- src/core/lib/iomgr/combiner.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index d16ce3d0f6..a3f75d48cf 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -31,8 +31,8 @@ * */ -#ifndef GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H -#define GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H +#ifndef GRPC_CORE_LIB_IOMGR_COMBINER_H +#define GRPC_CORE_LIB_IOMGR_COMBINER_H #include @@ -56,4 +56,4 @@ void grpc_combiner_destroy(grpc_combiner *lock); void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error); -#endif /* GRPC_CORE_LIB_IOMGR_ASYNC_EXECUTION_LOCK_H */ +#endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ -- cgit v1.2.3 From a36857da24b126300234f86450a61b7b2a7d0daa Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 8 Jul 2016 16:57:42 -0700 Subject: Progress on a finalization list --- src/core/lib/iomgr/closure.h | 2 ++ src/core/lib/iomgr/combiner.c | 76 +++++++++++++++++++++++++++++++++++------ src/core/lib/iomgr/combiner.h | 8 +++++ test/core/iomgr/combiner_test.c | 14 ++++++++ 4 files changed, 90 insertions(+), 10 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h index 310fcb1b86..c1a22b6021 100644 --- a/src/core/lib/iomgr/closure.h +++ b/src/core/lib/iomgr/closure.h @@ -89,6 +89,8 @@ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg); #define GRPC_CLOSURE_LIST_INIT \ { NULL, NULL } +void grpc_closure_list_init(grpc_closure_list *list); + /** add \a closure to the end of \a list and set \a closure's result to \a error */ void grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure, diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index 72e4d0edcb..00799e88c5 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -45,18 +45,18 @@ struct grpc_combiner { // lower bit - zero if orphaned // other bits - number of items queued on the lock gpr_atm state; + bool take_async_break_before_final_list; + grpc_closure_list final_list; grpc_closure continue_finishing; }; -static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error); - grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { grpc_combiner *lock = gpr_malloc(sizeof(*lock)); lock->optional_workqueue = optional_workqueue; gpr_atm_no_barrier_store(&lock->state, 1); gpr_mpscq_init(&lock->queue); - grpc_closure_init(&lock->continue_finishing, continue_finishing, lock); + lock->take_async_break_before_final_list = false; + grpc_closure_list_init(&lock->final_list); return lock; } @@ -72,11 +72,52 @@ void grpc_combiner_destroy(grpc_combiner *lock) { } } +static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); +static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); + +static void continue_finishing_mainline(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + if (maybe_finish_one(exec_ctx, arg)) finish(exec_ctx, arg); +} + +static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + grpc_closure *c = lock->final_list.head; + grpc_closure_list_init(&lock->final_list); + while (c != NULL) { + grpc_closure *next = c->next_data.next; + grpc_error *error = c->error; + c->cb(exec_ctx, c->cb_arg, error); + GRPC_ERROR_UNREF(error); + c = next; + } +} + +static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + execute_final(exec_ctx, arg); + finish(exec_ctx, arg); +} + +static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + if (lock->take_async_break_before_final_list) { + grpc_closure_init(&lock->continue_finishing, continue_executing_final, + lock); + grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, + lock->optional_workqueue); + return false; + } else { + execute_final(exec_ctx, lock); + return true; + } +} + static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); if (n == NULL) { // queue is in an inconsistant state: use this as a cue that we should // go off and do something else for a while (and come back later) + grpc_closure_init(&lock->continue_finishing, continue_finishing_mainline, + lock); grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, lock->optional_workqueue); return false; @@ -89,8 +130,16 @@ static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { } static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + bool (*executor)(grpc_exec_ctx * exec_ctx, grpc_combiner * lock) = + maybe_finish_one; do { switch (gpr_atm_full_fetch_add(&lock->state, -2)) { + case 5: // we're down to one queued item: if it's the final list we + case 4: // should do that + if (!grpc_closure_list_empty(lock->final_list)) { + executor = start_execute_final; + } + break; case 3: // had one count, one unorphaned --> unlocked unorphaned return; case 2: // and one count, one orphaned --> unlocked and orphaned @@ -102,12 +151,7 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { // deleted lock GPR_UNREACHABLE_CODE(return ); } - } while (maybe_finish_one(exec_ctx, lock)); -} - -static void continue_finishing(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - if (maybe_finish_one(exec_ctx, arg)) finish(exec_ctx, arg); + } while (executor(exec_ctx, lock)); } void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, @@ -123,3 +167,15 @@ void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); } } + +void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, + grpc_closure *closure, grpc_error *error, + bool force_async_break) { + if (force_async_break) { + lock->take_async_break_before_final_list = true; + } + if (grpc_closure_list_empty(lock->final_list)) { + gpr_atm_full_fetch_add(&lock->state, 2); + } + grpc_closure_list_append(&lock->final_list, closure, error); +} diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index a3f75d48cf..d6bc27111f 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -55,5 +55,13 @@ void grpc_combiner_destroy(grpc_combiner *lock); // Execute \a action within the lock. void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error); +// Execute \a action within the lock just prior to unlocking. +// if \a force_async_break is additionally set, the combiner is forced to trip +// through the workqueue between finishing the primary queue of combined +// closures and executing the finally list. +// Can only be called from within a closure scheduled by grpc_combiner_execute +void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, + grpc_closure *closure, grpc_error *error, + bool force_async_break); #endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ diff --git a/test/core/iomgr/combiner_test.c b/test/core/iomgr/combiner_test.c index 925a4f81ad..d9f7601722 100644 --- a/test/core/iomgr/combiner_test.c +++ b/test/core/iomgr/combiner_test.c @@ -120,12 +120,26 @@ static void test_execute_many(void) { grpc_combiner_destroy(lock); } +static void test_execute_finally(void) { + gpr_log(GPR_DEBUG, "test_execute_finally"); + + grpc_combiner *lock = grpc_combiner_create(NULL); + bool done = false; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_combiner_execute(&exec_ctx, lock, grpc_closure_create(add_finally, lock), + GRPC_ERROR_NONE); + grpc_exec_ctx_finish(&exec_ctx); + GPR_ASSERT(done); + grpc_combiner_destroy(lock); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_init(); test_no_op(); test_execute_one(); test_execute_many(); + test_execute_finally(); grpc_shutdown(); return 0; -- cgit v1.2.3 From 8d8d0d3d10709fe3413f5112531d89a5531203e7 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 8 Jul 2016 17:08:57 -0700 Subject: Get combiner finalization lists working --- src/core/lib/iomgr/closure.c | 4 ++++ test/core/iomgr/combiner_test.c | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/closure.c b/src/core/lib/iomgr/closure.c index 0b6c3b2539..1ba0a5c141 100644 --- a/src/core/lib/iomgr/closure.c +++ b/src/core/lib/iomgr/closure.c @@ -41,6 +41,10 @@ void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb, closure->cb_arg = cb_arg; } +void grpc_closure_list_init(grpc_closure_list *closure_list) { + closure_list->head = closure_list->tail = NULL; +} + void grpc_closure_list_append(grpc_closure_list *closure_list, grpc_closure *closure, grpc_error *error) { if (closure == NULL) { diff --git a/test/core/iomgr/combiner_test.c b/test/core/iomgr/combiner_test.c index d9f7601722..0aaeada345 100644 --- a/test/core/iomgr/combiner_test.c +++ b/test/core/iomgr/combiner_test.c @@ -120,16 +120,27 @@ static void test_execute_many(void) { grpc_combiner_destroy(lock); } +static bool got_in_finally = false; + +static void in_finally(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + got_in_finally = true; +} + +static void add_finally(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + grpc_combiner_execute_finally(exec_ctx, arg, + grpc_closure_create(in_finally, NULL), + GRPC_ERROR_NONE, false); +} + static void test_execute_finally(void) { gpr_log(GPR_DEBUG, "test_execute_finally"); grpc_combiner *lock = grpc_combiner_create(NULL); - bool done = false; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_combiner_execute(&exec_ctx, lock, grpc_closure_create(add_finally, lock), GRPC_ERROR_NONE); grpc_exec_ctx_finish(&exec_ctx); - GPR_ASSERT(done); + GPR_ASSERT(got_in_finally); grpc_combiner_destroy(lock); } @@ -138,8 +149,8 @@ int main(int argc, char **argv) { grpc_init(); test_no_op(); test_execute_one(); - test_execute_many(); test_execute_finally(); + test_execute_many(); grpc_shutdown(); return 0; -- cgit v1.2.3 From 6e7b45ed215fe113abed17002fddf5635c97549c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 8 Jul 2016 17:25:49 -0700 Subject: Make transport_stream_ops all be heap allocated --- src/core/lib/channel/channel_stack.c | 23 +++++--- src/core/lib/channel/compress_filter.c | 14 ++--- .../lib/security/transport/server_auth_filter.c | 27 ++++++---- src/core/lib/surface/call.c | 63 +++++++++++----------- 4 files changed, 71 insertions(+), 56 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c index 87175d7943..e1375348a9 100644 --- a/src/core/lib/channel/channel_stack.c +++ b/src/core/lib/channel/channel_stack.c @@ -32,6 +32,7 @@ */ #include "src/core/lib/channel/channel_stack.h" +#include #include #include @@ -259,21 +260,27 @@ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) { sizeof(grpc_call_stack))); } +static void destroy_op(grpc_exec_ctx *exec_ctx, void *op, grpc_error *error) { + gpr_free(op); +} + void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx, grpc_call_element *cur_elem) { - grpc_transport_stream_op op; - memset(&op, 0, sizeof(op)); - op.cancel_error = GRPC_ERROR_CANCELLED; - grpc_call_next_op(exec_ctx, cur_elem, &op); + grpc_transport_stream_op *op = gpr_malloc(sizeof(*op)); + memset(op, 0, sizeof(*op)); + op->cancel_error = GRPC_ERROR_CANCELLED; + op->on_complete = grpc_closure_create(destroy_op, op); + grpc_call_next_op(exec_ctx, cur_elem, op); } void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx, grpc_call_element *cur_elem, grpc_status_code status, gpr_slice *optional_message) { - grpc_transport_stream_op op; - memset(&op, 0, sizeof(op)); - grpc_transport_stream_op_add_cancellation_with_message(&op, status, + grpc_transport_stream_op *op = gpr_malloc(sizeof(*op)); + memset(op, 0, sizeof(*op)); + op->on_complete = grpc_closure_create(destroy_op, op); + grpc_transport_stream_op_add_cancellation_with_message(op, status, optional_message); - grpc_call_next_op(exec_ctx, cur_elem, &op); + grpc_call_next_op(exec_ctx, cur_elem, op); } diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c index 32ebe53ee6..d4b1cf0296 100644 --- a/src/core/lib/channel/compress_filter.c +++ b/src/core/lib/channel/compress_filter.c @@ -60,7 +60,7 @@ typedef struct call_data { /** If true, contents of \a compression_algorithm are authoritative */ int has_compression_algorithm; - grpc_transport_stream_op send_op; + grpc_transport_stream_op *send_op; uint32_t send_length; uint32_t send_flags; gpr_slice incoming_slice; @@ -199,11 +199,11 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx, grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices, calld->send_flags); - calld->send_op.send_message = &calld->replacement_stream.base; - calld->post_send = calld->send_op.on_complete; - calld->send_op.on_complete = &calld->send_done; + calld->send_op->send_message = &calld->replacement_stream.base; + calld->post_send = calld->send_op->on_complete; + calld->send_op->on_complete = &calld->send_done; - grpc_call_next_op(exec_ctx, elem, &calld->send_op); + grpc_call_next_op(exec_ctx, elem, calld->send_op); } static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { @@ -220,7 +220,7 @@ static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { static void continue_send_message(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { call_data *calld = elem->call_data; - while (grpc_byte_stream_next(exec_ctx, calld->send_op.send_message, + while (grpc_byte_stream_next(exec_ctx, calld->send_op->send_message, &calld->incoming_slice, ~(size_t)0, &calld->got_slice)) { gpr_slice_buffer_add(&calld->slices, calld->incoming_slice); @@ -243,7 +243,7 @@ static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx, } if (op->send_message != NULL && !skip_compression(elem) && 0 == (op->send_message->flags & GRPC_WRITE_NO_COMPRESS)) { - calld->send_op = *op; + calld->send_op = op; calld->send_length = op->send_message->length; calld->send_flags = op->send_message->flags; continue_send_message(exec_ctx, elem); diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c index 12e789bde9..1958a72b93 100644 --- a/src/core/lib/security/transport/server_auth_filter.c +++ b/src/core/lib/security/transport/server_auth_filter.c @@ -48,7 +48,7 @@ typedef struct call_data { up-call on transport_op, and remember to call our on_done_recv member after handling it. */ grpc_closure auth_on_recv; - grpc_transport_stream_op transport_op; + grpc_transport_stream_op *transport_op; grpc_metadata_array md; const grpc_metadata *consumed_md; size_t num_consumed_md; @@ -106,6 +106,10 @@ static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) { return md; } +static void destroy_op(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + gpr_free(arg); +} + /* called from application code */ static void on_md_processing_done( void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md, @@ -131,21 +135,22 @@ static void on_md_processing_done( grpc_exec_ctx_sched(&exec_ctx, calld->on_done_recv, GRPC_ERROR_NONE, NULL); } else { gpr_slice message; - grpc_transport_stream_op close_op; - memset(&close_op, 0, sizeof(close_op)); + grpc_transport_stream_op *close_op = gpr_malloc(sizeof(*close_op)); + memset(close_op, 0, sizeof(*close_op)); grpc_metadata_array_destroy(&calld->md); error_details = error_details != NULL ? error_details : "Authentication metadata processing failed."; message = gpr_slice_from_copied_string(error_details); - calld->transport_op.send_initial_metadata = NULL; - if (calld->transport_op.send_message != NULL) { - grpc_byte_stream_destroy(&exec_ctx, calld->transport_op.send_message); - calld->transport_op.send_message = NULL; + calld->transport_op->send_initial_metadata = NULL; + if (calld->transport_op->send_message != NULL) { + grpc_byte_stream_destroy(&exec_ctx, calld->transport_op->send_message); + calld->transport_op->send_message = NULL; } - calld->transport_op.send_trailing_metadata = NULL; - grpc_transport_stream_op_add_close(&close_op, status, &message); - grpc_call_next_op(&exec_ctx, elem, &close_op); + calld->transport_op->send_trailing_metadata = NULL; + close_op->on_complete = grpc_closure_create(destroy_op, close_op); + grpc_transport_stream_op_add_close(close_op, status, &message); + grpc_call_next_op(&exec_ctx, elem, close_op); grpc_exec_ctx_sched(&exec_ctx, calld->on_done_recv, grpc_error_set_int(GRPC_ERROR_CREATE(error_details), GRPC_ERROR_INT_GRPC_STATUS, status), @@ -182,7 +187,7 @@ static void set_recv_ops_md_callbacks(grpc_call_element *elem, calld->recv_initial_metadata = op->recv_initial_metadata; calld->on_done_recv = op->recv_initial_metadata_ready; op->recv_initial_metadata_ready = &calld->auth_on_recv; - calld->transport_op = *op; + calld->transport_op = op; } } diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index e5668be47f..7739a395b9 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -109,6 +109,10 @@ typedef struct batch_control { uint8_t recv_message; uint8_t recv_final_op; uint8_t is_notify_tag_closure; + + /* TODO(ctiller): now that this is inlined, figure out how much of the above + state can be eliminated */ + grpc_transport_stream_op op; } batch_control; struct grpc_call { @@ -761,6 +765,7 @@ typedef struct termination_closure { grpc_error *error; grpc_closure *op_closure; enum { TC_CANCEL, TC_CLOSE } type; + grpc_transport_stream_op op; } termination_closure; static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp, @@ -780,26 +785,24 @@ static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp, } static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { - grpc_transport_stream_op op; termination_closure *tc = tcp; - memset(&op, 0, sizeof(op)); - op.cancel_error = tc->error; + memset(&tc->op, 0, sizeof(tc->op)); + tc->op.cancel_error = tc->error; /* reuse closure to catch completion */ grpc_closure_init(&tc->closure, done_termination, tc); - op.on_complete = &tc->closure; - execute_op(exec_ctx, tc->call, &op); + tc->op.on_complete = &tc->closure; + execute_op(exec_ctx, tc->call, &tc->op); } static void send_close(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { - grpc_transport_stream_op op; termination_closure *tc = tcp; - memset(&op, 0, sizeof(op)); - op.close_error = tc->error; + memset(&tc->op, 0, sizeof(tc->op)); + tc->op.close_error = tc->error; /* reuse closure to catch completion */ grpc_closure_init(&tc->closure, done_termination, tc); - tc->op_closure = op.on_complete; - op.on_complete = &tc->closure; - execute_op(exec_ctx, tc->call, &op); + tc->op_closure = tc->op.on_complete; + tc->op.on_complete = &tc->closure; + execute_op(exec_ctx, tc->call, &tc->op); } static grpc_call_error terminate_with_status(grpc_exec_ctx *exec_ctx, @@ -1353,7 +1356,6 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_call *call, const grpc_op *ops, size_t nops, void *notify_tag, int is_notify_tag_closure) { - grpc_transport_stream_op stream_op; size_t i; const grpc_op *op; batch_control *bctl; @@ -1364,8 +1366,6 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag); - memset(&stream_op, 0, sizeof(stream_op)); - /* TODO(ctiller): this feels like it could be made lock-free */ gpr_mu_lock(&call->mu); bctl = allocate_batch_control(call); @@ -1374,6 +1374,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, bctl->notify_tag = notify_tag; bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0); + grpc_transport_stream_op *stream_op = &bctl->op; + memset(stream_op, 0, sizeof(*stream_op)); + if (nops == 0) { GRPC_CALL_INTERNAL_REF(call, "completion"); bctl->error = GRPC_ERROR_NONE; @@ -1452,9 +1455,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, } /* TODO(ctiller): just make these the same variable? */ call->metadata_batch[0][0].deadline = call->send_deadline; - stream_op.send_initial_metadata = + stream_op->send_initial_metadata = &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]; - stream_op.send_initial_metadata_flags = op->flags; + stream_op->send_initial_metadata_flags = op->flags; break; case GRPC_OP_SEND_MESSAGE: if (!are_write_flags_valid(op->flags)) { @@ -1474,7 +1477,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_slice_buffer_stream_init( &call->sending_stream, &op->data.send_message->data.raw.slice_buffer, op->flags); - stream_op.send_message = &call->sending_stream.base; + stream_op->send_message = &call->sending_stream.base; break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: /* Flag validation: currently allow no flags */ @@ -1492,7 +1495,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, } bctl->send_final_op = 1; call->sent_final_op = 1; - stream_op.send_trailing_metadata = + stream_op->send_trailing_metadata = &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]; break; case GRPC_OP_SEND_STATUS_FROM_SERVER: @@ -1539,7 +1542,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, error = GRPC_CALL_ERROR_INVALID_METADATA; goto done_with_error; } - stream_op.send_trailing_metadata = + stream_op->send_trailing_metadata = &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]; break; case GRPC_OP_RECV_INITIAL_METADATA: @@ -1557,9 +1560,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_closure_init(&call->receiving_initial_metadata_ready, receiving_initial_metadata_ready, bctl); bctl->recv_initial_metadata = 1; - stream_op.recv_initial_metadata = + stream_op->recv_initial_metadata = &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */]; - stream_op.recv_initial_metadata_ready = + stream_op->recv_initial_metadata_ready = &call->receiving_initial_metadata_ready; num_completion_callbacks_needed++; break; @@ -1576,10 +1579,10 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->receiving_message = 1; bctl->recv_message = 1; call->receiving_buffer = op->data.recv_message; - stream_op.recv_message = &call->receiving_stream; + stream_op->recv_message = &call->receiving_stream; grpc_closure_init(&call->receiving_stream_ready, receiving_stream_ready, bctl); - stream_op.recv_message_ready = &call->receiving_stream_ready; + stream_op->recv_message_ready = &call->receiving_stream_ready; num_completion_callbacks_needed++; break; case GRPC_OP_RECV_STATUS_ON_CLIENT: @@ -1605,9 +1608,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->final_op.client.status_details_capacity = op->data.recv_status_on_client.status_details_capacity; bctl->recv_final_op = 1; - stream_op.recv_trailing_metadata = + stream_op->recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - stream_op.collect_stats = &call->stats.transport_stream_stats; + stream_op->collect_stats = &call->stats.transport_stream_stats; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: /* Flag validation: currently allow no flags */ @@ -1627,9 +1630,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->final_op.server.cancelled = op->data.recv_close_on_server.cancelled; bctl->recv_final_op = 1; - stream_op.recv_trailing_metadata = + stream_op->recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - stream_op.collect_stats = &call->stats.transport_stream_stats; + stream_op->collect_stats = &call->stats.transport_stream_stats; break; } } @@ -1640,12 +1643,12 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, } gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed); - stream_op.context = call->context; + stream_op->context = call->context; grpc_closure_init(&bctl->finish_batch, finish_batch, bctl); - stream_op.on_complete = &bctl->finish_batch; + stream_op->on_complete = &bctl->finish_batch; gpr_mu_unlock(&call->mu); - execute_op(exec_ctx, call, &stream_op); + execute_op(exec_ctx, call, stream_op); done: GPR_TIMER_END("grpc_call_start_batch", 0); -- cgit v1.2.3 From 4e43685e511a1a3c19ac4060a8ee9f7894dea94d Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Sun, 10 Jul 2016 14:01:50 -0700 Subject: Afford other threads the opportunity to insert into a combiner prior to the final list being executed but after the async pause --- src/core/lib/iomgr/combiner.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index 00799e88c5..34e8f43905 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -83,6 +83,7 @@ static void continue_finishing_mainline(grpc_exec_ctx *exec_ctx, void *arg, static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { grpc_closure *c = lock->final_list.head; grpc_closure_list_init(&lock->final_list); + lock->take_async_break_before_final_list = false; while (c != NULL) { grpc_closure *next = c->next_data.next; grpc_error *error = c->error; @@ -94,8 +95,15 @@ static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - execute_final(exec_ctx, arg); - finish(exec_ctx, arg); + grpc_combiner *lock = arg; + // quick peek to see if new things have turned up on the queue: if so, go back + // to executing them before the final list + if ((gpr_atm_acq_load(&lock->state) >> 1) > 1) { + if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); + } else { + execute_final(exec_ctx, lock); + finish(exec_ctx, lock); + } } static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { -- cgit v1.2.3 From 93023e410b0ab351a9a4bb6312327f18d5fa4b68 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 11 Jul 2016 12:43:23 -0700 Subject: Progress to converting chttp2 to combiner locks --- .../transport/chttp2/transport/chttp2_transport.c | 612 +++++++-------------- src/core/ext/transport/chttp2/transport/internal.h | 46 +- src/core/lib/iomgr/combiner.c | 4 + src/core/lib/iomgr/combiner.h | 1 + src/core/lib/transport/transport.h | 17 + 5 files changed, 245 insertions(+), 435 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 41506094de..a3020236cf 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -31,6 +31,9 @@ * */ +// TODO(ctiller): schedule check_read_ops whenever something is added to that +// list + #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include @@ -89,8 +92,14 @@ static const grpc_transport_vtable vtable; static void writing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void reading_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void parsing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); -static void initiate_writing(grpc_exec_ctx *exec_ctx, void *t, - grpc_error *error); +static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void initiate_writing_locked(grpc_exec_ctx *exec_ctx, void *t, + grpc_error *error); +static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *t, + grpc_error *error); static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, @@ -104,11 +113,6 @@ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error); -/** Perform a transport_op */ -static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, void *transport_op); - /** Cancel a stream: coming from the transport API */ static void cancel_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, @@ -120,22 +124,10 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_global *stream_global, grpc_error *error); -/** Add endpoint from this transport to pollset */ -static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_ignored, void *pollset); -static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_ignored, - void *pollset_set); - /** Start new streams that have been created if we can */ static void maybe_start_some_streams( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global); -static void finish_global_actions(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t); - static void connectivity_state_set( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_connectivity_state state, grpc_error *error, const char *reason); @@ -148,9 +140,8 @@ static void incoming_byte_stream_update_flow_control( grpc_chttp2_stream_global *stream_global, size_t max_size_hint, size_t have_already); static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *byte_stream); + void *byte_stream, + grpc_error *error_ignored); static void fail_pending_writes(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global, @@ -164,9 +155,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { size_t i; - gpr_mu_lock(&t->executor.mu); - - GPR_ASSERT(t->ep == NULL); + grpc_endpoint_destroy(exec_ctx, t->ep); gpr_slice_buffer_destroy(&t->global.qbuf); @@ -190,8 +179,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_map_destroy(&t->new_stream_map); grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker); - gpr_mu_unlock(&t->executor.mu); - gpr_mu_destroy(&t->executor.mu); + grpc_combiner_destroy(t->executor.combiner); /* callback remaining pings: they're not allowed to call into the transpot, and maybe they hold resources that need to be freed */ @@ -250,11 +238,11 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, t->base.vtable = &vtable; t->ep = ep; - /* one ref is for destroy, the other for when ep becomes NULL */ - gpr_ref_init(&t->refs, 2); + /* one ref is for destroy */ + gpr_ref_init(&t->refs, 1); /* ref is dropped at transport close() */ gpr_ref_init(&t->shutdown_ep_refs, 1); - gpr_mu_init(&t->executor.mu); + t->executor.combiner = grpc_combiner_create(grpc_endpoint_get_workqueue(ep)); t->peer_string = grpc_endpoint_get_peer(ep); t->endpoint_reading = 1; t->global.next_stream_id = is_client ? 1 : 2; @@ -280,15 +268,18 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor); grpc_closure_init(&t->writing_action, writing_action, t); grpc_closure_init(&t->reading_action, reading_action, t); + grpc_closure_init(&t->reading_action_locked, reading_action_locked, t); grpc_closure_init(&t->parsing_action, parsing_action, t); - grpc_closure_init(&t->initiate_writing, initiate_writing, t); + grpc_closure_init(&t->post_parse_locked, post_parse_locked, t); + grpc_closure_init(&t->initiate_writing, initiate_writing_locked, t); + grpc_closure_init(&t->terminate_writing, terminate_writing_with_lock, t); + grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, + &t->writing); gpr_slice_buffer_init(&t->parsing.qbuf); grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser); - grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, - &t->writing); gpr_slice_buffer_init(&t->read_buffer); if (is_client) { @@ -412,45 +403,34 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, } } -static void destroy_transport_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_ignored, - void *arg_ignored) { +static void destroy_transport_locked(grpc_exec_ctx *exec_ctx, void *tp, + grpc_error *error) { + grpc_chttp2_transport *t = tp; t->destroying = 1; drop_connection(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed")); } static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, destroy_transport_locked, - NULL, 0); + grpc_combiner_execute(exec_ctx, t->executor.combiner, + grpc_closure_create(destroy_transport_locked, t), + GRPC_ERROR_NONE); UNREF_TRANSPORT(exec_ctx, t, "destroy"); } /** block grpc_endpoint_shutdown being called until a paired allow_endpoint_shutdown is made */ static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) { - GPR_ASSERT(t->ep); gpr_ref(&t->shutdown_ep_refs); } static void allow_endpoint_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { if (gpr_unref(&t->shutdown_ep_refs)) { - if (t->ep) { - grpc_endpoint_shutdown(exec_ctx, t->ep); - } + grpc_endpoint_shutdown(exec_ctx, t->ep); } } -static void destroy_endpoint(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - grpc_endpoint_destroy(exec_ctx, t->ep); - t->ep = NULL; - /* safe because we'll still have the ref for write */ - UNREF_TRANSPORT(exec_ctx, t, "disconnect"); -} - static void close_transport_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { @@ -461,9 +441,7 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx, t->closed = 1; connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), "close_transport"); - if (t->ep) { - allow_endpoint_shutdown_locked(exec_ctx, t); - } + allow_endpoint_shutdown_locked(exec_ctx, t); /* flush writable stream list to avoid dangling references */ grpc_chttp2_stream_global *stream_global; @@ -497,11 +475,10 @@ void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, } #endif -static void finish_init_stream_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *arg_ignored) { - grpc_chttp2_register_stream(t, s); +static void finish_init_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, + grpc_error *error) { + grpc_chttp2_stream *s = sp; + grpc_chttp2_register_stream(s->t, s); } static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, @@ -509,6 +486,7 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, const void *server_data) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; + s->t = t; memset(s, 0, sizeof(*s)); @@ -545,16 +523,18 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, s->global.in_stream_map = true; } - grpc_chttp2_run_with_global_lock(exec_ctx, t, s, finish_init_stream_locked, - NULL, 0); + grpc_closure_init(&s->init_stream, finish_init_stream_locked, s); + grpc_combiner_execute(exec_ctx, t->executor.combiner, &s->init_stream, + GRPC_ERROR_NONE); return 0; } -static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, void *arg) { +static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, + grpc_error *error) { grpc_byte_stream *bs; + grpc_chttp2_stream *s = sp; + grpc_chttp2_transport *t = s->t; GPR_TIMER_BEGIN("destroy_stream", 0); @@ -573,7 +553,7 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, while ( (bs = grpc_chttp2_incoming_frame_queue_pop(&s->global.incoming_frames))) { - incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global, @@ -610,7 +590,7 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, GPR_TIMER_END("destroy_stream", 0); - gpr_free(arg); + gpr_free(s->destroy_stream_arg); } static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, @@ -618,8 +598,10 @@ static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - grpc_chttp2_run_with_global_lock(exec_ctx, t, s, destroy_stream_locked, - and_free_memory, 0); + s->destroy_stream_arg = and_free_memory; + grpc_closure_init(&s->destroy_stream, destroy_stream_locked, s); + grpc_combiner_execute(exec_ctx, t->executor.combiner, &s->destroy_stream, + GRPC_ERROR_NONE); } grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream( @@ -652,10 +634,6 @@ static const char *write_state_name(grpc_chttp2_write_state state) { switch (state) { case GRPC_CHTTP2_WRITING_INACTIVE: return "INACTIVE"; - case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: - return "REQUESTED[p=0]"; - case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: - return "REQUESTED[p=1]"; case GRPC_CHTTP2_WRITE_SCHEDULED: return "SCHEDULED"; case GRPC_CHTTP2_WRITING: @@ -678,119 +656,17 @@ static void set_write_state(grpc_chttp2_transport *t, t->executor.write_state = state; } -static void finish_global_actions(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - grpc_chttp2_executor_action_header *hdr; - grpc_chttp2_executor_action_header *next; - - GPR_TIMER_BEGIN("finish_global_actions", 0); - - for (;;) { - check_read_ops(exec_ctx, &t->global); - - gpr_mu_lock(&t->executor.mu); - if (t->executor.pending_actions_head != NULL) { - hdr = t->executor.pending_actions_head; - t->executor.pending_actions_head = t->executor.pending_actions_tail = - NULL; - gpr_mu_unlock(&t->executor.mu); - while (hdr != NULL) { - GPR_TIMER_BEGIN("chttp2:locked_action", 0); - hdr->action(exec_ctx, t, hdr->stream, hdr->arg); - GPR_TIMER_END("chttp2:locked_action", 0); - next = hdr->next; - gpr_free(hdr); - UNREF_TRANSPORT(exec_ctx, t, "pending_action"); - hdr = next; - } - continue; - } else { - t->executor.global_active = false; - switch (t->executor.write_state) { - case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: - set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "unlocking"); - REF_TRANSPORT(t, "initiate_writing"); - gpr_mu_unlock(&t->executor.mu); - grpc_exec_ctx_sched(exec_ctx, &t->initiate_writing, GRPC_ERROR_NONE, - grpc_endpoint_get_workqueue(t->ep)); - break; - case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: - start_writing(exec_ctx, t); - gpr_mu_unlock(&t->executor.mu); - break; - case GRPC_CHTTP2_WRITING_INACTIVE: - case GRPC_CHTTP2_WRITING: - case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: - case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: - case GRPC_CHTTP2_WRITE_SCHEDULED: - gpr_mu_unlock(&t->executor.mu); - break; - } - } - break; - } - - GPR_TIMER_END("finish_global_actions", 0); +static void initiate_writing_locked(grpc_exec_ctx *exec_ctx, void *tp, + grpc_error *error) { + grpc_chttp2_transport *t = tp; + GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED); + start_writing(exec_ctx, t); } -void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *optional_stream, - grpc_chttp2_locked_action action, - void *arg, size_t sizeof_arg) { - grpc_chttp2_executor_action_header *hdr; - - GPR_TIMER_BEGIN("grpc_chttp2_run_with_global_lock", 0); - - REF_TRANSPORT(t, "run_global"); - gpr_mu_lock(&t->executor.mu); - - for (;;) { - if (!t->executor.global_active) { - t->executor.global_active = 1; - gpr_mu_unlock(&t->executor.mu); - - GPR_TIMER_BEGIN("chttp2:locked_action", 0); - action(exec_ctx, t, optional_stream, arg); - GPR_TIMER_END("chttp2:locked_action", 0); - - finish_global_actions(exec_ctx, t); - } else { - gpr_mu_unlock(&t->executor.mu); - - hdr = gpr_malloc(sizeof(*hdr) + sizeof_arg); - hdr->stream = optional_stream; - hdr->action = action; - if (sizeof_arg == 0) { - hdr->arg = arg; - } else { - hdr->arg = hdr + 1; - memcpy(hdr->arg, arg, sizeof_arg); - } - - gpr_mu_lock(&t->executor.mu); - if (!t->executor.global_active) { - /* global lock was released while allocating memory: release & retry */ - gpr_free(hdr); - continue; - } - hdr->next = NULL; - if (t->executor.pending_actions_head != NULL) { - t->executor.pending_actions_tail = - t->executor.pending_actions_tail->next = hdr; - } else { - t->executor.pending_actions_tail = t->executor.pending_actions_head = - hdr; - } - REF_TRANSPORT(t, "pending_action"); - gpr_mu_unlock(&t->executor.mu); - } - break; - } - - UNREF_TRANSPORT(exec_ctx, t, "run_global"); - - GPR_TIMER_END("grpc_chttp2_run_with_global_lock", 0); +static void initiate_read_flush_locked(grpc_exec_ctx *exec_ctx, void *tp, + grpc_error *error) { + grpc_chttp2_transport *t = tp; + check_read_ops(exec_ctx, &t->global); } /******************************************************************************* @@ -803,23 +679,17 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global); switch (t->executor.write_state) { case GRPC_CHTTP2_WRITING_INACTIVE: - set_write_state(t, covered_by_poller - ? GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER - : GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, - reason); - break; - case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: - /* nothing to do: write already requested */ + set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, reason); + grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, + &t->initiate_writing, GRPC_ERROR_NONE, + covered_by_poller); break; - case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: + case GRPC_CHTTP2_WRITE_SCHEDULED: if (covered_by_poller) { /* upgrade to note poller is available to cover the write */ - set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, reason); + grpc_combiner_force_async_finally(t->executor.combiner); } break; - case GRPC_CHTTP2_WRITE_SCHEDULED: - /* nothing to do: write already scheduled */ - break; case GRPC_CHTTP2_WRITING: set_write_state(t, covered_by_poller ? GRPC_CHTTP2_WRITING_STALE_WITH_POLLER @@ -839,8 +709,7 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, } static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { - GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED || - t->executor.write_state == GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER); + GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED); if (!t->closed && grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) { set_write_state(t, GRPC_CHTTP2_WRITING, "start_writing"); @@ -856,26 +725,9 @@ static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { "start_writing:nothing_to_write"); } end_waiting_for_write(exec_ctx, t, GRPC_ERROR_CREATE("Nothing to write")); - if (t->ep && !t->endpoint_reading) { - destroy_endpoint(exec_ctx, t); - } } } -static void initiate_writing_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, - void *arg_ignored) { - start_writing(exec_ctx, t); - UNREF_TRANSPORT(exec_ctx, t, "initiate_writing"); -} - -static void initiate_writing(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_chttp2_run_with_global_lock(exec_ctx, arg, NULL, initiate_writing_locked, - NULL, 0); -} - void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global, @@ -916,12 +768,9 @@ static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, GRPC_ERROR_UNREF(error); } -static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_ignored, - void *a) { - grpc_error *error = a; - +static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *tp, + grpc_error *error) { + grpc_chttp2_transport *t = tp; allow_endpoint_shutdown_locked(exec_ctx, t); if (error != GRPC_ERROR_NONE) { @@ -930,39 +779,37 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing); - end_waiting_for_write(exec_ctx, t, error); + end_waiting_for_write(exec_ctx, t, GRPC_ERROR_REF(error)); switch (t->executor.write_state) { case GRPC_CHTTP2_WRITING_INACTIVE: - case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: - case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: case GRPC_CHTTP2_WRITE_SCHEDULED: GPR_UNREACHABLE_CODE(break); case GRPC_CHTTP2_WRITING: set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "terminate_writing"); break; case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: - set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, - "terminate_writing"); + set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "terminate_writing"); + grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, + &t->initiate_writing, GRPC_ERROR_NONE, + true); break; case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: - set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, - "terminate_writing"); + set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "terminate_writing"); + grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, + &t->initiate_writing, GRPC_ERROR_NONE, + false); break; } - if (t->ep && !t->endpoint_reading) { - destroy_endpoint(exec_ctx, t); - } - UNREF_TRANSPORT(exec_ctx, t, "writing"); } void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx, void *transport_writing, grpc_error *error) { grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); - grpc_chttp2_run_with_global_lock( - exec_ctx, t, NULL, terminate_writing_with_lock, GRPC_ERROR_REF(error), 0); + grpc_combiner_execute(exec_ctx, t->executor.combiner, &t->terminate_writing, + GRPC_ERROR_REF(error)); } static void writing_action(grpc_exec_ctx *exec_ctx, void *gt, @@ -1106,12 +953,13 @@ static int contains_non_ok_status( static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} -static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, void *stream_op) { +static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, + grpc_error *error_ignored) { GPR_TIMER_BEGIN("perform_stream_op_locked", 0); grpc_transport_stream_op *op = stream_op; + grpc_chttp2_transport *t = op->transport_private.args[0]; + grpc_chttp2_stream *s = op->transport_private.args[1]; grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_stream_global *stream_global = &s->global; @@ -1291,9 +1139,12 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_transport_stream_op *op) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - grpc_chttp2_run_with_global_lock(exec_ctx, t, s, perform_stream_op_locked, op, - sizeof(*op)); + grpc_closure_init(&op->transport_private.closure, perform_stream_op_locked, + op); + op->transport_private.args[0] = gt; + op->transport_private.args[1] = gs; + grpc_combiner_execute(exec_ctx, t->executor.combiner, + &op->transport_private.closure, GRPC_ERROR_NONE); } static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, @@ -1315,13 +1166,20 @@ static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_initiate_write(exec_ctx, &t->global, true, "send_ping"); } -static void ack_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - grpc_chttp2_stream *s, void *opaque_8bytes) { +typedef struct ack_ping_args { + grpc_closure closure; + grpc_chttp2_transport *t; + uint8_t opaque_8bytes[8]; +} ack_ping_args; + +static void ack_ping_locked(grpc_exec_ctx *exec_ctx, void *a, + grpc_error *error_ignored) { + ack_ping_args *args = a; grpc_chttp2_outstanding_ping *ping; - grpc_chttp2_transport_global *transport_global = &t->global; + grpc_chttp2_transport_global *transport_global = &args->t->global; for (ping = transport_global->pings.next; ping != &transport_global->pings; ping = ping->next) { - if (0 == memcmp(opaque_8bytes, ping->id, 8)) { + if (0 == memcmp(args->opaque_8bytes, ping->id, 8)) { grpc_exec_ctx_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE, NULL); ping->next->prev = ping->prev; ping->prev->next = ping->next; @@ -1329,21 +1187,25 @@ static void ack_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, break; } } + gpr_free(args); } void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, const uint8_t *opaque_8bytes) { - grpc_chttp2_run_with_global_lock( - exec_ctx, TRANSPORT_FROM_PARSING(transport_parsing), NULL, - ack_ping_locked, (void *)opaque_8bytes, 8); + ack_ping_args *args = gpr_malloc(sizeof(*args)); + args->t = TRANSPORT_FROM_PARSING(transport_parsing); + memcpy(args->opaque_8bytes, opaque_8bytes, sizeof(args->opaque_8bytes)); + grpc_closure_init(&args->closure, ack_ping_locked, args); + grpc_combiner_execute(exec_ctx, args->t->executor.combiner, &args->closure, + GRPC_ERROR_NONE); } static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, - void *stream_op) { + void *stream_op, + grpc_error *error_ignored) { grpc_transport_op *op = stream_op; + grpc_chttp2_transport *t = op->transport_private.args[0]; grpc_error *close_transport = op->disconnect_with_error; /* If there's a set_accept_stream ensure that we're not parsing @@ -1355,8 +1217,6 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, return; } - grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); - if (op->on_connectivity_state_change != NULL) { grpc_connectivity_state_notify_on_state_change( exec_ctx, &t->channel_callback.state_tracker, op->connectivity_state, @@ -1382,11 +1242,11 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, } if (op->bind_pollset) { - add_to_pollset_locked(exec_ctx, t, NULL, op->bind_pollset); + grpc_endpoint_add_to_pollset(exec_ctx, t->ep, op->bind_pollset); } if (op->bind_pollset_set) { - add_to_pollset_set_locked(exec_ctx, t, NULL, op->bind_pollset_set); + grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, op->bind_pollset_set); } if (op->send_ping) { @@ -1396,13 +1256,18 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, if (close_transport != GRPC_ERROR_NONE) { close_transport_locked(exec_ctx, t, close_transport); } + + grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); } 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; - grpc_chttp2_run_with_global_lock( - exec_ctx, t, NULL, perform_transport_op_locked, op, sizeof(*op)); + op->transport_private.args[0] = gt; + grpc_closure_init(&op->transport_private.closure, perform_transport_op_locked, + op); + grpc_combiner_execute(exec_ctx, t->executor.combiner, + &op->transport_private.closure, GRPC_ERROR_NONE); } /******************************************************************************* @@ -1420,7 +1285,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, if (stream_global->seen_error) { while ((bs = grpc_chttp2_incoming_frame_queue_pop( &stream_global->incoming_frames)) != NULL) { - incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } if (stream_global->exceeded_metadata_size) { cancel_from_api( @@ -1443,7 +1308,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, stream_global->seen_error && (bs = grpc_chttp2_incoming_frame_queue_pop( &stream_global->incoming_frames)) != NULL) { - incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } if (stream_global->incoming_frames.head != NULL) { *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop( @@ -1464,7 +1329,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, if (stream_global->seen_error) { while ((bs = grpc_chttp2_incoming_frame_queue_pop( &stream_global->incoming_frames)) != NULL) { - incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } if (stream_global->exceeded_metadata_size) { cancel_from_api( @@ -1905,16 +1770,12 @@ static void update_global_window(void *args, uint32_t id, void *stream) { * INPUT PROCESSING - PARSING */ -static void reading_action_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *arg); static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); -static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *arg); -static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *arg); +static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); static void reading_action(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { @@ -1922,16 +1783,16 @@ static void reading_action(grpc_exec_ctx *exec_ctx, void *tp, reading_action_locked -> (parse_unlocked -> post_parse_locked)? -> post_reading_action_locked */ - grpc_chttp2_run_with_global_lock(exec_ctx, tp, NULL, reading_action_locked, - GRPC_ERROR_REF(error), 0); + grpc_chttp2_transport *t = tp; + grpc_combiner_execute(exec_ctx, t->executor.combiner, + &t->reading_action_locked, GRPC_ERROR_REF(error)); } -static void reading_action_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *arg) { +static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *tp, + grpc_error *error) { + grpc_chttp2_transport *t = tp; grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_transport_parsing *transport_parsing = &t->parsing; - grpc_error *error = arg; GPR_ASSERT(!t->executor.parsing_active); if (!t->closed) { @@ -1942,7 +1803,7 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_prepare_to_read(transport_global, transport_parsing); grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, error, NULL); } else { - post_reading_action_locked(exec_ctx, t, s_unused, arg); + post_reading_action_locked(exec_ctx, t, GRPC_ERROR_REF(error)); } } @@ -1997,12 +1858,13 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, GRPC_ERROR_UNREF(errors[i]); } GPR_TIMER_END("reading_action.parse", 0); - grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked, err, - 0); + grpc_combiner_execute(exec_ctx, t->executor.combiner, &t->post_parse_locked, + err); } -static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *arg) { +static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_transport *t = arg; grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_transport_parsing *transport_parsing = &t->parsing; /* copy parsing qbuf to global qbuf */ @@ -2028,7 +1890,7 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 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, NULL, op); + perform_transport_op_locked(exec_ctx, op, GRPC_ERROR_NONE); gpr_free(op); } /* if a stream is in the stream map, and gets cancelled, we need to @@ -2045,15 +1907,14 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2"); } - post_reading_action_locked(exec_ctx, t, s_unused, arg); + post_reading_action_locked(exec_ctx, t, error); } -static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, - void *arg) { - grpc_error *error = arg; +static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_transport *t = arg; bool keep_reading = false; + GRPC_ERROR_REF(error); if (error == GRPC_ERROR_NONE && t->closed) { error = GRPC_ERROR_CREATE("Transport closed"); } @@ -2068,16 +1929,12 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, gpr_log(GPR_DEBUG, "R:%p -> 0 ws=%s", t, write_state_name(t->executor.write_state)); } - if (t->executor.write_state == GRPC_CHTTP2_WRITING_INACTIVE && t->ep) { - destroy_endpoint(exec_ctx, t); - } } else if (!t->closed) { keep_reading = true; REF_TRANSPORT(t, "keep_reading"); prevent_endpoint_shutdown(t); } gpr_slice_buffer_reset_and_unref(&t->read_buffer); - GRPC_ERROR_UNREF(error); if (keep_reading) { grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->reading_action); @@ -2086,6 +1943,7 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, } else { UNREF_TRANSPORT(exec_ctx, t, "reading_action"); } + GRPC_ERROR_UNREF(error); } /******************************************************************************* @@ -2107,36 +1965,16 @@ static void connectivity_state_set( * POLLSET STUFF */ -static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *pollset) { - if (t->ep) { - grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset); - } -} - -static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, - void *pollset_set) { - if (t->ep) { - grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set); - } -} - static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_pollset *pollset) { - /* TODO(ctiller): keep pollset alive */ - grpc_chttp2_run_with_global_lock(exec_ctx, (grpc_chttp2_transport *)gt, - (grpc_chttp2_stream *)gs, - add_to_pollset_locked, pollset, 0); + grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; + grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset); } static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_pollset_set *pollset_set) { - grpc_chttp2_run_with_global_lock(exec_ctx, (grpc_chttp2_transport *)gt, - (grpc_chttp2_stream *)gs, - add_to_pollset_set_locked, pollset_set, 0); + grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; + grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set); } /******************************************************************************* @@ -2148,6 +1986,7 @@ static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx, if (gpr_unref(&bs->refs)) { GRPC_ERROR_UNREF(bs->error); gpr_slice_buffer_destroy(&bs->slices); + gpr_mu_destroy(&bs->slice_mu); gpr_free(bs); } } @@ -2193,38 +2032,31 @@ static void incoming_byte_stream_update_flow_control( } } -typedef struct { - grpc_chttp2_incoming_byte_stream *byte_stream; - gpr_slice *slice; - size_t max_size_hint; - grpc_closure *on_complete; -} incoming_byte_stream_next_arg; - static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *argp) { - incoming_byte_stream_next_arg *arg = argp; - grpc_chttp2_incoming_byte_stream *bs = - (grpc_chttp2_incoming_byte_stream *)arg->byte_stream; + void *argp, + grpc_error *error_ignored) { + grpc_chttp2_incoming_byte_stream *bs = argp; grpc_chttp2_transport_global *transport_global = &bs->transport->global; grpc_chttp2_stream_global *stream_global = &bs->stream->global; if (bs->is_tail) { - incoming_byte_stream_update_flow_control(exec_ctx, transport_global, - stream_global, arg->max_size_hint, - bs->slices.length); + incoming_byte_stream_update_flow_control( + exec_ctx, transport_global, stream_global, + bs->next_action.max_size_hint, bs->slices.length); } + gpr_mu_lock(&bs->slice_mu); if (bs->slices.count > 0) { - *arg->slice = gpr_slice_buffer_take_first(&bs->slices); - grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_NONE, NULL); - } else if (bs->error != GRPC_ERROR_NONE) { - grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_REF(bs->error), + *bs->next_action.slice = gpr_slice_buffer_take_first(&bs->slices); + grpc_exec_ctx_sched(exec_ctx, bs->next_action.on_complete, GRPC_ERROR_NONE, NULL); + } else if (bs->error != GRPC_ERROR_NONE) { + grpc_exec_ctx_sched(exec_ctx, bs->next_action.on_complete, + GRPC_ERROR_REF(bs->error), NULL); } else { - bs->on_next = arg->on_complete; - bs->next = arg->slice; + bs->on_next = bs->next_action.on_complete; + bs->next = bs->next_action.slice; } + gpr_mu_unlock(&bs->slice_mu); incoming_byte_stream_unref(exec_ctx, bs); } @@ -2234,11 +2066,14 @@ static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx, grpc_closure *on_complete) { grpc_chttp2_incoming_byte_stream *bs = (grpc_chttp2_incoming_byte_stream *)byte_stream; - incoming_byte_stream_next_arg arg = {bs, slice, max_size_hint, on_complete}; gpr_ref(&bs->refs); - grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, - incoming_byte_stream_next_locked, &arg, - sizeof(arg)); + bs->next_action.slice = slice; + bs->next_action.max_size_hint = max_size_hint; + bs->next_action.on_complete = on_complete; + grpc_closure_init(&bs->next_action.closure, incoming_byte_stream_next_locked, + bs); + grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, + &bs->next_action.closure, GRPC_ERROR_NONE); return 0; } @@ -2246,9 +2081,8 @@ static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream); static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *byte_stream) { + void *byte_stream, + grpc_error *error_ignored) { grpc_chttp2_incoming_byte_stream *bs = byte_stream; GPR_ASSERT(bs->base.destroy == incoming_byte_stream_destroy); decrement_active_streams_locked(exec_ctx, &bs->transport->global, @@ -2260,8 +2094,10 @@ static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream) { grpc_chttp2_incoming_byte_stream *bs = (grpc_chttp2_incoming_byte_stream *)byte_stream; - grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, - incoming_byte_stream_destroy_locked, bs, 0); + grpc_closure_init(&bs->destroy_action, incoming_byte_stream_destroy_locked, + bs); + grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, + &bs->destroy_action, GRPC_ERROR_NONE); } typedef struct { @@ -2269,64 +2105,29 @@ typedef struct { gpr_slice slice; } incoming_byte_stream_push_arg; -static void incoming_byte_stream_push_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *argp) { - incoming_byte_stream_push_arg *arg = argp; - grpc_chttp2_incoming_byte_stream *bs = arg->byte_stream; +void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx, + grpc_chttp2_incoming_byte_stream *bs, + gpr_slice slice) { + gpr_mu_lock(&bs->slice_mu); if (bs->on_next != NULL) { - *bs->next = arg->slice; + *bs->next = slice; grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_NONE, NULL); bs->on_next = NULL; } else { - gpr_slice_buffer_add(&bs->slices, arg->slice); + gpr_slice_buffer_add(&bs->slices, slice); } - incoming_byte_stream_unref(exec_ctx, bs); -} - -void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx, - grpc_chttp2_incoming_byte_stream *bs, - gpr_slice slice) { - incoming_byte_stream_push_arg arg = {bs, slice}; - gpr_ref(&bs->refs); - grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, - incoming_byte_stream_push_locked, &arg, - sizeof(arg)); -} - -typedef struct { - grpc_chttp2_incoming_byte_stream *bs; - grpc_error *error; -} bs_fail_args; - -static bs_fail_args *make_bs_fail_args(grpc_chttp2_incoming_byte_stream *bs, - grpc_error *error) { - bs_fail_args *a = gpr_malloc(sizeof(*a)); - a->bs = bs; - a->error = error; - return a; -} - -static void incoming_byte_stream_finished_failed_locked( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, - void *argp) { - bs_fail_args *a = argp; - grpc_chttp2_incoming_byte_stream *bs = a->bs; - grpc_error *error = a->error; - gpr_free(a); - grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error), NULL); - bs->on_next = NULL; - GRPC_ERROR_UNREF(bs->error); - bs->error = error; - incoming_byte_stream_unref(exec_ctx, bs); + gpr_mu_unlock(&bs->slice_mu); } -static void incoming_byte_stream_finished_ok_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *argp) { - grpc_chttp2_incoming_byte_stream *bs = argp; +static void incoming_byte_stream_finished_locked(grpc_exec_ctx *exec_ctx, + void *bsp, grpc_error *error) { + grpc_chttp2_incoming_byte_stream *bs = bsp; + if (error != GRPC_ERROR_NONE) { + grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error), NULL); + bs->on_next = NULL; + GRPC_ERROR_UNREF(bs->error); + bs->error = error; + } incoming_byte_stream_unref(exec_ctx, bs); } @@ -2334,24 +2135,12 @@ void grpc_chttp2_incoming_byte_stream_finished( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, grpc_error *error, int from_parsing_thread) { if (from_parsing_thread) { - if (error == GRPC_ERROR_NONE) { - grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, - incoming_byte_stream_finished_ok_locked, - bs, 0); - } else { - grpc_chttp2_run_with_global_lock( - exec_ctx, bs->transport, bs->stream, - incoming_byte_stream_finished_failed_locked, - make_bs_fail_args(bs, error), 0); - } + grpc_closure_init(&bs->finished_action, + incoming_byte_stream_finished_locked, bs); + grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, + &bs->finished_action, GRPC_ERROR_REF(error)); } else { - if (error == GRPC_ERROR_NONE) { - incoming_byte_stream_finished_ok_locked(exec_ctx, bs->transport, - bs->stream, bs); - } else { - incoming_byte_stream_finished_failed_locked( - exec_ctx, bs->transport, bs->stream, make_bs_fail_args(bs, error)); - } + incoming_byte_stream_finished_locked(exec_ctx, bs, error); } } @@ -2365,6 +2154,7 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create( incoming_byte_stream->base.flags = flags; incoming_byte_stream->base.next = incoming_byte_stream_next; incoming_byte_stream->base.destroy = incoming_byte_stream_destroy; + gpr_mu_init(&incoming_byte_stream->slice_mu); gpr_ref_init(&incoming_byte_stream->refs, 2); incoming_byte_stream->next_message = NULL; incoming_byte_stream->transport = TRANSPORT_FROM_PARSING(transport_parsing); diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 81ddaa8fa1..efac10a93c 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -48,6 +48,7 @@ #include "src/core/ext/transport/chttp2/transport/hpack_parser.h" #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" #include "src/core/ext/transport/chttp2/transport/stream_map.h" +#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/transport_impl.h" @@ -161,9 +162,20 @@ struct grpc_chttp2_incoming_byte_stream { grpc_chttp2_transport *transport; grpc_chttp2_stream *stream; int is_tail; + + gpr_mu slice_mu; // protects slices, on_next gpr_slice_buffer slices; grpc_closure *on_next; gpr_slice *next; + + struct { + grpc_closure closure; + gpr_slice *slice; + size_t max_size_hint; + grpc_closure *on_complete; + } next_action; + grpc_closure destroy_action; + grpc_closure finished_action; }; typedef struct { @@ -294,23 +306,9 @@ struct grpc_chttp2_transport_parsing { int64_t outgoing_window; }; -typedef void (*grpc_chttp2_locked_action)(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, void *arg); - -typedef struct grpc_chttp2_executor_action_header { - grpc_chttp2_stream *stream; - grpc_chttp2_locked_action action; - struct grpc_chttp2_executor_action_header *next; - void *arg; -} grpc_chttp2_executor_action_header; - typedef enum { /** no writing activity */ GRPC_CHTTP2_WRITING_INACTIVE, - /** write has been requested, but not scheduled yet */ - GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, - GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, /** write has been requested and scheduled against the workqueue */ GRPC_CHTTP2_WRITE_SCHEDULED, /** write has been initiated after being reaped from the workqueue */ @@ -331,7 +329,7 @@ struct grpc_chttp2_transport { gpr_refcount shutdown_ep_refs; struct { - gpr_mu mu; + grpc_combiner *combiner; /** is a thread currently in the global lock */ bool global_active; @@ -339,9 +337,6 @@ struct grpc_chttp2_transport { bool parsing_active; /** write execution state of the transport */ grpc_chttp2_write_state write_state; - - grpc_chttp2_executor_action_header *pending_actions_head; - grpc_chttp2_executor_action_header *pending_actions_tail; } executor; /** is the transport destroying itself? */ @@ -377,10 +372,14 @@ struct grpc_chttp2_transport { grpc_closure writing_action; /** closure to start reading from the endpoint */ grpc_closure reading_action; + grpc_closure reading_action_locked; + grpc_closure post_parse_locked; /** closure to actually do parsing */ grpc_closure parsing_action; /** closure to initiate writing */ grpc_closure initiate_writing; + /** closure to finish writing */ + grpc_closure terminate_writing; /** incoming read bytes */ gpr_slice_buffer read_buffer; @@ -522,11 +521,16 @@ struct grpc_chttp2_stream_parsing { }; struct grpc_chttp2_stream { + grpc_chttp2_transport *t; grpc_stream_refcount *refcount; grpc_chttp2_stream_global global; grpc_chttp2_stream_writing writing; grpc_chttp2_stream_parsing parsing; + grpc_closure init_stream; + grpc_closure destroy_stream; + void *destroy_stream_arg; + grpc_chttp2_stream_link links[STREAM_LIST_COUNT]; uint8_t included[STREAM_LIST_COUNT]; }; @@ -698,12 +702,6 @@ void grpc_chttp2_complete_closure_step( grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure, grpc_error *error); -void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *transport, - grpc_chttp2_stream *optional_stream, - grpc_chttp2_locked_action action, - void *arg, size_t sizeof_arg); - #define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" #define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \ (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1) diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index 34e8f43905..5dfef4f25b 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -187,3 +187,7 @@ void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, } grpc_closure_list_append(&lock->final_list, closure, error); } + +void grpc_combiner_force_async_finally(grpc_combiner *lock) { + lock->take_async_break_before_final_list = true; +} diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index d6bc27111f..3554202aae 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -63,5 +63,6 @@ void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error, bool force_async_break); +void grpc_combiner_force_async_finally(grpc_combiner *lock); #endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 08c0a237c9..b04b60ec3d 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -96,6 +96,11 @@ void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats *from, void grpc_transport_move_stats(grpc_transport_stream_stats *from, grpc_transport_stream_stats *to); +typedef struct { + grpc_closure closure; + void *args[2]; +} grpc_transport_private_op_data; + /* Transport stream op: a set of operations to perform on a transport against a single stream */ typedef struct grpc_transport_stream_op { @@ -144,6 +149,12 @@ typedef struct grpc_transport_stream_op { /* Indexes correspond to grpc_context_index enum values */ grpc_call_context_element *context; + + /*************************************************************************** + * remaining fields are initialized and used at the discretion of the + * transport implementation */ + + grpc_transport_private_op_data transport_private; } grpc_transport_stream_op; /** Transport op: a set of operations to perform on a transport as a whole */ @@ -177,6 +188,12 @@ typedef struct grpc_transport_op { grpc_pollset_set *bind_pollset_set; /** send a ping, call this back if not NULL */ grpc_closure *send_ping; + + /*************************************************************************** + * remaining fields are initialized and used at the discretion of the + * transport implementation */ + + grpc_transport_private_op_data transport_private; } grpc_transport_op; /* Returns the amount of memory required to store a grpc_stream for this -- cgit v1.2.3 From e0221ff3401d397b981fbb3e057fa7812de37f35 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 11 Jul 2016 15:56:08 -0700 Subject: Debugging --- src/core/ext/client_config/subchannel.c | 17 +++--- .../transport/chttp2/transport/chttp2_transport.c | 2 +- src/core/lib/iomgr/combiner.c | 61 ++++++++++++++++++---- src/core/lib/iomgr/combiner.h | 11 ++-- src/core/lib/iomgr/exec_ctx.h | 6 ++- src/core/lib/surface/channel.c | 7 ++- src/core/lib/surface/channel_ping.c | 9 ++-- src/core/lib/surface/server.c | 56 +++++++++----------- src/core/lib/transport/transport.c | 26 +++++++++ src/core/lib/transport/transport.h | 4 ++ test/core/iomgr/combiner_test.c | 20 ++++--- test/core/surface/lame_client_test.c | 15 +++--- 12 files changed, 152 insertions(+), 82 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c index d089cd4399..2318bd1023 100644 --- a/src/core/ext/client_config/subchannel.c +++ b/src/core/ext/client_config/subchannel.c @@ -504,14 +504,14 @@ static void connected_subchannel_state_op(grpc_exec_ctx *exec_ctx, grpc_pollset_set *interested_parties, grpc_connectivity_state *state, grpc_closure *closure) { - grpc_transport_op op; + grpc_transport_op *op = grpc_make_transport_op(NULL); grpc_channel_element *elem; memset(&op, 0, sizeof(op)); - op.connectivity_state = state; - op.on_connectivity_state_change = closure; - op.bind_pollset_set = interested_parties; + op->connectivity_state = state; + op->on_connectivity_state_change = closure; + op->bind_pollset_set = interested_parties; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); - elem->filter->start_transport_op(exec_ctx, elem, &op); + elem->filter->start_transport_op(exec_ctx, elem, op); } void grpc_connected_subchannel_notify_on_state_change( @@ -525,12 +525,11 @@ void grpc_connected_subchannel_notify_on_state_change( void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, grpc_closure *closure) { - grpc_transport_op op; + grpc_transport_op *op = grpc_make_transport_op(NULL); grpc_channel_element *elem; - memset(&op, 0, sizeof(op)); - op.send_ping = closure; + op->send_ping = closure; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); - elem->filter->start_transport_op(exec_ctx, elem, &op); + elem->filter->start_transport_op(exec_ctx, elem, op); } static void publish_transport_locked(grpc_exec_ctx *exec_ctx, diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 194264c8f9..4dc642e37a 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -181,7 +181,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_map_destroy(&t->new_stream_map); grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker); - grpc_combiner_destroy(t->executor.combiner); + grpc_combiner_destroy(exec_ctx, t->executor.combiner); /* callback remaining pings: they're not allowed to call into the transpot, and maybe they hold resources that need to be freed */ diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index 5dfef4f25b..99e112308b 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -32,6 +32,7 @@ */ #include "src/core/lib/iomgr/combiner.h" +#include "src/core/lib/iomgr/workqueue.h" #include @@ -52,7 +53,9 @@ struct grpc_combiner { grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { grpc_combiner *lock = gpr_malloc(sizeof(*lock)); - lock->optional_workqueue = optional_workqueue; + lock->optional_workqueue = + optional_workqueue ? GRPC_WORKQUEUE_REF(optional_workqueue, "combiner") + : NULL; gpr_atm_no_barrier_store(&lock->state, 1); gpr_mpscq_init(&lock->queue); lock->take_async_break_before_final_list = false; @@ -60,15 +63,18 @@ grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { return lock; } -static void really_destroy(grpc_combiner *lock) { +static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); gpr_mpscq_destroy(&lock->queue); + if (lock->optional_workqueue != NULL) { + GRPC_WORKQUEUE_UNREF(exec_ctx, lock->optional_workqueue, "combiner"); + } gpr_free(lock); } -void grpc_combiner_destroy(grpc_combiner *lock) { +void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { if (gpr_atm_full_fetch_add(&lock->state, -1) == 1) { - really_destroy(lock); + really_destroy(exec_ctx, lock); } } @@ -77,7 +83,12 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); static void continue_finishing_mainline(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - if (maybe_finish_one(exec_ctx, arg)) finish(exec_ctx, arg); + grpc_combiner *lock = arg; + GPR_ASSERT(exec_ctx->active_combiner == NULL); + exec_ctx->active_combiner = lock; + if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); + GPR_ASSERT(exec_ctx->active_combiner == lock); + exec_ctx->active_combiner = NULL; } static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { @@ -96,6 +107,8 @@ static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_combiner *lock = arg; + GPR_ASSERT(exec_ctx->active_combiner == NULL); + exec_ctx->active_combiner = lock; // quick peek to see if new things have turned up on the queue: if so, go back // to executing them before the final list if ((gpr_atm_acq_load(&lock->state) >> 1) > 1) { @@ -104,9 +117,12 @@ static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, execute_final(exec_ctx, lock); finish(exec_ctx, lock); } + GPR_ASSERT(exec_ctx->active_combiner == lock); + exec_ctx->active_combiner = NULL; } static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + GPR_ASSERT(exec_ctx->active_combiner == lock); if (lock->take_async_break_before_final_list) { grpc_closure_init(&lock->continue_finishing, continue_executing_final, lock); @@ -121,6 +137,7 @@ static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); + GPR_ASSERT(exec_ctx->active_combiner == lock); if (n == NULL) { // queue is in an inconsistant state: use this as a cue that we should // go off and do something else for a while (and come back later) @@ -151,7 +168,7 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { case 3: // had one count, one unorphaned --> unlocked unorphaned return; case 2: // and one count, one orphaned --> unlocked and orphaned - really_destroy(lock); + really_destroy(exec_ctx, lock); return; case 1: case 0: @@ -166,19 +183,43 @@ void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *cl, grpc_error *error) { gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); GPR_ASSERT(last & 1); // ensure lock has not been destroyed - if (last == 1) { - cl->cb(exec_ctx, cl->cb_arg, error); - GRPC_ERROR_UNREF(error); - finish(exec_ctx, lock); + if (exec_ctx->active_combiner == NULL) { + if (last == 1) { + exec_ctx->active_combiner = lock; + cl->cb(exec_ctx, cl->cb_arg, error); + GRPC_ERROR_UNREF(error); + finish(exec_ctx, lock); + GPR_ASSERT(exec_ctx->active_combiner == lock); + exec_ctx->active_combiner = NULL; + } else { + cl->error = error; + gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); + } } else { cl->error = error; gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); + grpc_closure_init(&lock->continue_finishing, continue_finishing_mainline, + lock); + grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, + lock->optional_workqueue); } } +static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, + grpc_error *error) { + grpc_combiner_execute_finally(exec_ctx, exec_ctx->active_combiner, closure, + GRPC_ERROR_REF(error), true); +} + void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error, bool force_async_break) { + if (exec_ctx->active_combiner != lock) { + grpc_combiner_execute(exec_ctx, lock, + grpc_closure_create(enqueue_finally, closure), error); + return; + } + if (force_async_break) { lock->take_async_break_before_final_list = true; } diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index 3554202aae..5b94d5bd99 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -40,8 +40,6 @@ #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/support/mpscq.h" -typedef struct grpc_combiner grpc_combiner; - // Provides serialized access to some resource. // Each action queued on an aelock is executed serially in a borrowed thread. // The actual thread executing actions may change over time (but there will only @@ -51,18 +49,19 @@ typedef struct grpc_combiner grpc_combiner; // necessary grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue); // Destroy the lock -void grpc_combiner_destroy(grpc_combiner *lock); +void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); // Execute \a action within the lock. void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error); // Execute \a action within the lock just prior to unlocking. -// if \a force_async_break is additionally set, the combiner is forced to trip +// if \a hint_async_break is additionally set, the combiner is tries to trip // through the workqueue between finishing the primary queue of combined // closures and executing the finally list. -// Can only be called from within a closure scheduled by grpc_combiner_execute +// Takes a very slow and round-about path if not called from a +// grpc_combiner_execute closure void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error, - bool force_async_break); + bool hint_async_break); void grpc_combiner_force_async_finally(grpc_combiner *lock); #endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index 917f332f03..1895ee6245 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -40,8 +40,8 @@ /** A workqueue represents a list of work to be executed asynchronously. Forward declared here to avoid a circular dependency with workqueue.h. */ -struct grpc_workqueue; typedef struct grpc_workqueue grpc_workqueue; +typedef struct grpc_combiner grpc_combiner; #ifndef GRPC_EXECUTION_CONTEXT_SANITIZER /** Execution context. @@ -66,13 +66,15 @@ typedef struct grpc_workqueue grpc_workqueue; */ struct grpc_exec_ctx { grpc_closure_list closure_list; + /** currently active combiner: updated only via combiner.c */ + grpc_combiner *active_combiner; bool cached_ready_to_finish; void *check_ready_to_finish_arg; bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg); }; #define GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(finish_check, finish_check_arg) \ - { GRPC_CLOSURE_LIST_INIT, false, finish_check_arg, finish_check } + { GRPC_CLOSURE_LIST_INIT, NULL, false, finish_check_arg, finish_check } #else struct grpc_exec_ctx { bool cached_ready_to_finish; diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c index 6d2b1c4935..52e78567bd 100644 --- a/src/core/lib/surface/channel.c +++ b/src/core/lib/surface/channel.c @@ -334,14 +334,13 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, } void grpc_channel_destroy(grpc_channel *channel) { - grpc_transport_op op; + grpc_transport_op *op = grpc_make_transport_op(NULL); grpc_channel_element *elem; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel)); - memset(&op, 0, sizeof(op)); - op.disconnect_with_error = GRPC_ERROR_CREATE("Channel Destroyed"); + op->disconnect_with_error = GRPC_ERROR_CREATE("Channel Destroyed"); elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); - elem->filter->start_transport_op(&exec_ctx, elem, &op); + elem->filter->start_transport_op(&exec_ctx, elem, op); GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "channel"); diff --git a/src/core/lib/surface/channel_ping.c b/src/core/lib/surface/channel_ping.c index 9818f9d2f2..5f9f07f89a 100644 --- a/src/core/lib/surface/channel_ping.c +++ b/src/core/lib/surface/channel_ping.c @@ -61,19 +61,18 @@ static void ping_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved) { - grpc_transport_op op; + grpc_transport_op *op = grpc_make_transport_op(NULL); ping_result *pr = gpr_malloc(sizeof(*pr)); grpc_channel_element *top_elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT(reserved == NULL); - memset(&op, 0, sizeof(op)); pr->tag = tag; pr->cq = cq; grpc_closure_init(&pr->closure, ping_done, pr); - op.send_ping = &pr->closure; - op.bind_pollset = grpc_cq_pollset(cq); + op->send_ping = &pr->closure; + op->bind_pollset = grpc_cq_pollset(cq); grpc_cq_begin_op(cq, tag); - top_elem->filter->start_transport_op(&exec_ctx, top_elem, &op); + top_elem->filter->start_transport_op(&exec_ctx, top_elem, op); grpc_exec_ctx_finish(&exec_ctx); } diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index def6e5068b..fc9987f0aa 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -272,22 +272,20 @@ static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg, static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel, int send_goaway, grpc_error *send_disconnect) { - grpc_transport_op op; - struct shutdown_cleanup_args *sc; + struct shutdown_cleanup_args *sc = gpr_malloc(sizeof(*sc)); + grpc_closure_init(&sc->closure, shutdown_cleanup, sc); + grpc_transport_op *op = grpc_make_transport_op(&sc->closure); grpc_channel_element *elem; - memset(&op, 0, sizeof(op)); - op.send_goaway = send_goaway; - sc = gpr_malloc(sizeof(*sc)); + op->send_goaway = send_goaway; sc->slice = gpr_slice_from_copied_string("Server shutdown"); - op.goaway_message = &sc->slice; - op.goaway_status = GRPC_STATUS_OK; - op.disconnect_with_error = send_disconnect; - grpc_closure_init(&sc->closure, shutdown_cleanup, sc); - op.on_consumed = &sc->closure; + op->goaway_message = &sc->slice; + op->goaway_status = GRPC_STATUS_OK; + op->disconnect_with_error = send_disconnect; + op->on_consumed = &sc->closure; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); - elem->filter->start_transport_op(exec_ctx, elem, &op); + elem->filter->start_transport_op(exec_ctx, elem, op); } static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx, @@ -434,14 +432,13 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) { chand->finish_destroy_channel_closure.cb = finish_destroy_channel; chand->finish_destroy_channel_closure.cb_arg = chand; - grpc_transport_op op; - memset(&op, 0, sizeof(op)); - op.set_accept_stream = true; - op.on_consumed = &chand->finish_destroy_channel_closure; + grpc_transport_op *op = + grpc_make_transport_op(&chand->finish_destroy_channel_closure); + op->set_accept_stream = true; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), - &op); + op); } static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) { @@ -832,14 +829,13 @@ static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd, channel_data *chand = cd; grpc_server *server = chand->server; if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { - grpc_transport_op op; - memset(&op, 0, sizeof(op)); - op.on_connectivity_state_change = &chand->channel_connectivity_changed, - op.connectivity_state = &chand->connectivity_state; + grpc_transport_op *op = grpc_make_transport_op(NULL); + op->on_connectivity_state_change = &chand->channel_connectivity_changed, + op->connectivity_state = &chand->connectivity_state; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), - &op); + op); } else { gpr_mu_lock(&server->mu_global); destroy_channel(exec_ctx, chand); @@ -1101,7 +1097,7 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, size_t slots; uint32_t probes; uint32_t max_probes = 0; - grpc_transport_op op; + grpc_transport_op *op = NULL; channel = grpc_channel_create(exec_ctx, NULL, args, GRPC_SERVER_CHANNEL, transport); @@ -1161,16 +1157,16 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, gpr_mu_unlock(&s->mu_global); GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity"); - memset(&op, 0, sizeof(op)); - 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; + op = grpc_make_transport_op(NULL); + 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; if (gpr_atm_acq_load(&s->shutdown_flag) != 0) { - op.disconnect_with_error = GRPC_ERROR_CREATE("Server shutdown"); + op->disconnect_with_error = GRPC_ERROR_CREATE("Server shutdown"); } - grpc_transport_perform_op(exec_ctx, transport, &op); + grpc_transport_perform_op(exec_ctx, transport, op); } void done_published_shutdown(grpc_exec_ctx *exec_ctx, void *done_arg, diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c index 857c3909d2..970d9c389a 100644 --- a/src/core/lib/transport/transport.c +++ b/src/core/lib/transport/transport.c @@ -32,10 +32,14 @@ */ #include "src/core/lib/transport/transport.h" + +#include + #include #include #include #include + #include "src/core/lib/support/string.h" #include "src/core/lib/transport/transport_impl.h" @@ -247,3 +251,25 @@ void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op, error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status); add_error(op, &op->close_error, error); } + +typedef struct { + grpc_closure outer_on_complete; + grpc_closure *inner_on_complete; + grpc_transport_op op; +} made_transport_op; + +static void destroy_made_transport_op(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + made_transport_op *op = arg; + grpc_exec_ctx_sched(exec_ctx, op->inner_on_complete, GRPC_ERROR_REF(error), + NULL); + gpr_free(op); +} + +grpc_transport_op *grpc_make_transport_op(grpc_closure *on_complete) { + made_transport_op *op = gpr_malloc(sizeof(*op)); + grpc_closure_init(&op->outer_on_complete, destroy_made_transport_op, op); + op->inner_on_complete = on_complete; + memset(&op->op, 0, sizeof(op->op)); + return &op->op; +} diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index b04b60ec3d..508b57a5b4 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -285,4 +285,8 @@ void grpc_transport_destroy(grpc_exec_ctx *exec_ctx, grpc_transport *transport); char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *transport); +/* Allocate a grpc_transport_op, and preconfigure the on_consumed closure to + \a on_consumed and then delete the returned transport op */ +grpc_transport_op *grpc_make_transport_op(grpc_closure *on_consumed); + #endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_H */ diff --git a/test/core/iomgr/combiner_test.c b/test/core/iomgr/combiner_test.c index 0aaeada345..7cf016d82c 100644 --- a/test/core/iomgr/combiner_test.c +++ b/test/core/iomgr/combiner_test.c @@ -43,7 +43,9 @@ static void test_no_op(void) { gpr_log(GPR_DEBUG, "test_no_op"); - grpc_combiner_destroy(grpc_combiner_create(NULL)); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_combiner_destroy(&exec_ctx, grpc_combiner_create(NULL)); + grpc_exec_ctx_finish(&exec_ctx); } static void set_bool_to_true(grpc_exec_ctx *exec_ctx, void *value, @@ -60,9 +62,10 @@ static void test_execute_one(void) { grpc_combiner_execute(&exec_ctx, lock, grpc_closure_create(set_bool_to_true, &done), GRPC_ERROR_NONE); - grpc_exec_ctx_finish(&exec_ctx); + grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(done); - grpc_combiner_destroy(lock); + grpc_combiner_destroy(&exec_ctx, lock); + grpc_exec_ctx_finish(&exec_ctx); } typedef struct { @@ -89,7 +92,7 @@ static void execute_many_loop(void *a) { size_t n = 1; for (size_t i = 0; i < 10; i++) { for (size_t j = 0; j < 10000; j++) { - ex_args *c = gpr_malloc(sizeof(*a)); + ex_args *c = gpr_malloc(sizeof(*c)); c->ctr = &args->ctr; c->value = n++; grpc_combiner_execute(&exec_ctx, args->lock, @@ -117,7 +120,9 @@ static void test_execute_many(void) { for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { gpr_thd_join(thds[i]); } - grpc_combiner_destroy(lock); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_combiner_destroy(&exec_ctx, lock); + grpc_exec_ctx_finish(&exec_ctx); } static bool got_in_finally = false; @@ -139,9 +144,10 @@ static void test_execute_finally(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_combiner_execute(&exec_ctx, lock, grpc_closure_create(add_finally, lock), GRPC_ERROR_NONE); - grpc_exec_ctx_finish(&exec_ctx); + grpc_exec_ctx_flush(&exec_ctx); GPR_ASSERT(got_in_finally); - grpc_combiner_destroy(lock); + grpc_combiner_destroy(&exec_ctx, lock); + grpc_exec_ctx_finish(&exec_ctx); } int main(int argc, char **argv) { diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index f36f980575..cad45cc9fa 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -57,24 +57,23 @@ void verify_connectivity(grpc_exec_ctx *exec_ctx, void *arg, void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} void test_transport_op(grpc_channel *channel) { - grpc_transport_op op; + grpc_transport_op *op; grpc_channel_element *elem; grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - memset(&op, 0, sizeof(op)); grpc_closure_init(&transport_op_cb, verify_connectivity, &op); - op.on_connectivity_state_change = &transport_op_cb; - op.connectivity_state = &state; + op = grpc_make_transport_op(NULL); + op->on_connectivity_state_change = &transport_op_cb; + op->connectivity_state = &state; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); - elem->filter->start_transport_op(&exec_ctx, elem, &op); + elem->filter->start_transport_op(&exec_ctx, elem, op); grpc_exec_ctx_finish(&exec_ctx); - memset(&op, 0, sizeof(op)); grpc_closure_init(&transport_op_cb, do_nothing, NULL); - op.on_consumed = &transport_op_cb; - elem->filter->start_transport_op(&exec_ctx, elem, &op); + op = grpc_make_transport_op(&transport_op_cb); + elem->filter->start_transport_op(&exec_ctx, elem, op); grpc_exec_ctx_finish(&exec_ctx); } -- cgit v1.2.3 From 9dc01dd44d169811141853b47d6331e4c3a4245b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 11 Jul 2016 16:26:34 -0700 Subject: Fix some refcounting bugs --- src/core/ext/client_config/subchannel.c | 1 - .../transport/chttp2/transport/chttp2_transport.c | 2 +- src/core/lib/iomgr/combiner.c | 35 +++++++--------------- src/core/lib/iomgr/workqueue_posix.c | 11 +++++-- 4 files changed, 21 insertions(+), 28 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c index 2318bd1023..43b88d2ce4 100644 --- a/src/core/ext/client_config/subchannel.c +++ b/src/core/ext/client_config/subchannel.c @@ -506,7 +506,6 @@ static void connected_subchannel_state_op(grpc_exec_ctx *exec_ctx, grpc_closure *closure) { grpc_transport_op *op = grpc_make_transport_op(NULL); grpc_channel_element *elem; - memset(&op, 0, sizeof(op)); op->connectivity_state = state; op->on_connectivity_state_change = closure; op->bind_pollset_set = interested_parties; diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 4dc642e37a..28f27c271d 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -490,10 +490,10 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, const void *server_data) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - s->t = t; memset(s, 0, sizeof(*s)); + s->t = t; s->refcount = refcount; /* We reserve one 'active stream' that's dropped when the stream is read-closed. The others are for incoming_byte_streams that are actively diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index 99e112308b..6b326facc3 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -53,9 +53,7 @@ struct grpc_combiner { grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { grpc_combiner *lock = gpr_malloc(sizeof(*lock)); - lock->optional_workqueue = - optional_workqueue ? GRPC_WORKQUEUE_REF(optional_workqueue, "combiner") - : NULL; + lock->optional_workqueue = GRPC_WORKQUEUE_REF(optional_workqueue, "combiner"); gpr_atm_no_barrier_store(&lock->state, 1); gpr_mpscq_init(&lock->queue); lock->take_async_break_before_final_list = false; @@ -66,9 +64,7 @@ grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); gpr_mpscq_destroy(&lock->queue); - if (lock->optional_workqueue != NULL) { - GRPC_WORKQUEUE_UNREF(exec_ctx, lock->optional_workqueue, "combiner"); - } + GRPC_WORKQUEUE_UNREF(exec_ctx, lock->optional_workqueue, "combiner"); gpr_free(lock); } @@ -127,7 +123,7 @@ static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { grpc_closure_init(&lock->continue_finishing, continue_executing_final, lock); grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, - lock->optional_workqueue); + GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); return false; } else { execute_final(exec_ctx, lock); @@ -144,7 +140,7 @@ static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { grpc_closure_init(&lock->continue_finishing, continue_finishing_mainline, lock); grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, - lock->optional_workqueue); + GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); return false; } grpc_closure *cl = (grpc_closure *)n; @@ -183,25 +179,16 @@ void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *cl, grpc_error *error) { gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); GPR_ASSERT(last & 1); // ensure lock has not been destroyed - if (exec_ctx->active_combiner == NULL) { - if (last == 1) { - exec_ctx->active_combiner = lock; - cl->cb(exec_ctx, cl->cb_arg, error); - GRPC_ERROR_UNREF(error); - finish(exec_ctx, lock); - GPR_ASSERT(exec_ctx->active_combiner == lock); - exec_ctx->active_combiner = NULL; - } else { - cl->error = error; - gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); - } + if (last == 1) { + exec_ctx->active_combiner = lock; + cl->cb(exec_ctx, cl->cb_arg, error); + GRPC_ERROR_UNREF(error); + finish(exec_ctx, lock); + GPR_ASSERT(exec_ctx->active_combiner == lock); + exec_ctx->active_combiner = NULL; } else { cl->error = error; gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); - grpc_closure_init(&lock->continue_finishing, continue_finishing_mainline, - lock); - grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, - lock->optional_workqueue); } } diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c index 1d52a91694..5accd06744 100644 --- a/src/core/lib/iomgr/workqueue_posix.c +++ b/src/core/lib/iomgr/workqueue_posix.c @@ -86,11 +86,13 @@ void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p ref %d -> %d %s", workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count + 1, reason); + gpr_ref(&workqueue->refs); +} #else void grpc_workqueue_ref(grpc_workqueue *workqueue) { -#endif gpr_ref(&workqueue->refs); } +#endif #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, @@ -98,13 +100,17 @@ void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p unref %d -> %d %s", workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count - 1, reason); + if (gpr_unref(&workqueue->refs)) { + workqueue_orphan(exec_ctx, workqueue); + } +} #else void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { -#endif if (gpr_unref(&workqueue->refs)) { workqueue_orphan(exec_ctx, workqueue); } } +#endif static void drain(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { abort(); @@ -168,6 +174,7 @@ void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, grpc_closure *closure, grpc_error *error) { gpr_atm last = gpr_atm_full_fetch_add(&workqueue->state, 2); GPR_ASSERT(last & 1); + closure->error = error; gpr_mpscq_push(&workqueue->queue, &closure->next_data.atm_next); if (last == 1) { wakeup(exec_ctx, workqueue); -- cgit v1.2.3 From 5beba2818e9a2436dcf410ac6d4c6886cb00444c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 11 Jul 2016 22:05:07 -0700 Subject: fixes --- composer.json | 6 ++---- src/core/ext/transport/chttp2/transport/chttp2_transport.c | 6 ++---- src/core/lib/iomgr/workqueue_posix.c | 2 ++ 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src/core/lib') diff --git a/composer.json b/composer.json index 6e7f24b451..05ac003714 100644 --- a/composer.json +++ b/composer.json @@ -13,10 +13,8 @@ ], "require": { "php": ">=5.5.0", - "datto/protobuf-php": "dev-master" - }, - "require-dev": { - "google/auth": "v0.9" + "datto/protobuf-php": "dev-master", + "google/auth": "v0.7" }, "autoload": { "psr-4": { diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 28f27c271d..91ca2683e0 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -31,9 +31,6 @@ * */ -// TODO(ctiller): schedule check_read_ops whenever something is added to that -// list - #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include @@ -1816,7 +1813,8 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map); grpc_chttp2_prepare_to_read(transport_global, transport_parsing); - grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, error, NULL); + grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, GRPC_ERROR_REF(error), + NULL); } else { post_reading_action_locked(exec_ctx, t, GRPC_ERROR_REF(error)); } diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c index 5accd06744..160f88bdee 100644 --- a/src/core/lib/iomgr/workqueue_posix.c +++ b/src/core/lib/iomgr/workqueue_posix.c @@ -90,6 +90,7 @@ void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, } #else void grpc_workqueue_ref(grpc_workqueue *workqueue) { + if (workqueue == NULL) return; gpr_ref(&workqueue->refs); } #endif @@ -106,6 +107,7 @@ void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, } #else void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { + if (workqueue == NULL) return; if (gpr_unref(&workqueue->refs)) { workqueue_orphan(exec_ctx, workqueue); } -- cgit v1.2.3 From ed334f0f3ead942c23f474c7d241a66b9cf8dafa Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 12 Jul 2016 09:15:07 -0700 Subject: Fixes --- src/core/ext/transport/chttp2/transport/chttp2_transport.c | 2 +- src/core/lib/iomgr/workqueue_posix.c | 2 +- src/core/lib/security/transport/secure_endpoint.c | 4 ++-- src/core/lib/surface/server.c | 1 - src/core/lib/transport/transport.c | 1 + 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 91ca2683e0..aff3afce12 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -1816,7 +1816,7 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, GRPC_ERROR_REF(error), NULL); } else { - post_reading_action_locked(exec_ctx, t, GRPC_ERROR_REF(error)); + post_reading_action_locked(exec_ctx, t, error); } } diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c index 160f88bdee..49a100520e 100644 --- a/src/core/lib/iomgr/workqueue_posix.c +++ b/src/core/lib/iomgr/workqueue_posix.c @@ -133,7 +133,7 @@ static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { workqueue->wakeup_fd.read_fd = 0; grpc_wakeup_fd_destroy(&workqueue->wakeup_fd); grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy"); - drain(exec_ctx, workqueue); + GPR_ASSERT(gpr_atm_no_barrier_load(&workqueue->state) == 0); gpr_free(workqueue); } else { error = grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd); diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c index bc50f9d1b0..0169ccd9ef 100644 --- a/src/core/lib/security/transport/secure_endpoint.c +++ b/src/core/lib/security/transport/secure_endpoint.c @@ -128,7 +128,7 @@ static void flush_read_staging_buffer(secure_endpoint *ep, uint8_t **cur, static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep, grpc_error *error) { - if (false && grpc_trace_secure_endpoint) { + if (grpc_trace_secure_endpoint) { size_t i; for (i = 0; i < ep->read_buffer->count; i++) { char *data = gpr_dump_slice(ep->read_buffer->slices[i], @@ -256,7 +256,7 @@ static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, gpr_slice_buffer_reset_and_unref(&ep->output_buffer); - if (false && grpc_trace_secure_endpoint) { + if (grpc_trace_secure_endpoint) { for (i = 0; i < slices->count; i++) { char *data = gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index fc9987f0aa..08f741119d 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -282,7 +282,6 @@ static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel, op->goaway_message = &sc->slice; op->goaway_status = GRPC_STATUS_OK; op->disconnect_with_error = send_disconnect; - op->on_consumed = &sc->closure; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); elem->filter->start_transport_op(exec_ctx, elem, op); diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c index 970d9c389a..08f9d7e8d9 100644 --- a/src/core/lib/transport/transport.c +++ b/src/core/lib/transport/transport.c @@ -271,5 +271,6 @@ grpc_transport_op *grpc_make_transport_op(grpc_closure *on_complete) { grpc_closure_init(&op->outer_on_complete, destroy_made_transport_op, op); op->inner_on_complete = on_complete; memset(&op->op, 0, sizeof(op->op)); + op->op.on_consumed = &op->outer_on_complete; return &op->op; } -- cgit v1.2.3 From 16125a805f533fb6e73e60b2b22976e9dbef2388 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 13 Jul 2016 16:46:22 -0700 Subject: Refs --- src/core/lib/iomgr/combiner.c | 2 +- src/core/lib/iomgr/workqueue.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index 6b326facc3..73347d5024 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -53,7 +53,7 @@ struct grpc_combiner { grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { grpc_combiner *lock = gpr_malloc(sizeof(*lock)); - lock->optional_workqueue = GRPC_WORKQUEUE_REF(optional_workqueue, "combiner"); + lock->optional_workqueue = optional_workqueue; gpr_atm_no_barrier_store(&lock->state, 1); gpr_mpscq_init(&lock->queue); lock->take_async_break_before_final_list = false; diff --git a/src/core/lib/iomgr/workqueue.h b/src/core/lib/iomgr/workqueue.h index 416618e258..01f4cb01b8 100644 --- a/src/core/lib/iomgr/workqueue.h +++ b/src/core/lib/iomgr/workqueue.h @@ -50,7 +50,7 @@ /* grpc_workqueue is forward declared in exec_ctx.h */ -//#define GRPC_WORKQUEUE_REFCOUNT_DEBUG +#define GRPC_WORKQUEUE_REFCOUNT_DEBUG #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG #define GRPC_WORKQUEUE_REF(p, r) \ (grpc_workqueue_ref((p), __FILE__, __LINE__, (r)), (p)) -- cgit v1.2.3 From 9e1803ec0b0efa28a8845e538c796853bca5011a Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 13 Jul 2016 17:24:47 -0700 Subject: wq fixes --- src/core/lib/iomgr/workqueue.h | 2 +- src/core/lib/iomgr/workqueue_posix.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/workqueue.h b/src/core/lib/iomgr/workqueue.h index 01f4cb01b8..416618e258 100644 --- a/src/core/lib/iomgr/workqueue.h +++ b/src/core/lib/iomgr/workqueue.h @@ -50,7 +50,7 @@ /* grpc_workqueue is forward declared in exec_ctx.h */ -#define GRPC_WORKQUEUE_REFCOUNT_DEBUG +//#define GRPC_WORKQUEUE_REFCOUNT_DEBUG #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG #define GRPC_WORKQUEUE_REF(p, r) \ (grpc_workqueue_ref((p), __FILE__, __LINE__, (r)), (p)) diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c index 49a100520e..801c097566 100644 --- a/src/core/lib/iomgr/workqueue_posix.c +++ b/src/core/lib/iomgr/workqueue_posix.c @@ -83,6 +83,7 @@ static void workqueue_orphan(grpc_exec_ctx *exec_ctx, #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) { + if (workqueue == NULL) return; gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p ref %d -> %d %s", workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count + 1, reason); @@ -98,6 +99,7 @@ void grpc_workqueue_ref(grpc_workqueue *workqueue) { #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason) { + if (workqueue == NULL) return; gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p unref %d -> %d %s", workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count - 1, reason); -- cgit v1.2.3 From c69d27b67d16f635aa234f28cc51608b609e0d1d Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 14 Jul 2016 13:20:22 -0700 Subject: Add timing data --- .../transport/chttp2/transport/chttp2_transport.c | 39 +++++++++++++++++++++- src/core/ext/transport/chttp2/transport/writing.c | 2 ++ src/core/lib/iomgr/combiner.c | 28 +++++++++++++++- src/core/lib/iomgr/workqueue_posix.c | 8 +++++ 4 files changed, 75 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 705761d46b..23389047e4 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -494,6 +494,7 @@ static void finish_init_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_stream_refcount *refcount, const void *server_data) { + GPR_TIMER_BEGIN("init_stream", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; @@ -539,6 +540,8 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_combiner_execute(exec_ctx, t->executor.combiner, &s->init_stream, GRPC_ERROR_NONE); + GPR_TIMER_END("init_stream", 0); + return 0; } @@ -607,6 +610,7 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, void *and_free_memory) { + GPR_TIMER_BEGIN("destroy_stream", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; @@ -614,6 +618,7 @@ static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_closure_init(&s->destroy_stream, destroy_stream_locked, s); grpc_combiner_execute(exec_ctx, t->executor.combiner, &s->destroy_stream, GRPC_ERROR_NONE); + GPR_TIMER_END("destroy_stream", 0); } grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream( @@ -691,6 +696,7 @@ static void initiate_read_flush_locked(grpc_exec_ctx *exec_ctx, void *tp, void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, bool covered_by_poller, const char *reason) { + GPR_TIMER_BEGIN("grpc_chttp2_initiate_write", 0); grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global); switch (t->executor.write_state) { case GRPC_CHTTP2_WRITES_CORKED: @@ -724,9 +730,11 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, } break; } + GPR_TIMER_END("grpc_chttp2_initiate_write", 0); } static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { + GPR_TIMER_BEGIN("start_writing", 0); GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED); if (!t->closed && grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) { @@ -744,6 +752,7 @@ static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { end_waiting_for_write(exec_ctx, t, GRPC_ERROR_CREATE("Nothing to write")); UNREF_TRANSPORT(exec_ctx, t, "writing"); } + GPR_TIMER_END("start_writing", 0); } void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx, @@ -788,6 +797,7 @@ static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { + GPR_TIMER_BEGIN("terminate_writing_with_lock", 0); grpc_chttp2_transport *t = tp; allow_endpoint_shutdown_locked(exec_ctx, t); @@ -805,9 +815,11 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *tp, case GRPC_CHTTP2_WRITE_SCHEDULED: GPR_UNREACHABLE_CODE(break); case GRPC_CHTTP2_WRITING: + GPR_TIMER_MARK("state=writing", 0); set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "terminate_writing"); break; case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: + GPR_TIMER_MARK("state=writing_stale_with_poller", 0); set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "terminate_writing"); REF_TRANSPORT(t, "writing"); grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, @@ -815,6 +827,7 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *tp, true); break; case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: + GPR_TIMER_MARK("state=writing_stale_no_poller", 0); set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "terminate_writing"); REF_TRANSPORT(t, "writing"); grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, @@ -824,13 +837,16 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *tp, } UNREF_TRANSPORT(exec_ctx, t, "writing"); + GPR_TIMER_END("terminate_writing_with_lock", 0); } void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx, void *transport_writing, grpc_error *error) { + GPR_TIMER_BEGIN("grpc_chttp2_terminate_writing", 0); grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); grpc_combiner_execute(exec_ctx, t->executor.combiner, &t->terminate_writing, GRPC_ERROR_REF(error)); + GPR_TIMER_END("grpc_chttp2_terminate_writing", 0); } static void writing_action(grpc_exec_ctx *exec_ctx, void *gt, @@ -1170,6 +1186,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_transport_stream_op *op) { + GPR_TIMER_BEGIN("perform_stream_op", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; grpc_closure_init(&op->transport_private.closure, perform_stream_op_locked, @@ -1179,6 +1196,7 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, GRPC_CHTTP2_STREAM_REF(&s->global, "perform_stream_op"); grpc_combiner_execute(exec_ctx, t->executor.combiner, &op->transport_private.closure, GRPC_ERROR_NONE); + GPR_TIMER_END("perform_stream_op", 0); } static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, @@ -1315,6 +1333,7 @@ static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, static void check_read_ops(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global) { + GPR_TIMER_BEGIN("check_read_ops", 0); grpc_chttp2_stream_global *stream_global; grpc_byte_stream *bs; while ( @@ -1389,6 +1408,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, } } } + GPR_TIMER_END("check_read_ops", 0); } static void decrement_active_streams_locked( @@ -1830,13 +1850,17 @@ static void reading_action(grpc_exec_ctx *exec_ctx, void *tp, reading_action_locked -> (parse_unlocked -> post_parse_locked)? -> post_reading_action_locked */ + GPR_TIMER_BEGIN("reading_action", 0); grpc_chttp2_transport *t = tp; grpc_combiner_execute(exec_ctx, t->executor.combiner, &t->reading_action_locked, GRPC_ERROR_REF(error)); + GPR_TIMER_END("reading_action", 0); } static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { + GPR_TIMER_BEGIN("reading_action_locked", 0); + grpc_chttp2_transport *t = tp; grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_transport_parsing *transport_parsing = &t->parsing; @@ -1853,6 +1877,8 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *tp, } else { post_reading_action_locked(exec_ctx, t, error); } + + GPR_TIMER_END("reading_action_locked", 0); } static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, @@ -1905,13 +1931,14 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) { GRPC_ERROR_UNREF(errors[i]); } - GPR_TIMER_END("reading_action.parse", 0); grpc_combiner_execute(exec_ctx, t->executor.combiner, &t->post_parse_locked, err); + GPR_TIMER_END("reading_action.parse", 0); } static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_TIMER_BEGIN("post_parse_locked", 0); grpc_chttp2_transport *t = arg; grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_transport_parsing *transport_parsing = &t->parsing; @@ -1956,10 +1983,12 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, } post_reading_action_locked(exec_ctx, t, error); + GPR_TIMER_END("post_parse_locked", 0); } static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_TIMER_BEGIN("post_reading_action_locked", 0); grpc_chttp2_transport *t = arg; bool keep_reading = false; GRPC_ERROR_REF(error); @@ -1992,6 +2021,8 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, UNREF_TRANSPORT(exec_ctx, t, "reading_action"); } GRPC_ERROR_UNREF(error); + + GPR_TIMER_END("post_reading_action_locked", 0); } /******************************************************************************* @@ -2112,6 +2143,7 @@ static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream, gpr_slice *slice, size_t max_size_hint, grpc_closure *on_complete) { + GPR_TIMER_BEGIN("incoming_byte_stream_next", 0); grpc_chttp2_incoming_byte_stream *bs = (grpc_chttp2_incoming_byte_stream *)byte_stream; gpr_ref(&bs->refs); @@ -2122,6 +2154,7 @@ static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx, bs); grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, &bs->next_action.closure, GRPC_ERROR_NONE); + GPR_TIMER_END("incoming_byte_stream_next", 0); return 0; } @@ -2140,12 +2173,14 @@ static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream) { + GPR_TIMER_BEGIN("incoming_byte_stream_destroy", 0); grpc_chttp2_incoming_byte_stream *bs = (grpc_chttp2_incoming_byte_stream *)byte_stream; grpc_closure_init(&bs->destroy_action, incoming_byte_stream_destroy_locked, bs); grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, &bs->destroy_action, GRPC_ERROR_NONE); + GPR_TIMER_END("incoming_byte_stream_destroy", 0); } typedef struct { @@ -2182,6 +2217,7 @@ static void incoming_byte_stream_finished_locked(grpc_exec_ctx *exec_ctx, void grpc_chttp2_incoming_byte_stream_finished( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, grpc_error *error, int from_parsing_thread) { + GPR_TIMER_BEGIN("grpc_chttp2_incoming_byte_stream_finished", 0); if (from_parsing_thread) { grpc_closure_init(&bs->finished_action, incoming_byte_stream_finished_locked, bs); @@ -2190,6 +2226,7 @@ void grpc_chttp2_incoming_byte_stream_finished( } else { incoming_byte_stream_finished_locked(exec_ctx, bs, error); } + GPR_TIMER_END("grpc_chttp2_incoming_byte_stream_finished", 0); } grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create( diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c index e0d87725e9..ad3441cfeb 100644 --- a/src/core/ext/transport/chttp2/transport/writing.c +++ b/src/core/ext/transport/chttp2/transport/writing.c @@ -332,6 +332,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx, void grpc_chttp2_cleanup_writing( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_writing *transport_writing) { + GPR_TIMER_BEGIN("grpc_chttp2_cleanup_writing", 0); grpc_chttp2_stream_writing *stream_writing; grpc_chttp2_stream_global *stream_global; @@ -370,4 +371,5 @@ void grpc_chttp2_cleanup_writing( GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing"); } gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf); + GPR_TIMER_END("grpc_chttp2_cleanup_writing", 0); } diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index 73347d5024..ebe9fd24ec 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -32,13 +32,15 @@ */ #include "src/core/lib/iomgr/combiner.h" -#include "src/core/lib/iomgr/workqueue.h" #include #include #include +#include "src/core/lib/iomgr/workqueue.h" +#include "src/core/lib/profiling/timers.h" + struct grpc_combiner { grpc_workqueue *optional_workqueue; gpr_mpscq queue; @@ -79,15 +81,18 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); static void continue_finishing_mainline(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_TIMER_BEGIN("combiner.continue_executing_mainline", 0); grpc_combiner *lock = arg; GPR_ASSERT(exec_ctx->active_combiner == NULL); exec_ctx->active_combiner = lock; if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); GPR_ASSERT(exec_ctx->active_combiner == lock); exec_ctx->active_combiner = NULL; + GPR_TIMER_END("combiner.continue_executing_mainline", 0); } static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + GPR_TIMER_BEGIN("combiner.execute_final", 0); grpc_closure *c = lock->final_list.head; grpc_closure_list_init(&lock->final_list); lock->take_async_break_before_final_list = false; @@ -98,10 +103,12 @@ static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { GRPC_ERROR_UNREF(error); c = next; } + GPR_TIMER_END("combiner.execute_final", 0); } static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_TIMER_BEGIN("combiner.continue_executing_final", 0); grpc_combiner *lock = arg; GPR_ASSERT(exec_ctx->active_combiner == NULL); exec_ctx->active_combiner = lock; @@ -115,23 +122,28 @@ static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, } GPR_ASSERT(exec_ctx->active_combiner == lock); exec_ctx->active_combiner = NULL; + GPR_TIMER_END("combiner.continue_executing_final", 0); } static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + GPR_TIMER_BEGIN("combiner.start_execute_final", 0); GPR_ASSERT(exec_ctx->active_combiner == lock); if (lock->take_async_break_before_final_list) { grpc_closure_init(&lock->continue_finishing, continue_executing_final, lock); grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); + GPR_TIMER_END("combiner.start_execute_final", 0); return false; } else { execute_final(exec_ctx, lock); + GPR_TIMER_END("combiner.start_execute_final", 0); return true; } } static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + GPR_TIMER_BEGIN("combiner.maybe_finish_one", 0); gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); GPR_ASSERT(exec_ctx->active_combiner == lock); if (n == NULL) { @@ -141,18 +153,21 @@ static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { lock); grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); + GPR_TIMER_END("combiner.maybe_finish_one", 0); return false; } grpc_closure *cl = (grpc_closure *)n; grpc_error *error = cl->error; cl->cb(exec_ctx, cl->cb_arg, error); GRPC_ERROR_UNREF(error); + GPR_TIMER_END("combiner.maybe_finish_one", 0); return true; } static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { bool (*executor)(grpc_exec_ctx * exec_ctx, grpc_combiner * lock) = maybe_finish_one; + GPR_TIMER_BEGIN("combiner.finish",0); do { switch (gpr_atm_full_fetch_add(&lock->state, -2)) { case 5: // we're down to one queued item: if it's the final list we @@ -162,9 +177,11 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { } break; case 3: // had one count, one unorphaned --> unlocked unorphaned + GPR_TIMER_END("combiner.finish", 0); return; case 2: // and one count, one orphaned --> unlocked and orphaned really_destroy(exec_ctx, lock); + GPR_TIMER_END("combiner.finish", 0); return; case 1: case 0: @@ -173,15 +190,19 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { GPR_UNREACHABLE_CODE(return ); } } while (executor(exec_ctx, lock)); + GPR_TIMER_END("combiner.finish", 0); } void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *cl, grpc_error *error) { + GPR_TIMER_BEGIN("combiner.execute", 0); gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); GPR_ASSERT(last & 1); // ensure lock has not been destroyed if (last == 1) { exec_ctx->active_combiner = lock; + GPR_TIMER_BEGIN("combiner.execute_first_cb", 0); cl->cb(exec_ctx, cl->cb_arg, error); + GPR_TIMER_END("combiner.execute_first_cb", 0); GRPC_ERROR_UNREF(error); finish(exec_ctx, lock); GPR_ASSERT(exec_ctx->active_combiner == lock); @@ -190,6 +211,7 @@ void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, cl->error = error; gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); } + GPR_TIMER_END("combiner.execute", 0); } static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, @@ -201,9 +223,12 @@ static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error, bool force_async_break) { + GPR_TIMER_BEGIN("combiner.execute_finally", 0); if (exec_ctx->active_combiner != lock) { + GPR_TIMER_MARK("slowpath", 0); grpc_combiner_execute(exec_ctx, lock, grpc_closure_create(enqueue_finally, closure), error); + GPR_TIMER_END("combiner.execute_finally", 0); return; } @@ -214,6 +239,7 @@ void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, gpr_atm_full_fetch_add(&lock->state, 2); } grpc_closure_list_append(&lock->final_list, closure, error); + GPR_TIMER_END("combiner.execute_finally", 0); } void grpc_combiner_force_async_finally(grpc_combiner *lock) { diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c index 801c097566..289c7a2fe2 100644 --- a/src/core/lib/iomgr/workqueue_posix.c +++ b/src/core/lib/iomgr/workqueue_posix.c @@ -43,6 +43,7 @@ #include #include +#include "src/core/lib/profiling/timers.h" #include "src/core/lib/iomgr/ev_posix.h" static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); @@ -121,6 +122,7 @@ static void drain(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { } static void wakeup(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { + GPR_TIMER_MARK("workqueue.wakeup", 0); grpc_error *err = grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd); if (!GRPC_LOG_IF_ERROR("wakeupfd_wakeup", err)) { drain(exec_ctx, workqueue); @@ -128,6 +130,8 @@ static void wakeup(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { } static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_TIMER_BEGIN("workqueue.on_readable", 0); + grpc_workqueue *workqueue = arg; if (error != GRPC_ERROR_NONE) { @@ -172,10 +176,13 @@ static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { GRPC_ERROR_UNREF(clerr); } } + + GPR_TIMER_END("workqueue.on_readable", 0); } void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, grpc_closure *closure, grpc_error *error) { + GPR_TIMER_BEGIN("workqueue.enqueue", 0); gpr_atm last = gpr_atm_full_fetch_add(&workqueue->state, 2); GPR_ASSERT(last & 1); closure->error = error; @@ -183,6 +190,7 @@ void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, if (last == 1) { wakeup(exec_ctx, workqueue); } + GPR_TIMER_END("workqueue.enqueue", 0); } #endif /* GPR_POSIX_SOCKET */ -- cgit v1.2.3 From 9d01848ef2a933d50e5d7ed95598788614d70bc8 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 18 Jul 2016 08:53:49 -0700 Subject: Fixes --- src/core/ext/client_config/subchannel_call_holder.c | 4 ++++ .../ext/transport/chttp2/transport/chttp2_transport.c | 4 ++-- src/core/ext/transport/chttp2/transport/writing.c | 19 ++++++++++--------- src/core/lib/iomgr/ev_epoll_linux.c | 4 ++++ src/core/lib/security/transport/client_auth_filter.c | 5 +++++ src/core/lib/security/transport/secure_endpoint.c | 5 +++++ src/core/lib/surface/channel_ping.c | 2 ++ src/core/lib/surface/lame_client.c | 6 +++--- src/core/lib/surface/server.c | 7 +++++-- test/core/surface/lame_client_test.c | 6 +++--- 10 files changed, 43 insertions(+), 19 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/subchannel_call_holder.c b/src/core/ext/client_config/subchannel_call_holder.c index 7eb17c713a..b10b204ff2 100644 --- a/src/core/ext/client_config/subchannel_call_holder.c +++ b/src/core/ext/client_config/subchannel_call_holder.c @@ -207,6 +207,10 @@ typedef struct { static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, grpc_subchannel_call_holder *holder) { + if (holder->waiting_ops_count == 0) { + return; + } + retry_ops_args *a = gpr_malloc(sizeof(*a)); a->ops = holder->waiting_ops; a->nops = holder->waiting_ops_count; diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 98b01426a4..edb5346dbe 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -311,7 +311,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, if (is_client) { gpr_slice_buffer_add( - &t->global.qbuf, + &t->writing.outbuf, gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)); grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "initial_write"); } @@ -768,7 +768,7 @@ static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "start_writing:nothing_to_write"); } - end_waiting_for_write(exec_ctx, t, GRPC_ERROR_CREATE("Nothing to write")); + end_waiting_for_write(exec_ctx, t, GRPC_ERROR_NONE); UNREF_TRANSPORT(exec_ctx, t, "writing"); } GPR_TIMER_END("start_writing", 0); diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c index ad3441cfeb..9e6555cdd3 100644 --- a/src/core/ext/transport/chttp2/transport/writing.c +++ b/src/core/ext/transport/chttp2/transport/writing.c @@ -51,15 +51,6 @@ int grpc_chttp2_unlocking_check_writes( GPR_TIMER_BEGIN("grpc_chttp2_unlocking_check_writes", 0); - /* simple writes are queued to qbuf, and flushed here */ - gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf); - GPR_ASSERT(transport_global->qbuf.count == 0); - - grpc_chttp2_hpack_compressor_set_max_table_size( - &transport_writing->hpack_compressor, - transport_global->settings[GRPC_PEER_SETTINGS] - [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); - if (transport_global->dirtied_local_settings && !transport_global->sent_local_settings) { gpr_slice_buffer_add( @@ -73,6 +64,16 @@ int grpc_chttp2_unlocking_check_writes( transport_global->sent_local_settings = 1; } + /* simple writes are queued to qbuf, and flushed here */ + gpr_slice_buffer_move_into(&transport_global->qbuf, + &transport_writing->outbuf); + GPR_ASSERT(transport_global->qbuf.count == 0); + + grpc_chttp2_hpack_compressor_set_max_table_size( + &transport_writing->hpack_compressor, + transport_global->settings[GRPC_PEER_SETTINGS] + [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); + GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window, transport_global, outgoing_window); if (transport_writing->outgoing_window > 0) { diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c index 6a63c4d1d1..57c26138be 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epoll_linux.c @@ -1526,6 +1526,8 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_fd *fd) { + GPR_TIMER_BEGIN("pollset_add_fd", 0); + grpc_error *error = GRPC_ERROR_NONE; gpr_mu_lock(&pollset->mu); @@ -1638,6 +1640,8 @@ retry: gpr_mu_unlock(&pollset->mu); GRPC_LOG_IF_ERROR("pollset_add_fd", error); + + GPR_TIMER_END("pollset_add_fd", 0); } /******************************************************************************* diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c index ed7929aa27..b13bd55df1 100644 --- a/src/core/lib/security/transport/client_auth_filter.c +++ b/src/core/lib/security/transport/client_auth_filter.c @@ -40,6 +40,7 @@ #include #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/profiling/timers.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/transport/security_connector.h" @@ -218,6 +219,8 @@ static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data, static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op *op) { + GPR_TIMER_BEGIN("auth_start_transport_op", 0); + /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; @@ -258,12 +261,14 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector_check_call_host( exec_ctx, chand->security_connector, call_host, chand->auth_context, on_host_checked, elem); + GPR_TIMER_END("auth_start_transport_op", 0); return; /* early exit */ } } /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, op); + GPR_TIMER_END("auth_start_transport_op", 0); } /* Constructor for call_data */ diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c index 0169ccd9ef..acb0113ea8 100644 --- a/src/core/lib/security/transport/secure_endpoint.c +++ b/src/core/lib/security/transport/secure_endpoint.c @@ -38,6 +38,7 @@ #include #include #include "src/core/lib/debug/trace.h" +#include "src/core/lib/profiling/timers.h" #include "src/core/lib/security/transport/tsi_error.h" #include "src/core/lib/support/string.h" #include "src/core/lib/tsi/transport_security_interface.h" @@ -248,6 +249,8 @@ static void flush_write_staging_buffer(secure_endpoint *ep, uint8_t **cur, static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, gpr_slice_buffer *slices, grpc_closure *cb) { + GPR_TIMER_BEGIN("secure_endpoint.endpoint_write", 0); + unsigned i; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)secure_ep; @@ -323,10 +326,12 @@ static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, exec_ctx, cb, grpc_set_tsi_error_result(GRPC_ERROR_CREATE("Wrap failed"), result), NULL); + GPR_TIMER_END("secure_endpoint.endpoint_write", 0); return; } grpc_endpoint_write(exec_ctx, ep->wrapped_ep, &ep->output_buffer, cb); + GPR_TIMER_END("secure_endpoint.endpoint_write", 0); } static void endpoint_shutdown(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/surface/channel_ping.c b/src/core/lib/surface/channel_ping.c index 5f9f07f89a..0d2f01a649 100644 --- a/src/core/lib/surface/channel_ping.c +++ b/src/core/lib/surface/channel_ping.c @@ -61,6 +61,8 @@ static void ping_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved) { + GRPC_API_TRACE("grpc_channel_ping(channel=%p, cq=%p, tag=%p, reserved=%p)", 4, + (channel, cq, tag, reserved)); grpc_transport_op *op = grpc_make_transport_op(NULL); ping_result *pr = gpr_malloc(sizeof(*pr)); grpc_channel_element *top_elem = diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c index 5ea4cba5d1..203d614b31 100644 --- a/src/core/lib/surface/lame_client.c +++ b/src/core/lib/surface/lame_client.c @@ -97,14 +97,14 @@ static void lame_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_exec_ctx_sched(exec_ctx, op->on_connectivity_state_change, GRPC_ERROR_NONE, NULL); } - if (op->on_consumed != NULL) { - grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); - } if (op->send_ping != NULL) { grpc_exec_ctx_sched(exec_ctx, op->send_ping, GRPC_ERROR_CREATE("lame client channel"), NULL); } GRPC_ERROR_UNREF(op->disconnect_with_error); + if (op->on_consumed != NULL) { + grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); + } } static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index e0b5ed6297..b6f4b5e427 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -428,7 +428,8 @@ static void finish_destroy_channel(grpc_exec_ctx *exec_ctx, void *cd, server_unref(exec_ctx, server); } -static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) { +static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand, + grpc_error *error) { if (is_channel_orphaned(chand)) return; GPR_ASSERT(chand->server != NULL); orphan_channel(chand); @@ -444,6 +445,8 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) { grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), op); + + GRPC_LOG_IF_ERROR("disconnecting client", error); } static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) { @@ -845,7 +848,7 @@ static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd, op); } else { gpr_mu_lock(&server->mu_global); - destroy_channel(exec_ctx, chand); + destroy_channel(exec_ctx, chand, GRPC_ERROR_REF(error)); gpr_mu_unlock(&server->mu_global); GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "connectivity"); } diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index cad45cc9fa..68c1e0eab0 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -49,8 +49,8 @@ static void *tag(intptr_t x) { return (void *)x; } void verify_connectivity(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - grpc_transport_op *op = arg; - GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *op->connectivity_state); + grpc_connectivity_state *state = arg; + GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *state); GPR_ASSERT(error == GRPC_ERROR_NONE); } @@ -62,7 +62,7 @@ void test_transport_op(grpc_channel *channel) { grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_closure_init(&transport_op_cb, verify_connectivity, &op); + grpc_closure_init(&transport_op_cb, verify_connectivity, &state); op = grpc_make_transport_op(NULL); op->on_connectivity_state_change = &transport_op_cb; -- cgit v1.2.3 From 4623e1c5d948b79402158644f5fd6cf6bb69d8f8 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Mon, 18 Jul 2016 14:09:18 -0700 Subject: Initial framework for HTTP CONNECT handshaker. --- .../ext/client_config/http_connect_handshaker.c | 122 +++++++++++++++++++++ .../ext/client_config/http_connect_handshaker.h | 41 +++++++ src/core/lib/iomgr/endpoint.h | 3 +- 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 src/core/ext/client_config/http_connect_handshaker.c create mode 100644 src/core/ext/client_config/http_connect_handshaker.h (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/http_connect_handshaker.c b/src/core/ext/client_config/http_connect_handshaker.c new file mode 100644 index 0000000000..3590805beb --- /dev/null +++ b/src/core/ext/client_config/http_connect_handshaker.c @@ -0,0 +1,122 @@ +/* + * + * 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 + +#include +#include + +#include "src/core/ext/client_config/http_connect_handshaker.h" + +typedef struct http_connect_handshaker { + // Base class. Must be first. + grpc_handshaker base; + + // State saved while performing the handshake. + grpc_endpoint* endpoint; + grpc_channel_args* args; + grpc_handshaker_done_cb cb; + void* user_data; + + // Objects for processing the HTTP CONNECT request and response. + grpc_slice_buffer request_buffer; + grpc_closure request_done_closure; + grpc_slice_buffer response_buffer; + grpc_closure response_read_closure; +} http_connect_handshaker; + +static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx, + grpc_handshaker* handshaker) { +} + +static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx, + grpc_handshaker* handshaker) { +} + +// Callback invoked for reading HTTP CONNECT response. +static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + http_connect_handshaker* h = arg; +// FIXME: process response; on failure, figure out how to abort + + // Invoke handshake-done callback. + h->cb(exec_ctx, h->endpoint, h->args, h->user_data); +} + +// Callback invoked when finished writing HTTP CONNECT request. +static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + http_connect_handshaker* h = arg; + // Read HTTP CONNECT response. + gpr_slice_buffer_init(&h->response_buffer); + grpc_closure_init(&h->response_read_closure, on_read_done, h); + grpc_endpoint_read(exec_ctx, h->endpoint, &h->response_buffer, + &h->response_read_closure); +} + +static void http_connect_handshaker_do_handshake(grpc_exec_ctx* exec_ctx, + grpc_handshaker* handshaker, + grpc_endpoint* endpoint, + grpc_channel_args* args, + gpr_timespec deadline, + grpc_handshaker_done_cb cb, + void* user_data) { + http_connect_handshaker* h = (http_connect_handshaker*)handshaker; + // Save state in the handshaker object. + h->endpoint = endpoint; + h->args = args; + h->cb = cb; + h->user_data = user_data; + // Send HTTP CONNECT request. + gpr_slice_buffer_init(&h->request_buffer); + gpr_slice_buffer_add(&h->request_buffer, "HTTP CONNECT "); +// FIXME: get server name from somewhere... + gpr_slice_buffer_add(&h->request_buffer, WHEE); +// FIXME: add headers as needed? + gpr_slice_buffer_add(&h->request_buffer, "\n\n"); + grpc_closure_init(&h->request_done_closure, on_write_done, h); + grpc_endpoint_write(exec_ctx, endpoint, &h->request_buffer, + &h->request_done_closure); +} + +static const struct grpc_handshaker_vtable http_connect_handshaker_vtable = { + http_connect_handshaker_destroy, http_connect_handshaker_shutdown, + http_connect_handshaker_do_handshake}; + +grpc_handshaker* grpc_http_connect_handshaker_create() { + http_connect_handshaker* handshaker = + gpr_malloc(sizeof(http_connect_handshaker)); + memset(handshaker, 0, sizeof(*handshaker)); + grpc_handshaker_init(http_connect_handshaker_vtable, &handshaker->base); + return (grpc_handshaker*)handshaker; +} diff --git a/src/core/ext/client_config/http_connect_handshaker.h b/src/core/ext/client_config/http_connect_handshaker.h new file mode 100644 index 0000000000..b7d4e8b1dd --- /dev/null +++ b/src/core/ext/client_config/http_connect_handshaker.h @@ -0,0 +1,41 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_EXT_CLIENT_CONFIG_HTTP_CONNECT_HANDSHAKER_H +#define GRPC_CORE_EXT_CLIENT_CONFIG_HTTP_CONNECT_HANDSHAKER_H + +#include "src/core/lib/channel/handshaker.h" + +grpc_handshaker* grpc_http_connect_handshaker_create(); + +#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_HTTP_CONNECT_HANDSHAKER_H */ diff --git a/src/core/lib/iomgr/endpoint.h b/src/core/lib/iomgr/endpoint.h index f9808bbda1..4d5593b0b0 100644 --- a/src/core/lib/iomgr/endpoint.h +++ b/src/core/lib/iomgr/endpoint.h @@ -63,7 +63,8 @@ struct grpc_endpoint_vtable { /* When data is available on the connection, calls the callback with slices. Callback success indicates that the endpoint can accept more reads, failure indicates the endpoint is closed. - Valid slices may be placed into \a slices even on callback success == 0. */ + Valid slices may be placed into \a slices even when the callback is + invoked with error != GRPC_ERROR_NONE. */ void grpc_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, gpr_slice_buffer *slices, grpc_closure *cb); -- cgit v1.2.3 From e7603b887eee0bbc21225fbae7231c0e5b629e24 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 18 Jul 2016 15:43:42 -0700 Subject: Fixes & debug --- .../transport/chttp2/transport/chttp2_transport.c | 14 ++++-- src/core/lib/iomgr/combiner.c | 50 ++++++++++++++++++---- src/core/lib/iomgr/tcp_posix.c | 9 ++++ src/core/lib/surface/server.c | 7 ++- 4 files changed, 66 insertions(+), 14 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index edb5346dbe..ced74dc8ff 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -1019,6 +1019,12 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_stream_global *stream_global = &s->global; + if (grpc_http_trace) { + char *str = grpc_transport_stream_op_string(op); + gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s", str); + gpr_free(str); + } + grpc_closure *on_complete = op->on_complete; if (on_complete == NULL) { on_complete = grpc_closure_create(do_nothing, NULL); @@ -1821,6 +1827,10 @@ static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { + if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { + error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_UNAVAILABLE); + } close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error)); end_all_the_calls(exec_ctx, t, error); } @@ -2015,10 +2025,6 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, error = GRPC_ERROR_CREATE("Transport closed"); } if (error != GRPC_ERROR_NONE) { - if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { - error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, - GRPC_STATUS_UNAVAILABLE); - } drop_connection(exec_ctx, t, GRPC_ERROR_REF(error)); t->endpoint_reading = 0; if (grpc_http_write_state_trace) { diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index ebe9fd24ec..c3c32cb8a3 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -41,6 +41,13 @@ #include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" +int grpc_combiner_trace = 0; + +#define COMBINER_TRACE(fn) \ + if (grpc_combiner_trace) { \ + fn \ + } + struct grpc_combiner { grpc_workqueue *optional_workqueue; gpr_mpscq queue; @@ -60,10 +67,12 @@ grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { gpr_mpscq_init(&lock->queue); lock->take_async_break_before_final_list = false; grpc_closure_list_init(&lock->final_list); + gpr_log(GPR_DEBUG, "C:%p create", lock); return lock; } static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + gpr_log(GPR_DEBUG, "C:%p really_destroy", lock); GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); gpr_mpscq_destroy(&lock->queue); GRPC_WORKQUEUE_UNREF(exec_ctx, lock->optional_workqueue, "combiner"); @@ -71,7 +80,10 @@ static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { } void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { - if (gpr_atm_full_fetch_add(&lock->state, -1) == 1) { + gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -1); + gpr_log(GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, + old_state); + if (old_state == 1) { really_destroy(exec_ctx, lock); } } @@ -83,6 +95,7 @@ static void continue_finishing_mainline(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { GPR_TIMER_BEGIN("combiner.continue_executing_mainline", 0); grpc_combiner *lock = arg; + gpr_log(GPR_DEBUG, "C:%p continue_finishing_mainline", lock); GPR_ASSERT(exec_ctx->active_combiner == NULL); exec_ctx->active_combiner = lock; if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); @@ -94,14 +107,18 @@ static void continue_finishing_mainline(grpc_exec_ctx *exec_ctx, void *arg, static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { GPR_TIMER_BEGIN("combiner.execute_final", 0); grpc_closure *c = lock->final_list.head; + GPR_ASSERT(c != NULL); grpc_closure_list_init(&lock->final_list); lock->take_async_break_before_final_list = false; + int loops = 0; while (c != NULL) { + gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c); grpc_closure *next = c->next_data.next; grpc_error *error = c->error; c->cb(exec_ctx, c->cb_arg, error); GRPC_ERROR_UNREF(error); c = next; + loops++; } GPR_TIMER_END("combiner.execute_final", 0); } @@ -110,6 +127,7 @@ static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { GPR_TIMER_BEGIN("combiner.continue_executing_final", 0); grpc_combiner *lock = arg; + gpr_log(GPR_DEBUG, "C:%p continue_executing_final", lock); GPR_ASSERT(exec_ctx->active_combiner == NULL); exec_ctx->active_combiner = lock; // quick peek to see if new things have turned up on the queue: if so, go back @@ -128,6 +146,9 @@ static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { GPR_TIMER_BEGIN("combiner.start_execute_final", 0); GPR_ASSERT(exec_ctx->active_combiner == lock); + gpr_log(GPR_DEBUG, + "C:%p start_execute_final take_async_break_before_final_list=%d", + lock, lock->take_async_break_before_final_list); if (lock->take_async_break_before_final_list) { grpc_closure_init(&lock->continue_finishing, continue_executing_final, lock); @@ -145,6 +166,7 @@ static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { GPR_TIMER_BEGIN("combiner.maybe_finish_one", 0); gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); + gpr_log(GPR_DEBUG, "C:%p maybe_finish_one n=%p", lock, n); GPR_ASSERT(exec_ctx->active_combiner == lock); if (n == NULL) { // queue is in an inconsistant state: use this as a cue that we should @@ -160,16 +182,21 @@ static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { grpc_error *error = cl->error; cl->cb(exec_ctx, cl->cb_arg, error); GRPC_ERROR_UNREF(error); - GPR_TIMER_END("combiner.maybe_finish_one", 0); + GPR_TIMER_END("combiner.maybe_finish_one", 0); return true; } static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { - bool (*executor)(grpc_exec_ctx * exec_ctx, grpc_combiner * lock) = - maybe_finish_one; - GPR_TIMER_BEGIN("combiner.finish",0); + bool (*executor)(grpc_exec_ctx * exec_ctx, grpc_combiner * lock); + GPR_TIMER_BEGIN("combiner.finish", 0); + int loops = 0; do { - switch (gpr_atm_full_fetch_add(&lock->state, -2)) { + executor = maybe_finish_one; + gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -2); + gpr_log(GPR_DEBUG, "C:%p finish[%d] old_state=%" PRIdPTR " cl=[%p,%p]", + lock, loops, old_state, lock->final_list.head, + lock->final_list.tail); + switch (old_state) { case 5: // we're down to one queued item: if it's the final list we case 4: // should do that if (!grpc_closure_list_empty(lock->final_list)) { @@ -189,12 +216,14 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { // deleted lock GPR_UNREACHABLE_CODE(return ); } + loops++; } while (executor(exec_ctx, lock)); - GPR_TIMER_END("combiner.finish", 0); + GPR_TIMER_END("combiner.finish", 0); } void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *cl, grpc_error *error) { + gpr_log(GPR_DEBUG, "C:%p grpc_combiner_execute c=%p", lock, cl); GPR_TIMER_BEGIN("combiner.execute", 0); gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); GPR_ASSERT(last & 1); // ensure lock has not been destroyed @@ -217,12 +246,15 @@ void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, grpc_error *error) { grpc_combiner_execute_finally(exec_ctx, exec_ctx->active_combiner, closure, - GRPC_ERROR_REF(error), true); + GRPC_ERROR_REF(error), false); } void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error, bool force_async_break) { + gpr_log(GPR_DEBUG, + "C:%p grpc_combiner_execute_finally c=%p force_async_break=%d; ac=%p", + lock, closure, force_async_break, exec_ctx->active_combiner); GPR_TIMER_BEGIN("combiner.execute_finally", 0); if (exec_ctx->active_combiner != lock) { GPR_TIMER_MARK("slowpath", 0); @@ -239,7 +271,7 @@ void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, gpr_atm_full_fetch_add(&lock->state, 2); } grpc_closure_list_append(&lock->final_list, closure, error); - GPR_TIMER_END("combiner.execute_finally", 0); + GPR_TIMER_END("combiner.execute_finally", 0); } void grpc_combiner_force_async_finally(grpc_combiner *lock) { diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c index ec21e03944..bf6e9b16b3 100644 --- a/src/core/lib/iomgr/tcp_posix.c +++ b/src/core/lib/iomgr/tcp_posix.c @@ -379,10 +379,15 @@ static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, } if (!tcp_flush(tcp, &error)) { + gpr_log(GPR_DEBUG, "write: delayed"); grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { cb = tcp->write_cb; tcp->write_cb = NULL; + const char *str = grpc_error_string(error); + gpr_log(GPR_DEBUG, "write: %s", str); + grpc_error_free_string(str); + GPR_TIMER_BEGIN("tcp_handle_write.cb", 0); cb->cb(exec_ctx, cb->cb_arg, error); GPR_TIMER_END("tcp_handle_write.cb", 0); @@ -425,8 +430,12 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, if (!tcp_flush(tcp, &error)) { TCP_REF(tcp, "write"); tcp->write_cb = cb; + gpr_log(GPR_DEBUG, "write: delayed"); grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { + const char *str = grpc_error_string(error); + gpr_log(GPR_DEBUG, "write: %s", str); + grpc_error_free_string(str); grpc_exec_ctx_sched(exec_ctx, cb, error, NULL); } diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index b6f4b5e427..964333c57b 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -446,7 +446,12 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand, grpc_channel_get_channel_stack(chand->channel), 0), op); - GRPC_LOG_IF_ERROR("disconnecting client", error); + if (error != GRPC_ERROR_NONE) { + const char *msg = grpc_error_string(error); + gpr_log(GPR_INFO, "Disconnected client: %s", msg); + grpc_error_free_string(msg); + } + GRPC_ERROR_UNREF(error); } static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) { -- cgit v1.2.3 From c3df7b4924227d60589e5b1fc3d1f809815e88c2 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 18 Jul 2016 15:51:26 -0700 Subject: Get traces around everything --- src/core/lib/iomgr/combiner.c | 53 ++++++++++++++++++++++++------------------ src/core/lib/iomgr/combiner.h | 2 ++ src/core/lib/iomgr/error.c | 2 +- src/core/lib/iomgr/tcp_posix.c | 24 ++++++++++++------- src/core/lib/surface/init.c | 2 ++ 5 files changed, 52 insertions(+), 31 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index c3c32cb8a3..eb476c0572 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -43,10 +43,12 @@ int grpc_combiner_trace = 0; -#define COMBINER_TRACE(fn) \ - if (grpc_combiner_trace) { \ - fn \ - } +#define GRPC_COMBINER_TRACE(fn) \ + do { \ + if (grpc_combiner_trace) { \ + fn; \ + } \ + } while (0) struct grpc_combiner { grpc_workqueue *optional_workqueue; @@ -67,12 +69,12 @@ grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { gpr_mpscq_init(&lock->queue); lock->take_async_break_before_final_list = false; grpc_closure_list_init(&lock->final_list); - gpr_log(GPR_DEBUG, "C:%p create", lock); + GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p create", lock)); return lock; } static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { - gpr_log(GPR_DEBUG, "C:%p really_destroy", lock); + GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p really_destroy", lock)); GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); gpr_mpscq_destroy(&lock->queue); GRPC_WORKQUEUE_UNREF(exec_ctx, lock->optional_workqueue, "combiner"); @@ -81,8 +83,8 @@ static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -1); - gpr_log(GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, - old_state); + GRPC_COMBINER_TRACE(gpr_log( + GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state)); if (old_state == 1) { really_destroy(exec_ctx, lock); } @@ -95,7 +97,8 @@ static void continue_finishing_mainline(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { GPR_TIMER_BEGIN("combiner.continue_executing_mainline", 0); grpc_combiner *lock = arg; - gpr_log(GPR_DEBUG, "C:%p continue_finishing_mainline", lock); + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, "C:%p continue_finishing_mainline", lock)); GPR_ASSERT(exec_ctx->active_combiner == NULL); exec_ctx->active_combiner = lock; if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); @@ -112,7 +115,8 @@ static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { lock->take_async_break_before_final_list = false; int loops = 0; while (c != NULL) { - gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c); + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c)); grpc_closure *next = c->next_data.next; grpc_error *error = c->error; c->cb(exec_ctx, c->cb_arg, error); @@ -127,7 +131,8 @@ static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { GPR_TIMER_BEGIN("combiner.continue_executing_final", 0); grpc_combiner *lock = arg; - gpr_log(GPR_DEBUG, "C:%p continue_executing_final", lock); + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, "C:%p continue_executing_final", lock)); GPR_ASSERT(exec_ctx->active_combiner == NULL); exec_ctx->active_combiner = lock; // quick peek to see if new things have turned up on the queue: if so, go back @@ -146,9 +151,10 @@ static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { GPR_TIMER_BEGIN("combiner.start_execute_final", 0); GPR_ASSERT(exec_ctx->active_combiner == lock); - gpr_log(GPR_DEBUG, - "C:%p start_execute_final take_async_break_before_final_list=%d", - lock, lock->take_async_break_before_final_list); + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, + "C:%p start_execute_final take_async_break_before_final_list=%d", + lock, lock->take_async_break_before_final_list)); if (lock->take_async_break_before_final_list) { grpc_closure_init(&lock->continue_finishing, continue_executing_final, lock); @@ -166,7 +172,8 @@ static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { GPR_TIMER_BEGIN("combiner.maybe_finish_one", 0); gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); - gpr_log(GPR_DEBUG, "C:%p maybe_finish_one n=%p", lock, n); + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, "C:%p maybe_finish_one n=%p", lock, n)); GPR_ASSERT(exec_ctx->active_combiner == lock); if (n == NULL) { // queue is in an inconsistant state: use this as a cue that we should @@ -193,9 +200,9 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { do { executor = maybe_finish_one; gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -2); - gpr_log(GPR_DEBUG, "C:%p finish[%d] old_state=%" PRIdPTR " cl=[%p,%p]", - lock, loops, old_state, lock->final_list.head, - lock->final_list.tail); + GRPC_COMBINER_TRACE(gpr_log( + GPR_DEBUG, "C:%p finish[%d] old_state=%" PRIdPTR " cl=[%p,%p]", lock, + loops, old_state, lock->final_list.head, lock->final_list.tail)); switch (old_state) { case 5: // we're down to one queued item: if it's the final list we case 4: // should do that @@ -223,7 +230,8 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *cl, grpc_error *error) { - gpr_log(GPR_DEBUG, "C:%p grpc_combiner_execute c=%p", lock, cl); + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, "C:%p grpc_combiner_execute c=%p", lock, cl)); GPR_TIMER_BEGIN("combiner.execute", 0); gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); GPR_ASSERT(last & 1); // ensure lock has not been destroyed @@ -252,9 +260,10 @@ static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error, bool force_async_break) { - gpr_log(GPR_DEBUG, - "C:%p grpc_combiner_execute_finally c=%p force_async_break=%d; ac=%p", - lock, closure, force_async_break, exec_ctx->active_combiner); + GRPC_COMBINER_TRACE(gpr_log( + GPR_DEBUG, + "C:%p grpc_combiner_execute_finally c=%p force_async_break=%d; ac=%p", + lock, closure, force_async_break, exec_ctx->active_combiner)); GPR_TIMER_BEGIN("combiner.execute_finally", 0); if (exec_ctx->active_combiner != lock) { GPR_TIMER_MARK("slowpath", 0); diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index 5b94d5bd99..3eb9f34638 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -64,4 +64,6 @@ void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, bool hint_async_break); void grpc_combiner_force_async_finally(grpc_combiner *lock); +extern int grpc_combiner_trace; + #endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c index 149c55663c..e366961936 100644 --- a/src/core/lib/iomgr/error.c +++ b/src/core/lib/iomgr/error.c @@ -332,7 +332,7 @@ grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) { return new; } -static const char *no_error_string = "null"; +static const char *no_error_string = "\"No Error\""; static const char *oom_error_string = "\"Out of memory\""; static const char *cancelled_error_string = "\"Cancelled\""; diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c index bf6e9b16b3..fa4b72acbb 100644 --- a/src/core/lib/iomgr/tcp_posix.c +++ b/src/core/lib/iomgr/tcp_posix.c @@ -379,14 +379,18 @@ static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, } if (!tcp_flush(tcp, &error)) { - gpr_log(GPR_DEBUG, "write: delayed"); + if (grpc_tcp_trace) { + gpr_log(GPR_DEBUG, "write: delayed"); + } grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { cb = tcp->write_cb; tcp->write_cb = NULL; - const char *str = grpc_error_string(error); - gpr_log(GPR_DEBUG, "write: %s", str); - grpc_error_free_string(str); + if (grpc_tcp_trace) { + const char *str = grpc_error_string(error); + gpr_log(GPR_DEBUG, "write: %s", str); + grpc_error_free_string(str); + } GPR_TIMER_BEGIN("tcp_handle_write.cb", 0); cb->cb(exec_ctx, cb->cb_arg, error); @@ -430,12 +434,16 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, if (!tcp_flush(tcp, &error)) { TCP_REF(tcp, "write"); tcp->write_cb = cb; - gpr_log(GPR_DEBUG, "write: delayed"); + if (grpc_tcp_trace) { + gpr_log(GPR_DEBUG, "write: delayed"); + } grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { - const char *str = grpc_error_string(error); - gpr_log(GPR_DEBUG, "write: %s", str); - grpc_error_free_string(str); + if (grpc_tcp_trace) { + const char *str = grpc_error_string(error); + gpr_log(GPR_DEBUG, "write: %s", str); + grpc_error_free_string(str); + } grpc_exec_ctx_sched(exec_ctx, cb, error, NULL); } diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index 5397913a21..edda0c85fa 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -47,6 +47,7 @@ #include "src/core/lib/channel/http_server_filter.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/http/parser.h" +#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/profiling/timers.h" @@ -165,6 +166,7 @@ void grpc_init(void) { grpc_register_tracer("http1", &grpc_http1_trace); grpc_register_tracer("compression", &grpc_compression_trace); grpc_register_tracer("queue_pluck", &grpc_cq_pluck_trace); + grpc_register_tracer("combiner", &grpc_combiner_trace); // Default pluck trace to 1 grpc_cq_pluck_trace = 1; grpc_register_tracer("queue_timeout", &grpc_cq_event_timeout_trace); -- cgit v1.2.3 From 2da58cf638805764e0ce4d2dfe484604c0cda343 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 19 Jul 2016 17:09:22 -0700 Subject: Force queuing to workqueue instead of relying on exec_ctx --- src/core/lib/iomgr/combiner.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index eb476c0572..25b2ec3d4c 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -155,11 +155,12 @@ static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { gpr_log(GPR_DEBUG, "C:%p start_execute_final take_async_break_before_final_list=%d", lock, lock->take_async_break_before_final_list)); - if (lock->take_async_break_before_final_list) { + if (lock->optional_workqueue != NULL && + lock->take_async_break_before_final_list) { grpc_closure_init(&lock->continue_finishing, continue_executing_final, lock); - grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, - GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); + grpc_workqueue_enqueue(exec_ctx, lock->optional_workqueue, + &lock->continue_finishing, GRPC_ERROR_NONE); GPR_TIMER_END("combiner.start_execute_final", 0); return false; } else { -- cgit v1.2.3 From f7250197a733141be58bab3453b0ac1a2d278e62 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 22 Jul 2016 08:06:09 -0700 Subject: Add support for CONNECT to httpcli code and flesh out handshaker implementation. --- .../ext/client_config/http_connect_handshaker.c | 78 +++++++++++++++++----- src/core/lib/http/format_request.c | 22 ++++-- src/core/lib/http/format_request.h | 2 + src/core/lib/http/httpcli.h | 6 +- src/core/lib/http/parser.c | 8 +-- 5 files changed, 85 insertions(+), 31 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/http_connect_handshaker.c b/src/core/ext/client_config/http_connect_handshaker.c index 2b71ca60f6..c649796f42 100644 --- a/src/core/ext/client_config/http_connect_handshaker.c +++ b/src/core/ext/client_config/http_connect_handshaker.c @@ -36,6 +36,8 @@ #include #include +#include "src/core/lib/http/format_request.h" +#include "src/core/lib/http/parser.h" #include "src/core/ext/client_config/http_connect_handshaker.h" typedef struct http_connect_handshaker { @@ -53,35 +55,65 @@ typedef struct http_connect_handshaker { grpc_closure request_done_closure; grpc_slice_buffer response_buffer; grpc_closure response_read_closure; + grpc_http_parser http_parser; + grpc_http_response http_response; } http_connect_handshaker; -// Callback invoked for reading HTTP CONNECT response. -static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, - grpc_error* error) { - http_connect_handshaker* h = arg; -// FIXME: process response; on failure, figure out how to abort - - // Invoke handshake-done callback. - h->cb(exec_ctx, h->endpoint, h->args, h->user_data); -} - // Callback invoked when finished writing HTTP CONNECT request. static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { http_connect_handshaker* h = arg; // Read HTTP CONNECT response. - gpr_slice_buffer_init(&h->response_buffer); - grpc_closure_init(&h->response_read_closure, on_read_done, h); grpc_endpoint_read(exec_ctx, h->endpoint, &h->response_buffer, &h->response_read_closure); } +// Callback invoked for reading HTTP CONNECT response. +static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + http_connect_handshaker* h = arg; + if (error == GRPC_ERROR_NONE) { + for (size_t i = 0; i < h->response_buffer.count; ++i) { + if (GPR_SLICE_LENGTH(h->response_buffer.slices[i]) > 0) { + error = grpc_http_parser_parse( + &h->http_parser, h->response_buffer.slices[i]); + if (error != GRPC_ERROR_NONE) + goto done; + } + } + // If we're not done reading the response, read more data. + // TODO(roth): In practice, I suspect that the response to a CONNECT + // request will never include a body, in which case this check is + // sufficient. However, the language of RFC-2817 doesn't explicitly + // forbid the response from including a body. If there is a body, + // it's possible that we might have parsed part but not all of the + // body, in which case this check will cause us to fail to parse the + // remainder of the body. If that ever becomes an issue, we may + // need to fix the HTTP parser to understand when the body is + // complete (e.g., handling chunked transfer encoding or looking + // at the Content-Length: header). + if (h->http_parser->state != GRPC_HTTP_BODY) { + grpc_endpoint_read(exec_ctx, h->endpoint, &h->response_buffer, + &h->response_read_closure); + return; + } + } + done: + // Invoke handshake-done callback. +// FIXME: pass error to callback + h->cb(exec_ctx, h->endpoint, h->args, h->user_data); +} + // // Public handshaker methods // static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker) { + grpc_slice_buffer_destroy(&handshaker->request_buffer); + grpc_slice_buffer_destroy(&handshaker->response_buffer); + grpc_http_parser_destroy(&handshaker->http_parser); + grpc_http_response_destroy(&handshaker->http_response); gpr_free(handshaker); } @@ -100,14 +132,24 @@ static void http_connect_handshaker_do_handshake( h->args = args; h->cb = cb; h->user_data = user_data; - // Send HTTP CONNECT request. + // Initialize fields. gpr_slice_buffer_init(&h->request_buffer); - gpr_slice_buffer_add(&h->request_buffer, "HTTP CONNECT "); -// FIXME: get server name from somewhere... - gpr_slice_buffer_add(&h->request_buffer, WHEE); -// FIXME: add headers as needed? - gpr_slice_buffer_add(&h->request_buffer, "\n\n"); grpc_closure_init(&h->request_done_closure, on_write_done, h); + gpr_slice_buffer_init(&h->response_buffer); + grpc_closure_init(&h->response_read_closure, on_read_done, h); + grpc_http_parser_init(&h->http_parser, GRPC_HTTP_RESPONSE, + &h->http_response); + // Send HTTP CONNECT request. + grpc_httpcli_request request; + memset(&request, 0, sizeof(request)); + // FIXME: get proxy name from somewhere... + request.host = gpr_strdup(""); + request.http.method = gpr_strdup("CONNECT"); + // FIXME: get server name from somewhere... + request.http.path = gpr_strdup(""); + request.handshaker = grpc_httpcli_plaintext; + gpr_slice request_slice = grpc_httpcli_format_connect_request(request); + gpr_slice_buffer_add(&h->request_buffer, request_slice); grpc_endpoint_write(exec_ctx, endpoint, &h->request_buffer, &h->request_done_closure); } diff --git a/src/core/lib/http/format_request.c b/src/core/lib/http/format_request.c index 9240356fea..e818b70113 100644 --- a/src/core/lib/http/format_request.c +++ b/src/core/lib/http/format_request.c @@ -44,7 +44,7 @@ #include "src/core/lib/support/string.h" static void fill_common_header(const grpc_httpcli_request *request, - gpr_strvec *buf) { + gpr_strvec *buf, bool connection_close) { size_t i; gpr_strvec_add(buf, gpr_strdup(request->http.path)); gpr_strvec_add(buf, gpr_strdup(" HTTP/1.0\r\n")); @@ -52,7 +52,8 @@ static void fill_common_header(const grpc_httpcli_request *request, gpr_strvec_add(buf, gpr_strdup("Host: ")); gpr_strvec_add(buf, gpr_strdup(request->host)); gpr_strvec_add(buf, gpr_strdup("\r\n")); - gpr_strvec_add(buf, gpr_strdup("Connection: close\r\n")); + if (connection_close) + gpr_strvec_add(buf, gpr_strdup("Connection: close\r\n")); gpr_strvec_add(buf, gpr_strdup("User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n")); /* user supplied headers */ @@ -71,7 +72,7 @@ gpr_slice grpc_httpcli_format_get_request(const grpc_httpcli_request *request) { gpr_strvec_init(&out); gpr_strvec_add(&out, gpr_strdup("GET ")); - fill_common_header(request, &out); + fill_common_header(request, &out, true); gpr_strvec_add(&out, gpr_strdup("\r\n")); flat = gpr_strvec_flatten(&out, &flat_len); @@ -91,7 +92,7 @@ gpr_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request, gpr_strvec_init(&out); gpr_strvec_add(&out, gpr_strdup("POST ")); - fill_common_header(request, &out); + fill_common_header(request, &out, true); if (body_bytes) { uint8_t has_content_type = 0; for (i = 0; i < request->http.hdr_count; i++) { @@ -118,3 +119,16 @@ gpr_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request, return gpr_slice_new(tmp, out_len, gpr_free); } + +gpr_slice grpc_httpcli_format_connect_request( + const grpc_httpcli_request *request) { + gpr_strvec out; + gpr_strvec_init(&out); + gpr_strvec_add(&out, gpr_strdup("CONNECT ")); + fill_common_header(request, &out, false); + gpr_strvec_add(&out, gpr_strdup("\r\n")); + size_t flat_len; + char *flat = gpr_strvec_flatten(&out, &flat_len); + gpr_strvec_destroy(&out); + return gpr_slice_new(flat, flat_len, gpr_free); +} diff --git a/src/core/lib/http/format_request.h b/src/core/lib/http/format_request.h index 1543efe4b0..7abd55f2f7 100644 --- a/src/core/lib/http/format_request.h +++ b/src/core/lib/http/format_request.h @@ -41,5 +41,7 @@ gpr_slice grpc_httpcli_format_get_request(const grpc_httpcli_request *request); gpr_slice grpc_httpcli_format_post_request(const grpc_httpcli_request *request, const char *body_bytes, size_t body_size); +gpr_slice grpc_httpcli_format_connect_request( + const grpc_httpcli_request *request); #endif /* GRPC_CORE_LIB_HTTP_FORMAT_REQUEST_H */ diff --git a/src/core/lib/http/httpcli.h b/src/core/lib/http/httpcli.h index 662e176f4c..320c0f86c6 100644 --- a/src/core/lib/http/httpcli.h +++ b/src/core/lib/http/httpcli.h @@ -93,8 +93,7 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context *context); 'request' contains request parameters - these are caller owned and can be destroyed once the call returns 'deadline' contains a deadline for the request (or gpr_inf_future) - 'on_response' is a callback to report results to (and 'user_data' is a user - supplied pointer to pass to said call) */ + 'on_response' is a callback to report results to */ void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context, grpc_polling_entity *pollent, const grpc_httpcli_request *request, @@ -113,8 +112,7 @@ void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context, 'deadline' contains a deadline for the request (or gpr_inf_future) 'em' points to a caller owned event manager that must be alive for the lifetime of the request - 'on_response' is a callback to report results to (and 'user_data' is a user - supplied pointer to pass to said call) + 'on_response' is a callback to report results to Does not support ?var1=val1&var2=val2 in the path. */ void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context, grpc_polling_entity *pollent, diff --git a/src/core/lib/http/parser.c b/src/core/lib/http/parser.c index 92ed08ae51..d3bac5b876 100644 --- a/src/core/lib/http/parser.c +++ b/src/core/lib/http/parser.c @@ -282,20 +282,18 @@ static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte) { if (grpc_http1_trace) gpr_log(GPR_ERROR, "HTTP client max line length (%d) exceeded", GRPC_HTTP_PARSER_MAX_HEADER_LENGTH); - return 0; + return GRPC_ERROR_NONE; } parser->cur_line[parser->cur_line_length] = byte; parser->cur_line_length++; if (check_line(parser)) { return finish_line(parser); - } else { - return GRPC_ERROR_NONE; } - GPR_UNREACHABLE_CODE(return 0); + return GRPC_ERROR_NONE; case GRPC_HTTP_BODY: return addbyte_body(parser, byte); } - GPR_UNREACHABLE_CODE(return 0); + GPR_UNREACHABLE_CODE(return GRPC_ERROR_NONE); } void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type, -- cgit v1.2.3 From 3cfc5a7b1d8c428d50c9be537b47ad543bff3a40 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 27 Jul 2016 07:48:39 -0700 Subject: Made significant progress on the test, but not working yet. --- Makefile | 2 + build.yaml | 2 + .../ext/client_config/http_connect_handshaker.c | 1 + src/core/lib/iomgr/exec_ctx.h | 12 +- test/core/end2end/fixtures/h2_http_proxy.c | 21 +- test/core/end2end/fixtures/http_proxy.c | 351 +++++++++++++++++++++ test/core/end2end/fixtures/http_proxy.h | 41 +++ tools/run_tests/sources_and_headers.json | 3 + .../vcxproj/grpc_test_util/grpc_test_util.vcxproj | 3 + .../grpc_test_util/grpc_test_util.vcxproj.filters | 6 + .../grpc_test_util_unsecure.vcxproj | 3 + .../grpc_test_util_unsecure.vcxproj.filters | 6 + 12 files changed, 436 insertions(+), 15 deletions(-) create mode 100644 test/core/end2end/fixtures/http_proxy.c create mode 100644 test/core/end2end/fixtures/http_proxy.h (limited to 'src/core/lib') diff --git a/Makefile b/Makefile index 8e89ece272..76da2ca57b 100644 --- a/Makefile +++ b/Makefile @@ -3051,6 +3051,7 @@ LIBGRPC_TEST_UTIL_SRC = \ test/core/end2end/data/test_root_cert.c \ test/core/security/oauth2_utils.c \ test/core/end2end/cq_verifier.c \ + test/core/end2end/fixtures/http_proxy.c \ test/core/end2end/fixtures/proxy.c \ test/core/iomgr/endpoint_tests.c \ test/core/util/grpc_profiler.c \ @@ -3101,6 +3102,7 @@ endif LIBGRPC_TEST_UTIL_UNSECURE_SRC = \ test/core/end2end/cq_verifier.c \ + test/core/end2end/fixtures/http_proxy.c \ test/core/end2end/fixtures/proxy.c \ test/core/iomgr/endpoint_tests.c \ test/core/util/grpc_profiler.c \ diff --git a/build.yaml b/build.yaml index 585d4de978..1cb428de00 100644 --- a/build.yaml +++ b/build.yaml @@ -484,6 +484,7 @@ filegroups: build: test headers: - test/core/end2end/cq_verifier.h + - test/core/end2end/fixtures/http_proxy.h - test/core/end2end/fixtures/proxy.h - test/core/iomgr/endpoint_tests.h - test/core/util/grpc_profiler.h @@ -496,6 +497,7 @@ filegroups: - test/core/util/slice_splitter.h src: - test/core/end2end/cq_verifier.c + - test/core/end2end/fixtures/http_proxy.c - test/core/end2end/fixtures/proxy.c - test/core/iomgr/endpoint_tests.c - test/core/util/grpc_profiler.c diff --git a/src/core/ext/client_config/http_connect_handshaker.c b/src/core/ext/client_config/http_connect_handshaker.c index a5cb6d1047..25246ddfd1 100644 --- a/src/core/ext/client_config/http_connect_handshaker.c +++ b/src/core/ext/client_config/http_connect_handshaker.c @@ -103,6 +103,7 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, // complete (e.g., handling chunked transfer encoding or looking // at the Content-Length: header). if (h->http_parser.state != GRPC_HTTP_BODY) { + gpr_slice_buffer_reset_and_unref(&h->response_buffer); grpc_endpoint_read(exec_ctx, h->endpoint, &h->response_buffer, &h->response_read_closure); return; diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index 917f332f03..65584ea0de 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -43,7 +43,6 @@ struct grpc_workqueue; typedef struct grpc_workqueue grpc_workqueue; -#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER /** Execution context. * A bag of data that collects information along a callstack. * Generally created at public API entry points, and passed down as @@ -58,12 +57,13 @@ typedef struct grpc_workqueue grpc_workqueue; * should actively try to finish up and get this thread back to its owner * * CONVENTIONS: - * Instance of this must ALWAYS be constructed on the stack, never - * heap allocated. Instances and pointers to them must always be called - * exec_ctx. Instances are always passed as the first argument - * to a function that takes it, and always as a pointer (grpc_exec_ctx - * is never copied). + * - Instance of this must ALWAYS be constructed on the stack, never + * heap allocated. + * - Instances and pointers to them must always be called exec_ctx. + * - Instances are always passed as the first argument to a function that + * takes it, and always as a pointer (grpc_exec_ctx is never copied). */ +#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER struct grpc_exec_ctx { grpc_closure_list closure_list; bool cached_ready_to_finish; diff --git a/test/core/end2end/fixtures/h2_http_proxy.c b/test/core/end2end/fixtures/h2_http_proxy.c index 4578d753f6..d84f0b8cb9 100644 --- a/test/core/end2end/fixtures/h2_http_proxy.c +++ b/test/core/end2end/fixtures/h2_http_proxy.c @@ -48,21 +48,24 @@ #include "src/core/lib/channel/http_server_filter.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/server.h" +#include "test/core/end2end/fixtures/http_proxy.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" typedef struct fullstack_fixture_data { - char *localaddr; + char *server_addr; + grpc_end2end_http_proxy *proxy; } fullstack_fixture_data; static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( grpc_channel_args *client_args, grpc_channel_args *server_args) { grpc_end2end_test_fixture f; - int port = grpc_pick_unused_port_or_die(); - fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); memset(&f, 0, sizeof(f)); - gpr_join_host_port(&ffd->localaddr, "localhost", port); + fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); + const int server_port = grpc_pick_unused_port_or_die(); + gpr_join_host_port(&ffd->server_addr, "localhost", server_port); + ffd->proxy = grpc_end2end_http_proxy_create(); f.fixture_data = ffd; f.cq = grpc_completion_queue_create(NULL); @@ -73,10 +76,9 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { fullstack_fixture_data *ffd = f->fixture_data; -// FIXME: this requires a separate proxy running at localhost:9999. need to -// change this test to provide its own proxy. char *target_uri; - gpr_asprintf(&target_uri, "%s?http_proxy=127.0.0.1:9999", ffd->localaddr); + gpr_asprintf(&target_uri, "%s?http_proxy=%s", ffd->server_addr, + grpc_end2end_http_proxy_get_proxy_name(ffd->proxy)); gpr_log(GPR_INFO, "target_uri: %s", target_uri); f->client = grpc_insecure_channel_create(target_uri, client_args, NULL); gpr_free(target_uri); @@ -91,13 +93,14 @@ void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f, } f->server = grpc_server_create(server_args, NULL); grpc_server_register_completion_queue(f->server, f->cq, NULL); - GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->localaddr)); + GPR_ASSERT(grpc_server_add_insecure_http2_port(f->server, ffd->server_addr)); grpc_server_start(f->server); } void chttp2_tear_down_fullstack(grpc_end2end_test_fixture *f) { fullstack_fixture_data *ffd = f->fixture_data; - gpr_free(ffd->localaddr); + gpr_free(ffd->server_addr); + grpc_end2end_http_proxy_destroy(ffd->proxy); gpr_free(ffd); } diff --git a/test/core/end2end/fixtures/http_proxy.c b/test/core/end2end/fixtures/http_proxy.c new file mode 100644 index 0000000000..a8d68f0249 --- /dev/null +++ b/test/core/end2end/fixtures/http_proxy.c @@ -0,0 +1,351 @@ +/* + * + * 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 "test/core/end2end/fixtures/http_proxy.h" + +#include + +#include +#include +#include +#include +#include +#include +//#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/http/parser.h" +#include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/pollset.h" +#include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/tcp_client.h" +#include "src/core/lib/iomgr/tcp_server.h" +#include "test/core/util/port.h" + +// +// Connection handling +// + +typedef struct connection_data { + grpc_endpoint* client_endpoint; + grpc_endpoint* server_endpoint; + + grpc_pollset_set* pollset_set; + + grpc_closure on_read_request_done; + grpc_closure on_server_connect_done; + grpc_closure on_write_response_done; + grpc_closure on_client_read_done; + grpc_closure on_client_write_done; + grpc_closure on_server_read_done; + grpc_closure on_server_write_done; + + gpr_slice_buffer client_read_buffer; + gpr_slice_buffer client_write_buffer; + gpr_slice_buffer server_read_buffer; + gpr_slice_buffer server_write_buffer; + + grpc_http_parser http_parser; + grpc_http_request http_request; +} connection_data; + +static void connection_data_destroy(grpc_exec_ctx* exec_ctx, + connection_data* cd) { + grpc_endpoint_destroy(exec_ctx, cd->client_endpoint); + if (cd->server_endpoint != NULL) + grpc_endpoint_destroy(exec_ctx, cd->server_endpoint); + grpc_pollset_set_destroy(cd->pollset_set); + gpr_slice_buffer_destroy(&cd->client_read_buffer); + gpr_slice_buffer_destroy(&cd->client_write_buffer); + gpr_slice_buffer_destroy(&cd->server_read_buffer); + gpr_slice_buffer_destroy(&cd->server_write_buffer); + grpc_http_parser_destroy(&cd->http_parser); + grpc_http_request_destroy(&cd->http_request); + gpr_free(cd); +} + +static void connection_data_failed(grpc_exec_ctx* exec_ctx, + connection_data* cd, const char* prefix, + grpc_error* error) { + const char* msg = grpc_error_string(error); + gpr_log(GPR_ERROR, "%s: %s", prefix, msg); + grpc_error_free_string(msg); + GRPC_ERROR_UNREF(error); + grpc_endpoint_shutdown(exec_ctx, cd->client_endpoint); + if (cd->server_endpoint != NULL) + grpc_endpoint_shutdown(exec_ctx, cd->server_endpoint); + connection_data_destroy(exec_ctx, cd); +} + +static void on_client_write_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + connection_data* cd = arg; + if (error != GRPC_ERROR_NONE) + connection_data_failed(exec_ctx, cd, "HTTP proxy client write", error); +} + +static void on_server_write_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + connection_data* cd = arg; + if (error != GRPC_ERROR_NONE) + connection_data_failed(exec_ctx, cd, "HTTP proxy server write", error); +} + +static void on_client_read_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + connection_data* cd = arg; + if (error != GRPC_ERROR_NONE) { + connection_data_failed(exec_ctx, cd, "HTTP proxy client read", error); + return; + } + gpr_slice_buffer_move_into(&cd->client_read_buffer, &cd->server_write_buffer); + grpc_endpoint_write(exec_ctx, cd->server_endpoint, &cd->server_write_buffer, + &cd->on_server_write_done); +} + +static void on_server_read_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + connection_data* cd = arg; + if (error != GRPC_ERROR_NONE) { + connection_data_failed(exec_ctx, cd, "HTTP proxy server read", error); + return; + } + gpr_slice_buffer_move_into(&cd->server_read_buffer, &cd->client_write_buffer); + grpc_endpoint_write(exec_ctx, cd->client_endpoint, &cd->client_write_buffer, + &cd->on_client_write_done); +} + +static void on_write_response_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + connection_data* cd = arg; + if (error != GRPC_ERROR_NONE) { + connection_data_failed(exec_ctx, cd, "HTTP proxy write response", error); + return; + } + // Set up proxying. + grpc_endpoint_read(exec_ctx, cd->client_endpoint, &cd->client_read_buffer, + &cd->on_client_read_done); + grpc_endpoint_read(exec_ctx, cd->server_endpoint, &cd->server_read_buffer, + &cd->on_server_read_done); +} + +static void on_server_connect_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + connection_data* cd = arg; + if (error != GRPC_ERROR_NONE) { + connection_data_failed(exec_ctx, cd, "HTTP proxy server connect", error); + return; + } + // We've established a connection, so send back a 200 response code to + // the client. + gpr_slice slice = gpr_slice_from_copied_string("200 connected\r\n"); + gpr_slice_buffer_reset_and_unref(&cd->client_write_buffer); + gpr_slice_buffer_add(&cd->client_write_buffer, slice); + grpc_endpoint_write(exec_ctx, cd->client_endpoint, &cd->client_write_buffer, + &cd->on_write_response_done); +} + +static void on_read_request_done(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + connection_data* cd = arg; + if (error != GRPC_ERROR_NONE) { + connection_data_failed(exec_ctx, cd, "HTTP proxy read request", error); + return; + } + // Read request and feed it to the parser. + for (size_t i = 0; i < cd->client_read_buffer.count; ++i) { + if (GPR_SLICE_LENGTH(cd->client_read_buffer.slices[i]) > 0) { + error = grpc_http_parser_parse( + &cd->http_parser, cd->client_read_buffer.slices[i]); + if (error != GRPC_ERROR_NONE) { + connection_data_failed(exec_ctx, cd, "HTTP proxy request parse", + error); + return; + } + } + } + gpr_slice_buffer_reset_and_unref(&cd->client_read_buffer); + // If we're not done reading the request, read more data. + if (cd->http_parser.state != GRPC_HTTP_BODY) { + grpc_endpoint_read(exec_ctx, cd->client_endpoint, &cd->client_read_buffer, + &cd->on_read_request_done); + return; + } + // Make sure we got a CONNECT request. + if (strcmp(cd->http_request.method, "CONNECT") != 0) { + char* msg; + gpr_asprintf(&msg, "HTTP proxy got request method %s", + cd->http_request.method); + error = GRPC_ERROR_CREATE(msg); + gpr_free(msg); + connection_data_failed(exec_ctx, cd, "HTTP proxy read request", error); + return; + } + // Resolve address. + grpc_resolved_addresses* resolved_addresses = NULL; + error = grpc_blocking_resolve_address(cd->http_request.path, "80", + &resolved_addresses); + if (error != GRPC_ERROR_NONE) { + connection_data_failed(exec_ctx, cd, "HTTP proxy DNS lookup", error); + return; + } + GPR_ASSERT(resolved_addresses->naddrs >= 1); + // Connect to requested address. + const gpr_timespec deadline = gpr_time_add( + gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(10, GPR_TIMESPAN)); + grpc_tcp_client_connect(exec_ctx, &cd->on_server_connect_done, + &cd->server_endpoint, cd->pollset_set, + (struct sockaddr*)&resolved_addresses->addrs[0].addr, + resolved_addresses->addrs[0].len, deadline); + grpc_resolved_addresses_destroy(resolved_addresses); +} + +static void on_accept(grpc_exec_ctx* exec_ctx, void* arg, + grpc_endpoint* ep, grpc_pollset* accepting_pollset, + grpc_tcp_server_acceptor* acceptor) { +// FIXME: remove +gpr_log(GPR_ERROR, "==> on_accept()"); + // Instantiate connection_data. + connection_data* cd = gpr_malloc(sizeof(*cd)); + memset(cd, 0, sizeof(*cd)); + cd->client_endpoint = ep; + cd->pollset_set = grpc_pollset_set_create(); + grpc_closure_init(&cd->on_read_request_done, on_read_request_done, cd); + grpc_closure_init(&cd->on_server_connect_done, on_server_connect_done, cd); + grpc_closure_init(&cd->on_write_response_done, on_write_response_done, cd); + grpc_closure_init(&cd->on_client_read_done, on_client_read_done, cd); + grpc_closure_init(&cd->on_client_write_done, on_client_write_done, cd); + grpc_closure_init(&cd->on_server_read_done, on_server_read_done, cd); + grpc_closure_init(&cd->on_server_write_done, on_server_write_done, cd); + gpr_slice_buffer_init(&cd->client_read_buffer); + gpr_slice_buffer_init(&cd->client_write_buffer); + gpr_slice_buffer_init(&cd->server_read_buffer); + gpr_slice_buffer_init(&cd->server_write_buffer); + grpc_http_parser_init(&cd->http_parser, GRPC_HTTP_REQUEST, + &cd->http_request); + grpc_endpoint_read(exec_ctx, cd->client_endpoint, &cd->client_read_buffer, + &cd->on_read_request_done); +} + +// +// Proxy class +// + +struct grpc_end2end_http_proxy { + char* proxy_name; +// gpr_thd_id thd; + grpc_tcp_server* server; + grpc_channel_args* channel_args; + gpr_mu* mu; + grpc_pollset* pollset; +}; + +#if 0 +static void thread_main(void *arg) { + //grpc_end2end_http_proxy *proxy = arg; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + while (true) { + grpc_exec_ctx_flush(&exec_ctx); + } +} +#endif + +grpc_end2end_http_proxy* grpc_end2end_http_proxy_create() { + grpc_end2end_http_proxy* proxy = gpr_malloc(sizeof(*proxy)); + memset(proxy, 0, sizeof(*proxy)); + // Construct proxy address. + const int proxy_port = grpc_pick_unused_port_or_die(); + gpr_join_host_port(&proxy->proxy_name, "localhost", proxy_port); + gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name); +// FIXME: remove +gpr_log(GPR_ERROR, "Proxy address: %s", proxy->proxy_name); + // Create TCP server. + proxy->channel_args = grpc_channel_args_copy(NULL); + grpc_error* error = grpc_tcp_server_create( + NULL, proxy->channel_args, &proxy->server); + GPR_ASSERT(error == GRPC_ERROR_NONE); + // Bind to port. + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + grpc_sockaddr_set_port((struct sockaddr*)&addr, proxy_port); + int port; + error = grpc_tcp_server_add_port( + proxy->server, (struct sockaddr*)&addr, sizeof(addr), &port); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(port == proxy_port); + // Start server. + proxy->pollset = gpr_malloc(grpc_pollset_size()); + grpc_pollset_init(proxy->pollset, &proxy->mu); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_tcp_server_start(&exec_ctx, proxy->server, &proxy->pollset, 1, + on_accept, NULL); + grpc_exec_ctx_finish(&exec_ctx); +#if 0 + // Start proxy thread. + gpr_thd_options opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt)); +#endif + return proxy; +} + +static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, + grpc_error *error) { + grpc_pollset_destroy(p); +} + +void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_tcp_server_shutdown_listeners(&exec_ctx, proxy->server); + grpc_tcp_server_unref(&exec_ctx, proxy->server); +// gpr_thd_join(proxy->thd); + gpr_free(proxy->proxy_name); + grpc_channel_args_destroy(proxy->channel_args); + grpc_closure destroyed; + grpc_closure_init(&destroyed, destroy_pollset, &proxy->pollset); + grpc_pollset_shutdown(&exec_ctx, proxy->pollset, &destroyed); + gpr_free(proxy); + grpc_exec_ctx_finish(&exec_ctx); +} + +const char *grpc_end2end_http_proxy_get_proxy_name( + grpc_end2end_http_proxy *proxy) { + return proxy->proxy_name; +} diff --git a/test/core/end2end/fixtures/http_proxy.h b/test/core/end2end/fixtures/http_proxy.h new file mode 100644 index 0000000000..7af2ea92d0 --- /dev/null +++ b/test/core/end2end/fixtures/http_proxy.h @@ -0,0 +1,41 @@ +/* + * + * 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. + * + */ + +typedef struct grpc_end2end_http_proxy grpc_end2end_http_proxy; + +grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(); + +void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy); + +const char *grpc_end2end_http_proxy_get_proxy_name( + grpc_end2end_http_proxy *proxy); diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index d09aa418d7..0bc1ab7815 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -6282,6 +6282,7 @@ ], "headers": [ "test/core/end2end/cq_verifier.h", + "test/core/end2end/fixtures/http_proxy.h", "test/core/end2end/fixtures/proxy.h", "test/core/iomgr/endpoint_tests.h", "test/core/util/grpc_profiler.h", @@ -6298,6 +6299,8 @@ "src": [ "test/core/end2end/cq_verifier.c", "test/core/end2end/cq_verifier.h", + "test/core/end2end/fixtures/http_proxy.c", + "test/core/end2end/fixtures/http_proxy.h", "test/core/end2end/fixtures/proxy.c", "test/core/end2end/fixtures/proxy.h", "test/core/iomgr/endpoint_tests.c", diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index f0a8f7b6b9..6f1a3f3490 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -150,6 +150,7 @@ + @@ -174,6 +175,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index a1d31eb54e..45d7677380 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -19,6 +19,9 @@ test\core\end2end + + test\core\end2end\fixtures + test\core\end2end\fixtures @@ -63,6 +66,9 @@ test\core\end2end + + test\core\end2end\fixtures + test\core\end2end\fixtures diff --git a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj index 33860c48a4..04d1e584b5 100644 --- a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj @@ -148,6 +148,7 @@ + @@ -162,6 +163,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters index 372bb2af67..0f7072aa61 100644 --- a/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util_unsecure/grpc_test_util_unsecure.vcxproj.filters @@ -4,6 +4,9 @@ test\core\end2end + + test\core\end2end\fixtures + test\core\end2end\fixtures @@ -42,6 +45,9 @@ test\core\end2end + + test\core\end2end\fixtures + test\core\end2end\fixtures -- cgit v1.2.3 From 6b11462da1b0a4607d0ea679d2cb42d8d851f55d Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Wed, 27 Jul 2016 14:49:53 -0700 Subject: removed codegen/alloc.h --- BUILD | 9 --- Makefile | 8 --- build.yaml | 1 - gRPC-Core.podspec | 2 - grpc.def | 14 ++-- grpc.gemspec | 2 - include/grpc++/impl/codegen/call.h | 1 - include/grpc/impl/codegen/alloc.h | 74 ---------------------- include/grpc/support/alloc.h | 37 ++++++++++- package.xml | 2 - src/core/lib/channel/handshaker.c | 2 +- src/cpp/common/core_codegen.cc | 2 +- test/core/surface/public_headers_must_be_c89.c | 1 - test/cpp/interop/client.cc | 1 + test/cpp/interop/interop_client.cc | 1 + tools/doxygen/Doxyfile.c++ | 1 - tools/doxygen/Doxyfile.c++.internal | 1 - tools/doxygen/Doxyfile.core | 2 - tools/doxygen/Doxyfile.core.internal | 2 - tools/run_tests/sources_and_headers.json | 2 - vsprojects/vcxproj/gpr/gpr.vcxproj | 1 - vsprojects/vcxproj/gpr/gpr.vcxproj.filters | 3 - vsprojects/vcxproj/grpc++/grpc++.vcxproj | 1 - vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters | 3 - .../grpc++_reflection/grpc++_reflection.vcxproj | 1 - .../grpc++_reflection.vcxproj.filters | 3 - .../grpc++_test_util/grpc++_test_util.vcxproj | 1 - .../grpc++_test_util.vcxproj.filters | 3 - .../grpc++_unsecure/grpc++_unsecure.vcxproj | 1 - .../grpc++_unsecure.vcxproj.filters | 3 - vsprojects/vcxproj/grpc/grpc.vcxproj | 1 - vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 3 - .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 1 - .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 3 - .../codegen_test_full/codegen_test_full.vcxproj | 1 - .../codegen_test_full.vcxproj.filters | 3 - .../codegen_test_minimal.vcxproj | 1 - .../codegen_test_minimal.vcxproj.filters | 3 - 38 files changed, 47 insertions(+), 154 deletions(-) delete mode 100644 include/grpc/impl/codegen/alloc.h (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index 8a6d7fdc0a..82c6cb7fd0 100644 --- a/BUILD +++ b/BUILD @@ -131,7 +131,6 @@ cc_library( "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", @@ -510,7 +509,6 @@ cc_library( "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/status.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", @@ -869,7 +867,6 @@ cc_library( "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/status.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", @@ -1200,7 +1197,6 @@ cc_library( "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/status.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", @@ -1360,7 +1356,6 @@ cc_library( "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/status.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", @@ -1439,7 +1434,6 @@ cc_library( "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/status.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", @@ -1586,7 +1580,6 @@ cc_library( "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/status.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", @@ -1752,7 +1745,6 @@ objc_library( "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", @@ -1990,7 +1982,6 @@ objc_library( "include/grpc/impl/codegen/grpc_types.h", "include/grpc/impl/codegen/propagation_bits.h", "include/grpc/impl/codegen/status.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", diff --git a/Makefile b/Makefile index 8b6114bd7f..07d7de02db 100644 --- a/Makefile +++ b/Makefile @@ -2438,7 +2438,6 @@ PUBLIC_HEADERS_C += \ 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 \ @@ -2718,7 +2717,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ @@ -2968,7 +2966,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ @@ -3303,7 +3300,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ @@ -3554,7 +3550,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ @@ -3680,7 +3675,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ @@ -3907,7 +3901,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ @@ -4090,7 +4083,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ diff --git a/build.yaml b/build.yaml index 37c95ccdc0..f5ce0abe03 100644 --- a/build.yaml +++ b/build.yaml @@ -127,7 +127,6 @@ filegroups: - gpr_codegen - name: gpr_codegen public_headers: - - 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 diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 10e9d00d70..451f4e879c 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -144,7 +144,6 @@ Pod::Spec.new do |s| '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', @@ -171,7 +170,6 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/grpc_types.h', 'include/grpc/impl/codegen/propagation_bits.h', 'include/grpc/impl/codegen/status.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', diff --git a/grpc.def b/grpc.def index c2f83f577f..7f24b85a5e 100644 --- a/grpc.def +++ b/grpc.def @@ -123,13 +123,6 @@ EXPORTS grpc_server_add_secure_http2_port grpc_call_set_credentials grpc_server_credentials_set_auth_metadata_processor - gpr_malloc - gpr_free - gpr_realloc - gpr_malloc_aligned - gpr_free_aligned - gpr_set_allocation_functions - gpr_get_allocation_functions grpc_raw_byte_buffer_create grpc_raw_compressed_byte_buffer_create grpc_byte_buffer_copy @@ -218,6 +211,13 @@ EXPORTS gpr_time_similar gpr_sleep_until gpr_timespec_to_micros + gpr_malloc + gpr_free + gpr_realloc + gpr_malloc_aligned + gpr_free_aligned + gpr_set_allocation_functions + gpr_get_allocation_functions gpr_avl_create gpr_avl_ref gpr_avl_unref diff --git a/grpc.gemspec b/grpc.gemspec index 6b8beba907..1185ca4ae0 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -71,7 +71,6 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/support/tls_msvc.h ) s.files += %w( include/grpc/support/tls_pthread.h ) s.files += %w( include/grpc/support/useful.h ) - s.files += %w( include/grpc/impl/codegen/alloc.h ) s.files += %w( include/grpc/impl/codegen/atm.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) @@ -154,7 +153,6 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/grpc_types.h ) s.files += %w( include/grpc/impl/codegen/propagation_bits.h ) s.files += %w( include/grpc/impl/codegen/status.h ) - s.files += %w( include/grpc/impl/codegen/alloc.h ) s.files += %w( include/grpc/impl/codegen/atm.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h index fab85d1517..05d537a7f3 100644 --- a/include/grpc++/impl/codegen/call.h +++ b/include/grpc++/impl/codegen/call.h @@ -48,7 +48,6 @@ #include #include -#include #include #include diff --git a/include/grpc/impl/codegen/alloc.h b/include/grpc/impl/codegen/alloc.h deleted file mode 100644 index 683c755f2c..0000000000 --- a/include/grpc/impl/codegen/alloc.h +++ /dev/null @@ -1,74 +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_IMPL_CODEGEN_ALLOC_H -#define GRPC_IMPL_CODEGEN_ALLOC_H - -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct gpr_allocation_functions { - void *(*malloc_fn)(size_t size); - void *(*realloc_fn)(void *ptr, size_t size); - void (*free_fn)(void *ptr); -} gpr_allocation_functions; - -/* malloc, never returns NULL */ -GPRAPI void *gpr_malloc(size_t size); -/* free */ -GPRAPI void gpr_free(void *ptr); -/* realloc, never returns NULL */ -GPRAPI void *gpr_realloc(void *p, size_t size); -/* aligned malloc, never returns NULL, will align to 1 << alignment_log */ -GPRAPI void *gpr_malloc_aligned(size_t size, size_t alignment_log); -/* free memory allocated by gpr_malloc_aligned */ -GPRAPI void gpr_free_aligned(void *ptr); - -/** Request the family of allocation functions in \a functions be used. NOTE - * that this request will be honored in a *best effort* basis and that no - * guarantees are made about the default functions (eg, malloc) being called. */ -GPRAPI void gpr_set_allocation_functions(gpr_allocation_functions functions); - -/** Return the family of allocation functions currently in effect. */ -GPRAPI gpr_allocation_functions gpr_get_allocation_functions(); - -#ifdef __cplusplus -} -#endif - -#endif /* GRPC_IMPL_CODEGEN_ALLOC_H */ diff --git a/include/grpc/support/alloc.h b/include/grpc/support/alloc.h index 8d03af8424..327a9ff9f0 100644 --- a/include/grpc/support/alloc.h +++ b/include/grpc/support/alloc.h @@ -34,6 +34,41 @@ #ifndef GRPC_SUPPORT_ALLOC_H #define GRPC_SUPPORT_ALLOC_H -#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct gpr_allocation_functions { + void *(*malloc_fn)(size_t size); + void *(*realloc_fn)(void *ptr, size_t size); + void (*free_fn)(void *ptr); +} gpr_allocation_functions; + +/* malloc, never returns NULL */ +GPRAPI void *gpr_malloc(size_t size); +/* free */ +GPRAPI void gpr_free(void *ptr); +/* realloc, never returns NULL */ +GPRAPI void *gpr_realloc(void *p, size_t size); +/* aligned malloc, never returns NULL, will align to 1 << alignment_log */ +GPRAPI void *gpr_malloc_aligned(size_t size, size_t alignment_log); +/* free memory allocated by gpr_malloc_aligned */ +GPRAPI void gpr_free_aligned(void *ptr); + +/** Request the family of allocation functions in \a functions be used. NOTE + * that this request will be honored in a *best effort* basis and that no + * guarantees are made about the default functions (eg, malloc) being called. */ +GPRAPI void gpr_set_allocation_functions(gpr_allocation_functions functions); + +/** Return the family of allocation functions currently in effect. */ +GPRAPI gpr_allocation_functions gpr_get_allocation_functions(); + +#ifdef __cplusplus +} +#endif #endif /* GRPC_SUPPORT_ALLOC_H */ diff --git a/package.xml b/package.xml index 66bd6886bb..9447a19816 100644 --- a/package.xml +++ b/package.xml @@ -79,7 +79,6 @@ - @@ -162,7 +161,6 @@ - diff --git a/src/core/lib/channel/handshaker.c b/src/core/lib/channel/handshaker.c index 6c3ca198b7..b5638e4202 100644 --- a/src/core/lib/channel/handshaker.c +++ b/src/core/lib/channel/handshaker.c @@ -33,8 +33,8 @@ #include -#include #include +#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc index 3d6780bcb8..b0f48e7e99 100644 --- a/src/cpp/common/core_codegen.cc +++ b/src/cpp/common/core_codegen.cc @@ -39,9 +39,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 3eeb55d033..e666a3324a 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc index e8ae6ee572..032b378b1a 100644 --- a/test/cpp/interop/client.cc +++ b/test/cpp/interop/client.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc index 8861bc1163..6117878a33 100644 --- a/test/cpp/interop/interop_client.cc +++ b/test/cpp/interop/interop_client.cc @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index a2415e1217..64c7d3491d 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -844,7 +844,6 @@ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 945298b964..907e96c403 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -844,7 +844,6 @@ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index e631c962b3..7be91461a7 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -773,7 +773,6 @@ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ @@ -818,7 +817,6 @@ 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 \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 62cf5cc8c7..680d6ae52d 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -773,7 +773,6 @@ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/propagation_bits.h \ include/grpc/impl/codegen/status.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 \ @@ -1161,7 +1160,6 @@ 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 \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index e85dd2c820..b454418290 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -5653,7 +5653,6 @@ { "deps": [], "headers": [ - "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", @@ -5671,7 +5670,6 @@ "language": "c", "name": "gpr_codegen", "src": [ - "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", diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index db8594e745..4b3383b38b 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -175,7 +175,6 @@ - diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index 9bab373513..45638be102 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -222,9 +222,6 @@ include\grpc\support - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index cb9e41ea22..c8b3df44d5 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -342,7 +342,6 @@ - diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index a9051182b3..5e3a17c5c9 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -354,9 +354,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj index 7c3e63b208..371d2e30df 100644 --- a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj +++ b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj @@ -188,7 +188,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters index d9cd49cc30..af0dc48bb0 100644 --- a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters @@ -138,9 +138,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj index d0fca9ba65..7bc71a52a1 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj @@ -184,7 +184,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters index cc98c60408..577bab57ea 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters @@ -144,9 +144,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index 03be485b29..e879ab0f88 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -342,7 +342,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index ba99bc53c8..dcdbf2fd94 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -339,9 +339,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 33485d3dc9..c5d96c1a6c 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -280,7 +280,6 @@ - diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index a21d873b88..c3103d51e7 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -603,9 +603,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 3a3610d524..982cf2a89e 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -271,7 +271,6 @@ - diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index bec089e860..c580913971 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -516,9 +516,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj index e608f7ed3a..eeef46d363 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj @@ -197,7 +197,6 @@ - diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters index 8fc8f3901b..65e33e77fe 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters @@ -132,9 +132,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj index 3331c61847..1caed32bbd 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj @@ -197,7 +197,6 @@ - diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters index a8ff115317..153d10a656 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters @@ -135,9 +135,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen -- cgit v1.2.3 From 3b31fdf77b6504f6582e66b156ca38bd6979ae1f Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Wed, 27 Jul 2016 18:17:12 -0700 Subject: removed codegen/byte_buffer.h --- BUILD | 7 -- Makefile | 7 -- build.yaml | 1 - gRPC-Core.podspec | 1 - grpc.def | 20 ++-- grpc.gemspec | 1 - .../grpc++/impl/codegen/core_codegen_interface.h | 6 + include/grpc++/impl/codegen/proto_utils.h | 2 +- include/grpc++/impl/codegen/rpc_service_method.h | 5 +- include/grpc/byte_buffer.h | 65 ++++++++++- include/grpc/impl/codegen/byte_buffer.h | 122 --------------------- include/grpc/impl/codegen/byte_buffer_reader.h | 8 +- include/grpc/impl/codegen/grpc_types.h | 118 +++++++++++++++++++- include/grpc/impl/codegen/slice.h | 48 -------- include/grpc/impl/codegen/slice_buffer.h | 17 --- include/grpc/impl/codegen/sync.h | 2 +- include/grpc/impl/codegen/time.h | 24 +--- package.xml | 1 - src/core/lib/security/credentials/jwt/json_token.c | 1 + src/cpp/common/core_codegen.cc | 5 +- src/ruby/ext/grpc/rb_grpc_imports.generated.c | 68 ++++++------ src/ruby/ext/grpc/rb_grpc_imports.generated.h | 106 +++++++++--------- test/core/surface/public_headers_must_be_c89.c | 1 - tools/doxygen/Doxyfile.c++ | 1 - tools/doxygen/Doxyfile.c++.internal | 1 - tools/doxygen/Doxyfile.core | 1 - tools/doxygen/Doxyfile.core.internal | 1 - tools/run_tests/sources_and_headers.json | 2 - vsprojects/vcxproj/grpc++/grpc++.vcxproj | 1 - vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters | 3 - .../grpc++_reflection/grpc++_reflection.vcxproj | 1 - .../grpc++_reflection.vcxproj.filters | 3 - .../grpc++_test_util/grpc++_test_util.vcxproj | 1 - .../grpc++_test_util.vcxproj.filters | 3 - .../grpc++_unsecure/grpc++_unsecure.vcxproj | 1 - .../grpc++_unsecure.vcxproj.filters | 3 - vsprojects/vcxproj/grpc/grpc.vcxproj | 1 - vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 3 - .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 1 - .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 3 - .../codegen_test_full/codegen_test_full.vcxproj | 1 - .../codegen_test_full.vcxproj.filters | 3 - .../codegen_test_minimal.vcxproj | 1 - .../codegen_test_minimal.vcxproj.filters | 3 - 44 files changed, 298 insertions(+), 376 deletions(-) delete mode 100644 include/grpc/impl/codegen/byte_buffer.h (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index 82c6cb7fd0..48239488d3 100644 --- a/BUILD +++ b/BUILD @@ -502,7 +502,6 @@ cc_library( "include/grpc/grpc.h", "include/grpc/grpc_posix.h", "include/grpc/status.h", - "include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", @@ -860,7 +859,6 @@ cc_library( "include/grpc/grpc.h", "include/grpc/grpc_posix.h", "include/grpc/status.h", - "include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", @@ -1190,7 +1188,6 @@ cc_library( "include/grpc/grpc.h", "include/grpc/grpc_posix.h", "include/grpc/status.h", - "include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", @@ -1349,7 +1346,6 @@ cc_library( "include/grpc++/impl/codegen/sync_no_cxx11.h", "include/grpc++/impl/codegen/sync_stream.h", "include/grpc++/impl/codegen/time.h", - "include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", @@ -1427,7 +1423,6 @@ cc_library( "include/grpc++/impl/codegen/sync_no_cxx11.h", "include/grpc++/impl/codegen/sync_stream.h", "include/grpc++/impl/codegen/time.h", - "include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", @@ -1573,7 +1568,6 @@ cc_library( "include/grpc++/impl/codegen/sync_no_cxx11.h", "include/grpc++/impl/codegen/sync_stream.h", "include/grpc++/impl/codegen/time.h", - "include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", @@ -1975,7 +1969,6 @@ objc_library( "include/grpc/grpc.h", "include/grpc/grpc_posix.h", "include/grpc/status.h", - "include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", diff --git a/Makefile b/Makefile index 07d7de02db..402294b549 100644 --- a/Makefile +++ b/Makefile @@ -2710,7 +2710,6 @@ PUBLIC_HEADERS_C += \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/status.h \ - include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ @@ -2959,7 +2958,6 @@ PUBLIC_HEADERS_C += \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/status.h \ - include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ @@ -3293,7 +3291,6 @@ PUBLIC_HEADERS_C += \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/status.h \ - include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ @@ -3543,7 +3540,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc++/impl/codegen/sync_no_cxx11.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ - include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ @@ -3668,7 +3664,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc++/impl/codegen/sync_no_cxx11.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ - include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ @@ -3894,7 +3889,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc++/impl/codegen/sync_no_cxx11.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ - include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ @@ -4076,7 +4070,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc++/impl/codegen/sync_no_cxx11.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ - include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ diff --git a/build.yaml b/build.yaml index f5ce0abe03..3113836a57 100644 --- a/build.yaml +++ b/build.yaml @@ -364,7 +364,6 @@ filegroups: - grpc_base - name: grpc_codegen public_headers: - - include/grpc/impl/codegen/byte_buffer.h - include/grpc/impl/codegen/byte_buffer_reader.h - include/grpc/impl/codegen/compression_types.h - include/grpc/impl/codegen/connectivity_state.h diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 451f4e879c..dbc57865de 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -163,7 +163,6 @@ Pod::Spec.new do |s| 'include/grpc/grpc.h', 'include/grpc/grpc_posix.h', 'include/grpc/status.h', - 'include/grpc/impl/codegen/byte_buffer.h', 'include/grpc/impl/codegen/byte_buffer_reader.h', 'include/grpc/impl/codegen/compression_types.h', 'include/grpc/impl/codegen/connectivity_state.h', diff --git a/grpc.def b/grpc.def index 7f24b85a5e..456198d3fa 100644 --- a/grpc.def +++ b/grpc.def @@ -1,4 +1,14 @@ EXPORTS + grpc_raw_byte_buffer_create + grpc_raw_compressed_byte_buffer_create + grpc_byte_buffer_copy + grpc_byte_buffer_length + grpc_byte_buffer_destroy + grpc_byte_buffer_reader_init + grpc_byte_buffer_reader_destroy + grpc_byte_buffer_reader_next + grpc_byte_buffer_reader_readall + grpc_raw_byte_buffer_from_reader census_initialize census_shutdown census_supported @@ -123,16 +133,6 @@ EXPORTS grpc_server_add_secure_http2_port grpc_call_set_credentials grpc_server_credentials_set_auth_metadata_processor - grpc_raw_byte_buffer_create - grpc_raw_compressed_byte_buffer_create - grpc_byte_buffer_copy - grpc_byte_buffer_length - grpc_byte_buffer_destroy - grpc_byte_buffer_reader_init - grpc_byte_buffer_reader_destroy - grpc_byte_buffer_reader_next - grpc_byte_buffer_reader_readall - grpc_raw_byte_buffer_from_reader gpr_log gpr_log_message gpr_set_log_verbosity diff --git a/grpc.gemspec b/grpc.gemspec index 1185ca4ae0..099cbe1f33 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -146,7 +146,6 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/grpc.h ) s.files += %w( include/grpc/grpc_posix.h ) s.files += %w( include/grpc/status.h ) - s.files += %w( include/grpc/impl/codegen/byte_buffer.h ) s.files += %w( include/grpc/impl/codegen/byte_buffer_reader.h ) s.files += %w( include/grpc/impl/codegen/compression_types.h ) s.files += %w( include/grpc/impl/codegen/connectivity_state.h ) diff --git a/include/grpc++/impl/codegen/core_codegen_interface.h b/include/grpc++/impl/codegen/core_codegen_interface.h index f9a8f9b980..5ff885a074 100644 --- a/include/grpc++/impl/codegen/core_codegen_interface.h +++ b/include/grpc++/impl/codegen/core_codegen_interface.h @@ -36,7 +36,13 @@ #include #include +#include #include +#include + +extern "C" { +struct grpc_byte_buffer; +} namespace grpc { diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h index d4599c5fff..5b9551c26b 100644 --- a/include/grpc++/impl/codegen/proto_utils.h +++ b/include/grpc++/impl/codegen/proto_utils.h @@ -40,8 +40,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/include/grpc++/impl/codegen/rpc_service_method.h b/include/grpc++/impl/codegen/rpc_service_method.h index 8b1f026c91..addbc36c0b 100644 --- a/include/grpc++/impl/codegen/rpc_service_method.h +++ b/include/grpc++/impl/codegen/rpc_service_method.h @@ -43,7 +43,10 @@ #include #include #include -#include + +extern "C" { +struct grpc_byte_buffer; +} namespace grpc { class ServerContext; diff --git a/include/grpc/byte_buffer.h b/include/grpc/byte_buffer.h index c3a394371d..4e17345b82 100644 --- a/include/grpc/byte_buffer.h +++ b/include/grpc/byte_buffer.h @@ -34,6 +34,69 @@ #ifndef GRPC_BYTE_BUFFER_H #define GRPC_BYTE_BUFFER_H -#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Returns a RAW byte buffer instance over the given slices (up to \a nslices). + * + * Increases the reference count for all \a slices processed. The user is + * responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/ +GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_create(gpr_slice *slices, + size_t nslices); + +/** Returns a *compressed* RAW byte buffer instance over the given slices (up to + * \a nslices). The \a compression argument defines the compression algorithm + * used to generate the data in \a slices. + * + * Increases the reference count for all \a slices processed. The user is + * responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/ +GRPCAPI grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create( + gpr_slice *slices, size_t nslices, grpc_compression_algorithm compression); + +/** Copies input byte buffer \a bb. + * + * Increases the reference count of all the source slices. The user is + * responsible for calling grpc_byte_buffer_destroy over the returned copy. */ +GRPCAPI grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb); + +/** Returns the size of the given byte buffer, in bytes. */ +GRPCAPI size_t grpc_byte_buffer_length(grpc_byte_buffer *bb); + +/** Destroys \a byte_buffer deallocating all its memory. */ +GRPCAPI void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer); + +/** Reader for byte buffers. Iterates over slices in the byte buffer */ +struct grpc_byte_buffer_reader; +typedef struct grpc_byte_buffer_reader grpc_byte_buffer_reader; + +/** Initialize \a reader to read over \a buffer. + * Returns 1 upon success, 0 otherwise. */ +GRPCAPI int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, + grpc_byte_buffer *buffer); + +/** Cleanup and destroy \a reader */ +GRPCAPI void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader); + +/** Updates \a slice with the next piece of data from from \a reader and returns + * 1. Returns 0 at the end of the stream. Caller is responsible for calling + * gpr_slice_unref on the result. */ +GRPCAPI int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, + gpr_slice *slice); + +/** Merge all data from \a reader into single slice */ +GRPCAPI gpr_slice +grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader); + +/** Returns a RAW byte buffer instance from the output of \a reader. */ +GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_from_reader( + grpc_byte_buffer_reader *reader); + +#ifdef __cplusplus +} +#endif #endif /* GRPC_BYTE_BUFFER_H */ diff --git a/include/grpc/impl/codegen/byte_buffer.h b/include/grpc/impl/codegen/byte_buffer.h deleted file mode 100644 index fe1e215979..0000000000 --- a/include/grpc/impl/codegen/byte_buffer.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * 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_IMPL_CODEGEN_BYTE_BUFFER_H -#define GRPC_IMPL_CODEGEN_BYTE_BUFFER_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - GRPC_BB_RAW - /* Future types may include GRPC_BB_PROTOBUF, etc. */ -} grpc_byte_buffer_type; - -struct grpc_byte_buffer { - void *reserved; - grpc_byte_buffer_type type; - union { - struct { - void *reserved[8]; - } reserved; - struct { - grpc_compression_algorithm compression; - gpr_slice_buffer slice_buffer; - } raw; - } data; -}; -typedef struct grpc_byte_buffer grpc_byte_buffer; - -/** Returns a RAW byte buffer instance over the given slices (up to \a nslices). - * - * Increases the reference count for all \a slices processed. The user is - * responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/ -GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_create(gpr_slice *slices, - size_t nslices); - -/** Returns a *compressed* RAW byte buffer instance over the given slices (up to - * \a nslices). The \a compression argument defines the compression algorithm - * used to generate the data in \a slices. - * - * Increases the reference count for all \a slices processed. The user is - * responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/ -GRPCAPI grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create( - gpr_slice *slices, size_t nslices, grpc_compression_algorithm compression); - -/** Copies input byte buffer \a bb. - * - * Increases the reference count of all the source slices. The user is - * responsible for calling grpc_byte_buffer_destroy over the returned copy. */ -GRPCAPI grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb); - -/** Returns the size of the given byte buffer, in bytes. */ -GRPCAPI size_t grpc_byte_buffer_length(grpc_byte_buffer *bb); - -/** Destroys \a byte_buffer deallocating all its memory. */ -GRPCAPI void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer); - -/** Reader for byte buffers. Iterates over slices in the byte buffer */ -struct grpc_byte_buffer_reader; -typedef struct grpc_byte_buffer_reader grpc_byte_buffer_reader; - -/** Initialize \a reader to read over \a buffer. - * Returns 1 upon success, 0 otherwise. */ -GRPCAPI int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, - grpc_byte_buffer *buffer); - -/** Cleanup and destroy \a reader */ -GRPCAPI void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader); - -/** Updates \a slice with the next piece of data from from \a reader and returns - * 1. Returns 0 at the end of the stream. Caller is responsible for calling - * gpr_slice_unref on the result. */ -GRPCAPI int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, - gpr_slice *slice); - -/** Merge all data from \a reader into single slice */ -GRPCAPI gpr_slice -grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader); - -/** Returns a RAW byte buffer instance from the output of \a reader. */ -GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_from_reader( - grpc_byte_buffer_reader *reader); - -#ifdef __cplusplus -} -#endif - -#endif /* GRPC_IMPL_CODEGEN_BYTE_BUFFER_H */ diff --git a/include/grpc/impl/codegen/byte_buffer_reader.h b/include/grpc/impl/codegen/byte_buffer_reader.h index 10c382924e..85a4864140 100644 --- a/include/grpc/impl/codegen/byte_buffer_reader.h +++ b/include/grpc/impl/codegen/byte_buffer_reader.h @@ -34,15 +34,15 @@ #ifndef GRPC_IMPL_CODEGEN_BYTE_BUFFER_READER_H #define GRPC_IMPL_CODEGEN_BYTE_BUFFER_READER_H -#include - #ifdef __cplusplus extern "C" { #endif +struct grpc_byte_buffer; + struct grpc_byte_buffer_reader { - grpc_byte_buffer *buffer_in; - grpc_byte_buffer *buffer_out; + struct grpc_byte_buffer *buffer_in; + struct grpc_byte_buffer *buffer_out; /* Different current objects correspond to different types of byte buffers */ union { /* Index into a slice buffer's array of slices */ diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index e5a82883be..6aa7dc6eab 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -34,15 +34,125 @@ #ifndef GRPC_IMPL_CODEGEN_GRPC_TYPES_H #define GRPC_IMPL_CODEGEN_GRPC_TYPES_H -#include +#include #include #include +#include #ifdef __cplusplus extern "C" { #endif +/* The clocks we support. */ +typedef enum { + /* Monotonic clock. Epoch undefined. Always moves forwards. */ + GPR_CLOCK_MONOTONIC = 0, + /* Realtime clock. May jump forwards or backwards. Settable by + the system administrator. Has its epoch at 0:00:00 UTC 1 Jan 1970. */ + GPR_CLOCK_REALTIME, + /* CPU cycle time obtained by rdtsc instruction on x86 platforms. Epoch + undefined. Degrades to GPR_CLOCK_REALTIME on other platforms. */ + GPR_CLOCK_PRECISE, + /* Unmeasurable clock type: no base, created by taking the difference + between two times */ + GPR_TIMESPAN +} gpr_clock_type; + +/* Analogous to struct timespec. On some machines, absolute times may be in + * local time. */ +typedef struct gpr_timespec { + int64_t tv_sec; + int32_t tv_nsec; + /** Against which clock was this time measured? (or GPR_TIMESPAN if + this is a relative time meaure) */ + gpr_clock_type clock_type; +} gpr_timespec; + +/* Slice API + + A slice represents a contiguous reference counted array of bytes. + It is cheap to take references to a slice, and it is cheap to create a + slice pointing to a subset of another slice. + + The data-structure for slices is exposed here to allow non-gpr code to + build slices from whatever data they have available. + + When defining interfaces that handle slices, care should be taken to define + reference ownership semantics (who should call unref?) and mutability + constraints (is the callee allowed to modify the slice?) */ + +/* Reference count container for gpr_slice. Contains function pointers to + increment and decrement reference counts. Implementations should cleanup + when the reference count drops to zero. + Typically client code should not touch this, and use gpr_slice_malloc, + gpr_slice_new, or gpr_slice_new_with_len instead. */ +typedef struct gpr_slice_refcount { + void (*ref)(void *); + void (*unref)(void *); +} gpr_slice_refcount; + +#define GPR_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1) + +/* A gpr_slice s, if initialized, represents the byte range + s.bytes[0..s.length-1]. + + It can have an associated ref count which has a destruction routine to be run + when the ref count reaches zero (see gpr_slice_new() and grp_slice_unref()). + Multiple gpr_slice values may share a ref count. + + If the slice does not have a refcount, it represents an inlined small piece + of data that is copied by value. */ +typedef struct gpr_slice { + struct gpr_slice_refcount *refcount; + union { + struct { + uint8_t *bytes; + size_t length; + } refcounted; + struct { + uint8_t length; + uint8_t bytes[GPR_SLICE_INLINED_SIZE]; + } inlined; + } data; +} gpr_slice; + +#define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8 + +/* Represents an expandable array of slices, to be interpreted as a + single item. */ +typedef struct { + /* slices in the array */ + gpr_slice *slices; + /* the number of slices in the array */ + size_t count; + /* the number of slices allocated in the array */ + size_t capacity; + /* the combined length of all slices in the array */ + size_t length; + /* inlined elements to avoid allocations */ + gpr_slice inlined[GRPC_SLICE_BUFFER_INLINE_ELEMENTS]; +} gpr_slice_buffer; + +typedef enum { + GRPC_BB_RAW + /* Future types may include GRPC_BB_PROTOBUF, etc. */ +} grpc_byte_buffer_type; + +typedef struct grpc_byte_buffer { + void *reserved; + grpc_byte_buffer_type type; + union { + struct { + void *reserved[8]; + } reserved; + struct { + grpc_compression_algorithm compression; + gpr_slice_buffer slice_buffer; + } raw; + } data; +} grpc_byte_buffer; + /** Completion Queues enable notification of the completion of asynchronous actions. */ typedef struct grpc_completion_queue grpc_completion_queue; @@ -327,6 +437,8 @@ typedef enum { GRPC_OP_RECV_CLOSE_ON_SERVER } grpc_op_type; +struct grpc_byte_buffer; + /** Operation data: one field for each op type (except SEND_CLOSE_FROM_CLIENT which has no arguments) */ typedef struct grpc_op { @@ -351,7 +463,7 @@ typedef struct grpc_op { grpc_compression_level level; } maybe_compression_level; } send_initial_metadata; - grpc_byte_buffer *send_message; + struct grpc_byte_buffer *send_message; struct { size_t trailing_metadata_count; grpc_metadata *trailing_metadata; @@ -367,7 +479,7 @@ typedef struct grpc_op { /** ownership of the byte buffer is moved to the caller; the caller must call grpc_byte_buffer_destroy on this value, or reuse it in a future op. */ - grpc_byte_buffer **recv_message; + struct grpc_byte_buffer **recv_message; struct { /** ownership of the array is with the caller, but ownership of the elements stays with the call object (ie key, value members are owned diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h index dfc0a774fc..c0ab00fcda 100644 --- a/include/grpc/impl/codegen/slice.h +++ b/include/grpc/impl/codegen/slice.h @@ -42,54 +42,6 @@ extern "C" { #endif -/* Slice API - - A slice represents a contiguous reference counted array of bytes. - It is cheap to take references to a slice, and it is cheap to create a - slice pointing to a subset of another slice. - - The data-structure for slices is exposed here to allow non-gpr code to - build slices from whatever data they have available. - - When defining interfaces that handle slices, care should be taken to define - reference ownership semantics (who should call unref?) and mutability - constraints (is the callee allowed to modify the slice?) */ - -/* Reference count container for gpr_slice. Contains function pointers to - increment and decrement reference counts. Implementations should cleanup - when the reference count drops to zero. - Typically client code should not touch this, and use gpr_slice_malloc, - gpr_slice_new, or gpr_slice_new_with_len instead. */ -typedef struct gpr_slice_refcount { - void (*ref)(void *); - void (*unref)(void *); -} gpr_slice_refcount; - -#define GPR_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1) - -/* A gpr_slice s, if initialized, represents the byte range - s.bytes[0..s.length-1]. - - It can have an associated ref count which has a destruction routine to be run - when the ref count reaches zero (see gpr_slice_new() and grp_slice_unref()). - Multiple gpr_slice values may share a ref count. - - If the slice does not have a refcount, it represents an inlined small piece - of data that is copied by value. */ -typedef struct gpr_slice { - struct gpr_slice_refcount *refcount; - union { - struct { - uint8_t *bytes; - size_t length; - } refcounted; - struct { - uint8_t length; - uint8_t bytes[GPR_SLICE_INLINED_SIZE]; - } inlined; - } data; -} gpr_slice; - #define GPR_SLICE_START_PTR(slice) \ ((slice).refcount ? (slice).data.refcounted.bytes \ : (slice).data.inlined.bytes) diff --git a/include/grpc/impl/codegen/slice_buffer.h b/include/grpc/impl/codegen/slice_buffer.h index 7858021600..0d36d96b4f 100644 --- a/include/grpc/impl/codegen/slice_buffer.h +++ b/include/grpc/impl/codegen/slice_buffer.h @@ -40,23 +40,6 @@ extern "C" { #endif -#define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8 - -/* Represents an expandable array of slices, to be interpreted as a - single item. */ -typedef struct { - /* slices in the array */ - gpr_slice *slices; - /* the number of slices in the array */ - size_t count; - /* the number of slices allocated in the array */ - size_t capacity; - /* the combined length of all slices in the array */ - size_t length; - /* inlined elements to avoid allocations */ - gpr_slice inlined[GRPC_SLICE_BUFFER_INLINE_ELEMENTS]; -} gpr_slice_buffer; - /* initialize a slice buffer */ GPRAPI void gpr_slice_buffer_init(gpr_slice_buffer *sb); /* destroy a slice buffer - unrefs any held elements */ diff --git a/include/grpc/impl/codegen/sync.h b/include/grpc/impl/codegen/sync.h index 5542482ed8..3eabc5c17b 100644 --- a/include/grpc/impl/codegen/sync.h +++ b/include/grpc/impl/codegen/sync.h @@ -64,7 +64,7 @@ #error Unable to determine platform for sync #endif -#include /* for gpr_timespec */ +#include /* for gpr_timespec */ #ifdef __cplusplus extern "C" { diff --git a/include/grpc/impl/codegen/time.h b/include/grpc/impl/codegen/time.h index 381e267259..c7c476ce38 100644 --- a/include/grpc/impl/codegen/time.h +++ b/include/grpc/impl/codegen/time.h @@ -37,6 +37,7 @@ We use gpr_timespec, which is analogous to struct timespec. On some machines, absolute times may be in local time. */ +#include #include #include #include @@ -45,29 +46,6 @@ extern "C" { #endif -/* The clocks we support. */ -typedef enum { - /* Monotonic clock. Epoch undefined. Always moves forwards. */ - GPR_CLOCK_MONOTONIC = 0, - /* Realtime clock. May jump forwards or backwards. Settable by - the system administrator. Has its epoch at 0:00:00 UTC 1 Jan 1970. */ - GPR_CLOCK_REALTIME, - /* CPU cycle time obtained by rdtsc instruction on x86 platforms. Epoch - undefined. Degrades to GPR_CLOCK_REALTIME on other platforms. */ - GPR_CLOCK_PRECISE, - /* Unmeasurable clock type: no base, created by taking the difference - between two times */ - GPR_TIMESPAN -} gpr_clock_type; - -typedef struct gpr_timespec { - int64_t tv_sec; - int32_t tv_nsec; - /** Against which clock was this time measured? (or GPR_TIMESPAN if - this is a relative time meaure) */ - gpr_clock_type clock_type; -} gpr_timespec; - /* Time constants. */ GPRAPI gpr_timespec gpr_time_0(gpr_clock_type type); /* The zero time interval. */ diff --git a/package.xml b/package.xml index 9447a19816..09b85d5d21 100644 --- a/package.xml +++ b/package.xml @@ -154,7 +154,6 @@ - diff --git a/src/core/lib/security/credentials/jwt/json_token.c b/src/core/lib/security/credentials/jwt/json_token.c index 354c13133e..192a5f47ed 100644 --- a/src/core/lib/security/credentials/jwt/json_token.c +++ b/src/core/lib/security/credentials/jwt/json_token.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "src/core/lib/security/util/b64.h" #include "src/core/lib/security/util/json_util.h" diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc index b0f48e7e99..14ba826de2 100644 --- a/src/cpp/common/core_codegen.cc +++ b/src/cpp/common/core_codegen.cc @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -48,6 +47,10 @@ #include "src/core/lib/profiling/timers.h" +extern "C" { +struct grpc_byte_buffer; +} + namespace grpc { grpc_completion_queue* CoreCodegen::grpc_completion_queue_create( diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index d7f862cd9c..2583ea86eb 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -37,6 +37,16 @@ #include "rb_grpc_imports.generated.h" +grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import; +grpc_raw_compressed_byte_buffer_create_type grpc_raw_compressed_byte_buffer_create_import; +grpc_byte_buffer_copy_type grpc_byte_buffer_copy_import; +grpc_byte_buffer_length_type grpc_byte_buffer_length_import; +grpc_byte_buffer_destroy_type grpc_byte_buffer_destroy_import; +grpc_byte_buffer_reader_init_type grpc_byte_buffer_reader_init_import; +grpc_byte_buffer_reader_destroy_type grpc_byte_buffer_reader_destroy_import; +grpc_byte_buffer_reader_next_type grpc_byte_buffer_reader_next_import; +grpc_byte_buffer_reader_readall_type grpc_byte_buffer_reader_readall_import; +grpc_raw_byte_buffer_from_reader_type grpc_raw_byte_buffer_from_reader_import; census_initialize_type census_initialize_import; census_shutdown_type census_shutdown_import; census_supported_type census_supported_import; @@ -161,23 +171,6 @@ grpc_ssl_server_credentials_create_ex_type grpc_ssl_server_credentials_create_ex grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import; grpc_call_set_credentials_type grpc_call_set_credentials_import; grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import; -gpr_malloc_type gpr_malloc_import; -gpr_free_type gpr_free_import; -gpr_realloc_type gpr_realloc_import; -gpr_malloc_aligned_type gpr_malloc_aligned_import; -gpr_free_aligned_type gpr_free_aligned_import; -gpr_set_allocation_functions_type gpr_set_allocation_functions_import; -gpr_get_allocation_functions_type gpr_get_allocation_functions_import; -grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import; -grpc_raw_compressed_byte_buffer_create_type grpc_raw_compressed_byte_buffer_create_import; -grpc_byte_buffer_copy_type grpc_byte_buffer_copy_import; -grpc_byte_buffer_length_type grpc_byte_buffer_length_import; -grpc_byte_buffer_destroy_type grpc_byte_buffer_destroy_import; -grpc_byte_buffer_reader_init_type grpc_byte_buffer_reader_init_import; -grpc_byte_buffer_reader_destroy_type grpc_byte_buffer_reader_destroy_import; -grpc_byte_buffer_reader_next_type grpc_byte_buffer_reader_next_import; -grpc_byte_buffer_reader_readall_type grpc_byte_buffer_reader_readall_import; -grpc_raw_byte_buffer_from_reader_type grpc_raw_byte_buffer_from_reader_import; gpr_log_type gpr_log_import; gpr_log_message_type gpr_log_message_import; gpr_set_log_verbosity_type gpr_set_log_verbosity_import; @@ -256,6 +249,13 @@ gpr_time_to_millis_type gpr_time_to_millis_import; gpr_time_similar_type gpr_time_similar_import; gpr_sleep_until_type gpr_sleep_until_import; gpr_timespec_to_micros_type gpr_timespec_to_micros_import; +gpr_malloc_type gpr_malloc_import; +gpr_free_type gpr_free_import; +gpr_realloc_type gpr_realloc_import; +gpr_malloc_aligned_type gpr_malloc_aligned_import; +gpr_free_aligned_type gpr_free_aligned_import; +gpr_set_allocation_functions_type gpr_set_allocation_functions_import; +gpr_get_allocation_functions_type gpr_get_allocation_functions_import; gpr_avl_create_type gpr_avl_create_import; gpr_avl_ref_type gpr_avl_ref_import; gpr_avl_unref_type gpr_avl_unref_import; @@ -310,6 +310,16 @@ gpr_thd_currentid_type gpr_thd_currentid_import; gpr_thd_join_type gpr_thd_join_import; void grpc_rb_load_imports(HMODULE library) { + grpc_raw_byte_buffer_create_import = (grpc_raw_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_byte_buffer_create"); + grpc_raw_compressed_byte_buffer_create_import = (grpc_raw_compressed_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_compressed_byte_buffer_create"); + grpc_byte_buffer_copy_import = (grpc_byte_buffer_copy_type) GetProcAddress(library, "grpc_byte_buffer_copy"); + grpc_byte_buffer_length_import = (grpc_byte_buffer_length_type) GetProcAddress(library, "grpc_byte_buffer_length"); + grpc_byte_buffer_destroy_import = (grpc_byte_buffer_destroy_type) GetProcAddress(library, "grpc_byte_buffer_destroy"); + grpc_byte_buffer_reader_init_import = (grpc_byte_buffer_reader_init_type) GetProcAddress(library, "grpc_byte_buffer_reader_init"); + grpc_byte_buffer_reader_destroy_import = (grpc_byte_buffer_reader_destroy_type) GetProcAddress(library, "grpc_byte_buffer_reader_destroy"); + grpc_byte_buffer_reader_next_import = (grpc_byte_buffer_reader_next_type) GetProcAddress(library, "grpc_byte_buffer_reader_next"); + grpc_byte_buffer_reader_readall_import = (grpc_byte_buffer_reader_readall_type) GetProcAddress(library, "grpc_byte_buffer_reader_readall"); + grpc_raw_byte_buffer_from_reader_import = (grpc_raw_byte_buffer_from_reader_type) GetProcAddress(library, "grpc_raw_byte_buffer_from_reader"); census_initialize_import = (census_initialize_type) GetProcAddress(library, "census_initialize"); census_shutdown_import = (census_shutdown_type) GetProcAddress(library, "census_shutdown"); census_supported_import = (census_supported_type) GetProcAddress(library, "census_supported"); @@ -434,23 +444,6 @@ void grpc_rb_load_imports(HMODULE library) { grpc_server_add_secure_http2_port_import = (grpc_server_add_secure_http2_port_type) GetProcAddress(library, "grpc_server_add_secure_http2_port"); grpc_call_set_credentials_import = (grpc_call_set_credentials_type) GetProcAddress(library, "grpc_call_set_credentials"); grpc_server_credentials_set_auth_metadata_processor_import = (grpc_server_credentials_set_auth_metadata_processor_type) GetProcAddress(library, "grpc_server_credentials_set_auth_metadata_processor"); - gpr_malloc_import = (gpr_malloc_type) GetProcAddress(library, "gpr_malloc"); - gpr_free_import = (gpr_free_type) GetProcAddress(library, "gpr_free"); - gpr_realloc_import = (gpr_realloc_type) GetProcAddress(library, "gpr_realloc"); - gpr_malloc_aligned_import = (gpr_malloc_aligned_type) GetProcAddress(library, "gpr_malloc_aligned"); - gpr_free_aligned_import = (gpr_free_aligned_type) GetProcAddress(library, "gpr_free_aligned"); - gpr_set_allocation_functions_import = (gpr_set_allocation_functions_type) GetProcAddress(library, "gpr_set_allocation_functions"); - gpr_get_allocation_functions_import = (gpr_get_allocation_functions_type) GetProcAddress(library, "gpr_get_allocation_functions"); - grpc_raw_byte_buffer_create_import = (grpc_raw_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_byte_buffer_create"); - grpc_raw_compressed_byte_buffer_create_import = (grpc_raw_compressed_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_compressed_byte_buffer_create"); - grpc_byte_buffer_copy_import = (grpc_byte_buffer_copy_type) GetProcAddress(library, "grpc_byte_buffer_copy"); - grpc_byte_buffer_length_import = (grpc_byte_buffer_length_type) GetProcAddress(library, "grpc_byte_buffer_length"); - grpc_byte_buffer_destroy_import = (grpc_byte_buffer_destroy_type) GetProcAddress(library, "grpc_byte_buffer_destroy"); - grpc_byte_buffer_reader_init_import = (grpc_byte_buffer_reader_init_type) GetProcAddress(library, "grpc_byte_buffer_reader_init"); - grpc_byte_buffer_reader_destroy_import = (grpc_byte_buffer_reader_destroy_type) GetProcAddress(library, "grpc_byte_buffer_reader_destroy"); - grpc_byte_buffer_reader_next_import = (grpc_byte_buffer_reader_next_type) GetProcAddress(library, "grpc_byte_buffer_reader_next"); - grpc_byte_buffer_reader_readall_import = (grpc_byte_buffer_reader_readall_type) GetProcAddress(library, "grpc_byte_buffer_reader_readall"); - grpc_raw_byte_buffer_from_reader_import = (grpc_raw_byte_buffer_from_reader_type) GetProcAddress(library, "grpc_raw_byte_buffer_from_reader"); gpr_log_import = (gpr_log_type) GetProcAddress(library, "gpr_log"); gpr_log_message_import = (gpr_log_message_type) GetProcAddress(library, "gpr_log_message"); gpr_set_log_verbosity_import = (gpr_set_log_verbosity_type) GetProcAddress(library, "gpr_set_log_verbosity"); @@ -529,6 +522,13 @@ void grpc_rb_load_imports(HMODULE library) { gpr_time_similar_import = (gpr_time_similar_type) GetProcAddress(library, "gpr_time_similar"); gpr_sleep_until_import = (gpr_sleep_until_type) GetProcAddress(library, "gpr_sleep_until"); gpr_timespec_to_micros_import = (gpr_timespec_to_micros_type) GetProcAddress(library, "gpr_timespec_to_micros"); + gpr_malloc_import = (gpr_malloc_type) GetProcAddress(library, "gpr_malloc"); + gpr_free_import = (gpr_free_type) GetProcAddress(library, "gpr_free"); + gpr_realloc_import = (gpr_realloc_type) GetProcAddress(library, "gpr_realloc"); + gpr_malloc_aligned_import = (gpr_malloc_aligned_type) GetProcAddress(library, "gpr_malloc_aligned"); + gpr_free_aligned_import = (gpr_free_aligned_type) GetProcAddress(library, "gpr_free_aligned"); + gpr_set_allocation_functions_import = (gpr_set_allocation_functions_type) GetProcAddress(library, "gpr_set_allocation_functions"); + gpr_get_allocation_functions_import = (gpr_get_allocation_functions_type) GetProcAddress(library, "gpr_get_allocation_functions"); gpr_avl_create_import = (gpr_avl_create_type) GetProcAddress(library, "gpr_avl_create"); gpr_avl_ref_import = (gpr_avl_ref_type) GetProcAddress(library, "gpr_avl_ref"); gpr_avl_unref_import = (gpr_avl_unref_type) GetProcAddress(library, "gpr_avl_unref"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 14da63780c..9563e95e96 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -40,18 +40,18 @@ #include +#include #include #include #include #include #include -#include -#include #include #include #include #include #include +#include #include #include #include @@ -62,6 +62,36 @@ #include #include +typedef grpc_byte_buffer *(*grpc_raw_byte_buffer_create_type)(gpr_slice *slices, size_t nslices); +extern grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import; +#define grpc_raw_byte_buffer_create grpc_raw_byte_buffer_create_import +typedef grpc_byte_buffer *(*grpc_raw_compressed_byte_buffer_create_type)(gpr_slice *slices, size_t nslices, grpc_compression_algorithm compression); +extern grpc_raw_compressed_byte_buffer_create_type grpc_raw_compressed_byte_buffer_create_import; +#define grpc_raw_compressed_byte_buffer_create grpc_raw_compressed_byte_buffer_create_import +typedef grpc_byte_buffer *(*grpc_byte_buffer_copy_type)(grpc_byte_buffer *bb); +extern grpc_byte_buffer_copy_type grpc_byte_buffer_copy_import; +#define grpc_byte_buffer_copy grpc_byte_buffer_copy_import +typedef size_t(*grpc_byte_buffer_length_type)(grpc_byte_buffer *bb); +extern grpc_byte_buffer_length_type grpc_byte_buffer_length_import; +#define grpc_byte_buffer_length grpc_byte_buffer_length_import +typedef void(*grpc_byte_buffer_destroy_type)(grpc_byte_buffer *byte_buffer); +extern grpc_byte_buffer_destroy_type grpc_byte_buffer_destroy_import; +#define grpc_byte_buffer_destroy grpc_byte_buffer_destroy_import +typedef int(*grpc_byte_buffer_reader_init_type)(grpc_byte_buffer_reader *reader, grpc_byte_buffer *buffer); +extern grpc_byte_buffer_reader_init_type grpc_byte_buffer_reader_init_import; +#define grpc_byte_buffer_reader_init grpc_byte_buffer_reader_init_import +typedef void(*grpc_byte_buffer_reader_destroy_type)(grpc_byte_buffer_reader *reader); +extern grpc_byte_buffer_reader_destroy_type grpc_byte_buffer_reader_destroy_import; +#define grpc_byte_buffer_reader_destroy grpc_byte_buffer_reader_destroy_import +typedef int(*grpc_byte_buffer_reader_next_type)(grpc_byte_buffer_reader *reader, gpr_slice *slice); +extern grpc_byte_buffer_reader_next_type grpc_byte_buffer_reader_next_import; +#define grpc_byte_buffer_reader_next grpc_byte_buffer_reader_next_import +typedef gpr_slice(*grpc_byte_buffer_reader_readall_type)(grpc_byte_buffer_reader *reader); +extern grpc_byte_buffer_reader_readall_type grpc_byte_buffer_reader_readall_import; +#define grpc_byte_buffer_reader_readall grpc_byte_buffer_reader_readall_import +typedef grpc_byte_buffer *(*grpc_raw_byte_buffer_from_reader_type)(grpc_byte_buffer_reader *reader); +extern grpc_raw_byte_buffer_from_reader_type grpc_raw_byte_buffer_from_reader_import; +#define grpc_raw_byte_buffer_from_reader grpc_raw_byte_buffer_from_reader_import typedef int(*census_initialize_type)(int features); extern census_initialize_type census_initialize_import; #define census_initialize census_initialize_import @@ -434,57 +464,6 @@ extern grpc_call_set_credentials_type grpc_call_set_credentials_import; typedef void(*grpc_server_credentials_set_auth_metadata_processor_type)(grpc_server_credentials *creds, grpc_auth_metadata_processor processor); extern grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import; #define grpc_server_credentials_set_auth_metadata_processor grpc_server_credentials_set_auth_metadata_processor_import -typedef void *(*gpr_malloc_type)(size_t size); -extern gpr_malloc_type gpr_malloc_import; -#define gpr_malloc gpr_malloc_import -typedef void(*gpr_free_type)(void *ptr); -extern gpr_free_type gpr_free_import; -#define gpr_free gpr_free_import -typedef void *(*gpr_realloc_type)(void *p, size_t size); -extern gpr_realloc_type gpr_realloc_import; -#define gpr_realloc gpr_realloc_import -typedef void *(*gpr_malloc_aligned_type)(size_t size, size_t alignment_log); -extern gpr_malloc_aligned_type gpr_malloc_aligned_import; -#define gpr_malloc_aligned gpr_malloc_aligned_import -typedef void(*gpr_free_aligned_type)(void *ptr); -extern gpr_free_aligned_type gpr_free_aligned_import; -#define gpr_free_aligned gpr_free_aligned_import -typedef void(*gpr_set_allocation_functions_type)(gpr_allocation_functions functions); -extern gpr_set_allocation_functions_type gpr_set_allocation_functions_import; -#define gpr_set_allocation_functions gpr_set_allocation_functions_import -typedef gpr_allocation_functions(*gpr_get_allocation_functions_type)(); -extern gpr_get_allocation_functions_type gpr_get_allocation_functions_import; -#define gpr_get_allocation_functions gpr_get_allocation_functions_import -typedef grpc_byte_buffer *(*grpc_raw_byte_buffer_create_type)(gpr_slice *slices, size_t nslices); -extern grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import; -#define grpc_raw_byte_buffer_create grpc_raw_byte_buffer_create_import -typedef grpc_byte_buffer *(*grpc_raw_compressed_byte_buffer_create_type)(gpr_slice *slices, size_t nslices, grpc_compression_algorithm compression); -extern grpc_raw_compressed_byte_buffer_create_type grpc_raw_compressed_byte_buffer_create_import; -#define grpc_raw_compressed_byte_buffer_create grpc_raw_compressed_byte_buffer_create_import -typedef grpc_byte_buffer *(*grpc_byte_buffer_copy_type)(grpc_byte_buffer *bb); -extern grpc_byte_buffer_copy_type grpc_byte_buffer_copy_import; -#define grpc_byte_buffer_copy grpc_byte_buffer_copy_import -typedef size_t(*grpc_byte_buffer_length_type)(grpc_byte_buffer *bb); -extern grpc_byte_buffer_length_type grpc_byte_buffer_length_import; -#define grpc_byte_buffer_length grpc_byte_buffer_length_import -typedef void(*grpc_byte_buffer_destroy_type)(grpc_byte_buffer *byte_buffer); -extern grpc_byte_buffer_destroy_type grpc_byte_buffer_destroy_import; -#define grpc_byte_buffer_destroy grpc_byte_buffer_destroy_import -typedef int(*grpc_byte_buffer_reader_init_type)(grpc_byte_buffer_reader *reader, grpc_byte_buffer *buffer); -extern grpc_byte_buffer_reader_init_type grpc_byte_buffer_reader_init_import; -#define grpc_byte_buffer_reader_init grpc_byte_buffer_reader_init_import -typedef void(*grpc_byte_buffer_reader_destroy_type)(grpc_byte_buffer_reader *reader); -extern grpc_byte_buffer_reader_destroy_type grpc_byte_buffer_reader_destroy_import; -#define grpc_byte_buffer_reader_destroy grpc_byte_buffer_reader_destroy_import -typedef int(*grpc_byte_buffer_reader_next_type)(grpc_byte_buffer_reader *reader, gpr_slice *slice); -extern grpc_byte_buffer_reader_next_type grpc_byte_buffer_reader_next_import; -#define grpc_byte_buffer_reader_next grpc_byte_buffer_reader_next_import -typedef gpr_slice(*grpc_byte_buffer_reader_readall_type)(grpc_byte_buffer_reader *reader); -extern grpc_byte_buffer_reader_readall_type grpc_byte_buffer_reader_readall_import; -#define grpc_byte_buffer_reader_readall grpc_byte_buffer_reader_readall_import -typedef grpc_byte_buffer *(*grpc_raw_byte_buffer_from_reader_type)(grpc_byte_buffer_reader *reader); -extern grpc_raw_byte_buffer_from_reader_type grpc_raw_byte_buffer_from_reader_import; -#define grpc_raw_byte_buffer_from_reader grpc_raw_byte_buffer_from_reader_import typedef void(*gpr_log_type)(const char *file, int line, gpr_log_severity severity, const char *format, ...) GPRC_PRINT_FORMAT_CHECK(4, 5); extern gpr_log_type gpr_log_import; #define gpr_log gpr_log_import @@ -719,6 +698,27 @@ extern gpr_sleep_until_type gpr_sleep_until_import; typedef double(*gpr_timespec_to_micros_type)(gpr_timespec t); extern gpr_timespec_to_micros_type gpr_timespec_to_micros_import; #define gpr_timespec_to_micros gpr_timespec_to_micros_import +typedef void *(*gpr_malloc_type)(size_t size); +extern gpr_malloc_type gpr_malloc_import; +#define gpr_malloc gpr_malloc_import +typedef void(*gpr_free_type)(void *ptr); +extern gpr_free_type gpr_free_import; +#define gpr_free gpr_free_import +typedef void *(*gpr_realloc_type)(void *p, size_t size); +extern gpr_realloc_type gpr_realloc_import; +#define gpr_realloc gpr_realloc_import +typedef void *(*gpr_malloc_aligned_type)(size_t size, size_t alignment_log); +extern gpr_malloc_aligned_type gpr_malloc_aligned_import; +#define gpr_malloc_aligned gpr_malloc_aligned_import +typedef void(*gpr_free_aligned_type)(void *ptr); +extern gpr_free_aligned_type gpr_free_aligned_import; +#define gpr_free_aligned gpr_free_aligned_import +typedef void(*gpr_set_allocation_functions_type)(gpr_allocation_functions functions); +extern gpr_set_allocation_functions_type gpr_set_allocation_functions_import; +#define gpr_set_allocation_functions gpr_set_allocation_functions_import +typedef gpr_allocation_functions(*gpr_get_allocation_functions_type)(); +extern gpr_get_allocation_functions_type gpr_get_allocation_functions_import; +#define gpr_get_allocation_functions gpr_get_allocation_functions_import typedef gpr_avl(*gpr_avl_create_type)(const gpr_avl_vtable *vtable); extern gpr_avl_create_type gpr_avl_create_import; #define gpr_avl_create gpr_avl_create_import diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index e666a3324a..f9aaf59a67 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 64c7d3491d..c18218d1a2 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -837,7 +837,6 @@ include/grpc++/impl/codegen/sync_cxx11.h \ include/grpc++/impl/codegen/sync_no_cxx11.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ -include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 907e96c403..ac90a18e87 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -837,7 +837,6 @@ include/grpc++/impl/codegen/sync_cxx11.h \ include/grpc++/impl/codegen/sync_no_cxx11.h \ include/grpc++/impl/codegen/sync_stream.h \ include/grpc++/impl/codegen/time.h \ -include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 7be91461a7..3e6d19f230 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -766,7 +766,6 @@ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/status.h \ -include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 680d6ae52d..bc63c9418a 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -766,7 +766,6 @@ include/grpc/compression.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ include/grpc/status.h \ -include/grpc/impl/codegen/byte_buffer.h \ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index b454418290..a3ed76ffa8 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -6029,7 +6029,6 @@ "gpr_codegen" ], "headers": [ - "include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", @@ -6040,7 +6039,6 @@ "language": "c", "name": "grpc_codegen", "src": [ - "include/grpc/impl/codegen/byte_buffer.h", "include/grpc/impl/codegen/byte_buffer_reader.h", "include/grpc/impl/codegen/compression_types.h", "include/grpc/impl/codegen/connectivity_state.h", diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index c8b3df44d5..0878cbb46d 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -335,7 +335,6 @@ - diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index 5e3a17c5c9..e92e43b9c4 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -333,9 +333,6 @@ include\grpc++\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj index 371d2e30df..0cc3245a20 100644 --- a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj +++ b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj @@ -181,7 +181,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters index af0dc48bb0..8d0c9a8f0f 100644 --- a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters @@ -117,9 +117,6 @@ include\grpc++\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj index 7bc71a52a1..b3f1df5bf7 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj @@ -177,7 +177,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters index 577bab57ea..23cbbfddc8 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters @@ -123,9 +123,6 @@ include\grpc++\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index e879ab0f88..cfb87d279e 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -335,7 +335,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index dcdbf2fd94..22d19ffaec 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -318,9 +318,6 @@ include\grpc++\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index c5d96c1a6c..6945ff5da3 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -273,7 +273,6 @@ - diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index c3103d51e7..b7aefec905 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -582,9 +582,6 @@ include\grpc - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 982cf2a89e..b68301c24c 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -264,7 +264,6 @@ - diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index c580913971..2f86004440 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -495,9 +495,6 @@ include\grpc - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj index eeef46d363..6533b1f080 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj @@ -190,7 +190,6 @@ - diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters index 65e33e77fe..73acaf4edb 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters @@ -111,9 +111,6 @@ include\grpc++\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj index 1caed32bbd..9ff5b79692 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj @@ -190,7 +190,6 @@ - diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters index 153d10a656..babdf1ad61 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters @@ -114,9 +114,6 @@ include\grpc++\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen -- cgit v1.2.3 From 1399e466b0bc7cf8a7f86b256461a132229ecaf4 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Wed, 27 Jul 2016 20:31:55 -0700 Subject: removed codegen/time.h --- BUILD | 9 -- Makefile | 8 -- build.yaml | 1 - gRPC-Core.podspec | 2 - grpc.def | 42 +++---- grpc.gemspec | 2 - include/grpc++/impl/codegen/client_context.h | 1 - include/grpc++/impl/codegen/completion_queue.h | 3 +- include/grpc++/impl/codegen/core_codegen.h | 1 + .../grpc++/impl/codegen/core_codegen_interface.h | 1 + include/grpc++/impl/codegen/server_context.h | 1 - include/grpc++/impl/codegen/server_interface.h | 7 +- include/grpc++/impl/codegen/time.h | 4 +- include/grpc/impl/codegen/time.h | 108 ----------------- include/grpc/support/time.h | 68 ++++++++++- package.xml | 2 - src/core/lib/channel/handshaker.h | 1 - src/cpp/common/core_codegen.cc | 4 + src/ruby/ext/grpc/rb_grpc_imports.generated.c | 84 +++++++------- src/ruby/ext/grpc/rb_grpc_imports.generated.h | 128 ++++++++++----------- test/core/surface/public_headers_must_be_c89.c | 1 - test/cpp/codegen/codegen_test_full.cc | 1 + tools/doxygen/Doxyfile.c++ | 3 +- tools/doxygen/Doxyfile.c++.internal | 1 - tools/doxygen/Doxyfile.core | 4 +- tools/doxygen/Doxyfile.core.internal | 2 - tools/run_tests/sources_and_headers.json | 6 +- vsprojects/vcxproj/gpr/gpr.vcxproj | 1 - vsprojects/vcxproj/gpr/gpr.vcxproj.filters | 3 - vsprojects/vcxproj/grpc++/grpc++.vcxproj | 1 - vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters | 3 - .../grpc++_reflection/grpc++_reflection.vcxproj | 1 - .../grpc++_reflection.vcxproj.filters | 3 - .../grpc++_test_util/grpc++_test_util.vcxproj | 1 - .../grpc++_test_util.vcxproj.filters | 3 - .../grpc++_unsecure/grpc++_unsecure.vcxproj | 1 - .../grpc++_unsecure.vcxproj.filters | 3 - vsprojects/vcxproj/grpc/grpc.vcxproj | 1 - vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 3 - .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 1 - .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 3 - .../codegen_test_full/codegen_test_full.vcxproj | 1 - .../codegen_test_full.vcxproj.filters | 3 - .../codegen_test_minimal.vcxproj | 1 - .../codegen_test_minimal.vcxproj.filters | 3 - 45 files changed, 214 insertions(+), 317 deletions(-) delete mode 100644 include/grpc/impl/codegen/time.h (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index 48239488d3..84ce5b2433 100644 --- a/BUILD +++ b/BUILD @@ -143,7 +143,6 @@ cc_library( "include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_windows.h", - "include/grpc/impl/codegen/time.h", ], includes = [ "include", @@ -520,7 +519,6 @@ cc_library( "include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_windows.h", - "include/grpc/impl/codegen/time.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "include/grpc/census.h", @@ -877,7 +875,6 @@ cc_library( "include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_windows.h", - "include/grpc/impl/codegen/time.h", "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", @@ -1206,7 +1203,6 @@ cc_library( "include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_windows.h", - "include/grpc/impl/codegen/time.h", "include/grpc/census.h", ], includes = [ @@ -1364,7 +1360,6 @@ cc_library( "include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_windows.h", - "include/grpc/impl/codegen/time.h", ], includes = [ "include", @@ -1441,7 +1436,6 @@ cc_library( "include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_windows.h", - "include/grpc/impl/codegen/time.h", "include/grpc++/impl/codegen/config_protobuf.h", ], includes = [ @@ -1586,7 +1580,6 @@ cc_library( "include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_windows.h", - "include/grpc/impl/codegen/time.h", ], includes = [ "include", @@ -1751,7 +1744,6 @@ objc_library( "include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_windows.h", - "include/grpc/impl/codegen/time.h", "src/core/lib/profiling/timers.h", "src/core/lib/support/backoff.h", "src/core/lib/support/block_annotate.h", @@ -1987,7 +1979,6 @@ objc_library( "include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_windows.h", - "include/grpc/impl/codegen/time.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", "include/grpc/census.h", diff --git a/Makefile b/Makefile index 402294b549..ddbe15da3a 100644 --- a/Makefile +++ b/Makefile @@ -2450,7 +2450,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ - include/grpc/impl/codegen/time.h \ LIBGPR_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGPR_SRC)))) @@ -2728,7 +2727,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ - include/grpc/impl/codegen/time.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -2976,7 +2974,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ - include/grpc/impl/codegen/time.h \ include/grpc/grpc_cronet.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ @@ -3309,7 +3306,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ - include/grpc/impl/codegen/time.h \ include/grpc/census.h \ LIBGRPC_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_UNSECURE_SRC)))) @@ -3558,7 +3554,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ - include/grpc/impl/codegen/time.h \ LIBGRPC++_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_SRC)))) @@ -3682,7 +3677,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ - include/grpc/impl/codegen/time.h \ include/grpc++/impl/codegen/config_protobuf.h \ LIBGRPC++_REFLECTION_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_REFLECTION_SRC)))) @@ -3907,7 +3901,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ - include/grpc/impl/codegen/time.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpc++/impl/codegen/config_protobuf.h \ @@ -4088,7 +4081,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ - include/grpc/impl/codegen/time.h \ LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC)))) diff --git a/build.yaml b/build.yaml index 3113836a57..eb3a39a9a5 100644 --- a/build.yaml +++ b/build.yaml @@ -139,7 +139,6 @@ filegroups: - include/grpc/impl/codegen/sync_generic.h - include/grpc/impl/codegen/sync_posix.h - include/grpc/impl/codegen/sync_windows.h - - include/grpc/impl/codegen/time.h - name: grpc_base public_headers: - include/grpc/byte_buffer.h diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index dbc57865de..34c385cdb8 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -156,7 +156,6 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/sync_generic.h', 'include/grpc/impl/codegen/sync_posix.h', 'include/grpc/impl/codegen/sync_windows.h', - 'include/grpc/impl/codegen/time.h', 'include/grpc/byte_buffer.h', 'include/grpc/byte_buffer_reader.h', 'include/grpc/compression.h', @@ -181,7 +180,6 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/sync_generic.h', 'include/grpc/impl/codegen/sync_posix.h', 'include/grpc/impl/codegen/sync_windows.h', - 'include/grpc/impl/codegen/time.h', 'include/grpc/grpc_security.h', 'include/grpc/grpc_security_constants.h', 'include/grpc/census.h' diff --git a/grpc.def b/grpc.def index 456198d3fa..f264bf7624 100644 --- a/grpc.def +++ b/grpc.def @@ -190,27 +190,6 @@ EXPORTS gpr_stats_init gpr_stats_inc gpr_stats_read - gpr_time_0 - gpr_inf_future - gpr_inf_past - gpr_time_init - gpr_now - gpr_convert_clock_type - gpr_time_cmp - gpr_time_max - gpr_time_min - gpr_time_add - gpr_time_sub - gpr_time_from_micros - gpr_time_from_nanos - gpr_time_from_millis - gpr_time_from_seconds - gpr_time_from_minutes - gpr_time_from_hours - gpr_time_to_millis - gpr_time_similar - gpr_sleep_until - gpr_timespec_to_micros gpr_malloc gpr_free gpr_realloc @@ -270,3 +249,24 @@ EXPORTS gpr_thd_options_is_joinable gpr_thd_currentid gpr_thd_join + gpr_time_0 + gpr_inf_future + gpr_inf_past + gpr_time_init + gpr_now + gpr_convert_clock_type + gpr_time_cmp + gpr_time_max + gpr_time_min + gpr_time_add + gpr_time_sub + gpr_time_from_micros + gpr_time_from_nanos + gpr_time_from_millis + gpr_time_from_seconds + gpr_time_from_minutes + gpr_time_from_hours + gpr_time_to_millis + gpr_time_similar + gpr_sleep_until + gpr_timespec_to_micros diff --git a/grpc.gemspec b/grpc.gemspec index 099cbe1f33..bb2070b7b3 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -83,7 +83,6 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/sync_generic.h ) s.files += %w( include/grpc/impl/codegen/sync_posix.h ) s.files += %w( include/grpc/impl/codegen/sync_windows.h ) - s.files += %w( include/grpc/impl/codegen/time.h ) s.files += %w( src/core/lib/profiling/timers.h ) s.files += %w( src/core/lib/support/backoff.h ) s.files += %w( src/core/lib/support/block_annotate.h ) @@ -164,7 +163,6 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/sync_generic.h ) s.files += %w( include/grpc/impl/codegen/sync_posix.h ) s.files += %w( include/grpc/impl/codegen/sync_windows.h ) - s.files += %w( include/grpc/impl/codegen/time.h ) s.files += %w( include/grpc/grpc_security.h ) s.files += %w( include/grpc/grpc_security_constants.h ) s.files += %w( include/grpc/census.h ) diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h index 012bcc2bbe..d6596d402c 100644 --- a/include/grpc++/impl/codegen/client_context.h +++ b/include/grpc++/impl/codegen/client_context.h @@ -64,7 +64,6 @@ #include #include #include -#include struct census_context; struct grpc_call; diff --git a/include/grpc++/impl/codegen/completion_queue.h b/include/grpc++/impl/codegen/completion_queue.h index 03009e0561..2c22c3b354 100644 --- a/include/grpc++/impl/codegen/completion_queue.h +++ b/include/grpc++/impl/codegen/completion_queue.h @@ -52,7 +52,6 @@ #include #include #include -#include struct grpc_completion_queue; @@ -217,7 +216,7 @@ class CompletionQueue : private GrpcLibraryCodegen { /// Performs a single polling pluck on \a tag. /// \warning Must not be mixed with calls to \a Next. void TryPluck(CompletionQueueTag* tag) { - auto deadline = gpr_time_0(GPR_CLOCK_REALTIME); + auto deadline = g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME); auto ev = g_core_codegen_interface->grpc_completion_queue_pluck( cq_, tag, deadline, nullptr); if (ev.type == GRPC_QUEUE_TIMEOUT) return; diff --git a/include/grpc++/impl/codegen/core_codegen.h b/include/grpc++/impl/codegen/core_codegen.h index 9699abfb43..9ad5902763 100644 --- a/include/grpc++/impl/codegen/core_codegen.h +++ b/include/grpc++/impl/codegen/core_codegen.h @@ -75,6 +75,7 @@ class CoreCodegen : public CoreCodegenInterface { void grpc_metadata_array_destroy(grpc_metadata_array* array) GRPC_OVERRIDE; gpr_timespec gpr_inf_future(gpr_clock_type type) GRPC_OVERRIDE; + gpr_timespec gpr_time_0(gpr_clock_type type) GRPC_OVERRIDE; virtual const Status& ok() GRPC_OVERRIDE; virtual const Status& cancelled() GRPC_OVERRIDE; diff --git a/include/grpc++/impl/codegen/core_codegen_interface.h b/include/grpc++/impl/codegen/core_codegen_interface.h index 5ff885a074..24891ec23c 100644 --- a/include/grpc++/impl/codegen/core_codegen_interface.h +++ b/include/grpc++/impl/codegen/core_codegen_interface.h @@ -95,6 +95,7 @@ class CoreCodegenInterface { virtual const Status& cancelled() = 0; virtual gpr_timespec gpr_inf_future(gpr_clock_type type) = 0; + virtual gpr_timespec gpr_time_0(gpr_clock_type type) = 0; }; extern CoreCodegenInterface* g_core_codegen_interface; diff --git a/include/grpc++/impl/codegen/server_context.h b/include/grpc++/impl/codegen/server_context.h index cea13a513f..be8a69f448 100644 --- a/include/grpc++/impl/codegen/server_context.h +++ b/include/grpc++/impl/codegen/server_context.h @@ -43,7 +43,6 @@ #include #include #include -#include struct gpr_timespec; struct grpc_metadata; diff --git a/include/grpc++/impl/codegen/server_interface.h b/include/grpc++/impl/codegen/server_interface.h index 3a3e052d9e..1f1b714cbf 100644 --- a/include/grpc++/impl/codegen/server_interface.h +++ b/include/grpc++/impl/codegen/server_interface.h @@ -52,6 +52,8 @@ class ServerCredentials; class Service; class ThreadPoolInterface; +extern CoreCodegenInterface* g_core_codegen_interface; + /// Models a gRPC server. /// /// Servers are configured and started via \a grpc::ServerBuilder. @@ -78,7 +80,10 @@ class ServerInterface : public CallHook { /// All completion queue associated with the server (for example, for async /// serving) must be shutdown *after* this method has returned: /// See \a ServerBuilder::AddCompletionQueue for details. - void Shutdown() { ShutdownInternal(gpr_inf_future(GPR_CLOCK_MONOTONIC)); } + void Shutdown() { + ShutdownInternal( + g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_MONOTONIC)); + } /// Block waiting for all work to complete. /// diff --git a/include/grpc++/impl/codegen/time.h b/include/grpc++/impl/codegen/time.h index d9b19bce64..87c5112d0d 100644 --- a/include/grpc++/impl/codegen/time.h +++ b/include/grpc++/impl/codegen/time.h @@ -35,7 +35,7 @@ #define GRPCXX_IMPL_CODEGEN_TIME_H #include -#include +#include namespace grpc { @@ -79,7 +79,7 @@ class TimePoint { #include -#include +#include namespace grpc { diff --git a/include/grpc/impl/codegen/time.h b/include/grpc/impl/codegen/time.h deleted file mode 100644 index c7c476ce38..0000000000 --- a/include/grpc/impl/codegen/time.h +++ /dev/null @@ -1,108 +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_IMPL_CODEGEN_TIME_H -#define GRPC_IMPL_CODEGEN_TIME_H -/* Time support. - We use gpr_timespec, which is analogous to struct timespec. On some - machines, absolute times may be in local time. */ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Time constants. */ -GPRAPI gpr_timespec -gpr_time_0(gpr_clock_type type); /* The zero time interval. */ -GPRAPI gpr_timespec gpr_inf_future(gpr_clock_type type); /* The far future */ -GPRAPI gpr_timespec gpr_inf_past(gpr_clock_type type); /* The far past. */ - -#define GPR_MS_PER_SEC 1000 -#define GPR_US_PER_SEC 1000000 -#define GPR_NS_PER_SEC 1000000000 -#define GPR_NS_PER_MS 1000000 -#define GPR_NS_PER_US 1000 -#define GPR_US_PER_MS 1000 - -/* initialize time subsystem */ -GPRAPI void gpr_time_init(void); - -/* Return the current time measured from the given clocks epoch. */ -GPRAPI gpr_timespec gpr_now(gpr_clock_type clock); - -/* Convert a timespec from one clock to another */ -GPRAPI gpr_timespec gpr_convert_clock_type(gpr_timespec t, - gpr_clock_type target_clock); - -/* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b - respectively. */ -GPRAPI int gpr_time_cmp(gpr_timespec a, gpr_timespec b); - -GPRAPI gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b); -GPRAPI gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b); - -/* Add and subtract times. Calculations saturate at infinities. */ -GPRAPI gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b); -GPRAPI gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b); - -/* Return a timespec representing a given number of time units. INT64_MIN is - interpreted as gpr_inf_past, and INT64_MAX as gpr_inf_future. */ -GPRAPI gpr_timespec gpr_time_from_micros(int64_t x, gpr_clock_type clock_type); -GPRAPI gpr_timespec gpr_time_from_nanos(int64_t x, gpr_clock_type clock_type); -GPRAPI gpr_timespec gpr_time_from_millis(int64_t x, gpr_clock_type clock_type); -GPRAPI gpr_timespec gpr_time_from_seconds(int64_t x, gpr_clock_type clock_type); -GPRAPI gpr_timespec gpr_time_from_minutes(int64_t x, gpr_clock_type clock_type); -GPRAPI gpr_timespec gpr_time_from_hours(int64_t x, gpr_clock_type clock_type); - -GPRAPI int32_t gpr_time_to_millis(gpr_timespec timespec); - -/* Return 1 if two times are equal or within threshold of each other, - 0 otherwise */ -GPRAPI int gpr_time_similar(gpr_timespec a, gpr_timespec b, - gpr_timespec threshold); - -/* Sleep until at least 'until' - an absolute timeout */ -GPRAPI void gpr_sleep_until(gpr_timespec until); - -GPRAPI double gpr_timespec_to_micros(gpr_timespec t); - -#ifdef __cplusplus -} -#endif - -#endif /* GRPC_IMPL_CODEGEN_TIME_H */ diff --git a/include/grpc/support/time.h b/include/grpc/support/time.h index b3f2f8cd44..5b36dd8db5 100644 --- a/include/grpc/support/time.h +++ b/include/grpc/support/time.h @@ -34,6 +34,72 @@ #ifndef GRPC_SUPPORT_TIME_H #define GRPC_SUPPORT_TIME_H -#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Time constants. */ +GPRAPI gpr_timespec +gpr_time_0(gpr_clock_type type); /* The zero time interval. */ +GPRAPI gpr_timespec gpr_inf_future(gpr_clock_type type); /* The far future */ +GPRAPI gpr_timespec gpr_inf_past(gpr_clock_type type); /* The far past. */ + +#define GPR_MS_PER_SEC 1000 +#define GPR_US_PER_SEC 1000000 +#define GPR_NS_PER_SEC 1000000000 +#define GPR_NS_PER_MS 1000000 +#define GPR_NS_PER_US 1000 +#define GPR_US_PER_MS 1000 + +/* initialize time subsystem */ +GPRAPI void gpr_time_init(void); + +/* Return the current time measured from the given clocks epoch. */ +GPRAPI gpr_timespec gpr_now(gpr_clock_type clock); + +/* Convert a timespec from one clock to another */ +GPRAPI gpr_timespec gpr_convert_clock_type(gpr_timespec t, + gpr_clock_type target_clock); + +/* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b + respectively. */ +GPRAPI int gpr_time_cmp(gpr_timespec a, gpr_timespec b); + +GPRAPI gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b); +GPRAPI gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b); + +/* Add and subtract times. Calculations saturate at infinities. */ +GPRAPI gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b); +GPRAPI gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b); + +/* Return a timespec representing a given number of time units. INT64_MIN is + interpreted as gpr_inf_past, and INT64_MAX as gpr_inf_future. */ +GPRAPI gpr_timespec gpr_time_from_micros(int64_t x, gpr_clock_type clock_type); +GPRAPI gpr_timespec gpr_time_from_nanos(int64_t x, gpr_clock_type clock_type); +GPRAPI gpr_timespec gpr_time_from_millis(int64_t x, gpr_clock_type clock_type); +GPRAPI gpr_timespec gpr_time_from_seconds(int64_t x, gpr_clock_type clock_type); +GPRAPI gpr_timespec gpr_time_from_minutes(int64_t x, gpr_clock_type clock_type); +GPRAPI gpr_timespec gpr_time_from_hours(int64_t x, gpr_clock_type clock_type); + +GPRAPI int32_t gpr_time_to_millis(gpr_timespec timespec); + +/* Return 1 if two times are equal or within threshold of each other, + 0 otherwise */ +GPRAPI int gpr_time_similar(gpr_timespec a, gpr_timespec b, + gpr_timespec threshold); + +/* Sleep until at least 'until' - an absolute timeout */ +GPRAPI void gpr_sleep_until(gpr_timespec until); + +GPRAPI double gpr_timespec_to_micros(gpr_timespec t); + +#ifdef __cplusplus +} +#endif #endif /* GRPC_SUPPORT_TIME_H */ diff --git a/package.xml b/package.xml index 09b85d5d21..79f8e989a6 100644 --- a/package.xml +++ b/package.xml @@ -91,7 +91,6 @@ - @@ -172,7 +171,6 @@ - diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h index dfc469c417..ec0b966940 100644 --- a/src/core/lib/channel/handshaker.h +++ b/src/core/lib/channel/handshaker.h @@ -35,7 +35,6 @@ #define GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H #include -#include #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/endpoint.h" diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc index 14ba826de2..f51e31680d 100644 --- a/src/cpp/common/core_codegen.cc +++ b/src/cpp/common/core_codegen.cc @@ -131,6 +131,10 @@ gpr_timespec CoreCodegen::gpr_inf_future(gpr_clock_type type) { return ::gpr_inf_future(type); } +gpr_timespec CoreCodegen::gpr_time_0(gpr_clock_type type) { + return ::gpr_time_0(type); +} + void CoreCodegen::assert_fail(const char* failed_assertion) { gpr_log(GPR_ERROR, "assertion failed: %s", failed_assertion); abort(); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 2583ea86eb..e9f84fa7be 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -228,27 +228,6 @@ gpr_unref_type gpr_unref_import; gpr_stats_init_type gpr_stats_init_import; gpr_stats_inc_type gpr_stats_inc_import; gpr_stats_read_type gpr_stats_read_import; -gpr_time_0_type gpr_time_0_import; -gpr_inf_future_type gpr_inf_future_import; -gpr_inf_past_type gpr_inf_past_import; -gpr_time_init_type gpr_time_init_import; -gpr_now_type gpr_now_import; -gpr_convert_clock_type_type gpr_convert_clock_type_import; -gpr_time_cmp_type gpr_time_cmp_import; -gpr_time_max_type gpr_time_max_import; -gpr_time_min_type gpr_time_min_import; -gpr_time_add_type gpr_time_add_import; -gpr_time_sub_type gpr_time_sub_import; -gpr_time_from_micros_type gpr_time_from_micros_import; -gpr_time_from_nanos_type gpr_time_from_nanos_import; -gpr_time_from_millis_type gpr_time_from_millis_import; -gpr_time_from_seconds_type gpr_time_from_seconds_import; -gpr_time_from_minutes_type gpr_time_from_minutes_import; -gpr_time_from_hours_type gpr_time_from_hours_import; -gpr_time_to_millis_type gpr_time_to_millis_import; -gpr_time_similar_type gpr_time_similar_import; -gpr_sleep_until_type gpr_sleep_until_import; -gpr_timespec_to_micros_type gpr_timespec_to_micros_import; gpr_malloc_type gpr_malloc_import; gpr_free_type gpr_free_import; gpr_realloc_type gpr_realloc_import; @@ -308,6 +287,27 @@ gpr_thd_options_is_detached_type gpr_thd_options_is_detached_import; gpr_thd_options_is_joinable_type gpr_thd_options_is_joinable_import; gpr_thd_currentid_type gpr_thd_currentid_import; gpr_thd_join_type gpr_thd_join_import; +gpr_time_0_type gpr_time_0_import; +gpr_inf_future_type gpr_inf_future_import; +gpr_inf_past_type gpr_inf_past_import; +gpr_time_init_type gpr_time_init_import; +gpr_now_type gpr_now_import; +gpr_convert_clock_type_type gpr_convert_clock_type_import; +gpr_time_cmp_type gpr_time_cmp_import; +gpr_time_max_type gpr_time_max_import; +gpr_time_min_type gpr_time_min_import; +gpr_time_add_type gpr_time_add_import; +gpr_time_sub_type gpr_time_sub_import; +gpr_time_from_micros_type gpr_time_from_micros_import; +gpr_time_from_nanos_type gpr_time_from_nanos_import; +gpr_time_from_millis_type gpr_time_from_millis_import; +gpr_time_from_seconds_type gpr_time_from_seconds_import; +gpr_time_from_minutes_type gpr_time_from_minutes_import; +gpr_time_from_hours_type gpr_time_from_hours_import; +gpr_time_to_millis_type gpr_time_to_millis_import; +gpr_time_similar_type gpr_time_similar_import; +gpr_sleep_until_type gpr_sleep_until_import; +gpr_timespec_to_micros_type gpr_timespec_to_micros_import; void grpc_rb_load_imports(HMODULE library) { grpc_raw_byte_buffer_create_import = (grpc_raw_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_byte_buffer_create"); @@ -501,27 +501,6 @@ void grpc_rb_load_imports(HMODULE library) { gpr_stats_init_import = (gpr_stats_init_type) GetProcAddress(library, "gpr_stats_init"); gpr_stats_inc_import = (gpr_stats_inc_type) GetProcAddress(library, "gpr_stats_inc"); gpr_stats_read_import = (gpr_stats_read_type) GetProcAddress(library, "gpr_stats_read"); - gpr_time_0_import = (gpr_time_0_type) GetProcAddress(library, "gpr_time_0"); - gpr_inf_future_import = (gpr_inf_future_type) GetProcAddress(library, "gpr_inf_future"); - gpr_inf_past_import = (gpr_inf_past_type) GetProcAddress(library, "gpr_inf_past"); - gpr_time_init_import = (gpr_time_init_type) GetProcAddress(library, "gpr_time_init"); - gpr_now_import = (gpr_now_type) GetProcAddress(library, "gpr_now"); - gpr_convert_clock_type_import = (gpr_convert_clock_type_type) GetProcAddress(library, "gpr_convert_clock_type"); - gpr_time_cmp_import = (gpr_time_cmp_type) GetProcAddress(library, "gpr_time_cmp"); - gpr_time_max_import = (gpr_time_max_type) GetProcAddress(library, "gpr_time_max"); - gpr_time_min_import = (gpr_time_min_type) GetProcAddress(library, "gpr_time_min"); - gpr_time_add_import = (gpr_time_add_type) GetProcAddress(library, "gpr_time_add"); - gpr_time_sub_import = (gpr_time_sub_type) GetProcAddress(library, "gpr_time_sub"); - gpr_time_from_micros_import = (gpr_time_from_micros_type) GetProcAddress(library, "gpr_time_from_micros"); - gpr_time_from_nanos_import = (gpr_time_from_nanos_type) GetProcAddress(library, "gpr_time_from_nanos"); - gpr_time_from_millis_import = (gpr_time_from_millis_type) GetProcAddress(library, "gpr_time_from_millis"); - gpr_time_from_seconds_import = (gpr_time_from_seconds_type) GetProcAddress(library, "gpr_time_from_seconds"); - gpr_time_from_minutes_import = (gpr_time_from_minutes_type) GetProcAddress(library, "gpr_time_from_minutes"); - gpr_time_from_hours_import = (gpr_time_from_hours_type) GetProcAddress(library, "gpr_time_from_hours"); - gpr_time_to_millis_import = (gpr_time_to_millis_type) GetProcAddress(library, "gpr_time_to_millis"); - gpr_time_similar_import = (gpr_time_similar_type) GetProcAddress(library, "gpr_time_similar"); - gpr_sleep_until_import = (gpr_sleep_until_type) GetProcAddress(library, "gpr_sleep_until"); - gpr_timespec_to_micros_import = (gpr_timespec_to_micros_type) GetProcAddress(library, "gpr_timespec_to_micros"); gpr_malloc_import = (gpr_malloc_type) GetProcAddress(library, "gpr_malloc"); gpr_free_import = (gpr_free_type) GetProcAddress(library, "gpr_free"); gpr_realloc_import = (gpr_realloc_type) GetProcAddress(library, "gpr_realloc"); @@ -581,6 +560,27 @@ void grpc_rb_load_imports(HMODULE library) { gpr_thd_options_is_joinable_import = (gpr_thd_options_is_joinable_type) GetProcAddress(library, "gpr_thd_options_is_joinable"); gpr_thd_currentid_import = (gpr_thd_currentid_type) GetProcAddress(library, "gpr_thd_currentid"); gpr_thd_join_import = (gpr_thd_join_type) GetProcAddress(library, "gpr_thd_join"); + gpr_time_0_import = (gpr_time_0_type) GetProcAddress(library, "gpr_time_0"); + gpr_inf_future_import = (gpr_inf_future_type) GetProcAddress(library, "gpr_inf_future"); + gpr_inf_past_import = (gpr_inf_past_type) GetProcAddress(library, "gpr_inf_past"); + gpr_time_init_import = (gpr_time_init_type) GetProcAddress(library, "gpr_time_init"); + gpr_now_import = (gpr_now_type) GetProcAddress(library, "gpr_now"); + gpr_convert_clock_type_import = (gpr_convert_clock_type_type) GetProcAddress(library, "gpr_convert_clock_type"); + gpr_time_cmp_import = (gpr_time_cmp_type) GetProcAddress(library, "gpr_time_cmp"); + gpr_time_max_import = (gpr_time_max_type) GetProcAddress(library, "gpr_time_max"); + gpr_time_min_import = (gpr_time_min_type) GetProcAddress(library, "gpr_time_min"); + gpr_time_add_import = (gpr_time_add_type) GetProcAddress(library, "gpr_time_add"); + gpr_time_sub_import = (gpr_time_sub_type) GetProcAddress(library, "gpr_time_sub"); + gpr_time_from_micros_import = (gpr_time_from_micros_type) GetProcAddress(library, "gpr_time_from_micros"); + gpr_time_from_nanos_import = (gpr_time_from_nanos_type) GetProcAddress(library, "gpr_time_from_nanos"); + gpr_time_from_millis_import = (gpr_time_from_millis_type) GetProcAddress(library, "gpr_time_from_millis"); + gpr_time_from_seconds_import = (gpr_time_from_seconds_type) GetProcAddress(library, "gpr_time_from_seconds"); + gpr_time_from_minutes_import = (gpr_time_from_minutes_type) GetProcAddress(library, "gpr_time_from_minutes"); + gpr_time_from_hours_import = (gpr_time_from_hours_type) GetProcAddress(library, "gpr_time_from_hours"); + gpr_time_to_millis_import = (gpr_time_to_millis_type) GetProcAddress(library, "gpr_time_to_millis"); + gpr_time_similar_import = (gpr_time_similar_type) GetProcAddress(library, "gpr_time_similar"); + gpr_sleep_until_import = (gpr_sleep_until_type) GetProcAddress(library, "gpr_sleep_until"); + gpr_timespec_to_micros_import = (gpr_timespec_to_micros_type) GetProcAddress(library, "gpr_timespec_to_micros"); } #endif /* GPR_WINDOWS */ diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 9563e95e96..fccefb44bf 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include @@ -61,6 +60,7 @@ #include #include #include +#include typedef grpc_byte_buffer *(*grpc_raw_byte_buffer_create_type)(gpr_slice *slices, size_t nslices); extern grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import; @@ -635,69 +635,6 @@ extern gpr_stats_inc_type gpr_stats_inc_import; typedef intptr_t(*gpr_stats_read_type)(const gpr_stats_counter *c); extern gpr_stats_read_type gpr_stats_read_import; #define gpr_stats_read gpr_stats_read_import -typedef gpr_timespec(*gpr_time_0_type)(gpr_clock_type type); -extern gpr_time_0_type gpr_time_0_import; -#define gpr_time_0 gpr_time_0_import -typedef gpr_timespec(*gpr_inf_future_type)(gpr_clock_type type); -extern gpr_inf_future_type gpr_inf_future_import; -#define gpr_inf_future gpr_inf_future_import -typedef gpr_timespec(*gpr_inf_past_type)(gpr_clock_type type); -extern gpr_inf_past_type gpr_inf_past_import; -#define gpr_inf_past gpr_inf_past_import -typedef void(*gpr_time_init_type)(void); -extern gpr_time_init_type gpr_time_init_import; -#define gpr_time_init gpr_time_init_import -typedef gpr_timespec(*gpr_now_type)(gpr_clock_type clock); -extern gpr_now_type gpr_now_import; -#define gpr_now gpr_now_import -typedef gpr_timespec(*gpr_convert_clock_type_type)(gpr_timespec t, gpr_clock_type target_clock); -extern gpr_convert_clock_type_type gpr_convert_clock_type_import; -#define gpr_convert_clock_type gpr_convert_clock_type_import -typedef int(*gpr_time_cmp_type)(gpr_timespec a, gpr_timespec b); -extern gpr_time_cmp_type gpr_time_cmp_import; -#define gpr_time_cmp gpr_time_cmp_import -typedef gpr_timespec(*gpr_time_max_type)(gpr_timespec a, gpr_timespec b); -extern gpr_time_max_type gpr_time_max_import; -#define gpr_time_max gpr_time_max_import -typedef gpr_timespec(*gpr_time_min_type)(gpr_timespec a, gpr_timespec b); -extern gpr_time_min_type gpr_time_min_import; -#define gpr_time_min gpr_time_min_import -typedef gpr_timespec(*gpr_time_add_type)(gpr_timespec a, gpr_timespec b); -extern gpr_time_add_type gpr_time_add_import; -#define gpr_time_add gpr_time_add_import -typedef gpr_timespec(*gpr_time_sub_type)(gpr_timespec a, gpr_timespec b); -extern gpr_time_sub_type gpr_time_sub_import; -#define gpr_time_sub gpr_time_sub_import -typedef gpr_timespec(*gpr_time_from_micros_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_micros_type gpr_time_from_micros_import; -#define gpr_time_from_micros gpr_time_from_micros_import -typedef gpr_timespec(*gpr_time_from_nanos_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_nanos_type gpr_time_from_nanos_import; -#define gpr_time_from_nanos gpr_time_from_nanos_import -typedef gpr_timespec(*gpr_time_from_millis_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_millis_type gpr_time_from_millis_import; -#define gpr_time_from_millis gpr_time_from_millis_import -typedef gpr_timespec(*gpr_time_from_seconds_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_seconds_type gpr_time_from_seconds_import; -#define gpr_time_from_seconds gpr_time_from_seconds_import -typedef gpr_timespec(*gpr_time_from_minutes_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_minutes_type gpr_time_from_minutes_import; -#define gpr_time_from_minutes gpr_time_from_minutes_import -typedef gpr_timespec(*gpr_time_from_hours_type)(int64_t x, gpr_clock_type clock_type); -extern gpr_time_from_hours_type gpr_time_from_hours_import; -#define gpr_time_from_hours gpr_time_from_hours_import -typedef int32_t(*gpr_time_to_millis_type)(gpr_timespec timespec); -extern gpr_time_to_millis_type gpr_time_to_millis_import; -#define gpr_time_to_millis gpr_time_to_millis_import -typedef int(*gpr_time_similar_type)(gpr_timespec a, gpr_timespec b, gpr_timespec threshold); -extern gpr_time_similar_type gpr_time_similar_import; -#define gpr_time_similar gpr_time_similar_import -typedef void(*gpr_sleep_until_type)(gpr_timespec until); -extern gpr_sleep_until_type gpr_sleep_until_import; -#define gpr_sleep_until gpr_sleep_until_import -typedef double(*gpr_timespec_to_micros_type)(gpr_timespec t); -extern gpr_timespec_to_micros_type gpr_timespec_to_micros_import; -#define gpr_timespec_to_micros gpr_timespec_to_micros_import typedef void *(*gpr_malloc_type)(size_t size); extern gpr_malloc_type gpr_malloc_import; #define gpr_malloc gpr_malloc_import @@ -875,6 +812,69 @@ extern gpr_thd_currentid_type gpr_thd_currentid_import; typedef void(*gpr_thd_join_type)(gpr_thd_id t); extern gpr_thd_join_type gpr_thd_join_import; #define gpr_thd_join gpr_thd_join_import +typedef gpr_timespec(*gpr_time_0_type)(gpr_clock_type type); +extern gpr_time_0_type gpr_time_0_import; +#define gpr_time_0 gpr_time_0_import +typedef gpr_timespec(*gpr_inf_future_type)(gpr_clock_type type); +extern gpr_inf_future_type gpr_inf_future_import; +#define gpr_inf_future gpr_inf_future_import +typedef gpr_timespec(*gpr_inf_past_type)(gpr_clock_type type); +extern gpr_inf_past_type gpr_inf_past_import; +#define gpr_inf_past gpr_inf_past_import +typedef void(*gpr_time_init_type)(void); +extern gpr_time_init_type gpr_time_init_import; +#define gpr_time_init gpr_time_init_import +typedef gpr_timespec(*gpr_now_type)(gpr_clock_type clock); +extern gpr_now_type gpr_now_import; +#define gpr_now gpr_now_import +typedef gpr_timespec(*gpr_convert_clock_type_type)(gpr_timespec t, gpr_clock_type target_clock); +extern gpr_convert_clock_type_type gpr_convert_clock_type_import; +#define gpr_convert_clock_type gpr_convert_clock_type_import +typedef int(*gpr_time_cmp_type)(gpr_timespec a, gpr_timespec b); +extern gpr_time_cmp_type gpr_time_cmp_import; +#define gpr_time_cmp gpr_time_cmp_import +typedef gpr_timespec(*gpr_time_max_type)(gpr_timespec a, gpr_timespec b); +extern gpr_time_max_type gpr_time_max_import; +#define gpr_time_max gpr_time_max_import +typedef gpr_timespec(*gpr_time_min_type)(gpr_timespec a, gpr_timespec b); +extern gpr_time_min_type gpr_time_min_import; +#define gpr_time_min gpr_time_min_import +typedef gpr_timespec(*gpr_time_add_type)(gpr_timespec a, gpr_timespec b); +extern gpr_time_add_type gpr_time_add_import; +#define gpr_time_add gpr_time_add_import +typedef gpr_timespec(*gpr_time_sub_type)(gpr_timespec a, gpr_timespec b); +extern gpr_time_sub_type gpr_time_sub_import; +#define gpr_time_sub gpr_time_sub_import +typedef gpr_timespec(*gpr_time_from_micros_type)(int64_t x, gpr_clock_type clock_type); +extern gpr_time_from_micros_type gpr_time_from_micros_import; +#define gpr_time_from_micros gpr_time_from_micros_import +typedef gpr_timespec(*gpr_time_from_nanos_type)(int64_t x, gpr_clock_type clock_type); +extern gpr_time_from_nanos_type gpr_time_from_nanos_import; +#define gpr_time_from_nanos gpr_time_from_nanos_import +typedef gpr_timespec(*gpr_time_from_millis_type)(int64_t x, gpr_clock_type clock_type); +extern gpr_time_from_millis_type gpr_time_from_millis_import; +#define gpr_time_from_millis gpr_time_from_millis_import +typedef gpr_timespec(*gpr_time_from_seconds_type)(int64_t x, gpr_clock_type clock_type); +extern gpr_time_from_seconds_type gpr_time_from_seconds_import; +#define gpr_time_from_seconds gpr_time_from_seconds_import +typedef gpr_timespec(*gpr_time_from_minutes_type)(int64_t x, gpr_clock_type clock_type); +extern gpr_time_from_minutes_type gpr_time_from_minutes_import; +#define gpr_time_from_minutes gpr_time_from_minutes_import +typedef gpr_timespec(*gpr_time_from_hours_type)(int64_t x, gpr_clock_type clock_type); +extern gpr_time_from_hours_type gpr_time_from_hours_import; +#define gpr_time_from_hours gpr_time_from_hours_import +typedef int32_t(*gpr_time_to_millis_type)(gpr_timespec timespec); +extern gpr_time_to_millis_type gpr_time_to_millis_import; +#define gpr_time_to_millis gpr_time_to_millis_import +typedef int(*gpr_time_similar_type)(gpr_timespec a, gpr_timespec b, gpr_timespec threshold); +extern gpr_time_similar_type gpr_time_similar_import; +#define gpr_time_similar gpr_time_similar_import +typedef void(*gpr_sleep_until_type)(gpr_timespec until); +extern gpr_sleep_until_type gpr_sleep_until_import; +#define gpr_sleep_until gpr_sleep_until_import +typedef double(*gpr_timespec_to_micros_type)(gpr_timespec t); +extern gpr_timespec_to_micros_type gpr_timespec_to_micros_import; +#define gpr_timespec_to_micros gpr_timespec_to_micros_import void grpc_rb_load_imports(HMODULE library); diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index f9aaf59a67..ec901a1547 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -51,7 +51,6 @@ #include #include #include -#include #include #include #include diff --git a/test/cpp/codegen/codegen_test_full.cc b/test/cpp/codegen/codegen_test_full.cc index 4500540baf..d6e2416b55 100644 --- a/test/cpp/codegen/codegen_test_full.cc +++ b/test/cpp/codegen/codegen_test_full.cc @@ -32,6 +32,7 @@ */ #include +#include #include namespace grpc { diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index c18218d1a2..d7eab48bda 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -854,8 +854,7 @@ 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_windows.h \ -include/grpc/impl/codegen/time.h +include/grpc/impl/codegen/sync_windows.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index ac90a18e87..beab3e1e5d 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -855,7 +855,6 @@ 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_windows.h \ -include/grpc/impl/codegen/time.h \ include/grpc++/impl/codegen/core_codegen.h \ src/cpp/client/secure_credentials.h \ src/cpp/common/secure_auth_context.h \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 3e6d19f230..af07968f4f 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -784,7 +784,6 @@ 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_windows.h \ -include/grpc/impl/codegen/time.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -827,8 +826,7 @@ 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_windows.h \ -include/grpc/impl/codegen/time.h +include/grpc/impl/codegen/sync_windows.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index bc63c9418a..9c7335946c 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -784,7 +784,6 @@ 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_windows.h \ -include/grpc/impl/codegen/time.h \ include/grpc/grpc_security.h \ include/grpc/grpc_security_constants.h \ include/grpc/census.h \ @@ -1171,7 +1170,6 @@ 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_windows.h \ -include/grpc/impl/codegen/time.h \ src/core/lib/profiling/timers.h \ src/core/lib/support/backoff.h \ src/core/lib/support/block_annotate.h \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index a3ed76ffa8..295e877062 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -5664,8 +5664,7 @@ "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_windows.h", - "include/grpc/impl/codegen/time.h" + "include/grpc/impl/codegen/sync_windows.h" ], "language": "c", "name": "gpr_codegen", @@ -5681,8 +5680,7 @@ "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_windows.h", - "include/grpc/impl/codegen/time.h" + "include/grpc/impl/codegen/sync_windows.h" ], "third_party": false, "type": "filegroup" diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index 4b3383b38b..5df3434bb1 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -187,7 +187,6 @@ - diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index 45638be102..4bfef3e3e1 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -258,9 +258,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index 0878cbb46d..2538583d70 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -353,7 +353,6 @@ - diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index e92e43b9c4..e356826fdd 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -387,9 +387,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - diff --git a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj index 0cc3245a20..af509e7259 100644 --- a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj +++ b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj @@ -199,7 +199,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters index 8d0c9a8f0f..e40f42915e 100644 --- a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters @@ -171,9 +171,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc++\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj index b3f1df5bf7..8146f081b8 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj @@ -195,7 +195,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters index 23cbbfddc8..66f264e0cb 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters @@ -177,9 +177,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc++\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index cfb87d279e..28247a263a 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -353,7 +353,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index 22d19ffaec..2890126200 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -372,9 +372,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 6945ff5da3..cbe040426e 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -291,7 +291,6 @@ - diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index b7aefec905..d7ebb21571 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -636,9 +636,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index b68301c24c..f5a17653cf 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -282,7 +282,6 @@ - diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 2f86004440..5e0056937f 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -549,9 +549,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj index 6533b1f080..71894e03ed 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj @@ -208,7 +208,6 @@ - diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters index 73acaf4edb..eeff87762c 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters @@ -165,9 +165,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj index 9ff5b79692..f6f15c15fa 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj @@ -208,7 +208,6 @@ - diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters index babdf1ad61..2297d917a3 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters @@ -168,9 +168,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - -- cgit v1.2.3 From c79b0650d2eccb5d1af8512c7f3178a39a3df063 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Wed, 27 Jul 2016 21:11:58 -0700 Subject: removed codegen/log.h --- BUILD | 9 -- Makefile | 8 -- build.yaml | 1 - gRPC-Core.podspec | 2 - grpc.def | 10 +- grpc.gemspec | 2 - include/grpc++/impl/codegen/async_unary_call.h | 1 - include/grpc++/impl/codegen/client_context.h | 1 - include/grpc++/impl/codegen/grpc_library.h | 1 - include/grpc++/impl/codegen/proto_utils.h | 1 - include/grpc++/impl/codegen/sync_stream.h | 1 - include/grpc/impl/codegen/log.h | 118 --------------------- include/grpc/support/log.h | 81 +++++++++++++- package.xml | 2 - src/core/lib/channel/handshaker.c | 2 +- src/cpp/client/client_context.cc | 1 + src/cpp/common/core_codegen.cc | 2 +- src/ruby/ext/grpc/rb_grpc_imports.generated.c | 20 ++-- src/ruby/ext/grpc/rb_grpc_imports.generated.h | 32 +++--- test/core/surface/public_headers_must_be_c89.c | 1 - test/cpp/end2end/client_crash_test.cc | 1 + test/cpp/end2end/client_crash_test_server.cc | 2 + test/cpp/end2end/end2end_test.cc | 1 + test/cpp/end2end/mock_test.cc | 1 + test/cpp/end2end/server_crash_test.cc | 1 + test/cpp/end2end/server_crash_test_client.cc | 2 + test/cpp/end2end/shutdown_test.cc | 4 +- test/cpp/end2end/streaming_throughput_test.cc | 4 +- test/cpp/end2end/test_service_impl.cc | 3 +- test/cpp/interop/metrics_client.cc | 1 + test/cpp/interop/stress_interop_client.cc | 1 + test/cpp/interop/stress_test.cc | 1 + test/cpp/util/metrics_server.cc | 1 + test/cpp/util/test_credentials_provider.cc | 1 + tools/doxygen/Doxyfile.c++ | 1 - tools/doxygen/Doxyfile.c++.internal | 1 - tools/doxygen/Doxyfile.core | 2 - tools/doxygen/Doxyfile.core.internal | 2 - tools/run_tests/sources_and_headers.json | 2 - vsprojects/vcxproj/gpr/gpr.vcxproj | 1 - vsprojects/vcxproj/gpr/gpr.vcxproj.filters | 3 - vsprojects/vcxproj/grpc++/grpc++.vcxproj | 1 - vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters | 3 - .../grpc++_reflection/grpc++_reflection.vcxproj | 1 - .../grpc++_reflection.vcxproj.filters | 3 - .../grpc++_test_util/grpc++_test_util.vcxproj | 1 - .../grpc++_test_util.vcxproj.filters | 3 - .../grpc++_unsecure/grpc++_unsecure.vcxproj | 1 - .../grpc++_unsecure.vcxproj.filters | 3 - vsprojects/vcxproj/grpc/grpc.vcxproj | 1 - vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 3 - .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 1 - .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 3 - .../codegen_test_full/codegen_test_full.vcxproj | 1 - .../codegen_test_full.vcxproj.filters | 3 - .../codegen_test_minimal.vcxproj | 1 - .../codegen_test_minimal.vcxproj.filters | 3 - 57 files changed, 135 insertions(+), 229 deletions(-) delete mode 100644 include/grpc/impl/codegen/log.h (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index 84ce5b2433..92f22f2084 100644 --- a/BUILD +++ b/BUILD @@ -135,7 +135,6 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", @@ -511,7 +510,6 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", @@ -867,7 +865,6 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", @@ -1195,7 +1192,6 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", @@ -1352,7 +1348,6 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", @@ -1428,7 +1423,6 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", @@ -1572,7 +1566,6 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", @@ -1736,7 +1729,6 @@ objc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", @@ -1971,7 +1963,6 @@ objc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", diff --git a/Makefile b/Makefile index ddbe15da3a..04b8c642d1 100644 --- a/Makefile +++ b/Makefile @@ -2442,7 +2442,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.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 \ @@ -2719,7 +2718,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.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 \ @@ -2966,7 +2964,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.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 \ @@ -3298,7 +3295,6 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.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 \ @@ -3546,7 +3542,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.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 \ @@ -3669,7 +3664,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.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 \ @@ -3893,7 +3887,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.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 \ @@ -4073,7 +4066,6 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.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 \ diff --git a/build.yaml b/build.yaml index eb3a39a9a5..cb7da07c37 100644 --- a/build.yaml +++ b/build.yaml @@ -131,7 +131,6 @@ filegroups: - include/grpc/impl/codegen/atm_gcc_atomic.h - include/grpc/impl/codegen/atm_gcc_sync.h - include/grpc/impl/codegen/atm_windows.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 diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 34c385cdb8..e63829af07 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -148,7 +148,6 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/atm_gcc_atomic.h', 'include/grpc/impl/codegen/atm_gcc_sync.h', 'include/grpc/impl/codegen/atm_windows.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', @@ -172,7 +171,6 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/atm_gcc_atomic.h', 'include/grpc/impl/codegen/atm_gcc_sync.h', 'include/grpc/impl/codegen/atm_windows.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', diff --git a/grpc.def b/grpc.def index f264bf7624..bca8648253 100644 --- a/grpc.def +++ b/grpc.def @@ -133,11 +133,6 @@ EXPORTS grpc_server_add_secure_http2_port grpc_call_set_credentials grpc_server_credentials_set_auth_metadata_processor - gpr_log - gpr_log_message - gpr_set_log_verbosity - gpr_log_verbosity_init - gpr_set_log_function gpr_slice_ref gpr_slice_unref gpr_slice_new @@ -233,6 +228,11 @@ EXPORTS gpr_histogram_merge_contents gpr_join_host_port gpr_split_host_port + gpr_log + gpr_log_message + gpr_set_log_verbosity + gpr_log_verbosity_init + gpr_set_log_function gpr_format_message gpr_strdup gpr_asprintf diff --git a/grpc.gemspec b/grpc.gemspec index bb2070b7b3..a9f1d026e0 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -75,7 +75,6 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) s.files += %w( include/grpc/impl/codegen/atm_windows.h ) - s.files += %w( include/grpc/impl/codegen/log.h ) s.files += %w( include/grpc/impl/codegen/port_platform.h ) s.files += %w( include/grpc/impl/codegen/slice.h ) s.files += %w( include/grpc/impl/codegen/slice_buffer.h ) @@ -155,7 +154,6 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) s.files += %w( include/grpc/impl/codegen/atm_windows.h ) - s.files += %w( include/grpc/impl/codegen/log.h ) s.files += %w( include/grpc/impl/codegen/port_platform.h ) s.files += %w( include/grpc/impl/codegen/slice.h ) s.files += %w( include/grpc/impl/codegen/slice_buffer.h ) diff --git a/include/grpc++/impl/codegen/async_unary_call.h b/include/grpc++/impl/codegen/async_unary_call.h index 05681e2242..96f91eaf76 100644 --- a/include/grpc++/impl/codegen/async_unary_call.h +++ b/include/grpc++/impl/codegen/async_unary_call.h @@ -40,7 +40,6 @@ #include #include #include -#include namespace grpc { diff --git a/include/grpc++/impl/codegen/client_context.h b/include/grpc++/impl/codegen/client_context.h index d6596d402c..3467ab14c2 100644 --- a/include/grpc++/impl/codegen/client_context.h +++ b/include/grpc++/impl/codegen/client_context.h @@ -62,7 +62,6 @@ #include #include #include -#include #include struct census_context; diff --git a/include/grpc++/impl/codegen/grpc_library.h b/include/grpc++/impl/codegen/grpc_library.h index 3cdc6f3f7c..2b11aff214 100644 --- a/include/grpc++/impl/codegen/grpc_library.h +++ b/include/grpc++/impl/codegen/grpc_library.h @@ -35,7 +35,6 @@ #define GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H #include -#include namespace grpc { diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h index 5b9551c26b..d2e0f6fcdd 100644 --- a/include/grpc++/impl/codegen/proto_utils.h +++ b/include/grpc++/impl/codegen/proto_utils.h @@ -42,7 +42,6 @@ #include #include #include -#include #include namespace grpc { diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h index cbfa410699..121c84cc18 100644 --- a/include/grpc++/impl/codegen/sync_stream.h +++ b/include/grpc++/impl/codegen/sync_stream.h @@ -42,7 +42,6 @@ #include #include #include -#include namespace grpc { diff --git a/include/grpc/impl/codegen/log.h b/include/grpc/impl/codegen/log.h deleted file mode 100644 index e5010c29da..0000000000 --- a/include/grpc/impl/codegen/log.h +++ /dev/null @@ -1,118 +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_IMPL_CODEGEN_LOG_H -#define GRPC_IMPL_CODEGEN_LOG_H - -#include -#include -#include /* for abort() */ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* GPR log API. - - Usage (within grpc): - - int argument1 = 3; - char* argument2 = "hello"; - gpr_log(GPR_DEBUG, "format string %d", argument1); - gpr_log(GPR_INFO, "hello world"); - gpr_log(GPR_ERROR, "%d %s!!", argument1, argument2); */ - -/* The severity of a log message - use the #defines below when calling into - gpr_log to additionally supply file and line data */ -typedef enum gpr_log_severity { - GPR_LOG_SEVERITY_DEBUG, - GPR_LOG_SEVERITY_INFO, - GPR_LOG_SEVERITY_ERROR -} gpr_log_severity; - -#define GPR_LOG_VERBOSITY_UNSET -1 - -/* Returns a string representation of the log severity */ -const char *gpr_log_severity_string(gpr_log_severity severity); - -/* Macros to build log contexts at various severity levels */ -#define GPR_DEBUG __FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG -#define GPR_INFO __FILE__, __LINE__, GPR_LOG_SEVERITY_INFO -#define GPR_ERROR __FILE__, __LINE__, GPR_LOG_SEVERITY_ERROR - -/* Log a message. It's advised to use GPR_xxx above to generate the context - * for each message */ -GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, - const char *format, ...) GPRC_PRINT_FORMAT_CHECK(4, 5); - -GPRAPI void gpr_log_message(const char *file, int line, - gpr_log_severity severity, const char *message); - -/* Set global log verbosity */ -GPRAPI void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print); - -GPRAPI void gpr_log_verbosity_init(); - -/* Log overrides: applications can use this API to intercept logging calls - and use their own implementations */ - -typedef struct { - const char *file; - int line; - gpr_log_severity severity; - const char *message; -} gpr_log_func_args; - -typedef void (*gpr_log_func)(gpr_log_func_args *args); -GPRAPI void gpr_set_log_function(gpr_log_func func); - -/* abort() the process if x is zero, having written a line to the log. - - Intended for internal invariants. If the error can be recovered from, - without the possibility of corruption, or might best be reflected via - an exception in a higher-level language, consider returning error code. */ -#define GPR_ASSERT(x) \ - do { \ - if (!(x)) { \ - gpr_log(GPR_ERROR, "assertion failed: %s", #x); \ - abort(); \ - } \ - } while (0) - -#ifdef __cplusplus -} -#endif - -#endif /* GRPC_IMPL_CODEGEN_LOG_H */ diff --git a/include/grpc/support/log.h b/include/grpc/support/log.h index 3fdba04943..5acf17fc2c 100644 --- a/include/grpc/support/log.h +++ b/include/grpc/support/log.h @@ -34,6 +34,85 @@ #ifndef GRPC_SUPPORT_LOG_H #define GRPC_SUPPORT_LOG_H -#include +#include +#include +#include /* for abort() */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* GPR log API. + + Usage (within grpc): + + int argument1 = 3; + char* argument2 = "hello"; + gpr_log(GPR_DEBUG, "format string %d", argument1); + gpr_log(GPR_INFO, "hello world"); + gpr_log(GPR_ERROR, "%d %s!!", argument1, argument2); */ + +/* The severity of a log message - use the #defines below when calling into + gpr_log to additionally supply file and line data */ +typedef enum gpr_log_severity { + GPR_LOG_SEVERITY_DEBUG, + GPR_LOG_SEVERITY_INFO, + GPR_LOG_SEVERITY_ERROR +} gpr_log_severity; + +#define GPR_LOG_VERBOSITY_UNSET -1 + +/* Returns a string representation of the log severity */ +const char *gpr_log_severity_string(gpr_log_severity severity); + +/* Macros to build log contexts at various severity levels */ +#define GPR_DEBUG __FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG +#define GPR_INFO __FILE__, __LINE__, GPR_LOG_SEVERITY_INFO +#define GPR_ERROR __FILE__, __LINE__, GPR_LOG_SEVERITY_ERROR + +/* Log a message. It's advised to use GPR_xxx above to generate the context + * for each message */ +GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, + const char *format, ...) GPRC_PRINT_FORMAT_CHECK(4, 5); + +GPRAPI void gpr_log_message(const char *file, int line, + gpr_log_severity severity, const char *message); + +/* Set global log verbosity */ +GPRAPI void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print); + +GPRAPI void gpr_log_verbosity_init(); + +/* Log overrides: applications can use this API to intercept logging calls + and use their own implementations */ + +typedef struct { + const char *file; + int line; + gpr_log_severity severity; + const char *message; +} gpr_log_func_args; + +typedef void (*gpr_log_func)(gpr_log_func_args *args); +GPRAPI void gpr_set_log_function(gpr_log_func func); + +/* abort() the process if x is zero, having written a line to the log. + + Intended for internal invariants. If the error can be recovered from, + without the possibility of corruption, or might best be reflected via + an exception in a higher-level language, consider returning error code. */ +#define GPR_ASSERT(x) \ + do { \ + if (!(x)) { \ + gpr_log(GPR_ERROR, "assertion failed: %s", #x); \ + abort(); \ + } \ + } while (0) + +#ifdef __cplusplus +} +#endif #endif /* GRPC_SUPPORT_LOG_H */ diff --git a/package.xml b/package.xml index 79f8e989a6..59f733e6da 100644 --- a/package.xml +++ b/package.xml @@ -83,7 +83,6 @@ - @@ -163,7 +162,6 @@ - diff --git a/src/core/lib/channel/handshaker.c b/src/core/lib/channel/handshaker.c index b5638e4202..1badba9069 100644 --- a/src/core/lib/channel/handshaker.c +++ b/src/core/lib/channel/handshaker.c @@ -33,8 +33,8 @@ #include -#include #include +#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index 0ba77a5057..20df384a6f 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include #include diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc index f51e31680d..c64f6514ab 100644 --- a/src/cpp/common/core_codegen.cc +++ b/src/cpp/common/core_codegen.cc @@ -39,8 +39,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index e9f84fa7be..d0236f13ca 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -171,11 +171,6 @@ grpc_ssl_server_credentials_create_ex_type grpc_ssl_server_credentials_create_ex grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import; grpc_call_set_credentials_type grpc_call_set_credentials_import; grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import; -gpr_log_type gpr_log_import; -gpr_log_message_type gpr_log_message_import; -gpr_set_log_verbosity_type gpr_set_log_verbosity_import; -gpr_log_verbosity_init_type gpr_log_verbosity_init_import; -gpr_set_log_function_type gpr_set_log_function_import; gpr_slice_ref_type gpr_slice_ref_import; gpr_slice_unref_type gpr_slice_unref_import; gpr_slice_new_type gpr_slice_new_import; @@ -271,6 +266,11 @@ gpr_histogram_get_contents_type gpr_histogram_get_contents_import; gpr_histogram_merge_contents_type gpr_histogram_merge_contents_import; gpr_join_host_port_type gpr_join_host_port_import; gpr_split_host_port_type gpr_split_host_port_import; +gpr_log_type gpr_log_import; +gpr_log_message_type gpr_log_message_import; +gpr_set_log_verbosity_type gpr_set_log_verbosity_import; +gpr_log_verbosity_init_type gpr_log_verbosity_init_import; +gpr_set_log_function_type gpr_set_log_function_import; gpr_format_message_type gpr_format_message_import; gpr_strdup_type gpr_strdup_import; gpr_asprintf_type gpr_asprintf_import; @@ -444,11 +444,6 @@ void grpc_rb_load_imports(HMODULE library) { grpc_server_add_secure_http2_port_import = (grpc_server_add_secure_http2_port_type) GetProcAddress(library, "grpc_server_add_secure_http2_port"); grpc_call_set_credentials_import = (grpc_call_set_credentials_type) GetProcAddress(library, "grpc_call_set_credentials"); grpc_server_credentials_set_auth_metadata_processor_import = (grpc_server_credentials_set_auth_metadata_processor_type) GetProcAddress(library, "grpc_server_credentials_set_auth_metadata_processor"); - gpr_log_import = (gpr_log_type) GetProcAddress(library, "gpr_log"); - gpr_log_message_import = (gpr_log_message_type) GetProcAddress(library, "gpr_log_message"); - gpr_set_log_verbosity_import = (gpr_set_log_verbosity_type) GetProcAddress(library, "gpr_set_log_verbosity"); - gpr_log_verbosity_init_import = (gpr_log_verbosity_init_type) GetProcAddress(library, "gpr_log_verbosity_init"); - gpr_set_log_function_import = (gpr_set_log_function_type) GetProcAddress(library, "gpr_set_log_function"); gpr_slice_ref_import = (gpr_slice_ref_type) GetProcAddress(library, "gpr_slice_ref"); gpr_slice_unref_import = (gpr_slice_unref_type) GetProcAddress(library, "gpr_slice_unref"); gpr_slice_new_import = (gpr_slice_new_type) GetProcAddress(library, "gpr_slice_new"); @@ -544,6 +539,11 @@ void grpc_rb_load_imports(HMODULE library) { gpr_histogram_merge_contents_import = (gpr_histogram_merge_contents_type) GetProcAddress(library, "gpr_histogram_merge_contents"); gpr_join_host_port_import = (gpr_join_host_port_type) GetProcAddress(library, "gpr_join_host_port"); gpr_split_host_port_import = (gpr_split_host_port_type) GetProcAddress(library, "gpr_split_host_port"); + gpr_log_import = (gpr_log_type) GetProcAddress(library, "gpr_log"); + gpr_log_message_import = (gpr_log_message_type) GetProcAddress(library, "gpr_log_message"); + gpr_set_log_verbosity_import = (gpr_set_log_verbosity_type) GetProcAddress(library, "gpr_set_log_verbosity"); + gpr_log_verbosity_init_import = (gpr_log_verbosity_init_type) GetProcAddress(library, "gpr_log_verbosity_init"); + gpr_set_log_function_import = (gpr_set_log_function_type) GetProcAddress(library, "gpr_set_log_function"); gpr_format_message_import = (gpr_format_message_type) GetProcAddress(library, "gpr_format_message"); gpr_strdup_import = (gpr_strdup_type) GetProcAddress(library, "gpr_strdup"); gpr_asprintf_import = (gpr_asprintf_type) GetProcAddress(library, "gpr_asprintf"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index fccefb44bf..f99e9c4429 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -56,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -464,21 +464,6 @@ extern grpc_call_set_credentials_type grpc_call_set_credentials_import; typedef void(*grpc_server_credentials_set_auth_metadata_processor_type)(grpc_server_credentials *creds, grpc_auth_metadata_processor processor); extern grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import; #define grpc_server_credentials_set_auth_metadata_processor grpc_server_credentials_set_auth_metadata_processor_import -typedef void(*gpr_log_type)(const char *file, int line, gpr_log_severity severity, const char *format, ...) GPRC_PRINT_FORMAT_CHECK(4, 5); -extern gpr_log_type gpr_log_import; -#define gpr_log gpr_log_import -typedef void(*gpr_log_message_type)(const char *file, int line, gpr_log_severity severity, const char *message); -extern gpr_log_message_type gpr_log_message_import; -#define gpr_log_message gpr_log_message_import -typedef void(*gpr_set_log_verbosity_type)(gpr_log_severity min_severity_to_print); -extern gpr_set_log_verbosity_type gpr_set_log_verbosity_import; -#define gpr_set_log_verbosity gpr_set_log_verbosity_import -typedef void(*gpr_log_verbosity_init_type)(); -extern gpr_log_verbosity_init_type gpr_log_verbosity_init_import; -#define gpr_log_verbosity_init gpr_log_verbosity_init_import -typedef void(*gpr_set_log_function_type)(gpr_log_func func); -extern gpr_set_log_function_type gpr_set_log_function_import; -#define gpr_set_log_function gpr_set_log_function_import typedef gpr_slice(*gpr_slice_ref_type)(gpr_slice s); extern gpr_slice_ref_type gpr_slice_ref_import; #define gpr_slice_ref gpr_slice_ref_import @@ -764,6 +749,21 @@ extern gpr_join_host_port_type gpr_join_host_port_import; typedef int(*gpr_split_host_port_type)(const char *name, char **host, char **port); extern gpr_split_host_port_type gpr_split_host_port_import; #define gpr_split_host_port gpr_split_host_port_import +typedef void(*gpr_log_type)(const char *file, int line, gpr_log_severity severity, const char *format, ...) GPRC_PRINT_FORMAT_CHECK(4, 5); +extern gpr_log_type gpr_log_import; +#define gpr_log gpr_log_import +typedef void(*gpr_log_message_type)(const char *file, int line, gpr_log_severity severity, const char *message); +extern gpr_log_message_type gpr_log_message_import; +#define gpr_log_message gpr_log_message_import +typedef void(*gpr_set_log_verbosity_type)(gpr_log_severity min_severity_to_print); +extern gpr_set_log_verbosity_type gpr_set_log_verbosity_import; +#define gpr_set_log_verbosity gpr_set_log_verbosity_import +typedef void(*gpr_log_verbosity_init_type)(); +extern gpr_log_verbosity_init_type gpr_log_verbosity_init_import; +#define gpr_log_verbosity_init gpr_log_verbosity_init_import +typedef void(*gpr_set_log_function_type)(gpr_log_func func); +extern gpr_set_log_function_type gpr_set_log_function_import; +#define gpr_set_log_function gpr_set_log_function_import typedef char *(*gpr_format_message_type)(int messageid); extern gpr_format_message_type gpr_format_message_import; #define gpr_format_message gpr_format_message_import diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index ec901a1547..9eadb12aba 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc index 30b04fb9b9..c452ad2beb 100644 --- a/test/cpp/end2end/client_crash_test.cc +++ b/test/cpp/end2end/client_crash_test.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include diff --git a/test/cpp/end2end/client_crash_test_server.cc b/test/cpp/end2end/client_crash_test_server.cc index 9568ca26be..6e1457407c 100644 --- a/test/cpp/end2end/client_crash_test_server.cc +++ b/test/cpp/end2end/client_crash_test_server.cc @@ -39,6 +39,8 @@ #include #include #include +#include + #include "src/proto/grpc/testing/echo.grpc.pb.h" DEFINE_string(address, "", "Address to bind to"); diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 46a58d3ac3..af706a90a0 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc index 0ace5d9418..f1e6aac36a 100644 --- a/test/cpp/end2end/mock_test.cc +++ b/test/cpp/end2end/mock_test.cc @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc index e447360276..16a5fa2322 100644 --- a/test/cpp/end2end/server_crash_test.cc +++ b/test/cpp/end2end/server_crash_test.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include diff --git a/test/cpp/end2end/server_crash_test_client.cc b/test/cpp/end2end/server_crash_test_client.cc index ece948d5a7..10a251c952 100644 --- a/test/cpp/end2end/server_crash_test_client.cc +++ b/test/cpp/end2end/server_crash_test_client.cc @@ -40,6 +40,8 @@ #include #include #include +#include + #include "src/proto/grpc/testing/echo.grpc.pb.h" DEFINE_string(address, "", "Address to connect to"); diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc index 3f98de6db7..4cba3b1c81 100644 --- a/test/cpp/end2end/shutdown_test.cc +++ b/test/cpp/end2end/shutdown_test.cc @@ -33,6 +33,8 @@ #include +#include + #include #include #include @@ -40,8 +42,8 @@ #include #include #include +#include #include -#include #include "src/core/lib/support/env.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" diff --git a/test/cpp/end2end/streaming_throughput_test.cc b/test/cpp/end2end/streaming_throughput_test.cc index 9e82c30701..fbef761ca9 100644 --- a/test/cpp/end2end/streaming_throughput_test.cc +++ b/test/cpp/end2end/streaming_throughput_test.cc @@ -35,6 +35,8 @@ #include #include +#include + #include #include #include @@ -45,9 +47,9 @@ #include #include #include +#include #include #include -#include #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc index 52abd80d69..2de344efd5 100644 --- a/test/cpp/end2end/test_service_impl.cc +++ b/test/cpp/end2end/test_service_impl.cc @@ -38,7 +38,8 @@ #include #include -#include +#include + #include #include "src/proto/grpc/testing/echo.grpc.pb.h" diff --git a/test/cpp/interop/metrics_client.cc b/test/cpp/interop/metrics_client.cc index 179de30805..9d5212e9d5 100644 --- a/test/cpp/interop/metrics_client.cc +++ b/test/cpp/interop/metrics_client.cc @@ -36,6 +36,7 @@ #include #include +#include #include "src/proto/grpc/testing/metrics.grpc.pb.h" #include "src/proto/grpc/testing/metrics.pb.h" diff --git a/test/cpp/interop/stress_interop_client.cc b/test/cpp/interop/stress_interop_client.cc index 1d5fc80cf2..0ea71e4cf4 100644 --- a/test/cpp/interop/stress_interop_client.cc +++ b/test/cpp/interop/stress_interop_client.cc @@ -38,6 +38,7 @@ #include #include +#include #include "test/cpp/interop/interop_client.h" #include "test/cpp/util/metrics_server.h" diff --git a/test/cpp/interop/stress_test.cc b/test/cpp/interop/stress_test.cc index 7787931900..5647cb5531 100644 --- a/test/cpp/interop/stress_test.cc +++ b/test/cpp/interop/stress_test.cc @@ -41,6 +41,7 @@ #include #include #include +#include #include #include "src/proto/grpc/testing/metrics.grpc.pb.h" diff --git a/test/cpp/util/metrics_server.cc b/test/cpp/util/metrics_server.cc index 1c7cd6382a..9296d6515e 100644 --- a/test/cpp/util/metrics_server.cc +++ b/test/cpp/util/metrics_server.cc @@ -35,6 +35,7 @@ #include #include +#include #include "src/proto/grpc/testing/metrics.grpc.pb.h" #include "src/proto/grpc/testing/metrics.pb.h" diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc index 6e68f59e6a..ca15f29795 100644 --- a/test/cpp/util/test_credentials_provider.cc +++ b/test/cpp/util/test_credentials_provider.cc @@ -37,6 +37,7 @@ #include #include +#include #include #include "test/core/end2end/data/ssl_test_data.h" diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index d7eab48bda..27eecc3528 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -847,7 +847,6 @@ 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_windows.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 \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index beab3e1e5d..bf49c0354e 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -847,7 +847,6 @@ 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_windows.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 \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index af07968f4f..2a3f200507 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -776,7 +776,6 @@ 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_windows.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 \ @@ -819,7 +818,6 @@ 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_windows.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 \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 9c7335946c..47b75f2b6e 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -776,7 +776,6 @@ 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_windows.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 \ @@ -1162,7 +1161,6 @@ 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_windows.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 \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 295e877062..80c67ce2af 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -5657,7 +5657,6 @@ "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", @@ -5673,7 +5672,6 @@ "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.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", diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index 5df3434bb1..df12d455ff 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -179,7 +179,6 @@ - diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index 4bfef3e3e1..636fd96958 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -234,9 +234,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index 2538583d70..ac69a3c3b5 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -345,7 +345,6 @@ - diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index e356826fdd..2e50ff5514 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -363,9 +363,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj index af509e7259..b87c3543bb 100644 --- a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj +++ b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj @@ -191,7 +191,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters index e40f42915e..5a12bae437 100644 --- a/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_reflection/grpc++_reflection.vcxproj.filters @@ -147,9 +147,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj index 8146f081b8..ba6b0e41b0 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj @@ -187,7 +187,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters index 66f264e0cb..75f269c680 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters @@ -153,9 +153,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index 28247a263a..c99e47b942 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -345,7 +345,6 @@ - diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index 2890126200..45bdc496ab 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -348,9 +348,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index cbe040426e..53dd95ec5d 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -283,7 +283,6 @@ - diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index d7ebb21571..4dcf2292cd 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -612,9 +612,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index f5a17653cf..839882066f 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -274,7 +274,6 @@ - diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 5e0056937f..69963d21e7 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -525,9 +525,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj index 71894e03ed..28f6416a83 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj @@ -200,7 +200,6 @@ - diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters index eeff87762c..9ab33e16d2 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters @@ -141,9 +141,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj index f6f15c15fa..ffbdf4b160 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj @@ -200,7 +200,6 @@ - diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters index 2297d917a3..342d3aab46 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters @@ -144,9 +144,6 @@ include\grpc\impl\codegen - - include\grpc\impl\codegen - include\grpc\impl\codegen -- cgit v1.2.3 From ce8f977593dc111e9c1516accbbb88913812090f Mon Sep 17 00:00:00 2001 From: Robbie Shade Date: Mon, 1 Aug 2016 16:06:00 -0400 Subject: Call orphan_cb before FD shutdown --- src/core/lib/iomgr/udp_server.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c index 48032412a2..12e929fa6a 100644 --- a/src/core/lib/iomgr/udp_server.c +++ b/src/core/lib/iomgr/udp_server.c @@ -171,6 +171,8 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) { sp->destroyed_closure.cb = destroyed_port; sp->destroyed_closure.cb_arg = s; + /* Call the orphan_cb to signal that the FD is about to be closed and + * should no longer be used. */ GPR_ASSERT(sp->orphan_cb); sp->orphan_cb(sp->emfd); @@ -197,6 +199,11 @@ void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s, /* shutdown all fd's */ if (s->active_ports) { for (i = 0; i < s->nports; i++) { + /* Call the orphan_cb to signal that the FD is about to be closed and + * should no longer be used. */ + GPR_ASSERT(sp->orphan_cb); + sp->orphan_cb(sp->emfd); + grpc_fd_shutdown(exec_ctx, s->ports[i].emfd); } gpr_mu_unlock(&s->mu); -- cgit v1.2.3 From 26f90888d6d98322974a75dc8938dc070edea4c5 Mon Sep 17 00:00:00 2001 From: Robbie Shade Date: Tue, 2 Aug 2016 15:26:00 -0400 Subject: Remove GRPC_NEED_UDP ifdefs --- src/core/lib/iomgr/udp_server.c | 2 -- test/core/iomgr/udp_server_test.c | 8 -------- 2 files changed, 10 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c index 48032412a2..f68288169b 100644 --- a/src/core/lib/iomgr/udp_server.c +++ b/src/core/lib/iomgr/udp_server.c @@ -38,7 +38,6 @@ #include -#ifdef GRPC_NEED_UDP #ifdef GPR_POSIX_SOCKET #include "src/core/lib/iomgr/udp_server.h" @@ -439,4 +438,3 @@ void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s, } #endif -#endif diff --git a/test/core/iomgr/udp_server_test.c b/test/core/iomgr/udp_server_test.c index a959a7e07f..2a30427504 100644 --- a/test/core/iomgr/udp_server_test.c +++ b/test/core/iomgr/udp_server_test.c @@ -48,8 +48,6 @@ #include "src/core/lib/iomgr/iomgr.h" #include "test/core/util/test_config.h" -#ifdef GRPC_NEED_UDP - #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x) static grpc_pollset *g_pollset; @@ -229,9 +227,3 @@ int main(int argc, char **argv) { grpc_iomgr_shutdown(); return 0; } - -#else - -int main(int argc, char **argv) { return 0; } - -#endif -- cgit v1.2.3 From 292b7cb3e14fa7cf51e683deefb05267c01f3472 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 4 Aug 2016 11:34:01 -0700 Subject: clang-format --- src/core/ext/transport/chttp2/transport/parsing.c | 4 ++-- src/core/lib/iomgr/workqueue_posix.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index cd128c3310..0e6d579ba9 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -87,8 +87,8 @@ void grpc_chttp2_prepare_to_read( transport_global->settings[GRPC_SENT_SETTINGS], sizeof(transport_parsing->last_sent_settings)); transport_parsing->max_frame_size = - transport_global - ->settings[GRPC_ACKED_SETTINGS][GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]; + transport_global->settings[GRPC_ACKED_SETTINGS] + [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]; /* update the parsing view of incoming window */ while (grpc_chttp2_list_pop_unannounced_incoming_window_available( diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c index 289c7a2fe2..ecfea68f56 100644 --- a/src/core/lib/iomgr/workqueue_posix.c +++ b/src/core/lib/iomgr/workqueue_posix.c @@ -43,8 +43,8 @@ #include #include -#include "src/core/lib/profiling/timers.h" #include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/profiling/timers.h" static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); @@ -131,7 +131,7 @@ static void wakeup(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { GPR_TIMER_BEGIN("workqueue.on_readable", 0); - + grpc_workqueue *workqueue = arg; if (error != GRPC_ERROR_NONE) { @@ -176,7 +176,7 @@ static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { GRPC_ERROR_UNREF(clerr); } } - + GPR_TIMER_END("workqueue.on_readable", 0); } -- cgit v1.2.3 From 427d7d71dc963e32d04120479b6e0ad53ae726a7 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 4 Aug 2016 12:11:08 -0700 Subject: Fix tsan reported error in trace --- src/core/lib/iomgr/combiner.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index 25b2ec3d4c..eb5ad634bd 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -155,12 +155,11 @@ static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { gpr_log(GPR_DEBUG, "C:%p start_execute_final take_async_break_before_final_list=%d", lock, lock->take_async_break_before_final_list)); - if (lock->optional_workqueue != NULL && - lock->take_async_break_before_final_list) { + if (lock->take_async_break_before_final_list) { grpc_closure_init(&lock->continue_finishing, continue_executing_final, lock); - grpc_workqueue_enqueue(exec_ctx, lock->optional_workqueue, - &lock->continue_finishing, GRPC_ERROR_NONE); + grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, + GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); GPR_TIMER_END("combiner.start_execute_final", 0); return false; } else { @@ -201,9 +200,9 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { do { executor = maybe_finish_one; gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -2); - GRPC_COMBINER_TRACE(gpr_log( - GPR_DEBUG, "C:%p finish[%d] old_state=%" PRIdPTR " cl=[%p,%p]", lock, - loops, old_state, lock->final_list.head, lock->final_list.tail)); + GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, + "C:%p finish[%d] old_state=%" PRIdPTR, lock, + loops, old_state)); switch (old_state) { case 5: // we're down to one queued item: if it's the final list we case 4: // should do that -- cgit v1.2.3 From 714c7ec74aab3e99d5e577eddd3665cbcbca5dd6 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 4 Aug 2016 12:58:16 -0700 Subject: Plumbed read_buffer through and fixed leftover bytes problem. --- .../ext/client_config/http_connect_handshaker.c | 52 +++++++++++++++------- .../transport/chttp2/transport/chttp2_transport.c | 3 +- src/core/lib/http/httpcli.c | 2 +- src/core/lib/http/parser.c | 24 ++++++---- src/core/lib/http/parser.h | 4 +- test/core/end2end/fixtures/http_proxy.c | 5 ++- test/core/http/parser_test.c | 10 +++-- test/core/http/request_fuzzer.c | 2 +- test/core/http/response_fuzzer.c | 2 +- 9 files changed, 67 insertions(+), 37 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/http_connect_handshaker.c b/src/core/ext/client_config/http_connect_handshaker.c index 25851c2efb..e6660fe2d4 100644 --- a/src/core/ext/client_config/http_connect_handshaker.c +++ b/src/core/ext/client_config/http_connect_handshaker.c @@ -56,9 +56,9 @@ typedef struct http_connect_handshaker { void* user_data; // Objects for processing the HTTP CONNECT request and response. - gpr_slice_buffer request_buffer; + gpr_slice_buffer write_buffer; + gpr_slice_buffer* read_buffer; grpc_closure request_done_closure; - gpr_slice_buffer response_buffer; grpc_closure response_read_closure; grpc_http_parser http_parser; grpc_http_response http_response; @@ -70,10 +70,11 @@ static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg, http_connect_handshaker* h = arg; if (error != GRPC_ERROR_NONE) { // If the write failed, invoke the callback immediately with the error. - h->cb(exec_ctx, h->endpoint, h->args, h->user_data, GRPC_ERROR_REF(error)); + h->cb(exec_ctx, h->endpoint, h->args, h->read_buffer, h->user_data, + GRPC_ERROR_REF(error)); } else { // Otherwise, read the response. - grpc_endpoint_read(exec_ctx, h->endpoint, &h->response_buffer, + grpc_endpoint_read(exec_ctx, h->endpoint, h->read_buffer, &h->response_read_closure); } } @@ -87,12 +88,29 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, goto done; } // Add buffer to parser. - for (size_t i = 0; i < h->response_buffer.count; ++i) { - if (GPR_SLICE_LENGTH(h->response_buffer.slices[i]) > 0) { + for (size_t i = 0; i < h->read_buffer->count; ++i) { + if (GPR_SLICE_LENGTH(h->read_buffer->slices[i]) > 0) { + size_t body_start_offset = 0; error = grpc_http_parser_parse( - &h->http_parser, h->response_buffer.slices[i]); + &h->http_parser, h->read_buffer->slices[i], &body_start_offset); if (error != GRPC_ERROR_NONE) goto done; + if (h->http_parser.state == GRPC_HTTP_BODY) { + // Remove the data we've already read from the read buffer, + // leaving only the leftover bytes (if any). + gpr_slice_buffer tmp_buffer; + gpr_slice_buffer_init(&tmp_buffer); + if (body_start_offset < GPR_SLICE_LENGTH(h->read_buffer->slices[i])) { + gpr_slice_buffer_add(&tmp_buffer, + gpr_slice_split_tail(&h->read_buffer->slices[i], + body_start_offset)); + } + gpr_slice_buffer_addn(&tmp_buffer, &h->read_buffer->slices[i + 1], + h->read_buffer->count - i - 1); + gpr_slice_buffer_swap(h->read_buffer, &tmp_buffer); + gpr_slice_buffer_destroy(&tmp_buffer); + break; + } } } // If we're not done reading the response, read more data. @@ -107,8 +125,8 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, // complete (e.g., handling chunked transfer encoding or looking // at the Content-Length: header). if (h->http_parser.state != GRPC_HTTP_BODY) { - gpr_slice_buffer_reset_and_unref(&h->response_buffer); - grpc_endpoint_read(exec_ctx, h->endpoint, &h->response_buffer, + gpr_slice_buffer_reset_and_unref(h->read_buffer); + grpc_endpoint_read(exec_ctx, h->endpoint, h->read_buffer, &h->response_read_closure); return; } @@ -122,7 +140,7 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, } done: // Invoke handshake-done callback. - h->cb(exec_ctx, h->endpoint, h->args, h->user_data, error); + h->cb(exec_ctx, h->endpoint, h->args, h->read_buffer, h->user_data, error); } // @@ -134,8 +152,7 @@ static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx, http_connect_handshaker* h = (http_connect_handshaker*)handshaker; gpr_free(h->proxy_server); gpr_free(h->server_name); - gpr_slice_buffer_destroy(&h->request_buffer); - gpr_slice_buffer_destroy(&h->response_buffer); + gpr_slice_buffer_destroy(&h->write_buffer); grpc_http_parser_destroy(&h->http_parser); grpc_http_response_destroy(&h->http_response); gpr_free(h); @@ -148,7 +165,8 @@ static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx, // FIXME BEFORE MERGING: apply deadline static void http_connect_handshaker_do_handshake( grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, - grpc_endpoint* endpoint, grpc_channel_args* args, gpr_timespec deadline, + grpc_endpoint* endpoint, grpc_channel_args* args, + gpr_slice_buffer* read_buffer, gpr_timespec deadline, grpc_tcp_server_acceptor* acceptor, grpc_handshaker_done_cb cb, void* user_data) { http_connect_handshaker* h = (http_connect_handshaker*)handshaker; @@ -158,9 +176,9 @@ static void http_connect_handshaker_do_handshake( h->cb = cb; h->user_data = user_data; // Initialize fields. - gpr_slice_buffer_init(&h->request_buffer); + gpr_slice_buffer_init(&h->write_buffer); + h->read_buffer = read_buffer; grpc_closure_init(&h->request_done_closure, on_write_done, h); - gpr_slice_buffer_init(&h->response_buffer); grpc_closure_init(&h->response_read_closure, on_read_done, h); grpc_http_parser_init(&h->http_parser, GRPC_HTTP_RESPONSE, &h->http_response); @@ -174,8 +192,8 @@ static void http_connect_handshaker_do_handshake( request.http.path = h->server_name; request.handshaker = &grpc_httpcli_plaintext; gpr_slice request_slice = grpc_httpcli_format_connect_request(&request); - gpr_slice_buffer_add(&h->request_buffer, request_slice); - grpc_endpoint_write(exec_ctx, endpoint, &h->request_buffer, + gpr_slice_buffer_add(&h->write_buffer, request_slice); + grpc_endpoint_write(exec_ctx, endpoint, &h->write_buffer, &h->request_done_closure); } diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index f2f5465201..6c608c8013 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -1987,7 +1987,8 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, grpc_error *parse_error = GRPC_ERROR_NONE; for (; i < t->read_buffer.count && parse_error == GRPC_ERROR_NONE; i++) { - parse_error = grpc_http_parser_parse(&parser, t->read_buffer.slices[i]); + parse_error = grpc_http_parser_parse(&parser, t->read_buffer.slices[i], + NULL); } if (parse_error == GRPC_ERROR_NONE && (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) { diff --git a/src/core/lib/http/httpcli.c b/src/core/lib/http/httpcli.c index 18135bcb58..7f3c2d120d 100644 --- a/src/core/lib/http/httpcli.c +++ b/src/core/lib/http/httpcli.c @@ -146,7 +146,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, if (GPR_SLICE_LENGTH(req->incoming.slices[i])) { req->have_read_byte = 1; grpc_error *err = - grpc_http_parser_parse(&req->parser, req->incoming.slices[i]); + grpc_http_parser_parse(&req->parser, req->incoming.slices[i], NULL); if (err != GRPC_ERROR_NONE) { finish(exec_ctx, req, err); return; diff --git a/src/core/lib/http/parser.c b/src/core/lib/http/parser.c index d3bac5b876..cbf26811f7 100644 --- a/src/core/lib/http/parser.c +++ b/src/core/lib/http/parser.c @@ -33,6 +33,7 @@ #include "src/core/lib/http/parser.h" +#include #include #include @@ -200,7 +201,8 @@ done: return error; } -static grpc_error *finish_line(grpc_http_parser *parser) { +static grpc_error *finish_line(grpc_http_parser *parser, + bool *found_body_start) { grpc_error *err; switch (parser->state) { case GRPC_HTTP_FIRST_LINE: @@ -211,6 +213,7 @@ static grpc_error *finish_line(grpc_http_parser *parser) { case GRPC_HTTP_HEADERS: if (parser->cur_line_length == parser->cur_line_end_length) { parser->state = GRPC_HTTP_BODY; + *found_body_start = true; break; } err = add_header(parser); @@ -274,7 +277,8 @@ static bool check_line(grpc_http_parser *parser) { return false; } -static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte) { +static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte, + bool *found_body_start) { switch (parser->state) { case GRPC_HTTP_FIRST_LINE: case GRPC_HTTP_HEADERS: @@ -287,7 +291,7 @@ static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte) { parser->cur_line[parser->cur_line_length] = byte; parser->cur_line_length++; if (check_line(parser)) { - return finish_line(parser); + return finish_line(parser, found_body_start); } return GRPC_ERROR_NONE; case GRPC_HTTP_BODY: @@ -329,14 +333,16 @@ void grpc_http_response_destroy(grpc_http_response *response) { gpr_free(response->hdrs); } -grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) { - size_t i; - - for (i = 0; i < GPR_SLICE_LENGTH(slice); i++) { - grpc_error *err = addbyte(parser, GPR_SLICE_START_PTR(slice)[i]); +grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice, + size_t *start_of_body) { + for (size_t i = 0; i < GPR_SLICE_LENGTH(slice); i++) { + bool found_body_start = false; + grpc_error *err = addbyte(parser, GPR_SLICE_START_PTR(slice)[i], + &found_body_start); if (err != GRPC_ERROR_NONE) return err; + if (found_body_start && start_of_body != NULL) + *start_of_body = i + 1; } - return GRPC_ERROR_NONE; } diff --git a/src/core/lib/http/parser.h b/src/core/lib/http/parser.h index 6df3cc8b13..fab42979cd 100644 --- a/src/core/lib/http/parser.h +++ b/src/core/lib/http/parser.h @@ -113,7 +113,9 @@ void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type, void *request_or_response); void grpc_http_parser_destroy(grpc_http_parser *parser); -grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice); +/* Sets \a start_of_body to the offset in \a slice of the start of the body. */ +grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice, + size_t *start_of_body); grpc_error *grpc_http_parser_eof(grpc_http_parser *parser); void grpc_http_request_destroy(grpc_http_request *request); diff --git a/test/core/end2end/fixtures/http_proxy.c b/test/core/end2end/fixtures/http_proxy.c index 3953687c26..77e0d9942b 100644 --- a/test/core/end2end/fixtures/http_proxy.c +++ b/test/core/end2end/fixtures/http_proxy.c @@ -297,7 +297,8 @@ gpr_log(GPR_INFO, "==> %s()", __func__); // We've established a connection, so send back a 200 response code to // the client. // The write callback inherits our reference to conn. - gpr_slice slice = gpr_slice_from_copied_string("200 connected\r\n\r\n"); + gpr_slice slice = + gpr_slice_from_copied_string("HTTP/1.0 200 connected\r\n\r\n"); gpr_slice_buffer_add(&conn->client_write_buffer, slice); grpc_endpoint_write(exec_ctx, conn->client_endpoint, &conn->client_write_buffer, @@ -323,7 +324,7 @@ gpr_log(GPR_INFO, "==> %s()", __func__); for (size_t i = 0; i < conn->client_read_buffer.count; ++i) { if (GPR_SLICE_LENGTH(conn->client_read_buffer.slices[i]) > 0) { error = grpc_http_parser_parse( - &conn->http_parser, conn->client_read_buffer.slices[i]); + &conn->http_parser, conn->client_read_buffer.slices[i], NULL); if (error != GRPC_ERROR_NONE) { proxy_connection_failed(exec_ctx, conn, true /* is_client */, "HTTP proxy request parse", error); diff --git a/test/core/http/parser_test.c b/test/core/http/parser_test.c index d645d2879c..211690eff9 100644 --- a/test/core/http/parser_test.c +++ b/test/core/http/parser_test.c @@ -62,7 +62,8 @@ static void test_request_succeeds(grpc_slice_split_mode split_mode, grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request); for (i = 0; i < num_slices; i++) { - GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i]) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], NULL) + == GRPC_ERROR_NONE); gpr_slice_unref(slices[i]); } GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE); @@ -118,7 +119,8 @@ static void test_succeeds(grpc_slice_split_mode split_mode, char *response_text, grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); for (i = 0; i < num_slices; i++) { - GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i]) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], NULL) + == GRPC_ERROR_NONE); gpr_slice_unref(slices[i]); } GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE); @@ -171,7 +173,7 @@ static void test_fails(grpc_slice_split_mode split_mode, char *response_text) { for (i = 0; i < num_slices; i++) { if (GRPC_ERROR_NONE == error) { - error = grpc_http_parser_parse(&parser, slices[i]); + error = grpc_http_parser_parse(&parser, slices[i], NULL); } gpr_slice_unref(slices[i]); } @@ -204,7 +206,7 @@ static void test_request_fails(grpc_slice_split_mode split_mode, for (i = 0; i < num_slices; i++) { if (error == GRPC_ERROR_NONE) { - error = grpc_http_parser_parse(&parser, slices[i]); + error = grpc_http_parser_parse(&parser, slices[i], NULL); } gpr_slice_unref(slices[i]); } diff --git a/test/core/http/request_fuzzer.c b/test/core/http/request_fuzzer.c index 5941401867..bb6cb92c0c 100644 --- a/test/core/http/request_fuzzer.c +++ b/test/core/http/request_fuzzer.c @@ -48,7 +48,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { memset(&request, 0, sizeof(request)); grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request); gpr_slice slice = gpr_slice_from_copied_buffer((const char *)data, size); - GRPC_ERROR_UNREF(grpc_http_parser_parse(&parser, slice)); + GRPC_ERROR_UNREF(grpc_http_parser_parse(&parser, slice, NULL)); GRPC_ERROR_UNREF(grpc_http_parser_eof(&parser)); gpr_slice_unref(slice); grpc_http_parser_destroy(&parser); diff --git a/test/core/http/response_fuzzer.c b/test/core/http/response_fuzzer.c index acde7c80a4..4393840484 100644 --- a/test/core/http/response_fuzzer.c +++ b/test/core/http/response_fuzzer.c @@ -47,7 +47,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { memset(&response, 0, sizeof(response)); grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); gpr_slice slice = gpr_slice_from_copied_buffer((const char *)data, size); - GRPC_ERROR_UNREF(grpc_http_parser_parse(&parser, slice)); + GRPC_ERROR_UNREF(grpc_http_parser_parse(&parser, slice, NULL)); GRPC_ERROR_UNREF(grpc_http_parser_eof(&parser)); gpr_slice_unref(slice); grpc_http_parser_destroy(&parser); -- cgit v1.2.3 From 0a05ab6e8e8e605f0fe4f2d0f4373d660bbdfe06 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 4 Aug 2016 13:10:13 -0700 Subject: clang-format --- .../ext/client_config/http_connect_handshaker.c | 22 +++++++------- src/core/ext/client_config/resolver_registry.c | 3 +- .../chttp2/client/insecure/channel_create.c | 7 ++--- .../chttp2/client/secure/secure_channel_create.c | 7 ++--- .../transport/chttp2/transport/chttp2_transport.c | 4 +-- src/core/lib/http/parser.c | 7 ++--- test/core/end2end/fixtures/h2_http_proxy.c | 2 +- test/core/end2end/fixtures/http_proxy.c | 34 +++++++++++----------- test/core/end2end/fixtures/http_proxy.h | 4 +-- test/core/http/parser_test.c | 8 ++--- 10 files changed, 46 insertions(+), 52 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/http_connect_handshaker.c b/src/core/ext/client_config/http_connect_handshaker.c index e6660fe2d4..54f592ef61 100644 --- a/src/core/ext/client_config/http_connect_handshaker.c +++ b/src/core/ext/client_config/http_connect_handshaker.c @@ -31,6 +31,8 @@ * */ +#include "src/core/ext/client_config/http_connect_handshaker.h" + #include #include @@ -40,7 +42,6 @@ #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" -#include "src/core/ext/client_config/http_connect_handshaker.h" typedef struct http_connect_handshaker { // Base class. Must be first. @@ -91,10 +92,9 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, for (size_t i = 0; i < h->read_buffer->count; ++i) { if (GPR_SLICE_LENGTH(h->read_buffer->slices[i]) > 0) { size_t body_start_offset = 0; - error = grpc_http_parser_parse( - &h->http_parser, h->read_buffer->slices[i], &body_start_offset); - if (error != GRPC_ERROR_NONE) - goto done; + error = grpc_http_parser_parse(&h->http_parser, h->read_buffer->slices[i], + &body_start_offset); + if (error != GRPC_ERROR_NONE) goto done; if (h->http_parser.state == GRPC_HTTP_BODY) { // Remove the data we've already read from the read buffer, // leaving only the leftover bytes (if any). @@ -138,7 +138,7 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg, error = GRPC_ERROR_CREATE(msg); gpr_free(msg); } - done: +done: // Invoke handshake-done callback. h->cb(exec_ctx, h->endpoint, h->args, h->read_buffer, h->user_data, error); } @@ -159,8 +159,7 @@ static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx, } static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx, - grpc_handshaker* handshaker) { -} + grpc_handshaker* handshaker) {} // FIXME BEFORE MERGING: apply deadline static void http_connect_handshaker_do_handshake( @@ -180,11 +179,10 @@ static void http_connect_handshaker_do_handshake( h->read_buffer = read_buffer; grpc_closure_init(&h->request_done_closure, on_write_done, h); grpc_closure_init(&h->response_read_closure, on_read_done, h); - grpc_http_parser_init(&h->http_parser, GRPC_HTTP_RESPONSE, - &h->http_response); + grpc_http_parser_init(&h->http_parser, GRPC_HTTP_RESPONSE, &h->http_response); // Send HTTP CONNECT request. - gpr_log(GPR_INFO, "Connecting to server %s via HTTP proxy %s", - h->server_name, h->proxy_server); + gpr_log(GPR_INFO, "Connecting to server %s via HTTP proxy %s", h->server_name, + h->proxy_server); grpc_httpcli_request request; memset(&request, 0, sizeof(request)); request.host = h->proxy_server; diff --git a/src/core/ext/client_config/resolver_registry.c b/src/core/ext/client_config/resolver_registry.c index 13f08e9fe6..5a8f137103 100644 --- a/src/core/ext/client_config/resolver_registry.c +++ b/src/core/ext/client_config/resolver_registry.c @@ -140,8 +140,7 @@ grpc_resolver *grpc_resolver_create( args.client_channel_factory = client_channel_factory; resolver = grpc_resolver_factory_create_resolver(factory, &args); const char *proxy = grpc_uri_get_query_arg(uri, "http_proxy"); - if (proxy != NULL) - *http_proxy = gpr_strdup(proxy); + if (proxy != NULL) *http_proxy = gpr_strdup(proxy); grpc_uri_destroy(uri); return resolver; } diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c index 7f0b13e321..475224effd 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c @@ -180,8 +180,7 @@ static void client_channel_factory_unref( "client_channel_factory"); } grpc_channel_args_destroy(f->merge_args); - if (f->http_proxy != NULL) - gpr_free(f->http_proxy); + if (f->http_proxy != NULL) gpr_free(f->http_proxy); gpr_free(f); } } @@ -219,8 +218,8 @@ static grpc_channel *client_channel_factory_create_channel( grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args, GRPC_CLIENT_CHANNEL, NULL); grpc_channel_args_destroy(final_args); - grpc_resolver *resolver = grpc_resolver_create(target, &f->base, - &f->http_proxy); + grpc_resolver *resolver = + grpc_resolver_create(target, &f->base, &f->http_proxy); if (!resolver) { GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "client_channel_factory_create_channel"); diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c index 73c093fcd2..e06ae9e02c 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c @@ -242,8 +242,7 @@ static void client_channel_factory_unref( "client_channel_factory"); } grpc_channel_args_destroy(f->merge_args); - if (f->http_proxy != NULL) - gpr_free(f->http_proxy); + if (f->http_proxy != NULL) gpr_free(f->http_proxy); gpr_free(f); } } @@ -285,8 +284,8 @@ static grpc_channel *client_channel_factory_create_channel( GRPC_CLIENT_CHANNEL, NULL); grpc_channel_args_destroy(final_args); - grpc_resolver *resolver = grpc_resolver_create(target, &f->base, - &f->http_proxy); + grpc_resolver *resolver = + grpc_resolver_create(target, &f->base, &f->http_proxy); if (resolver != NULL) { grpc_client_channel_set_resolver( exec_ctx, grpc_channel_get_channel_stack(channel), resolver); diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 6c608c8013..0a28f7b5e8 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -1987,8 +1987,8 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, grpc_error *parse_error = GRPC_ERROR_NONE; for (; i < t->read_buffer.count && parse_error == GRPC_ERROR_NONE; i++) { - parse_error = grpc_http_parser_parse(&parser, t->read_buffer.slices[i], - NULL); + parse_error = + grpc_http_parser_parse(&parser, t->read_buffer.slices[i], NULL); } if (parse_error == GRPC_ERROR_NONE && (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) { diff --git a/src/core/lib/http/parser.c b/src/core/lib/http/parser.c index cbf26811f7..be9e9b6b63 100644 --- a/src/core/lib/http/parser.c +++ b/src/core/lib/http/parser.c @@ -337,11 +337,10 @@ grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice, size_t *start_of_body) { for (size_t i = 0; i < GPR_SLICE_LENGTH(slice); i++) { bool found_body_start = false; - grpc_error *err = addbyte(parser, GPR_SLICE_START_PTR(slice)[i], - &found_body_start); + grpc_error *err = + addbyte(parser, GPR_SLICE_START_PTR(slice)[i], &found_body_start); if (err != GRPC_ERROR_NONE) return err; - if (found_body_start && start_of_body != NULL) - *start_of_body = i + 1; + if (found_body_start && start_of_body != NULL) *start_of_body = i + 1; } return GRPC_ERROR_NONE; } diff --git a/test/core/end2end/fixtures/h2_http_proxy.c b/test/core/end2end/fixtures/h2_http_proxy.c index d84f0b8cb9..612a3dbb83 100644 --- a/test/core/end2end/fixtures/h2_http_proxy.c +++ b/test/core/end2end/fixtures/h2_http_proxy.c @@ -38,10 +38,10 @@ #include #include #include +#include #include #include #include -#include #include "src/core/ext/client_config/client_channel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/connected_channel.h" diff --git a/test/core/end2end/fixtures/http_proxy.c b/test/core/end2end/fixtures/http_proxy.c index 0cdb2884ee..53132c1636 100644 --- a/test/core/end2end/fixtures/http_proxy.c +++ b/test/core/end2end/fixtures/http_proxy.c @@ -281,8 +281,8 @@ static void on_read_request_done(grpc_exec_ctx* exec_ctx, void* arg, // Read request and feed it to the parser. for (size_t i = 0; i < conn->client_read_buffer.count; ++i) { if (GPR_SLICE_LENGTH(conn->client_read_buffer.slices[i]) > 0) { - error = grpc_http_parser_parse( - &conn->http_parser, conn->client_read_buffer.slices[i], NULL); + error = grpc_http_parser_parse(&conn->http_parser, + conn->client_read_buffer.slices[i], NULL); if (error != GRPC_ERROR_NONE) { proxy_connection_failed(exec_ctx, conn, true /* is_client */, "HTTP proxy request parse", error); @@ -368,17 +368,17 @@ static void on_accept(grpc_exec_ctx* exec_ctx, void* arg, // static void thread_main(void* arg) { - grpc_end2end_http_proxy *proxy = arg; + grpc_end2end_http_proxy* proxy = arg; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; do { const gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); const gpr_timespec deadline = gpr_time_add(now, gpr_time_from_seconds(1, GPR_TIMESPAN)); - grpc_pollset_worker *worker = NULL; + grpc_pollset_worker* worker = NULL; gpr_mu_lock(proxy->mu); - GRPC_LOG_IF_ERROR("grpc_pollset_work", - grpc_pollset_work(&exec_ctx, proxy->pollset, &worker, - now, deadline)); + GRPC_LOG_IF_ERROR( + "grpc_pollset_work", + grpc_pollset_work(&exec_ctx, proxy->pollset, &worker, now, deadline)); gpr_mu_unlock(proxy->mu); grpc_exec_ctx_flush(&exec_ctx); } while (!proxy->shutdown); @@ -394,8 +394,8 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create() { gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name); // Create TCP server. proxy->channel_args = grpc_channel_args_copy(NULL); - grpc_error* error = grpc_tcp_server_create( - NULL, proxy->channel_args, &proxy->server); + grpc_error* error = + grpc_tcp_server_create(NULL, proxy->channel_args, &proxy->server); GPR_ASSERT(error == GRPC_ERROR_NONE); // Bind to port. struct sockaddr_in addr; @@ -403,16 +403,16 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create() { addr.sin_family = AF_INET; grpc_sockaddr_set_port((struct sockaddr*)&addr, proxy_port); int port; - error = grpc_tcp_server_add_port( - proxy->server, (struct sockaddr*)&addr, sizeof(addr), &port); + error = grpc_tcp_server_add_port(proxy->server, (struct sockaddr*)&addr, + sizeof(addr), &port); GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(port == proxy_port); // Start server. proxy->pollset = gpr_malloc(grpc_pollset_size()); grpc_pollset_init(proxy->pollset, &proxy->mu); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_tcp_server_start(&exec_ctx, proxy->server, &proxy->pollset, 1, - on_accept, proxy); + grpc_tcp_server_start(&exec_ctx, proxy->server, &proxy->pollset, 1, on_accept, + proxy); grpc_exec_ctx_finish(&exec_ctx); // Start proxy thread. gpr_thd_options opt = gpr_thd_options_default(); @@ -421,8 +421,8 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create() { return proxy; } -static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { +static void destroy_pollset(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { grpc_pollset* pollset = arg; grpc_pollset_destroy(pollset); gpr_free(pollset); @@ -442,7 +442,7 @@ void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy) { grpc_exec_ctx_finish(&exec_ctx); } -const char *grpc_end2end_http_proxy_get_proxy_name( - grpc_end2end_http_proxy *proxy) { +const char* grpc_end2end_http_proxy_get_proxy_name( + grpc_end2end_http_proxy* proxy) { return proxy->proxy_name; } diff --git a/test/core/end2end/fixtures/http_proxy.h b/test/core/end2end/fixtures/http_proxy.h index 7af2ea92d0..cd47b432af 100644 --- a/test/core/end2end/fixtures/http_proxy.h +++ b/test/core/end2end/fixtures/http_proxy.h @@ -37,5 +37,5 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(); void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy); -const char *grpc_end2end_http_proxy_get_proxy_name( - grpc_end2end_http_proxy *proxy); +const char* grpc_end2end_http_proxy_get_proxy_name( + grpc_end2end_http_proxy* proxy); diff --git a/test/core/http/parser_test.c b/test/core/http/parser_test.c index 211690eff9..2fc354d9ee 100644 --- a/test/core/http/parser_test.c +++ b/test/core/http/parser_test.c @@ -62,8 +62,8 @@ static void test_request_succeeds(grpc_slice_split_mode split_mode, grpc_http_parser_init(&parser, GRPC_HTTP_REQUEST, &request); for (i = 0; i < num_slices; i++) { - GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], NULL) - == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], NULL) == + GRPC_ERROR_NONE); gpr_slice_unref(slices[i]); } GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE); @@ -119,8 +119,8 @@ static void test_succeeds(grpc_slice_split_mode split_mode, char *response_text, grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); for (i = 0; i < num_slices; i++) { - GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], NULL) - == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_http_parser_parse(&parser, slices[i], NULL) == + GRPC_ERROR_NONE); gpr_slice_unref(slices[i]); } GPR_ASSERT(grpc_http_parser_eof(&parser) == GRPC_ERROR_NONE); -- cgit v1.2.3 From cc357bf74e27888a354f361ad3b66e4e2b565dbc Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Mon, 22 Aug 2016 16:08:50 -0700 Subject: Remove completion queue parameter from grpc_server_add_insecure_channel_from_fd API --- include/grpc/grpc_posix.h | 11 +++++++---- .../chttp2/server/insecure/server_chttp2_posix.c | 19 +++++++++++++------ src/core/lib/surface/server.c | 6 ++++++ src/core/lib/surface/server.h | 5 +++++ src/cpp/server/server_posix.cc | 3 +-- src/ruby/ext/grpc/rb_grpc_imports.generated.h | 2 +- test/core/end2end/fixtures/h2_fd.c | 2 +- 7 files changed, 34 insertions(+), 14 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc/grpc_posix.h b/include/grpc/grpc_posix.h index 5e89ae3b1e..b426c329ef 100644 --- a/include/grpc/grpc_posix.h +++ b/include/grpc/grpc_posix.h @@ -57,11 +57,14 @@ GRPCAPI grpc_channel *grpc_insecure_channel_create_from_fd( /** Add the connected communication channel based on file descriptor 'fd' to the 'server'. The 'fd' must be an open file descriptor corresponding to a - connected socket. The 'cq' is a completion queue that will be getting events - from that descriptor. */ + connected socket. Events from the file descriptor may come on any of the + server completion queues (i.e completion queues registered via the + grpc_server_register_completion_queue API). + + The 'reserved' pointer MUST be NULL. + */ GRPCAPI void grpc_server_add_insecure_channel_from_fd(grpc_server *server, - grpc_completion_queue *cq, - int fd); + void *reserved, int fd); /** GRPC Core POSIX library may internally use signals to optimize some work. The library uses (SIGRTMIN + 2) signal by default. Use this API to instruct diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c b/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c index 4350543c27..9af17fb5ae 100644 --- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c +++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c @@ -50,10 +50,10 @@ #include "src/core/lib/surface/server.h" void grpc_server_add_insecure_channel_from_fd(grpc_server *server, - grpc_completion_queue *cq, - int fd) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + void *reserved, int fd) { + GPR_ASSERT(reserved == NULL); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; char *name; gpr_asprintf(&name, "fd:%d", fd); @@ -65,7 +65,15 @@ void grpc_server_add_insecure_channel_from_fd(grpc_server *server, const grpc_channel_args *server_args = grpc_server_get_channel_args(server); grpc_transport *transport = grpc_create_chttp2_transport( &exec_ctx, server_args, server_endpoint, 0 /* is_client */); - grpc_endpoint_add_to_pollset(&exec_ctx, server_endpoint, grpc_cq_pollset(cq)); + + grpc_pollset **pollsets; + size_t num_pollsets = 0; + grpc_server_get_pollsets(server, &pollsets, &num_pollsets); + + for (size_t i = 0; i < num_pollsets; i++) { + grpc_endpoint_add_to_pollset(&exec_ctx, server_endpoint, pollsets[i]); + } + grpc_server_setup_transport(&exec_ctx, server, transport, NULL, server_args); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); grpc_exec_ctx_finish(&exec_ctx); @@ -74,8 +82,7 @@ void grpc_server_add_insecure_channel_from_fd(grpc_server *server, #else // !GPR_SUPPORT_CHANNELS_FROM_FD void grpc_server_add_insecure_channel_from_fd(grpc_server *server, - grpc_completion_queue *cq, - int fd) { + void *reserved, int fd) { GPR_ASSERT(0); } diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index 64afcecc07..8811b6e803 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -1098,6 +1098,12 @@ void grpc_server_start(grpc_server *server) { grpc_exec_ctx_finish(&exec_ctx); } +void grpc_server_get_pollsets(grpc_server *server, grpc_pollset ***pollsets, + size_t *pollset_count) { + *pollset_count = server->cq_count; + *pollsets = server->pollsets; +} + void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, grpc_transport *transport, grpc_pollset *accepting_pollset, diff --git a/src/core/lib/surface/server.h b/src/core/lib/surface/server.h index fb6e4d60c5..551a40a4ff 100644 --- a/src/core/lib/surface/server.h +++ b/src/core/lib/surface/server.h @@ -60,4 +60,9 @@ const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server); int grpc_server_has_open_connections(grpc_server *server); +/* Do not call this before grpc_server_start. Returns the pollsets and the + * number of pollsets via 'pollsets' and 'pollset_count'. */ +void grpc_server_get_pollsets(grpc_server *server, grpc_pollset ***pollsets, + size_t *pollset_count); + #endif /* GRPC_CORE_LIB_SURFACE_SERVER_H */ diff --git a/src/cpp/server/server_posix.cc b/src/cpp/server/server_posix.cc index c3aa2adc60..33d42a8dc7 100644 --- a/src/cpp/server/server_posix.cc +++ b/src/cpp/server/server_posix.cc @@ -40,8 +40,7 @@ namespace grpc { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD void AddInsecureChannelFromFd(Server* server, int fd) { - grpc_server_add_insecure_channel_from_fd( - server->c_server(), server->completion_queue()->cq(), fd); + grpc_server_add_insecure_channel_from_fd(server->c_server(), NULL, fd); } #endif // GPR_SUPPORT_CHANNELS_FROM_FD diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 3bb76fbb97..b3960b462d 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -317,7 +317,7 @@ extern grpc_call_error_to_string_type grpc_call_error_to_string_import; typedef grpc_channel *(*grpc_insecure_channel_create_from_fd_type)(const char *target, int fd, const grpc_channel_args *args); extern grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import; #define grpc_insecure_channel_create_from_fd grpc_insecure_channel_create_from_fd_import -typedef void(*grpc_server_add_insecure_channel_from_fd_type)(grpc_server *server, grpc_completion_queue *cq, int fd); +typedef void(*grpc_server_add_insecure_channel_from_fd_type)(grpc_server *server, void *reserved, int fd); extern grpc_server_add_insecure_channel_from_fd_type grpc_server_add_insecure_channel_from_fd_import; #define grpc_server_add_insecure_channel_from_fd grpc_server_add_insecure_channel_from_fd_import typedef void(*grpc_use_signal_type)(int signum); diff --git a/test/core/end2end/fixtures/h2_fd.c b/test/core/end2end/fixtures/h2_fd.c index 89fa02517d..8561feed70 100644 --- a/test/core/end2end/fixtures/h2_fd.c +++ b/test/core/end2end/fixtures/h2_fd.c @@ -95,7 +95,7 @@ static void chttp2_init_server_socketpair(grpc_end2end_test_fixture *f, grpc_server_register_completion_queue(f->server, f->cq, NULL); grpc_server_start(f->server); - grpc_server_add_insecure_channel_from_fd(f->server, f->cq, sfd->fd_pair[1]); + grpc_server_add_insecure_channel_from_fd(f->server, NULL, sfd->fd_pair[1]); grpc_exec_ctx_finish(&exec_ctx); } -- cgit v1.2.3 From af00d8bfb24f6debdc2a0ac78d2dc5bf67fc01e4 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 23 Aug 2016 12:48:16 -0700 Subject: Add channel arg for max send message size and add message size filter. --- BUILD | 8 + CMakeLists.txt | 3 + Makefile | 4 + binding.gyp | 1 + build.yaml | 2 + config.m4 | 1 + gRPC-Core.podspec | 3 + grpc.gemspec | 2 + include/grpc/impl/codegen/grpc_types.h | 6 +- package.xml | 2 + src/core/lib/channel/message_size_filter.c | 175 +++++++++++++++++++++ src/core/lib/channel/message_size_filter.h | 40 +++++ src/core/lib/surface/call.c | 11 -- src/core/lib/surface/channel.c | 21 +-- src/core/lib/surface/channel.h | 1 - src/core/lib/surface/init.c | 10 ++ src/python/grpcio/grpc_core_dependencies.py | 1 + test/core/end2end/tests/max_message_length.c | 45 ++++-- tools/doxygen/Doxyfile.core.internal | 2 + tools/run_tests/sources_and_headers.json | 3 + vsprojects/vcxproj/grpc/grpc.vcxproj | 3 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 6 + .../vcxproj/grpc_test_util/grpc_test_util.vcxproj | 3 + .../grpc_test_util/grpc_test_util.vcxproj.filters | 6 + .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 3 + .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 + 26 files changed, 320 insertions(+), 48 deletions(-) create mode 100644 src/core/lib/channel/message_size_filter.c create mode 100644 src/core/lib/channel/message_size_filter.h (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index 12f0fd316e..7f661e9714 100644 --- a/BUILD +++ b/BUILD @@ -168,6 +168,7 @@ cc_library( "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", + "src/core/lib/channel/message_size_filter.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/message_compress.h", "src/core/lib/debug/trace.h", @@ -323,6 +324,7 @@ cc_library( "src/core/lib/channel/handshaker.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", + "src/core/lib/channel/message_size_filter.c", "src/core/lib/compression/compression.c", "src/core/lib/compression/message_compress.c", "src/core/lib/debug/trace.c", @@ -563,6 +565,7 @@ cc_library( "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", + "src/core/lib/channel/message_size_filter.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/message_compress.h", "src/core/lib/debug/trace.h", @@ -705,6 +708,7 @@ cc_library( "src/core/lib/channel/handshaker.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", + "src/core/lib/channel/message_size_filter.c", "src/core/lib/compression/compression.c", "src/core/lib/compression/message_compress.c", "src/core/lib/debug/trace.c", @@ -917,6 +921,7 @@ cc_library( "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", + "src/core/lib/channel/message_size_filter.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/message_compress.h", "src/core/lib/debug/trace.h", @@ -1049,6 +1054,7 @@ cc_library( "src/core/lib/channel/handshaker.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", + "src/core/lib/channel/message_size_filter.c", "src/core/lib/compression/compression.c", "src/core/lib/compression/message_compress.c", "src/core/lib/debug/trace.c", @@ -1816,6 +1822,7 @@ objc_library( "src/core/lib/channel/handshaker.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", + "src/core/lib/channel/message_size_filter.c", "src/core/lib/compression/compression.c", "src/core/lib/compression/message_compress.c", "src/core/lib/debug/trace.c", @@ -2035,6 +2042,7 @@ objc_library( "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", + "src/core/lib/channel/message_size_filter.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/message_compress.h", "src/core/lib/debug/trace.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index f847c9b0e6..567ec1fcb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -299,6 +299,7 @@ add_library(grpc src/core/lib/channel/handshaker.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c + src/core/lib/channel/message_size_filter.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c src/core/lib/debug/trace.c @@ -557,6 +558,7 @@ add_library(grpc_cronet src/core/lib/channel/handshaker.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c + src/core/lib/channel/message_size_filter.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c src/core/lib/debug/trace.c @@ -789,6 +791,7 @@ add_library(grpc_unsecure src/core/lib/channel/handshaker.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c + src/core/lib/channel/message_size_filter.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c src/core/lib/debug/trace.c diff --git a/Makefile b/Makefile index 6b619e310b..fdd1bfdfd1 100644 --- a/Makefile +++ b/Makefile @@ -2515,6 +2515,7 @@ LIBGRPC_SRC = \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ + src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ @@ -2791,6 +2792,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ + src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ @@ -3057,6 +3059,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ + src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ @@ -3249,6 +3252,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ + src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ diff --git a/binding.gyp b/binding.gyp index a29cfda6fc..2cb43b0eb5 100644 --- a/binding.gyp +++ b/binding.gyp @@ -571,6 +571,7 @@ 'src/core/lib/channel/handshaker.c', 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', + 'src/core/lib/channel/message_size_filter.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', 'src/core/lib/debug/trace.c', diff --git a/build.yaml b/build.yaml index 73c626351d..a0ff4ec859 100644 --- a/build.yaml +++ b/build.yaml @@ -163,6 +163,7 @@ filegroups: - src/core/lib/channel/handshaker.h - src/core/lib/channel/http_client_filter.h - src/core/lib/channel/http_server_filter.h + - src/core/lib/channel/message_size_filter.h - src/core/lib/compression/algorithm_metadata.h - src/core/lib/compression/message_compress.h - src/core/lib/debug/trace.h @@ -243,6 +244,7 @@ filegroups: - src/core/lib/channel/handshaker.c - src/core/lib/channel/http_client_filter.c - src/core/lib/channel/http_server_filter.c + - src/core/lib/channel/message_size_filter.c - src/core/lib/compression/compression.c - src/core/lib/compression/message_compress.c - src/core/lib/debug/trace.c diff --git a/config.m4 b/config.m4 index 5b47074bcd..c1b2fd9c9b 100644 --- a/config.m4 +++ b/config.m4 @@ -90,6 +90,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ + src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 02a500f626..1046f503db 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -261,6 +261,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/handshaker.h', 'src/core/lib/channel/http_client_filter.h', 'src/core/lib/channel/http_server_filter.h', + 'src/core/lib/channel/message_size_filter.h', 'src/core/lib/compression/algorithm_metadata.h', 'src/core/lib/compression/message_compress.h', 'src/core/lib/debug/trace.h', @@ -420,6 +421,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/handshaker.c', 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', + 'src/core/lib/channel/message_size_filter.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', 'src/core/lib/debug/trace.c', @@ -622,6 +624,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/handshaker.h', 'src/core/lib/channel/http_client_filter.h', 'src/core/lib/channel/http_server_filter.h', + 'src/core/lib/channel/message_size_filter.h', 'src/core/lib/compression/algorithm_metadata.h', 'src/core/lib/compression/message_compress.h', 'src/core/lib/debug/trace.h', diff --git a/grpc.gemspec b/grpc.gemspec index 9c82db8ee3..c69988f669 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -180,6 +180,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/handshaker.h ) s.files += %w( src/core/lib/channel/http_client_filter.h ) s.files += %w( src/core/lib/channel/http_server_filter.h ) + s.files += %w( src/core/lib/channel/message_size_filter.h ) s.files += %w( src/core/lib/compression/algorithm_metadata.h ) s.files += %w( src/core/lib/compression/message_compress.h ) s.files += %w( src/core/lib/debug/trace.h ) @@ -339,6 +340,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/handshaker.c ) s.files += %w( src/core/lib/channel/http_client_filter.c ) s.files += %w( src/core/lib/channel/http_server_filter.c ) + s.files += %w( src/core/lib/channel/message_size_filter.c ) s.files += %w( src/core/lib/compression/compression.c ) s.files += %w( src/core/lib/compression/message_compress.c ) s.files += %w( src/core/lib/debug/trace.c ) diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index e5a82883be..8b1ba63494 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -127,7 +127,11 @@ typedef struct { connection. Int valued. */ #define GRPC_ARG_MAX_CONCURRENT_STREAMS "grpc.max_concurrent_streams" /** Maximum message length that the channel can receive. Int valued, bytes. */ -#define GRPC_ARG_MAX_MESSAGE_LENGTH "grpc.max_message_length" +#define GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH "grpc.max_receive_message_length" +/** Backward compatibility. */ +#define GRPC_ARG_MAX_MESSAGE_LENGTH GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH +/** Maximum message length that the channel can send. Int valued, bytes. */ +#define GRPC_ARG_MAX_SEND_MESSAGE_LENGTH "grpc.max_send_message_length" /** Initial sequence number for http2 transports. Int valued. */ #define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \ "grpc.http2.initial_sequence_number" diff --git a/package.xml b/package.xml index be8c08d766..c2c8e0cdb5 100644 --- a/package.xml +++ b/package.xml @@ -188,6 +188,7 @@ + @@ -347,6 +348,7 @@ + diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c new file mode 100644 index 0000000000..264c07ca8e --- /dev/null +++ b/src/core/lib/channel/message_size_filter.c @@ -0,0 +1,175 @@ +/* + * 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/lib/channel/message_size_filter.h" + +#include + +#include +#include +#include + +/* the protobuf library will (by default) start warning at 100megs */ +#define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024) + +typedef struct call_data { + // Receive closures are chained: we inject this closure as the + // recv_message_ready up-call on transport_stream_op, and remember to + // call our next_recv_message_ready member after handling it. + grpc_closure recv_message_ready; + // Used by recv_message_ready. + grpc_byte_stream** recv_message; + // Original recv_message_ready callback, invoked after our own. + grpc_closure* next_recv_message_ready; +} call_data; + +typedef struct channel_data { + size_t max_send_size; + size_t max_recv_size; +} channel_data; + +// Callback invoked when we receive a message. Here we check the max +// receive message size. +static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, + grpc_error* error) { + grpc_call_element* elem = user_data; + call_data* calld = elem->call_data; + channel_data* chand = elem->channel_data; + if ((*calld->recv_message)->length > chand->max_recv_size) { + char* message_string; + gpr_asprintf(&message_string, "Received message larger than max (%lu)", + chand->max_recv_size); + gpr_slice message = gpr_slice_from_copied_string(message_string); + gpr_free(message_string); + grpc_call_element_send_cancel_with_message( + exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message); + } + // Invoke the next callback. + calld->next_recv_message_ready->cb( + exec_ctx, calld->next_recv_message_ready->cb_arg, error); +} + +// Start transport op. +static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, + grpc_call_element* elem, + grpc_transport_stream_op* op) { + call_data* calld = elem->call_data; + channel_data* chand = elem->channel_data; + // Check max send message size. + if (op->send_message != NULL && chand->max_send_size > 0 && + op->send_message->length > chand->max_send_size) { + char* message_string; + gpr_asprintf(&message_string, "Sent message larger than max (%lu)", + chand->max_send_size); + gpr_slice message = gpr_slice_from_copied_string(message_string); + gpr_free(message_string); + grpc_call_element_send_cancel_with_message( + exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message); + } + // Inject callback for receiving a message. + if (op->recv_message_ready != NULL && chand->max_recv_size > 0) { + calld->next_recv_message_ready = op->recv_message_ready; + calld->recv_message = op->recv_message; + op->recv_message_ready = &calld->recv_message_ready; + } + // Chain to the next filter. + grpc_call_next_op(exec_ctx, elem, op); +} + +// Constructor for call_data. +static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, + grpc_call_element* elem, + grpc_call_element_args* args) { + call_data* calld = elem->call_data; + calld->next_recv_message_ready = NULL; + grpc_closure_init(&calld->recv_message_ready, recv_message_ready, elem); + return GRPC_ERROR_NONE; +} + +// Destructor for call_data. +static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, + const grpc_call_final_info* final_info, + void* ignored) {} + +// Constructor for channel_data. +static void init_channel_elem(grpc_exec_ctx* exec_ctx, + grpc_channel_element* elem, + grpc_channel_element_args* args) { + GPR_ASSERT(!args->is_last); + channel_data* chand = elem->channel_data; + memset(chand, 0, sizeof(*chand)); + for (size_t i = 0; i < args->channel_args->num_args; ++i) { + if (strcmp(args->channel_args->args[i].key, + GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) { + if (args->channel_args->args[i].type != GRPC_ARG_INTEGER) { + gpr_log(GPR_ERROR, "%s ignored: it must be an integer", + GRPC_ARG_MAX_SEND_MESSAGE_LENGTH); + } else if (args->channel_args->args[i].value.integer < 0) { + gpr_log(GPR_ERROR, "%s ignored: it must be >= 0", + GRPC_ARG_MAX_SEND_MESSAGE_LENGTH); + } else { + chand->max_send_size = + (size_t)args->channel_args->args[i].value.integer; + } + } + if (strcmp(args->channel_args->args[i].key, + GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) { + if (args->channel_args->args[i].type != GRPC_ARG_INTEGER) { + gpr_log(GPR_ERROR, "%s ignored: it must be an integer", + GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH); + } else if (args->channel_args->args[i].value.integer < 0) { + gpr_log(GPR_ERROR, "%s ignored: it must be >= 0", + GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH); + } else { + chand->max_recv_size = + (size_t)args->channel_args->args[i].value.integer; + } + } + } +} + +// Destructor for channel_data. +static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, + grpc_channel_element* elem) {} + +const grpc_channel_filter grpc_message_size_filter = { + start_transport_stream_op, + grpc_channel_next_op, + sizeof(call_data), + init_call_elem, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + destroy_call_elem, + sizeof(channel_data), + init_channel_elem, + destroy_channel_elem, + grpc_call_next_get_peer, + "message_size"}; diff --git a/src/core/lib/channel/message_size_filter.h b/src/core/lib/channel/message_size_filter.h new file mode 100644 index 0000000000..367a322b37 --- /dev/null +++ b/src/core/lib/channel/message_size_filter.h @@ -0,0 +1,40 @@ +/* + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H +#define GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H + +#include "src/core/lib/channel/channel_stack.h" + +extern const grpc_channel_filter grpc_message_size_filter; + +#endif /* GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H */ diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 772681109a..6717024ab2 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -1160,17 +1160,6 @@ static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl, if (gpr_unref(&bctl->steps_to_complete)) { post_batch_completion(exec_ctx, bctl); } - } else if (call->receiving_stream->length > - grpc_channel_get_max_message_length(call->channel)) { - cancel_with_status(exec_ctx, call, GRPC_STATUS_INTERNAL, - "Max message size exceeded"); - grpc_byte_stream_destroy(exec_ctx, call->receiving_stream); - call->receiving_stream = NULL; - *call->receiving_buffer = NULL; - call->receiving_message = 0; - if (gpr_unref(&bctl->steps_to_complete)) { - post_batch_completion(exec_ctx, bctl); - } } else { call->test_only_last_message_flags = call->receiving_stream->flags; if ((call->receiving_stream->flags & GRPC_WRITE_INTERNAL_COMPRESS) && diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c index 6d2b1c4935..0e8e5bbfcd 100644 --- a/src/core/lib/surface/channel.c +++ b/src/core/lib/surface/channel.c @@ -64,7 +64,6 @@ typedef struct registered_call { struct grpc_channel { int is_client; - uint32_t max_message_length; grpc_compression_options compression_options; grpc_mdelem *default_authority; @@ -80,9 +79,6 @@ struct grpc_channel { #define CHANNEL_FROM_TOP_ELEM(top_elem) \ CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem)) -/* the protobuf library will (by default) start warning at 100megs */ -#define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024) - static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); @@ -114,21 +110,10 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target, gpr_mu_init(&channel->registered_call_mu); channel->registered_calls = NULL; - channel->max_message_length = DEFAULT_MAX_MESSAGE_LENGTH; grpc_compression_options_init(&channel->compression_options); if (args) { for (size_t i = 0; i < args->num_args; i++) { - if (0 == strcmp(args->args[i].key, GRPC_ARG_MAX_MESSAGE_LENGTH)) { - if (args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s ignored: it must be an integer", - GRPC_ARG_MAX_MESSAGE_LENGTH); - } else if (args->args[i].value.integer < 0) { - gpr_log(GPR_ERROR, "%s ignored: it must be >= 0", - GRPC_ARG_MAX_MESSAGE_LENGTH); - } else { - channel->max_message_length = (uint32_t)args->args[i].value.integer; - } - } else if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) { + if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) { if (args->args[i].type != GRPC_ARG_STRING) { gpr_log(GPR_ERROR, "%s ignored: it must be a string", GRPC_ARG_DEFAULT_AUTHORITY); @@ -371,7 +356,3 @@ grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) { return grpc_mdelem_from_metadata_strings(GRPC_MDSTR_GRPC_STATUS, grpc_mdstr_from_string(tmp)); } - -uint32_t grpc_channel_get_max_message_length(grpc_channel *channel) { - return channel->max_message_length; -} diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h index 4c62974346..23cc8656ca 100644 --- a/src/core/lib/surface/channel.h +++ b/src/core/lib/surface/channel.h @@ -64,7 +64,6 @@ grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel); The returned elem is owned by the caller. */ grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int status_code); -uint32_t grpc_channel_get_max_message_length(grpc_channel *channel); #ifdef GRPC_STREAM_REFCOUNT_DEBUG void grpc_channel_internal_ref(grpc_channel *channel, const char *reason); diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index 5397913a21..1f2769f871 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -45,6 +45,7 @@ #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/http_client_filter.h" #include "src/core/lib/channel/http_server_filter.h" +#include "src/core/lib/channel/message_size_filter.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/executor.h" @@ -97,6 +98,15 @@ static bool maybe_add_http_filter(grpc_channel_stack_builder *builder, } static void register_builtin_channel_init() { + grpc_channel_init_register_stage( + GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, + (void *)&grpc_message_size_filter); + grpc_channel_init_register_stage( + GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + prepend_filter, (void *)&grpc_message_size_filter); + grpc_channel_init_register_stage( + GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, + (void *)&grpc_message_size_filter); grpc_channel_init_register_stage( GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_compress_filter); diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 660e34d742..491e38c4cf 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -84,6 +84,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/channel/handshaker.c', 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', + 'src/core/lib/channel/message_size_filter.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', 'src/core/lib/debug/trace.c', diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c index 08d326ab4d..c8e0748f00 100644 --- a/test/core/end2end/tests/max_message_length.c +++ b/test/core/end2end/tests/max_message_length.c @@ -100,19 +100,22 @@ static void end_test(grpc_end2end_test_fixture *f) { grpc_completion_queue_destroy(f->cq); } -static void test_max_message_length(grpc_end2end_test_config config) { +static void test_max_message_length(grpc_end2end_test_config config, + bool send_limit) { + gpr_log(GPR_INFO, "testing with send_limit=%d", send_limit); + grpc_end2end_test_fixture f; - grpc_arg server_arg; - grpc_channel_args server_args; + grpc_arg channel_arg; + grpc_channel_args channel_args; grpc_call *c; - grpc_call *s; + grpc_call *s = NULL; cq_verifier *cqv; grpc_op ops[6]; grpc_op *op; gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer *recv_payload; + grpc_byte_buffer *recv_payload = NULL; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; @@ -123,14 +126,17 @@ static void test_max_message_length(grpc_end2end_test_config config) { size_t details_capacity = 0; int was_cancelled = 2; - server_arg.key = GRPC_ARG_MAX_MESSAGE_LENGTH; - server_arg.type = GRPC_ARG_INTEGER; - server_arg.value.integer = 5; + channel_arg.key = send_limit ? GRPC_ARG_MAX_SEND_MESSAGE_LENGTH + : GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH; + channel_arg.type = GRPC_ARG_INTEGER; + channel_arg.value.integer = 5; - server_args.num_args = 1; - server_args.args = &server_arg; + channel_args.num_args = 1; + channel_args.args = &channel_arg; - f = begin_test(config, "test_max_message_length", NULL, &server_args); + f = begin_test(config, "test_max_message_length", + send_limit ? &channel_args : NULL, + send_limit ? NULL : &channel_args); cqv = cq_verifier_create(f.cq); c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, @@ -175,6 +181,12 @@ static void test_max_message_length(grpc_end2end_test_config config) { error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); + if (send_limit) { + cq_expect_completion(cqv, tag(1), 1); + cq_verify(cqv); + goto done; + } + error = grpc_server_request_call(f.server, &s, &call_details, &request_metadata_recv, f.cq, f.cq, tag(101)); @@ -201,11 +213,12 @@ static void test_max_message_length(grpc_end2end_test_config config) { cq_expect_completion(cqv, tag(1), 1); cq_verify(cqv); - GPR_ASSERT(status != GRPC_STATUS_OK); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234")); GPR_ASSERT(was_cancelled == 1); - GPR_ASSERT(recv_payload == NULL); + +done: + GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT); gpr_free(details); grpc_metadata_array_destroy(&initial_metadata_recv); @@ -213,9 +226,10 @@ static void test_max_message_length(grpc_end2end_test_config config) { grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(recv_payload); grpc_call_destroy(c); - grpc_call_destroy(s); + if (s != NULL) grpc_call_destroy(s); cq_verifier_destroy(cqv); @@ -224,7 +238,8 @@ static void test_max_message_length(grpc_end2end_test_config config) { } void max_message_length(grpc_end2end_test_config config) { - test_max_message_length(config); + test_max_message_length(config, true); + test_max_message_length(config, false); } void max_message_length_pre_init(void) {} diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 50cebfa84e..d8e1dbc613 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -799,6 +799,7 @@ src/core/lib/channel/context.h \ src/core/lib/channel/handshaker.h \ src/core/lib/channel/http_client_filter.h \ src/core/lib/channel/http_server_filter.h \ +src/core/lib/channel/message_size_filter.h \ src/core/lib/compression/algorithm_metadata.h \ src/core/lib/compression/message_compress.h \ src/core/lib/debug/trace.h \ @@ -958,6 +959,7 @@ src/core/lib/channel/connected_channel.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ +src/core/lib/channel/message_size_filter.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ src/core/lib/debug/trace.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 84f7da8cb9..e3f43da8c7 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -5825,6 +5825,7 @@ "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", + "src/core/lib/channel/message_size_filter.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/message_compress.h", "src/core/lib/debug/trace.h", @@ -5923,6 +5924,8 @@ "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.c", "src/core/lib/channel/http_server_filter.h", + "src/core/lib/channel/message_size_filter.c", + "src/core/lib/channel/message_size_filter.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/compression.c", "src/core/lib/compression/message_compress.c", diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 298887e915..e8e3081897 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -308,6 +308,7 @@ + @@ -478,6 +479,8 @@ + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 539dbad360..f8d97e9ab0 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -28,6 +28,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\compression @@ -692,6 +695,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\compression diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index 84a71d217d..2e5fecc490 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -198,6 +198,7 @@ + @@ -321,6 +322,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 18fe926405..bfa0cdadcf 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -76,6 +76,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\compression @@ -470,6 +473,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\compression diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 6a89065654..f2bcac82ac 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -297,6 +297,7 @@ + @@ -445,6 +446,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 8325d910ec..679832388b 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -31,6 +31,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\compression @@ -599,6 +602,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\compression -- cgit v1.2.3 From 370ef8941e261a19c53446cc5d337f59dca657d2 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 23 Aug 2016 15:08:37 -0700 Subject: Fix portability problem. --- src/core/lib/channel/message_size_filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index 264c07ca8e..153f578a14 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -67,7 +67,7 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, if ((*calld->recv_message)->length > chand->max_recv_size) { char* message_string; gpr_asprintf(&message_string, "Received message larger than max (%lu)", - chand->max_recv_size); + (unsigned long)chand->max_recv_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_cancel_with_message( @@ -89,7 +89,7 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, op->send_message->length > chand->max_send_size) { char* message_string; gpr_asprintf(&message_string, "Sent message larger than max (%lu)", - chand->max_send_size); + (unsigned long)chand->max_send_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_cancel_with_message( -- cgit v1.2.3 From a6f1b98f2c125ed3df7397f89e6e5f9defc5c39a Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 24 Aug 2016 08:16:16 -0700 Subject: Set the right default max message sizes. Also use single-line comment style throughout the new files. --- src/core/lib/channel/message_size_filter.c | 69 +++++++++++++++--------------- src/core/lib/channel/message_size_filter.h | 63 ++++++++++++++------------- 2 files changed, 66 insertions(+), 66 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index 153f578a14..78aafc7d3d 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -1,34 +1,33 @@ -/* - * 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. - * - */ +// +// 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/lib/channel/message_size_filter.h" @@ -38,7 +37,7 @@ #include #include -/* the protobuf library will (by default) start warning at 100megs */ +// The protobuf library will (by default) start warning at 100 megs. #define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024) typedef struct call_data { @@ -85,7 +84,7 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, call_data* calld = elem->call_data; channel_data* chand = elem->channel_data; // Check max send message size. - if (op->send_message != NULL && chand->max_send_size > 0 && + if (op->send_message != NULL && op->send_message->length > chand->max_send_size) { char* message_string; gpr_asprintf(&message_string, "Sent message larger than max (%lu)", @@ -96,7 +95,7 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message); } // Inject callback for receiving a message. - if (op->recv_message_ready != NULL && chand->max_recv_size > 0) { + if (op->recv_message_ready != NULL) { calld->next_recv_message_ready = op->recv_message_ready; calld->recv_message = op->recv_message; op->recv_message_ready = &calld->recv_message_ready; @@ -127,6 +126,8 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx, GPR_ASSERT(!args->is_last); channel_data* chand = elem->channel_data; memset(chand, 0, sizeof(*chand)); + chand->max_send_size = DEFAULT_MAX_MESSAGE_LENGTH; + chand->max_recv_size = DEFAULT_MAX_MESSAGE_LENGTH; for (size_t i = 0; i < args->channel_args->num_args; ++i) { if (strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) { diff --git a/src/core/lib/channel/message_size_filter.h b/src/core/lib/channel/message_size_filter.h index 367a322b37..9460360b95 100644 --- a/src/core/lib/channel/message_size_filter.h +++ b/src/core/lib/channel/message_size_filter.h @@ -1,34 +1,33 @@ -/* - * 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. - * - */ +// +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// #ifndef GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H #define GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H @@ -37,4 +36,4 @@ extern const grpc_channel_filter grpc_message_size_filter; -#endif /* GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H */ +#endif // GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H -- cgit v1.2.3 From 500a466217760749aebf4a1204781aa36e8ded62 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 24 Aug 2016 14:28:08 -0700 Subject: Add filter to subchannel instead of main client channel. --- src/core/lib/surface/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index 1f2769f871..57cf6f5314 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -99,8 +99,8 @@ static bool maybe_add_http_filter(grpc_channel_stack_builder *builder, static void register_builtin_channel_init() { grpc_channel_init_register_stage( - GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, - (void *)&grpc_message_size_filter); + GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + prepend_filter, (void *)&grpc_message_size_filter); grpc_channel_init_register_stage( GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_message_size_filter); -- cgit v1.2.3 From 0002d8322260ad0ae4c7f4266ca7494194f12d45 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 25 Aug 2016 07:57:24 -0700 Subject: Fix crash caused by invoking receive callback with recv_message=NULL. --- src/core/lib/channel/message_size_filter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index 78aafc7d3d..10cb1998d1 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -63,7 +63,8 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, grpc_call_element* elem = user_data; call_data* calld = elem->call_data; channel_data* chand = elem->channel_data; - if ((*calld->recv_message)->length > chand->max_recv_size) { + if (*calld->recv_message != NULL && + (*calld->recv_message)->length > chand->max_recv_size) { char* message_string; gpr_asprintf(&message_string, "Received message larger than max (%lu)", (unsigned long)chand->max_recv_size); -- cgit v1.2.3 From 14c072ccc0ee33c26c55999344a501d2f1f2d93d Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 26 Aug 2016 08:31:34 -0700 Subject: Initial code to move deadline timer into a filter. Timer cancellation not working right -- will fix in subsequent commit. --- BUILD | 12 ++ CMakeLists.txt | 5 + Makefile | 6 + binding.gyp | 1 + build.yaml | 2 + config.m4 | 1 + gRPC-Core.podspec | 3 + grpc.gemspec | 2 + package.xml | 2 + src/core/lib/channel/deadline_filter.c | 209 +++++++++++++++++++++ src/core/lib/channel/deadline_filter.h | 40 ++++ src/core/lib/surface/call.c | 54 +----- src/core/lib/surface/init.c | 10 + src/python/grpcio/grpc_core_dependencies.py | 1 + tools/doxygen/Doxyfile.c++.internal | 2 + tools/doxygen/Doxyfile.core.internal | 2 + tools/run_tests/sources_and_headers.json | 3 + vsprojects/vcxproj/grpc++/grpc++.vcxproj | 3 + vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters | 6 + .../grpc++_unsecure/grpc++_unsecure.vcxproj | 3 + .../grpc++_unsecure.vcxproj.filters | 6 + vsprojects/vcxproj/grpc/grpc.vcxproj | 3 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 6 + .../vcxproj/grpc_test_util/grpc_test_util.vcxproj | 3 + .../grpc_test_util/grpc_test_util.vcxproj.filters | 6 + .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 3 + .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 + 27 files changed, 348 insertions(+), 52 deletions(-) create mode 100644 src/core/lib/channel/deadline_filter.c create mode 100644 src/core/lib/channel/deadline_filter.h (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index b36ce254e9..2b8c1180d2 100644 --- a/BUILD +++ b/BUILD @@ -165,6 +165,7 @@ cc_library( "src/core/lib/channel/compress_filter.h", "src/core/lib/channel/connected_channel.h", "src/core/lib/channel/context.h", + "src/core/lib/channel/deadline_filter.h", "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", @@ -320,6 +321,7 @@ cc_library( "src/core/lib/channel/channel_stack_builder.c", "src/core/lib/channel/compress_filter.c", "src/core/lib/channel/connected_channel.c", + "src/core/lib/channel/deadline_filter.c", "src/core/lib/channel/handshaker.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", @@ -560,6 +562,7 @@ cc_library( "src/core/lib/channel/compress_filter.h", "src/core/lib/channel/connected_channel.h", "src/core/lib/channel/context.h", + "src/core/lib/channel/deadline_filter.h", "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", @@ -702,6 +705,7 @@ cc_library( "src/core/lib/channel/channel_stack_builder.c", "src/core/lib/channel/compress_filter.c", "src/core/lib/channel/connected_channel.c", + "src/core/lib/channel/deadline_filter.c", "src/core/lib/channel/handshaker.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", @@ -914,6 +918,7 @@ cc_library( "src/core/lib/channel/compress_filter.h", "src/core/lib/channel/connected_channel.h", "src/core/lib/channel/context.h", + "src/core/lib/channel/deadline_filter.h", "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", @@ -1046,6 +1051,7 @@ cc_library( "src/core/lib/channel/channel_stack_builder.c", "src/core/lib/channel/compress_filter.c", "src/core/lib/channel/connected_channel.c", + "src/core/lib/channel/deadline_filter.c", "src/core/lib/channel/handshaker.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", @@ -1261,6 +1267,7 @@ cc_library( "src/core/lib/channel/compress_filter.h", "src/core/lib/channel/connected_channel.h", "src/core/lib/channel/context.h", + "src/core/lib/channel/deadline_filter.h", "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", @@ -1373,6 +1380,7 @@ cc_library( "src/core/lib/channel/channel_stack_builder.c", "src/core/lib/channel/compress_filter.c", "src/core/lib/channel/connected_channel.c", + "src/core/lib/channel/deadline_filter.c", "src/core/lib/channel/handshaker.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", @@ -1671,6 +1679,7 @@ cc_library( "src/core/lib/channel/compress_filter.h", "src/core/lib/channel/connected_channel.h", "src/core/lib/channel/context.h", + "src/core/lib/channel/deadline_filter.h", "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", @@ -1778,6 +1787,7 @@ cc_library( "src/core/lib/channel/channel_stack_builder.c", "src/core/lib/channel/compress_filter.c", "src/core/lib/channel/connected_channel.c", + "src/core/lib/channel/deadline_filter.c", "src/core/lib/channel/handshaker.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", @@ -2166,6 +2176,7 @@ objc_library( "src/core/lib/channel/channel_stack_builder.c", "src/core/lib/channel/compress_filter.c", "src/core/lib/channel/connected_channel.c", + "src/core/lib/channel/deadline_filter.c", "src/core/lib/channel/handshaker.c", "src/core/lib/channel/http_client_filter.c", "src/core/lib/channel/http_server_filter.c", @@ -2385,6 +2396,7 @@ objc_library( "src/core/lib/channel/compress_filter.h", "src/core/lib/channel/connected_channel.h", "src/core/lib/channel/context.h", + "src/core/lib/channel/deadline_filter.h", "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index fbcc6bbeae..6eda5fe4f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -296,6 +296,7 @@ add_library(grpc src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c + src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c @@ -554,6 +555,7 @@ add_library(grpc_cronet src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c + src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c @@ -786,6 +788,7 @@ add_library(grpc_unsecure src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c + src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c @@ -1043,6 +1046,7 @@ add_library(grpc++ src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c + src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c @@ -1400,6 +1404,7 @@ add_library(grpc++_unsecure src/core/lib/channel/channel_stack_builder.c src/core/lib/channel/compress_filter.c src/core/lib/channel/connected_channel.c + src/core/lib/channel/deadline_filter.c src/core/lib/channel/handshaker.c src/core/lib/channel/http_client_filter.c src/core/lib/channel/http_server_filter.c diff --git a/Makefile b/Makefile index c7622c0b9a..2a25ccb47f 100644 --- a/Makefile +++ b/Makefile @@ -2512,6 +2512,7 @@ LIBGRPC_SRC = \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ + src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ @@ -2788,6 +2789,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ + src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ @@ -3054,6 +3056,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ + src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ @@ -3247,6 +3250,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ + src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ @@ -3587,6 +3591,7 @@ LIBGRPC++_SRC = \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ + src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ @@ -4222,6 +4227,7 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ + src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ diff --git a/binding.gyp b/binding.gyp index 17dbfc0d38..1c29798bd5 100644 --- a/binding.gyp +++ b/binding.gyp @@ -568,6 +568,7 @@ 'src/core/lib/channel/channel_stack_builder.c', 'src/core/lib/channel/compress_filter.c', 'src/core/lib/channel/connected_channel.c', + 'src/core/lib/channel/deadline_filter.c', 'src/core/lib/channel/handshaker.c', 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', diff --git a/build.yaml b/build.yaml index 506a02920c..7f8a7d032b 100644 --- a/build.yaml +++ b/build.yaml @@ -161,6 +161,7 @@ filegroups: - src/core/lib/channel/compress_filter.h - src/core/lib/channel/connected_channel.h - src/core/lib/channel/context.h + - src/core/lib/channel/deadline_filter.h - src/core/lib/channel/handshaker.h - src/core/lib/channel/http_client_filter.h - src/core/lib/channel/http_server_filter.h @@ -241,6 +242,7 @@ filegroups: - src/core/lib/channel/channel_stack_builder.c - src/core/lib/channel/compress_filter.c - src/core/lib/channel/connected_channel.c + - src/core/lib/channel/deadline_filter.c - src/core/lib/channel/handshaker.c - src/core/lib/channel/http_client_filter.c - src/core/lib/channel/http_server_filter.c diff --git a/config.m4 b/config.m4 index b37658dc61..2fff96f14a 100644 --- a/config.m4 +++ b/config.m4 @@ -87,6 +87,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ + src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 86b811a3ec..5eee9c486e 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -258,6 +258,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/compress_filter.h', 'src/core/lib/channel/connected_channel.h', 'src/core/lib/channel/context.h', + 'src/core/lib/channel/deadline_filter.h', 'src/core/lib/channel/handshaker.h', 'src/core/lib/channel/http_client_filter.h', 'src/core/lib/channel/http_server_filter.h', @@ -417,6 +418,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/channel_stack_builder.c', 'src/core/lib/channel/compress_filter.c', 'src/core/lib/channel/connected_channel.c', + 'src/core/lib/channel/deadline_filter.c', 'src/core/lib/channel/handshaker.c', 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', @@ -619,6 +621,7 @@ Pod::Spec.new do |s| 'src/core/lib/channel/compress_filter.h', 'src/core/lib/channel/connected_channel.h', 'src/core/lib/channel/context.h', + 'src/core/lib/channel/deadline_filter.h', 'src/core/lib/channel/handshaker.h', 'src/core/lib/channel/http_client_filter.h', 'src/core/lib/channel/http_server_filter.h', diff --git a/grpc.gemspec b/grpc.gemspec index 8d74e36e7b..4b79e6cda0 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -177,6 +177,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/compress_filter.h ) s.files += %w( src/core/lib/channel/connected_channel.h ) s.files += %w( src/core/lib/channel/context.h ) + s.files += %w( src/core/lib/channel/deadline_filter.h ) s.files += %w( src/core/lib/channel/handshaker.h ) s.files += %w( src/core/lib/channel/http_client_filter.h ) s.files += %w( src/core/lib/channel/http_server_filter.h ) @@ -336,6 +337,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/channel_stack_builder.c ) s.files += %w( src/core/lib/channel/compress_filter.c ) s.files += %w( src/core/lib/channel/connected_channel.c ) + s.files += %w( src/core/lib/channel/deadline_filter.c ) s.files += %w( src/core/lib/channel/handshaker.c ) s.files += %w( src/core/lib/channel/http_client_filter.c ) s.files += %w( src/core/lib/channel/http_server_filter.c ) diff --git a/package.xml b/package.xml index 387afc3498..5f774ef5c5 100644 --- a/package.xml +++ b/package.xml @@ -185,6 +185,7 @@ + @@ -344,6 +345,7 @@ + diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c new file mode 100644 index 0000000000..032dea0221 --- /dev/null +++ b/src/core/lib/channel/deadline_filter.c @@ -0,0 +1,209 @@ +// +// 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/lib/channel/deadline_filter.h" + +#include +#include + +#include +#include + +#include "src/core/lib/iomgr/timer.h" + +// Used for both client and server filters. +typedef struct channel_data { +} channel_data; + +// Call data used for both client and server filter. +typedef struct base_call_data { + grpc_call_stack* call_stack; + bool timer_pending; + grpc_timer timer; +} base_call_data; + +// Additional call data used only for the server filter. +typedef struct server_call_data { + base_call_data base; // Must be first. + // The closure for receiving initial metadata. + grpc_closure recv_initial_metadata_ready; + // Received initial metadata batch. + grpc_metadata_batch* recv_initial_metadata; + // The original recv_initial_metadata_ready closure, which we chain to + // after our own closure is invoked. + grpc_closure* next_recv_initial_metadata_ready; +} server_call_data; + +// Constructor for channel_data. Used for both client and server filters. +static void init_channel_elem(grpc_exec_ctx* exec_ctx, + grpc_channel_element* elem, + grpc_channel_element_args* args) { + GPR_ASSERT(!args->is_last); +} + +// Destructor for channel_data. Used for both client and server filters. +static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, + grpc_channel_element* elem) { +} + +// Constructor for call_data. Used for both client and server filters. +static grpc_error *init_call_elem(grpc_exec_ctx* exec_ctx, + grpc_call_element* elem, + grpc_call_element_args* args) { + base_call_data* calld = elem->call_data; + // Note: size of call data is different between client and server. + memset(calld, 0, elem->filter->sizeof_call_data); + calld->call_stack = args->call_stack; + return GRPC_ERROR_NONE; +} + +// Destructor for call_data. Used for both client and server filters. +static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, + const grpc_call_final_info* final_info, + void* and_free_memory) { + base_call_data* calld = elem->call_data; +gpr_log(GPR_INFO, "==> destroy_call_elem()"); +// FIXME: this is not working -- timer holds a ref, so we won't get +// called until after timer pops + if (calld->timer_pending) +{ +gpr_log(GPR_INFO, "CANCELLING TIMER"); + grpc_timer_cancel(exec_ctx, &calld->timer); +} + +} + +// Timer callback. +static void timer_callback(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_call_element* elem = arg; + base_call_data* calld = elem->call_data; + calld->timer_pending = false; + if (error != GRPC_ERROR_CANCELLED) { +gpr_log(GPR_INFO, "DEADLINE EXCEEDED"); + gpr_slice message = gpr_slice_from_static_string("Deadline Exceeded"); + grpc_call_element_send_cancel_with_message( + exec_ctx, elem, GRPC_STATUS_DEADLINE_EXCEEDED, &message); + } +else gpr_log(GPR_INFO, "TIMER CANCELLED"); +gpr_log(GPR_INFO, "UNREF"); + GRPC_CALL_STACK_UNREF(exec_ctx, calld->call_stack, "deadline"); +} + +// Starts the deadline timer. +static void start_timer_if_needed(grpc_exec_ctx *exec_ctx, + grpc_call_element* elem, + gpr_timespec deadline) { + base_call_data* calld = elem->call_data; + deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); + if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) { + // Take a reference to the call stack, to be owned by the timer. +gpr_log(GPR_INFO, "REF"); + GRPC_CALL_STACK_REF(calld->call_stack, "deadline"); + grpc_timer_init(exec_ctx, &calld->timer, deadline, timer_callback, elem, + gpr_now(GPR_CLOCK_MONOTONIC)); + calld->timer_pending = true; + } +} + +// Method for starting a call op for client filter. +static void client_start_transport_stream_op(grpc_exec_ctx* exec_ctx, + grpc_call_element* elem, + grpc_transport_stream_op* op) { + // If we're sending initial metadata, get the deadline from the metadata + // and start the timer if needed. + if (op->send_initial_metadata != NULL) { + start_timer_if_needed(exec_ctx, elem, + op->send_initial_metadata->deadline); + } + // Chain to next filter. + grpc_call_next_op(exec_ctx, elem, op); +} + +// Callback for receiving initial metadata on the server. +static void recv_initial_metadata_ready(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_call_element* elem = arg; + server_call_data* calld = elem->call_data; + // Get deadline from metadata and start the timer if needed. + start_timer_if_needed(exec_ctx, elem, + calld->recv_initial_metadata->deadline); + // Invoke the next callback. + calld->next_recv_initial_metadata_ready->cb( + exec_ctx, calld->next_recv_initial_metadata_ready->cb_arg, error); +} + +// Method for starting a call op for server filter. +static void server_start_transport_stream_op(grpc_exec_ctx* exec_ctx, + grpc_call_element* elem, + grpc_transport_stream_op* op) { + server_call_data* calld = elem->call_data; + // If we're receiving initial metadata, we need to get the deadline + // from the recv_initial_metadata_ready callback. So we inject our + // own callback into that hook. + if (op->recv_initial_metadata_ready != NULL) { + calld->next_recv_initial_metadata_ready = op->recv_initial_metadata_ready; + calld->recv_initial_metadata = op->recv_initial_metadata; + grpc_closure_init(&calld->recv_initial_metadata_ready, + recv_initial_metadata_ready, elem); + op->recv_initial_metadata_ready = &calld->recv_initial_metadata_ready; + } + // Chain to next filter. + grpc_call_next_op(exec_ctx, elem, op); +} + +const grpc_channel_filter grpc_client_deadline_filter = { + client_start_transport_stream_op, + grpc_channel_next_op, + sizeof(base_call_data), + init_call_elem, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + destroy_call_elem, + sizeof(channel_data), + init_channel_elem, + destroy_channel_elem, + grpc_call_next_get_peer, + "deadline", +}; + +const grpc_channel_filter grpc_server_deadline_filter = { + server_start_transport_stream_op, + grpc_channel_next_op, + sizeof(server_call_data), + init_call_elem, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + destroy_call_elem, + sizeof(channel_data), + init_channel_elem, + destroy_channel_elem, + grpc_call_next_get_peer, + "deadline", +}; diff --git a/src/core/lib/channel/deadline_filter.h b/src/core/lib/channel/deadline_filter.h new file mode 100644 index 0000000000..323cb4e10c --- /dev/null +++ b/src/core/lib/channel/deadline_filter.h @@ -0,0 +1,40 @@ +// +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H +#define GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H + +#include "src/core/lib/channel/channel_stack.h" + +extern const grpc_channel_filter grpc_client_deadline_filter; +extern const grpc_channel_filter grpc_server_deadline_filter; + +#endif // GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 772681109a..c05ed67c43 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -122,8 +122,6 @@ struct grpc_call { /* client or server call */ bool is_client; - /* is the alarm set */ - bool have_alarm; /** has grpc_call_destroy been called */ bool destroy_called; /** flag indicating that cancellation is inherited */ @@ -166,9 +164,6 @@ struct grpc_call { /* Contexts for various subsystems (security, tracing, ...). */ grpc_call_context_element context[GRPC_CONTEXT_COUNT]; - /* Deadline alarm - if have_alarm is non-zero */ - grpc_timer alarm; - /* for the client, extra metadata is initial metadata; for the server, it's trailing metadata */ grpc_linked_mdelem send_extra_metadata[MAX_SEND_EXTRA_METADATA_COUNT]; @@ -211,8 +206,6 @@ struct grpc_call { #define CALL_FROM_TOP_ELEM(top_elem) \ CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem)) -static void set_deadline_alarm(grpc_exec_ctx *exec_ctx, grpc_call *call, - gpr_timespec deadline); static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call, grpc_transport_stream_op *op); static grpc_call_error cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c, @@ -260,7 +253,7 @@ grpc_call *grpc_call_create( call->metadata_batch[i][j].deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); } } - call->send_deadline = + send_deadline = gpr_convert_clock_type(send_deadline, GPR_CLOCK_MONOTONIC); GRPC_CHANNEL_INTERNAL_REF(channel, "call"); /* initial refcount dropped by grpc_call_destroy */ @@ -334,10 +327,7 @@ grpc_call *grpc_call_create( gpr_mu_unlock(&parent_call->mu); } - if (gpr_time_cmp(send_deadline, gpr_inf_future(send_deadline.clock_type)) != - 0) { - set_deadline_alarm(&exec_ctx, call, send_deadline); - } + call->send_deadline = send_deadline; grpc_exec_ctx_finish(&exec_ctx); GPR_TIMER_END("grpc_call_create", 0); return call; @@ -736,9 +726,6 @@ void grpc_call_destroy(grpc_call *c) { gpr_mu_lock(&c->mu); GPR_ASSERT(!c->destroy_called); c->destroy_called = 1; - if (c->have_alarm) { - grpc_timer_cancel(&exec_ctx, &c->alarm); - } cancel = !c->received_final_op; gpr_mu_unlock(&c->mu); if (cancel) grpc_call_cancel(c, NULL); @@ -897,32 +884,6 @@ grpc_call *grpc_call_from_top_element(grpc_call_element *elem) { return CALL_FROM_TOP_ELEM(elem); } -static void call_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - grpc_call *call = arg; - gpr_mu_lock(&call->mu); - call->have_alarm = 0; - if (error != GRPC_ERROR_CANCELLED) { - cancel_with_status(exec_ctx, call, GRPC_STATUS_DEADLINE_EXCEEDED, - "Deadline Exceeded"); - } - gpr_mu_unlock(&call->mu); - GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "alarm"); -} - -static void set_deadline_alarm(grpc_exec_ctx *exec_ctx, grpc_call *call, - gpr_timespec deadline) { - if (call->have_alarm) { - gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice"); - assert(0); - return; - } - GRPC_CALL_INTERNAL_REF(call, "alarm"); - call->have_alarm = 1; - call->send_deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); - grpc_timer_init(exec_ctx, &call->alarm, call->send_deadline, call_alarm, call, - gpr_now(GPR_CLOCK_MONOTONIC)); -} - /* we offset status by a small amount when storing it into transport metadata as metadata cannot store a 0 value (which is used as OK for grpc_status_codes */ @@ -1271,14 +1232,6 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx, GPR_TIMER_BEGIN("validate_filtered_metadata", 0); validate_filtered_metadata(exec_ctx, bctl); GPR_TIMER_END("validate_filtered_metadata", 0); - - if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) != - 0 && - !call->is_client) { - GPR_TIMER_BEGIN("set_deadline_alarm", 0); - set_deadline_alarm(exec_ctx, call, md->deadline); - GPR_TIMER_END("set_deadline_alarm", 0); - } } call->has_initial_md_been_received = true; @@ -1326,9 +1279,6 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_metadata_batch_filter(md, recv_trailing_filter, call); call->received_final_op = true; - if (call->have_alarm) { - grpc_timer_cancel(exec_ctx, &call->alarm); - } /* propagate cancellation to any interested children */ child_call = call->first_child; if (child_call != NULL) { diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index 5397913a21..4a3c03b915 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -43,6 +43,7 @@ #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/compress_filter.h" #include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/channel/deadline_filter.h" #include "src/core/lib/channel/http_client_filter.h" #include "src/core/lib/channel/http_server_filter.h" #include "src/core/lib/debug/trace.h" @@ -97,6 +98,15 @@ static bool maybe_add_http_filter(grpc_channel_stack_builder *builder, } static void register_builtin_channel_init() { + grpc_channel_init_register_stage( + GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + prepend_filter, (void *)&grpc_client_deadline_filter); + grpc_channel_init_register_stage( + GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + prepend_filter, (void *)&grpc_client_deadline_filter); + grpc_channel_init_register_stage( + GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, + (void *)&grpc_server_deadline_filter); grpc_channel_init_register_stage( GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_compress_filter); diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 7ae76f52c1..bc8e8ea444 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -81,6 +81,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/channel/channel_stack_builder.c', 'src/core/lib/channel/compress_filter.c', 'src/core/lib/channel/connected_channel.c', + 'src/core/lib/channel/deadline_filter.c', 'src/core/lib/channel/handshaker.c', 'src/core/lib/channel/http_client_filter.c', 'src/core/lib/channel/http_server_filter.c', diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 12eb651384..ebaca73ed2 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -879,6 +879,7 @@ src/core/lib/channel/channel_stack_builder.h \ src/core/lib/channel/compress_filter.h \ src/core/lib/channel/connected_channel.h \ src/core/lib/channel/context.h \ +src/core/lib/channel/deadline_filter.h \ src/core/lib/channel/handshaker.h \ src/core/lib/channel/http_client_filter.h \ src/core/lib/channel/http_server_filter.h \ @@ -991,6 +992,7 @@ src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ +src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 426c6d91e3..71ac349616 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -796,6 +796,7 @@ src/core/lib/channel/channel_stack_builder.h \ src/core/lib/channel/compress_filter.h \ src/core/lib/channel/connected_channel.h \ src/core/lib/channel/context.h \ +src/core/lib/channel/deadline_filter.h \ src/core/lib/channel/handshaker.h \ src/core/lib/channel/http_client_filter.h \ src/core/lib/channel/http_server_filter.h \ @@ -955,6 +956,7 @@ src/core/lib/channel/channel_stack.c \ src/core/lib/channel/channel_stack_builder.c \ src/core/lib/channel/compress_filter.c \ src/core/lib/channel/connected_channel.c \ +src/core/lib/channel/deadline_filter.c \ src/core/lib/channel/handshaker.c \ src/core/lib/channel/http_client_filter.c \ src/core/lib/channel/http_server_filter.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 11daf24e0a..adc37dff83 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -5823,6 +5823,7 @@ "src/core/lib/channel/compress_filter.h", "src/core/lib/channel/connected_channel.h", "src/core/lib/channel/context.h", + "src/core/lib/channel/deadline_filter.h", "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.h", "src/core/lib/channel/http_server_filter.h", @@ -5919,6 +5920,8 @@ "src/core/lib/channel/connected_channel.c", "src/core/lib/channel/connected_channel.h", "src/core/lib/channel/context.h", + "src/core/lib/channel/deadline_filter.c", + "src/core/lib/channel/deadline_filter.h", "src/core/lib/channel/handshaker.c", "src/core/lib/channel/handshaker.h", "src/core/lib/channel/http_client_filter.c", diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index 321a403c49..baee3a309e 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -379,6 +379,7 @@ + @@ -531,6 +532,8 @@ + + diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index b34ca03a53..fec96cda4c 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -115,6 +115,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\channel @@ -731,6 +734,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\channel diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index a7bb3ef23d..a1a42d82b9 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -375,6 +375,7 @@ + @@ -517,6 +518,8 @@ + + diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index 4ad0ae31d9..78c0a924ed 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -100,6 +100,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\channel @@ -704,6 +707,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\channel diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 252704756d..e892f0d57d 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -305,6 +305,7 @@ + @@ -472,6 +473,8 @@ + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 1fdf0f5eca..d4a6d8834a 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -19,6 +19,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\channel @@ -683,6 +686,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\channel diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index 80dd6b2dcb..1a74cf4b39 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -196,6 +196,7 @@ + @@ -316,6 +317,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 8dc28d1cb9..ce5a1326dc 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -67,6 +67,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\channel @@ -464,6 +467,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\channel diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index fffb409781..96b6569e3e 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -295,6 +295,7 @@ + @@ -440,6 +441,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 8c8afb6b86..0e2c27779b 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -22,6 +22,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\channel @@ -593,6 +596,9 @@ src\core\lib\channel + + src\core\lib\channel + src\core\lib\channel -- cgit v1.2.3 From c3c6fafef8485dd5357d4771b53e25621f0d8080 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 26 Aug 2016 09:20:49 -0700 Subject: Add grpc_channel_arg_get_integer() utility function. --- src/core/ext/client_config/subchannel.c | 26 +++--- .../transport/chttp2/transport/chttp2_transport.c | 92 ++++++++++------------ src/core/lib/channel/channel_args.c | 18 +++++ src/core/lib/channel/channel_args.h | 8 ++ src/core/lib/channel/message_size_filter.c | 28 ++----- 5 files changed, 87 insertions(+), 85 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c index df35904b85..3854e757c2 100644 --- a/src/core/ext/client_config/subchannel.c +++ b/src/core/ext/client_config/subchannel.c @@ -33,6 +33,7 @@ #include "src/core/ext/client_config/subchannel.h" +#include #include #include @@ -347,21 +348,16 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, } if (0 == strcmp(c->args->args[i].key, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS)) { - if (c->args->args[i].type == GRPC_ARG_INTEGER) { - if (c->args->args[i].value.integer >= 0) { - gpr_backoff_init( - &c->backoff_state, GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER, - GRPC_SUBCHANNEL_RECONNECT_JITTER, - GPR_MIN(c->args->args[i].value.integer, - GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000), - c->args->args[i].value.integer); - } else { - gpr_log(GPR_ERROR, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS - " : must be non-negative"); - } - } else { - gpr_log(GPR_ERROR, - GRPC_ARG_MAX_RECONNECT_BACKOFF_MS " : must be an integer"); + const grpc_integer_options options = {-1, 0, INT_MAX}; + const int value = grpc_channel_arg_get_integer(&c->args->args[i], + options); + if (value >= 0) { + gpr_backoff_init( + &c->backoff_state, GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER, + GRPC_SUBCHANNEL_RECONNECT_JITTER, + GPR_MIN(value, + GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000), + value); } } } diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 0e8dfb7d96..21759dd9af 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -33,6 +33,7 @@ #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include #include #include #include @@ -46,6 +47,7 @@ #include "src/core/ext/transport/chttp2/transport/http2_errors.h" #include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/status_conversion.h" +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" @@ -337,76 +339,66 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, if (is_client) { gpr_log(GPR_ERROR, "%s: is ignored on the client", GRPC_ARG_MAX_CONCURRENT_STREAMS); - } else if (channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s: must be an integer", - GRPC_ARG_MAX_CONCURRENT_STREAMS); } else { - push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, - (uint32_t)channel_args->args[i].value.integer); + const grpc_integer_options options = {-1, 0, INT_MAX}; + const int value = grpc_channel_arg_get_integer(&channel_args->args[i], + options); + if (value >= 0) { + push_setting(exec_ctx, t, + GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, + (uint32_t)value); + } } } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) { - if (channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s: must be an integer", - GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER); - } else if ((t->global.next_stream_id & 1) != - (channel_args->args[i].value.integer & 1)) { - gpr_log(GPR_ERROR, "%s: low bit must be %d on %s", - GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, - t->global.next_stream_id & 1, - is_client ? "client" : "server"); - } else { - t->global.next_stream_id = - (uint32_t)channel_args->args[i].value.integer; + const grpc_integer_options options = {-1, 0, INT_MAX}; + const int value = grpc_channel_arg_get_integer(&channel_args->args[i], + options); + if (value >= 0) { + if ((t->global.next_stream_id & 1) != (value & 1)) { + gpr_log(GPR_ERROR, "%s: low bit must be %d on %s", + GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, + t->global.next_stream_id & 1, + is_client ? "client" : "server"); + } else { + t->global.next_stream_id = (uint32_t)value; + } } } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES)) { - if (channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s: must be an integer", - GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES); - } else if (channel_args->args[i].value.integer <= 5) { - gpr_log(GPR_ERROR, "%s: must be at least 5", - GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES); - } else { - t->global.stream_lookahead = - (uint32_t)channel_args->args[i].value.integer; + const grpc_integer_options options = {-1, 5, INT_MAX}; + const int value = grpc_channel_arg_get_integer(&channel_args->args[i], + options); + if (value >= 0) { + t->global.stream_lookahead = (uint32_t)value; } } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER)) { - if (channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s: must be an integer", - GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER); - } else if (channel_args->args[i].value.integer < 0) { - gpr_log(GPR_ERROR, "%s: must be non-negative", - GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER); - } else { + const grpc_integer_options options = {-1, 0, INT_MAX}; + const int value = grpc_channel_arg_get_integer(&channel_args->args[i], + options); + if (value >= 0) { push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE, - (uint32_t)channel_args->args[i].value.integer); + (uint32_t)value); } } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) { - if (channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s: must be an integer", - GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER); - } else if (channel_args->args[i].value.integer < 0) { - gpr_log(GPR_ERROR, "%s: must be non-negative", - GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER); - } else { + const grpc_integer_options options = {-1, 0, INT_MAX}; + const int value = grpc_channel_arg_get_integer(&channel_args->args[i], + options); + if (value >= 0) { grpc_chttp2_hpack_compressor_set_max_usable_size( &t->writing.hpack_compressor, - (uint32_t)channel_args->args[i].value.integer); + (uint32_t)value); } } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_MAX_METADATA_SIZE)) { - if (channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s: must be an integer", - GRPC_ARG_MAX_METADATA_SIZE); - } else if (channel_args->args[i].value.integer < 0) { - gpr_log(GPR_ERROR, "%s: must be non-negative", - GRPC_ARG_MAX_METADATA_SIZE); - } else { + const grpc_integer_options options = {-1, 0, INT_MAX}; + const int value = grpc_channel_arg_get_integer(&channel_args->args[i], + options); + if (value >= 0) { push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, - (uint32_t)channel_args->args[i].value.integer); + (uint32_t)value); } } } diff --git a/src/core/lib/channel/channel_args.c b/src/core/lib/channel/channel_args.c index 79ceeb66b3..3a56b1ff20 100644 --- a/src/core/lib/channel/channel_args.c +++ b/src/core/lib/channel/channel_args.c @@ -271,3 +271,21 @@ int grpc_channel_args_compare(const grpc_channel_args *a, } return 0; } + +int grpc_channel_arg_get_integer(grpc_arg *arg, grpc_integer_options options) { + if (arg->type != GRPC_ARG_INTEGER) { + gpr_log(GPR_ERROR, "%s ignored: it must be an integer", arg->key); + return options.default_value; + } + if (arg->value.integer < options.min_value) { + gpr_log(GPR_ERROR, "%s ignored: it must be >= %d", arg->key, + options.min_value); + return options.default_value; + } + if (arg->value.integer > options.max_value) { + gpr_log(GPR_ERROR, "%s ignored: it must be <= %d", arg->key, + options.max_value); + return options.default_value; + } + return arg->value.integer; +} diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h index aec61ee7c6..71fde5ad7e 100644 --- a/src/core/lib/channel/channel_args.h +++ b/src/core/lib/channel/channel_args.h @@ -89,4 +89,12 @@ uint32_t grpc_channel_args_compression_algorithm_get_states( int grpc_channel_args_compare(const grpc_channel_args *a, const grpc_channel_args *b); +/** Returns the value of \a arg, subject to the contraints in \a options. */ +typedef struct grpc_integer_options { + int default_value; // Return this if value is outside of expected bounds. + int min_value; + int max_value; +} grpc_integer_options; +int grpc_channel_arg_get_integer(grpc_arg *arg, grpc_integer_options options); + #endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H */ diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index 10cb1998d1..ee9e3ee734 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -31,12 +31,15 @@ #include "src/core/lib/channel/message_size_filter.h" +#include #include #include #include #include +#include "src/core/lib/channel/channel_args.h" + // The protobuf library will (by default) start warning at 100 megs. #define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024) @@ -129,32 +132,17 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx, memset(chand, 0, sizeof(*chand)); chand->max_send_size = DEFAULT_MAX_MESSAGE_LENGTH; chand->max_recv_size = DEFAULT_MAX_MESSAGE_LENGTH; + const grpc_integer_options options = {DEFAULT_MAX_MESSAGE_LENGTH, 0, INT_MAX}; for (size_t i = 0; i < args->channel_args->num_args; ++i) { if (strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) { - if (args->channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s ignored: it must be an integer", - GRPC_ARG_MAX_SEND_MESSAGE_LENGTH); - } else if (args->channel_args->args[i].value.integer < 0) { - gpr_log(GPR_ERROR, "%s ignored: it must be >= 0", - GRPC_ARG_MAX_SEND_MESSAGE_LENGTH); - } else { - chand->max_send_size = - (size_t)args->channel_args->args[i].value.integer; - } + chand->max_send_size = (size_t)grpc_channel_arg_get_integer( + &args->channel_args->args[i], options); } if (strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) { - if (args->channel_args->args[i].type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s ignored: it must be an integer", - GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH); - } else if (args->channel_args->args[i].value.integer < 0) { - gpr_log(GPR_ERROR, "%s ignored: it must be >= 0", - GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH); - } else { - chand->max_recv_size = - (size_t)args->channel_args->args[i].value.integer; - } + chand->max_recv_size = (size_t)grpc_channel_arg_get_integer( + &args->channel_args->args[i], options); } } } -- cgit v1.2.3 From d2b4533df27c54fc782be88b0b0ea581066fac40 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 26 Aug 2016 11:18:00 -0700 Subject: Cancel deadline timer from on_complete instead of destroy_call_elem(). --- src/core/lib/channel/deadline_filter.c | 49 ++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 14 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index 032dea0221..852fbaf003 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -45,9 +45,18 @@ typedef struct channel_data { // Call data used for both client and server filter. typedef struct base_call_data { + // We take a reference to the call stack for the timer callback. grpc_call_stack* call_stack; + // True if the timer callback is currently pending. bool timer_pending; + // The deadline timer. grpc_timer timer; + // Closure to invoke when the call is complete. + // We use this to cancel the timer. + grpc_closure on_complete; + // The original on_complete closure, which we chain to after our own + // closure is invoked. + grpc_closure* next_on_complete; } base_call_data; // Additional call data used only for the server filter. @@ -89,16 +98,6 @@ static grpc_error *init_call_elem(grpc_exec_ctx* exec_ctx, static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_final_info* final_info, void* and_free_memory) { - base_call_data* calld = elem->call_data; -gpr_log(GPR_INFO, "==> destroy_call_elem()"); -// FIXME: this is not working -- timer holds a ref, so we won't get -// called until after timer pops - if (calld->timer_pending) -{ -gpr_log(GPR_INFO, "CANCELLING TIMER"); - grpc_timer_cancel(exec_ctx, &calld->timer); -} - } // Timer callback. @@ -108,13 +107,10 @@ static void timer_callback(grpc_exec_ctx *exec_ctx, void *arg, base_call_data* calld = elem->call_data; calld->timer_pending = false; if (error != GRPC_ERROR_CANCELLED) { -gpr_log(GPR_INFO, "DEADLINE EXCEEDED"); gpr_slice message = gpr_slice_from_static_string("Deadline Exceeded"); grpc_call_element_send_cancel_with_message( exec_ctx, elem, GRPC_STATUS_DEADLINE_EXCEEDED, &message); } -else gpr_log(GPR_INFO, "TIMER CANCELLED"); -gpr_log(GPR_INFO, "UNREF"); GRPC_CALL_STACK_UNREF(exec_ctx, calld->call_stack, "deadline"); } @@ -126,7 +122,6 @@ static void start_timer_if_needed(grpc_exec_ctx *exec_ctx, deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) { // Take a reference to the call stack, to be owned by the timer. -gpr_log(GPR_INFO, "REF"); GRPC_CALL_STACK_REF(calld->call_stack, "deadline"); grpc_timer_init(exec_ctx, &calld->timer, deadline, timer_callback, elem, gpr_now(GPR_CLOCK_MONOTONIC)); @@ -134,16 +129,35 @@ gpr_log(GPR_INFO, "REF"); } } +// Callback run when the call is complete. +static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + base_call_data* calld = arg; + if (calld->timer_pending) { + grpc_timer_cancel(exec_ctx, &calld->timer); + calld->timer_pending = false; + } + // Invoke the next callback. + calld->next_on_complete->cb(exec_ctx, calld->next_on_complete->cb_arg, error); +} + // Method for starting a call op for client filter. static void client_start_transport_stream_op(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op) { + base_call_data* calld = elem->call_data; // If we're sending initial metadata, get the deadline from the metadata // and start the timer if needed. if (op->send_initial_metadata != NULL) { start_timer_if_needed(exec_ctx, elem, op->send_initial_metadata->deadline); } + // Make sure we know when the call is complete, so that we can cancel + // the timer. + if (op->recv_trailing_metadata != NULL) { + calld->next_on_complete = op->on_complete; + grpc_closure_init(&calld->on_complete, on_complete, calld); + op->on_complete = &calld->on_complete; + } // Chain to next filter. grpc_call_next_op(exec_ctx, elem, op); } @@ -176,6 +190,13 @@ static void server_start_transport_stream_op(grpc_exec_ctx* exec_ctx, recv_initial_metadata_ready, elem); op->recv_initial_metadata_ready = &calld->recv_initial_metadata_ready; } + // Make sure we know when the call is complete, so that we can cancel + // the timer. + if (op->send_trailing_metadata != NULL) { + calld->base.next_on_complete = op->on_complete; + grpc_closure_init(&calld->base.on_complete, on_complete, calld); + op->on_complete = &calld->base.on_complete; + } // Chain to next filter. grpc_call_next_op(exec_ctx, elem, op); } -- cgit v1.2.3 From ee7000a5605bd7512259922c59705f13e04066e5 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 26 Aug 2016 13:37:09 -0700 Subject: Switch back to C-style comment to appease check_include_guards.py. --- src/core/lib/channel/message_size_filter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/message_size_filter.h b/src/core/lib/channel/message_size_filter.h index 9460360b95..a88ff7f81a 100644 --- a/src/core/lib/channel/message_size_filter.h +++ b/src/core/lib/channel/message_size_filter.h @@ -36,4 +36,4 @@ extern const grpc_channel_filter grpc_message_size_filter; -#endif // GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H +#endif /* GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H */ -- cgit v1.2.3 From d59a5fc9ee39b32bcb076e80ff81d9e3170bc9cb Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Mon, 29 Aug 2016 10:55:57 -0700 Subject: Fix build problems when refcount debugging is enabled. --- src/core/ext/client_config/subchannel.c | 4 ++-- src/core/lib/surface/completion_queue.h | 2 ++ src/core/lib/transport/transport.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c index df35904b85..3d4318774b 100644 --- a/src/core/ext/client_config/subchannel.c +++ b/src/core/ext/client_config/subchannel.c @@ -219,8 +219,8 @@ static gpr_atm ref_mutate(grpc_subchannel *c, gpr_atm delta, : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta); #ifdef GRPC_STREAM_REFCOUNT_DEBUG gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "SUBCHANNEL: %p % 12s 0x%08x -> 0x%08x [%s]", c, purpose, old_val, - old_val + delta, reason); + "SUBCHANNEL: %p %12s 0x%08d -> 0x%08d [%s]", c, purpose, (int)old_val, + (int)(old_val + delta), reason); #endif return old_val; } diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h index 3049284f68..4dbf3aae63 100644 --- a/src/core/lib/surface/completion_queue.h +++ b/src/core/lib/surface/completion_queue.h @@ -57,6 +57,8 @@ typedef struct grpc_cq_completion { uintptr_t next; } grpc_cq_completion; +//#define GRPC_CQ_REF_COUNT_DEBUG + #ifdef GRPC_CQ_REF_COUNT_DEBUG void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason, const char *file, int line); diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c index 857c3909d2..36672bdbc5 100644 --- a/src/core/lib/transport/transport.c +++ b/src/core/lib/transport/transport.c @@ -43,7 +43,7 @@ void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) { gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count); gpr_log(GPR_DEBUG, "%s %p:%p REF %d->%d %s", refcount->object_type, - refcount, refcount->destroy.cb_arg, val, val + 1, reason); + refcount, refcount->destroy.cb_arg, (int)val, (int)val + 1, reason); #else void grpc_stream_ref(grpc_stream_refcount *refcount) { #endif @@ -55,7 +55,7 @@ void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount, const char *reason) { gpr_atm val = gpr_atm_no_barrier_load(&refcount->refs.count); gpr_log(GPR_DEBUG, "%s %p:%p UNREF %d->%d %s", refcount->object_type, - refcount, refcount->destroy.cb_arg, val, val - 1, reason); + refcount, refcount->destroy.cb_arg, (int)val, (int)val - 1, reason); #else void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount) { -- cgit v1.2.3 From 1bbe6cb143e98805a5f9dc2745a45bff85bd768c Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 31 Aug 2016 08:33:37 -0700 Subject: Add locking. Add cancellation check. Use grpc_call_element_send_cancel(). --- src/core/lib/channel/deadline_filter.c | 105 +++++++++++++++++++++------------ src/core/lib/transport/transport.c | 4 ++ 2 files changed, 72 insertions(+), 37 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index 852fbaf003..9dff1c4d63 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -35,6 +35,7 @@ #include #include +#include #include #include "src/core/lib/iomgr/timer.h" @@ -47,6 +48,8 @@ typedef struct channel_data { typedef struct base_call_data { // We take a reference to the call stack for the timer callback. grpc_call_stack* call_stack; + // Guards access to timer_pending and timer. + gpr_mu timer_mu; // True if the timer callback is currently pending. bool timer_pending; // The deadline timer. @@ -91,6 +94,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx* exec_ctx, // Note: size of call data is different between client and server. memset(calld, 0, elem->filter->sizeof_call_data); calld->call_stack = args->call_stack; + gpr_mu_init(&calld->timer_mu); return GRPC_ERROR_NONE; } @@ -98,6 +102,8 @@ static grpc_error *init_call_elem(grpc_exec_ctx* exec_ctx, static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_final_info* final_info, void* and_free_memory) { + base_call_data* calld = elem->call_data; + gpr_mu_destroy(&calld->timer_mu); } // Timer callback. @@ -105,13 +111,13 @@ static void timer_callback(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_call_element* elem = arg; base_call_data* calld = elem->call_data; + gpr_mu_lock(&calld->timer_mu); calld->timer_pending = false; + gpr_mu_unlock(&calld->timer_mu); if (error != GRPC_ERROR_CANCELLED) { - gpr_slice message = gpr_slice_from_static_string("Deadline Exceeded"); - grpc_call_element_send_cancel_with_message( - exec_ctx, elem, GRPC_STATUS_DEADLINE_EXCEEDED, &message); + grpc_call_element_send_cancel(exec_ctx, elem); } - GRPC_CALL_STACK_UNREF(exec_ctx, calld->call_stack, "deadline"); + GRPC_CALL_STACK_UNREF(exec_ctx, calld->call_stack, "deadline_timer"); } // Starts the deadline timer. @@ -122,20 +128,30 @@ static void start_timer_if_needed(grpc_exec_ctx *exec_ctx, deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) { // Take a reference to the call stack, to be owned by the timer. - GRPC_CALL_STACK_REF(calld->call_stack, "deadline"); + GRPC_CALL_STACK_REF(calld->call_stack, "deadline_timer"); + gpr_mu_lock(&calld->timer_mu); + calld->timer_pending = true; grpc_timer_init(exec_ctx, &calld->timer, deadline, timer_callback, elem, gpr_now(GPR_CLOCK_MONOTONIC)); - calld->timer_pending = true; + gpr_mu_unlock(&calld->timer_mu); } } -// Callback run when the call is complete. -static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - base_call_data* calld = arg; +// Cancels the deadline timer. +static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx, + base_call_data* calld) { + gpr_mu_lock(&calld->timer_mu); if (calld->timer_pending) { grpc_timer_cancel(exec_ctx, &calld->timer); calld->timer_pending = false; } + gpr_mu_unlock(&calld->timer_mu); +} + +// Callback run when the call is complete. +static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + base_call_data* calld = arg; + cancel_timer_if_needed(exec_ctx, calld); // Invoke the next callback. calld->next_on_complete->cb(exec_ctx, calld->next_on_complete->cb_arg, error); } @@ -145,18 +161,24 @@ static void client_start_transport_stream_op(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op) { base_call_data* calld = elem->call_data; - // If we're sending initial metadata, get the deadline from the metadata - // and start the timer if needed. - if (op->send_initial_metadata != NULL) { - start_timer_if_needed(exec_ctx, elem, - op->send_initial_metadata->deadline); - } - // Make sure we know when the call is complete, so that we can cancel - // the timer. - if (op->recv_trailing_metadata != NULL) { - calld->next_on_complete = op->on_complete; - grpc_closure_init(&calld->on_complete, on_complete, calld); - op->on_complete = &calld->on_complete; + // If the call is cancelled or closed, cancel the timer. + if (op->cancel_error != GRPC_ERROR_NONE || + op->close_error != GRPC_ERROR_NONE) { + cancel_timer_if_needed(exec_ctx, calld); + } else { + // If we're sending initial metadata, get the deadline from the metadata + // and start the timer if needed. + if (op->send_initial_metadata != NULL) { + start_timer_if_needed(exec_ctx, elem, + op->send_initial_metadata->deadline); + } + // Make sure we know when the call is complete, so that we can cancel + // the timer. + if (op->recv_trailing_metadata != NULL) { + calld->next_on_complete = op->on_complete; + grpc_closure_init(&calld->on_complete, on_complete, calld); + op->on_complete = &calld->on_complete; + } } // Chain to next filter. grpc_call_next_op(exec_ctx, elem, op); @@ -180,22 +202,31 @@ static void server_start_transport_stream_op(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op) { server_call_data* calld = elem->call_data; - // If we're receiving initial metadata, we need to get the deadline - // from the recv_initial_metadata_ready callback. So we inject our - // own callback into that hook. - if (op->recv_initial_metadata_ready != NULL) { - calld->next_recv_initial_metadata_ready = op->recv_initial_metadata_ready; - calld->recv_initial_metadata = op->recv_initial_metadata; - grpc_closure_init(&calld->recv_initial_metadata_ready, - recv_initial_metadata_ready, elem); - op->recv_initial_metadata_ready = &calld->recv_initial_metadata_ready; - } - // Make sure we know when the call is complete, so that we can cancel - // the timer. - if (op->send_trailing_metadata != NULL) { - calld->base.next_on_complete = op->on_complete; - grpc_closure_init(&calld->base.on_complete, on_complete, calld); - op->on_complete = &calld->base.on_complete; + // If the call is cancelled or closed, cancel the timer. + if (op->cancel_error != GRPC_ERROR_NONE || + op->close_error != GRPC_ERROR_NONE) { + cancel_timer_if_needed(exec_ctx, &calld->base); + } else { + // If we're receiving initial metadata, we need to get the deadline + // from the recv_initial_metadata_ready callback. So we inject our + // own callback into that hook. + if (op->recv_initial_metadata_ready != NULL) { + calld->next_recv_initial_metadata_ready = op->recv_initial_metadata_ready; + calld->recv_initial_metadata = op->recv_initial_metadata; + grpc_closure_init(&calld->recv_initial_metadata_ready, + recv_initial_metadata_ready, elem); + op->recv_initial_metadata_ready = &calld->recv_initial_metadata_ready; + } + // Make sure we know when the call is complete, so that we can cancel + // the timer. + // Note that we trigger this on recv_trailing_metadata, even though + // the client never sends trailing metadata, because this is the + // hook that tells us when the call is complete on the server side. + if (op->recv_trailing_metadata != NULL) { + calld->base.next_on_complete = op->on_complete; + grpc_closure_init(&calld->base.on_complete, on_complete, calld); + op->on_complete = &calld->base.on_complete; + } } // Chain to next filter. grpc_call_next_op(exec_ctx, elem, op); diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c index 36672bdbc5..d4e197fa5c 100644 --- a/src/core/lib/transport/transport.c +++ b/src/core/lib/transport/transport.c @@ -220,6 +220,10 @@ void grpc_transport_stream_op_add_cancellation_with_message( error = GRPC_ERROR_CREATE("Call cancelled"); } error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status); + // TODO(ctiller): We are intentionally setting close_error instead of + // cancel_error here. This is an ugly hack and should be replaced + // by a more general-purpose mechanism that allows us to control + // cancel/close behavior. add_error(op, &op->close_error, error); } -- cgit v1.2.3 From ed4605b71c8ed5ea1b4d4ff27dbea230a458fb44 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 31 Aug 2016 13:05:46 -0700 Subject: Change error messages to include actual values and limits. --- src/core/lib/channel/message_size_filter.c | 7 +++++-- test/core/end2end/tests/max_message_length.c | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index ee9e3ee734..e2d7ff795c 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -69,7 +69,9 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, if (*calld->recv_message != NULL && (*calld->recv_message)->length > chand->max_recv_size) { char* message_string; - gpr_asprintf(&message_string, "Received message larger than max (%lu)", + gpr_asprintf(&message_string, + "Received message larger than max (%lu vs. %lu)", + (unsigned long)(*calld->recv_message)->length, (unsigned long)chand->max_recv_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); @@ -91,7 +93,8 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, if (op->send_message != NULL && op->send_message->length > chand->max_send_size) { char* message_string; - gpr_asprintf(&message_string, "Sent message larger than max (%lu)", + gpr_asprintf(&message_string, "Sent message larger than max (%lu vs. %lu)", + (unsigned long)op->send_message->length, (unsigned long)chand->max_send_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c index 33683aaecd..7368bca308 100644 --- a/test/core/end2end/tests/max_message_length.c +++ b/test/core/end2end/tests/max_message_length.c @@ -217,6 +217,10 @@ static void test_max_message_length(grpc_end2end_test_config config, done: GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT); + GPR_ASSERT(strcmp(details, + send_limit + ? "Sent message larger than max (11 vs. 5)" + : "Received message larger than max (11 vs. 5)") == 0); gpr_free(details); grpc_metadata_array_destroy(&initial_metadata_recv); -- cgit v1.2.3 From 23aff2e0cd188c0ce6e7949a1b0ff253e3eebf8f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 2 Sep 2016 09:18:27 -0700 Subject: Improve comment --- src/core/lib/iomgr/combiner.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index 3eb9f34638..57df8f0ba8 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -54,14 +54,16 @@ void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error); // Execute \a action within the lock just prior to unlocking. -// if \a hint_async_break is additionally set, the combiner is tries to trip -// through the workqueue between finishing the primary queue of combined -// closures and executing the finally list. +// if \a hint_async_break is true, the combiner is tries to hand execution to +// another thread before finishing the primary queue of combined closures and +// executing the finally list. +// Deprecation warning: \a hint_async_break will be removed in a future version // Takes a very slow and round-about path if not called from a -// grpc_combiner_execute closure +// grpc_combiner_execute closure. void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error, bool hint_async_break); +// Deprecated: force the finally list execution onto another thread void grpc_combiner_force_async_finally(grpc_combiner *lock); extern int grpc_combiner_trace; -- cgit v1.2.3 From f6b6d2984157cc24ee69afb9b025b5d250a5a9ad Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 2 Sep 2016 09:27:26 -0700 Subject: Address review comments --- src/core/lib/iomgr/combiner.c | 9 +++++++-- src/core/lib/iomgr/combiner.h | 2 +- src/core/lib/support/mpscq.c | 11 +++++++---- src/core/lib/support/mpscq.h | 4 ++-- test/core/iomgr/combiner_test.c | 3 ++- 5 files changed, 19 insertions(+), 10 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index eb5ad634bd..831bdb4aff 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -176,8 +176,10 @@ static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { gpr_log(GPR_DEBUG, "C:%p maybe_finish_one n=%p", lock, n)); GPR_ASSERT(exec_ctx->active_combiner == lock); if (n == NULL) { - // queue is in an inconsistant state: use this as a cue that we should - // go off and do something else for a while (and come back later) + // Queue is in an transiently inconsistent state: a new item is being queued + // but is not visible to this thread yet. + // Use this as a cue that we should go off and do something else for a while + // (and come back later) grpc_closure_init(&lock->continue_finishing, continue_finishing_mainline, lock); grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, @@ -204,6 +206,9 @@ static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { "C:%p finish[%d] old_state=%" PRIdPTR, lock, loops, old_state)); switch (old_state) { + default: + // we have multiple queued work items: just continue executing them + break; case 5: // we're down to one queued item: if it's the final list we case 4: // should do that if (!grpc_closure_list_empty(lock->final_list)) { diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index 57df8f0ba8..08acbb7441 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -41,7 +41,7 @@ #include "src/core/lib/support/mpscq.h" // Provides serialized access to some resource. -// Each action queued on an aelock is executed serially in a borrowed thread. +// Each action queued on a combiner is executed serially in a borrowed thread. // The actual thread executing actions may change over time (but there will only // every be one at a time). diff --git a/src/core/lib/support/mpscq.c b/src/core/lib/support/mpscq.c index 25b055b172..cdd6335f82 100644 --- a/src/core/lib/support/mpscq.c +++ b/src/core/lib/support/mpscq.c @@ -38,7 +38,7 @@ void gpr_mpscq_init(gpr_mpscq *q) { gpr_atm_no_barrier_store(&q->head, (gpr_atm)&q->stub); q->tail = &q->stub; - gpr_atm_no_barrier_store(&q->stub.next, 0); + gpr_atm_no_barrier_store(&q->stub.next, (gpr_atm)NULL); } void gpr_mpscq_destroy(gpr_mpscq *q) { @@ -47,16 +47,17 @@ void gpr_mpscq_destroy(gpr_mpscq *q) { } void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n) { - gpr_atm_no_barrier_store(&n->next, 0); + gpr_atm_no_barrier_store(&n->next, (gpr_atm)NULL); gpr_mpscq_node *prev = (gpr_mpscq_node *)gpr_atm_full_xchg(&q->head, (gpr_atm)n); - gpr_atm_rel_store(&prev->next, (gpr_atm)n); + gpr_atm_no_barrier_store(&prev->next, (gpr_atm)n); } gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { gpr_mpscq_node *tail = q->tail; gpr_mpscq_node *next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); if (tail == &q->stub) { + // indicates the list is actually (ephemerally) empty if (next == NULL) return NULL; q->tail = next; tail = next; @@ -68,7 +69,8 @@ gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { } gpr_mpscq_node *head = (gpr_mpscq_node *)gpr_atm_acq_load(&q->head); if (tail != head) { - return 0; + // indicates a retry is in order: we're still adding + return NULL; } gpr_mpscq_push(q, &q->stub); next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); @@ -76,5 +78,6 @@ gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { q->tail = next; return tail; } + // indicates a retry is in order: we're still adding return NULL; } diff --git a/src/core/lib/support/mpscq.h b/src/core/lib/support/mpscq.h index 1201edceb1..977a117952 100644 --- a/src/core/lib/support/mpscq.h +++ b/src/core/lib/support/mpscq.h @@ -41,8 +41,8 @@ // implementation from Dmitry Vyukov here: // http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue -// List node (include this in a data structure and dangle the rest of the -// interesting bits off the end) +// List node (include this in a data structure at the top, and add application +// fields after it - to simulate inheritance) typedef struct gpr_mpscq_node { gpr_atm next; } gpr_mpscq_node; // Actual queue type diff --git a/test/core/iomgr/combiner_test.c b/test/core/iomgr/combiner_test.c index 7cf016d82c..197998c1e5 100644 --- a/test/core/iomgr/combiner_test.c +++ b/test/core/iomgr/combiner_test.c @@ -80,7 +80,6 @@ typedef struct { static void check_one(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) { ex_args *args = a; - // gpr_log(GPR_DEBUG, "*%p=%d; step %d", args->ctr, *args->ctr, args->value); GPR_ASSERT(*args->ctr == args->value - 1); *args->ctr = args->value; gpr_free(a); @@ -99,6 +98,8 @@ static void execute_many_loop(void *a) { grpc_closure_create(check_one, c), GRPC_ERROR_NONE); grpc_exec_ctx_flush(&exec_ctx); } + // sleep for a little bit, to test a combiner draining and another thread + // picking it up gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); } grpc_exec_ctx_finish(&exec_ctx); -- cgit v1.2.3 From 62622970cd0a38507f71dde73d1f2c75e413306f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 2 Sep 2016 10:18:03 -0700 Subject: Fix typo --- src/core/lib/iomgr/combiner.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index 08acbb7441..1409db24b9 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -54,7 +54,7 @@ void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, grpc_closure *closure, grpc_error *error); // Execute \a action within the lock just prior to unlocking. -// if \a hint_async_break is true, the combiner is tries to hand execution to +// if \a hint_async_break is true, the combiner tries to hand execution to // another thread before finishing the primary queue of combined closures and // executing the finally list. // Deprecation warning: \a hint_async_break will be removed in a future version -- cgit v1.2.3 From 72f6da8bacd15e878071b982c5e17409004da730 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 2 Sep 2016 13:42:38 -0700 Subject: Move client-side deadline handling to client_channel filter. --- src/core/ext/client_config/client_channel.c | 41 ++++- src/core/lib/channel/deadline_filter.c | 244 ++++++++++++++++------------ src/core/lib/channel/deadline_filter.h | 41 +++++ src/core/lib/surface/init.c | 3 - 4 files changed, 215 insertions(+), 114 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c index 61e012578e..bbae37d7af 100644 --- a/src/core/ext/client_config/client_channel.c +++ b/src/core/ext/client_config/client_channel.c @@ -45,6 +45,7 @@ #include "src/core/ext/client_config/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/channel/deadline_filter.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/profiling/timers.h" @@ -377,6 +378,15 @@ typedef enum { for initial metadata before trying to create a call object, and handling cancellation gracefully. */ typedef struct client_channel_call_data { + // State for handling deadlines. + // The code in deadline_filter.c requires this to be the first field. +// FIXME + // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state + // and this struct both independently store a pointer to the call + // stack and each has its own mutex. If/when we have time, find a way + // to avoid this without breaking either abstraction. + grpc_deadline_state deadline_state; + /** either 0 for no call, 1 for cancelled, or a pointer to a grpc_subchannel_call */ gpr_atm subchannel_call; @@ -465,7 +475,7 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, gpr_atm_no_barrier_store(&calld->subchannel_call, 1); fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING( "Failed to create subchannel", &error, 1)); - } else if (1 == gpr_atm_acq_load(&calld->subchannel_call)) { + } else if (GET_CALL(calld) == CANCELLED_CALL) { /* already cancelled before subchannel became ready */ fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING( @@ -511,7 +521,7 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags, grpc_connected_subchannel **connected_subchannel, - grpc_closure *on_ready); + grpc_closure *on_ready, grpc_error *error); static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { @@ -522,7 +532,8 @@ static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error), NULL); } else if (pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata, cpa->initial_metadata_flags, - cpa->connected_subchannel, cpa->on_ready)) { + cpa->connected_subchannel, cpa->on_ready, + GRPC_ERROR_NONE)) { grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE, NULL); } gpr_free(cpa); @@ -532,7 +543,7 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags, grpc_connected_subchannel **connected_subchannel, - grpc_closure *on_ready) { + grpc_closure *on_ready, grpc_error *error) { GPR_TIMER_BEGIN("pick_subchannel", 0); channel_data *chand = elem->channel_data; @@ -554,7 +565,8 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, if (cpa->connected_subchannel == connected_subchannel) { cpa->connected_subchannel = NULL; grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, - GRPC_ERROR_CREATE("Pick cancelled"), NULL); + GRPC_ERROR_CREATE_REFERENCING( + "Pick cancelled", &error, 1), NULL); } } gpr_mu_unlock(&chand->mu); @@ -609,6 +621,7 @@ static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op) { call_data *calld = elem->call_data; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); + grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op); /* try to (atomically) get the call */ grpc_subchannel_call *call = GET_CALL(calld); GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0); @@ -645,20 +658,23 @@ retry: if (op->cancel_error != GRPC_ERROR_NONE) { if (!gpr_atm_rel_cas(&calld->subchannel_call, 0, (gpr_atm)(uintptr_t)CANCELLED_CALL)) { +gpr_log(GPR_INFO, "CANCELLED_CALL"); goto retry; } else { switch (calld->creation_phase) { case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING: +gpr_log(GPR_INFO, "GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING"); fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error)); break; case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL: +gpr_log(GPR_INFO, "GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL"); pick_subchannel(exec_ctx, elem, NULL, 0, &calld->connected_subchannel, - NULL); + NULL, GRPC_ERROR_REF(op->cancel_error)); break; } gpr_mu_unlock(&calld->mu); - grpc_transport_stream_op_finish_with_failure(exec_ctx, op, - GRPC_ERROR_CANCELLED); + grpc_transport_stream_op_finish_with_failure( + exec_ctx, op, GRPC_ERROR_REF(op->cancel_error)); GPR_TIMER_END("cc_start_transport_stream_op", 0); return; } @@ -672,7 +688,8 @@ retry: GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel"); if (pick_subchannel(exec_ctx, elem, op->send_initial_metadata, op->send_initial_metadata_flags, - &calld->connected_subchannel, &calld->next_step)) { + &calld->connected_subchannel, &calld->next_step, + GRPC_ERROR_NONE)) { calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel"); } @@ -705,6 +722,11 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_call_element_args *args) { call_data *calld = elem->call_data; + grpc_deadline_state_init(&calld->deadline_state, args->call_stack); + +// FIXME: remove +calld->deadline_state.is_client = true; + gpr_atm_rel_store(&calld->subchannel_call, 0); gpr_mu_init(&calld->mu); calld->connected_subchannel = NULL; @@ -723,6 +745,7 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx, const grpc_call_final_info *final_info, void *and_free_memory) { call_data *calld = elem->call_data; + grpc_deadline_state_destroy(exec_ctx, &calld->deadline_state); grpc_subchannel_call *call = GET_CALL(calld); if (call != NULL && call != CANCELLED_CALL) { GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call"); diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index 9dff1c4d63..e4f132624f 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -40,131 +40,107 @@ #include "src/core/lib/iomgr/timer.h" -// Used for both client and server filters. -typedef struct channel_data { -} channel_data; - -// Call data used for both client and server filter. -typedef struct base_call_data { - // We take a reference to the call stack for the timer callback. - grpc_call_stack* call_stack; - // Guards access to timer_pending and timer. - gpr_mu timer_mu; - // True if the timer callback is currently pending. - bool timer_pending; - // The deadline timer. - grpc_timer timer; - // Closure to invoke when the call is complete. - // We use this to cancel the timer. - grpc_closure on_complete; - // The original on_complete closure, which we chain to after our own - // closure is invoked. - grpc_closure* next_on_complete; -} base_call_data; - -// Additional call data used only for the server filter. -typedef struct server_call_data { - base_call_data base; // Must be first. - // The closure for receiving initial metadata. - grpc_closure recv_initial_metadata_ready; - // Received initial metadata batch. - grpc_metadata_batch* recv_initial_metadata; - // The original recv_initial_metadata_ready closure, which we chain to - // after our own closure is invoked. - grpc_closure* next_recv_initial_metadata_ready; -} server_call_data; - -// Constructor for channel_data. Used for both client and server filters. -static void init_channel_elem(grpc_exec_ctx* exec_ctx, - grpc_channel_element* elem, - grpc_channel_element_args* args) { - GPR_ASSERT(!args->is_last); -} - -// Destructor for channel_data. Used for both client and server filters. -static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, - grpc_channel_element* elem) { -} - -// Constructor for call_data. Used for both client and server filters. -static grpc_error *init_call_elem(grpc_exec_ctx* exec_ctx, - grpc_call_element* elem, - grpc_call_element_args* args) { - base_call_data* calld = elem->call_data; - // Note: size of call data is different between client and server. - memset(calld, 0, elem->filter->sizeof_call_data); - calld->call_stack = args->call_stack; - gpr_mu_init(&calld->timer_mu); - return GRPC_ERROR_NONE; -} - -// Destructor for call_data. Used for both client and server filters. -static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, - const grpc_call_final_info* final_info, - void* and_free_memory) { - base_call_data* calld = elem->call_data; - gpr_mu_destroy(&calld->timer_mu); -} +// +// grpc_deadline_state +// // Timer callback. static void timer_callback(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_call_element* elem = arg; - base_call_data* calld = elem->call_data; - gpr_mu_lock(&calld->timer_mu); - calld->timer_pending = false; - gpr_mu_unlock(&calld->timer_mu); + grpc_deadline_state* deadline_state = elem->call_data; +gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client); + gpr_mu_lock(&deadline_state->timer_mu); + deadline_state->timer_pending = false; + gpr_mu_unlock(&deadline_state->timer_mu); if (error != GRPC_ERROR_CANCELLED) { - grpc_call_element_send_cancel(exec_ctx, elem); +gpr_log(GPR_INFO, "DEADLINE_EXCEEDED"); +// FIXME: change grpc_call_element_send_cancel_with_message to not call close +// grpc_call_element_send_cancel(exec_ctx, elem); + grpc_transport_stream_op op; + memset(&op, 0, sizeof(op)); + op.cancel_error = grpc_error_set_int( + GRPC_ERROR_CREATE("Deadline Exceeded"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_DEADLINE_EXCEEDED); + elem->filter->start_transport_stream_op(exec_ctx, elem, &op); } - GRPC_CALL_STACK_UNREF(exec_ctx, calld->call_stack, "deadline_timer"); + GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, "deadline_timer"); } // Starts the deadline timer. static void start_timer_if_needed(grpc_exec_ctx *exec_ctx, grpc_call_element* elem, gpr_timespec deadline) { - base_call_data* calld = elem->call_data; + grpc_deadline_state* deadline_state = elem->call_data; +gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client); deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) { // Take a reference to the call stack, to be owned by the timer. - GRPC_CALL_STACK_REF(calld->call_stack, "deadline_timer"); - gpr_mu_lock(&calld->timer_mu); - calld->timer_pending = true; - grpc_timer_init(exec_ctx, &calld->timer, deadline, timer_callback, elem, - gpr_now(GPR_CLOCK_MONOTONIC)); - gpr_mu_unlock(&calld->timer_mu); + GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer"); + gpr_mu_lock(&deadline_state->timer_mu); +gpr_log(GPR_INFO, "STARTING TIMER -- is_client=%d", deadline_state->is_client); + deadline_state->timer_pending = true; + grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, timer_callback, + elem, gpr_now(GPR_CLOCK_MONOTONIC)); + gpr_mu_unlock(&deadline_state->timer_mu); } } // Cancels the deadline timer. static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx, - base_call_data* calld) { - gpr_mu_lock(&calld->timer_mu); - if (calld->timer_pending) { - grpc_timer_cancel(exec_ctx, &calld->timer); - calld->timer_pending = false; + grpc_deadline_state* deadline_state) { +gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client); + gpr_mu_lock(&deadline_state->timer_mu); + if (deadline_state->timer_pending) { +gpr_log(GPR_INFO, "CANCELLING TIMER -- is_client=%d", deadline_state->is_client); + grpc_timer_cancel(exec_ctx, &deadline_state->timer); + deadline_state->timer_pending = false; } - gpr_mu_unlock(&calld->timer_mu); + gpr_mu_unlock(&deadline_state->timer_mu); } // Callback run when the call is complete. static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - base_call_data* calld = arg; - cancel_timer_if_needed(exec_ctx, calld); + grpc_deadline_state* deadline_state = arg; +gpr_log(GPR_INFO, "==> %s(), is_client=%d, next_on_complete->cb=%p", __func__, deadline_state->is_client, deadline_state->next_on_complete->cb); + cancel_timer_if_needed(exec_ctx, deadline_state); // Invoke the next callback. - calld->next_on_complete->cb(exec_ctx, calld->next_on_complete->cb_arg, error); + deadline_state->next_on_complete->cb( + exec_ctx, deadline_state->next_on_complete->cb_arg, error); } -// Method for starting a call op for client filter. -static void client_start_transport_stream_op(grpc_exec_ctx* exec_ctx, - grpc_call_element* elem, - grpc_transport_stream_op* op) { - base_call_data* calld = elem->call_data; - // If the call is cancelled or closed, cancel the timer. +// Inject our own on_complete callback into op. +static void inject_on_complete_cb(grpc_deadline_state* deadline_state, + grpc_transport_stream_op* op) { +gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client); + deadline_state->next_on_complete = op->on_complete; + grpc_closure_init(&deadline_state->on_complete, on_complete, deadline_state); + op->on_complete = &deadline_state->on_complete; +} + +void grpc_deadline_state_init(grpc_deadline_state* deadline_state, + grpc_call_stack* call_stack) { +gpr_log(GPR_INFO, "==> %s()", __func__); + memset(deadline_state, 0, sizeof(*deadline_state)); + deadline_state->call_stack = call_stack; + gpr_mu_init(&deadline_state->timer_mu); +} + +void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, + grpc_deadline_state* deadline_state) { +gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client); + cancel_timer_if_needed(exec_ctx, deadline_state); + gpr_mu_destroy(&deadline_state->timer_mu); +} + +void grpc_deadline_state_client_start_transport_stream_op( + grpc_exec_ctx* exec_ctx, grpc_call_element* elem, + grpc_transport_stream_op* op) { +gpr_log(GPR_INFO, "==> %s(): op=%p {on_complete=%p, cancel_error=%p, close_error=%p, send_initial_metadata=%p, send_trailing_metadata=%p, send_message=%p, recv_initial_metadata_ready=%p, recv_trailing_metadata=%p}", __func__, op, op->on_complete, op->cancel_error, op->close_error, op->send_initial_metadata, op->send_trailing_metadata, op->send_message, op->recv_initial_metadata_ready, op->recv_trailing_metadata); + grpc_deadline_state* deadline_state = elem->call_data; if (op->cancel_error != GRPC_ERROR_NONE || op->close_error != GRPC_ERROR_NONE) { - cancel_timer_if_needed(exec_ctx, calld); + cancel_timer_if_needed(exec_ctx, deadline_state); } else { // If we're sending initial metadata, get the deadline from the metadata // and start the timer if needed. @@ -175,11 +151,77 @@ static void client_start_transport_stream_op(grpc_exec_ctx* exec_ctx, // Make sure we know when the call is complete, so that we can cancel // the timer. if (op->recv_trailing_metadata != NULL) { - calld->next_on_complete = op->on_complete; - grpc_closure_init(&calld->on_complete, on_complete, calld); - op->on_complete = &calld->on_complete; + inject_on_complete_cb(deadline_state, op); } } +} + +// +// filter code +// + +// Used for both client and server filters. +typedef struct channel_data { +} channel_data; + +// Constructor for channel_data. Used for both client and server filters. +static void init_channel_elem(grpc_exec_ctx* exec_ctx, + grpc_channel_element* elem, + grpc_channel_element_args* args) { + GPR_ASSERT(!args->is_last); +} + +// Destructor for channel_data. Used for both client and server filters. +static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, + grpc_channel_element* elem) { +} + +// Call data used for both client and server filter. +typedef struct base_call_data { + grpc_deadline_state deadline_state; +} base_call_data; + +// Additional call data used only for the server filter. +typedef struct server_call_data { + base_call_data base; // Must be first. + // The closure for receiving initial metadata. + grpc_closure recv_initial_metadata_ready; + // Received initial metadata batch. + grpc_metadata_batch* recv_initial_metadata; + // The original recv_initial_metadata_ready closure, which we chain to + // after our own closure is invoked. + grpc_closure* next_recv_initial_metadata_ready; +} server_call_data; + +// Constructor for call_data. Used for both client and server filters. +static grpc_error *init_call_elem(grpc_exec_ctx* exec_ctx, + grpc_call_element* elem, + grpc_call_element_args* args) { +gpr_log(GPR_INFO, "==> %s() -- call_data_size=%lu", __func__, elem->filter->sizeof_call_data); + base_call_data* calld = elem->call_data; + // Note: size of call data is different between client and server. + memset(calld, 0, elem->filter->sizeof_call_data); + grpc_deadline_state_init(&calld->deadline_state, args->call_stack); + +calld->deadline_state.is_client = elem->filter->sizeof_call_data == sizeof(base_call_data); + + return GRPC_ERROR_NONE; +} + +// Destructor for call_data. Used for both client and server filters. +static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, + const grpc_call_final_info* final_info, + void* and_free_memory) { + base_call_data* calld = elem->call_data; + grpc_deadline_state_destroy(exec_ctx, &calld->deadline_state); +} + +// Method for starting a call op for client filter. +static void client_start_transport_stream_op(grpc_exec_ctx* exec_ctx, + grpc_call_element* elem, + grpc_transport_stream_op* op) { +gpr_log(GPR_INFO, "==> %s()", __func__); + grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op); // Chain to next filter. grpc_call_next_op(exec_ctx, elem, op); } @@ -201,11 +243,11 @@ static void recv_initial_metadata_ready(grpc_exec_ctx *exec_ctx, void *arg, static void server_start_transport_stream_op(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op) { +gpr_log(GPR_INFO, "==> %s(): op=%p {on_complete=%p, cancel_error=%p, close_error=%p, send_initial_metadata=%p, send_trailing_metadata=%p, send_message=%p, recv_initial_metadata_ready=%p, recv_trailing_metadata=%p}", __func__, op, op->on_complete, op->cancel_error, op->close_error, op->send_initial_metadata, op->send_trailing_metadata, op->send_message, op->recv_initial_metadata_ready, op->recv_trailing_metadata); server_call_data* calld = elem->call_data; - // If the call is cancelled or closed, cancel the timer. if (op->cancel_error != GRPC_ERROR_NONE || op->close_error != GRPC_ERROR_NONE) { - cancel_timer_if_needed(exec_ctx, &calld->base); + cancel_timer_if_needed(exec_ctx, &calld->base.deadline_state); } else { // If we're receiving initial metadata, we need to get the deadline // from the recv_initial_metadata_ready callback. So we inject our @@ -223,9 +265,7 @@ static void server_start_transport_stream_op(grpc_exec_ctx* exec_ctx, // the client never sends trailing metadata, because this is the // hook that tells us when the call is complete on the server side. if (op->recv_trailing_metadata != NULL) { - calld->base.next_on_complete = op->on_complete; - grpc_closure_init(&calld->base.on_complete, on_complete, calld); - op->on_complete = &calld->base.on_complete; + inject_on_complete_cb(&calld->base.deadline_state, op); } } // Chain to next filter. diff --git a/src/core/lib/channel/deadline_filter.h b/src/core/lib/channel/deadline_filter.h index 323cb4e10c..793b76f9b6 100644 --- a/src/core/lib/channel/deadline_filter.h +++ b/src/core/lib/channel/deadline_filter.h @@ -33,7 +33,48 @@ #define GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/iomgr/timer.h" +// State used for filters that enforce call deadlines. +// Should be the first field in the filter's call_data. +typedef struct grpc_deadline_state { + // We take a reference to the call stack for the timer callback. + grpc_call_stack* call_stack; + // Guards access to timer_pending and timer. + gpr_mu timer_mu; + // True if the timer callback is currently pending. + bool timer_pending; + // The deadline timer. + grpc_timer timer; + // Closure to invoke when the call is complete. + // We use this to cancel the timer. + grpc_closure on_complete; + // The original on_complete closure, which we chain to after our own + // closure is invoked. + grpc_closure* next_on_complete; + +// FIXME: remove +bool is_client; + +} grpc_deadline_state; + +void grpc_deadline_state_init(grpc_deadline_state* call_data, + grpc_call_stack* call_stack); +void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, + grpc_deadline_state* call_data); + +// To be used in a filter's start_transport_stream_op() method to +// enforce call deadlines. +// It is the caller's responsibility to chain to the next filter if +// necessary after this function returns. +// REQUIRES: The first field in elem is a grpc_deadline_state struct. +void grpc_deadline_state_client_start_transport_stream_op( + grpc_exec_ctx* exec_ctx, grpc_call_element* elem, + grpc_transport_stream_op* op); + +// Deadline filters for direct client channels and server channels. +// Note: Deadlines for non-direct client channels are handled by the +// client_channel filter. extern const grpc_channel_filter grpc_client_deadline_filter; extern const grpc_channel_filter grpc_server_deadline_filter; diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index 4a3c03b915..158dca0964 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -98,9 +98,6 @@ static bool maybe_add_http_filter(grpc_channel_stack_builder *builder, } static void register_builtin_channel_init() { - grpc_channel_init_register_stage( - GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, - prepend_filter, (void *)&grpc_client_deadline_filter); grpc_channel_init_register_stage( GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter, (void *)&grpc_client_deadline_filter); -- cgit v1.2.3 From dabb376f50289025402044ec1736c050dc073121 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 2 Sep 2016 13:43:20 -0700 Subject: Start cancellations at the current filter instead of the next one. --- src/core/lib/channel/channel_stack.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c index 98f304f2da..fb0c70986f 100644 --- a/src/core/lib/channel/channel_stack.c +++ b/src/core/lib/channel/channel_stack.c @@ -271,20 +271,20 @@ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) { } void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx, - grpc_call_element *cur_elem) { + grpc_call_element *elem) { grpc_transport_stream_op op; memset(&op, 0, sizeof(op)); op.cancel_error = GRPC_ERROR_CANCELLED; - grpc_call_next_op(exec_ctx, cur_elem, &op); + elem->filter->start_transport_stream_op(exec_ctx, elem, &op); } void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx, - grpc_call_element *cur_elem, + grpc_call_element *elem, grpc_status_code status, gpr_slice *optional_message) { grpc_transport_stream_op op; memset(&op, 0, sizeof(op)); grpc_transport_stream_op_add_cancellation_with_message(&op, status, optional_message); - grpc_call_next_op(exec_ctx, cur_elem, &op); + elem->filter->start_transport_stream_op(exec_ctx, elem, &op); } -- cgit v1.2.3 From 1e35b69788242095fe781bf730b45a0a65549ca0 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 2 Sep 2016 13:44:32 -0700 Subject: Set status from the grpc_error or whichever of its children has the data. --- src/core/lib/iomgr/error.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ src/core/lib/iomgr/error.h | 8 ++++++ src/core/lib/surface/call.c | 34 ++++++++++--------------- 3 files changed, 83 insertions(+), 21 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c index 149c55663c..e54154421a 100644 --- a/src/core/lib/iomgr/error.c +++ b/src/core/lib/iomgr/error.c @@ -324,6 +324,68 @@ const char *grpc_error_get_str(grpc_error *err, grpc_error_strs which) { return gpr_avl_get(err->strs, (void *)(uintptr_t)which); } +typedef struct { + grpc_error *error; + grpc_status_code code; + const char *msg; +} special_error_status_map; +static special_error_status_map error_status_map[] = { + { GRPC_ERROR_NONE, GRPC_STATUS_OK, "" }, + { GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "RPC cancelled" }, + { GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory" }, +}; + +static grpc_error *recursively_find_error_with_status(grpc_error* error, + intptr_t* status) { + // If the error itself has a status code, return it. + if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, status)) { + return error; + } + // Otherwise, search through its children. + intptr_t key = 0; + while (true) { + grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++); + if (child_error == NULL) + break; + grpc_error *result = + recursively_find_error_with_status(child_error, status); + if (result != NULL) + return result; + } + return NULL; +} + +void grpc_error_get_status(grpc_error *error, grpc_status_code *code, + const char **msg) { + // Handle special errors via the static map. + for (size_t i = 0; + i < sizeof(error_status_map) / sizeof(special_error_status_map); + ++i) { + if (error == error_status_map[i].error) { + *code = error_status_map[i].code; + *msg = error_status_map[i].msg; + return; + } + } + // Populate code. + // Start with the parent error and recurse through the tree of children + // until we find the first one that has a status code. + intptr_t status = GRPC_STATUS_UNKNOWN; // Default in case we don't find one. + grpc_error* found_error = recursively_find_error_with_status(error, &status); + *code = status; + // Now populate msg. + // If we found an error with a status code above, use that; otherwise, + // fall back to using the parent error. + if (found_error == NULL) found_error = error; + // If the error has a status message, use it. Otherwise, fall back to + // the error description. + *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_GRPC_MESSAGE); + if (*msg == NULL) { + *msg = grpc_error_get_str(found_error, GRPC_ERROR_STR_DESCRIPTION); + if (*msg == NULL) *msg = "uknown error"; // Just in case. + } +} + grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) { GPR_TIMER_BEGIN("grpc_error_add_child", 0); grpc_error *new = copy_error_and_unref(src); diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h index 6c769accdb..7e2fd7a3bd 100644 --- a/src/core/lib/iomgr/error.h +++ b/src/core/lib/iomgr/error.h @@ -37,6 +37,7 @@ #include #include +#include #include /// Opaque representation of an error. @@ -175,6 +176,13 @@ grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which, /// Returns NULL if the specified string is not set. /// Caller does NOT own return value. const char *grpc_error_get_str(grpc_error *error, grpc_error_strs which); + +/// A utility function to get the status code and message to be returned +/// to the application. If not set in the top-level message, looks +/// through child errors until it finds the first one with these attributes. +void grpc_error_get_status(grpc_error *error, grpc_status_code *code, + const char **msg); + /// Add a child error: an error that is believed to have contributed to this /// error occurring. Allows root causing high level errors from lower level /// errors that contributed to them. diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index c05ed67c43..7ab97f3140 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -261,13 +261,10 @@ grpc_call *grpc_call_create( &exec_ctx, channel_stack, 1, destroy_call, call, call->context, server_transport_data, CALL_STACK_FROM_CALL(call)); if (error != GRPC_ERROR_NONE) { - intptr_t status; - if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &status)) - status = GRPC_STATUS_UNKNOWN; - const char *error_str = - grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION); - close_with_status(&exec_ctx, call, (grpc_status_code)status, - error_str == NULL ? "unknown error" : error_str); + grpc_status_code status; + const char *error_str; + grpc_error_get_status(error, &status, &error_str); + close_with_status(&exec_ctx, call, status, error_str); GRPC_ERROR_UNREF(error); } if (cq != NULL) { @@ -440,20 +437,11 @@ static void set_status_details(grpc_call *call, status_source source, static void set_status_from_error(grpc_call *call, status_source source, grpc_error *error) { - intptr_t status; - if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &status)) { - set_status_code(call, source, (uint32_t)status); - } else { - set_status_code(call, source, GRPC_STATUS_INTERNAL); - } - const char *msg = grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE); - bool free_msg = false; - if (msg == NULL) { - free_msg = true; - msg = grpc_error_string(error); - } + grpc_status_code status; + const char* msg; + grpc_error_get_status(error, &status, &msg); + set_status_code(call, source, (uint32_t)status); set_status_details(call, source, grpc_mdstr_from_string(msg)); - if (free_msg) grpc_error_free_string(msg); } static void set_incoming_compression_algorithm( @@ -1256,12 +1244,16 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_call *child_call; grpc_call *next_child_call; +const char* msg = grpc_error_string(error); +gpr_log(GPR_INFO, "==> finish_batch(): is_client=%d, error=%s", call->is_client, msg); +grpc_error_free_string(msg); + GRPC_ERROR_REF(error); gpr_mu_lock(&call->mu); if (bctl->send_initial_metadata) { if (error != GRPC_ERROR_NONE) { - set_status_code(call, STATUS_FROM_CORE, GRPC_STATUS_UNAVAILABLE); + set_status_from_error(call, STATUS_FROM_CORE, error); } grpc_metadata_batch_destroy( &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]); -- cgit v1.2.3 From 78dc25e86b090c7fa26e77ce6521a30002d150be Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 2 Sep 2016 14:36:56 -0700 Subject: Revert barrier change to restore TSAN passing --- src/core/lib/support/mpscq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/support/mpscq.c b/src/core/lib/support/mpscq.c index cdd6335f82..5b9323275a 100644 --- a/src/core/lib/support/mpscq.c +++ b/src/core/lib/support/mpscq.c @@ -50,7 +50,7 @@ void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n) { gpr_atm_no_barrier_store(&n->next, (gpr_atm)NULL); gpr_mpscq_node *prev = (gpr_mpscq_node *)gpr_atm_full_xchg(&q->head, (gpr_atm)n); - gpr_atm_no_barrier_store(&prev->next, (gpr_atm)n); + gpr_atm_rel_store(&prev->next, (gpr_atm)n); } gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { -- cgit v1.2.3 From abc1a4414d7ca8d94ddeec884aa4c4a85fd513ff Mon Sep 17 00:00:00 2001 From: thinkerou Date: Sun, 4 Sep 2016 16:15:41 +0800 Subject: fix type convert --- src/core/lib/support/time_posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/support/time_posix.c b/src/core/lib/support/time_posix.c index 11542072fe..a69c501e9f 100644 --- a/src/core/lib/support/time_posix.c +++ b/src/core/lib/support/time_posix.c @@ -127,7 +127,7 @@ static gpr_timespec now_impl(gpr_clock_type clock) { now.tv_nsec = now_tv.tv_usec * 1000; break; case GPR_CLOCK_MONOTONIC: - now_dbl = (mach_absolute_time() - g_time_start) * g_time_scale; + now_dbl = ((double)(mach_absolute_time() - g_time_start)) * g_time_scale; now.tv_sec = (int64_t)(now_dbl * 1e-9); now.tv_nsec = (int32_t)(now_dbl - ((double)now.tv_sec) * 1e9); break; -- cgit v1.2.3 From e5f434913975f039b434d05852c6b7ab12774076 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 6 Sep 2016 10:49:52 -0700 Subject: Fix portability problems. --- src/core/lib/channel/deadline_filter.c | 2 +- src/core/lib/iomgr/error.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index e4f132624f..2ca43e105b 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -197,7 +197,7 @@ typedef struct server_call_data { static grpc_error *init_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element_args* args) { -gpr_log(GPR_INFO, "==> %s() -- call_data_size=%lu", __func__, elem->filter->sizeof_call_data); +gpr_log(GPR_INFO, "==> %s() -- call_data_size=%lu", __func__, (unsigned long)elem->filter->sizeof_call_data); base_call_data* calld = elem->call_data; // Note: size of call data is different between client and server. memset(calld, 0, elem->filter->sizeof_call_data); diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c index e54154421a..17f19423a3 100644 --- a/src/core/lib/iomgr/error.c +++ b/src/core/lib/iomgr/error.c @@ -372,7 +372,7 @@ void grpc_error_get_status(grpc_error *error, grpc_status_code *code, // until we find the first one that has a status code. intptr_t status = GRPC_STATUS_UNKNOWN; // Default in case we don't find one. grpc_error* found_error = recursively_find_error_with_status(error, &status); - *code = status; + *code = (grpc_status_code)status; // Now populate msg. // If we found an error with a status code above, use that; otherwise, // fall back to using the parent error. -- cgit v1.2.3 From 697a1f602325518cdd4e48a4ef44e49a09f0579a Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 7 Sep 2016 13:35:07 -0700 Subject: Fix error refcounting. --- src/core/ext/client_config/client_channel.c | 2 ++ src/core/lib/channel/deadline_filter.c | 1 + 2 files changed, 3 insertions(+) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c index bbae37d7af..f1eb0eaebc 100644 --- a/src/core/ext/client_config/client_channel.c +++ b/src/core/ext/client_config/client_channel.c @@ -571,8 +571,10 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, } gpr_mu_unlock(&chand->mu); GPR_TIMER_END("pick_subchannel", 0); + GRPC_ERROR_UNREF(error); return true; } + GPR_ASSERT(error == GRPC_ERROR_NONE); if (chand->lb_policy != NULL) { grpc_lb_policy *lb_policy = chand->lb_policy; int r; diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index 2ca43e105b..5e91d524af 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -63,6 +63,7 @@ gpr_log(GPR_INFO, "DEADLINE_EXCEEDED"); GRPC_ERROR_CREATE("Deadline Exceeded"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_DEADLINE_EXCEEDED); elem->filter->start_transport_stream_op(exec_ctx, elem, &op); + GRPC_ERROR_UNREF(op.cancel_error); } GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, "deadline_timer"); } -- cgit v1.2.3 From f7dd851c2a00d34e51d34555deac5c9bbee528c5 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 7 Sep 2016 13:35:31 -0700 Subject: Remove unused code for chaining on_complete closures in call.c. --- src/core/lib/surface/call.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 7ab97f3140..15c002015c 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -751,7 +751,6 @@ typedef struct termination_closure { grpc_closure closure; grpc_call *call; grpc_error *error; - grpc_closure *op_closure; enum { TC_CANCEL, TC_CLOSE } type; } termination_closure; @@ -767,13 +766,12 @@ static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp, break; } GRPC_ERROR_UNREF(tc->error); - grpc_exec_ctx_sched(exec_ctx, tc->op_closure, GRPC_ERROR_NONE, NULL); gpr_free(tc); } static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { - grpc_transport_stream_op op; termination_closure *tc = tcp; + grpc_transport_stream_op op; memset(&op, 0, sizeof(op)); op.cancel_error = tc->error; /* reuse closure to catch completion */ @@ -783,13 +781,12 @@ static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { } static void send_close(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { - grpc_transport_stream_op op; termination_closure *tc = tcp; + grpc_transport_stream_op op; memset(&op, 0, sizeof(op)); op.close_error = tc->error; /* reuse closure to catch completion */ grpc_closure_init(&tc->closure, done_termination, tc); - tc->op_closure = op.on_complete; op.on_complete = &tc->closure; execute_op(exec_ctx, tc->call, &op); } -- cgit v1.2.3 From 75d7478d122de8142f9306463058e8d18dfd614a Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 9 Sep 2016 07:46:01 -0700 Subject: Fix close vs. cancel confusion in transport helper functions. --- src/core/lib/channel/channel_stack.c | 10 ++++++++++ src/core/lib/channel/channel_stack.h | 5 +++++ src/core/lib/channel/deadline_filter.c | 14 +++++--------- src/core/lib/channel/http_client_filter.c | 4 ++-- src/core/lib/transport/transport.c | 6 +----- 5 files changed, 23 insertions(+), 16 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c index fb0c70986f..f5fa0b0390 100644 --- a/src/core/lib/channel/channel_stack.c +++ b/src/core/lib/channel/channel_stack.c @@ -288,3 +288,13 @@ void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx, optional_message); elem->filter->start_transport_stream_op(exec_ctx, elem, &op); } + +void grpc_call_element_send_close_with_message(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + grpc_status_code status, + gpr_slice *optional_message) { + grpc_transport_stream_op op; + memset(&op, 0, sizeof(op)); + grpc_transport_stream_op_add_close(&op, status, optional_message); + elem->filter->start_transport_stream_op(exec_ctx, elem, &op); +} diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index 6b73cce380..eeaab17d39 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -290,6 +290,11 @@ void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx, grpc_status_code status, gpr_slice *optional_message); +void grpc_call_element_send_close_with_message(grpc_exec_ctx *exec_ctx, + grpc_call_element *cur_elem, + grpc_status_code status, + gpr_slice *optional_message); + extern int grpc_trace_channel; #define GRPC_CALL_LOG_OP(sev, elem, op) \ diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index 5e91d524af..9597783b63 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -55,15 +55,11 @@ gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client) gpr_mu_unlock(&deadline_state->timer_mu); if (error != GRPC_ERROR_CANCELLED) { gpr_log(GPR_INFO, "DEADLINE_EXCEEDED"); -// FIXME: change grpc_call_element_send_cancel_with_message to not call close -// grpc_call_element_send_cancel(exec_ctx, elem); - grpc_transport_stream_op op; - memset(&op, 0, sizeof(op)); - op.cancel_error = grpc_error_set_int( - GRPC_ERROR_CREATE("Deadline Exceeded"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_DEADLINE_EXCEEDED); - elem->filter->start_transport_stream_op(exec_ctx, elem, &op); - GRPC_ERROR_UNREF(op.cancel_error); + gpr_slice msg = gpr_slice_from_static_string("Deadline Exceeded"); + grpc_call_element_send_cancel_with_message(exec_ctx, elem, + GRPC_STATUS_DEADLINE_EXCEEDED, + &msg); + gpr_slice_unref(msg); } GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, "deadline_timer"); } diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c index edcc741ff6..1dc05fb20d 100644 --- a/src/core/lib/channel/http_client_filter.c +++ b/src/core/lib/channel/http_client_filter.c @@ -103,8 +103,8 @@ static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) { grpc_mdstr_as_c_string(md->value)); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); - grpc_call_element_send_cancel_with_message(a->exec_ctx, a->elem, - GRPC_STATUS_CANCELLED, &message); + grpc_call_element_send_close_with_message(a->exec_ctx, a->elem, + GRPC_STATUS_CANCELLED, &message); return NULL; } else if (md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) { return NULL; diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c index d4e197fa5c..205a136742 100644 --- a/src/core/lib/transport/transport.c +++ b/src/core/lib/transport/transport.c @@ -220,11 +220,7 @@ void grpc_transport_stream_op_add_cancellation_with_message( error = GRPC_ERROR_CREATE("Call cancelled"); } error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status); - // TODO(ctiller): We are intentionally setting close_error instead of - // cancel_error here. This is an ugly hack and should be replaced - // by a more general-purpose mechanism that allows us to control - // cancel/close behavior. - add_error(op, &op->close_error, error); + add_error(op, &op->cancel_error, error); } void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op, -- cgit v1.2.3 From 6ad991783f35bf24b1f31a6aa302774206666d78 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 9 Sep 2016 07:52:48 -0700 Subject: Remove debugging code. --- src/core/ext/client_config/client_channel.c | 19 +------------------ src/core/lib/channel/deadline_filter.c | 17 ----------------- src/core/lib/channel/deadline_filter.h | 6 +----- src/core/lib/surface/call.c | 4 ---- 4 files changed, 2 insertions(+), 44 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c index 2708e2d481..569ca38b87 100644 --- a/src/core/ext/client_config/client_channel.c +++ b/src/core/ext/client_config/client_channel.c @@ -380,11 +380,10 @@ typedef enum { typedef struct client_channel_call_data { // State for handling deadlines. // The code in deadline_filter.c requires this to be the first field. -// FIXME // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state // and this struct both independently store a pointer to the call // stack and each has its own mutex. If/when we have time, find a way - // to avoid this without breaking either abstraction. + // to avoid this without breaking the grpc_deadline_state abstraction. grpc_deadline_state deadline_state; /** either 0 for no call, 1 for cancelled, or a pointer to a @@ -466,9 +465,6 @@ static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) { static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { -const char* msg = grpc_error_string(error); -gpr_log(GPR_INFO, "==> %s(): error=%s", __func__, msg); -grpc_error_free_string(msg); call_data *calld = arg; gpr_mu_lock(&calld->mu); GPR_ASSERT(calld->creation_phase == @@ -547,8 +543,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, uint32_t initial_metadata_flags, grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready, grpc_error *error) { -gpr_log(GPR_INFO, "==> %s()", __func__); - GPR_TIMER_BEGIN("pick_subchannel", 0); channel_data *chand = elem->channel_data; @@ -561,13 +555,11 @@ gpr_log(GPR_INFO, "==> %s()", __func__); gpr_mu_lock(&chand->mu); if (initial_metadata == NULL) { if (chand->lb_policy != NULL) { -gpr_log(GPR_INFO, "asking LB policy to cancel pick"); grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy, connected_subchannel, GRPC_ERROR_REF(error)); } for (closure = chand->waiting_for_config_closures.head; closure != NULL; closure = closure->next_data.next) { -gpr_log(GPR_INFO, "top of closure loop"); cpa = closure->cb_arg; if (cpa->connected_subchannel == connected_subchannel) { cpa->connected_subchannel = NULL; @@ -579,7 +571,6 @@ gpr_log(GPR_INFO, "top of closure loop"); gpr_mu_unlock(&chand->mu); GPR_TIMER_END("pick_subchannel", 0); GRPC_ERROR_UNREF(error); -gpr_log(GPR_INFO, "returning from pick_subchannel()"); return true; } GPR_ASSERT(error == GRPC_ERROR_NONE); @@ -629,7 +620,6 @@ gpr_log(GPR_INFO, "returning from pick_subchannel()"); static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op *op) { -gpr_log(GPR_INFO, "==> %s()", __func__); call_data *calld = elem->call_data; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op); @@ -669,16 +659,13 @@ retry: if (op->cancel_error != GRPC_ERROR_NONE) { if (!gpr_atm_rel_cas(&calld->subchannel_call, 0, (gpr_atm)(uintptr_t)CANCELLED_CALL)) { -gpr_log(GPR_INFO, "CANCELLED_CALL"); goto retry; } else { switch (calld->creation_phase) { case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING: -gpr_log(GPR_INFO, "GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING"); fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error)); break; case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL: -gpr_log(GPR_INFO, "GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL"); pick_subchannel(exec_ctx, elem, NULL, 0, &calld->connected_subchannel, NULL, GRPC_ERROR_REF(op->cancel_error)); break; @@ -734,10 +721,6 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element_args *args) { call_data *calld = elem->call_data; grpc_deadline_state_init(&calld->deadline_state, args->call_stack); - -// FIXME: remove -calld->deadline_state.is_client = true; - gpr_atm_rel_store(&calld->subchannel_call, 0); gpr_mu_init(&calld->mu); calld->connected_subchannel = NULL; diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index 9597783b63..424d09d3d8 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -49,12 +49,10 @@ static void timer_callback(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_call_element* elem = arg; grpc_deadline_state* deadline_state = elem->call_data; -gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client); gpr_mu_lock(&deadline_state->timer_mu); deadline_state->timer_pending = false; gpr_mu_unlock(&deadline_state->timer_mu); if (error != GRPC_ERROR_CANCELLED) { -gpr_log(GPR_INFO, "DEADLINE_EXCEEDED"); gpr_slice msg = gpr_slice_from_static_string("Deadline Exceeded"); grpc_call_element_send_cancel_with_message(exec_ctx, elem, GRPC_STATUS_DEADLINE_EXCEEDED, @@ -69,13 +67,11 @@ static void start_timer_if_needed(grpc_exec_ctx *exec_ctx, grpc_call_element* elem, gpr_timespec deadline) { grpc_deadline_state* deadline_state = elem->call_data; -gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client); deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) { // Take a reference to the call stack, to be owned by the timer. GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer"); gpr_mu_lock(&deadline_state->timer_mu); -gpr_log(GPR_INFO, "STARTING TIMER -- is_client=%d", deadline_state->is_client); deadline_state->timer_pending = true; grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, timer_callback, elem, gpr_now(GPR_CLOCK_MONOTONIC)); @@ -86,10 +82,8 @@ gpr_log(GPR_INFO, "STARTING TIMER -- is_client=%d", deadline_state->is_client); // Cancels the deadline timer. static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx, grpc_deadline_state* deadline_state) { -gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client); gpr_mu_lock(&deadline_state->timer_mu); if (deadline_state->timer_pending) { -gpr_log(GPR_INFO, "CANCELLING TIMER -- is_client=%d", deadline_state->is_client); grpc_timer_cancel(exec_ctx, &deadline_state->timer); deadline_state->timer_pending = false; } @@ -99,7 +93,6 @@ gpr_log(GPR_INFO, "CANCELLING TIMER -- is_client=%d", deadline_state->is_client) // Callback run when the call is complete. static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_deadline_state* deadline_state = arg; -gpr_log(GPR_INFO, "==> %s(), is_client=%d, next_on_complete->cb=%p", __func__, deadline_state->is_client, deadline_state->next_on_complete->cb); cancel_timer_if_needed(exec_ctx, deadline_state); // Invoke the next callback. deadline_state->next_on_complete->cb( @@ -109,7 +102,6 @@ gpr_log(GPR_INFO, "==> %s(), is_client=%d, next_on_complete->cb=%p", __func__, d // Inject our own on_complete callback into op. static void inject_on_complete_cb(grpc_deadline_state* deadline_state, grpc_transport_stream_op* op) { -gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client); deadline_state->next_on_complete = op->on_complete; grpc_closure_init(&deadline_state->on_complete, on_complete, deadline_state); op->on_complete = &deadline_state->on_complete; @@ -117,7 +109,6 @@ gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client) void grpc_deadline_state_init(grpc_deadline_state* deadline_state, grpc_call_stack* call_stack) { -gpr_log(GPR_INFO, "==> %s()", __func__); memset(deadline_state, 0, sizeof(*deadline_state)); deadline_state->call_stack = call_stack; gpr_mu_init(&deadline_state->timer_mu); @@ -125,7 +116,6 @@ gpr_log(GPR_INFO, "==> %s()", __func__); void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, grpc_deadline_state* deadline_state) { -gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client); cancel_timer_if_needed(exec_ctx, deadline_state); gpr_mu_destroy(&deadline_state->timer_mu); } @@ -133,7 +123,6 @@ gpr_log(GPR_INFO, "==> %s(), is_client=%d", __func__, deadline_state->is_client) void grpc_deadline_state_client_start_transport_stream_op( grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op) { -gpr_log(GPR_INFO, "==> %s(): op=%p {on_complete=%p, cancel_error=%p, close_error=%p, send_initial_metadata=%p, send_trailing_metadata=%p, send_message=%p, recv_initial_metadata_ready=%p, recv_trailing_metadata=%p}", __func__, op, op->on_complete, op->cancel_error, op->close_error, op->send_initial_metadata, op->send_trailing_metadata, op->send_message, op->recv_initial_metadata_ready, op->recv_trailing_metadata); grpc_deadline_state* deadline_state = elem->call_data; if (op->cancel_error != GRPC_ERROR_NONE || op->close_error != GRPC_ERROR_NONE) { @@ -194,14 +183,10 @@ typedef struct server_call_data { static grpc_error *init_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element_args* args) { -gpr_log(GPR_INFO, "==> %s() -- call_data_size=%lu", __func__, (unsigned long)elem->filter->sizeof_call_data); base_call_data* calld = elem->call_data; // Note: size of call data is different between client and server. memset(calld, 0, elem->filter->sizeof_call_data); grpc_deadline_state_init(&calld->deadline_state, args->call_stack); - -calld->deadline_state.is_client = elem->filter->sizeof_call_data == sizeof(base_call_data); - return GRPC_ERROR_NONE; } @@ -217,7 +202,6 @@ static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, static void client_start_transport_stream_op(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op) { -gpr_log(GPR_INFO, "==> %s()", __func__); grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op); // Chain to next filter. grpc_call_next_op(exec_ctx, elem, op); @@ -240,7 +224,6 @@ static void recv_initial_metadata_ready(grpc_exec_ctx *exec_ctx, void *arg, static void server_start_transport_stream_op(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op) { -gpr_log(GPR_INFO, "==> %s(): op=%p {on_complete=%p, cancel_error=%p, close_error=%p, send_initial_metadata=%p, send_trailing_metadata=%p, send_message=%p, recv_initial_metadata_ready=%p, recv_trailing_metadata=%p}", __func__, op, op->on_complete, op->cancel_error, op->close_error, op->send_initial_metadata, op->send_trailing_metadata, op->send_message, op->recv_initial_metadata_ready, op->recv_trailing_metadata); server_call_data* calld = elem->call_data; if (op->cancel_error != GRPC_ERROR_NONE || op->close_error != GRPC_ERROR_NONE) { diff --git a/src/core/lib/channel/deadline_filter.h b/src/core/lib/channel/deadline_filter.h index 793b76f9b6..bfe2cab90e 100644 --- a/src/core/lib/channel/deadline_filter.h +++ b/src/core/lib/channel/deadline_filter.h @@ -52,10 +52,6 @@ typedef struct grpc_deadline_state { // The original on_complete closure, which we chain to after our own // closure is invoked. grpc_closure* next_on_complete; - -// FIXME: remove -bool is_client; - } grpc_deadline_state; void grpc_deadline_state_init(grpc_deadline_state* call_data, @@ -67,7 +63,7 @@ void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, // enforce call deadlines. // It is the caller's responsibility to chain to the next filter if // necessary after this function returns. -// REQUIRES: The first field in elem is a grpc_deadline_state struct. +// REQUIRES: The first field in elem->call_data is a grpc_deadline_state. void grpc_deadline_state_client_start_transport_stream_op( grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op); diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 15c002015c..fa0ee46da6 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -1241,10 +1241,6 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_call *child_call; grpc_call *next_child_call; -const char* msg = grpc_error_string(error); -gpr_log(GPR_INFO, "==> finish_batch(): is_client=%d, error=%s", call->is_client, msg); -grpc_error_free_string(msg); - GRPC_ERROR_REF(error); gpr_mu_lock(&call->mu); -- cgit v1.2.3 From 932b10c75bb4674650a6862d2f155f3548ebfede Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 9 Sep 2016 08:44:30 -0700 Subject: clang-format --- src/core/ext/client_config/client_channel.c | 6 +++--- src/core/ext/lb_policy/grpclb/grpclb.c | 6 +++--- src/core/ext/lb_policy/pick_first/pick_first.c | 6 +++--- src/core/ext/lb_policy/round_robin/round_robin.c | 6 +++--- src/core/lib/channel/deadline_filter.c | 25 +++++++++++------------- src/core/lib/channel/deadline_filter.h | 2 +- src/core/lib/iomgr/error.c | 21 +++++++++----------- src/core/lib/surface/call.c | 5 ++--- 8 files changed, 35 insertions(+), 42 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c index 569ca38b87..762fa271b2 100644 --- a/src/core/ext/client_config/client_channel.c +++ b/src/core/ext/client_config/client_channel.c @@ -563,9 +563,9 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, cpa = closure->cb_arg; if (cpa->connected_subchannel == connected_subchannel) { cpa->connected_subchannel = NULL; - grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, - GRPC_ERROR_CREATE_REFERENCING( - "Pick cancelled", &error, 1), NULL); + grpc_exec_ctx_sched( + exec_ctx, cpa->on_ready, + GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1), NULL); } } gpr_mu_unlock(&chand->mu); diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c index 9b7fcea1b0..cf4fae1d55 100644 --- a/src/core/ext/lb_policy/grpclb/grpclb.c +++ b/src/core/ext/lb_policy/grpclb/grpclb.c @@ -545,9 +545,9 @@ static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_polling_entity_del_from_pollset_set( exec_ctx, pp->pollent, glb_policy->base.interested_parties); *target = NULL; - grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete, - GRPC_ERROR_CREATE_REFERENCING( - "Pick Cancelled", &error, 1), NULL); + grpc_exec_ctx_sched( + exec_ctx, &pp->wrapped_on_complete, + GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1), NULL); gpr_free(pp); } else { pp->next = glb_policy->pending_picks; diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c index 089d6f45fb..dcee25b2c2 100644 --- a/src/core/ext/lb_policy/pick_first/pick_first.c +++ b/src/core/ext/lb_policy/pick_first/pick_first.c @@ -141,9 +141,9 @@ static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent, p->base.interested_parties); *target = NULL; - grpc_exec_ctx_sched(exec_ctx, pp->on_complete, - GRPC_ERROR_CREATE_REFERENCING( - "Pick Cancelled", &error, 1), NULL); + grpc_exec_ctx_sched( + exec_ctx, pp->on_complete, + GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1), NULL); gpr_free(pp); } else { pp->next = p->pending_picks; diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c index 1134495755..83aba0f8ba 100644 --- a/src/core/ext/lb_policy/round_robin/round_robin.c +++ b/src/core/ext/lb_policy/round_robin/round_robin.c @@ -294,9 +294,9 @@ static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent, p->base.interested_parties); *target = NULL; - grpc_exec_ctx_sched(exec_ctx, pp->on_complete, - GRPC_ERROR_CREATE_REFERENCING( - "Pick cancelled", &error, 1), NULL); + grpc_exec_ctx_sched( + exec_ctx, pp->on_complete, + GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1), NULL); gpr_free(pp); } else { pp->next = p->pending_picks; diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index 424d09d3d8..d83a231cac 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -45,8 +45,8 @@ // // Timer callback. -static void timer_callback(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { +static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { grpc_call_element* elem = arg; grpc_deadline_state* deadline_state = elem->call_data; gpr_mu_lock(&deadline_state->timer_mu); @@ -54,16 +54,15 @@ static void timer_callback(grpc_exec_ctx *exec_ctx, void *arg, gpr_mu_unlock(&deadline_state->timer_mu); if (error != GRPC_ERROR_CANCELLED) { gpr_slice msg = gpr_slice_from_static_string("Deadline Exceeded"); - grpc_call_element_send_cancel_with_message(exec_ctx, elem, - GRPC_STATUS_DEADLINE_EXCEEDED, - &msg); + grpc_call_element_send_cancel_with_message( + exec_ctx, elem, GRPC_STATUS_DEADLINE_EXCEEDED, &msg); gpr_slice_unref(msg); } GRPC_CALL_STACK_UNREF(exec_ctx, deadline_state->call_stack, "deadline_timer"); } // Starts the deadline timer. -static void start_timer_if_needed(grpc_exec_ctx *exec_ctx, +static void start_timer_if_needed(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, gpr_timespec deadline) { grpc_deadline_state* deadline_state = elem->call_data; @@ -91,7 +90,7 @@ static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx, } // Callback run when the call is complete. -static void on_complete(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { +static void on_complete(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { grpc_deadline_state* deadline_state = arg; cancel_timer_if_needed(exec_ctx, deadline_state); // Invoke the next callback. @@ -159,8 +158,7 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx, // Destructor for channel_data. Used for both client and server filters. static void destroy_channel_elem(grpc_exec_ctx* exec_ctx, - grpc_channel_element* elem) { -} + grpc_channel_element* elem) {} // Call data used for both client and server filter. typedef struct base_call_data { @@ -180,7 +178,7 @@ typedef struct server_call_data { } server_call_data; // Constructor for call_data. Used for both client and server filters. -static grpc_error *init_call_elem(grpc_exec_ctx* exec_ctx, +static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element_args* args) { base_call_data* calld = elem->call_data; @@ -208,13 +206,12 @@ static void client_start_transport_stream_op(grpc_exec_ctx* exec_ctx, } // Callback for receiving initial metadata on the server. -static void recv_initial_metadata_ready(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { +static void recv_initial_metadata_ready(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { grpc_call_element* elem = arg; server_call_data* calld = elem->call_data; // Get deadline from metadata and start the timer if needed. - start_timer_if_needed(exec_ctx, elem, - calld->recv_initial_metadata->deadline); + start_timer_if_needed(exec_ctx, elem, calld->recv_initial_metadata->deadline); // Invoke the next callback. calld->next_recv_initial_metadata_ready->cb( exec_ctx, calld->next_recv_initial_metadata_ready->cb_arg, error); diff --git a/src/core/lib/channel/deadline_filter.h b/src/core/lib/channel/deadline_filter.h index bfe2cab90e..a09f85afe6 100644 --- a/src/core/lib/channel/deadline_filter.h +++ b/src/core/lib/channel/deadline_filter.h @@ -74,4 +74,4 @@ void grpc_deadline_state_client_start_transport_stream_op( extern const grpc_channel_filter grpc_client_deadline_filter; extern const grpc_channel_filter grpc_server_deadline_filter; -#endif // GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H +#endif /* GRPC_CORE_LIB_CHANNEL_DEADLINE_FILTER_H */ diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c index 17f19423a3..e13f37f8ed 100644 --- a/src/core/lib/iomgr/error.c +++ b/src/core/lib/iomgr/error.c @@ -330,13 +330,13 @@ typedef struct { const char *msg; } special_error_status_map; static special_error_status_map error_status_map[] = { - { GRPC_ERROR_NONE, GRPC_STATUS_OK, "" }, - { GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "RPC cancelled" }, - { GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory" }, + {GRPC_ERROR_NONE, GRPC_STATUS_OK, ""}, + {GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "RPC cancelled"}, + {GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"}, }; -static grpc_error *recursively_find_error_with_status(grpc_error* error, - intptr_t* status) { +static grpc_error *recursively_find_error_with_status(grpc_error *error, + intptr_t *status) { // If the error itself has a status code, return it. if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, status)) { return error; @@ -345,12 +345,10 @@ static grpc_error *recursively_find_error_with_status(grpc_error* error, intptr_t key = 0; while (true) { grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++); - if (child_error == NULL) - break; + if (child_error == NULL) break; grpc_error *result = recursively_find_error_with_status(child_error, status); - if (result != NULL) - return result; + if (result != NULL) return result; } return NULL; } @@ -359,8 +357,7 @@ void grpc_error_get_status(grpc_error *error, grpc_status_code *code, const char **msg) { // Handle special errors via the static map. for (size_t i = 0; - i < sizeof(error_status_map) / sizeof(special_error_status_map); - ++i) { + i < sizeof(error_status_map) / sizeof(special_error_status_map); ++i) { if (error == error_status_map[i].error) { *code = error_status_map[i].code; *msg = error_status_map[i].msg; @@ -371,7 +368,7 @@ void grpc_error_get_status(grpc_error *error, grpc_status_code *code, // Start with the parent error and recurse through the tree of children // until we find the first one that has a status code. intptr_t status = GRPC_STATUS_UNKNOWN; // Default in case we don't find one. - grpc_error* found_error = recursively_find_error_with_status(error, &status); + grpc_error *found_error = recursively_find_error_with_status(error, &status); *code = (grpc_status_code)status; // Now populate msg. // If we found an error with a status code above, use that; otherwise, diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index fa0ee46da6..424cd00d96 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -253,8 +253,7 @@ grpc_call *grpc_call_create( call->metadata_batch[i][j].deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); } } - send_deadline = - gpr_convert_clock_type(send_deadline, GPR_CLOCK_MONOTONIC); + send_deadline = gpr_convert_clock_type(send_deadline, GPR_CLOCK_MONOTONIC); GRPC_CHANNEL_INTERNAL_REF(channel, "call"); /* initial refcount dropped by grpc_call_destroy */ grpc_error *error = grpc_call_stack_init( @@ -438,7 +437,7 @@ static void set_status_details(grpc_call *call, status_source source, static void set_status_from_error(grpc_call *call, status_source source, grpc_error *error) { grpc_status_code status; - const char* msg; + const char *msg; grpc_error_get_status(error, &status, &msg); set_status_code(call, source, (uint32_t)status); set_status_details(call, source, grpc_mdstr_from_string(msg)); -- cgit v1.2.3 From b3405f0a7370857373d71bb6a62e056f37493529 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 9 Sep 2016 08:46:28 -0700 Subject: Fix build problem on Windows. --- src/core/lib/channel/deadline_filter.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index d83a231cac..010fedd7b7 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -145,10 +145,6 @@ void grpc_deadline_state_client_start_transport_stream_op( // filter code // -// Used for both client and server filters. -typedef struct channel_data { -} channel_data; - // Constructor for channel_data. Used for both client and server filters. static void init_channel_elem(grpc_exec_ctx* exec_ctx, grpc_channel_element* elem, @@ -256,7 +252,7 @@ const grpc_channel_filter grpc_client_deadline_filter = { init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, - sizeof(channel_data), + 0, // sizeof(channel_data) init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, @@ -270,7 +266,7 @@ const grpc_channel_filter grpc_server_deadline_filter = { init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, - sizeof(channel_data), + 0, // sizeof(channel_data) init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, -- cgit v1.2.3 From a4a223fb87ae407bda044f16cba3750d169a33f4 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 9 Sep 2016 10:54:06 -0700 Subject: Fix Windows no_logging test failure. --- src/core/lib/iomgr/socket_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/socket_windows.c b/src/core/lib/iomgr/socket_windows.c index d7d5f6f157..78ef46d042 100644 --- a/src/core/lib/iomgr/socket_windows.c +++ b/src/core/lib/iomgr/socket_windows.c @@ -84,7 +84,7 @@ void grpc_winsocket_shutdown(grpc_winsocket *winsocket) { DisconnectEx(winsocket->socket, NULL, 0, 0); } else { char *utf8_message = gpr_format_message(WSAGetLastError()); - gpr_log(GPR_ERROR, "Unable to retrieve DisconnectEx pointer : %s", + gpr_log(GPR_INFO, "Unable to retrieve DisconnectEx pointer : %s", utf8_message); gpr_free(utf8_message); } -- cgit v1.2.3 From e65ff1116158958febacd1131a7c2f84f4e0eb1b Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 9 Sep 2016 13:48:38 -0700 Subject: Propagate error through grpc_lb_policy_cancel_picks(). Also fix error reporting (and improve control flow) in on_writable() in tcp_client_posix.c. --- src/core/ext/client_config/client_channel.c | 3 +- src/core/ext/client_config/lb_policy.c | 5 +- src/core/ext/client_config/lb_policy.h | 5 +- src/core/ext/client_config/subchannel.c | 4 +- src/core/ext/lb_policy/grpclb/grpclb.c | 7 +- src/core/ext/lb_policy/pick_first/pick_first.c | 7 +- src/core/ext/lb_policy/round_robin/round_robin.c | 9 ++- src/core/lib/iomgr/tcp_client_posix.c | 96 ++++++++++++------------ 8 files changed, 73 insertions(+), 63 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c index 762fa271b2..245cfbb8c4 100644 --- a/src/core/ext/client_config/client_channel.c +++ b/src/core/ext/client_config/client_channel.c @@ -112,7 +112,8 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy_cancel_picks( exec_ctx, chand->lb_policy, /* mask= */ GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY, - /* check= */ 0); + /* check= */ 0, + GRPC_ERROR_REF(error)); } grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error, reason); diff --git a/src/core/ext/client_config/lb_policy.c b/src/core/ext/client_config/lb_policy.c index 5e605491e7..3e498f5f56 100644 --- a/src/core/ext/client_config/lb_policy.c +++ b/src/core/ext/client_config/lb_policy.c @@ -118,9 +118,10 @@ void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, uint32_t initial_metadata_flags_mask, - uint32_t initial_metadata_flags_eq) { + uint32_t initial_metadata_flags_eq, + grpc_error *error) { policy->vtable->cancel_picks(exec_ctx, policy, initial_metadata_flags_mask, - initial_metadata_flags_eq); + initial_metadata_flags_eq, error); } void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) { diff --git a/src/core/ext/client_config/lb_policy.h b/src/core/ext/client_config/lb_policy.h index 9650110cce..eb07ad3360 100644 --- a/src/core/ext/client_config/lb_policy.h +++ b/src/core/ext/client_config/lb_policy.h @@ -68,7 +68,7 @@ struct grpc_lb_policy_vtable { grpc_connected_subchannel **target, grpc_error *error); void (*cancel_picks)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, uint32_t initial_metadata_flags_mask, - uint32_t initial_metadata_flags_eq); + uint32_t initial_metadata_flags_eq, grpc_error *error); void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, grpc_closure *closure); @@ -148,7 +148,8 @@ void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, uint32_t initial_metadata_flags_mask, - uint32_t initial_metadata_flags_eq); + uint32_t initial_metadata_flags_eq, + grpc_error *error); /** Try to enter a READY connectivity state */ void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy); diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c index 3d4318774b..456cc44635 100644 --- a/src/core/ext/client_config/subchannel.c +++ b/src/core/ext/client_config/subchannel.c @@ -635,7 +635,9 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg, c->have_alarm = 1; grpc_connectivity_state_set( exec_ctx, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, - GRPC_ERROR_CREATE_REFERENCING("Connect Failed", &error, 1), + grpc_error_set_int( + GRPC_ERROR_CREATE_REFERENCING("Connect Failed", &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), "connect_failed"); gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now); const char *errmsg = grpc_error_string(error); diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c index cf4fae1d55..50eb54f1cc 100644 --- a/src/core/ext/lb_policy/grpclb/grpclb.c +++ b/src/core/ext/lb_policy/grpclb/grpclb.c @@ -562,7 +562,8 @@ static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, static grpc_call *lb_client_data_get_call(struct lb_client_data *lb_client); static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, uint32_t initial_metadata_flags_mask, - uint32_t initial_metadata_flags_eq) { + uint32_t initial_metadata_flags_eq, + grpc_error *error) { glb_lb_policy *glb_policy = (glb_lb_policy *)pol; gpr_mu_lock(&glb_policy->mu); if (glb_policy->lb_client != NULL) { @@ -578,7 +579,8 @@ static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_polling_entity_del_from_pollset_set( exec_ctx, pp->pollent, glb_policy->base.interested_parties); grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete, - GRPC_ERROR_CANCELLED, NULL); + GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", + &error, 1), NULL); gpr_free(pp); } else { pp->next = glb_policy->pending_picks; @@ -587,6 +589,7 @@ static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, pp = next; } gpr_mu_unlock(&glb_policy->mu); + GRPC_ERROR_UNREF(error); } static void query_for_backends(grpc_exec_ctx *exec_ctx, diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c index dcee25b2c2..9e83de28e5 100644 --- a/src/core/ext/lb_policy/pick_first/pick_first.c +++ b/src/core/ext/lb_policy/pick_first/pick_first.c @@ -157,7 +157,8 @@ static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, uint32_t initial_metadata_flags_mask, - uint32_t initial_metadata_flags_eq) { + uint32_t initial_metadata_flags_eq, + grpc_error *error) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; pending_pick *pp; gpr_mu_lock(&p->mu); @@ -170,7 +171,8 @@ static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent, p->base.interested_parties); grpc_exec_ctx_sched(exec_ctx, pp->on_complete, - GRPC_ERROR_CREATE("Pick Cancelled"), NULL); + GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", + &error, 1), NULL); gpr_free(pp); } else { pp->next = p->pending_picks; @@ -179,6 +181,7 @@ static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, pp = next; } gpr_mu_unlock(&p->mu); + GRPC_ERROR_UNREF(error); } static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) { diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c index 83aba0f8ba..0c40dcf961 100644 --- a/src/core/ext/lb_policy/round_robin/round_robin.c +++ b/src/core/ext/lb_policy/round_robin/round_robin.c @@ -310,7 +310,8 @@ static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, uint32_t initial_metadata_flags_mask, - uint32_t initial_metadata_flags_eq) { + uint32_t initial_metadata_flags_eq, + grpc_error *error) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; pending_pick *pp; gpr_mu_lock(&p->mu); @@ -323,8 +324,9 @@ static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent, p->base.interested_parties); *pp->target = NULL; - grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_CANCELLED, - NULL); + grpc_exec_ctx_sched(exec_ctx, pp->on_complete, + GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", + &error, 1), NULL); gpr_free(pp); } else { pp->next = p->pending_picks; @@ -333,6 +335,7 @@ static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, pp = next; } gpr_mu_unlock(&p->mu); + GRPC_ERROR_UNREF(error); } static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) { diff --git a/src/core/lib/iomgr/tcp_client_posix.c b/src/core/lib/iomgr/tcp_client_posix.c index 80c7a3f128..3496b6094f 100644 --- a/src/core/lib/iomgr/tcp_client_posix.c +++ b/src/core/lib/iomgr/tcp_client_posix.c @@ -146,61 +146,57 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { grpc_timer_cancel(exec_ctx, &ac->alarm); gpr_mu_lock(&ac->mu); - if (error == GRPC_ERROR_NONE) { - do { - so_error_size = sizeof(so_error); - err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error, - &so_error_size); - } while (err < 0 && errno == EINTR); - if (err < 0) { - error = GRPC_OS_ERROR(errno, "getsockopt"); - goto finish; - } else if (so_error != 0) { - if (so_error == ENOBUFS) { - /* We will get one of these errors if we have run out of - memory in the kernel for the data structures allocated - when you connect a socket. If this happens it is very - likely that if we wait a little bit then try again the - connection will work (since other programs or this - program will close their network connections and free up - memory). This does _not_ indicate that there is anything - wrong with the server we are connecting to, this is a - local problem. - - If you are looking at this code, then chances are that - your program or another program on the same computer - opened too many network connections. The "easy" fix: - don't do that! */ - gpr_log(GPR_ERROR, "kernel out of buffers"); - gpr_mu_unlock(&ac->mu); - grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure); - return; - } else { - switch (so_error) { - case ECONNREFUSED: - error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, errno); - error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, - "Connection refused"); - break; - default: - error = GRPC_OS_ERROR(errno, "getsockopt(SO_ERROR)"); - break; - } - goto finish; - } - } else { - grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd); - *ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str); - fd = NULL; - goto finish; - } - } else { + if (error != GRPC_ERROR_NONE) { error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, "Timeout occurred"); goto finish; } - GPR_UNREACHABLE_CODE(return ); + do { + so_error_size = sizeof(so_error); + err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error, + &so_error_size); + } while (err < 0 && errno == EINTR); + if (err < 0) { + error = GRPC_OS_ERROR(errno, "getsockopt"); + goto finish; + } + + switch (so_error) { + case 0: + grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd); + *ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str); + fd = NULL; + break; + case ENOBUFS: + /* We will get one of these errors if we have run out of + memory in the kernel for the data structures allocated + when you connect a socket. If this happens it is very + likely that if we wait a little bit then try again the + connection will work (since other programs or this + program will close their network connections and free up + memory). This does _not_ indicate that there is anything + wrong with the server we are connecting to, this is a + local problem. + + If you are looking at this code, then chances are that + your program or another program on the same computer + opened too many network connections. The "easy" fix: + don't do that! */ + gpr_log(GPR_ERROR, "kernel out of buffers"); + gpr_mu_unlock(&ac->mu); + grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure); + return; + case ECONNREFUSED: + /* This error shouldn't happen for anything other than connect(). */ + error = GRPC_OS_ERROR(so_error, "connect"); + break; + default: + /* We don't really know which syscall triggered the problem here, + so punt by reporting getsockopt(). */ + error = GRPC_OS_ERROR(so_error, "getsockopt(SO_ERROR)"); + break; + } finish: if (fd != NULL) { -- cgit v1.2.3 From 537f7c2a136641487febeac89a25e430029eb40c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 12 Sep 2016 11:56:39 -0700 Subject: Revert "Grand unified closures" --- BUILD | 16 - CMakeLists.txt | 6 - Makefile | 79 --- binding.gyp | 2 - build.yaml | 24 - config.m4 | 2 - gRPC-Core.podspec | 6 - grpc.gemspec | 4 - include/grpc/impl/codegen/atm.h | 3 - include/grpc/impl/codegen/atm_gcc_atomic.h | 2 - include/grpc/impl/codegen/atm_gcc_sync.h | 8 - include/grpc/impl/codegen/atm_windows.h | 4 - package.xml | 4 - src/core/ext/client_config/client_channel.c | 14 +- src/core/ext/client_config/subchannel.c | 18 +- .../transport/chttp2/transport/chttp2_transport.c | 766 ++++++++++++--------- src/core/ext/transport/chttp2/transport/internal.h | 54 +- src/core/ext/transport/chttp2/transport/parsing.c | 12 +- .../ext/transport/chttp2/transport/stream_lists.c | 9 +- src/core/ext/transport/chttp2/transport/writing.c | 21 +- src/core/lib/channel/channel_stack.c | 23 +- src/core/lib/channel/compress_filter.c | 14 +- src/core/lib/iomgr/closure.c | 4 - src/core/lib/iomgr/closure.h | 18 +- src/core/lib/iomgr/combiner.c | 293 -------- src/core/lib/iomgr/combiner.h | 71 -- src/core/lib/iomgr/error.c | 2 +- src/core/lib/iomgr/ev_epoll_linux.c | 4 - src/core/lib/iomgr/exec_ctx.h | 6 +- src/core/lib/iomgr/tcp_posix.c | 17 - src/core/lib/iomgr/workqueue.h | 4 + src/core/lib/iomgr/workqueue_posix.c | 97 +-- src/core/lib/iomgr/workqueue_posix.h | 9 +- src/core/lib/iomgr/workqueue_windows.c | 2 + .../lib/security/transport/client_auth_filter.c | 5 - src/core/lib/security/transport/secure_endpoint.c | 5 - .../lib/security/transport/server_auth_filter.c | 27 +- src/core/lib/support/mpscq.c | 83 --- src/core/lib/support/mpscq.h | 65 -- src/core/lib/surface/call.c | 63 +- src/core/lib/surface/channel.c | 7 +- src/core/lib/surface/channel_ping.c | 11 +- src/core/lib/surface/init.c | 2 - src/core/lib/surface/lame_client.c | 6 +- src/core/lib/surface/server.c | 69 +- src/core/lib/transport/transport.c | 27 - src/core/lib/transport/transport.h | 21 - src/python/grpcio/grpc_core_dependencies.py | 2 - test/core/iomgr/combiner_test.c | 164 ----- test/core/support/mpscq_test.c | 206 ------ test/core/surface/lame_client_test.c | 21 +- tools/doxygen/Doxyfile.c++.internal | 2 - tools/doxygen/Doxyfile.core.internal | 4 - tools/run_tests/sources_and_headers.json | 36 - tools/run_tests/tests.json | 42 -- vsprojects/buildtests_c.sln | 52 -- vsprojects/vcxproj/gpr/gpr.vcxproj | 3 - vsprojects/vcxproj/gpr/gpr.vcxproj.filters | 6 - vsprojects/vcxproj/grpc++/grpc++.vcxproj | 3 - vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters | 6 - .../grpc++_unsecure/grpc++_unsecure.vcxproj | 3 - .../grpc++_unsecure.vcxproj.filters | 6 - vsprojects/vcxproj/grpc/grpc.vcxproj | 3 - vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 6 - .../vcxproj/grpc_test_util/grpc_test_util.vcxproj | 3 - .../grpc_test_util/grpc_test_util.vcxproj.filters | 6 - .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 3 - .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 - .../test/combiner_test/combiner_test.vcxproj | 199 ------ .../combiner_test/combiner_test.vcxproj.filters | 21 - .../test/gpr_mpscq_test/gpr_mpscq_test.vcxproj | 193 ------ .../gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters | 21 - 72 files changed, 660 insertions(+), 2366 deletions(-) delete mode 100644 src/core/lib/iomgr/combiner.c delete mode 100644 src/core/lib/iomgr/combiner.h delete mode 100644 src/core/lib/support/mpscq.c delete mode 100644 src/core/lib/support/mpscq.h delete mode 100644 test/core/iomgr/combiner_test.c delete mode 100644 test/core/support/mpscq_test.c delete mode 100644 vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj delete mode 100644 vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters delete mode 100644 vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj delete mode 100644 vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index 7db1c1d2f6..ee41d1ab21 100644 --- a/BUILD +++ b/BUILD @@ -51,7 +51,6 @@ cc_library( "src/core/lib/support/backoff.h", "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", - "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/percent_encoding.h", "src/core/lib/support/stack_lockfree.h", @@ -80,7 +79,6 @@ cc_library( "src/core/lib/support/log_linux.c", "src/core/lib/support/log_posix.c", "src/core/lib/support/log_windows.c", - "src/core/lib/support/mpscq.c", "src/core/lib/support/murmur_hash.c", "src/core/lib/support/percent_encoding.c", "src/core/lib/support/slice.c", @@ -181,7 +179,6 @@ cc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -337,7 +334,6 @@ cc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", - "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -578,7 +574,6 @@ cc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -720,7 +715,6 @@ cc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", - "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -932,7 +926,6 @@ cc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -1065,7 +1058,6 @@ cc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", - "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -1281,7 +1273,6 @@ cc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -1394,7 +1385,6 @@ cc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", - "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -1693,7 +1683,6 @@ cc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -1801,7 +1790,6 @@ cc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", - "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -2080,7 +2068,6 @@ objc_library( "src/core/lib/support/log_linux.c", "src/core/lib/support/log_posix.c", "src/core/lib/support/log_windows.c", - "src/core/lib/support/mpscq.c", "src/core/lib/support/murmur_hash.c", "src/core/lib/support/percent_encoding.c", "src/core/lib/support/slice.c", @@ -2155,7 +2142,6 @@ objc_library( "src/core/lib/support/backoff.h", "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", - "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/percent_encoding.h", "src/core/lib/support/stack_lockfree.h", @@ -2194,7 +2180,6 @@ objc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", - "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -2414,7 +2399,6 @@ objc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 915c406c9a..05aa323ca9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,7 +191,6 @@ add_library(gpr src/core/lib/support/log_linux.c src/core/lib/support/log_posix.c src/core/lib/support/log_windows.c - src/core/lib/support/mpscq.c src/core/lib/support/murmur_hash.c src/core/lib/support/percent_encoding.c src/core/lib/support/slice.c @@ -308,7 +307,6 @@ add_library(grpc src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c - src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -567,7 +565,6 @@ add_library(grpc_cronet src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c - src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -799,7 +796,6 @@ add_library(grpc_unsecure src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c - src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -1057,7 +1053,6 @@ add_library(grpc++ src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c - src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -1415,7 +1410,6 @@ add_library(grpc++_unsecure src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c - src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c diff --git a/Makefile b/Makefile index 219c0e4a43..e454ad6cd7 100644 --- a/Makefile +++ b/Makefile @@ -915,7 +915,6 @@ chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test client_fuzzer: $(BINDIR)/$(CONFIG)/client_fuzzer -combiner_test: $(BINDIR)/$(CONFIG)/combiner_test compression_test: $(BINDIR)/$(CONFIG)/compression_test concurrent_connectivity_test: $(BINDIR)/$(CONFIG)/concurrent_connectivity_test dns_resolver_connectivity_test: $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test @@ -941,7 +940,6 @@ gpr_env_test: $(BINDIR)/$(CONFIG)/gpr_env_test gpr_histogram_test: $(BINDIR)/$(CONFIG)/gpr_histogram_test gpr_host_port_test: $(BINDIR)/$(CONFIG)/gpr_host_port_test gpr_log_test: $(BINDIR)/$(CONFIG)/gpr_log_test -gpr_mpscq_test: $(BINDIR)/$(CONFIG)/gpr_mpscq_test gpr_percent_encoding_test: $(BINDIR)/$(CONFIG)/gpr_percent_encoding_test gpr_slice_buffer_test: $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test gpr_slice_test: $(BINDIR)/$(CONFIG)/gpr_slice_test @@ -1242,7 +1240,6 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test \ $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \ $(BINDIR)/$(CONFIG)/chttp2_varint_test \ - $(BINDIR)/$(CONFIG)/combiner_test \ $(BINDIR)/$(CONFIG)/compression_test \ $(BINDIR)/$(CONFIG)/concurrent_connectivity_test \ $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test \ @@ -1265,7 +1262,6 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/gpr_histogram_test \ $(BINDIR)/$(CONFIG)/gpr_host_port_test \ $(BINDIR)/$(CONFIG)/gpr_log_test \ - $(BINDIR)/$(CONFIG)/gpr_mpscq_test \ $(BINDIR)/$(CONFIG)/gpr_percent_encoding_test \ $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test \ $(BINDIR)/$(CONFIG)/gpr_slice_test \ @@ -1561,8 +1557,6 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_stream_map_test || ( echo test chttp2_stream_map_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_varint_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_varint_test || ( echo test chttp2_varint_test failed ; exit 1 ) - $(E) "[RUN] Testing combiner_test" - $(Q) $(BINDIR)/$(CONFIG)/combiner_test || ( echo test combiner_test failed ; exit 1 ) $(E) "[RUN] Testing compression_test" $(Q) $(BINDIR)/$(CONFIG)/compression_test || ( echo test compression_test failed ; exit 1 ) $(E) "[RUN] Testing concurrent_connectivity_test" @@ -1603,8 +1597,6 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/gpr_host_port_test || ( echo test gpr_host_port_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_mpscq_test" - $(Q) $(BINDIR)/$(CONFIG)/gpr_mpscq_test || ( echo test gpr_mpscq_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_percent_encoding_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_percent_encoding_test || ( echo test gpr_percent_encoding_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_slice_buffer_test" @@ -2386,7 +2378,6 @@ LIBGPR_SRC = \ src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_windows.c \ - src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/percent_encoding.c \ src/core/lib/support/slice.c \ @@ -2537,7 +2528,6 @@ LIBGRPC_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ - src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -2814,7 +2804,6 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ - src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -3080,7 +3069,6 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ - src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -3274,7 +3262,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ - src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -3615,7 +3602,6 @@ LIBGRPC++_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ - src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -4251,7 +4237,6 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ - src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -7428,38 +7413,6 @@ endif endif -COMBINER_TEST_SRC = \ - test/core/iomgr/combiner_test.c \ - -COMBINER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(COMBINER_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL. - -$(BINDIR)/$(CONFIG)/combiner_test: openssl_dep_error - -else - - - -$(BINDIR)/$(CONFIG)/combiner_test: $(COMBINER_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) $(COMBINER_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)/combiner_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/iomgr/combiner_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - -deps_combiner_test: $(COMBINER_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(COMBINER_TEST_OBJS:.o=.dep) -endif -endif - - COMPRESSION_TEST_SRC = \ test/core/compression/compression_test.c \ @@ -8260,38 +8213,6 @@ endif endif -GPR_MPSCQ_TEST_SRC = \ - test/core/support/mpscq_test.c \ - -GPR_MPSCQ_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_MPSCQ_TEST_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL. - -$(BINDIR)/$(CONFIG)/gpr_mpscq_test: openssl_dep_error - -else - - - -$(BINDIR)/$(CONFIG)/gpr_mpscq_test: $(GPR_MPSCQ_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(GPR_MPSCQ_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_mpscq_test - -endif - -$(OBJDIR)/$(CONFIG)/test/core/support/mpscq_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - -deps_gpr_mpscq_test: $(GPR_MPSCQ_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(GPR_MPSCQ_TEST_OBJS:.o=.dep) -endif -endif - - GPR_PERCENT_ENCODING_TEST_SRC = \ test/core/support/percent_encoding_test.c \ diff --git a/binding.gyp b/binding.gyp index b4f182c4b7..7cc8a58c01 100644 --- a/binding.gyp +++ b/binding.gyp @@ -515,7 +515,6 @@ 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_windows.c', - 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/percent_encoding.c', 'src/core/lib/support/slice.c', @@ -580,7 +579,6 @@ 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', 'src/core/lib/iomgr/closure.c', - 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', diff --git a/build.yaml b/build.yaml index ee459ea3f5..6eb23d6fb7 100644 --- a/build.yaml +++ b/build.yaml @@ -82,7 +82,6 @@ filegroups: - src/core/lib/support/backoff.h - src/core/lib/support/block_annotate.h - src/core/lib/support/env.h - - src/core/lib/support/mpscq.h - src/core/lib/support/murmur_hash.h - src/core/lib/support/percent_encoding.h - src/core/lib/support/stack_lockfree.h @@ -112,7 +111,6 @@ filegroups: - src/core/lib/support/log_linux.c - src/core/lib/support/log_posix.c - src/core/lib/support/log_windows.c - - src/core/lib/support/mpscq.c - src/core/lib/support/murmur_hash.c - src/core/lib/support/percent_encoding.c - src/core/lib/support/slice.c @@ -183,7 +181,6 @@ filegroups: - src/core/lib/http/httpcli.h - src/core/lib/http/parser.h - src/core/lib/iomgr/closure.h - - src/core/lib/iomgr/combiner.h - src/core/lib/iomgr/endpoint.h - src/core/lib/iomgr/endpoint_pair.h - src/core/lib/iomgr/error.h @@ -264,7 +261,6 @@ filegroups: - src/core/lib/http/httpcli.c - src/core/lib/http/parser.c - src/core/lib/iomgr/closure.c - - src/core/lib/iomgr/combiner.c - src/core/lib/iomgr/endpoint.c - src/core/lib/iomgr/endpoint_pair_posix.c - src/core/lib/iomgr/endpoint_pair_windows.c @@ -1412,17 +1408,6 @@ targets: - test/core/end2end/fuzzers/client_fuzzer_corpus dict: test/core/end2end/fuzzers/hpack.dictionary maxlen: 2048 -- name: combiner_test - cpu_cost: 30 - build: test - language: c - src: - - test/core/iomgr/combiner_test.c - deps: - - grpc_test_util - - grpc - - gpr_test_util - - gpr - name: compression_test build: test language: c @@ -1680,15 +1665,6 @@ targets: deps: - gpr_test_util - gpr -- name: gpr_mpscq_test - cpu_cost: 30 - build: test - language: c - src: - - test/core/support/mpscq_test.c - deps: - - gpr_test_util - - gpr - name: gpr_percent_encoding_test build: test language: c diff --git a/config.m4 b/config.m4 index 5947306c39..5384585dd6 100644 --- a/config.m4 +++ b/config.m4 @@ -56,7 +56,6 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_windows.c \ - src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/percent_encoding.c \ src/core/lib/support/slice.c \ @@ -99,7 +98,6 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ - src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 895e39b2a7..deffa1653e 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -200,7 +200,6 @@ Pod::Spec.new do |s| 'src/core/lib/support/backoff.h', 'src/core/lib/support/block_annotate.h', 'src/core/lib/support/env.h', - 'src/core/lib/support/mpscq.h', 'src/core/lib/support/murmur_hash.h', 'src/core/lib/support/percent_encoding.h', 'src/core/lib/support/stack_lockfree.h', @@ -229,7 +228,6 @@ Pod::Spec.new do |s| 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_windows.c', - 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/percent_encoding.c', 'src/core/lib/support/slice.c', @@ -272,7 +270,6 @@ Pod::Spec.new do |s| 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', 'src/core/lib/iomgr/closure.h', - 'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/error.h', @@ -432,7 +429,6 @@ Pod::Spec.new do |s| 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', 'src/core/lib/iomgr/closure.c', - 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', @@ -612,7 +608,6 @@ Pod::Spec.new do |s| 'src/core/lib/support/backoff.h', 'src/core/lib/support/block_annotate.h', 'src/core/lib/support/env.h', - 'src/core/lib/support/mpscq.h', 'src/core/lib/support/murmur_hash.h', 'src/core/lib/support/percent_encoding.h', 'src/core/lib/support/stack_lockfree.h', @@ -637,7 +632,6 @@ Pod::Spec.new do |s| 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', 'src/core/lib/iomgr/closure.h', - 'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/error.h', diff --git a/grpc.gemspec b/grpc.gemspec index 2a27492cfe..f249006065 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -90,7 +90,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/support/backoff.h ) s.files += %w( src/core/lib/support/block_annotate.h ) s.files += %w( src/core/lib/support/env.h ) - s.files += %w( src/core/lib/support/mpscq.h ) s.files += %w( src/core/lib/support/murmur_hash.h ) s.files += %w( src/core/lib/support/percent_encoding.h ) s.files += %w( src/core/lib/support/stack_lockfree.h ) @@ -119,7 +118,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/support/log_linux.c ) s.files += %w( src/core/lib/support/log_posix.c ) s.files += %w( src/core/lib/support/log_windows.c ) - s.files += %w( src/core/lib/support/mpscq.c ) s.files += %w( src/core/lib/support/murmur_hash.c ) s.files += %w( src/core/lib/support/percent_encoding.c ) s.files += %w( src/core/lib/support/slice.c ) @@ -192,7 +190,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/http/httpcli.h ) s.files += %w( src/core/lib/http/parser.h ) s.files += %w( src/core/lib/iomgr/closure.h ) - s.files += %w( src/core/lib/iomgr/combiner.h ) s.files += %w( src/core/lib/iomgr/endpoint.h ) s.files += %w( src/core/lib/iomgr/endpoint_pair.h ) s.files += %w( src/core/lib/iomgr/error.h ) @@ -352,7 +349,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/http/httpcli.c ) s.files += %w( src/core/lib/http/parser.c ) s.files += %w( src/core/lib/iomgr/closure.c ) - s.files += %w( src/core/lib/iomgr/combiner.c ) s.files += %w( src/core/lib/iomgr/endpoint.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_posix.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c ) diff --git a/include/grpc/impl/codegen/atm.h b/include/grpc/impl/codegen/atm.h index ae00fb0f16..5589d5d411 100644 --- a/include/grpc/impl/codegen/atm.h +++ b/include/grpc/impl/codegen/atm.h @@ -75,9 +75,6 @@ int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n); int gpr_atm_acq_cas(gpr_atm *p, gpr_atm o, gpr_atm n); int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n); - - // Atomically, set *p=n and return the old value of *p - gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n); */ #include diff --git a/include/grpc/impl/codegen/atm_gcc_atomic.h b/include/grpc/impl/codegen/atm_gcc_atomic.h index 7d4ae98cf7..8caf7edbde 100644 --- a/include/grpc/impl/codegen/atm_gcc_atomic.h +++ b/include/grpc/impl/codegen/atm_gcc_atomic.h @@ -69,6 +69,4 @@ static __inline int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { __ATOMIC_RELAXED); } -#define gpr_atm_full_xchg(p, n) __atomic_exchange_n((p), (n), __ATOMIC_ACQ_REL) - #endif /* GRPC_IMPL_CODEGEN_ATM_GCC_ATOMIC_H */ diff --git a/include/grpc/impl/codegen/atm_gcc_sync.h b/include/grpc/impl/codegen/atm_gcc_sync.h index 9aa2b43189..915b09fb0c 100644 --- a/include/grpc/impl/codegen/atm_gcc_sync.h +++ b/include/grpc/impl/codegen/atm_gcc_sync.h @@ -84,12 +84,4 @@ static __inline void gpr_atm_no_barrier_store(gpr_atm *p, gpr_atm value) { #define gpr_atm_acq_cas(p, o, n) (__sync_bool_compare_and_swap((p), (o), (n))) #define gpr_atm_rel_cas(p, o, n) gpr_atm_acq_cas((p), (o), (n)) -static __inline gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n) { - gpr_atm cur; - do { - cur = gpr_atm_acq_load(p); - } while (!gpr_atm_rel_cas(p, cur, n)); - return cur; -} - #endif /* GRPC_IMPL_CODEGEN_ATM_GCC_SYNC_H */ diff --git a/include/grpc/impl/codegen/atm_windows.h b/include/grpc/impl/codegen/atm_windows.h index 0ab70b95c4..d5fa8c0f62 100644 --- a/include/grpc/impl/codegen/atm_windows.h +++ b/include/grpc/impl/codegen/atm_windows.h @@ -122,8 +122,4 @@ static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm *p, gpr_atm delta) { return old; } -static __inline gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n) { - return (gpr_atm)InterlockedExchangePointer((PVOID *)p, (PVOID)n); -} - #endif /* GRPC_IMPL_CODEGEN_ATM_WINDOWS_H */ diff --git a/package.xml b/package.xml index 4f596e0e8f..93210ee47b 100644 --- a/package.xml +++ b/package.xml @@ -97,7 +97,6 @@ - @@ -126,7 +125,6 @@ - @@ -199,7 +197,6 @@ - @@ -359,7 +356,6 @@ - diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c index be333f4e0d..61e012578e 100644 --- a/src/core/ext/client_config/client_channel.c +++ b/src/core/ext/client_config/client_channel.c @@ -387,7 +387,7 @@ typedef struct client_channel_call_data { grpc_connected_subchannel *connected_subchannel; grpc_polling_entity *pollent; - grpc_transport_stream_op **waiting_ops; + grpc_transport_stream_op *waiting_ops; size_t waiting_ops_count; size_t waiting_ops_capacity; @@ -404,7 +404,7 @@ static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) { gpr_realloc(calld->waiting_ops, calld->waiting_ops_capacity * sizeof(*calld->waiting_ops)); } - calld->waiting_ops[calld->waiting_ops_count++] = op; + calld->waiting_ops[calld->waiting_ops_count++] = *op; GPR_TIMER_END("add_waiting_locked", 0); } @@ -413,14 +413,14 @@ static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld, size_t i; for (i = 0; i < calld->waiting_ops_count; i++) { grpc_transport_stream_op_finish_with_failure( - exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error)); + exec_ctx, &calld->waiting_ops[i], GRPC_ERROR_REF(error)); } calld->waiting_ops_count = 0; GRPC_ERROR_UNREF(error); } typedef struct { - grpc_transport_stream_op **ops; + grpc_transport_stream_op *ops; size_t nops; grpc_subchannel_call *call; } retry_ops_args; @@ -429,7 +429,7 @@ static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) { retry_ops_args *a = args; size_t i; for (i = 0; i < a->nops; i++) { - grpc_subchannel_call_process_op(exec_ctx, a->call, a->ops[i]); + grpc_subchannel_call_process_op(exec_ctx, a->call, &a->ops[i]); } GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops"); gpr_free(a->ops); @@ -437,10 +437,6 @@ static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) { } static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) { - if (calld->waiting_ops_count == 0) { - return; - } - retry_ops_args *a = gpr_malloc(sizeof(*a)); a->ops = calld->waiting_ops; a->nops = calld->waiting_ops_count; diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c index 2c4364b259..df35904b85 100644 --- a/src/core/ext/client_config/subchannel.c +++ b/src/core/ext/client_config/subchannel.c @@ -504,13 +504,14 @@ static void connected_subchannel_state_op(grpc_exec_ctx *exec_ctx, grpc_pollset_set *interested_parties, grpc_connectivity_state *state, grpc_closure *closure) { - grpc_transport_op *op = grpc_make_transport_op(NULL); + grpc_transport_op op; grpc_channel_element *elem; - op->connectivity_state = state; - op->on_connectivity_state_change = closure; - op->bind_pollset_set = interested_parties; + memset(&op, 0, sizeof(op)); + op.connectivity_state = state; + op.on_connectivity_state_change = closure; + op.bind_pollset_set = interested_parties; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); - elem->filter->start_transport_op(exec_ctx, elem, op); + elem->filter->start_transport_op(exec_ctx, elem, &op); } void grpc_connected_subchannel_notify_on_state_change( @@ -524,11 +525,12 @@ void grpc_connected_subchannel_notify_on_state_change( void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, grpc_closure *closure) { - grpc_transport_op *op = grpc_make_transport_op(NULL); + grpc_transport_op op; grpc_channel_element *elem; - op->send_ping = closure; + memset(&op, 0, sizeof(op)); + op.send_ping = closure; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); - elem->filter->start_transport_op(exec_ctx, elem, op); + elem->filter->start_transport_op(exec_ctx, elem, &op); } static void publish_transport_locked(grpc_exec_ctx *exec_ctx, diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 53da0e5d70..00999e3b94 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -89,20 +89,13 @@ static const grpc_transport_vtable vtable; static void writing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void reading_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void parsing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); -static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error); -static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error); -static void initiate_writing_locked(grpc_exec_ctx *exec_ctx, void *t, - grpc_error *error); -static void initiate_read_flush_locked(grpc_exec_ctx *exec_ctx, void *t, - grpc_error *error); -static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *t, - grpc_error *error); +static void initiate_writing(grpc_exec_ctx *exec_ctx, void *t, + grpc_error *error); static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, grpc_error *error); + grpc_chttp2_transport *t, grpc_error *error, + const char *reason); /** Set a transport level setting, and push it to our peer */ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, @@ -112,6 +105,11 @@ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error); +/** Perform a transport_op */ +static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, void *transport_op); + /** Cancel a stream: coming from the transport API */ static void cancel_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, @@ -123,10 +121,22 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_global *stream_global, grpc_error *error); +/** Add endpoint from this transport to pollset */ +static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_ignored, void *pollset); +static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_ignored, + void *pollset_set); + /** Start new streams that have been created if we can */ static void maybe_start_some_streams( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global); +static void finish_global_actions(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t); + static void connectivity_state_set( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_connectivity_state state, grpc_error *error, const char *reason); @@ -139,16 +149,14 @@ static void incoming_byte_stream_update_flow_control( grpc_chttp2_stream_global *stream_global, size_t max_size_hint, size_t have_already); static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, - void *byte_stream, - grpc_error *error_ignored); + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, + void *byte_stream); static void fail_pending_writes(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global, grpc_error *error); -static void set_write_state(grpc_chttp2_transport *t, - grpc_chttp2_write_state state, const char *reason); - /******************************************************************************* * CONSTRUCTION/DESTRUCTION/REFCOUNTING */ @@ -157,7 +165,9 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { size_t i; - grpc_endpoint_destroy(exec_ctx, t->ep); + gpr_mu_lock(&t->executor.mu); + + GPR_ASSERT(t->ep == NULL); gpr_slice_buffer_destroy(&t->global.qbuf); @@ -181,7 +191,8 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_map_destroy(&t->new_stream_map); grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker); - grpc_combiner_destroy(exec_ctx, t->executor.combiner); + gpr_mu_unlock(&t->executor.mu); + gpr_mu_destroy(&t->executor.mu); /* callback remaining pings: they're not allowed to call into the transpot, and maybe they hold resources that need to be freed */ @@ -239,13 +250,12 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, memset(t, 0, sizeof(*t)); t->base.vtable = &vtable; - t->executor.write_state = GRPC_CHTTP2_WRITES_CORKED; t->ep = ep; - /* one ref is for destroy */ - gpr_ref_init(&t->refs, 1); + /* one ref is for destroy, the other for when ep becomes NULL */ + gpr_ref_init(&t->refs, 2); /* ref is dropped at transport close() */ gpr_ref_init(&t->shutdown_ep_refs, 1); - t->executor.combiner = grpc_combiner_create(grpc_endpoint_get_workqueue(ep)); + gpr_mu_init(&t->executor.mu); t->peer_string = grpc_endpoint_get_peer(ep); t->endpoint_reading = 1; t->global.next_stream_id = is_client ? 1 : 2; @@ -271,22 +281,23 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor); grpc_closure_init(&t->writing_action, writing_action, t); grpc_closure_init(&t->reading_action, reading_action, t); - grpc_closure_init(&t->reading_action_locked, reading_action_locked, t); grpc_closure_init(&t->parsing_action, parsing_action, t); - grpc_closure_init(&t->post_parse_locked, post_parse_locked, t); - grpc_closure_init(&t->initiate_writing, initiate_writing_locked, t); - grpc_closure_init(&t->terminate_writing, terminate_writing_with_lock, t); - grpc_closure_init(&t->initiate_read_flush_locked, initiate_read_flush_locked, - t); - grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, - &t->writing); + grpc_closure_init(&t->initiate_writing, initiate_writing, t); gpr_slice_buffer_init(&t->parsing.qbuf); grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser); + grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, + &t->writing); gpr_slice_buffer_init(&t->read_buffer); + if (is_client) { + gpr_slice_buffer_add( + &t->global.qbuf, + gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)); + grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "initial_write"); + } /* 8 is a random stab in the dark as to a good initial size: it's small enough that it shouldn't waste memory for infrequently used connections, yet large enough that the exponential growth should happen nicely when it's @@ -309,13 +320,6 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, t->global.force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; t->global.sent_local_settings = 0; - if (is_client) { - gpr_slice_buffer_add( - &t->writing.outbuf, - gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)); - grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "initial_write"); - } - /* configure http2 the way we like it */ if (is_client) { push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); @@ -420,39 +424,47 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, } } } - - set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "uncork"); - grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "init"); } -static void destroy_transport_locked(grpc_exec_ctx *exec_ctx, void *tp, - grpc_error *error) { - grpc_chttp2_transport *t = tp; +static void destroy_transport_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_ignored, + void *arg_ignored) { t->destroying = 1; drop_connection(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed")); - UNREF_TRANSPORT(exec_ctx, t, "destroy"); } static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - grpc_combiner_execute(exec_ctx, t->executor.combiner, - grpc_closure_create(destroy_transport_locked, t), - GRPC_ERROR_NONE); + grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, destroy_transport_locked, + NULL, 0); + UNREF_TRANSPORT(exec_ctx, t, "destroy"); } /** block grpc_endpoint_shutdown being called until a paired allow_endpoint_shutdown is made */ static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) { + GPR_ASSERT(t->ep); gpr_ref(&t->shutdown_ep_refs); } static void allow_endpoint_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { if (gpr_unref(&t->shutdown_ep_refs)) { - grpc_endpoint_shutdown(exec_ctx, t->ep); + if (t->ep) { + grpc_endpoint_shutdown(exec_ctx, t->ep); + } } } +static void destroy_endpoint(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t) { + grpc_endpoint_destroy(exec_ctx, t->ep); + t->ep = NULL; + /* safe because we'll still have the ref for write */ + UNREF_TRANSPORT(exec_ctx, t, "disconnect"); +} + static void close_transport_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { @@ -463,7 +475,9 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx, t->closed = 1; connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), "close_transport"); - allow_endpoint_shutdown_locked(exec_ctx, t); + if (t->ep) { + allow_endpoint_shutdown_locked(exec_ctx, t); + } /* flush writable stream list to avoid dangling references */ grpc_chttp2_stream_global *stream_global; @@ -497,23 +511,21 @@ void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, } #endif -static void finish_init_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, - grpc_error *error) { - grpc_chttp2_stream *s = sp; - grpc_chttp2_register_stream(s->t, s); - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "init"); +static void finish_init_stream_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, + void *arg_ignored) { + grpc_chttp2_register_stream(t, s); } static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_stream_refcount *refcount, const void *server_data) { - GPR_TIMER_BEGIN("init_stream", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; memset(s, 0, sizeof(*s)); - s->t = t; s->refcount = refcount; /* We reserve one 'active stream' that's dropped when the stream is read-closed. The others are for incoming_byte_streams that are actively @@ -548,21 +560,16 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, s->global.in_stream_map = true; } - grpc_closure_init(&s->init_stream, finish_init_stream_locked, s); - GRPC_CHTTP2_STREAM_REF(&s->global, "init"); - grpc_combiner_execute(exec_ctx, t->executor.combiner, &s->init_stream, - GRPC_ERROR_NONE); - - GPR_TIMER_END("init_stream", 0); + grpc_chttp2_run_with_global_lock(exec_ctx, t, s, finish_init_stream_locked, + NULL, 0); return 0; } -static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, - grpc_error *error) { +static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, void *arg) { grpc_byte_stream *bs; - grpc_chttp2_stream *s = sp; - grpc_chttp2_transport *t = s->t; GPR_TIMER_BEGIN("destroy_stream", 0); @@ -581,7 +588,7 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, while ( (bs = grpc_chttp2_incoming_frame_queue_pop(&s->global.incoming_frames))) { - incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); + incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); } grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global, @@ -618,20 +625,16 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, GPR_TIMER_END("destroy_stream", 0); - gpr_free(s->destroy_stream_arg); + gpr_free(arg); } static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, void *and_free_memory) { - GPR_TIMER_BEGIN("destroy_stream", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - s->destroy_stream_arg = and_free_memory; - grpc_closure_init(&s->destroy_stream, destroy_stream_locked, s); - grpc_combiner_execute(exec_ctx, t->executor.combiner, &s->destroy_stream, - GRPC_ERROR_NONE); - GPR_TIMER_END("destroy_stream", 0); + grpc_chttp2_run_with_global_lock(exec_ctx, t, s, destroy_stream_locked, + and_free_memory, 0); } grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream( @@ -662,10 +665,12 @@ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream( static const char *write_state_name(grpc_chttp2_write_state state) { switch (state) { - case GRPC_CHTTP2_WRITES_CORKED: - return "CORKED"; case GRPC_CHTTP2_WRITING_INACTIVE: return "INACTIVE"; + case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: + return "REQUESTED[p=0]"; + case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: + return "REQUESTED[p=1]"; case GRPC_CHTTP2_WRITE_SCHEDULED: return "SCHEDULED"; case GRPC_CHTTP2_WRITING: @@ -688,18 +693,120 @@ static void set_write_state(grpc_chttp2_transport *t, t->executor.write_state = state; } -static void initiate_writing_locked(grpc_exec_ctx *exec_ctx, void *tp, - grpc_error *error) { - grpc_chttp2_transport *t = tp; - GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED); - start_writing(exec_ctx, t); +static void finish_global_actions(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t) { + grpc_chttp2_executor_action_header *hdr; + grpc_chttp2_executor_action_header *next; + + GPR_TIMER_BEGIN("finish_global_actions", 0); + + for (;;) { + check_read_ops(exec_ctx, &t->global); + + gpr_mu_lock(&t->executor.mu); + if (t->executor.pending_actions_head != NULL) { + hdr = t->executor.pending_actions_head; + t->executor.pending_actions_head = t->executor.pending_actions_tail = + NULL; + gpr_mu_unlock(&t->executor.mu); + while (hdr != NULL) { + GPR_TIMER_BEGIN("chttp2:locked_action", 0); + hdr->action(exec_ctx, t, hdr->stream, hdr->arg); + GPR_TIMER_END("chttp2:locked_action", 0); + next = hdr->next; + gpr_free(hdr); + UNREF_TRANSPORT(exec_ctx, t, "pending_action"); + hdr = next; + } + continue; + } else { + t->executor.global_active = false; + switch (t->executor.write_state) { + case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: + set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "unlocking"); + REF_TRANSPORT(t, "initiate_writing"); + gpr_mu_unlock(&t->executor.mu); + grpc_exec_ctx_sched( + exec_ctx, &t->initiate_writing, GRPC_ERROR_NONE, + t->ep != NULL ? grpc_endpoint_get_workqueue(t->ep) : NULL); + break; + case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: + start_writing(exec_ctx, t); + gpr_mu_unlock(&t->executor.mu); + break; + case GRPC_CHTTP2_WRITING_INACTIVE: + case GRPC_CHTTP2_WRITING: + case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: + case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: + case GRPC_CHTTP2_WRITE_SCHEDULED: + gpr_mu_unlock(&t->executor.mu); + break; + } + } + break; + } + + GPR_TIMER_END("finish_global_actions", 0); } -static void initiate_read_flush_locked(grpc_exec_ctx *exec_ctx, void *tp, - grpc_error *error) { - grpc_chttp2_transport *t = tp; - t->executor.check_read_ops_scheduled = false; - check_read_ops(exec_ctx, &t->global); +void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *optional_stream, + grpc_chttp2_locked_action action, + void *arg, size_t sizeof_arg) { + grpc_chttp2_executor_action_header *hdr; + + GPR_TIMER_BEGIN("grpc_chttp2_run_with_global_lock", 0); + + REF_TRANSPORT(t, "run_global"); + gpr_mu_lock(&t->executor.mu); + + for (;;) { + if (!t->executor.global_active) { + t->executor.global_active = 1; + gpr_mu_unlock(&t->executor.mu); + + GPR_TIMER_BEGIN("chttp2:locked_action", 0); + action(exec_ctx, t, optional_stream, arg); + GPR_TIMER_END("chttp2:locked_action", 0); + + finish_global_actions(exec_ctx, t); + } else { + gpr_mu_unlock(&t->executor.mu); + + hdr = gpr_malloc(sizeof(*hdr) + sizeof_arg); + hdr->stream = optional_stream; + hdr->action = action; + if (sizeof_arg == 0) { + hdr->arg = arg; + } else { + hdr->arg = hdr + 1; + memcpy(hdr->arg, arg, sizeof_arg); + } + + gpr_mu_lock(&t->executor.mu); + if (!t->executor.global_active) { + /* global lock was released while allocating memory: release & retry */ + gpr_free(hdr); + continue; + } + hdr->next = NULL; + if (t->executor.pending_actions_head != NULL) { + t->executor.pending_actions_tail = + t->executor.pending_actions_tail->next = hdr; + } else { + t->executor.pending_actions_tail = t->executor.pending_actions_head = + hdr; + } + REF_TRANSPORT(t, "pending_action"); + gpr_mu_unlock(&t->executor.mu); + } + break; + } + + UNREF_TRANSPORT(exec_ctx, t, "run_global"); + + GPR_TIMER_END("grpc_chttp2_run_with_global_lock", 0); } /******************************************************************************* @@ -709,12 +816,11 @@ static void initiate_read_flush_locked(grpc_exec_ctx *exec_ctx, void *tp, void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, bool covered_by_poller, const char *reason) { - GPR_TIMER_BEGIN("grpc_chttp2_initiate_write", 0); - /* Perform state checks, and transition to a scheduled state if appropriate. - If we are inactive, schedule a write chain to begin once the transport - combiner finishes any executions in its current batch (which may be - scheduled AFTER this code executes). The write chain will: + Each time we finish the global lock execution, we check if we need to + write. If we do: + - (if there is a poller surrounding the write) schedule + initiate_writing, which locks and calls initiate_writing_locked to... - call start_writing, which verifies (under the global lock) that there are things that need to be written by calling grpc_chttp2_unlocking_check_writes, and if so schedules writing_action @@ -724,28 +830,31 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, to do *another* write immediately, and if so loops back to start_writing. - Current problems: + Current problems: - too much lock entry/exiting - the writing thread can become stuck indefinitely (punt through the workqueue periodically to fix) */ grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global); switch (t->executor.write_state) { - case GRPC_CHTTP2_WRITES_CORKED: - break; case GRPC_CHTTP2_WRITING_INACTIVE: - set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, reason); - REF_TRANSPORT(t, "writing"); - grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, - &t->initiate_writing, GRPC_ERROR_NONE, - covered_by_poller); + set_write_state(t, covered_by_poller + ? GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER + : GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, + reason); break; - case GRPC_CHTTP2_WRITE_SCHEDULED: + case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: + /* nothing to do: write already requested */ + break; + case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: if (covered_by_poller) { /* upgrade to note poller is available to cover the write */ - grpc_combiner_force_async_finally(t->executor.combiner); + set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, reason); } break; + case GRPC_CHTTP2_WRITE_SCHEDULED: + /* nothing to do: write already scheduled */ + break; case GRPC_CHTTP2_WRITING: set_write_state(t, covered_by_poller ? GRPC_CHTTP2_WRITING_STALE_WITH_POLLER @@ -762,15 +871,15 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, } break; } - GPR_TIMER_END("grpc_chttp2_initiate_write", 0); } static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { - GPR_TIMER_BEGIN("start_writing", 0); - GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED); + GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED || + t->executor.write_state == GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER); if (!t->closed && grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) { set_write_state(t, GRPC_CHTTP2_WRITING, "start_writing"); + REF_TRANSPORT(t, "writing"); prevent_endpoint_shutdown(t); grpc_exec_ctx_sched(exec_ctx, &t->writing_action, GRPC_ERROR_NONE, NULL); } else { @@ -781,10 +890,25 @@ static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "start_writing:nothing_to_write"); } - end_waiting_for_write(exec_ctx, t, GRPC_ERROR_NONE); - UNREF_TRANSPORT(exec_ctx, t, "writing"); + end_waiting_for_write(exec_ctx, t, GRPC_ERROR_NONE, "Nothing to write"); + if (t->ep && !t->endpoint_reading) { + destroy_endpoint(exec_ctx, t); + } } - GPR_TIMER_END("start_writing", 0); +} + +static void initiate_writing_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, + void *arg_ignored) { + start_writing(exec_ctx, t); + UNREF_TRANSPORT(exec_ctx, t, "initiate_writing"); +} + +static void initiate_writing(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_chttp2_run_with_global_lock(exec_ctx, arg, NULL, initiate_writing_locked, + NULL, 0); } void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx, @@ -818,10 +942,15 @@ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, /* error may be GRPC_ERROR_NONE if there is no error allocated yet. In that case, use "reason" as the text for a new error. */ static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, grpc_error *error) { + grpc_chttp2_transport *t, grpc_error *error, + const char *reason) { grpc_chttp2_stream_global *stream_global; while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global, &stream_global)) { + if (error == GRPC_ERROR_NONE && reason != NULL) { + /* create error object. */ + error = GRPC_ERROR_CREATE(reason); + } fail_pending_writes(exec_ctx, &t->global, stream_global, GRPC_ERROR_REF(error)); GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes"); @@ -829,10 +958,12 @@ static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, GRPC_ERROR_UNREF(error); } -static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *tp, - grpc_error *error) { - GPR_TIMER_BEGIN("terminate_writing_with_lock", 0); - grpc_chttp2_transport *t = tp; +static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_ignored, + void *a) { + grpc_error *error = a; + allow_endpoint_shutdown_locked(exec_ctx, t); if (error != GRPC_ERROR_NONE) { @@ -841,46 +972,39 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *tp, grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing); - end_waiting_for_write(exec_ctx, t, GRPC_ERROR_REF(error)); + end_waiting_for_write(exec_ctx, t, error, NULL); switch (t->executor.write_state) { - case GRPC_CHTTP2_WRITES_CORKED: case GRPC_CHTTP2_WRITING_INACTIVE: + case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: + case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: case GRPC_CHTTP2_WRITE_SCHEDULED: GPR_UNREACHABLE_CODE(break); case GRPC_CHTTP2_WRITING: - GPR_TIMER_MARK("state=writing", 0); set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "terminate_writing"); break; case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: - GPR_TIMER_MARK("state=writing_stale_with_poller", 0); - set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "terminate_writing"); - REF_TRANSPORT(t, "writing"); - grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, - &t->initiate_writing, GRPC_ERROR_NONE, - true); + set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, + "terminate_writing"); break; case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: - GPR_TIMER_MARK("state=writing_stale_no_poller", 0); - set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "terminate_writing"); - REF_TRANSPORT(t, "writing"); - grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, - &t->initiate_writing, GRPC_ERROR_NONE, - false); + set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, + "terminate_writing"); break; } + if (t->ep && !t->endpoint_reading) { + destroy_endpoint(exec_ctx, t); + } + UNREF_TRANSPORT(exec_ctx, t, "writing"); - GPR_TIMER_END("terminate_writing_with_lock", 0); } void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx, void *transport_writing, grpc_error *error) { - GPR_TIMER_BEGIN("grpc_chttp2_terminate_writing", 0); grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); - grpc_combiner_execute(exec_ctx, t->executor.combiner, &t->terminate_writing, - GRPC_ERROR_REF(error)); - GPR_TIMER_END("grpc_chttp2_terminate_writing", 0); + grpc_chttp2_run_with_global_lock( + exec_ctx, t, NULL, terminate_writing_with_lock, GRPC_ERROR_REF(error), 0); } static void writing_action(grpc_exec_ctx *exec_ctx, void *gt, @@ -1024,22 +1148,15 @@ static int contains_non_ok_status( static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} -static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, - grpc_error *error_ignored) { +static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, void *stream_op) { GPR_TIMER_BEGIN("perform_stream_op_locked", 0); grpc_transport_stream_op *op = stream_op; - grpc_chttp2_transport *t = op->transport_private.args[0]; - grpc_chttp2_stream *s = op->transport_private.args[1]; grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_stream_global *stream_global = &s->global; - if (grpc_http_trace) { - char *str = grpc_transport_stream_op_string(op); - gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s", str); - gpr_free(str); - } - grpc_closure *on_complete = op->on_complete; if (on_complete == NULL) { on_complete = grpc_closure_create(do_nothing, NULL); @@ -1094,8 +1211,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, } else { if (contains_non_ok_status(transport_global, op->send_initial_metadata)) { stream_global->seen_error = true; - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (!stream_global->write_closed) { if (transport_global->is_client) { @@ -1162,8 +1278,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, if (contains_non_ok_status(transport_global, op->send_trailing_metadata)) { stream_global->seen_error = true; - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (stream_global->write_closed) { stream_global->send_trailing_metadata = NULL; @@ -1188,8 +1303,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, stream_global->recv_initial_metadata_ready = op->recv_initial_metadata_ready; stream_global->recv_initial_metadata = op->recv_initial_metadata; - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (op->recv_message != NULL) { @@ -1203,8 +1317,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, exec_ctx, transport_global, stream_global, transport_global->stream_lookahead, 0); } - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (op->recv_trailing_metadata != NULL) { @@ -1213,30 +1326,21 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, add_closure_barrier(on_complete); stream_global->recv_trailing_metadata = op->recv_trailing_metadata; stream_global->final_metadata_requested = true; - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } grpc_chttp2_complete_closure_step(exec_ctx, transport_global, stream_global, &on_complete, GRPC_ERROR_NONE); GPR_TIMER_END("perform_stream_op_locked", 0); - GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "perform_stream_op"); } static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_transport_stream_op *op) { - GPR_TIMER_BEGIN("perform_stream_op", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - grpc_closure_init(&op->transport_private.closure, perform_stream_op_locked, - op); - op->transport_private.args[0] = gt; - op->transport_private.args[1] = gs; - GRPC_CHTTP2_STREAM_REF(&s->global, "perform_stream_op"); - grpc_combiner_execute(exec_ctx, t->executor.combiner, - &op->transport_private.closure, GRPC_ERROR_NONE); - GPR_TIMER_END("perform_stream_op", 0); + grpc_chttp2_run_with_global_lock(exec_ctx, t, s, perform_stream_op_locked, op, + sizeof(*op)); } static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, @@ -1258,20 +1362,13 @@ static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_initiate_write(exec_ctx, &t->global, true, "send_ping"); } -typedef struct ack_ping_args { - grpc_closure closure; - grpc_chttp2_transport *t; - uint8_t opaque_8bytes[8]; -} ack_ping_args; - -static void ack_ping_locked(grpc_exec_ctx *exec_ctx, void *a, - grpc_error *error_ignored) { - ack_ping_args *args = a; +static void ack_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, + grpc_chttp2_stream *s, void *opaque_8bytes) { grpc_chttp2_outstanding_ping *ping; - grpc_chttp2_transport_global *transport_global = &args->t->global; + grpc_chttp2_transport_global *transport_global = &t->global; for (ping = transport_global->pings.next; ping != &transport_global->pings; ping = ping->next) { - if (0 == memcmp(args->opaque_8bytes, ping->id, 8)) { + if (0 == memcmp(opaque_8bytes, ping->id, 8)) { grpc_exec_ctx_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE, NULL); ping->next->prev = ping->prev; ping->prev->next = ping->next; @@ -1279,27 +1376,21 @@ static void ack_ping_locked(grpc_exec_ctx *exec_ctx, void *a, break; } } - UNREF_TRANSPORT(exec_ctx, args->t, "ack_ping"); - gpr_free(args); } void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, const uint8_t *opaque_8bytes) { - ack_ping_args *args = gpr_malloc(sizeof(*args)); - args->t = TRANSPORT_FROM_PARSING(transport_parsing); - memcpy(args->opaque_8bytes, opaque_8bytes, sizeof(args->opaque_8bytes)); - grpc_closure_init(&args->closure, ack_ping_locked, args); - REF_TRANSPORT(args->t, "ack_ping"); - grpc_combiner_execute(exec_ctx, args->t->executor.combiner, &args->closure, - GRPC_ERROR_NONE); + grpc_chttp2_run_with_global_lock( + exec_ctx, TRANSPORT_FROM_PARSING(transport_parsing), NULL, + ack_ping_locked, (void *)opaque_8bytes, 8); } static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, - void *stream_op, - grpc_error *error_ignored) { + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, + void *stream_op) { grpc_transport_op *op = stream_op; - grpc_chttp2_transport *t = op->transport_private.args[0]; grpc_error *close_transport = op->disconnect_with_error; /* If there's a set_accept_stream ensure that we're not parsing @@ -1311,6 +1402,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, return; } + grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); + if (op->on_connectivity_state_change != NULL) { grpc_connectivity_state_notify_on_state_change( exec_ctx, &t->channel_callback.state_tracker, op->connectivity_state, @@ -1336,11 +1429,11 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, } if (op->bind_pollset) { - grpc_endpoint_add_to_pollset(exec_ctx, t->ep, op->bind_pollset); + add_to_pollset_locked(exec_ctx, t, NULL, op->bind_pollset); } if (op->bind_pollset_set) { - grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, op->bind_pollset_set); + add_to_pollset_set_locked(exec_ctx, t, NULL, op->bind_pollset_set); } if (op->send_ping) { @@ -1350,21 +1443,13 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, if (close_transport != GRPC_ERROR_NONE) { close_transport_locked(exec_ctx, t, close_transport); } - - grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); - - UNREF_TRANSPORT(exec_ctx, t, "transport_op"); } 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; - op->transport_private.args[0] = gt; - grpc_closure_init(&op->transport_private.closure, perform_transport_op_locked, - op); - REF_TRANSPORT(t, "transport_op"); - grpc_combiner_execute(exec_ctx, t->executor.combiner, - &op->transport_private.closure, GRPC_ERROR_NONE); + grpc_chttp2_run_with_global_lock( + exec_ctx, t, NULL, perform_transport_op_locked, op, sizeof(*op)); } /******************************************************************************* @@ -1373,7 +1458,6 @@ static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, static void check_read_ops(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global) { - GPR_TIMER_BEGIN("check_read_ops", 0); grpc_chttp2_stream_global *stream_global; grpc_byte_stream *bs; while ( @@ -1383,7 +1467,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, if (stream_global->seen_error) { while ((bs = grpc_chttp2_incoming_frame_queue_pop( &stream_global->incoming_frames)) != NULL) { - incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); + incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); } if (stream_global->exceeded_metadata_size) { cancel_from_api( @@ -1406,7 +1490,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, stream_global->seen_error && (bs = grpc_chttp2_incoming_frame_queue_pop( &stream_global->incoming_frames)) != NULL) { - incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); + incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); } if (stream_global->incoming_frames.head != NULL) { *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop( @@ -1427,7 +1511,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, if (stream_global->seen_error) { while ((bs = grpc_chttp2_incoming_frame_queue_pop( &stream_global->incoming_frames)) != NULL) { - incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); + incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); } if (stream_global->exceeded_metadata_size) { cancel_from_api( @@ -1448,7 +1532,6 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, } } } - GPR_TIMER_END("check_read_ops", 0); } static void decrement_active_streams_locked( @@ -1456,8 +1539,7 @@ static void decrement_active_streams_locked( grpc_chttp2_stream_global *stream_global) { if ((stream_global->all_incoming_byte_streams_finished = gpr_unref(&stream_global->active_streams))) { - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } } @@ -1561,8 +1643,7 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx, } if (due_to_error != GRPC_ERROR_NONE && !stream_global->seen_error) { stream_global->seen_error = true; - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1, 1, due_to_error); @@ -1574,8 +1655,7 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_status_code status, gpr_slice *slice) { if (status != GRPC_STATUS_OK) { stream_global->seen_error = true; - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } /* stream_global->recv_trailing_metadata_finished gives us a last chance replacement: we've received trailing metadata, @@ -1599,8 +1679,7 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_mdstr_from_slice(gpr_slice_ref(*slice)))); } stream_global->published_trailing_metadata = true; - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (slice) { gpr_slice_unref(*slice); @@ -1660,8 +1739,7 @@ void grpc_chttp2_mark_stream_closed( GRPC_ERROR_UNREF(error); return; } - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); if (close_reads && !stream_global->read_closed) { stream_global->read_closed_error = GRPC_ERROR_REF(error); stream_global->read_closed = true; @@ -1842,10 +1920,6 @@ static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { - if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { - error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, - GRPC_STATUS_UNAVAILABLE); - } close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error)); end_all_the_calls(exec_ctx, t, error); } @@ -1881,12 +1955,16 @@ static void update_global_window(void *args, uint32_t id, void *stream) { * INPUT PROCESSING - PARSING */ +static void reading_action_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, void *arg); static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); -static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error); -static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error); +static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, void *arg); +static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, void *arg); static void reading_action(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { @@ -1894,20 +1972,16 @@ static void reading_action(grpc_exec_ctx *exec_ctx, void *tp, reading_action_locked -> (parse_unlocked -> post_parse_locked)? -> post_reading_action_locked */ - GPR_TIMER_BEGIN("reading_action", 0); - grpc_chttp2_transport *t = tp; - grpc_combiner_execute(exec_ctx, t->executor.combiner, - &t->reading_action_locked, GRPC_ERROR_REF(error)); - GPR_TIMER_END("reading_action", 0); + grpc_chttp2_run_with_global_lock(exec_ctx, tp, NULL, reading_action_locked, + GRPC_ERROR_REF(error), 0); } -static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *tp, - grpc_error *error) { - GPR_TIMER_BEGIN("reading_action_locked", 0); - - grpc_chttp2_transport *t = tp; +static void reading_action_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, void *arg) { grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_transport_parsing *transport_parsing = &t->parsing; + grpc_error *error = arg; GPR_ASSERT(!t->executor.parsing_active); if (!t->closed) { @@ -1916,13 +1990,10 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map); grpc_chttp2_prepare_to_read(transport_global, transport_parsing); - grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, GRPC_ERROR_REF(error), - NULL); + grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, error, NULL); } else { - post_reading_action_locked(exec_ctx, t, error); + post_reading_action_locked(exec_ctx, t, s_unused, arg); } - - GPR_TIMER_END("reading_action_locked", 0); } static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, @@ -1974,15 +2045,13 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) { GRPC_ERROR_UNREF(errors[i]); } - grpc_combiner_execute(exec_ctx, t->executor.combiner, &t->post_parse_locked, - err); GPR_TIMER_END("reading_action.parse", 0); + grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked, err, + 0); } -static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - GPR_TIMER_BEGIN("post_parse_locked", 0); - grpc_chttp2_transport *t = arg; +static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, void *arg) { grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_transport_parsing *transport_parsing = &t->parsing; /* copy parsing qbuf to global qbuf */ @@ -2008,7 +2077,7 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, if (t->post_parsing_op) { grpc_transport_op *op = t->post_parsing_op; t->post_parsing_op = NULL; - perform_transport_op_locked(exec_ctx, op, GRPC_ERROR_NONE); + perform_transport_op_locked(exec_ctx, t, NULL, op); gpr_free(op); } /* if a stream is in the stream map, and gets cancelled, we need to @@ -2025,32 +2094,39 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2"); } - post_reading_action_locked(exec_ctx, t, error); - GPR_TIMER_END("post_parse_locked", 0); + post_reading_action_locked(exec_ctx, t, s_unused, arg); } -static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - GPR_TIMER_BEGIN("post_reading_action_locked", 0); - grpc_chttp2_transport *t = arg; +static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, + void *arg) { + grpc_error *error = arg; bool keep_reading = false; - GRPC_ERROR_REF(error); if (error == GRPC_ERROR_NONE && t->closed) { error = GRPC_ERROR_CREATE("Transport closed"); } if (error != GRPC_ERROR_NONE) { + if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { + error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_UNAVAILABLE); + } drop_connection(exec_ctx, t, GRPC_ERROR_REF(error)); t->endpoint_reading = 0; if (grpc_http_write_state_trace) { gpr_log(GPR_DEBUG, "R:%p -> 0 ws=%s", t, write_state_name(t->executor.write_state)); } + if (t->executor.write_state == GRPC_CHTTP2_WRITING_INACTIVE && t->ep) { + destroy_endpoint(exec_ctx, t); + } } else if (!t->closed) { keep_reading = true; REF_TRANSPORT(t, "keep_reading"); prevent_endpoint_shutdown(t); } gpr_slice_buffer_reset_and_unref(&t->read_buffer); + GRPC_ERROR_UNREF(error); if (keep_reading) { grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->reading_action); @@ -2059,9 +2135,6 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, } else { UNREF_TRANSPORT(exec_ctx, t, "reading_action"); } - GRPC_ERROR_UNREF(error); - - GPR_TIMER_END("post_reading_action_locked", 0); } /******************************************************************************* @@ -2083,16 +2156,36 @@ static void connectivity_state_set( * POLLSET STUFF */ +static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, void *pollset) { + if (t->ep) { + grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset); + } +} + +static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s_unused, + void *pollset_set) { + if (t->ep) { + grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set); + } +} + static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_pollset *pollset) { - grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset); + /* TODO(ctiller): keep pollset alive */ + grpc_chttp2_run_with_global_lock(exec_ctx, (grpc_chttp2_transport *)gt, + (grpc_chttp2_stream *)gs, + add_to_pollset_locked, pollset, 0); } static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_pollset_set *pollset_set) { - grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set); + grpc_chttp2_run_with_global_lock(exec_ctx, (grpc_chttp2_transport *)gt, + (grpc_chttp2_stream *)gs, + add_to_pollset_set_locked, pollset_set, 0); } /******************************************************************************* @@ -2104,7 +2197,6 @@ static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx, if (gpr_unref(&bs->refs)) { GRPC_ERROR_UNREF(bs->error); gpr_slice_buffer_destroy(&bs->slices); - gpr_mu_destroy(&bs->slice_mu); gpr_free(bs); } } @@ -2150,34 +2242,38 @@ static void incoming_byte_stream_update_flow_control( } } +typedef struct { + grpc_chttp2_incoming_byte_stream *byte_stream; + gpr_slice *slice; + size_t max_size_hint; + grpc_closure *on_complete; +} incoming_byte_stream_next_arg; + static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx, - void *argp, - grpc_error *error_ignored) { - grpc_chttp2_incoming_byte_stream *bs = argp; + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, + void *argp) { + incoming_byte_stream_next_arg *arg = argp; + grpc_chttp2_incoming_byte_stream *bs = + (grpc_chttp2_incoming_byte_stream *)arg->byte_stream; grpc_chttp2_transport_global *transport_global = &bs->transport->global; grpc_chttp2_stream_global *stream_global = &bs->stream->global; if (bs->is_tail) { - gpr_mu_lock(&bs->slice_mu); - size_t cur_length = bs->slices.length; - gpr_mu_unlock(&bs->slice_mu); - incoming_byte_stream_update_flow_control( - exec_ctx, transport_global, stream_global, - bs->next_action.max_size_hint, cur_length); - } - gpr_mu_lock(&bs->slice_mu); + incoming_byte_stream_update_flow_control(exec_ctx, transport_global, + stream_global, arg->max_size_hint, + bs->slices.length); + } if (bs->slices.count > 0) { - *bs->next_action.slice = gpr_slice_buffer_take_first(&bs->slices); - grpc_exec_ctx_sched(exec_ctx, bs->next_action.on_complete, GRPC_ERROR_NONE, - NULL); + *arg->slice = gpr_slice_buffer_take_first(&bs->slices); + grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_NONE, NULL); } else if (bs->error != GRPC_ERROR_NONE) { - grpc_exec_ctx_sched(exec_ctx, bs->next_action.on_complete, - GRPC_ERROR_REF(bs->error), NULL); + grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_REF(bs->error), + NULL); } else { - bs->on_next = bs->next_action.on_complete; - bs->next = bs->next_action.slice; + bs->on_next = arg->on_complete; + bs->next = arg->slice; } - gpr_mu_unlock(&bs->slice_mu); incoming_byte_stream_unref(exec_ctx, bs); } @@ -2185,18 +2281,13 @@ static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream, gpr_slice *slice, size_t max_size_hint, grpc_closure *on_complete) { - GPR_TIMER_BEGIN("incoming_byte_stream_next", 0); grpc_chttp2_incoming_byte_stream *bs = (grpc_chttp2_incoming_byte_stream *)byte_stream; + incoming_byte_stream_next_arg arg = {bs, slice, max_size_hint, on_complete}; gpr_ref(&bs->refs); - bs->next_action.slice = slice; - bs->next_action.max_size_hint = max_size_hint; - bs->next_action.on_complete = on_complete; - grpc_closure_init(&bs->next_action.closure, incoming_byte_stream_next_locked, - bs); - grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, - &bs->next_action.closure, GRPC_ERROR_NONE); - GPR_TIMER_END("incoming_byte_stream_next", 0); + grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, + incoming_byte_stream_next_locked, &arg, + sizeof(arg)); return 0; } @@ -2204,8 +2295,9 @@ static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream); static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, - void *byte_stream, - grpc_error *error_ignored) { + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, + void *byte_stream) { grpc_chttp2_incoming_byte_stream *bs = byte_stream; GPR_ASSERT(bs->base.destroy == incoming_byte_stream_destroy); decrement_active_streams_locked(exec_ctx, &bs->transport->global, @@ -2215,14 +2307,10 @@ static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream) { - GPR_TIMER_BEGIN("incoming_byte_stream_destroy", 0); grpc_chttp2_incoming_byte_stream *bs = (grpc_chttp2_incoming_byte_stream *)byte_stream; - grpc_closure_init(&bs->destroy_action, incoming_byte_stream_destroy_locked, - bs); - grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, - &bs->destroy_action, GRPC_ERROR_NONE); - GPR_TIMER_END("incoming_byte_stream_destroy", 0); + grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, + incoming_byte_stream_destroy_locked, bs, 0); } typedef struct { @@ -2230,45 +2318,90 @@ typedef struct { gpr_slice slice; } incoming_byte_stream_push_arg; -void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx, - grpc_chttp2_incoming_byte_stream *bs, - gpr_slice slice) { - gpr_mu_lock(&bs->slice_mu); +static void incoming_byte_stream_push_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, + void *argp) { + incoming_byte_stream_push_arg *arg = argp; + grpc_chttp2_incoming_byte_stream *bs = arg->byte_stream; if (bs->on_next != NULL) { - *bs->next = slice; + *bs->next = arg->slice; grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_NONE, NULL); bs->on_next = NULL; } else { - gpr_slice_buffer_add(&bs->slices, slice); + gpr_slice_buffer_add(&bs->slices, arg->slice); } - gpr_mu_unlock(&bs->slice_mu); + incoming_byte_stream_unref(exec_ctx, bs); } -static void incoming_byte_stream_finished_locked(grpc_exec_ctx *exec_ctx, - void *bsp, grpc_error *error) { - grpc_chttp2_incoming_byte_stream *bs = bsp; - if (error != GRPC_ERROR_NONE) { - grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error), NULL); - bs->on_next = NULL; - GRPC_ERROR_UNREF(bs->error); - bs->error = error; - } +void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx, + grpc_chttp2_incoming_byte_stream *bs, + gpr_slice slice) { + incoming_byte_stream_push_arg arg = {bs, slice}; + gpr_ref(&bs->refs); + grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, + incoming_byte_stream_push_locked, &arg, + sizeof(arg)); +} + +typedef struct { + grpc_chttp2_incoming_byte_stream *bs; + grpc_error *error; +} bs_fail_args; + +static bs_fail_args *make_bs_fail_args(grpc_chttp2_incoming_byte_stream *bs, + grpc_error *error) { + bs_fail_args *a = gpr_malloc(sizeof(*a)); + a->bs = bs; + a->error = error; + return a; +} + +static void incoming_byte_stream_finished_failed_locked( + grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, + void *argp) { + bs_fail_args *a = argp; + grpc_chttp2_incoming_byte_stream *bs = a->bs; + grpc_error *error = a->error; + gpr_free(a); + grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error), NULL); + bs->on_next = NULL; + GRPC_ERROR_UNREF(bs->error); + bs->error = error; + incoming_byte_stream_unref(exec_ctx, bs); +} + +static void incoming_byte_stream_finished_ok_locked(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, + void *argp) { + grpc_chttp2_incoming_byte_stream *bs = argp; incoming_byte_stream_unref(exec_ctx, bs); } void grpc_chttp2_incoming_byte_stream_finished( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, grpc_error *error, int from_parsing_thread) { - GPR_TIMER_BEGIN("grpc_chttp2_incoming_byte_stream_finished", 0); if (from_parsing_thread) { - grpc_closure_init(&bs->finished_action, - incoming_byte_stream_finished_locked, bs); - grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, - &bs->finished_action, GRPC_ERROR_REF(error)); + if (error == GRPC_ERROR_NONE) { + grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, + incoming_byte_stream_finished_ok_locked, + bs, 0); + } else { + grpc_chttp2_run_with_global_lock( + exec_ctx, bs->transport, bs->stream, + incoming_byte_stream_finished_failed_locked, + make_bs_fail_args(bs, error), 0); + } } else { - incoming_byte_stream_finished_locked(exec_ctx, bs, error); + if (error == GRPC_ERROR_NONE) { + incoming_byte_stream_finished_ok_locked(exec_ctx, bs->transport, + bs->stream, bs); + } else { + incoming_byte_stream_finished_failed_locked( + exec_ctx, bs->transport, bs->stream, make_bs_fail_args(bs, error)); + } } - GPR_TIMER_END("grpc_chttp2_incoming_byte_stream_finished", 0); } grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create( @@ -2281,7 +2414,6 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create( incoming_byte_stream->base.flags = flags; incoming_byte_stream->base.next = incoming_byte_stream_next; incoming_byte_stream->base.destroy = incoming_byte_stream_destroy; - gpr_mu_init(&incoming_byte_stream->slice_mu); gpr_ref_init(&incoming_byte_stream->refs, 2); incoming_byte_stream->next_message = NULL; incoming_byte_stream->transport = TRANSPORT_FROM_PARSING(transport_parsing); diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 04b788b702..d67c014e54 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -48,7 +48,6 @@ #include "src/core/ext/transport/chttp2/transport/hpack_parser.h" #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" #include "src/core/ext/transport/chttp2/transport/stream_map.h" -#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/transport_impl.h" @@ -162,20 +161,9 @@ struct grpc_chttp2_incoming_byte_stream { grpc_chttp2_transport *transport; grpc_chttp2_stream *stream; int is_tail; - - gpr_mu slice_mu; // protects slices, on_next gpr_slice_buffer slices; grpc_closure *on_next; gpr_slice *next; - - struct { - grpc_closure closure; - gpr_slice *slice; - size_t max_size_hint; - grpc_closure *on_complete; - } next_action; - grpc_closure destroy_action; - grpc_closure finished_action; }; typedef struct { @@ -308,11 +296,23 @@ struct grpc_chttp2_transport_parsing { int64_t outgoing_window; }; +typedef void (*grpc_chttp2_locked_action)(grpc_exec_ctx *ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s, void *arg); + +typedef struct grpc_chttp2_executor_action_header { + grpc_chttp2_stream *stream; + grpc_chttp2_locked_action action; + struct grpc_chttp2_executor_action_header *next; + void *arg; +} grpc_chttp2_executor_action_header; + typedef enum { - /** no writing activity allowed */ - GRPC_CHTTP2_WRITES_CORKED, /** no writing activity */ GRPC_CHTTP2_WRITING_INACTIVE, + /** write has been requested, but not scheduled yet */ + GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, + GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, /** write has been requested and scheduled against the workqueue */ GRPC_CHTTP2_WRITE_SCHEDULED, /** write has been initiated after being reaped from the workqueue */ @@ -333,7 +333,7 @@ struct grpc_chttp2_transport { gpr_refcount shutdown_ep_refs; struct { - grpc_combiner *combiner; + gpr_mu mu; /** is a thread currently in the global lock */ bool global_active; @@ -341,8 +341,9 @@ struct grpc_chttp2_transport { bool parsing_active; /** write execution state of the transport */ grpc_chttp2_write_state write_state; - /** has a check_read_ops been scheduled */ - bool check_read_ops_scheduled; + + grpc_chttp2_executor_action_header *pending_actions_head; + grpc_chttp2_executor_action_header *pending_actions_tail; } executor; /** is the transport destroying itself? */ @@ -379,16 +380,10 @@ struct grpc_chttp2_transport { grpc_closure writing_action; /** closure to start reading from the endpoint */ grpc_closure reading_action; - grpc_closure reading_action_locked; - grpc_closure post_parse_locked; /** closure to actually do parsing */ grpc_closure parsing_action; /** closure to initiate writing */ grpc_closure initiate_writing; - /** closure to finish writing */ - grpc_closure terminate_writing; - /** closure to flush read state up the stack */ - grpc_closure initiate_read_flush_locked; /** incoming read bytes */ gpr_slice_buffer read_buffer; @@ -532,16 +527,11 @@ struct grpc_chttp2_stream_parsing { }; struct grpc_chttp2_stream { - grpc_chttp2_transport *t; grpc_stream_refcount *refcount; grpc_chttp2_stream_global global; grpc_chttp2_stream_writing writing; grpc_chttp2_stream_parsing parsing; - grpc_closure init_stream; - grpc_closure destroy_stream; - void *destroy_stream_arg; - grpc_chttp2_stream_link links[STREAM_LIST_COUNT]; uint8_t included[STREAM_LIST_COUNT]; }; @@ -636,7 +626,7 @@ int grpc_chttp2_list_pop_waiting_for_concurrency( grpc_chttp2_stream_global **stream_global); void grpc_chttp2_list_add_check_read_ops( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, + grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global); bool grpc_chttp2_list_remove_check_read_ops( grpc_chttp2_transport_global *transport_global, @@ -716,6 +706,12 @@ void grpc_chttp2_complete_closure_step( grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure, grpc_error *error); +void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *transport, + grpc_chttp2_stream *optional_stream, + grpc_chttp2_locked_action action, + void *arg, size_t sizeof_arg); + #define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" #define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \ (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1) diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index 0e6d579ba9..482cd55c44 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -177,8 +177,7 @@ void grpc_chttp2_publish_reads( stream_global->seen_error = true; stream_global->exceeded_metadata_size = stream_parsing->exceeded_metadata_size; - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } /* flush stats to global stream state */ @@ -204,8 +203,7 @@ void grpc_chttp2_publish_reads( stream_global->incoming_frames.tail->is_tail = 0; } if (stream_parsing->data_parser.incoming_frames.head != NULL) { - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } grpc_chttp2_incoming_frame_queue_merge( &stream_global->incoming_frames, @@ -221,8 +219,7 @@ void grpc_chttp2_publish_reads( GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, stream_parsing->metadata_buffer[0], stream_global->received_initial_metadata); - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (!stream_global->published_trailing_metadata && stream_parsing->got_metadata_on_parse[1]) { @@ -231,8 +228,7 @@ void grpc_chttp2_publish_reads( GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, stream_parsing->metadata_buffer[1], stream_global->received_trailing_metadata); - grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, - stream_global); + grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); } if (stream_parsing->forced_close_error != GRPC_ERROR_NONE) { diff --git a/src/core/ext/transport/chttp2/transport/stream_lists.c b/src/core/ext/transport/chttp2/transport/stream_lists.c index 4dc4968248..2eb5f5f632 100644 --- a/src/core/ext/transport/chttp2/transport/stream_lists.c +++ b/src/core/ext/transport/chttp2/transport/stream_lists.c @@ -298,15 +298,8 @@ int grpc_chttp2_list_pop_waiting_for_concurrency( } void grpc_chttp2_list_add_check_read_ops( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, + grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global) { - grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global); - if (!t->executor.check_read_ops_scheduled) { - grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, - &t->initiate_read_flush_locked, - GRPC_ERROR_NONE, false); - t->executor.check_read_ops_scheduled = true; - } stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global), STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_CHECK_READ_OPS); diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c index 979515bd54..311b26e354 100644 --- a/src/core/ext/transport/chttp2/transport/writing.c +++ b/src/core/ext/transport/chttp2/transport/writing.c @@ -55,6 +55,15 @@ int grpc_chttp2_unlocking_check_writes( transport_global->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]; + /* simple writes are queued to qbuf, and flushed here */ + gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf); + GPR_ASSERT(transport_global->qbuf.count == 0); + + grpc_chttp2_hpack_compressor_set_max_table_size( + &transport_writing->hpack_compressor, + transport_global->settings[GRPC_PEER_SETTINGS] + [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); + if (transport_global->dirtied_local_settings && !transport_global->sent_local_settings) { gpr_slice_buffer_add( @@ -68,16 +77,6 @@ int grpc_chttp2_unlocking_check_writes( transport_global->sent_local_settings = 1; } - /* simple writes are queued to qbuf, and flushed here */ - gpr_slice_buffer_move_into(&transport_global->qbuf, - &transport_writing->outbuf); - GPR_ASSERT(transport_global->qbuf.count == 0); - - grpc_chttp2_hpack_compressor_set_max_table_size( - &transport_writing->hpack_compressor, - transport_global->settings[GRPC_PEER_SETTINGS] - [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); - GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window, transport_global, outgoing_window); if (transport_writing->outgoing_window > 0) { @@ -345,7 +344,6 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx, void grpc_chttp2_cleanup_writing( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_writing *transport_writing) { - GPR_TIMER_BEGIN("grpc_chttp2_cleanup_writing", 0); grpc_chttp2_stream_writing *stream_writing; grpc_chttp2_stream_global *stream_global; @@ -384,5 +382,4 @@ void grpc_chttp2_cleanup_writing( GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing"); } gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf); - GPR_TIMER_END("grpc_chttp2_cleanup_writing", 0); } diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c index 0655b9353f..98f304f2da 100644 --- a/src/core/lib/channel/channel_stack.c +++ b/src/core/lib/channel/channel_stack.c @@ -32,7 +32,6 @@ */ #include "src/core/lib/channel/channel_stack.h" -#include #include #include @@ -271,27 +270,21 @@ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) { sizeof(grpc_call_stack))); } -static void destroy_op(grpc_exec_ctx *exec_ctx, void *op, grpc_error *error) { - gpr_free(op); -} - void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx, grpc_call_element *cur_elem) { - grpc_transport_stream_op *op = gpr_malloc(sizeof(*op)); - memset(op, 0, sizeof(*op)); - op->cancel_error = GRPC_ERROR_CANCELLED; - op->on_complete = grpc_closure_create(destroy_op, op); - grpc_call_next_op(exec_ctx, cur_elem, op); + grpc_transport_stream_op op; + memset(&op, 0, sizeof(op)); + op.cancel_error = GRPC_ERROR_CANCELLED; + grpc_call_next_op(exec_ctx, cur_elem, &op); } void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx, grpc_call_element *cur_elem, grpc_status_code status, gpr_slice *optional_message) { - grpc_transport_stream_op *op = gpr_malloc(sizeof(*op)); - memset(op, 0, sizeof(*op)); - op->on_complete = grpc_closure_create(destroy_op, op); - grpc_transport_stream_op_add_cancellation_with_message(op, status, + grpc_transport_stream_op op; + memset(&op, 0, sizeof(op)); + grpc_transport_stream_op_add_cancellation_with_message(&op, status, optional_message); - grpc_call_next_op(exec_ctx, cur_elem, op); + grpc_call_next_op(exec_ctx, cur_elem, &op); } diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c index 0981d59f63..134180e619 100644 --- a/src/core/lib/channel/compress_filter.c +++ b/src/core/lib/channel/compress_filter.c @@ -60,7 +60,7 @@ typedef struct call_data { /** If true, contents of \a compression_algorithm are authoritative */ int has_compression_algorithm; - grpc_transport_stream_op *send_op; + grpc_transport_stream_op send_op; uint32_t send_length; uint32_t send_flags; gpr_slice incoming_slice; @@ -199,11 +199,11 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx, grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices, calld->send_flags); - calld->send_op->send_message = &calld->replacement_stream.base; - calld->post_send = calld->send_op->on_complete; - calld->send_op->on_complete = &calld->send_done; + calld->send_op.send_message = &calld->replacement_stream.base; + calld->post_send = calld->send_op.on_complete; + calld->send_op.on_complete = &calld->send_done; - grpc_call_next_op(exec_ctx, elem, calld->send_op); + grpc_call_next_op(exec_ctx, elem, &calld->send_op); } static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { @@ -220,7 +220,7 @@ static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { static void continue_send_message(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { call_data *calld = elem->call_data; - while (grpc_byte_stream_next(exec_ctx, calld->send_op->send_message, + while (grpc_byte_stream_next(exec_ctx, calld->send_op.send_message, &calld->incoming_slice, ~(size_t)0, &calld->got_slice)) { gpr_slice_buffer_add(&calld->slices, calld->incoming_slice); @@ -243,7 +243,7 @@ static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx, } if (op->send_message != NULL && !skip_compression(elem) && 0 == (op->send_message->flags & GRPC_WRITE_NO_COMPRESS)) { - calld->send_op = op; + calld->send_op = *op; calld->send_length = op->send_message->length; calld->send_flags = op->send_message->flags; continue_send_message(exec_ctx, elem); diff --git a/src/core/lib/iomgr/closure.c b/src/core/lib/iomgr/closure.c index 1ba0a5c141..0b6c3b2539 100644 --- a/src/core/lib/iomgr/closure.c +++ b/src/core/lib/iomgr/closure.c @@ -41,10 +41,6 @@ void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb, closure->cb_arg = cb_arg; } -void grpc_closure_list_init(grpc_closure_list *closure_list) { - closure_list->head = closure_list->tail = NULL; -} - void grpc_closure_list_append(grpc_closure_list *closure_list, grpc_closure *closure, grpc_error *error) { if (closure == NULL) { diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h index c1a22b6021..08e59a168e 100644 --- a/src/core/lib/iomgr/closure.h +++ b/src/core/lib/iomgr/closure.h @@ -37,7 +37,6 @@ #include #include #include "src/core/lib/iomgr/error.h" -#include "src/core/lib/support/mpscq.h" struct grpc_closure; typedef struct grpc_closure grpc_closure; @@ -61,14 +60,6 @@ typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg, /** A closure over a grpc_iomgr_cb_func. */ struct grpc_closure { - /** Once queued, next indicates the next queued closure; before then, scratch - * space */ - union { - grpc_closure *next; - gpr_mpscq_node atm_next; - uintptr_t scratch; - } next_data; - /** Bound callback. */ grpc_iomgr_cb_func cb; @@ -77,6 +68,13 @@ struct grpc_closure { /** Once queued, the result of the closure. Before then: scratch space */ grpc_error *error; + + /** Once queued, next indicates the next queued closure; before then, scratch + * space */ + union { + grpc_closure *next; + uintptr_t scratch; + } next_data; }; /** Initializes \a closure with \a cb and \a cb_arg. */ @@ -89,8 +87,6 @@ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg); #define GRPC_CLOSURE_LIST_INIT \ { NULL, NULL } -void grpc_closure_list_init(grpc_closure_list *list); - /** add \a closure to the end of \a list and set \a closure's result to \a error */ void grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure, diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c deleted file mode 100644 index 831bdb4aff..0000000000 --- a/src/core/lib/iomgr/combiner.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * - * 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/lib/iomgr/combiner.h" - -#include - -#include -#include - -#include "src/core/lib/iomgr/workqueue.h" -#include "src/core/lib/profiling/timers.h" - -int grpc_combiner_trace = 0; - -#define GRPC_COMBINER_TRACE(fn) \ - do { \ - if (grpc_combiner_trace) { \ - fn; \ - } \ - } while (0) - -struct grpc_combiner { - grpc_workqueue *optional_workqueue; - gpr_mpscq queue; - // state is: - // lower bit - zero if orphaned - // other bits - number of items queued on the lock - gpr_atm state; - bool take_async_break_before_final_list; - grpc_closure_list final_list; - grpc_closure continue_finishing; -}; - -grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { - grpc_combiner *lock = gpr_malloc(sizeof(*lock)); - lock->optional_workqueue = optional_workqueue; - gpr_atm_no_barrier_store(&lock->state, 1); - gpr_mpscq_init(&lock->queue); - lock->take_async_break_before_final_list = false; - grpc_closure_list_init(&lock->final_list); - GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p create", lock)); - return lock; -} - -static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { - GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p really_destroy", lock)); - GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); - gpr_mpscq_destroy(&lock->queue); - GRPC_WORKQUEUE_UNREF(exec_ctx, lock->optional_workqueue, "combiner"); - gpr_free(lock); -} - -void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { - gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -1); - GRPC_COMBINER_TRACE(gpr_log( - GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state)); - if (old_state == 1) { - really_destroy(exec_ctx, lock); - } -} - -static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); -static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); - -static void continue_finishing_mainline(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - GPR_TIMER_BEGIN("combiner.continue_executing_mainline", 0); - grpc_combiner *lock = arg; - GRPC_COMBINER_TRACE( - gpr_log(GPR_DEBUG, "C:%p continue_finishing_mainline", lock)); - GPR_ASSERT(exec_ctx->active_combiner == NULL); - exec_ctx->active_combiner = lock; - if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); - GPR_ASSERT(exec_ctx->active_combiner == lock); - exec_ctx->active_combiner = NULL; - GPR_TIMER_END("combiner.continue_executing_mainline", 0); -} - -static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { - GPR_TIMER_BEGIN("combiner.execute_final", 0); - grpc_closure *c = lock->final_list.head; - GPR_ASSERT(c != NULL); - grpc_closure_list_init(&lock->final_list); - lock->take_async_break_before_final_list = false; - int loops = 0; - while (c != NULL) { - GRPC_COMBINER_TRACE( - gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c)); - grpc_closure *next = c->next_data.next; - grpc_error *error = c->error; - c->cb(exec_ctx, c->cb_arg, error); - GRPC_ERROR_UNREF(error); - c = next; - loops++; - } - GPR_TIMER_END("combiner.execute_final", 0); -} - -static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - GPR_TIMER_BEGIN("combiner.continue_executing_final", 0); - grpc_combiner *lock = arg; - GRPC_COMBINER_TRACE( - gpr_log(GPR_DEBUG, "C:%p continue_executing_final", lock)); - GPR_ASSERT(exec_ctx->active_combiner == NULL); - exec_ctx->active_combiner = lock; - // quick peek to see if new things have turned up on the queue: if so, go back - // to executing them before the final list - if ((gpr_atm_acq_load(&lock->state) >> 1) > 1) { - if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); - } else { - execute_final(exec_ctx, lock); - finish(exec_ctx, lock); - } - GPR_ASSERT(exec_ctx->active_combiner == lock); - exec_ctx->active_combiner = NULL; - GPR_TIMER_END("combiner.continue_executing_final", 0); -} - -static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { - GPR_TIMER_BEGIN("combiner.start_execute_final", 0); - GPR_ASSERT(exec_ctx->active_combiner == lock); - GRPC_COMBINER_TRACE( - gpr_log(GPR_DEBUG, - "C:%p start_execute_final take_async_break_before_final_list=%d", - lock, lock->take_async_break_before_final_list)); - if (lock->take_async_break_before_final_list) { - grpc_closure_init(&lock->continue_finishing, continue_executing_final, - lock); - grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, - GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); - GPR_TIMER_END("combiner.start_execute_final", 0); - return false; - } else { - execute_final(exec_ctx, lock); - GPR_TIMER_END("combiner.start_execute_final", 0); - return true; - } -} - -static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { - GPR_TIMER_BEGIN("combiner.maybe_finish_one", 0); - gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); - GRPC_COMBINER_TRACE( - gpr_log(GPR_DEBUG, "C:%p maybe_finish_one n=%p", lock, n)); - GPR_ASSERT(exec_ctx->active_combiner == lock); - if (n == NULL) { - // Queue is in an transiently inconsistent state: a new item is being queued - // but is not visible to this thread yet. - // Use this as a cue that we should go off and do something else for a while - // (and come back later) - grpc_closure_init(&lock->continue_finishing, continue_finishing_mainline, - lock); - grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, - GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); - GPR_TIMER_END("combiner.maybe_finish_one", 0); - return false; - } - grpc_closure *cl = (grpc_closure *)n; - grpc_error *error = cl->error; - cl->cb(exec_ctx, cl->cb_arg, error); - GRPC_ERROR_UNREF(error); - GPR_TIMER_END("combiner.maybe_finish_one", 0); - return true; -} - -static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { - bool (*executor)(grpc_exec_ctx * exec_ctx, grpc_combiner * lock); - GPR_TIMER_BEGIN("combiner.finish", 0); - int loops = 0; - do { - executor = maybe_finish_one; - gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -2); - GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, - "C:%p finish[%d] old_state=%" PRIdPTR, lock, - loops, old_state)); - switch (old_state) { - default: - // we have multiple queued work items: just continue executing them - break; - case 5: // we're down to one queued item: if it's the final list we - case 4: // should do that - if (!grpc_closure_list_empty(lock->final_list)) { - executor = start_execute_final; - } - break; - case 3: // had one count, one unorphaned --> unlocked unorphaned - GPR_TIMER_END("combiner.finish", 0); - return; - case 2: // and one count, one orphaned --> unlocked and orphaned - really_destroy(exec_ctx, lock); - GPR_TIMER_END("combiner.finish", 0); - return; - case 1: - case 0: - // these values are illegal - representing an already unlocked or - // deleted lock - GPR_UNREACHABLE_CODE(return ); - } - loops++; - } while (executor(exec_ctx, lock)); - GPR_TIMER_END("combiner.finish", 0); -} - -void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, - grpc_closure *cl, grpc_error *error) { - GRPC_COMBINER_TRACE( - gpr_log(GPR_DEBUG, "C:%p grpc_combiner_execute c=%p", lock, cl)); - GPR_TIMER_BEGIN("combiner.execute", 0); - gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); - GPR_ASSERT(last & 1); // ensure lock has not been destroyed - if (last == 1) { - exec_ctx->active_combiner = lock; - GPR_TIMER_BEGIN("combiner.execute_first_cb", 0); - cl->cb(exec_ctx, cl->cb_arg, error); - GPR_TIMER_END("combiner.execute_first_cb", 0); - GRPC_ERROR_UNREF(error); - finish(exec_ctx, lock); - GPR_ASSERT(exec_ctx->active_combiner == lock); - exec_ctx->active_combiner = NULL; - } else { - cl->error = error; - gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); - } - GPR_TIMER_END("combiner.execute", 0); -} - -static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, - grpc_error *error) { - grpc_combiner_execute_finally(exec_ctx, exec_ctx->active_combiner, closure, - GRPC_ERROR_REF(error), false); -} - -void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, - grpc_closure *closure, grpc_error *error, - bool force_async_break) { - GRPC_COMBINER_TRACE(gpr_log( - GPR_DEBUG, - "C:%p grpc_combiner_execute_finally c=%p force_async_break=%d; ac=%p", - lock, closure, force_async_break, exec_ctx->active_combiner)); - GPR_TIMER_BEGIN("combiner.execute_finally", 0); - if (exec_ctx->active_combiner != lock) { - GPR_TIMER_MARK("slowpath", 0); - grpc_combiner_execute(exec_ctx, lock, - grpc_closure_create(enqueue_finally, closure), error); - GPR_TIMER_END("combiner.execute_finally", 0); - return; - } - - if (force_async_break) { - lock->take_async_break_before_final_list = true; - } - if (grpc_closure_list_empty(lock->final_list)) { - gpr_atm_full_fetch_add(&lock->state, 2); - } - grpc_closure_list_append(&lock->final_list, closure, error); - GPR_TIMER_END("combiner.execute_finally", 0); -} - -void grpc_combiner_force_async_finally(grpc_combiner *lock) { - lock->take_async_break_before_final_list = true; -} diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h deleted file mode 100644 index 1409db24b9..0000000000 --- a/src/core/lib/iomgr/combiner.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_IOMGR_COMBINER_H -#define GRPC_CORE_LIB_IOMGR_COMBINER_H - -#include - -#include -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/support/mpscq.h" - -// Provides serialized access to some resource. -// Each action queued on a combiner is executed serially in a borrowed thread. -// The actual thread executing actions may change over time (but there will only -// every be one at a time). - -// Initialize the lock, with an optional workqueue to shift load to when -// necessary -grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue); -// Destroy the lock -void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); -// Execute \a action within the lock. -void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, - grpc_closure *closure, grpc_error *error); -// Execute \a action within the lock just prior to unlocking. -// if \a hint_async_break is true, the combiner tries to hand execution to -// another thread before finishing the primary queue of combined closures and -// executing the finally list. -// Deprecation warning: \a hint_async_break will be removed in a future version -// Takes a very slow and round-about path if not called from a -// grpc_combiner_execute closure. -void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, - grpc_closure *closure, grpc_error *error, - bool hint_async_break); -// Deprecated: force the finally list execution onto another thread -void grpc_combiner_force_async_finally(grpc_combiner *lock); - -extern int grpc_combiner_trace; - -#endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c index e366961936..149c55663c 100644 --- a/src/core/lib/iomgr/error.c +++ b/src/core/lib/iomgr/error.c @@ -332,7 +332,7 @@ grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) { return new; } -static const char *no_error_string = "\"No Error\""; +static const char *no_error_string = "null"; static const char *oom_error_string = "\"Out of memory\""; static const char *cancelled_error_string = "\"Cancelled\""; diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c index 740920d760..eba347125e 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epoll_linux.c @@ -1531,8 +1531,6 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_fd *fd) { - GPR_TIMER_BEGIN("pollset_add_fd", 0); - grpc_error *error = GRPC_ERROR_NONE; gpr_mu_lock(&pollset->mu); @@ -1645,8 +1643,6 @@ retry: gpr_mu_unlock(&pollset->mu); GRPC_LOG_IF_ERROR("pollset_add_fd", error); - - GPR_TIMER_END("pollset_add_fd", 0); } /******************************************************************************* diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index 1895ee6245..917f332f03 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -40,8 +40,8 @@ /** A workqueue represents a list of work to be executed asynchronously. Forward declared here to avoid a circular dependency with workqueue.h. */ +struct grpc_workqueue; typedef struct grpc_workqueue grpc_workqueue; -typedef struct grpc_combiner grpc_combiner; #ifndef GRPC_EXECUTION_CONTEXT_SANITIZER /** Execution context. @@ -66,15 +66,13 @@ typedef struct grpc_combiner grpc_combiner; */ struct grpc_exec_ctx { grpc_closure_list closure_list; - /** currently active combiner: updated only via combiner.c */ - grpc_combiner *active_combiner; bool cached_ready_to_finish; void *check_ready_to_finish_arg; bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg); }; #define GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(finish_check, finish_check_arg) \ - { GRPC_CLOSURE_LIST_INIT, NULL, false, finish_check_arg, finish_check } + { GRPC_CLOSURE_LIST_INIT, false, finish_check_arg, finish_check } #else struct grpc_exec_ctx { bool cached_ready_to_finish; diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c index 92767721d5..974d5ae479 100644 --- a/src/core/lib/iomgr/tcp_posix.c +++ b/src/core/lib/iomgr/tcp_posix.c @@ -379,19 +379,10 @@ static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, } if (!tcp_flush(tcp, &error)) { - if (grpc_tcp_trace) { - gpr_log(GPR_DEBUG, "write: delayed"); - } grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { cb = tcp->write_cb; tcp->write_cb = NULL; - if (grpc_tcp_trace) { - const char *str = grpc_error_string(error); - gpr_log(GPR_DEBUG, "write: %s", str); - grpc_error_free_string(str); - } - GPR_TIMER_BEGIN("tcp_handle_write.cb", 0); cb->cb(exec_ctx, cb->cb_arg, error); GPR_TIMER_END("tcp_handle_write.cb", 0); @@ -434,16 +425,8 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, if (!tcp_flush(tcp, &error)) { TCP_REF(tcp, "write"); tcp->write_cb = cb; - if (grpc_tcp_trace) { - gpr_log(GPR_DEBUG, "write: delayed"); - } grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { - if (grpc_tcp_trace) { - const char *str = grpc_error_string(error); - gpr_log(GPR_DEBUG, "write: %s", str); - grpc_error_free_string(str); - } grpc_exec_ctx_sched(exec_ctx, cb, error, NULL); } diff --git a/src/core/lib/iomgr/workqueue.h b/src/core/lib/iomgr/workqueue.h index b2805dc66c..7156e490d7 100644 --- a/src/core/lib/iomgr/workqueue.h +++ b/src/core/lib/iomgr/workqueue.h @@ -50,6 +50,10 @@ /* grpc_workqueue is forward declared in exec_ctx.h */ +/* Deprecated: do not use. + This has *already* been removed in a future commit. */ +void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue); + /* Reference counting functions. Use the macro's always (GRPC_WORKQUEUE_{REF,UNREF}). diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c index ecfea68f56..e0d6dac230 100644 --- a/src/core/lib/iomgr/workqueue_posix.c +++ b/src/core/lib/iomgr/workqueue_posix.c @@ -44,7 +44,6 @@ #include #include "src/core/lib/iomgr/ev_posix.h" -#include "src/core/lib/profiling/timers.h" static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); @@ -53,7 +52,8 @@ grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, char name[32]; *workqueue = gpr_malloc(sizeof(grpc_workqueue)); gpr_ref_init(&(*workqueue)->refs, 1); - gpr_atm_no_barrier_store(&(*workqueue)->state, 1); + gpr_mu_init(&(*workqueue)->mu); + (*workqueue)->closure_list.head = (*workqueue)->closure_list.tail = NULL; grpc_error *err = grpc_wakeup_fd_init(&(*workqueue)->wakeup_fd); if (err != GRPC_ERROR_NONE) { gpr_free(*workqueue); @@ -62,7 +62,6 @@ grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, sprintf(name, "workqueue:%p", (void *)(*workqueue)); (*workqueue)->wakeup_read_fd = grpc_fd_create( GRPC_WAKEUP_FD_GET_READ_FD(&(*workqueue)->wakeup_fd), name); - gpr_mpscq_init(&(*workqueue)->queue); grpc_closure_init(&(*workqueue)->read_closure, on_readable, *workqueue); grpc_fd_notify_on_read(exec_ctx, (*workqueue)->wakeup_read_fd, &(*workqueue)->read_closure); @@ -71,79 +70,57 @@ grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, static void workqueue_destroy(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { + grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); grpc_fd_shutdown(exec_ctx, workqueue->wakeup_read_fd); } -static void workqueue_orphan(grpc_exec_ctx *exec_ctx, - grpc_workqueue *workqueue) { - if (gpr_atm_full_fetch_add(&workqueue->state, -1) == 1) { - workqueue_destroy(exec_ctx, workqueue); - } -} - #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) { - if (workqueue == NULL) return; gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p ref %d -> %d %s", workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count + 1, reason); - gpr_ref(&workqueue->refs); -} #else void grpc_workqueue_ref(grpc_workqueue *workqueue) { - if (workqueue == NULL) return; +#endif gpr_ref(&workqueue->refs); } -#endif #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason) { - if (workqueue == NULL) return; gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p unref %d -> %d %s", workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count - 1, reason); - if (gpr_unref(&workqueue->refs)) { - workqueue_orphan(exec_ctx, workqueue); - } -} #else void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { - if (workqueue == NULL) return; +#endif if (gpr_unref(&workqueue->refs)) { - workqueue_orphan(exec_ctx, workqueue); + workqueue_destroy(exec_ctx, workqueue); } } -#endif - -static void drain(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { - abort(); -} -static void wakeup(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { - GPR_TIMER_MARK("workqueue.wakeup", 0); - grpc_error *err = grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd); - if (!GRPC_LOG_IF_ERROR("wakeupfd_wakeup", err)) { - drain(exec_ctx, workqueue); - } +void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { + gpr_mu_lock(&workqueue->mu); + grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); + gpr_mu_unlock(&workqueue->mu); } static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - GPR_TIMER_BEGIN("workqueue.on_readable", 0); - grpc_workqueue *workqueue = arg; if (error != GRPC_ERROR_NONE) { + gpr_mu_destroy(&workqueue->mu); /* HACK: let wakeup_fd code know that we stole the fd */ workqueue->wakeup_fd.read_fd = 0; grpc_wakeup_fd_destroy(&workqueue->wakeup_fd); grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy"); - GPR_ASSERT(gpr_atm_no_barrier_load(&workqueue->state) == 0); gpr_free(workqueue); } else { + gpr_mu_lock(&workqueue->mu); + grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); error = grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd); - gpr_mpscq_node *n = gpr_mpscq_pop(&workqueue->queue); + gpr_mu_unlock(&workqueue->mu); if (error == GRPC_ERROR_NONE) { grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd, &workqueue->read_closure); @@ -151,46 +128,24 @@ static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { /* recurse to get error handling */ on_readable(exec_ctx, arg, error); } - if (n == NULL) { - /* try again - queue in an inconsistant state */ - wakeup(exec_ctx, workqueue); - } else { - switch (gpr_atm_full_fetch_add(&workqueue->state, -2)) { - case 3: // had one count, one unorphaned --> done, unorphaned - break; - case 2: // had one count, one orphaned --> done, orphaned - workqueue_destroy(exec_ctx, workqueue); - break; - case 1: - case 0: - // these values are illegal - representing an already done or - // deleted workqueue - GPR_UNREACHABLE_CODE(break); - default: - // schedule a wakeup since there's more to do - wakeup(exec_ctx, workqueue); - } - grpc_closure *cl = (grpc_closure *)n; - grpc_error *clerr = cl->error; - cl->cb(exec_ctx, cl->cb_arg, clerr); - GRPC_ERROR_UNREF(clerr); - } } - - GPR_TIMER_END("workqueue.on_readable", 0); } void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, grpc_closure *closure, grpc_error *error) { - GPR_TIMER_BEGIN("workqueue.enqueue", 0); - gpr_atm last = gpr_atm_full_fetch_add(&workqueue->state, 2); - GPR_ASSERT(last & 1); - closure->error = error; - gpr_mpscq_push(&workqueue->queue, &closure->next_data.atm_next); - if (last == 1) { - wakeup(exec_ctx, workqueue); + grpc_error *push_error = GRPC_ERROR_NONE; + gpr_mu_lock(&workqueue->mu); + if (grpc_closure_list_empty(workqueue->closure_list)) { + push_error = grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd); + } + grpc_closure_list_append(&workqueue->closure_list, closure, error); + if (push_error != GRPC_ERROR_NONE) { + const char *msg = grpc_error_string(push_error); + gpr_log(GPR_ERROR, "Failed to push to workqueue: %s", msg); + grpc_error_free_string(msg); + grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); } - GPR_TIMER_END("workqueue.enqueue", 0); + gpr_mu_unlock(&workqueue->mu); } #endif /* GPR_POSIX_SOCKET */ diff --git a/src/core/lib/iomgr/workqueue_posix.h b/src/core/lib/iomgr/workqueue_posix.h index 03ee21cef7..0f26ba58e2 100644 --- a/src/core/lib/iomgr/workqueue_posix.h +++ b/src/core/lib/iomgr/workqueue_posix.h @@ -35,17 +35,14 @@ #define GRPC_CORE_LIB_IOMGR_WORKQUEUE_POSIX_H #include "src/core/lib/iomgr/wakeup_fd_posix.h" -#include "src/core/lib/support/mpscq.h" struct grpc_fd; struct grpc_workqueue { gpr_refcount refs; - gpr_mpscq queue; - // state is: - // lower bit - zero if orphaned - // other bits - number of items enqueued - gpr_atm state; + + gpr_mu mu; + grpc_closure_list closure_list; grpc_wakeup_fd wakeup_fd; struct grpc_fd *wakeup_read_fd; diff --git a/src/core/lib/iomgr/workqueue_windows.c b/src/core/lib/iomgr/workqueue_windows.c index ee81dc248e..23e2dea185 100644 --- a/src/core/lib/iomgr/workqueue_windows.c +++ b/src/core/lib/iomgr/workqueue_windows.c @@ -42,6 +42,8 @@ // context, which is at least correct, if not performant or in the spirit of // workqueues. +void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} + #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) {} diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c index b366d1410f..2a1bf4d4e3 100644 --- a/src/core/lib/security/transport/client_auth_filter.c +++ b/src/core/lib/security/transport/client_auth_filter.c @@ -40,7 +40,6 @@ #include #include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/profiling/timers.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/transport/security_connector.h" @@ -219,8 +218,6 @@ static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data, static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op *op) { - GPR_TIMER_BEGIN("auth_start_transport_op", 0); - /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; @@ -261,14 +258,12 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector_check_call_host( exec_ctx, chand->security_connector, call_host, chand->auth_context, on_host_checked, elem); - GPR_TIMER_END("auth_start_transport_op", 0); return; /* early exit */ } } /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, op); - GPR_TIMER_END("auth_start_transport_op", 0); } /* Constructor for call_data */ diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c index acb0113ea8..0169ccd9ef 100644 --- a/src/core/lib/security/transport/secure_endpoint.c +++ b/src/core/lib/security/transport/secure_endpoint.c @@ -38,7 +38,6 @@ #include #include #include "src/core/lib/debug/trace.h" -#include "src/core/lib/profiling/timers.h" #include "src/core/lib/security/transport/tsi_error.h" #include "src/core/lib/support/string.h" #include "src/core/lib/tsi/transport_security_interface.h" @@ -249,8 +248,6 @@ static void flush_write_staging_buffer(secure_endpoint *ep, uint8_t **cur, static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, gpr_slice_buffer *slices, grpc_closure *cb) { - GPR_TIMER_BEGIN("secure_endpoint.endpoint_write", 0); - unsigned i; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)secure_ep; @@ -326,12 +323,10 @@ static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, exec_ctx, cb, grpc_set_tsi_error_result(GRPC_ERROR_CREATE("Wrap failed"), result), NULL); - GPR_TIMER_END("secure_endpoint.endpoint_write", 0); return; } grpc_endpoint_write(exec_ctx, ep->wrapped_ep, &ep->output_buffer, cb); - GPR_TIMER_END("secure_endpoint.endpoint_write", 0); } static void endpoint_shutdown(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c index b2c6815af8..def16c8229 100644 --- a/src/core/lib/security/transport/server_auth_filter.c +++ b/src/core/lib/security/transport/server_auth_filter.c @@ -48,7 +48,7 @@ typedef struct call_data { up-call on transport_op, and remember to call our on_done_recv member after handling it. */ grpc_closure auth_on_recv; - grpc_transport_stream_op *transport_op; + grpc_transport_stream_op transport_op; grpc_metadata_array md; const grpc_metadata *consumed_md; size_t num_consumed_md; @@ -106,10 +106,6 @@ static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) { return md; } -static void destroy_op(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - gpr_free(arg); -} - /* called from application code */ static void on_md_processing_done( void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md, @@ -135,22 +131,21 @@ static void on_md_processing_done( grpc_exec_ctx_sched(&exec_ctx, calld->on_done_recv, GRPC_ERROR_NONE, NULL); } else { gpr_slice message; - grpc_transport_stream_op *close_op = gpr_malloc(sizeof(*close_op)); - memset(close_op, 0, sizeof(*close_op)); + grpc_transport_stream_op close_op; + memset(&close_op, 0, sizeof(close_op)); grpc_metadata_array_destroy(&calld->md); error_details = error_details != NULL ? error_details : "Authentication metadata processing failed."; message = gpr_slice_from_copied_string(error_details); - calld->transport_op->send_initial_metadata = NULL; - if (calld->transport_op->send_message != NULL) { - grpc_byte_stream_destroy(&exec_ctx, calld->transport_op->send_message); - calld->transport_op->send_message = NULL; + calld->transport_op.send_initial_metadata = NULL; + if (calld->transport_op.send_message != NULL) { + grpc_byte_stream_destroy(&exec_ctx, calld->transport_op.send_message); + calld->transport_op.send_message = NULL; } - calld->transport_op->send_trailing_metadata = NULL; - close_op->on_complete = grpc_closure_create(destroy_op, close_op); - grpc_transport_stream_op_add_close(close_op, status, &message); - grpc_call_next_op(&exec_ctx, elem, close_op); + calld->transport_op.send_trailing_metadata = NULL; + grpc_transport_stream_op_add_close(&close_op, status, &message); + grpc_call_next_op(&exec_ctx, elem, &close_op); grpc_exec_ctx_sched(&exec_ctx, calld->on_done_recv, grpc_error_set_int(GRPC_ERROR_CREATE(error_details), GRPC_ERROR_INT_GRPC_STATUS, status), @@ -187,7 +182,7 @@ static void set_recv_ops_md_callbacks(grpc_call_element *elem, calld->recv_initial_metadata = op->recv_initial_metadata; calld->on_done_recv = op->recv_initial_metadata_ready; op->recv_initial_metadata_ready = &calld->auth_on_recv; - calld->transport_op = op; + calld->transport_op = *op; } } diff --git a/src/core/lib/support/mpscq.c b/src/core/lib/support/mpscq.c deleted file mode 100644 index 5b9323275a..0000000000 --- a/src/core/lib/support/mpscq.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * 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/lib/support/mpscq.h" - -#include - -void gpr_mpscq_init(gpr_mpscq *q) { - gpr_atm_no_barrier_store(&q->head, (gpr_atm)&q->stub); - q->tail = &q->stub; - gpr_atm_no_barrier_store(&q->stub.next, (gpr_atm)NULL); -} - -void gpr_mpscq_destroy(gpr_mpscq *q) { - GPR_ASSERT(gpr_atm_no_barrier_load(&q->head) == (gpr_atm)&q->stub); - GPR_ASSERT(q->tail == &q->stub); -} - -void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n) { - gpr_atm_no_barrier_store(&n->next, (gpr_atm)NULL); - gpr_mpscq_node *prev = - (gpr_mpscq_node *)gpr_atm_full_xchg(&q->head, (gpr_atm)n); - gpr_atm_rel_store(&prev->next, (gpr_atm)n); -} - -gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { - gpr_mpscq_node *tail = q->tail; - gpr_mpscq_node *next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); - if (tail == &q->stub) { - // indicates the list is actually (ephemerally) empty - if (next == NULL) return NULL; - q->tail = next; - tail = next; - next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); - } - if (next != NULL) { - q->tail = next; - return tail; - } - gpr_mpscq_node *head = (gpr_mpscq_node *)gpr_atm_acq_load(&q->head); - if (tail != head) { - // indicates a retry is in order: we're still adding - return NULL; - } - gpr_mpscq_push(q, &q->stub); - next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); - if (next != NULL) { - q->tail = next; - return tail; - } - // indicates a retry is in order: we're still adding - return NULL; -} diff --git a/src/core/lib/support/mpscq.h b/src/core/lib/support/mpscq.h deleted file mode 100644 index 977a117952..0000000000 --- a/src/core/lib/support/mpscq.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_SUPPORT_MPSCQ_H -#define GRPC_CORE_LIB_SUPPORT_MPSCQ_H - -#include -#include - -// Multiple-producer single-consumer lock free queue, based upon the -// implementation from Dmitry Vyukov here: -// http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue - -// List node (include this in a data structure at the top, and add application -// fields after it - to simulate inheritance) -typedef struct gpr_mpscq_node { gpr_atm next; } gpr_mpscq_node; - -// Actual queue type -typedef struct gpr_mpscq { - gpr_atm head; - // make sure head & tail don't share a cacheline - char padding[GPR_CACHELINE_SIZE]; - gpr_mpscq_node *tail; - gpr_mpscq_node stub; -} gpr_mpscq; - -void gpr_mpscq_init(gpr_mpscq *q); -void gpr_mpscq_destroy(gpr_mpscq *q); -// Push a node -void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n); -// Pop a node (returns NULL if no node is ready - which doesn't indicate that -// the queue is empty!!) -gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q); - -#endif /* GRPC_CORE_LIB_SUPPORT_MPSCQ_H */ diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 119f5e82ab..772681109a 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -109,10 +109,6 @@ typedef struct batch_control { uint8_t recv_message; uint8_t recv_final_op; uint8_t is_notify_tag_closure; - - /* TODO(ctiller): now that this is inlined, figure out how much of the above - state can be eliminated */ - grpc_transport_stream_op op; } batch_control; struct grpc_call { @@ -782,7 +778,6 @@ typedef struct termination_closure { grpc_error *error; grpc_closure *op_closure; enum { TC_CANCEL, TC_CLOSE } type; - grpc_transport_stream_op op; } termination_closure; static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp, @@ -802,24 +797,26 @@ static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp, } static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { + grpc_transport_stream_op op; termination_closure *tc = tcp; - memset(&tc->op, 0, sizeof(tc->op)); - tc->op.cancel_error = tc->error; + memset(&op, 0, sizeof(op)); + op.cancel_error = tc->error; /* reuse closure to catch completion */ grpc_closure_init(&tc->closure, done_termination, tc); - tc->op.on_complete = &tc->closure; - execute_op(exec_ctx, tc->call, &tc->op); + op.on_complete = &tc->closure; + execute_op(exec_ctx, tc->call, &op); } static void send_close(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { + grpc_transport_stream_op op; termination_closure *tc = tcp; - memset(&tc->op, 0, sizeof(tc->op)); - tc->op.close_error = tc->error; + memset(&op, 0, sizeof(op)); + op.close_error = tc->error; /* reuse closure to catch completion */ grpc_closure_init(&tc->closure, done_termination, tc); - tc->op_closure = tc->op.on_complete; - tc->op.on_complete = &tc->closure; - execute_op(exec_ctx, tc->call, &tc->op); + tc->op_closure = op.on_complete; + op.on_complete = &tc->closure; + execute_op(exec_ctx, tc->call, &op); } static grpc_call_error terminate_with_status(grpc_exec_ctx *exec_ctx, @@ -1373,6 +1370,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_call *call, const grpc_op *ops, size_t nops, void *notify_tag, int is_notify_tag_closure) { + grpc_transport_stream_op stream_op; size_t i; const grpc_op *op; batch_control *bctl; @@ -1386,6 +1384,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag); + memset(&stream_op, 0, sizeof(stream_op)); + /* TODO(ctiller): this feels like it could be made lock-free */ gpr_mu_lock(&call->mu); bctl = allocate_batch_control(call); @@ -1394,9 +1394,6 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, bctl->notify_tag = notify_tag; bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0); - grpc_transport_stream_op *stream_op = &bctl->op; - memset(stream_op, 0, sizeof(*stream_op)); - if (nops == 0) { GRPC_CALL_INTERNAL_REF(call, "completion"); bctl->error = GRPC_ERROR_NONE; @@ -1474,9 +1471,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, } /* TODO(ctiller): just make these the same variable? */ call->metadata_batch[0][0].deadline = call->send_deadline; - stream_op->send_initial_metadata = + stream_op.send_initial_metadata = &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]; - stream_op->send_initial_metadata_flags = op->flags; + stream_op.send_initial_metadata_flags = op->flags; break; case GRPC_OP_SEND_MESSAGE: if (!are_write_flags_valid(op->flags)) { @@ -1496,7 +1493,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_slice_buffer_stream_init( &call->sending_stream, &op->data.send_message->data.raw.slice_buffer, op->flags); - stream_op->send_message = &call->sending_stream.base; + stream_op.send_message = &call->sending_stream.base; break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: /* Flag validation: currently allow no flags */ @@ -1514,7 +1511,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, } bctl->send_final_op = 1; call->sent_final_op = 1; - stream_op->send_trailing_metadata = + stream_op.send_trailing_metadata = &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]; break; case GRPC_OP_SEND_STATUS_FROM_SERVER: @@ -1561,7 +1558,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, error = GRPC_CALL_ERROR_INVALID_METADATA; goto done_with_error; } - stream_op->send_trailing_metadata = + stream_op.send_trailing_metadata = &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]; break; case GRPC_OP_RECV_INITIAL_METADATA: @@ -1579,9 +1576,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_closure_init(&call->receiving_initial_metadata_ready, receiving_initial_metadata_ready, bctl); bctl->recv_initial_metadata = 1; - stream_op->recv_initial_metadata = + stream_op.recv_initial_metadata = &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */]; - stream_op->recv_initial_metadata_ready = + stream_op.recv_initial_metadata_ready = &call->receiving_initial_metadata_ready; num_completion_callbacks_needed++; break; @@ -1598,10 +1595,10 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->receiving_message = 1; bctl->recv_message = 1; call->receiving_buffer = op->data.recv_message; - stream_op->recv_message = &call->receiving_stream; + stream_op.recv_message = &call->receiving_stream; grpc_closure_init(&call->receiving_stream_ready, receiving_stream_ready, bctl); - stream_op->recv_message_ready = &call->receiving_stream_ready; + stream_op.recv_message_ready = &call->receiving_stream_ready; num_completion_callbacks_needed++; break; case GRPC_OP_RECV_STATUS_ON_CLIENT: @@ -1627,9 +1624,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->final_op.client.status_details_capacity = op->data.recv_status_on_client.status_details_capacity; bctl->recv_final_op = 1; - stream_op->recv_trailing_metadata = + stream_op.recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - stream_op->collect_stats = + stream_op.collect_stats = &call->final_info.stats.transport_stream_stats; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: @@ -1650,9 +1647,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->final_op.server.cancelled = op->data.recv_close_on_server.cancelled; bctl->recv_final_op = 1; - stream_op->recv_trailing_metadata = + stream_op.recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - stream_op->collect_stats = + stream_op.collect_stats = &call->final_info.stats.transport_stream_stats; break; } @@ -1664,12 +1661,12 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, } gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed); - stream_op->context = call->context; + stream_op.context = call->context; grpc_closure_init(&bctl->finish_batch, finish_batch, bctl); - stream_op->on_complete = &bctl->finish_batch; + stream_op.on_complete = &bctl->finish_batch; gpr_mu_unlock(&call->mu); - execute_op(exec_ctx, call, stream_op); + execute_op(exec_ctx, call, &stream_op); done: GPR_TIMER_END("grpc_call_start_batch", 0); diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c index 52e78567bd..6d2b1c4935 100644 --- a/src/core/lib/surface/channel.c +++ b/src/core/lib/surface/channel.c @@ -334,13 +334,14 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, } void grpc_channel_destroy(grpc_channel *channel) { - grpc_transport_op *op = grpc_make_transport_op(NULL); + grpc_transport_op op; grpc_channel_element *elem; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel)); - op->disconnect_with_error = GRPC_ERROR_CREATE("Channel Destroyed"); + memset(&op, 0, sizeof(op)); + op.disconnect_with_error = GRPC_ERROR_CREATE("Channel Destroyed"); elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); - elem->filter->start_transport_op(&exec_ctx, elem, op); + elem->filter->start_transport_op(&exec_ctx, elem, &op); GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "channel"); diff --git a/src/core/lib/surface/channel_ping.c b/src/core/lib/surface/channel_ping.c index 0d2f01a649..9818f9d2f2 100644 --- a/src/core/lib/surface/channel_ping.c +++ b/src/core/lib/surface/channel_ping.c @@ -61,20 +61,19 @@ static void ping_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved) { - GRPC_API_TRACE("grpc_channel_ping(channel=%p, cq=%p, tag=%p, reserved=%p)", 4, - (channel, cq, tag, reserved)); - grpc_transport_op *op = grpc_make_transport_op(NULL); + grpc_transport_op op; ping_result *pr = gpr_malloc(sizeof(*pr)); grpc_channel_element *top_elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT(reserved == NULL); + memset(&op, 0, sizeof(op)); pr->tag = tag; pr->cq = cq; grpc_closure_init(&pr->closure, ping_done, pr); - op->send_ping = &pr->closure; - op->bind_pollset = grpc_cq_pollset(cq); + op.send_ping = &pr->closure; + op.bind_pollset = grpc_cq_pollset(cq); grpc_cq_begin_op(cq, tag); - top_elem->filter->start_transport_op(&exec_ctx, top_elem, op); + top_elem->filter->start_transport_op(&exec_ctx, top_elem, &op); grpc_exec_ctx_finish(&exec_ctx); } diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index edda0c85fa..5397913a21 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -47,7 +47,6 @@ #include "src/core/lib/channel/http_server_filter.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/http/parser.h" -#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/profiling/timers.h" @@ -166,7 +165,6 @@ void grpc_init(void) { grpc_register_tracer("http1", &grpc_http1_trace); grpc_register_tracer("compression", &grpc_compression_trace); grpc_register_tracer("queue_pluck", &grpc_cq_pluck_trace); - grpc_register_tracer("combiner", &grpc_combiner_trace); // Default pluck trace to 1 grpc_cq_pluck_trace = 1; grpc_register_tracer("queue_timeout", &grpc_cq_event_timeout_trace); diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c index d32c884e8e..19b78369dd 100644 --- a/src/core/lib/surface/lame_client.c +++ b/src/core/lib/surface/lame_client.c @@ -97,14 +97,14 @@ static void lame_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_exec_ctx_sched(exec_ctx, op->on_connectivity_state_change, GRPC_ERROR_NONE, NULL); } + if (op->on_consumed != NULL) { + grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); + } if (op->send_ping != NULL) { grpc_exec_ctx_sched(exec_ctx, op->send_ping, GRPC_ERROR_CREATE("lame client channel"), NULL); } GRPC_ERROR_UNREF(op->disconnect_with_error); - if (op->on_consumed != NULL) { - grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); - } } static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index 56fb80e92e..55e6d99057 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -273,20 +273,23 @@ static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg, } static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel, - int send_goaway, grpc_error *send_disconnect) { - struct shutdown_cleanup_args *sc = gpr_malloc(sizeof(*sc)); - grpc_closure_init(&sc->closure, shutdown_cleanup, sc); - grpc_transport_op *op = grpc_make_transport_op(&sc->closure); + bool send_goaway, grpc_error *send_disconnect) { + grpc_transport_op op; + struct shutdown_cleanup_args *sc; grpc_channel_element *elem; - op->send_goaway = send_goaway; + memset(&op, 0, sizeof(op)); + op.send_goaway = send_goaway; + sc = gpr_malloc(sizeof(*sc)); sc->slice = gpr_slice_from_copied_string("Server shutdown"); - op->goaway_message = &sc->slice; - op->goaway_status = GRPC_STATUS_OK; - op->disconnect_with_error = send_disconnect; + op.goaway_message = &sc->slice; + op.goaway_status = GRPC_STATUS_OK; + op.disconnect_with_error = send_disconnect; + grpc_closure_init(&sc->closure, shutdown_cleanup, sc); + op.on_consumed = &sc->closure; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); - elem->filter->start_transport_op(exec_ctx, elem, op); + elem->filter->start_transport_op(exec_ctx, elem, &op); } static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx, @@ -429,8 +432,7 @@ static void finish_destroy_channel(grpc_exec_ctx *exec_ctx, void *cd, server_unref(exec_ctx, server); } -static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand, - grpc_error *error) { +static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) { if (is_channel_orphaned(chand)) return; GPR_ASSERT(chand->server != NULL); orphan_channel(chand); @@ -439,20 +441,14 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand, chand->finish_destroy_channel_closure.cb = finish_destroy_channel; chand->finish_destroy_channel_closure.cb_arg = chand; - grpc_transport_op *op = - grpc_make_transport_op(&chand->finish_destroy_channel_closure); - op->set_accept_stream = true; + 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); - - if (error != GRPC_ERROR_NONE) { - const char *msg = grpc_error_string(error); - gpr_log(GPR_INFO, "Disconnected client: %s", msg); - grpc_error_free_string(msg); - } - GRPC_ERROR_UNREF(error); + &op); } static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) { @@ -849,16 +845,17 @@ static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd, channel_data *chand = cd; grpc_server *server = chand->server; if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { - grpc_transport_op *op = grpc_make_transport_op(NULL); - op->on_connectivity_state_change = &chand->channel_connectivity_changed, - op->connectivity_state = &chand->connectivity_state; + grpc_transport_op op; + memset(&op, 0, sizeof(op)); + op.on_connectivity_state_change = &chand->channel_connectivity_changed, + op.connectivity_state = &chand->connectivity_state; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), - op); + &op); } else { gpr_mu_lock(&server->mu_global); - destroy_channel(exec_ctx, chand, GRPC_ERROR_REF(error)); + destroy_channel(exec_ctx, chand); gpr_mu_unlock(&server->mu_global); GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "connectivity"); } @@ -1122,7 +1119,7 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, size_t slots; uint32_t probes; uint32_t max_probes = 0; - grpc_transport_op *op = NULL; + grpc_transport_op op; channel = grpc_channel_create(exec_ctx, NULL, args, GRPC_SERVER_CHANNEL, transport); @@ -1182,16 +1179,16 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, gpr_mu_unlock(&s->mu_global); GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity"); - op = grpc_make_transport_op(NULL); - 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; + memset(&op, 0, sizeof(op)); + 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; if (gpr_atm_acq_load(&s->shutdown_flag) != 0) { - op->disconnect_with_error = GRPC_ERROR_CREATE("Server shutdown"); + op.disconnect_with_error = GRPC_ERROR_CREATE("Server shutdown"); } - grpc_transport_perform_op(exec_ctx, transport, op); + grpc_transport_perform_op(exec_ctx, transport, &op); } void done_published_shutdown(grpc_exec_ctx *exec_ctx, void *done_arg, diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c index 08f9d7e8d9..857c3909d2 100644 --- a/src/core/lib/transport/transport.c +++ b/src/core/lib/transport/transport.c @@ -32,14 +32,10 @@ */ #include "src/core/lib/transport/transport.h" - -#include - #include #include #include #include - #include "src/core/lib/support/string.h" #include "src/core/lib/transport/transport_impl.h" @@ -251,26 +247,3 @@ void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op, error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status); add_error(op, &op->close_error, error); } - -typedef struct { - grpc_closure outer_on_complete; - grpc_closure *inner_on_complete; - grpc_transport_op op; -} made_transport_op; - -static void destroy_made_transport_op(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - made_transport_op *op = arg; - grpc_exec_ctx_sched(exec_ctx, op->inner_on_complete, GRPC_ERROR_REF(error), - NULL); - gpr_free(op); -} - -grpc_transport_op *grpc_make_transport_op(grpc_closure *on_complete) { - made_transport_op *op = gpr_malloc(sizeof(*op)); - grpc_closure_init(&op->outer_on_complete, destroy_made_transport_op, op); - op->inner_on_complete = on_complete; - memset(&op->op, 0, sizeof(op->op)); - op->op.on_consumed = &op->outer_on_complete; - return &op->op; -} diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 8dc393fd61..26ed6cb839 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -100,11 +100,6 @@ void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats *from, void grpc_transport_move_stats(grpc_transport_stream_stats *from, grpc_transport_stream_stats *to); -typedef struct { - grpc_closure closure; - void *args[2]; -} grpc_transport_private_op_data; - /* Transport stream op: a set of operations to perform on a transport against a single stream */ typedef struct grpc_transport_stream_op { @@ -154,12 +149,6 @@ typedef struct grpc_transport_stream_op { /* Indexes correspond to grpc_context_index enum values */ grpc_call_context_element *context; - - /*************************************************************************** - * remaining fields are initialized and used at the discretion of the - * transport implementation */ - - grpc_transport_private_op_data transport_private; } grpc_transport_stream_op; /** Transport op: a set of operations to perform on a transport as a whole */ @@ -193,12 +182,6 @@ typedef struct grpc_transport_op { grpc_pollset_set *bind_pollset_set; /** send a ping, call this back if not NULL */ grpc_closure *send_ping; - - /*************************************************************************** - * remaining fields are initialized and used at the discretion of the - * transport implementation */ - - grpc_transport_private_op_data transport_private; } grpc_transport_op; /* Returns the amount of memory required to store a grpc_stream for this @@ -290,10 +273,6 @@ void grpc_transport_destroy(grpc_exec_ctx *exec_ctx, grpc_transport *transport); char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *transport); -/* Allocate a grpc_transport_op, and preconfigure the on_consumed closure to - \a on_consumed and then delete the returned transport op */ -grpc_transport_op *grpc_make_transport_op(grpc_closure *on_consumed); - #ifdef __cplusplus } #endif diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index d53f46b18b..be7f30c29b 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -50,7 +50,6 @@ CORE_SOURCE_FILES = [ 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_windows.c', - 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/percent_encoding.c', 'src/core/lib/support/slice.c', @@ -93,7 +92,6 @@ CORE_SOURCE_FILES = [ 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', 'src/core/lib/iomgr/closure.c', - 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', diff --git a/test/core/iomgr/combiner_test.c b/test/core/iomgr/combiner_test.c deleted file mode 100644 index 197998c1e5..0000000000 --- a/test/core/iomgr/combiner_test.c +++ /dev/null @@ -1,164 +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. - * - */ - -#include "src/core/lib/iomgr/combiner.h" - -#include -#include -#include -#include -#include - -#include "test/core/util/test_config.h" - -static void test_no_op(void) { - gpr_log(GPR_DEBUG, "test_no_op"); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_combiner_destroy(&exec_ctx, grpc_combiner_create(NULL)); - grpc_exec_ctx_finish(&exec_ctx); -} - -static void set_bool_to_true(grpc_exec_ctx *exec_ctx, void *value, - grpc_error *error) { - *(bool *)value = true; -} - -static void test_execute_one(void) { - gpr_log(GPR_DEBUG, "test_execute_one"); - - grpc_combiner *lock = grpc_combiner_create(NULL); - bool done = false; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_combiner_execute(&exec_ctx, lock, - grpc_closure_create(set_bool_to_true, &done), - GRPC_ERROR_NONE); - grpc_exec_ctx_flush(&exec_ctx); - GPR_ASSERT(done); - grpc_combiner_destroy(&exec_ctx, lock); - grpc_exec_ctx_finish(&exec_ctx); -} - -typedef struct { - size_t ctr; - grpc_combiner *lock; -} thd_args; - -typedef struct { - size_t *ctr; - size_t value; -} ex_args; - -static void check_one(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) { - ex_args *args = a; - GPR_ASSERT(*args->ctr == args->value - 1); - *args->ctr = args->value; - gpr_free(a); -} - -static void execute_many_loop(void *a) { - thd_args *args = a; - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - size_t n = 1; - for (size_t i = 0; i < 10; i++) { - for (size_t j = 0; j < 10000; j++) { - ex_args *c = gpr_malloc(sizeof(*c)); - c->ctr = &args->ctr; - c->value = n++; - grpc_combiner_execute(&exec_ctx, args->lock, - grpc_closure_create(check_one, c), GRPC_ERROR_NONE); - grpc_exec_ctx_flush(&exec_ctx); - } - // sleep for a little bit, to test a combiner draining and another thread - // picking it up - gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); - } - grpc_exec_ctx_finish(&exec_ctx); -} - -static void test_execute_many(void) { - gpr_log(GPR_DEBUG, "test_execute_many"); - - grpc_combiner *lock = grpc_combiner_create(NULL); - gpr_thd_id thds[100]; - thd_args ta[GPR_ARRAY_SIZE(thds)]; - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - ta[i].ctr = 0; - ta[i].lock = lock; - GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &ta[i], &options)); - } - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_join(thds[i]); - } - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_combiner_destroy(&exec_ctx, lock); - grpc_exec_ctx_finish(&exec_ctx); -} - -static bool got_in_finally = false; - -static void in_finally(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - got_in_finally = true; -} - -static void add_finally(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - grpc_combiner_execute_finally(exec_ctx, arg, - grpc_closure_create(in_finally, NULL), - GRPC_ERROR_NONE, false); -} - -static void test_execute_finally(void) { - gpr_log(GPR_DEBUG, "test_execute_finally"); - - grpc_combiner *lock = grpc_combiner_create(NULL); - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_combiner_execute(&exec_ctx, lock, grpc_closure_create(add_finally, lock), - GRPC_ERROR_NONE); - grpc_exec_ctx_flush(&exec_ctx); - GPR_ASSERT(got_in_finally); - grpc_combiner_destroy(&exec_ctx, lock); - grpc_exec_ctx_finish(&exec_ctx); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - grpc_init(); - test_no_op(); - test_execute_one(); - test_execute_finally(); - test_execute_many(); - grpc_shutdown(); - - return 0; -} diff --git a/test/core/support/mpscq_test.c b/test/core/support/mpscq_test.c deleted file mode 100644 index 491eb9148b..0000000000 --- a/test/core/support/mpscq_test.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * - * 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/lib/support/mpscq.h" - -#include - -#include -#include -#include -#include -#include -#include "test/core/util/test_config.h" - -typedef struct test_node { - gpr_mpscq_node node; - size_t i; - size_t *ctr; -} test_node; - -static test_node *new_node(size_t i, size_t *ctr) { - test_node *n = gpr_malloc(sizeof(test_node)); - n->i = i; - n->ctr = ctr; - return n; -} - -static void test_serial(void) { - gpr_log(GPR_DEBUG, "test_serial"); - gpr_mpscq q; - gpr_mpscq_init(&q); - for (size_t i = 0; i < 10000000; i++) { - gpr_mpscq_push(&q, &new_node(i, NULL)->node); - } - for (size_t i = 0; i < 10000000; i++) { - test_node *n = (test_node *)gpr_mpscq_pop(&q); - GPR_ASSERT(n); - GPR_ASSERT(n->i == i); - gpr_free(n); - } -} - -typedef struct { - size_t ctr; - gpr_mpscq *q; - gpr_event *start; -} thd_args; - -#define THREAD_ITERATIONS 100000 - -static void test_thread(void *args) { - thd_args *a = args; - gpr_event_wait(a->start, gpr_inf_future(GPR_CLOCK_REALTIME)); - for (size_t i = 1; i <= THREAD_ITERATIONS; i++) { - gpr_mpscq_push(a->q, &new_node(i, &a->ctr)->node); - } -} - -static void test_mt(void) { - gpr_log(GPR_DEBUG, "test_mt"); - gpr_event start; - gpr_event_init(&start); - gpr_thd_id thds[100]; - thd_args ta[GPR_ARRAY_SIZE(thds)]; - gpr_mpscq q; - gpr_mpscq_init(&q); - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - ta[i].ctr = 0; - ta[i].q = &q; - ta[i].start = &start; - GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); - } - size_t num_done = 0; - size_t spins = 0; - gpr_event_set(&start, (void *)1); - while (num_done != GPR_ARRAY_SIZE(thds)) { - gpr_mpscq_node *n; - while ((n = gpr_mpscq_pop(&q)) == NULL) { - spins++; - } - test_node *tn = (test_node *)n; - GPR_ASSERT(*tn->ctr == tn->i - 1); - *tn->ctr = tn->i; - if (tn->i == THREAD_ITERATIONS) num_done++; - gpr_free(tn); - } - gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, spins); - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_join(thds[i]); - } - gpr_mpscq_destroy(&q); -} - -typedef struct { - thd_args *ta; - size_t num_thds; - gpr_mu mu; - size_t num_done; - size_t spins; - gpr_mpscq *q; - gpr_event *start; -} pull_args; - -static void pull_thread(void *arg) { - pull_args *pa = arg; - gpr_event_wait(pa->start, gpr_inf_future(GPR_CLOCK_REALTIME)); - - for (;;) { - gpr_mu_lock(&pa->mu); - if (pa->num_done == pa->num_thds) { - gpr_mu_unlock(&pa->mu); - return; - } - gpr_mpscq_node *n; - while ((n = gpr_mpscq_pop(pa->q)) == NULL) { - pa->spins++; - } - test_node *tn = (test_node *)n; - GPR_ASSERT(*tn->ctr == tn->i - 1); - *tn->ctr = tn->i; - if (tn->i == THREAD_ITERATIONS) pa->num_done++; - gpr_free(tn); - gpr_mu_unlock(&pa->mu); - } -} - -static void test_mt_multipop(void) { - gpr_log(GPR_DEBUG, "test_mt_multipop"); - gpr_event start; - gpr_event_init(&start); - gpr_thd_id thds[100]; - gpr_thd_id pull_thds[100]; - thd_args ta[GPR_ARRAY_SIZE(thds)]; - gpr_mpscq q; - gpr_mpscq_init(&q); - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - ta[i].ctr = 0; - ta[i].q = &q; - ta[i].start = &start; - GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); - } - pull_args pa; - pa.ta = ta; - pa.num_thds = GPR_ARRAY_SIZE(thds); - pa.spins = 0; - pa.num_done = 0; - pa.q = &q; - pa.start = &start; - gpr_mu_init(&pa.mu); - for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { - gpr_thd_options options = gpr_thd_options_default(); - gpr_thd_options_set_joinable(&options); - GPR_ASSERT(gpr_thd_new(&pull_thds[i], pull_thread, &pa, &options)); - } - gpr_event_set(&start, (void *)1); - for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { - gpr_thd_join(pull_thds[i]); - } - gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, pa.spins); - for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { - gpr_thd_join(thds[i]); - } - gpr_mpscq_destroy(&q); -} - -int main(int argc, char **argv) { - grpc_test_init(argc, argv); - test_serial(); - test_mt(); - test_mt_multipop(); - return 0; -} diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index 6afcefca92..2894b0c66f 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -49,31 +49,32 @@ static void *tag(intptr_t x) { return (void *)x; } void verify_connectivity(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - grpc_connectivity_state *state = arg; - GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *state); + grpc_transport_op *op = arg; + GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *op->connectivity_state); GPR_ASSERT(error == GRPC_ERROR_NONE); } void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} void test_transport_op(grpc_channel *channel) { - grpc_transport_op *op; + grpc_transport_op op; grpc_channel_element *elem; grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_closure_init(&transport_op_cb, verify_connectivity, &state); + memset(&op, 0, sizeof(op)); + grpc_closure_init(&transport_op_cb, verify_connectivity, &op); - op = grpc_make_transport_op(NULL); - op->on_connectivity_state_change = &transport_op_cb; - op->connectivity_state = &state; + op.on_connectivity_state_change = &transport_op_cb; + op.connectivity_state = &state; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); - elem->filter->start_transport_op(&exec_ctx, elem, op); + elem->filter->start_transport_op(&exec_ctx, elem, &op); grpc_exec_ctx_finish(&exec_ctx); + memset(&op, 0, sizeof(op)); grpc_closure_init(&transport_op_cb, do_nothing, NULL); - op = grpc_make_transport_op(&transport_op_cb); - elem->filter->start_transport_op(&exec_ctx, elem, op); + op.on_consumed = &transport_op_cb; + elem->filter->start_transport_op(&exec_ctx, elem, &op); grpc_exec_ctx_finish(&exec_ctx); } diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 0a412dd706..06b68c3b74 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -889,7 +889,6 @@ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ src/core/lib/http/parser.h \ src/core/lib/iomgr/closure.h \ -src/core/lib/iomgr/combiner.h \ src/core/lib/iomgr/endpoint.h \ src/core/lib/iomgr/endpoint_pair.h \ src/core/lib/iomgr/error.h \ @@ -1002,7 +1001,6 @@ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ -src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1c55859d26..02590db421 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -806,7 +806,6 @@ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ src/core/lib/http/parser.h \ src/core/lib/iomgr/closure.h \ -src/core/lib/iomgr/combiner.h \ src/core/lib/iomgr/endpoint.h \ src/core/lib/iomgr/endpoint_pair.h \ src/core/lib/iomgr/error.h \ @@ -966,7 +965,6 @@ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ -src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -1187,7 +1185,6 @@ src/core/lib/profiling/timers.h \ src/core/lib/support/backoff.h \ src/core/lib/support/block_annotate.h \ src/core/lib/support/env.h \ -src/core/lib/support/mpscq.h \ src/core/lib/support/murmur_hash.h \ src/core/lib/support/percent_encoding.h \ src/core/lib/support/stack_lockfree.h \ @@ -1216,7 +1213,6 @@ src/core/lib/support/log_android.c \ src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_windows.c \ -src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/percent_encoding.c \ src/core/lib/support/slice.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 37355c7e11..db84f21968 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -252,22 +252,6 @@ "third_party": false, "type": "target" }, - { - "deps": [ - "gpr", - "gpr_test_util", - "grpc", - "grpc_test_util" - ], - "headers": [], - "language": "c", - "name": "combiner_test", - "src": [ - "test/core/iomgr/combiner_test.c" - ], - "third_party": false, - "type": "target" - }, { "deps": [ "gpr", @@ -640,20 +624,6 @@ "third_party": false, "type": "target" }, - { - "deps": [ - "gpr", - "gpr_test_util" - ], - "headers": [], - "language": "c", - "name": "gpr_mpscq_test", - "src": [ - "test/core/support/mpscq_test.c" - ], - "third_party": false, - "type": "target" - }, { "deps": [ "gpr", @@ -5765,7 +5735,6 @@ "src/core/lib/support/backoff.h", "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", - "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/percent_encoding.h", "src/core/lib/support/stack_lockfree.h", @@ -5830,8 +5799,6 @@ "src/core/lib/support/log_linux.c", "src/core/lib/support/log_posix.c", "src/core/lib/support/log_windows.c", - "src/core/lib/support/mpscq.c", - "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.c", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/percent_encoding.c", @@ -5938,7 +5905,6 @@ "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -6045,8 +6011,6 @@ "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.c", "src/core/lib/iomgr/closure.h", - "src/core/lib/iomgr/combiner.c", - "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index fcd1bafce0..51e1dff96e 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -295,27 +295,6 @@ "windows" ] }, - { - "args": [], - "ci_platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "cpu_cost": 30, - "exclude_configs": [], - "flaky": false, - "gtest": false, - "language": "c", - "name": "combiner_test", - "platforms": [ - "linux", - "mac", - "posix", - "windows" - ] - }, { "args": [], "ci_platforms": [ @@ -718,27 +697,6 @@ "windows" ] }, - { - "args": [], - "ci_platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "cpu_cost": 30, - "exclude_configs": [], - "flaky": false, - "gtest": false, - "language": "c", - "name": "gpr_mpscq_test", - "platforms": [ - "linux", - "mac", - "posix", - "windows" - ] - }, { "args": [], "ci_platforms": [ diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index 04f487689c..8f3546f7be 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -175,17 +175,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chttp2_varint_test", "vcxpr {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "combiner_test", "vcxproj\test\combiner_test\combiner_test.vcxproj", "{C237D1E4-8825-80BA-1FC3-5E147E53E96E}" - 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}") = "compression_test", "vcxproj\test\compression_test\compression_test.vcxproj", "{5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}" ProjectSection(myProperties) = preProject lib = "False" @@ -393,15 +382,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_log_test", "vcxproj\tes {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_mpscq_test", "vcxproj\test\gpr_mpscq_test\gpr_mpscq_test.vcxproj", "{B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}" - ProjectSection(myProperties) = preProject - lib = "False" - EndProjectSection - ProjectSection(ProjectDependencies) = postProject - {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}") = "gpr_percent_encoding_test", "vcxproj\test\gpr_percent_encoding_test\gpr_percent_encoding_test.vcxproj", "{8313AE17-FCFA-8110-95C7-7AF2F814D188}" ProjectSection(myProperties) = preProject lib = "False" @@ -1740,22 +1720,6 @@ Global {6B29F634-1277-74B8-47F6-78756190BA7B}.Release-DLL|Win32.Build.0 = Release|Win32 {6B29F634-1277-74B8-47F6-78756190BA7B}.Release-DLL|x64.ActiveCfg = Release|x64 {6B29F634-1277-74B8-47F6-78756190BA7B}.Release-DLL|x64.Build.0 = Release|x64 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|Win32.ActiveCfg = Debug|Win32 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|x64.ActiveCfg = Debug|x64 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|Win32.ActiveCfg = Release|Win32 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|x64.ActiveCfg = Release|x64 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|Win32.Build.0 = Debug|Win32 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|x64.Build.0 = Debug|x64 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|Win32.Build.0 = Release|Win32 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|x64.Build.0 = Release|x64 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|Win32.Build.0 = Debug|Win32 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|x64.ActiveCfg = Debug|x64 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|x64.Build.0 = Debug|x64 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|Win32.ActiveCfg = Release|Win32 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|Win32.Build.0 = Release|Win32 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|x64.ActiveCfg = Release|x64 - {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|x64.Build.0 = Release|x64 {5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Debug|Win32.ActiveCfg = Debug|Win32 {5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Debug|x64.ActiveCfg = Debug|x64 {5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Release|Win32.ActiveCfg = Release|Win32 @@ -2108,22 +2072,6 @@ Global {38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release-DLL|Win32.Build.0 = Release|Win32 {38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release-DLL|x64.ActiveCfg = Release|x64 {38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release-DLL|x64.Build.0 = Release|x64 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|Win32.ActiveCfg = Debug|Win32 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|x64.ActiveCfg = Debug|x64 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|Win32.ActiveCfg = Release|Win32 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|x64.ActiveCfg = Release|x64 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|Win32.Build.0 = Debug|Win32 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|x64.Build.0 = Debug|x64 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|Win32.Build.0 = Release|Win32 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|x64.Build.0 = Release|x64 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|Win32.Build.0 = Debug|Win32 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|x64.ActiveCfg = Debug|x64 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|x64.Build.0 = Debug|x64 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|Win32.ActiveCfg = Release|Win32 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|Win32.Build.0 = Release|Win32 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|x64.ActiveCfg = Release|x64 - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|x64.Build.0 = Release|x64 {8313AE17-FCFA-8110-95C7-7AF2F814D188}.Debug|Win32.ActiveCfg = Debug|Win32 {8313AE17-FCFA-8110-95C7-7AF2F814D188}.Debug|x64.ActiveCfg = Debug|x64 {8313AE17-FCFA-8110-95C7-7AF2F814D188}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index 6ad67dda72..519b5d9250 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -195,7 +195,6 @@ - @@ -246,8 +245,6 @@ - - diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index 95e56e9956..9eac1ec519 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -61,9 +61,6 @@ src\core\lib\support - - src\core\lib\support - src\core\lib\support @@ -284,9 +281,6 @@ src\core\lib\support - - src\core\lib\support - src\core\lib\support diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index 354351364e..1bcb263911 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -389,7 +389,6 @@ - @@ -552,8 +551,6 @@ - - diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index e284e3f7f3..7343c80cc4 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -145,9 +145,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr @@ -764,9 +761,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index ac1593464f..3241bafa6b 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -385,7 +385,6 @@ - @@ -538,8 +537,6 @@ - - diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index 9352918fb0..3df26646fc 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -130,9 +130,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr @@ -737,9 +734,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 98873ca8d7..7c120bcf02 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -315,7 +315,6 @@ - @@ -493,8 +492,6 @@ - - diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index f3d7958f7c..9cbb2ce45b 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -49,9 +49,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr @@ -716,9 +713,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index b1bdde584d..80dd6b2dcb 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -206,7 +206,6 @@ - @@ -337,8 +336,6 @@ - - diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index b78c7bfb36..8dc28d1cb9 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -97,9 +97,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr @@ -497,9 +494,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 0ea880833a..d4a85768c3 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -305,7 +305,6 @@ - @@ -461,8 +460,6 @@ - - diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 7549a9609d..fba5a02099 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -52,9 +52,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr @@ -626,9 +623,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr diff --git a/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj b/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj deleted file mode 100644 index f889d21e2d..0000000000 --- a/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {C237D1E4-8825-80BA-1FC3-5E147E53E96E} - true - $(SolutionDir)IntDir\$(MSBuildProjectName)\ - - - - v100 - - - v110 - - - v120 - - - v140 - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - combiner_test - static - Debug - static - Debug - - - combiner_test - static - Release - static - Release - - - - NotUsing - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDebug - true - None - false - - - Console - true - false - - - - - - NotUsing - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDebug - true - None - false - - - Console - true - false - - - - - - NotUsing - Level3 - MaxSpeed - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - true - true - MultiThreaded - true - None - false - - - Console - true - false - true - true - - - - - - NotUsing - Level3 - MaxSpeed - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - true - true - MultiThreaded - true - None - false - - - Console - true - false - true - true - - - - - - - - - - {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} - - - {29D16885-7228-4C31-81ED-5F9187C7F2A9} - - - {EAB0A629-17A9-44DB-B5FF-E91A721FE037} - - - {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} - - - - - - - - - - - - - - - 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}. - - - - - - - - - diff --git a/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters b/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters deleted file mode 100644 index e8ebb09898..0000000000 --- a/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters +++ /dev/null @@ -1,21 +0,0 @@ - - - - - test\core\iomgr - - - - - - {82bca2af-d499-b405-fd05-4d345372496c} - - - {c32d8e20-b719-532d-ba23-bd9d523fac15} - - - {b4fa8ca1-e6c7-dec5-6d62-8a62396825c6} - - - - diff --git a/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj b/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj deleted file mode 100644 index 01342868b0..0000000000 --- a/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6} - true - $(SolutionDir)IntDir\$(MSBuildProjectName)\ - - - - v100 - - - v110 - - - v120 - - - v140 - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - gpr_mpscq_test - static - Debug - static - Debug - - - gpr_mpscq_test - static - Release - static - Release - - - - NotUsing - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDebug - true - None - false - - - Console - true - false - - - - - - NotUsing - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - MultiThreadedDebug - true - None - false - - - Console - true - false - - - - - - NotUsing - Level3 - MaxSpeed - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - true - true - MultiThreaded - true - None - false - - - Console - true - false - true - true - - - - - - NotUsing - Level3 - MaxSpeed - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - true - true - MultiThreaded - true - None - false - - - Console - true - false - true - true - - - - - - - - - - {EAB0A629-17A9-44DB-B5FF-E91A721FE037} - - - {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} - - - - - - - - - - - - - - - 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}. - - - - - - - - - diff --git a/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters b/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters deleted file mode 100644 index 9cceb9f3e2..0000000000 --- a/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters +++ /dev/null @@ -1,21 +0,0 @@ - - - - - test\core\support - - - - - - {e82fb80c-10ba-2959-55d6-8653715f1e4f} - - - {32120233-25e6-f3e4-f828-c6408d47ec04} - - - {aa3a22bc-229a-c00a-dd4a-924c818c6a49} - - - - -- cgit v1.2.3 From 57726ca5a9c08ba17c882a798b93e03d333edd9f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 12 Sep 2016 11:59:45 -0700 Subject: Revert "Revert "Grand unified closures"" --- BUILD | 16 + CMakeLists.txt | 6 + Makefile | 79 +++ binding.gyp | 2 + build.yaml | 24 + config.m4 | 2 + gRPC-Core.podspec | 6 + grpc.gemspec | 4 + include/grpc/impl/codegen/atm.h | 3 + include/grpc/impl/codegen/atm_gcc_atomic.h | 2 + include/grpc/impl/codegen/atm_gcc_sync.h | 8 + include/grpc/impl/codegen/atm_windows.h | 4 + package.xml | 4 + src/core/ext/client_config/client_channel.c | 14 +- src/core/ext/client_config/subchannel.c | 18 +- .../transport/chttp2/transport/chttp2_transport.c | 766 +++++++++------------ src/core/ext/transport/chttp2/transport/internal.h | 54 +- src/core/ext/transport/chttp2/transport/parsing.c | 12 +- .../ext/transport/chttp2/transport/stream_lists.c | 9 +- src/core/ext/transport/chttp2/transport/writing.c | 21 +- src/core/lib/channel/channel_stack.c | 23 +- src/core/lib/channel/compress_filter.c | 14 +- src/core/lib/iomgr/closure.c | 4 + src/core/lib/iomgr/closure.h | 18 +- src/core/lib/iomgr/combiner.c | 293 ++++++++ src/core/lib/iomgr/combiner.h | 71 ++ src/core/lib/iomgr/error.c | 2 +- src/core/lib/iomgr/ev_epoll_linux.c | 4 + src/core/lib/iomgr/exec_ctx.h | 6 +- src/core/lib/iomgr/tcp_posix.c | 17 + src/core/lib/iomgr/workqueue.h | 4 - src/core/lib/iomgr/workqueue_posix.c | 97 ++- src/core/lib/iomgr/workqueue_posix.h | 9 +- src/core/lib/iomgr/workqueue_windows.c | 2 - .../lib/security/transport/client_auth_filter.c | 5 + src/core/lib/security/transport/secure_endpoint.c | 5 + .../lib/security/transport/server_auth_filter.c | 27 +- src/core/lib/support/mpscq.c | 83 +++ src/core/lib/support/mpscq.h | 65 ++ src/core/lib/surface/call.c | 63 +- src/core/lib/surface/channel.c | 7 +- src/core/lib/surface/channel_ping.c | 11 +- src/core/lib/surface/init.c | 2 + src/core/lib/surface/lame_client.c | 6 +- src/core/lib/surface/server.c | 69 +- src/core/lib/transport/transport.c | 27 + src/core/lib/transport/transport.h | 21 + src/python/grpcio/grpc_core_dependencies.py | 2 + test/core/iomgr/combiner_test.c | 164 +++++ test/core/support/mpscq_test.c | 206 ++++++ test/core/surface/lame_client_test.c | 21 +- tools/doxygen/Doxyfile.c++.internal | 2 + tools/doxygen/Doxyfile.core.internal | 4 + tools/run_tests/sources_and_headers.json | 36 + tools/run_tests/tests.json | 42 ++ vsprojects/buildtests_c.sln | 52 ++ vsprojects/vcxproj/gpr/gpr.vcxproj | 3 + vsprojects/vcxproj/gpr/gpr.vcxproj.filters | 6 + vsprojects/vcxproj/grpc++/grpc++.vcxproj | 3 + vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters | 6 + .../grpc++_unsecure/grpc++_unsecure.vcxproj | 3 + .../grpc++_unsecure.vcxproj.filters | 6 + vsprojects/vcxproj/grpc/grpc.vcxproj | 3 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 6 + .../vcxproj/grpc_test_util/grpc_test_util.vcxproj | 3 + .../grpc_test_util/grpc_test_util.vcxproj.filters | 6 + .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 3 + .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 + .../test/combiner_test/combiner_test.vcxproj | 199 ++++++ .../combiner_test/combiner_test.vcxproj.filters | 21 + .../test/gpr_mpscq_test/gpr_mpscq_test.vcxproj | 193 ++++++ .../gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters | 21 + 72 files changed, 2366 insertions(+), 660 deletions(-) create mode 100644 src/core/lib/iomgr/combiner.c create mode 100644 src/core/lib/iomgr/combiner.h create mode 100644 src/core/lib/support/mpscq.c create mode 100644 src/core/lib/support/mpscq.h create mode 100644 test/core/iomgr/combiner_test.c create mode 100644 test/core/support/mpscq_test.c create mode 100644 vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj create mode 100644 vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters create mode 100644 vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj create mode 100644 vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index ee41d1ab21..7db1c1d2f6 100644 --- a/BUILD +++ b/BUILD @@ -51,6 +51,7 @@ cc_library( "src/core/lib/support/backoff.h", "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", + "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/percent_encoding.h", "src/core/lib/support/stack_lockfree.h", @@ -79,6 +80,7 @@ cc_library( "src/core/lib/support/log_linux.c", "src/core/lib/support/log_posix.c", "src/core/lib/support/log_windows.c", + "src/core/lib/support/mpscq.c", "src/core/lib/support/murmur_hash.c", "src/core/lib/support/percent_encoding.c", "src/core/lib/support/slice.c", @@ -179,6 +181,7 @@ cc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -334,6 +337,7 @@ cc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -574,6 +578,7 @@ cc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -715,6 +720,7 @@ cc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -926,6 +932,7 @@ cc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -1058,6 +1065,7 @@ cc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -1273,6 +1281,7 @@ cc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -1385,6 +1394,7 @@ cc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -1683,6 +1693,7 @@ cc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -1790,6 +1801,7 @@ cc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -2068,6 +2080,7 @@ objc_library( "src/core/lib/support/log_linux.c", "src/core/lib/support/log_posix.c", "src/core/lib/support/log_windows.c", + "src/core/lib/support/mpscq.c", "src/core/lib/support/murmur_hash.c", "src/core/lib/support/percent_encoding.c", "src/core/lib/support/slice.c", @@ -2142,6 +2155,7 @@ objc_library( "src/core/lib/support/backoff.h", "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", + "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/percent_encoding.h", "src/core/lib/support/stack_lockfree.h", @@ -2180,6 +2194,7 @@ objc_library( "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", "src/core/lib/iomgr/closure.c", + "src/core/lib/iomgr/combiner.c", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint_pair_posix.c", "src/core/lib/iomgr/endpoint_pair_windows.c", @@ -2399,6 +2414,7 @@ objc_library( "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 05aa323ca9..915c406c9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,7 @@ add_library(gpr src/core/lib/support/log_linux.c src/core/lib/support/log_posix.c src/core/lib/support/log_windows.c + src/core/lib/support/mpscq.c src/core/lib/support/murmur_hash.c src/core/lib/support/percent_encoding.c src/core/lib/support/slice.c @@ -307,6 +308,7 @@ add_library(grpc src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c + src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -565,6 +567,7 @@ add_library(grpc_cronet src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c + src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -796,6 +799,7 @@ add_library(grpc_unsecure src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c + src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -1053,6 +1057,7 @@ add_library(grpc++ src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c + src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c @@ -1410,6 +1415,7 @@ add_library(grpc++_unsecure src/core/lib/http/httpcli.c src/core/lib/http/parser.c src/core/lib/iomgr/closure.c + src/core/lib/iomgr/combiner.c src/core/lib/iomgr/endpoint.c src/core/lib/iomgr/endpoint_pair_posix.c src/core/lib/iomgr/endpoint_pair_windows.c diff --git a/Makefile b/Makefile index e454ad6cd7..219c0e4a43 100644 --- a/Makefile +++ b/Makefile @@ -915,6 +915,7 @@ chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test client_fuzzer: $(BINDIR)/$(CONFIG)/client_fuzzer +combiner_test: $(BINDIR)/$(CONFIG)/combiner_test compression_test: $(BINDIR)/$(CONFIG)/compression_test concurrent_connectivity_test: $(BINDIR)/$(CONFIG)/concurrent_connectivity_test dns_resolver_connectivity_test: $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test @@ -940,6 +941,7 @@ gpr_env_test: $(BINDIR)/$(CONFIG)/gpr_env_test gpr_histogram_test: $(BINDIR)/$(CONFIG)/gpr_histogram_test gpr_host_port_test: $(BINDIR)/$(CONFIG)/gpr_host_port_test gpr_log_test: $(BINDIR)/$(CONFIG)/gpr_log_test +gpr_mpscq_test: $(BINDIR)/$(CONFIG)/gpr_mpscq_test gpr_percent_encoding_test: $(BINDIR)/$(CONFIG)/gpr_percent_encoding_test gpr_slice_buffer_test: $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test gpr_slice_test: $(BINDIR)/$(CONFIG)/gpr_slice_test @@ -1240,6 +1242,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test \ $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \ $(BINDIR)/$(CONFIG)/chttp2_varint_test \ + $(BINDIR)/$(CONFIG)/combiner_test \ $(BINDIR)/$(CONFIG)/compression_test \ $(BINDIR)/$(CONFIG)/concurrent_connectivity_test \ $(BINDIR)/$(CONFIG)/dns_resolver_connectivity_test \ @@ -1262,6 +1265,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/gpr_histogram_test \ $(BINDIR)/$(CONFIG)/gpr_host_port_test \ $(BINDIR)/$(CONFIG)/gpr_log_test \ + $(BINDIR)/$(CONFIG)/gpr_mpscq_test \ $(BINDIR)/$(CONFIG)/gpr_percent_encoding_test \ $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test \ $(BINDIR)/$(CONFIG)/gpr_slice_test \ @@ -1557,6 +1561,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_stream_map_test || ( echo test chttp2_stream_map_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_varint_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_varint_test || ( echo test chttp2_varint_test failed ; exit 1 ) + $(E) "[RUN] Testing combiner_test" + $(Q) $(BINDIR)/$(CONFIG)/combiner_test || ( echo test combiner_test failed ; exit 1 ) $(E) "[RUN] Testing compression_test" $(Q) $(BINDIR)/$(CONFIG)/compression_test || ( echo test compression_test failed ; exit 1 ) $(E) "[RUN] Testing concurrent_connectivity_test" @@ -1597,6 +1603,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/gpr_host_port_test || ( echo test gpr_host_port_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_mpscq_test" + $(Q) $(BINDIR)/$(CONFIG)/gpr_mpscq_test || ( echo test gpr_mpscq_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_percent_encoding_test" $(Q) $(BINDIR)/$(CONFIG)/gpr_percent_encoding_test || ( echo test gpr_percent_encoding_test failed ; exit 1 ) $(E) "[RUN] Testing gpr_slice_buffer_test" @@ -2378,6 +2386,7 @@ LIBGPR_SRC = \ src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_windows.c \ + src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/percent_encoding.c \ src/core/lib/support/slice.c \ @@ -2528,6 +2537,7 @@ LIBGRPC_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -2804,6 +2814,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -3069,6 +3080,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -3262,6 +3274,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -3602,6 +3615,7 @@ LIBGRPC++_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -4237,6 +4251,7 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -7413,6 +7428,38 @@ endif endif +COMBINER_TEST_SRC = \ + test/core/iomgr/combiner_test.c \ + +COMBINER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(COMBINER_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/combiner_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/combiner_test: $(COMBINER_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) $(COMBINER_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)/combiner_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/combiner_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_combiner_test: $(COMBINER_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(COMBINER_TEST_OBJS:.o=.dep) +endif +endif + + COMPRESSION_TEST_SRC = \ test/core/compression/compression_test.c \ @@ -8213,6 +8260,38 @@ endif endif +GPR_MPSCQ_TEST_SRC = \ + test/core/support/mpscq_test.c \ + +GPR_MPSCQ_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GPR_MPSCQ_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/gpr_mpscq_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/gpr_mpscq_test: $(GPR_MPSCQ_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(GPR_MPSCQ_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gpr_mpscq_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/support/mpscq_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_gpr_mpscq_test: $(GPR_MPSCQ_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(GPR_MPSCQ_TEST_OBJS:.o=.dep) +endif +endif + + GPR_PERCENT_ENCODING_TEST_SRC = \ test/core/support/percent_encoding_test.c \ diff --git a/binding.gyp b/binding.gyp index 7cc8a58c01..b4f182c4b7 100644 --- a/binding.gyp +++ b/binding.gyp @@ -515,6 +515,7 @@ 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_windows.c', + 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/percent_encoding.c', 'src/core/lib/support/slice.c', @@ -579,6 +580,7 @@ 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', 'src/core/lib/iomgr/closure.c', + 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', diff --git a/build.yaml b/build.yaml index 6eb23d6fb7..ee459ea3f5 100644 --- a/build.yaml +++ b/build.yaml @@ -82,6 +82,7 @@ filegroups: - src/core/lib/support/backoff.h - src/core/lib/support/block_annotate.h - src/core/lib/support/env.h + - src/core/lib/support/mpscq.h - src/core/lib/support/murmur_hash.h - src/core/lib/support/percent_encoding.h - src/core/lib/support/stack_lockfree.h @@ -111,6 +112,7 @@ filegroups: - src/core/lib/support/log_linux.c - src/core/lib/support/log_posix.c - src/core/lib/support/log_windows.c + - src/core/lib/support/mpscq.c - src/core/lib/support/murmur_hash.c - src/core/lib/support/percent_encoding.c - src/core/lib/support/slice.c @@ -181,6 +183,7 @@ filegroups: - src/core/lib/http/httpcli.h - src/core/lib/http/parser.h - src/core/lib/iomgr/closure.h + - src/core/lib/iomgr/combiner.h - src/core/lib/iomgr/endpoint.h - src/core/lib/iomgr/endpoint_pair.h - src/core/lib/iomgr/error.h @@ -261,6 +264,7 @@ filegroups: - src/core/lib/http/httpcli.c - src/core/lib/http/parser.c - src/core/lib/iomgr/closure.c + - src/core/lib/iomgr/combiner.c - src/core/lib/iomgr/endpoint.c - src/core/lib/iomgr/endpoint_pair_posix.c - src/core/lib/iomgr/endpoint_pair_windows.c @@ -1408,6 +1412,17 @@ targets: - test/core/end2end/fuzzers/client_fuzzer_corpus dict: test/core/end2end/fuzzers/hpack.dictionary maxlen: 2048 +- name: combiner_test + cpu_cost: 30 + build: test + language: c + src: + - test/core/iomgr/combiner_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr - name: compression_test build: test language: c @@ -1665,6 +1680,15 @@ targets: deps: - gpr_test_util - gpr +- name: gpr_mpscq_test + cpu_cost: 30 + build: test + language: c + src: + - test/core/support/mpscq_test.c + deps: + - gpr_test_util + - gpr - name: gpr_percent_encoding_test build: test language: c diff --git a/config.m4 b/config.m4 index 5384585dd6..5947306c39 100644 --- a/config.m4 +++ b/config.m4 @@ -56,6 +56,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_windows.c \ + src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/percent_encoding.c \ src/core/lib/support/slice.c \ @@ -98,6 +99,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ + src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index deffa1653e..895e39b2a7 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -200,6 +200,7 @@ Pod::Spec.new do |s| 'src/core/lib/support/backoff.h', 'src/core/lib/support/block_annotate.h', 'src/core/lib/support/env.h', + 'src/core/lib/support/mpscq.h', 'src/core/lib/support/murmur_hash.h', 'src/core/lib/support/percent_encoding.h', 'src/core/lib/support/stack_lockfree.h', @@ -228,6 +229,7 @@ Pod::Spec.new do |s| 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_windows.c', + 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/percent_encoding.c', 'src/core/lib/support/slice.c', @@ -270,6 +272,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', 'src/core/lib/iomgr/closure.h', + 'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/error.h', @@ -429,6 +432,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', 'src/core/lib/iomgr/closure.c', + 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', @@ -608,6 +612,7 @@ Pod::Spec.new do |s| 'src/core/lib/support/backoff.h', 'src/core/lib/support/block_annotate.h', 'src/core/lib/support/env.h', + 'src/core/lib/support/mpscq.h', 'src/core/lib/support/murmur_hash.h', 'src/core/lib/support/percent_encoding.h', 'src/core/lib/support/stack_lockfree.h', @@ -632,6 +637,7 @@ Pod::Spec.new do |s| 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', 'src/core/lib/iomgr/closure.h', + 'src/core/lib/iomgr/combiner.h', 'src/core/lib/iomgr/endpoint.h', 'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/error.h', diff --git a/grpc.gemspec b/grpc.gemspec index f249006065..2a27492cfe 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -90,6 +90,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/support/backoff.h ) s.files += %w( src/core/lib/support/block_annotate.h ) s.files += %w( src/core/lib/support/env.h ) + s.files += %w( src/core/lib/support/mpscq.h ) s.files += %w( src/core/lib/support/murmur_hash.h ) s.files += %w( src/core/lib/support/percent_encoding.h ) s.files += %w( src/core/lib/support/stack_lockfree.h ) @@ -118,6 +119,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/support/log_linux.c ) s.files += %w( src/core/lib/support/log_posix.c ) s.files += %w( src/core/lib/support/log_windows.c ) + s.files += %w( src/core/lib/support/mpscq.c ) s.files += %w( src/core/lib/support/murmur_hash.c ) s.files += %w( src/core/lib/support/percent_encoding.c ) s.files += %w( src/core/lib/support/slice.c ) @@ -190,6 +192,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/http/httpcli.h ) s.files += %w( src/core/lib/http/parser.h ) s.files += %w( src/core/lib/iomgr/closure.h ) + s.files += %w( src/core/lib/iomgr/combiner.h ) s.files += %w( src/core/lib/iomgr/endpoint.h ) s.files += %w( src/core/lib/iomgr/endpoint_pair.h ) s.files += %w( src/core/lib/iomgr/error.h ) @@ -349,6 +352,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/http/httpcli.c ) s.files += %w( src/core/lib/http/parser.c ) s.files += %w( src/core/lib/iomgr/closure.c ) + s.files += %w( src/core/lib/iomgr/combiner.c ) s.files += %w( src/core/lib/iomgr/endpoint.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_posix.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c ) diff --git a/include/grpc/impl/codegen/atm.h b/include/grpc/impl/codegen/atm.h index 5589d5d411..ae00fb0f16 100644 --- a/include/grpc/impl/codegen/atm.h +++ b/include/grpc/impl/codegen/atm.h @@ -75,6 +75,9 @@ int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n); int gpr_atm_acq_cas(gpr_atm *p, gpr_atm o, gpr_atm n); int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n); + + // Atomically, set *p=n and return the old value of *p + gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n); */ #include diff --git a/include/grpc/impl/codegen/atm_gcc_atomic.h b/include/grpc/impl/codegen/atm_gcc_atomic.h index 8caf7edbde..7d4ae98cf7 100644 --- a/include/grpc/impl/codegen/atm_gcc_atomic.h +++ b/include/grpc/impl/codegen/atm_gcc_atomic.h @@ -69,4 +69,6 @@ static __inline int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { __ATOMIC_RELAXED); } +#define gpr_atm_full_xchg(p, n) __atomic_exchange_n((p), (n), __ATOMIC_ACQ_REL) + #endif /* GRPC_IMPL_CODEGEN_ATM_GCC_ATOMIC_H */ diff --git a/include/grpc/impl/codegen/atm_gcc_sync.h b/include/grpc/impl/codegen/atm_gcc_sync.h index 915b09fb0c..9aa2b43189 100644 --- a/include/grpc/impl/codegen/atm_gcc_sync.h +++ b/include/grpc/impl/codegen/atm_gcc_sync.h @@ -84,4 +84,12 @@ static __inline void gpr_atm_no_barrier_store(gpr_atm *p, gpr_atm value) { #define gpr_atm_acq_cas(p, o, n) (__sync_bool_compare_and_swap((p), (o), (n))) #define gpr_atm_rel_cas(p, o, n) gpr_atm_acq_cas((p), (o), (n)) +static __inline gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n) { + gpr_atm cur; + do { + cur = gpr_atm_acq_load(p); + } while (!gpr_atm_rel_cas(p, cur, n)); + return cur; +} + #endif /* GRPC_IMPL_CODEGEN_ATM_GCC_SYNC_H */ diff --git a/include/grpc/impl/codegen/atm_windows.h b/include/grpc/impl/codegen/atm_windows.h index d5fa8c0f62..0ab70b95c4 100644 --- a/include/grpc/impl/codegen/atm_windows.h +++ b/include/grpc/impl/codegen/atm_windows.h @@ -122,4 +122,8 @@ static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm *p, gpr_atm delta) { return old; } +static __inline gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n) { + return (gpr_atm)InterlockedExchangePointer((PVOID *)p, (PVOID)n); +} + #endif /* GRPC_IMPL_CODEGEN_ATM_WINDOWS_H */ diff --git a/package.xml b/package.xml index 93210ee47b..4f596e0e8f 100644 --- a/package.xml +++ b/package.xml @@ -97,6 +97,7 @@ + @@ -125,6 +126,7 @@ + @@ -197,6 +199,7 @@ + @@ -356,6 +359,7 @@ + diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c index 61e012578e..be333f4e0d 100644 --- a/src/core/ext/client_config/client_channel.c +++ b/src/core/ext/client_config/client_channel.c @@ -387,7 +387,7 @@ typedef struct client_channel_call_data { grpc_connected_subchannel *connected_subchannel; grpc_polling_entity *pollent; - grpc_transport_stream_op *waiting_ops; + grpc_transport_stream_op **waiting_ops; size_t waiting_ops_count; size_t waiting_ops_capacity; @@ -404,7 +404,7 @@ static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) { gpr_realloc(calld->waiting_ops, calld->waiting_ops_capacity * sizeof(*calld->waiting_ops)); } - calld->waiting_ops[calld->waiting_ops_count++] = *op; + calld->waiting_ops[calld->waiting_ops_count++] = op; GPR_TIMER_END("add_waiting_locked", 0); } @@ -413,14 +413,14 @@ static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld, size_t i; for (i = 0; i < calld->waiting_ops_count; i++) { grpc_transport_stream_op_finish_with_failure( - exec_ctx, &calld->waiting_ops[i], GRPC_ERROR_REF(error)); + exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error)); } calld->waiting_ops_count = 0; GRPC_ERROR_UNREF(error); } typedef struct { - grpc_transport_stream_op *ops; + grpc_transport_stream_op **ops; size_t nops; grpc_subchannel_call *call; } retry_ops_args; @@ -429,7 +429,7 @@ static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) { retry_ops_args *a = args; size_t i; for (i = 0; i < a->nops; i++) { - grpc_subchannel_call_process_op(exec_ctx, a->call, &a->ops[i]); + grpc_subchannel_call_process_op(exec_ctx, a->call, a->ops[i]); } GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops"); gpr_free(a->ops); @@ -437,6 +437,10 @@ static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) { } static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) { + if (calld->waiting_ops_count == 0) { + return; + } + retry_ops_args *a = gpr_malloc(sizeof(*a)); a->ops = calld->waiting_ops; a->nops = calld->waiting_ops_count; diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c index df35904b85..2c4364b259 100644 --- a/src/core/ext/client_config/subchannel.c +++ b/src/core/ext/client_config/subchannel.c @@ -504,14 +504,13 @@ static void connected_subchannel_state_op(grpc_exec_ctx *exec_ctx, grpc_pollset_set *interested_parties, grpc_connectivity_state *state, grpc_closure *closure) { - grpc_transport_op op; + grpc_transport_op *op = grpc_make_transport_op(NULL); grpc_channel_element *elem; - memset(&op, 0, sizeof(op)); - op.connectivity_state = state; - op.on_connectivity_state_change = closure; - op.bind_pollset_set = interested_parties; + op->connectivity_state = state; + op->on_connectivity_state_change = closure; + op->bind_pollset_set = interested_parties; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); - elem->filter->start_transport_op(exec_ctx, elem, &op); + elem->filter->start_transport_op(exec_ctx, elem, op); } void grpc_connected_subchannel_notify_on_state_change( @@ -525,12 +524,11 @@ void grpc_connected_subchannel_notify_on_state_change( void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, grpc_closure *closure) { - grpc_transport_op op; + grpc_transport_op *op = grpc_make_transport_op(NULL); grpc_channel_element *elem; - memset(&op, 0, sizeof(op)); - op.send_ping = closure; + op->send_ping = closure; elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(con), 0); - elem->filter->start_transport_op(exec_ctx, elem, &op); + elem->filter->start_transport_op(exec_ctx, elem, op); } static void publish_transport_locked(grpc_exec_ctx *exec_ctx, diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 00999e3b94..53da0e5d70 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -89,13 +89,20 @@ static const grpc_transport_vtable vtable; static void writing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void reading_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); static void parsing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error); -static void initiate_writing(grpc_exec_ctx *exec_ctx, void *t, - grpc_error *error); +static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void initiate_writing_locked(grpc_exec_ctx *exec_ctx, void *t, + grpc_error *error); +static void initiate_read_flush_locked(grpc_exec_ctx *exec_ctx, void *t, + grpc_error *error); +static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *t, + grpc_error *error); static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, grpc_error *error, - const char *reason); + grpc_chttp2_transport *t, grpc_error *error); /** Set a transport level setting, and push it to our peer */ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, @@ -105,11 +112,6 @@ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error); -/** Perform a transport_op */ -static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, void *transport_op); - /** Cancel a stream: coming from the transport API */ static void cancel_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, @@ -121,22 +123,10 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_global *stream_global, grpc_error *error); -/** Add endpoint from this transport to pollset */ -static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_ignored, void *pollset); -static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_ignored, - void *pollset_set); - /** Start new streams that have been created if we can */ static void maybe_start_some_streams( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global); -static void finish_global_actions(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t); - static void connectivity_state_set( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_connectivity_state state, grpc_error *error, const char *reason); @@ -149,14 +139,16 @@ static void incoming_byte_stream_update_flow_control( grpc_chttp2_stream_global *stream_global, size_t max_size_hint, size_t have_already); static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *byte_stream); + void *byte_stream, + grpc_error *error_ignored); static void fail_pending_writes(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global, grpc_error *error); +static void set_write_state(grpc_chttp2_transport *t, + grpc_chttp2_write_state state, const char *reason); + /******************************************************************************* * CONSTRUCTION/DESTRUCTION/REFCOUNTING */ @@ -165,9 +157,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { size_t i; - gpr_mu_lock(&t->executor.mu); - - GPR_ASSERT(t->ep == NULL); + grpc_endpoint_destroy(exec_ctx, t->ep); gpr_slice_buffer_destroy(&t->global.qbuf); @@ -191,8 +181,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_map_destroy(&t->new_stream_map); grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker); - gpr_mu_unlock(&t->executor.mu); - gpr_mu_destroy(&t->executor.mu); + grpc_combiner_destroy(exec_ctx, t->executor.combiner); /* callback remaining pings: they're not allowed to call into the transpot, and maybe they hold resources that need to be freed */ @@ -250,12 +239,13 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, memset(t, 0, sizeof(*t)); t->base.vtable = &vtable; + t->executor.write_state = GRPC_CHTTP2_WRITES_CORKED; t->ep = ep; - /* one ref is for destroy, the other for when ep becomes NULL */ - gpr_ref_init(&t->refs, 2); + /* one ref is for destroy */ + gpr_ref_init(&t->refs, 1); /* ref is dropped at transport close() */ gpr_ref_init(&t->shutdown_ep_refs, 1); - gpr_mu_init(&t->executor.mu); + t->executor.combiner = grpc_combiner_create(grpc_endpoint_get_workqueue(ep)); t->peer_string = grpc_endpoint_get_peer(ep); t->endpoint_reading = 1; t->global.next_stream_id = is_client ? 1 : 2; @@ -281,23 +271,22 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor); grpc_closure_init(&t->writing_action, writing_action, t); grpc_closure_init(&t->reading_action, reading_action, t); + grpc_closure_init(&t->reading_action_locked, reading_action_locked, t); grpc_closure_init(&t->parsing_action, parsing_action, t); - grpc_closure_init(&t->initiate_writing, initiate_writing, t); + grpc_closure_init(&t->post_parse_locked, post_parse_locked, t); + grpc_closure_init(&t->initiate_writing, initiate_writing_locked, t); + grpc_closure_init(&t->terminate_writing, terminate_writing_with_lock, t); + grpc_closure_init(&t->initiate_read_flush_locked, initiate_read_flush_locked, + t); + grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, + &t->writing); gpr_slice_buffer_init(&t->parsing.qbuf); grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser); - grpc_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, - &t->writing); gpr_slice_buffer_init(&t->read_buffer); - if (is_client) { - gpr_slice_buffer_add( - &t->global.qbuf, - gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)); - grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "initial_write"); - } /* 8 is a random stab in the dark as to a good initial size: it's small enough that it shouldn't waste memory for infrequently used connections, yet large enough that the exponential growth should happen nicely when it's @@ -320,6 +309,13 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, t->global.force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; t->global.sent_local_settings = 0; + if (is_client) { + gpr_slice_buffer_add( + &t->writing.outbuf, + gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING)); + grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "initial_write"); + } + /* configure http2 the way we like it */ if (is_client) { push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0); @@ -424,47 +420,39 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, } } } + + set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "uncork"); + grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "init"); } -static void destroy_transport_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_ignored, - void *arg_ignored) { +static void destroy_transport_locked(grpc_exec_ctx *exec_ctx, void *tp, + grpc_error *error) { + grpc_chttp2_transport *t = tp; t->destroying = 1; drop_connection(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed")); + UNREF_TRANSPORT(exec_ctx, t, "destroy"); } static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; - grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, destroy_transport_locked, - NULL, 0); - UNREF_TRANSPORT(exec_ctx, t, "destroy"); + grpc_combiner_execute(exec_ctx, t->executor.combiner, + grpc_closure_create(destroy_transport_locked, t), + GRPC_ERROR_NONE); } /** block grpc_endpoint_shutdown being called until a paired allow_endpoint_shutdown is made */ static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) { - GPR_ASSERT(t->ep); gpr_ref(&t->shutdown_ep_refs); } static void allow_endpoint_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { if (gpr_unref(&t->shutdown_ep_refs)) { - if (t->ep) { - grpc_endpoint_shutdown(exec_ctx, t->ep); - } + grpc_endpoint_shutdown(exec_ctx, t->ep); } } -static void destroy_endpoint(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - grpc_endpoint_destroy(exec_ctx, t->ep); - t->ep = NULL; - /* safe because we'll still have the ref for write */ - UNREF_TRANSPORT(exec_ctx, t, "disconnect"); -} - static void close_transport_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { @@ -475,9 +463,7 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx, t->closed = 1; connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error), "close_transport"); - if (t->ep) { - allow_endpoint_shutdown_locked(exec_ctx, t); - } + allow_endpoint_shutdown_locked(exec_ctx, t); /* flush writable stream list to avoid dangling references */ grpc_chttp2_stream_global *stream_global; @@ -511,21 +497,23 @@ void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, } #endif -static void finish_init_stream_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *arg_ignored) { - grpc_chttp2_register_stream(t, s); +static void finish_init_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, + grpc_error *error) { + grpc_chttp2_stream *s = sp; + grpc_chttp2_register_stream(s->t, s); + GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "init"); } static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_stream_refcount *refcount, const void *server_data) { + GPR_TIMER_BEGIN("init_stream", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; memset(s, 0, sizeof(*s)); + s->t = t; s->refcount = refcount; /* We reserve one 'active stream' that's dropped when the stream is read-closed. The others are for incoming_byte_streams that are actively @@ -560,16 +548,21 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, s->global.in_stream_map = true; } - grpc_chttp2_run_with_global_lock(exec_ctx, t, s, finish_init_stream_locked, - NULL, 0); + grpc_closure_init(&s->init_stream, finish_init_stream_locked, s); + GRPC_CHTTP2_STREAM_REF(&s->global, "init"); + grpc_combiner_execute(exec_ctx, t->executor.combiner, &s->init_stream, + GRPC_ERROR_NONE); + + GPR_TIMER_END("init_stream", 0); return 0; } -static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, void *arg) { +static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, + grpc_error *error) { grpc_byte_stream *bs; + grpc_chttp2_stream *s = sp; + grpc_chttp2_transport *t = s->t; GPR_TIMER_BEGIN("destroy_stream", 0); @@ -588,7 +581,7 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, while ( (bs = grpc_chttp2_incoming_frame_queue_pop(&s->global.incoming_frames))) { - incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global, @@ -625,16 +618,20 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, GPR_TIMER_END("destroy_stream", 0); - gpr_free(arg); + gpr_free(s->destroy_stream_arg); } static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, void *and_free_memory) { + GPR_TIMER_BEGIN("destroy_stream", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - grpc_chttp2_run_with_global_lock(exec_ctx, t, s, destroy_stream_locked, - and_free_memory, 0); + s->destroy_stream_arg = and_free_memory; + grpc_closure_init(&s->destroy_stream, destroy_stream_locked, s); + grpc_combiner_execute(exec_ctx, t->executor.combiner, &s->destroy_stream, + GRPC_ERROR_NONE); + GPR_TIMER_END("destroy_stream", 0); } grpc_chttp2_stream_parsing *grpc_chttp2_parsing_lookup_stream( @@ -665,12 +662,10 @@ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream( static const char *write_state_name(grpc_chttp2_write_state state) { switch (state) { + case GRPC_CHTTP2_WRITES_CORKED: + return "CORKED"; case GRPC_CHTTP2_WRITING_INACTIVE: return "INACTIVE"; - case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: - return "REQUESTED[p=0]"; - case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: - return "REQUESTED[p=1]"; case GRPC_CHTTP2_WRITE_SCHEDULED: return "SCHEDULED"; case GRPC_CHTTP2_WRITING: @@ -693,120 +688,18 @@ static void set_write_state(grpc_chttp2_transport *t, t->executor.write_state = state; } -static void finish_global_actions(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { - grpc_chttp2_executor_action_header *hdr; - grpc_chttp2_executor_action_header *next; - - GPR_TIMER_BEGIN("finish_global_actions", 0); - - for (;;) { - check_read_ops(exec_ctx, &t->global); - - gpr_mu_lock(&t->executor.mu); - if (t->executor.pending_actions_head != NULL) { - hdr = t->executor.pending_actions_head; - t->executor.pending_actions_head = t->executor.pending_actions_tail = - NULL; - gpr_mu_unlock(&t->executor.mu); - while (hdr != NULL) { - GPR_TIMER_BEGIN("chttp2:locked_action", 0); - hdr->action(exec_ctx, t, hdr->stream, hdr->arg); - GPR_TIMER_END("chttp2:locked_action", 0); - next = hdr->next; - gpr_free(hdr); - UNREF_TRANSPORT(exec_ctx, t, "pending_action"); - hdr = next; - } - continue; - } else { - t->executor.global_active = false; - switch (t->executor.write_state) { - case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: - set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "unlocking"); - REF_TRANSPORT(t, "initiate_writing"); - gpr_mu_unlock(&t->executor.mu); - grpc_exec_ctx_sched( - exec_ctx, &t->initiate_writing, GRPC_ERROR_NONE, - t->ep != NULL ? grpc_endpoint_get_workqueue(t->ep) : NULL); - break; - case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: - start_writing(exec_ctx, t); - gpr_mu_unlock(&t->executor.mu); - break; - case GRPC_CHTTP2_WRITING_INACTIVE: - case GRPC_CHTTP2_WRITING: - case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: - case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: - case GRPC_CHTTP2_WRITE_SCHEDULED: - gpr_mu_unlock(&t->executor.mu); - break; - } - } - break; - } - - GPR_TIMER_END("finish_global_actions", 0); +static void initiate_writing_locked(grpc_exec_ctx *exec_ctx, void *tp, + grpc_error *error) { + grpc_chttp2_transport *t = tp; + GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED); + start_writing(exec_ctx, t); } -void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *optional_stream, - grpc_chttp2_locked_action action, - void *arg, size_t sizeof_arg) { - grpc_chttp2_executor_action_header *hdr; - - GPR_TIMER_BEGIN("grpc_chttp2_run_with_global_lock", 0); - - REF_TRANSPORT(t, "run_global"); - gpr_mu_lock(&t->executor.mu); - - for (;;) { - if (!t->executor.global_active) { - t->executor.global_active = 1; - gpr_mu_unlock(&t->executor.mu); - - GPR_TIMER_BEGIN("chttp2:locked_action", 0); - action(exec_ctx, t, optional_stream, arg); - GPR_TIMER_END("chttp2:locked_action", 0); - - finish_global_actions(exec_ctx, t); - } else { - gpr_mu_unlock(&t->executor.mu); - - hdr = gpr_malloc(sizeof(*hdr) + sizeof_arg); - hdr->stream = optional_stream; - hdr->action = action; - if (sizeof_arg == 0) { - hdr->arg = arg; - } else { - hdr->arg = hdr + 1; - memcpy(hdr->arg, arg, sizeof_arg); - } - - gpr_mu_lock(&t->executor.mu); - if (!t->executor.global_active) { - /* global lock was released while allocating memory: release & retry */ - gpr_free(hdr); - continue; - } - hdr->next = NULL; - if (t->executor.pending_actions_head != NULL) { - t->executor.pending_actions_tail = - t->executor.pending_actions_tail->next = hdr; - } else { - t->executor.pending_actions_tail = t->executor.pending_actions_head = - hdr; - } - REF_TRANSPORT(t, "pending_action"); - gpr_mu_unlock(&t->executor.mu); - } - break; - } - - UNREF_TRANSPORT(exec_ctx, t, "run_global"); - - GPR_TIMER_END("grpc_chttp2_run_with_global_lock", 0); +static void initiate_read_flush_locked(grpc_exec_ctx *exec_ctx, void *tp, + grpc_error *error) { + grpc_chttp2_transport *t = tp; + t->executor.check_read_ops_scheduled = false; + check_read_ops(exec_ctx, &t->global); } /******************************************************************************* @@ -816,11 +709,12 @@ void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx, void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, bool covered_by_poller, const char *reason) { + GPR_TIMER_BEGIN("grpc_chttp2_initiate_write", 0); + /* Perform state checks, and transition to a scheduled state if appropriate. - Each time we finish the global lock execution, we check if we need to - write. If we do: - - (if there is a poller surrounding the write) schedule - initiate_writing, which locks and calls initiate_writing_locked to... + If we are inactive, schedule a write chain to begin once the transport + combiner finishes any executions in its current batch (which may be + scheduled AFTER this code executes). The write chain will: - call start_writing, which verifies (under the global lock) that there are things that need to be written by calling grpc_chttp2_unlocking_check_writes, and if so schedules writing_action @@ -830,31 +724,28 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, to do *another* write immediately, and if so loops back to start_writing. - Current problems: + Current problems: - too much lock entry/exiting - the writing thread can become stuck indefinitely (punt through the workqueue periodically to fix) */ grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global); switch (t->executor.write_state) { - case GRPC_CHTTP2_WRITING_INACTIVE: - set_write_state(t, covered_by_poller - ? GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER - : GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, - reason); + case GRPC_CHTTP2_WRITES_CORKED: break; - case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: - /* nothing to do: write already requested */ + case GRPC_CHTTP2_WRITING_INACTIVE: + set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, reason); + REF_TRANSPORT(t, "writing"); + grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, + &t->initiate_writing, GRPC_ERROR_NONE, + covered_by_poller); break; - case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: + case GRPC_CHTTP2_WRITE_SCHEDULED: if (covered_by_poller) { /* upgrade to note poller is available to cover the write */ - set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, reason); + grpc_combiner_force_async_finally(t->executor.combiner); } break; - case GRPC_CHTTP2_WRITE_SCHEDULED: - /* nothing to do: write already scheduled */ - break; case GRPC_CHTTP2_WRITING: set_write_state(t, covered_by_poller ? GRPC_CHTTP2_WRITING_STALE_WITH_POLLER @@ -871,15 +762,15 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, } break; } + GPR_TIMER_END("grpc_chttp2_initiate_write", 0); } static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { - GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED || - t->executor.write_state == GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER); + GPR_TIMER_BEGIN("start_writing", 0); + GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED); if (!t->closed && grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) { set_write_state(t, GRPC_CHTTP2_WRITING, "start_writing"); - REF_TRANSPORT(t, "writing"); prevent_endpoint_shutdown(t); grpc_exec_ctx_sched(exec_ctx, &t->writing_action, GRPC_ERROR_NONE, NULL); } else { @@ -890,25 +781,10 @@ static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "start_writing:nothing_to_write"); } - end_waiting_for_write(exec_ctx, t, GRPC_ERROR_NONE, "Nothing to write"); - if (t->ep && !t->endpoint_reading) { - destroy_endpoint(exec_ctx, t); - } + end_waiting_for_write(exec_ctx, t, GRPC_ERROR_NONE); + UNREF_TRANSPORT(exec_ctx, t, "writing"); } -} - -static void initiate_writing_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, - void *arg_ignored) { - start_writing(exec_ctx, t); - UNREF_TRANSPORT(exec_ctx, t, "initiate_writing"); -} - -static void initiate_writing(grpc_exec_ctx *exec_ctx, void *arg, - grpc_error *error) { - grpc_chttp2_run_with_global_lock(exec_ctx, arg, NULL, initiate_writing_locked, - NULL, 0); + GPR_TIMER_END("start_writing", 0); } void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx, @@ -942,15 +818,10 @@ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, /* error may be GRPC_ERROR_NONE if there is no error allocated yet. In that case, use "reason" as the text for a new error. */ static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, grpc_error *error, - const char *reason) { + grpc_chttp2_transport *t, grpc_error *error) { grpc_chttp2_stream_global *stream_global; while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global, &stream_global)) { - if (error == GRPC_ERROR_NONE && reason != NULL) { - /* create error object. */ - error = GRPC_ERROR_CREATE(reason); - } fail_pending_writes(exec_ctx, &t->global, stream_global, GRPC_ERROR_REF(error)); GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes"); @@ -958,12 +829,10 @@ static void end_waiting_for_write(grpc_exec_ctx *exec_ctx, GRPC_ERROR_UNREF(error); } -static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_ignored, - void *a) { - grpc_error *error = a; - +static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, void *tp, + grpc_error *error) { + GPR_TIMER_BEGIN("terminate_writing_with_lock", 0); + grpc_chttp2_transport *t = tp; allow_endpoint_shutdown_locked(exec_ctx, t); if (error != GRPC_ERROR_NONE) { @@ -972,39 +841,46 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx, grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing); - end_waiting_for_write(exec_ctx, t, error, NULL); + end_waiting_for_write(exec_ctx, t, GRPC_ERROR_REF(error)); switch (t->executor.write_state) { + case GRPC_CHTTP2_WRITES_CORKED: case GRPC_CHTTP2_WRITING_INACTIVE: - case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER: - case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER: case GRPC_CHTTP2_WRITE_SCHEDULED: GPR_UNREACHABLE_CODE(break); case GRPC_CHTTP2_WRITING: + GPR_TIMER_MARK("state=writing", 0); set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "terminate_writing"); break; case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER: - set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, - "terminate_writing"); + GPR_TIMER_MARK("state=writing_stale_with_poller", 0); + set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "terminate_writing"); + REF_TRANSPORT(t, "writing"); + grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, + &t->initiate_writing, GRPC_ERROR_NONE, + true); break; case GRPC_CHTTP2_WRITING_STALE_NO_POLLER: - set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, - "terminate_writing"); + GPR_TIMER_MARK("state=writing_stale_no_poller", 0); + set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "terminate_writing"); + REF_TRANSPORT(t, "writing"); + grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, + &t->initiate_writing, GRPC_ERROR_NONE, + false); break; } - if (t->ep && !t->endpoint_reading) { - destroy_endpoint(exec_ctx, t); - } - UNREF_TRANSPORT(exec_ctx, t, "writing"); + GPR_TIMER_END("terminate_writing_with_lock", 0); } void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx, void *transport_writing, grpc_error *error) { + GPR_TIMER_BEGIN("grpc_chttp2_terminate_writing", 0); grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); - grpc_chttp2_run_with_global_lock( - exec_ctx, t, NULL, terminate_writing_with_lock, GRPC_ERROR_REF(error), 0); + grpc_combiner_execute(exec_ctx, t->executor.combiner, &t->terminate_writing, + GRPC_ERROR_REF(error)); + GPR_TIMER_END("grpc_chttp2_terminate_writing", 0); } static void writing_action(grpc_exec_ctx *exec_ctx, void *gt, @@ -1148,15 +1024,22 @@ static int contains_non_ok_status( static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} -static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, void *stream_op) { +static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, + grpc_error *error_ignored) { GPR_TIMER_BEGIN("perform_stream_op_locked", 0); grpc_transport_stream_op *op = stream_op; + grpc_chttp2_transport *t = op->transport_private.args[0]; + grpc_chttp2_stream *s = op->transport_private.args[1]; grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_stream_global *stream_global = &s->global; + if (grpc_http_trace) { + char *str = grpc_transport_stream_op_string(op); + gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s", str); + gpr_free(str); + } + grpc_closure *on_complete = op->on_complete; if (on_complete == NULL) { on_complete = grpc_closure_create(do_nothing, NULL); @@ -1211,7 +1094,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, } else { if (contains_non_ok_status(transport_global, op->send_initial_metadata)) { stream_global->seen_error = true; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } if (!stream_global->write_closed) { if (transport_global->is_client) { @@ -1278,7 +1162,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, if (contains_non_ok_status(transport_global, op->send_trailing_metadata)) { stream_global->seen_error = true; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } if (stream_global->write_closed) { stream_global->send_trailing_metadata = NULL; @@ -1303,7 +1188,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, stream_global->recv_initial_metadata_ready = op->recv_initial_metadata_ready; stream_global->recv_initial_metadata = op->recv_initial_metadata; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } if (op->recv_message != NULL) { @@ -1317,7 +1203,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, exec_ctx, transport_global, stream_global, transport_global->stream_lookahead, 0); } - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } if (op->recv_trailing_metadata != NULL) { @@ -1326,21 +1213,30 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, add_closure_barrier(on_complete); stream_global->recv_trailing_metadata = op->recv_trailing_metadata; stream_global->final_metadata_requested = true; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } grpc_chttp2_complete_closure_step(exec_ctx, transport_global, stream_global, &on_complete, GRPC_ERROR_NONE); GPR_TIMER_END("perform_stream_op_locked", 0); + GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "perform_stream_op"); } static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_transport_stream_op *op) { + GPR_TIMER_BEGIN("perform_stream_op", 0); grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - grpc_chttp2_run_with_global_lock(exec_ctx, t, s, perform_stream_op_locked, op, - sizeof(*op)); + grpc_closure_init(&op->transport_private.closure, perform_stream_op_locked, + op); + op->transport_private.args[0] = gt; + op->transport_private.args[1] = gs; + GRPC_CHTTP2_STREAM_REF(&s->global, "perform_stream_op"); + grpc_combiner_execute(exec_ctx, t->executor.combiner, + &op->transport_private.closure, GRPC_ERROR_NONE); + GPR_TIMER_END("perform_stream_op", 0); } static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, @@ -1362,13 +1258,20 @@ static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_initiate_write(exec_ctx, &t->global, true, "send_ping"); } -static void ack_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - grpc_chttp2_stream *s, void *opaque_8bytes) { +typedef struct ack_ping_args { + grpc_closure closure; + grpc_chttp2_transport *t; + uint8_t opaque_8bytes[8]; +} ack_ping_args; + +static void ack_ping_locked(grpc_exec_ctx *exec_ctx, void *a, + grpc_error *error_ignored) { + ack_ping_args *args = a; grpc_chttp2_outstanding_ping *ping; - grpc_chttp2_transport_global *transport_global = &t->global; + grpc_chttp2_transport_global *transport_global = &args->t->global; for (ping = transport_global->pings.next; ping != &transport_global->pings; ping = ping->next) { - if (0 == memcmp(opaque_8bytes, ping->id, 8)) { + if (0 == memcmp(args->opaque_8bytes, ping->id, 8)) { grpc_exec_ctx_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE, NULL); ping->next->prev = ping->prev; ping->prev->next = ping->next; @@ -1376,21 +1279,27 @@ static void ack_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, break; } } + UNREF_TRANSPORT(exec_ctx, args->t, "ack_ping"); + gpr_free(args); } void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing, const uint8_t *opaque_8bytes) { - grpc_chttp2_run_with_global_lock( - exec_ctx, TRANSPORT_FROM_PARSING(transport_parsing), NULL, - ack_ping_locked, (void *)opaque_8bytes, 8); + ack_ping_args *args = gpr_malloc(sizeof(*args)); + args->t = TRANSPORT_FROM_PARSING(transport_parsing); + memcpy(args->opaque_8bytes, opaque_8bytes, sizeof(args->opaque_8bytes)); + grpc_closure_init(&args->closure, ack_ping_locked, args); + REF_TRANSPORT(args->t, "ack_ping"); + grpc_combiner_execute(exec_ctx, args->t->executor.combiner, &args->closure, + GRPC_ERROR_NONE); } static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, - void *stream_op) { + void *stream_op, + grpc_error *error_ignored) { grpc_transport_op *op = stream_op; + grpc_chttp2_transport *t = op->transport_private.args[0]; grpc_error *close_transport = op->disconnect_with_error; /* If there's a set_accept_stream ensure that we're not parsing @@ -1402,8 +1311,6 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, return; } - grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); - if (op->on_connectivity_state_change != NULL) { grpc_connectivity_state_notify_on_state_change( exec_ctx, &t->channel_callback.state_tracker, op->connectivity_state, @@ -1429,11 +1336,11 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, } if (op->bind_pollset) { - add_to_pollset_locked(exec_ctx, t, NULL, op->bind_pollset); + grpc_endpoint_add_to_pollset(exec_ctx, t->ep, op->bind_pollset); } if (op->bind_pollset_set) { - add_to_pollset_set_locked(exec_ctx, t, NULL, op->bind_pollset_set); + grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, op->bind_pollset_set); } if (op->send_ping) { @@ -1443,13 +1350,21 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx, if (close_transport != GRPC_ERROR_NONE) { close_transport_locked(exec_ctx, t, close_transport); } + + grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); + + UNREF_TRANSPORT(exec_ctx, t, "transport_op"); } 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; - grpc_chttp2_run_with_global_lock( - exec_ctx, t, NULL, perform_transport_op_locked, op, sizeof(*op)); + op->transport_private.args[0] = gt; + grpc_closure_init(&op->transport_private.closure, perform_transport_op_locked, + op); + REF_TRANSPORT(t, "transport_op"); + grpc_combiner_execute(exec_ctx, t->executor.combiner, + &op->transport_private.closure, GRPC_ERROR_NONE); } /******************************************************************************* @@ -1458,6 +1373,7 @@ static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, static void check_read_ops(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global) { + GPR_TIMER_BEGIN("check_read_ops", 0); grpc_chttp2_stream_global *stream_global; grpc_byte_stream *bs; while ( @@ -1467,7 +1383,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, if (stream_global->seen_error) { while ((bs = grpc_chttp2_incoming_frame_queue_pop( &stream_global->incoming_frames)) != NULL) { - incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } if (stream_global->exceeded_metadata_size) { cancel_from_api( @@ -1490,7 +1406,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, stream_global->seen_error && (bs = grpc_chttp2_incoming_frame_queue_pop( &stream_global->incoming_frames)) != NULL) { - incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } if (stream_global->incoming_frames.head != NULL) { *stream_global->recv_message = grpc_chttp2_incoming_frame_queue_pop( @@ -1511,7 +1427,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, if (stream_global->seen_error) { while ((bs = grpc_chttp2_incoming_frame_queue_pop( &stream_global->incoming_frames)) != NULL) { - incoming_byte_stream_destroy_locked(exec_ctx, NULL, NULL, bs); + incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE); } if (stream_global->exceeded_metadata_size) { cancel_from_api( @@ -1532,6 +1448,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx, } } } + GPR_TIMER_END("check_read_ops", 0); } static void decrement_active_streams_locked( @@ -1539,7 +1456,8 @@ static void decrement_active_streams_locked( grpc_chttp2_stream_global *stream_global) { if ((stream_global->all_incoming_byte_streams_finished = gpr_unref(&stream_global->active_streams))) { - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } } @@ -1643,7 +1561,8 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx, } if (due_to_error != GRPC_ERROR_NONE && !stream_global->seen_error) { stream_global->seen_error = true; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1, 1, due_to_error); @@ -1655,7 +1574,8 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_status_code status, gpr_slice *slice) { if (status != GRPC_STATUS_OK) { stream_global->seen_error = true; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } /* stream_global->recv_trailing_metadata_finished gives us a last chance replacement: we've received trailing metadata, @@ -1679,7 +1599,8 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_mdstr_from_slice(gpr_slice_ref(*slice)))); } stream_global->published_trailing_metadata = true; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } if (slice) { gpr_slice_unref(*slice); @@ -1739,7 +1660,8 @@ void grpc_chttp2_mark_stream_closed( GRPC_ERROR_UNREF(error); return; } - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); if (close_reads && !stream_global->read_closed) { stream_global->read_closed_error = GRPC_ERROR_REF(error); stream_global->read_closed = true; @@ -1920,6 +1842,10 @@ static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error) { + if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { + error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_UNAVAILABLE); + } close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error)); end_all_the_calls(exec_ctx, t, error); } @@ -1955,16 +1881,12 @@ static void update_global_window(void *args, uint32_t id, void *stream) { * INPUT PROCESSING - PARSING */ -static void reading_action_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *arg); static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); -static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *arg); -static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *arg); +static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); +static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); static void reading_action(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { @@ -1972,16 +1894,20 @@ static void reading_action(grpc_exec_ctx *exec_ctx, void *tp, reading_action_locked -> (parse_unlocked -> post_parse_locked)? -> post_reading_action_locked */ - grpc_chttp2_run_with_global_lock(exec_ctx, tp, NULL, reading_action_locked, - GRPC_ERROR_REF(error), 0); + GPR_TIMER_BEGIN("reading_action", 0); + grpc_chttp2_transport *t = tp; + grpc_combiner_execute(exec_ctx, t->executor.combiner, + &t->reading_action_locked, GRPC_ERROR_REF(error)); + GPR_TIMER_END("reading_action", 0); } -static void reading_action_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *arg) { +static void reading_action_locked(grpc_exec_ctx *exec_ctx, void *tp, + grpc_error *error) { + GPR_TIMER_BEGIN("reading_action_locked", 0); + + grpc_chttp2_transport *t = tp; grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_transport_parsing *transport_parsing = &t->parsing; - grpc_error *error = arg; GPR_ASSERT(!t->executor.parsing_active); if (!t->closed) { @@ -1990,10 +1916,13 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map); grpc_chttp2_prepare_to_read(transport_global, transport_parsing); - grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, error, NULL); + grpc_exec_ctx_sched(exec_ctx, &t->parsing_action, GRPC_ERROR_REF(error), + NULL); } else { - post_reading_action_locked(exec_ctx, t, s_unused, arg); + post_reading_action_locked(exec_ctx, t, error); } + + GPR_TIMER_END("reading_action_locked", 0); } static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, @@ -2045,13 +1974,15 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) { GRPC_ERROR_UNREF(errors[i]); } + grpc_combiner_execute(exec_ctx, t->executor.combiner, &t->post_parse_locked, + err); GPR_TIMER_END("reading_action.parse", 0); - grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked, err, - 0); } -static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *arg) { +static void post_parse_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + GPR_TIMER_BEGIN("post_parse_locked", 0); + grpc_chttp2_transport *t = arg; grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_transport_parsing *transport_parsing = &t->parsing; /* copy parsing qbuf to global qbuf */ @@ -2077,7 +2008,7 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, 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, NULL, op); + perform_transport_op_locked(exec_ctx, op, GRPC_ERROR_NONE); gpr_free(op); } /* if a stream is in the stream map, and gets cancelled, we need to @@ -2094,39 +2025,32 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2"); } - post_reading_action_locked(exec_ctx, t, s_unused, arg); + post_reading_action_locked(exec_ctx, t, error); + GPR_TIMER_END("post_parse_locked", 0); } -static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, - void *arg) { - grpc_error *error = arg; +static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + GPR_TIMER_BEGIN("post_reading_action_locked", 0); + grpc_chttp2_transport *t = arg; bool keep_reading = false; + GRPC_ERROR_REF(error); if (error == GRPC_ERROR_NONE && t->closed) { error = GRPC_ERROR_CREATE("Transport closed"); } if (error != GRPC_ERROR_NONE) { - if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) { - error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, - GRPC_STATUS_UNAVAILABLE); - } drop_connection(exec_ctx, t, GRPC_ERROR_REF(error)); t->endpoint_reading = 0; if (grpc_http_write_state_trace) { gpr_log(GPR_DEBUG, "R:%p -> 0 ws=%s", t, write_state_name(t->executor.write_state)); } - if (t->executor.write_state == GRPC_CHTTP2_WRITING_INACTIVE && t->ep) { - destroy_endpoint(exec_ctx, t); - } } else if (!t->closed) { keep_reading = true; REF_TRANSPORT(t, "keep_reading"); prevent_endpoint_shutdown(t); } gpr_slice_buffer_reset_and_unref(&t->read_buffer); - GRPC_ERROR_UNREF(error); if (keep_reading) { grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer, &t->reading_action); @@ -2135,6 +2059,9 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx, } else { UNREF_TRANSPORT(exec_ctx, t, "reading_action"); } + GRPC_ERROR_UNREF(error); + + GPR_TIMER_END("post_reading_action_locked", 0); } /******************************************************************************* @@ -2156,36 +2083,16 @@ static void connectivity_state_set( * POLLSET STUFF */ -static void add_to_pollset_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, void *pollset) { - if (t->ep) { - grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset); - } -} - -static void add_to_pollset_set_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s_unused, - void *pollset_set) { - if (t->ep) { - grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set); - } -} - static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_pollset *pollset) { - /* TODO(ctiller): keep pollset alive */ - grpc_chttp2_run_with_global_lock(exec_ctx, (grpc_chttp2_transport *)gt, - (grpc_chttp2_stream *)gs, - add_to_pollset_locked, pollset, 0); + grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; + grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset); } static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_stream *gs, grpc_pollset_set *pollset_set) { - grpc_chttp2_run_with_global_lock(exec_ctx, (grpc_chttp2_transport *)gt, - (grpc_chttp2_stream *)gs, - add_to_pollset_set_locked, pollset_set, 0); + grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; + grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set); } /******************************************************************************* @@ -2197,6 +2104,7 @@ static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx, if (gpr_unref(&bs->refs)) { GRPC_ERROR_UNREF(bs->error); gpr_slice_buffer_destroy(&bs->slices); + gpr_mu_destroy(&bs->slice_mu); gpr_free(bs); } } @@ -2242,38 +2150,34 @@ static void incoming_byte_stream_update_flow_control( } } -typedef struct { - grpc_chttp2_incoming_byte_stream *byte_stream; - gpr_slice *slice; - size_t max_size_hint; - grpc_closure *on_complete; -} incoming_byte_stream_next_arg; - static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *argp) { - incoming_byte_stream_next_arg *arg = argp; - grpc_chttp2_incoming_byte_stream *bs = - (grpc_chttp2_incoming_byte_stream *)arg->byte_stream; + void *argp, + grpc_error *error_ignored) { + grpc_chttp2_incoming_byte_stream *bs = argp; grpc_chttp2_transport_global *transport_global = &bs->transport->global; grpc_chttp2_stream_global *stream_global = &bs->stream->global; if (bs->is_tail) { - incoming_byte_stream_update_flow_control(exec_ctx, transport_global, - stream_global, arg->max_size_hint, - bs->slices.length); - } + gpr_mu_lock(&bs->slice_mu); + size_t cur_length = bs->slices.length; + gpr_mu_unlock(&bs->slice_mu); + incoming_byte_stream_update_flow_control( + exec_ctx, transport_global, stream_global, + bs->next_action.max_size_hint, cur_length); + } + gpr_mu_lock(&bs->slice_mu); if (bs->slices.count > 0) { - *arg->slice = gpr_slice_buffer_take_first(&bs->slices); - grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_NONE, NULL); - } else if (bs->error != GRPC_ERROR_NONE) { - grpc_exec_ctx_sched(exec_ctx, arg->on_complete, GRPC_ERROR_REF(bs->error), + *bs->next_action.slice = gpr_slice_buffer_take_first(&bs->slices); + grpc_exec_ctx_sched(exec_ctx, bs->next_action.on_complete, GRPC_ERROR_NONE, NULL); + } else if (bs->error != GRPC_ERROR_NONE) { + grpc_exec_ctx_sched(exec_ctx, bs->next_action.on_complete, + GRPC_ERROR_REF(bs->error), NULL); } else { - bs->on_next = arg->on_complete; - bs->next = arg->slice; + bs->on_next = bs->next_action.on_complete; + bs->next = bs->next_action.slice; } + gpr_mu_unlock(&bs->slice_mu); incoming_byte_stream_unref(exec_ctx, bs); } @@ -2281,13 +2185,18 @@ static int incoming_byte_stream_next(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream, gpr_slice *slice, size_t max_size_hint, grpc_closure *on_complete) { + GPR_TIMER_BEGIN("incoming_byte_stream_next", 0); grpc_chttp2_incoming_byte_stream *bs = (grpc_chttp2_incoming_byte_stream *)byte_stream; - incoming_byte_stream_next_arg arg = {bs, slice, max_size_hint, on_complete}; gpr_ref(&bs->refs); - grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, - incoming_byte_stream_next_locked, &arg, - sizeof(arg)); + bs->next_action.slice = slice; + bs->next_action.max_size_hint = max_size_hint; + bs->next_action.on_complete = on_complete; + grpc_closure_init(&bs->next_action.closure, incoming_byte_stream_next_locked, + bs); + grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, + &bs->next_action.closure, GRPC_ERROR_NONE); + GPR_TIMER_END("incoming_byte_stream_next", 0); return 0; } @@ -2295,9 +2204,8 @@ static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream); static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *byte_stream) { + void *byte_stream, + grpc_error *error_ignored) { grpc_chttp2_incoming_byte_stream *bs = byte_stream; GPR_ASSERT(bs->base.destroy == incoming_byte_stream_destroy); decrement_active_streams_locked(exec_ctx, &bs->transport->global, @@ -2307,10 +2215,14 @@ static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx, static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx, grpc_byte_stream *byte_stream) { + GPR_TIMER_BEGIN("incoming_byte_stream_destroy", 0); grpc_chttp2_incoming_byte_stream *bs = (grpc_chttp2_incoming_byte_stream *)byte_stream; - grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, - incoming_byte_stream_destroy_locked, bs, 0); + grpc_closure_init(&bs->destroy_action, incoming_byte_stream_destroy_locked, + bs); + grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, + &bs->destroy_action, GRPC_ERROR_NONE); + GPR_TIMER_END("incoming_byte_stream_destroy", 0); } typedef struct { @@ -2318,90 +2230,45 @@ typedef struct { gpr_slice slice; } incoming_byte_stream_push_arg; -static void incoming_byte_stream_push_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *argp) { - incoming_byte_stream_push_arg *arg = argp; - grpc_chttp2_incoming_byte_stream *bs = arg->byte_stream; +void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx, + grpc_chttp2_incoming_byte_stream *bs, + gpr_slice slice) { + gpr_mu_lock(&bs->slice_mu); if (bs->on_next != NULL) { - *bs->next = arg->slice; + *bs->next = slice; grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_NONE, NULL); bs->on_next = NULL; } else { - gpr_slice_buffer_add(&bs->slices, arg->slice); + gpr_slice_buffer_add(&bs->slices, slice); } - incoming_byte_stream_unref(exec_ctx, bs); + gpr_mu_unlock(&bs->slice_mu); } -void grpc_chttp2_incoming_byte_stream_push(grpc_exec_ctx *exec_ctx, - grpc_chttp2_incoming_byte_stream *bs, - gpr_slice slice) { - incoming_byte_stream_push_arg arg = {bs, slice}; - gpr_ref(&bs->refs); - grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, - incoming_byte_stream_push_locked, &arg, - sizeof(arg)); -} - -typedef struct { - grpc_chttp2_incoming_byte_stream *bs; - grpc_error *error; -} bs_fail_args; - -static bs_fail_args *make_bs_fail_args(grpc_chttp2_incoming_byte_stream *bs, - grpc_error *error) { - bs_fail_args *a = gpr_malloc(sizeof(*a)); - a->bs = bs; - a->error = error; - return a; -} - -static void incoming_byte_stream_finished_failed_locked( - grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, - void *argp) { - bs_fail_args *a = argp; - grpc_chttp2_incoming_byte_stream *bs = a->bs; - grpc_error *error = a->error; - gpr_free(a); - grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error), NULL); - bs->on_next = NULL; - GRPC_ERROR_UNREF(bs->error); - bs->error = error; - incoming_byte_stream_unref(exec_ctx, bs); -} - -static void incoming_byte_stream_finished_ok_locked(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, - void *argp) { - grpc_chttp2_incoming_byte_stream *bs = argp; +static void incoming_byte_stream_finished_locked(grpc_exec_ctx *exec_ctx, + void *bsp, grpc_error *error) { + grpc_chttp2_incoming_byte_stream *bs = bsp; + if (error != GRPC_ERROR_NONE) { + grpc_exec_ctx_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error), NULL); + bs->on_next = NULL; + GRPC_ERROR_UNREF(bs->error); + bs->error = error; + } incoming_byte_stream_unref(exec_ctx, bs); } void grpc_chttp2_incoming_byte_stream_finished( grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs, grpc_error *error, int from_parsing_thread) { + GPR_TIMER_BEGIN("grpc_chttp2_incoming_byte_stream_finished", 0); if (from_parsing_thread) { - if (error == GRPC_ERROR_NONE) { - grpc_chttp2_run_with_global_lock(exec_ctx, bs->transport, bs->stream, - incoming_byte_stream_finished_ok_locked, - bs, 0); - } else { - grpc_chttp2_run_with_global_lock( - exec_ctx, bs->transport, bs->stream, - incoming_byte_stream_finished_failed_locked, - make_bs_fail_args(bs, error), 0); - } + grpc_closure_init(&bs->finished_action, + incoming_byte_stream_finished_locked, bs); + grpc_combiner_execute(exec_ctx, bs->transport->executor.combiner, + &bs->finished_action, GRPC_ERROR_REF(error)); } else { - if (error == GRPC_ERROR_NONE) { - incoming_byte_stream_finished_ok_locked(exec_ctx, bs->transport, - bs->stream, bs); - } else { - incoming_byte_stream_finished_failed_locked( - exec_ctx, bs->transport, bs->stream, make_bs_fail_args(bs, error)); - } + incoming_byte_stream_finished_locked(exec_ctx, bs, error); } + GPR_TIMER_END("grpc_chttp2_incoming_byte_stream_finished", 0); } grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create( @@ -2414,6 +2281,7 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create( incoming_byte_stream->base.flags = flags; incoming_byte_stream->base.next = incoming_byte_stream_next; incoming_byte_stream->base.destroy = incoming_byte_stream_destroy; + gpr_mu_init(&incoming_byte_stream->slice_mu); gpr_ref_init(&incoming_byte_stream->refs, 2); incoming_byte_stream->next_message = NULL; incoming_byte_stream->transport = TRANSPORT_FROM_PARSING(transport_parsing); diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index d67c014e54..04b788b702 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -48,6 +48,7 @@ #include "src/core/ext/transport/chttp2/transport/hpack_parser.h" #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" #include "src/core/ext/transport/chttp2/transport/stream_map.h" +#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/transport_impl.h" @@ -161,9 +162,20 @@ struct grpc_chttp2_incoming_byte_stream { grpc_chttp2_transport *transport; grpc_chttp2_stream *stream; int is_tail; + + gpr_mu slice_mu; // protects slices, on_next gpr_slice_buffer slices; grpc_closure *on_next; gpr_slice *next; + + struct { + grpc_closure closure; + gpr_slice *slice; + size_t max_size_hint; + grpc_closure *on_complete; + } next_action; + grpc_closure destroy_action; + grpc_closure finished_action; }; typedef struct { @@ -296,23 +308,11 @@ struct grpc_chttp2_transport_parsing { int64_t outgoing_window; }; -typedef void (*grpc_chttp2_locked_action)(grpc_exec_ctx *ctx, - grpc_chttp2_transport *t, - grpc_chttp2_stream *s, void *arg); - -typedef struct grpc_chttp2_executor_action_header { - grpc_chttp2_stream *stream; - grpc_chttp2_locked_action action; - struct grpc_chttp2_executor_action_header *next; - void *arg; -} grpc_chttp2_executor_action_header; - typedef enum { + /** no writing activity allowed */ + GRPC_CHTTP2_WRITES_CORKED, /** no writing activity */ GRPC_CHTTP2_WRITING_INACTIVE, - /** write has been requested, but not scheduled yet */ - GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, - GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER, /** write has been requested and scheduled against the workqueue */ GRPC_CHTTP2_WRITE_SCHEDULED, /** write has been initiated after being reaped from the workqueue */ @@ -333,7 +333,7 @@ struct grpc_chttp2_transport { gpr_refcount shutdown_ep_refs; struct { - gpr_mu mu; + grpc_combiner *combiner; /** is a thread currently in the global lock */ bool global_active; @@ -341,9 +341,8 @@ struct grpc_chttp2_transport { bool parsing_active; /** write execution state of the transport */ grpc_chttp2_write_state write_state; - - grpc_chttp2_executor_action_header *pending_actions_head; - grpc_chttp2_executor_action_header *pending_actions_tail; + /** has a check_read_ops been scheduled */ + bool check_read_ops_scheduled; } executor; /** is the transport destroying itself? */ @@ -380,10 +379,16 @@ struct grpc_chttp2_transport { grpc_closure writing_action; /** closure to start reading from the endpoint */ grpc_closure reading_action; + grpc_closure reading_action_locked; + grpc_closure post_parse_locked; /** closure to actually do parsing */ grpc_closure parsing_action; /** closure to initiate writing */ grpc_closure initiate_writing; + /** closure to finish writing */ + grpc_closure terminate_writing; + /** closure to flush read state up the stack */ + grpc_closure initiate_read_flush_locked; /** incoming read bytes */ gpr_slice_buffer read_buffer; @@ -527,11 +532,16 @@ struct grpc_chttp2_stream_parsing { }; struct grpc_chttp2_stream { + grpc_chttp2_transport *t; grpc_stream_refcount *refcount; grpc_chttp2_stream_global global; grpc_chttp2_stream_writing writing; grpc_chttp2_stream_parsing parsing; + grpc_closure init_stream; + grpc_closure destroy_stream; + void *destroy_stream_arg; + grpc_chttp2_stream_link links[STREAM_LIST_COUNT]; uint8_t included[STREAM_LIST_COUNT]; }; @@ -626,7 +636,7 @@ int grpc_chttp2_list_pop_waiting_for_concurrency( grpc_chttp2_stream_global **stream_global); void grpc_chttp2_list_add_check_read_ops( - grpc_chttp2_transport_global *transport_global, + grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global); bool grpc_chttp2_list_remove_check_read_ops( grpc_chttp2_transport_global *transport_global, @@ -706,12 +716,6 @@ void grpc_chttp2_complete_closure_step( grpc_chttp2_stream_global *stream_global, grpc_closure **pclosure, grpc_error *error); -void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *transport, - grpc_chttp2_stream *optional_stream, - grpc_chttp2_locked_action action, - void *arg, size_t sizeof_arg); - #define GRPC_CHTTP2_CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" #define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \ (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1) diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index 482cd55c44..0e6d579ba9 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -177,7 +177,8 @@ void grpc_chttp2_publish_reads( stream_global->seen_error = true; stream_global->exceeded_metadata_size = stream_parsing->exceeded_metadata_size; - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } /* flush stats to global stream state */ @@ -203,7 +204,8 @@ void grpc_chttp2_publish_reads( stream_global->incoming_frames.tail->is_tail = 0; } if (stream_parsing->data_parser.incoming_frames.head != NULL) { - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } grpc_chttp2_incoming_frame_queue_merge( &stream_global->incoming_frames, @@ -219,7 +221,8 @@ void grpc_chttp2_publish_reads( GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, stream_parsing->metadata_buffer[0], stream_global->received_initial_metadata); - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } if (!stream_global->published_trailing_metadata && stream_parsing->got_metadata_on_parse[1]) { @@ -228,7 +231,8 @@ void grpc_chttp2_publish_reads( GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, stream_parsing->metadata_buffer[1], stream_global->received_trailing_metadata); - grpc_chttp2_list_add_check_read_ops(transport_global, stream_global); + grpc_chttp2_list_add_check_read_ops(exec_ctx, transport_global, + stream_global); } if (stream_parsing->forced_close_error != GRPC_ERROR_NONE) { diff --git a/src/core/ext/transport/chttp2/transport/stream_lists.c b/src/core/ext/transport/chttp2/transport/stream_lists.c index 2eb5f5f632..4dc4968248 100644 --- a/src/core/ext/transport/chttp2/transport/stream_lists.c +++ b/src/core/ext/transport/chttp2/transport/stream_lists.c @@ -298,8 +298,15 @@ int grpc_chttp2_list_pop_waiting_for_concurrency( } void grpc_chttp2_list_add_check_read_ops( - grpc_chttp2_transport_global *transport_global, + grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_stream_global *stream_global) { + grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global); + if (!t->executor.check_read_ops_scheduled) { + grpc_combiner_execute_finally(exec_ctx, t->executor.combiner, + &t->initiate_read_flush_locked, + GRPC_ERROR_NONE, false); + t->executor.check_read_ops_scheduled = true; + } stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global), STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_CHECK_READ_OPS); diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c index 311b26e354..979515bd54 100644 --- a/src/core/ext/transport/chttp2/transport/writing.c +++ b/src/core/ext/transport/chttp2/transport/writing.c @@ -55,15 +55,6 @@ int grpc_chttp2_unlocking_check_writes( transport_global->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]; - /* simple writes are queued to qbuf, and flushed here */ - gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf); - GPR_ASSERT(transport_global->qbuf.count == 0); - - grpc_chttp2_hpack_compressor_set_max_table_size( - &transport_writing->hpack_compressor, - transport_global->settings[GRPC_PEER_SETTINGS] - [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); - if (transport_global->dirtied_local_settings && !transport_global->sent_local_settings) { gpr_slice_buffer_add( @@ -77,6 +68,16 @@ int grpc_chttp2_unlocking_check_writes( transport_global->sent_local_settings = 1; } + /* simple writes are queued to qbuf, and flushed here */ + gpr_slice_buffer_move_into(&transport_global->qbuf, + &transport_writing->outbuf); + GPR_ASSERT(transport_global->qbuf.count == 0); + + grpc_chttp2_hpack_compressor_set_max_table_size( + &transport_writing->hpack_compressor, + transport_global->settings[GRPC_PEER_SETTINGS] + [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); + GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window, transport_global, outgoing_window); if (transport_writing->outgoing_window > 0) { @@ -344,6 +345,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx, void grpc_chttp2_cleanup_writing( grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_writing *transport_writing) { + GPR_TIMER_BEGIN("grpc_chttp2_cleanup_writing", 0); grpc_chttp2_stream_writing *stream_writing; grpc_chttp2_stream_global *stream_global; @@ -382,4 +384,5 @@ void grpc_chttp2_cleanup_writing( GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing"); } gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf); + GPR_TIMER_END("grpc_chttp2_cleanup_writing", 0); } diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c index 98f304f2da..0655b9353f 100644 --- a/src/core/lib/channel/channel_stack.c +++ b/src/core/lib/channel/channel_stack.c @@ -32,6 +32,7 @@ */ #include "src/core/lib/channel/channel_stack.h" +#include #include #include @@ -270,21 +271,27 @@ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) { sizeof(grpc_call_stack))); } +static void destroy_op(grpc_exec_ctx *exec_ctx, void *op, grpc_error *error) { + gpr_free(op); +} + void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx, grpc_call_element *cur_elem) { - grpc_transport_stream_op op; - memset(&op, 0, sizeof(op)); - op.cancel_error = GRPC_ERROR_CANCELLED; - grpc_call_next_op(exec_ctx, cur_elem, &op); + grpc_transport_stream_op *op = gpr_malloc(sizeof(*op)); + memset(op, 0, sizeof(*op)); + op->cancel_error = GRPC_ERROR_CANCELLED; + op->on_complete = grpc_closure_create(destroy_op, op); + grpc_call_next_op(exec_ctx, cur_elem, op); } void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx, grpc_call_element *cur_elem, grpc_status_code status, gpr_slice *optional_message) { - grpc_transport_stream_op op; - memset(&op, 0, sizeof(op)); - grpc_transport_stream_op_add_cancellation_with_message(&op, status, + grpc_transport_stream_op *op = gpr_malloc(sizeof(*op)); + memset(op, 0, sizeof(*op)); + op->on_complete = grpc_closure_create(destroy_op, op); + grpc_transport_stream_op_add_cancellation_with_message(op, status, optional_message); - grpc_call_next_op(exec_ctx, cur_elem, &op); + grpc_call_next_op(exec_ctx, cur_elem, op); } diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c index 134180e619..0981d59f63 100644 --- a/src/core/lib/channel/compress_filter.c +++ b/src/core/lib/channel/compress_filter.c @@ -60,7 +60,7 @@ typedef struct call_data { /** If true, contents of \a compression_algorithm are authoritative */ int has_compression_algorithm; - grpc_transport_stream_op send_op; + grpc_transport_stream_op *send_op; uint32_t send_length; uint32_t send_flags; gpr_slice incoming_slice; @@ -199,11 +199,11 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx, grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices, calld->send_flags); - calld->send_op.send_message = &calld->replacement_stream.base; - calld->post_send = calld->send_op.on_complete; - calld->send_op.on_complete = &calld->send_done; + calld->send_op->send_message = &calld->replacement_stream.base; + calld->post_send = calld->send_op->on_complete; + calld->send_op->on_complete = &calld->send_done; - grpc_call_next_op(exec_ctx, elem, &calld->send_op); + grpc_call_next_op(exec_ctx, elem, calld->send_op); } static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { @@ -220,7 +220,7 @@ static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { static void continue_send_message(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) { call_data *calld = elem->call_data; - while (grpc_byte_stream_next(exec_ctx, calld->send_op.send_message, + while (grpc_byte_stream_next(exec_ctx, calld->send_op->send_message, &calld->incoming_slice, ~(size_t)0, &calld->got_slice)) { gpr_slice_buffer_add(&calld->slices, calld->incoming_slice); @@ -243,7 +243,7 @@ static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx, } if (op->send_message != NULL && !skip_compression(elem) && 0 == (op->send_message->flags & GRPC_WRITE_NO_COMPRESS)) { - calld->send_op = *op; + calld->send_op = op; calld->send_length = op->send_message->length; calld->send_flags = op->send_message->flags; continue_send_message(exec_ctx, elem); diff --git a/src/core/lib/iomgr/closure.c b/src/core/lib/iomgr/closure.c index 0b6c3b2539..1ba0a5c141 100644 --- a/src/core/lib/iomgr/closure.c +++ b/src/core/lib/iomgr/closure.c @@ -41,6 +41,10 @@ void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb, closure->cb_arg = cb_arg; } +void grpc_closure_list_init(grpc_closure_list *closure_list) { + closure_list->head = closure_list->tail = NULL; +} + void grpc_closure_list_append(grpc_closure_list *closure_list, grpc_closure *closure, grpc_error *error) { if (closure == NULL) { diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h index 08e59a168e..c1a22b6021 100644 --- a/src/core/lib/iomgr/closure.h +++ b/src/core/lib/iomgr/closure.h @@ -37,6 +37,7 @@ #include #include #include "src/core/lib/iomgr/error.h" +#include "src/core/lib/support/mpscq.h" struct grpc_closure; typedef struct grpc_closure grpc_closure; @@ -60,6 +61,14 @@ typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg, /** A closure over a grpc_iomgr_cb_func. */ struct grpc_closure { + /** Once queued, next indicates the next queued closure; before then, scratch + * space */ + union { + grpc_closure *next; + gpr_mpscq_node atm_next; + uintptr_t scratch; + } next_data; + /** Bound callback. */ grpc_iomgr_cb_func cb; @@ -68,13 +77,6 @@ struct grpc_closure { /** Once queued, the result of the closure. Before then: scratch space */ grpc_error *error; - - /** Once queued, next indicates the next queued closure; before then, scratch - * space */ - union { - grpc_closure *next; - uintptr_t scratch; - } next_data; }; /** Initializes \a closure with \a cb and \a cb_arg. */ @@ -87,6 +89,8 @@ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg); #define GRPC_CLOSURE_LIST_INIT \ { NULL, NULL } +void grpc_closure_list_init(grpc_closure_list *list); + /** add \a closure to the end of \a list and set \a closure's result to \a error */ void grpc_closure_list_append(grpc_closure_list *list, grpc_closure *closure, diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c new file mode 100644 index 0000000000..831bdb4aff --- /dev/null +++ b/src/core/lib/iomgr/combiner.c @@ -0,0 +1,293 @@ +/* + * + * 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/lib/iomgr/combiner.h" + +#include + +#include +#include + +#include "src/core/lib/iomgr/workqueue.h" +#include "src/core/lib/profiling/timers.h" + +int grpc_combiner_trace = 0; + +#define GRPC_COMBINER_TRACE(fn) \ + do { \ + if (grpc_combiner_trace) { \ + fn; \ + } \ + } while (0) + +struct grpc_combiner { + grpc_workqueue *optional_workqueue; + gpr_mpscq queue; + // state is: + // lower bit - zero if orphaned + // other bits - number of items queued on the lock + gpr_atm state; + bool take_async_break_before_final_list; + grpc_closure_list final_list; + grpc_closure continue_finishing; +}; + +grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { + grpc_combiner *lock = gpr_malloc(sizeof(*lock)); + lock->optional_workqueue = optional_workqueue; + gpr_atm_no_barrier_store(&lock->state, 1); + gpr_mpscq_init(&lock->queue); + lock->take_async_break_before_final_list = false; + grpc_closure_list_init(&lock->final_list); + GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p create", lock)); + return lock; +} + +static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p really_destroy", lock)); + GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); + gpr_mpscq_destroy(&lock->queue); + GRPC_WORKQUEUE_UNREF(exec_ctx, lock->optional_workqueue, "combiner"); + gpr_free(lock); +} + +void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -1); + GRPC_COMBINER_TRACE(gpr_log( + GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state)); + if (old_state == 1) { + really_destroy(exec_ctx, lock); + } +} + +static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); +static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); + +static void continue_finishing_mainline(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + GPR_TIMER_BEGIN("combiner.continue_executing_mainline", 0); + grpc_combiner *lock = arg; + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, "C:%p continue_finishing_mainline", lock)); + GPR_ASSERT(exec_ctx->active_combiner == NULL); + exec_ctx->active_combiner = lock; + if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); + GPR_ASSERT(exec_ctx->active_combiner == lock); + exec_ctx->active_combiner = NULL; + GPR_TIMER_END("combiner.continue_executing_mainline", 0); +} + +static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + GPR_TIMER_BEGIN("combiner.execute_final", 0); + grpc_closure *c = lock->final_list.head; + GPR_ASSERT(c != NULL); + grpc_closure_list_init(&lock->final_list); + lock->take_async_break_before_final_list = false; + int loops = 0; + while (c != NULL) { + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c)); + grpc_closure *next = c->next_data.next; + grpc_error *error = c->error; + c->cb(exec_ctx, c->cb_arg, error); + GRPC_ERROR_UNREF(error); + c = next; + loops++; + } + GPR_TIMER_END("combiner.execute_final", 0); +} + +static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + GPR_TIMER_BEGIN("combiner.continue_executing_final", 0); + grpc_combiner *lock = arg; + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, "C:%p continue_executing_final", lock)); + GPR_ASSERT(exec_ctx->active_combiner == NULL); + exec_ctx->active_combiner = lock; + // quick peek to see if new things have turned up on the queue: if so, go back + // to executing them before the final list + if ((gpr_atm_acq_load(&lock->state) >> 1) > 1) { + if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); + } else { + execute_final(exec_ctx, lock); + finish(exec_ctx, lock); + } + GPR_ASSERT(exec_ctx->active_combiner == lock); + exec_ctx->active_combiner = NULL; + GPR_TIMER_END("combiner.continue_executing_final", 0); +} + +static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + GPR_TIMER_BEGIN("combiner.start_execute_final", 0); + GPR_ASSERT(exec_ctx->active_combiner == lock); + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, + "C:%p start_execute_final take_async_break_before_final_list=%d", + lock, lock->take_async_break_before_final_list)); + if (lock->take_async_break_before_final_list) { + grpc_closure_init(&lock->continue_finishing, continue_executing_final, + lock); + grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, + GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); + GPR_TIMER_END("combiner.start_execute_final", 0); + return false; + } else { + execute_final(exec_ctx, lock); + GPR_TIMER_END("combiner.start_execute_final", 0); + return true; + } +} + +static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + GPR_TIMER_BEGIN("combiner.maybe_finish_one", 0); + gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, "C:%p maybe_finish_one n=%p", lock, n)); + GPR_ASSERT(exec_ctx->active_combiner == lock); + if (n == NULL) { + // Queue is in an transiently inconsistent state: a new item is being queued + // but is not visible to this thread yet. + // Use this as a cue that we should go off and do something else for a while + // (and come back later) + grpc_closure_init(&lock->continue_finishing, continue_finishing_mainline, + lock); + grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, + GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); + GPR_TIMER_END("combiner.maybe_finish_one", 0); + return false; + } + grpc_closure *cl = (grpc_closure *)n; + grpc_error *error = cl->error; + cl->cb(exec_ctx, cl->cb_arg, error); + GRPC_ERROR_UNREF(error); + GPR_TIMER_END("combiner.maybe_finish_one", 0); + return true; +} + +static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { + bool (*executor)(grpc_exec_ctx * exec_ctx, grpc_combiner * lock); + GPR_TIMER_BEGIN("combiner.finish", 0); + int loops = 0; + do { + executor = maybe_finish_one; + gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -2); + GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, + "C:%p finish[%d] old_state=%" PRIdPTR, lock, + loops, old_state)); + switch (old_state) { + default: + // we have multiple queued work items: just continue executing them + break; + case 5: // we're down to one queued item: if it's the final list we + case 4: // should do that + if (!grpc_closure_list_empty(lock->final_list)) { + executor = start_execute_final; + } + break; + case 3: // had one count, one unorphaned --> unlocked unorphaned + GPR_TIMER_END("combiner.finish", 0); + return; + case 2: // and one count, one orphaned --> unlocked and orphaned + really_destroy(exec_ctx, lock); + GPR_TIMER_END("combiner.finish", 0); + return; + case 1: + case 0: + // these values are illegal - representing an already unlocked or + // deleted lock + GPR_UNREACHABLE_CODE(return ); + } + loops++; + } while (executor(exec_ctx, lock)); + GPR_TIMER_END("combiner.finish", 0); +} + +void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, + grpc_closure *cl, grpc_error *error) { + GRPC_COMBINER_TRACE( + gpr_log(GPR_DEBUG, "C:%p grpc_combiner_execute c=%p", lock, cl)); + GPR_TIMER_BEGIN("combiner.execute", 0); + gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); + GPR_ASSERT(last & 1); // ensure lock has not been destroyed + if (last == 1) { + exec_ctx->active_combiner = lock; + GPR_TIMER_BEGIN("combiner.execute_first_cb", 0); + cl->cb(exec_ctx, cl->cb_arg, error); + GPR_TIMER_END("combiner.execute_first_cb", 0); + GRPC_ERROR_UNREF(error); + finish(exec_ctx, lock); + GPR_ASSERT(exec_ctx->active_combiner == lock); + exec_ctx->active_combiner = NULL; + } else { + cl->error = error; + gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); + } + GPR_TIMER_END("combiner.execute", 0); +} + +static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, + grpc_error *error) { + grpc_combiner_execute_finally(exec_ctx, exec_ctx->active_combiner, closure, + GRPC_ERROR_REF(error), false); +} + +void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, + grpc_closure *closure, grpc_error *error, + bool force_async_break) { + GRPC_COMBINER_TRACE(gpr_log( + GPR_DEBUG, + "C:%p grpc_combiner_execute_finally c=%p force_async_break=%d; ac=%p", + lock, closure, force_async_break, exec_ctx->active_combiner)); + GPR_TIMER_BEGIN("combiner.execute_finally", 0); + if (exec_ctx->active_combiner != lock) { + GPR_TIMER_MARK("slowpath", 0); + grpc_combiner_execute(exec_ctx, lock, + grpc_closure_create(enqueue_finally, closure), error); + GPR_TIMER_END("combiner.execute_finally", 0); + return; + } + + if (force_async_break) { + lock->take_async_break_before_final_list = true; + } + if (grpc_closure_list_empty(lock->final_list)) { + gpr_atm_full_fetch_add(&lock->state, 2); + } + grpc_closure_list_append(&lock->final_list, closure, error); + GPR_TIMER_END("combiner.execute_finally", 0); +} + +void grpc_combiner_force_async_finally(grpc_combiner *lock) { + lock->take_async_break_before_final_list = true; +} diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h new file mode 100644 index 0000000000..1409db24b9 --- /dev/null +++ b/src/core/lib/iomgr/combiner.h @@ -0,0 +1,71 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_COMBINER_H +#define GRPC_CORE_LIB_IOMGR_COMBINER_H + +#include + +#include +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/support/mpscq.h" + +// Provides serialized access to some resource. +// Each action queued on a combiner is executed serially in a borrowed thread. +// The actual thread executing actions may change over time (but there will only +// every be one at a time). + +// Initialize the lock, with an optional workqueue to shift load to when +// necessary +grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue); +// Destroy the lock +void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); +// Execute \a action within the lock. +void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, + grpc_closure *closure, grpc_error *error); +// Execute \a action within the lock just prior to unlocking. +// if \a hint_async_break is true, the combiner tries to hand execution to +// another thread before finishing the primary queue of combined closures and +// executing the finally list. +// Deprecation warning: \a hint_async_break will be removed in a future version +// Takes a very slow and round-about path if not called from a +// grpc_combiner_execute closure. +void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, + grpc_closure *closure, grpc_error *error, + bool hint_async_break); +// Deprecated: force the finally list execution onto another thread +void grpc_combiner_force_async_finally(grpc_combiner *lock); + +extern int grpc_combiner_trace; + +#endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c index 149c55663c..e366961936 100644 --- a/src/core/lib/iomgr/error.c +++ b/src/core/lib/iomgr/error.c @@ -332,7 +332,7 @@ grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) { return new; } -static const char *no_error_string = "null"; +static const char *no_error_string = "\"No Error\""; static const char *oom_error_string = "\"Out of memory\""; static const char *cancelled_error_string = "\"Cancelled\""; diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c index eba347125e..740920d760 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epoll_linux.c @@ -1531,6 +1531,8 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_fd *fd) { + GPR_TIMER_BEGIN("pollset_add_fd", 0); + grpc_error *error = GRPC_ERROR_NONE; gpr_mu_lock(&pollset->mu); @@ -1643,6 +1645,8 @@ retry: gpr_mu_unlock(&pollset->mu); GRPC_LOG_IF_ERROR("pollset_add_fd", error); + + GPR_TIMER_END("pollset_add_fd", 0); } /******************************************************************************* diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index 917f332f03..1895ee6245 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -40,8 +40,8 @@ /** A workqueue represents a list of work to be executed asynchronously. Forward declared here to avoid a circular dependency with workqueue.h. */ -struct grpc_workqueue; typedef struct grpc_workqueue grpc_workqueue; +typedef struct grpc_combiner grpc_combiner; #ifndef GRPC_EXECUTION_CONTEXT_SANITIZER /** Execution context. @@ -66,13 +66,15 @@ typedef struct grpc_workqueue grpc_workqueue; */ struct grpc_exec_ctx { grpc_closure_list closure_list; + /** currently active combiner: updated only via combiner.c */ + grpc_combiner *active_combiner; bool cached_ready_to_finish; void *check_ready_to_finish_arg; bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg); }; #define GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(finish_check, finish_check_arg) \ - { GRPC_CLOSURE_LIST_INIT, false, finish_check_arg, finish_check } + { GRPC_CLOSURE_LIST_INIT, NULL, false, finish_check_arg, finish_check } #else struct grpc_exec_ctx { bool cached_ready_to_finish; diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c index 974d5ae479..92767721d5 100644 --- a/src/core/lib/iomgr/tcp_posix.c +++ b/src/core/lib/iomgr/tcp_posix.c @@ -379,10 +379,19 @@ static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, } if (!tcp_flush(tcp, &error)) { + if (grpc_tcp_trace) { + gpr_log(GPR_DEBUG, "write: delayed"); + } grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { cb = tcp->write_cb; tcp->write_cb = NULL; + if (grpc_tcp_trace) { + const char *str = grpc_error_string(error); + gpr_log(GPR_DEBUG, "write: %s", str); + grpc_error_free_string(str); + } + GPR_TIMER_BEGIN("tcp_handle_write.cb", 0); cb->cb(exec_ctx, cb->cb_arg, error); GPR_TIMER_END("tcp_handle_write.cb", 0); @@ -425,8 +434,16 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, if (!tcp_flush(tcp, &error)) { TCP_REF(tcp, "write"); tcp->write_cb = cb; + if (grpc_tcp_trace) { + gpr_log(GPR_DEBUG, "write: delayed"); + } grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { + if (grpc_tcp_trace) { + const char *str = grpc_error_string(error); + gpr_log(GPR_DEBUG, "write: %s", str); + grpc_error_free_string(str); + } grpc_exec_ctx_sched(exec_ctx, cb, error, NULL); } diff --git a/src/core/lib/iomgr/workqueue.h b/src/core/lib/iomgr/workqueue.h index 7156e490d7..b2805dc66c 100644 --- a/src/core/lib/iomgr/workqueue.h +++ b/src/core/lib/iomgr/workqueue.h @@ -50,10 +50,6 @@ /* grpc_workqueue is forward declared in exec_ctx.h */ -/* Deprecated: do not use. - This has *already* been removed in a future commit. */ -void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue); - /* Reference counting functions. Use the macro's always (GRPC_WORKQUEUE_{REF,UNREF}). diff --git a/src/core/lib/iomgr/workqueue_posix.c b/src/core/lib/iomgr/workqueue_posix.c index e0d6dac230..ecfea68f56 100644 --- a/src/core/lib/iomgr/workqueue_posix.c +++ b/src/core/lib/iomgr/workqueue_posix.c @@ -44,6 +44,7 @@ #include #include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/profiling/timers.h" static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); @@ -52,8 +53,7 @@ grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, char name[32]; *workqueue = gpr_malloc(sizeof(grpc_workqueue)); gpr_ref_init(&(*workqueue)->refs, 1); - gpr_mu_init(&(*workqueue)->mu); - (*workqueue)->closure_list.head = (*workqueue)->closure_list.tail = NULL; + gpr_atm_no_barrier_store(&(*workqueue)->state, 1); grpc_error *err = grpc_wakeup_fd_init(&(*workqueue)->wakeup_fd); if (err != GRPC_ERROR_NONE) { gpr_free(*workqueue); @@ -62,6 +62,7 @@ grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, sprintf(name, "workqueue:%p", (void *)(*workqueue)); (*workqueue)->wakeup_read_fd = grpc_fd_create( GRPC_WAKEUP_FD_GET_READ_FD(&(*workqueue)->wakeup_fd), name); + gpr_mpscq_init(&(*workqueue)->queue); grpc_closure_init(&(*workqueue)->read_closure, on_readable, *workqueue); grpc_fd_notify_on_read(exec_ctx, (*workqueue)->wakeup_read_fd, &(*workqueue)->read_closure); @@ -70,57 +71,79 @@ grpc_error *grpc_workqueue_create(grpc_exec_ctx *exec_ctx, static void workqueue_destroy(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { - grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); grpc_fd_shutdown(exec_ctx, workqueue->wakeup_read_fd); } +static void workqueue_orphan(grpc_exec_ctx *exec_ctx, + grpc_workqueue *workqueue) { + if (gpr_atm_full_fetch_add(&workqueue->state, -1) == 1) { + workqueue_destroy(exec_ctx, workqueue); + } +} + #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) { + if (workqueue == NULL) return; gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p ref %d -> %d %s", workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count + 1, reason); + gpr_ref(&workqueue->refs); +} #else void grpc_workqueue_ref(grpc_workqueue *workqueue) { -#endif + if (workqueue == NULL) return; gpr_ref(&workqueue->refs); } +#endif #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, const char *file, int line, const char *reason) { + if (workqueue == NULL) return; gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "WORKQUEUE:%p unref %d -> %d %s", workqueue, (int)workqueue->refs.count, (int)workqueue->refs.count - 1, reason); + if (gpr_unref(&workqueue->refs)) { + workqueue_orphan(exec_ctx, workqueue); + } +} #else void grpc_workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { -#endif + if (workqueue == NULL) return; if (gpr_unref(&workqueue->refs)) { - workqueue_destroy(exec_ctx, workqueue); + workqueue_orphan(exec_ctx, workqueue); } } +#endif + +static void drain(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { + abort(); +} -void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { - gpr_mu_lock(&workqueue->mu); - grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); - gpr_mu_unlock(&workqueue->mu); +static void wakeup(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) { + GPR_TIMER_MARK("workqueue.wakeup", 0); + grpc_error *err = grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd); + if (!GRPC_LOG_IF_ERROR("wakeupfd_wakeup", err)) { + drain(exec_ctx, workqueue); + } } static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + GPR_TIMER_BEGIN("workqueue.on_readable", 0); + grpc_workqueue *workqueue = arg; if (error != GRPC_ERROR_NONE) { - gpr_mu_destroy(&workqueue->mu); /* HACK: let wakeup_fd code know that we stole the fd */ workqueue->wakeup_fd.read_fd = 0; grpc_wakeup_fd_destroy(&workqueue->wakeup_fd); grpc_fd_orphan(exec_ctx, workqueue->wakeup_read_fd, NULL, NULL, "destroy"); + GPR_ASSERT(gpr_atm_no_barrier_load(&workqueue->state) == 0); gpr_free(workqueue); } else { - gpr_mu_lock(&workqueue->mu); - grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); error = grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd); - gpr_mu_unlock(&workqueue->mu); + gpr_mpscq_node *n = gpr_mpscq_pop(&workqueue->queue); if (error == GRPC_ERROR_NONE) { grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd, &workqueue->read_closure); @@ -128,24 +151,46 @@ static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { /* recurse to get error handling */ on_readable(exec_ctx, arg, error); } + if (n == NULL) { + /* try again - queue in an inconsistant state */ + wakeup(exec_ctx, workqueue); + } else { + switch (gpr_atm_full_fetch_add(&workqueue->state, -2)) { + case 3: // had one count, one unorphaned --> done, unorphaned + break; + case 2: // had one count, one orphaned --> done, orphaned + workqueue_destroy(exec_ctx, workqueue); + break; + case 1: + case 0: + // these values are illegal - representing an already done or + // deleted workqueue + GPR_UNREACHABLE_CODE(break); + default: + // schedule a wakeup since there's more to do + wakeup(exec_ctx, workqueue); + } + grpc_closure *cl = (grpc_closure *)n; + grpc_error *clerr = cl->error; + cl->cb(exec_ctx, cl->cb_arg, clerr); + GRPC_ERROR_UNREF(clerr); + } } + + GPR_TIMER_END("workqueue.on_readable", 0); } void grpc_workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, grpc_closure *closure, grpc_error *error) { - grpc_error *push_error = GRPC_ERROR_NONE; - gpr_mu_lock(&workqueue->mu); - if (grpc_closure_list_empty(workqueue->closure_list)) { - push_error = grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd); - } - grpc_closure_list_append(&workqueue->closure_list, closure, error); - if (push_error != GRPC_ERROR_NONE) { - const char *msg = grpc_error_string(push_error); - gpr_log(GPR_ERROR, "Failed to push to workqueue: %s", msg); - grpc_error_free_string(msg); - grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL); + GPR_TIMER_BEGIN("workqueue.enqueue", 0); + gpr_atm last = gpr_atm_full_fetch_add(&workqueue->state, 2); + GPR_ASSERT(last & 1); + closure->error = error; + gpr_mpscq_push(&workqueue->queue, &closure->next_data.atm_next); + if (last == 1) { + wakeup(exec_ctx, workqueue); } - gpr_mu_unlock(&workqueue->mu); + GPR_TIMER_END("workqueue.enqueue", 0); } #endif /* GPR_POSIX_SOCKET */ diff --git a/src/core/lib/iomgr/workqueue_posix.h b/src/core/lib/iomgr/workqueue_posix.h index 0f26ba58e2..03ee21cef7 100644 --- a/src/core/lib/iomgr/workqueue_posix.h +++ b/src/core/lib/iomgr/workqueue_posix.h @@ -35,14 +35,17 @@ #define GRPC_CORE_LIB_IOMGR_WORKQUEUE_POSIX_H #include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include "src/core/lib/support/mpscq.h" struct grpc_fd; struct grpc_workqueue { gpr_refcount refs; - - gpr_mu mu; - grpc_closure_list closure_list; + gpr_mpscq queue; + // state is: + // lower bit - zero if orphaned + // other bits - number of items enqueued + gpr_atm state; grpc_wakeup_fd wakeup_fd; struct grpc_fd *wakeup_read_fd; diff --git a/src/core/lib/iomgr/workqueue_windows.c b/src/core/lib/iomgr/workqueue_windows.c index 23e2dea185..ee81dc248e 100644 --- a/src/core/lib/iomgr/workqueue_windows.c +++ b/src/core/lib/iomgr/workqueue_windows.c @@ -42,8 +42,6 @@ // context, which is at least correct, if not performant or in the spirit of // workqueues. -void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {} - #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG void grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) {} diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c index 2a1bf4d4e3..b366d1410f 100644 --- a/src/core/lib/security/transport/client_auth_filter.c +++ b/src/core/lib/security/transport/client_auth_filter.c @@ -40,6 +40,7 @@ #include #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/profiling/timers.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/transport/security_connector.h" @@ -218,6 +219,8 @@ static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data, static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op *op) { + GPR_TIMER_BEGIN("auth_start_transport_op", 0); + /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; @@ -258,12 +261,14 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_channel_security_connector_check_call_host( exec_ctx, chand->security_connector, call_host, chand->auth_context, on_host_checked, elem); + GPR_TIMER_END("auth_start_transport_op", 0); return; /* early exit */ } } /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, op); + GPR_TIMER_END("auth_start_transport_op", 0); } /* Constructor for call_data */ diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c index 0169ccd9ef..acb0113ea8 100644 --- a/src/core/lib/security/transport/secure_endpoint.c +++ b/src/core/lib/security/transport/secure_endpoint.c @@ -38,6 +38,7 @@ #include #include #include "src/core/lib/debug/trace.h" +#include "src/core/lib/profiling/timers.h" #include "src/core/lib/security/transport/tsi_error.h" #include "src/core/lib/support/string.h" #include "src/core/lib/tsi/transport_security_interface.h" @@ -248,6 +249,8 @@ static void flush_write_staging_buffer(secure_endpoint *ep, uint8_t **cur, static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, gpr_slice_buffer *slices, grpc_closure *cb) { + GPR_TIMER_BEGIN("secure_endpoint.endpoint_write", 0); + unsigned i; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)secure_ep; @@ -323,10 +326,12 @@ static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, exec_ctx, cb, grpc_set_tsi_error_result(GRPC_ERROR_CREATE("Wrap failed"), result), NULL); + GPR_TIMER_END("secure_endpoint.endpoint_write", 0); return; } grpc_endpoint_write(exec_ctx, ep->wrapped_ep, &ep->output_buffer, cb); + GPR_TIMER_END("secure_endpoint.endpoint_write", 0); } static void endpoint_shutdown(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c index def16c8229..b2c6815af8 100644 --- a/src/core/lib/security/transport/server_auth_filter.c +++ b/src/core/lib/security/transport/server_auth_filter.c @@ -48,7 +48,7 @@ typedef struct call_data { up-call on transport_op, and remember to call our on_done_recv member after handling it. */ grpc_closure auth_on_recv; - grpc_transport_stream_op transport_op; + grpc_transport_stream_op *transport_op; grpc_metadata_array md; const grpc_metadata *consumed_md; size_t num_consumed_md; @@ -106,6 +106,10 @@ static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) { return md; } +static void destroy_op(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + gpr_free(arg); +} + /* called from application code */ static void on_md_processing_done( void *user_data, const grpc_metadata *consumed_md, size_t num_consumed_md, @@ -131,21 +135,22 @@ static void on_md_processing_done( grpc_exec_ctx_sched(&exec_ctx, calld->on_done_recv, GRPC_ERROR_NONE, NULL); } else { gpr_slice message; - grpc_transport_stream_op close_op; - memset(&close_op, 0, sizeof(close_op)); + grpc_transport_stream_op *close_op = gpr_malloc(sizeof(*close_op)); + memset(close_op, 0, sizeof(*close_op)); grpc_metadata_array_destroy(&calld->md); error_details = error_details != NULL ? error_details : "Authentication metadata processing failed."; message = gpr_slice_from_copied_string(error_details); - calld->transport_op.send_initial_metadata = NULL; - if (calld->transport_op.send_message != NULL) { - grpc_byte_stream_destroy(&exec_ctx, calld->transport_op.send_message); - calld->transport_op.send_message = NULL; + calld->transport_op->send_initial_metadata = NULL; + if (calld->transport_op->send_message != NULL) { + grpc_byte_stream_destroy(&exec_ctx, calld->transport_op->send_message); + calld->transport_op->send_message = NULL; } - calld->transport_op.send_trailing_metadata = NULL; - grpc_transport_stream_op_add_close(&close_op, status, &message); - grpc_call_next_op(&exec_ctx, elem, &close_op); + calld->transport_op->send_trailing_metadata = NULL; + close_op->on_complete = grpc_closure_create(destroy_op, close_op); + grpc_transport_stream_op_add_close(close_op, status, &message); + grpc_call_next_op(&exec_ctx, elem, close_op); grpc_exec_ctx_sched(&exec_ctx, calld->on_done_recv, grpc_error_set_int(GRPC_ERROR_CREATE(error_details), GRPC_ERROR_INT_GRPC_STATUS, status), @@ -182,7 +187,7 @@ static void set_recv_ops_md_callbacks(grpc_call_element *elem, calld->recv_initial_metadata = op->recv_initial_metadata; calld->on_done_recv = op->recv_initial_metadata_ready; op->recv_initial_metadata_ready = &calld->auth_on_recv; - calld->transport_op = *op; + calld->transport_op = op; } } diff --git a/src/core/lib/support/mpscq.c b/src/core/lib/support/mpscq.c new file mode 100644 index 0000000000..5b9323275a --- /dev/null +++ b/src/core/lib/support/mpscq.c @@ -0,0 +1,83 @@ +/* + * + * 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/lib/support/mpscq.h" + +#include + +void gpr_mpscq_init(gpr_mpscq *q) { + gpr_atm_no_barrier_store(&q->head, (gpr_atm)&q->stub); + q->tail = &q->stub; + gpr_atm_no_barrier_store(&q->stub.next, (gpr_atm)NULL); +} + +void gpr_mpscq_destroy(gpr_mpscq *q) { + GPR_ASSERT(gpr_atm_no_barrier_load(&q->head) == (gpr_atm)&q->stub); + GPR_ASSERT(q->tail == &q->stub); +} + +void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n) { + gpr_atm_no_barrier_store(&n->next, (gpr_atm)NULL); + gpr_mpscq_node *prev = + (gpr_mpscq_node *)gpr_atm_full_xchg(&q->head, (gpr_atm)n); + gpr_atm_rel_store(&prev->next, (gpr_atm)n); +} + +gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { + gpr_mpscq_node *tail = q->tail; + gpr_mpscq_node *next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); + if (tail == &q->stub) { + // indicates the list is actually (ephemerally) empty + if (next == NULL) return NULL; + q->tail = next; + tail = next; + next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); + } + if (next != NULL) { + q->tail = next; + return tail; + } + gpr_mpscq_node *head = (gpr_mpscq_node *)gpr_atm_acq_load(&q->head); + if (tail != head) { + // indicates a retry is in order: we're still adding + return NULL; + } + gpr_mpscq_push(q, &q->stub); + next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); + if (next != NULL) { + q->tail = next; + return tail; + } + // indicates a retry is in order: we're still adding + return NULL; +} diff --git a/src/core/lib/support/mpscq.h b/src/core/lib/support/mpscq.h new file mode 100644 index 0000000000..977a117952 --- /dev/null +++ b/src/core/lib/support/mpscq.h @@ -0,0 +1,65 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_SUPPORT_MPSCQ_H +#define GRPC_CORE_LIB_SUPPORT_MPSCQ_H + +#include +#include + +// Multiple-producer single-consumer lock free queue, based upon the +// implementation from Dmitry Vyukov here: +// http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue + +// List node (include this in a data structure at the top, and add application +// fields after it - to simulate inheritance) +typedef struct gpr_mpscq_node { gpr_atm next; } gpr_mpscq_node; + +// Actual queue type +typedef struct gpr_mpscq { + gpr_atm head; + // make sure head & tail don't share a cacheline + char padding[GPR_CACHELINE_SIZE]; + gpr_mpscq_node *tail; + gpr_mpscq_node stub; +} gpr_mpscq; + +void gpr_mpscq_init(gpr_mpscq *q); +void gpr_mpscq_destroy(gpr_mpscq *q); +// Push a node +void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n); +// Pop a node (returns NULL if no node is ready - which doesn't indicate that +// the queue is empty!!) +gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q); + +#endif /* GRPC_CORE_LIB_SUPPORT_MPSCQ_H */ diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 772681109a..119f5e82ab 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -109,6 +109,10 @@ typedef struct batch_control { uint8_t recv_message; uint8_t recv_final_op; uint8_t is_notify_tag_closure; + + /* TODO(ctiller): now that this is inlined, figure out how much of the above + state can be eliminated */ + grpc_transport_stream_op op; } batch_control; struct grpc_call { @@ -778,6 +782,7 @@ typedef struct termination_closure { grpc_error *error; grpc_closure *op_closure; enum { TC_CANCEL, TC_CLOSE } type; + grpc_transport_stream_op op; } termination_closure; static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp, @@ -797,26 +802,24 @@ static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp, } static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { - grpc_transport_stream_op op; termination_closure *tc = tcp; - memset(&op, 0, sizeof(op)); - op.cancel_error = tc->error; + memset(&tc->op, 0, sizeof(tc->op)); + tc->op.cancel_error = tc->error; /* reuse closure to catch completion */ grpc_closure_init(&tc->closure, done_termination, tc); - op.on_complete = &tc->closure; - execute_op(exec_ctx, tc->call, &op); + tc->op.on_complete = &tc->closure; + execute_op(exec_ctx, tc->call, &tc->op); } static void send_close(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { - grpc_transport_stream_op op; termination_closure *tc = tcp; - memset(&op, 0, sizeof(op)); - op.close_error = tc->error; + memset(&tc->op, 0, sizeof(tc->op)); + tc->op.close_error = tc->error; /* reuse closure to catch completion */ grpc_closure_init(&tc->closure, done_termination, tc); - tc->op_closure = op.on_complete; - op.on_complete = &tc->closure; - execute_op(exec_ctx, tc->call, &op); + tc->op_closure = tc->op.on_complete; + tc->op.on_complete = &tc->closure; + execute_op(exec_ctx, tc->call, &tc->op); } static grpc_call_error terminate_with_status(grpc_exec_ctx *exec_ctx, @@ -1370,7 +1373,6 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_call *call, const grpc_op *ops, size_t nops, void *notify_tag, int is_notify_tag_closure) { - grpc_transport_stream_op stream_op; size_t i; const grpc_op *op; batch_control *bctl; @@ -1384,8 +1386,6 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag); - memset(&stream_op, 0, sizeof(stream_op)); - /* TODO(ctiller): this feels like it could be made lock-free */ gpr_mu_lock(&call->mu); bctl = allocate_batch_control(call); @@ -1394,6 +1394,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, bctl->notify_tag = notify_tag; bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0); + grpc_transport_stream_op *stream_op = &bctl->op; + memset(stream_op, 0, sizeof(*stream_op)); + if (nops == 0) { GRPC_CALL_INTERNAL_REF(call, "completion"); bctl->error = GRPC_ERROR_NONE; @@ -1471,9 +1474,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, } /* TODO(ctiller): just make these the same variable? */ call->metadata_batch[0][0].deadline = call->send_deadline; - stream_op.send_initial_metadata = + stream_op->send_initial_metadata = &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]; - stream_op.send_initial_metadata_flags = op->flags; + stream_op->send_initial_metadata_flags = op->flags; break; case GRPC_OP_SEND_MESSAGE: if (!are_write_flags_valid(op->flags)) { @@ -1493,7 +1496,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_slice_buffer_stream_init( &call->sending_stream, &op->data.send_message->data.raw.slice_buffer, op->flags); - stream_op.send_message = &call->sending_stream.base; + stream_op->send_message = &call->sending_stream.base; break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: /* Flag validation: currently allow no flags */ @@ -1511,7 +1514,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, } bctl->send_final_op = 1; call->sent_final_op = 1; - stream_op.send_trailing_metadata = + stream_op->send_trailing_metadata = &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]; break; case GRPC_OP_SEND_STATUS_FROM_SERVER: @@ -1558,7 +1561,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, error = GRPC_CALL_ERROR_INVALID_METADATA; goto done_with_error; } - stream_op.send_trailing_metadata = + stream_op->send_trailing_metadata = &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]; break; case GRPC_OP_RECV_INITIAL_METADATA: @@ -1576,9 +1579,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, grpc_closure_init(&call->receiving_initial_metadata_ready, receiving_initial_metadata_ready, bctl); bctl->recv_initial_metadata = 1; - stream_op.recv_initial_metadata = + stream_op->recv_initial_metadata = &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */]; - stream_op.recv_initial_metadata_ready = + stream_op->recv_initial_metadata_ready = &call->receiving_initial_metadata_ready; num_completion_callbacks_needed++; break; @@ -1595,10 +1598,10 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->receiving_message = 1; bctl->recv_message = 1; call->receiving_buffer = op->data.recv_message; - stream_op.recv_message = &call->receiving_stream; + stream_op->recv_message = &call->receiving_stream; grpc_closure_init(&call->receiving_stream_ready, receiving_stream_ready, bctl); - stream_op.recv_message_ready = &call->receiving_stream_ready; + stream_op->recv_message_ready = &call->receiving_stream_ready; num_completion_callbacks_needed++; break; case GRPC_OP_RECV_STATUS_ON_CLIENT: @@ -1624,9 +1627,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->final_op.client.status_details_capacity = op->data.recv_status_on_client.status_details_capacity; bctl->recv_final_op = 1; - stream_op.recv_trailing_metadata = + stream_op->recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - stream_op.collect_stats = + stream_op->collect_stats = &call->final_info.stats.transport_stream_stats; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: @@ -1647,9 +1650,9 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, call->final_op.server.cancelled = op->data.recv_close_on_server.cancelled; bctl->recv_final_op = 1; - stream_op.recv_trailing_metadata = + stream_op->recv_trailing_metadata = &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; - stream_op.collect_stats = + stream_op->collect_stats = &call->final_info.stats.transport_stream_stats; break; } @@ -1661,12 +1664,12 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, } gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed); - stream_op.context = call->context; + stream_op->context = call->context; grpc_closure_init(&bctl->finish_batch, finish_batch, bctl); - stream_op.on_complete = &bctl->finish_batch; + stream_op->on_complete = &bctl->finish_batch; gpr_mu_unlock(&call->mu); - execute_op(exec_ctx, call, &stream_op); + execute_op(exec_ctx, call, stream_op); done: GPR_TIMER_END("grpc_call_start_batch", 0); diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c index 6d2b1c4935..52e78567bd 100644 --- a/src/core/lib/surface/channel.c +++ b/src/core/lib/surface/channel.c @@ -334,14 +334,13 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg, } void grpc_channel_destroy(grpc_channel *channel) { - grpc_transport_op op; + grpc_transport_op *op = grpc_make_transport_op(NULL); grpc_channel_element *elem; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel)); - memset(&op, 0, sizeof(op)); - op.disconnect_with_error = GRPC_ERROR_CREATE("Channel Destroyed"); + op->disconnect_with_error = GRPC_ERROR_CREATE("Channel Destroyed"); elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0); - elem->filter->start_transport_op(&exec_ctx, elem, &op); + elem->filter->start_transport_op(&exec_ctx, elem, op); GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "channel"); diff --git a/src/core/lib/surface/channel_ping.c b/src/core/lib/surface/channel_ping.c index 9818f9d2f2..0d2f01a649 100644 --- a/src/core/lib/surface/channel_ping.c +++ b/src/core/lib/surface/channel_ping.c @@ -61,19 +61,20 @@ static void ping_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved) { - grpc_transport_op op; + GRPC_API_TRACE("grpc_channel_ping(channel=%p, cq=%p, tag=%p, reserved=%p)", 4, + (channel, cq, tag, reserved)); + grpc_transport_op *op = grpc_make_transport_op(NULL); ping_result *pr = gpr_malloc(sizeof(*pr)); grpc_channel_element *top_elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT(reserved == NULL); - memset(&op, 0, sizeof(op)); pr->tag = tag; pr->cq = cq; grpc_closure_init(&pr->closure, ping_done, pr); - op.send_ping = &pr->closure; - op.bind_pollset = grpc_cq_pollset(cq); + op->send_ping = &pr->closure; + op->bind_pollset = grpc_cq_pollset(cq); grpc_cq_begin_op(cq, tag); - top_elem->filter->start_transport_op(&exec_ctx, top_elem, &op); + top_elem->filter->start_transport_op(&exec_ctx, top_elem, op); grpc_exec_ctx_finish(&exec_ctx); } diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index 5397913a21..edda0c85fa 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -47,6 +47,7 @@ #include "src/core/lib/channel/http_server_filter.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/http/parser.h" +#include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/profiling/timers.h" @@ -165,6 +166,7 @@ void grpc_init(void) { grpc_register_tracer("http1", &grpc_http1_trace); grpc_register_tracer("compression", &grpc_compression_trace); grpc_register_tracer("queue_pluck", &grpc_cq_pluck_trace); + grpc_register_tracer("combiner", &grpc_combiner_trace); // Default pluck trace to 1 grpc_cq_pluck_trace = 1; grpc_register_tracer("queue_timeout", &grpc_cq_event_timeout_trace); diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c index 19b78369dd..d32c884e8e 100644 --- a/src/core/lib/surface/lame_client.c +++ b/src/core/lib/surface/lame_client.c @@ -97,14 +97,14 @@ static void lame_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_exec_ctx_sched(exec_ctx, op->on_connectivity_state_change, GRPC_ERROR_NONE, NULL); } - if (op->on_consumed != NULL) { - grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); - } if (op->send_ping != NULL) { grpc_exec_ctx_sched(exec_ctx, op->send_ping, GRPC_ERROR_CREATE("lame client channel"), NULL); } GRPC_ERROR_UNREF(op->disconnect_with_error); + if (op->on_consumed != NULL) { + grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL); + } } static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index 55e6d99057..56fb80e92e 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -273,23 +273,20 @@ static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg, } static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel, - bool send_goaway, grpc_error *send_disconnect) { - grpc_transport_op op; - struct shutdown_cleanup_args *sc; + int send_goaway, grpc_error *send_disconnect) { + struct shutdown_cleanup_args *sc = gpr_malloc(sizeof(*sc)); + grpc_closure_init(&sc->closure, shutdown_cleanup, sc); + grpc_transport_op *op = grpc_make_transport_op(&sc->closure); grpc_channel_element *elem; - memset(&op, 0, sizeof(op)); - op.send_goaway = send_goaway; - sc = gpr_malloc(sizeof(*sc)); + op->send_goaway = send_goaway; sc->slice = gpr_slice_from_copied_string("Server shutdown"); - op.goaway_message = &sc->slice; - op.goaway_status = GRPC_STATUS_OK; - op.disconnect_with_error = send_disconnect; - grpc_closure_init(&sc->closure, shutdown_cleanup, sc); - op.on_consumed = &sc->closure; + op->goaway_message = &sc->slice; + op->goaway_status = GRPC_STATUS_OK; + op->disconnect_with_error = send_disconnect; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); - elem->filter->start_transport_op(exec_ctx, elem, &op); + elem->filter->start_transport_op(exec_ctx, elem, op); } static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx, @@ -432,7 +429,8 @@ static void finish_destroy_channel(grpc_exec_ctx *exec_ctx, void *cd, server_unref(exec_ctx, server); } -static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) { +static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand, + grpc_error *error) { if (is_channel_orphaned(chand)) return; GPR_ASSERT(chand->server != NULL); orphan_channel(chand); @@ -441,14 +439,20 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) { chand->finish_destroy_channel_closure.cb = finish_destroy_channel; chand->finish_destroy_channel_closure.cb_arg = chand; - grpc_transport_op op; - memset(&op, 0, sizeof(op)); - op.set_accept_stream = true; - op.on_consumed = &chand->finish_destroy_channel_closure; + grpc_transport_op *op = + grpc_make_transport_op(&chand->finish_destroy_channel_closure); + op->set_accept_stream = true; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), - &op); + op); + + if (error != GRPC_ERROR_NONE) { + const char *msg = grpc_error_string(error); + gpr_log(GPR_INFO, "Disconnected client: %s", msg); + grpc_error_free_string(msg); + } + GRPC_ERROR_UNREF(error); } static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) { @@ -845,17 +849,16 @@ static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd, channel_data *chand = cd; grpc_server *server = chand->server; if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) { - grpc_transport_op op; - memset(&op, 0, sizeof(op)); - op.on_connectivity_state_change = &chand->channel_connectivity_changed, - op.connectivity_state = &chand->connectivity_state; + grpc_transport_op *op = grpc_make_transport_op(NULL); + op->on_connectivity_state_change = &chand->channel_connectivity_changed, + op->connectivity_state = &chand->connectivity_state; grpc_channel_next_op(exec_ctx, grpc_channel_stack_element( grpc_channel_get_channel_stack(chand->channel), 0), - &op); + op); } else { gpr_mu_lock(&server->mu_global); - destroy_channel(exec_ctx, chand); + destroy_channel(exec_ctx, chand, GRPC_ERROR_REF(error)); gpr_mu_unlock(&server->mu_global); GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->channel, "connectivity"); } @@ -1119,7 +1122,7 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, size_t slots; uint32_t probes; uint32_t max_probes = 0; - grpc_transport_op op; + grpc_transport_op *op = NULL; channel = grpc_channel_create(exec_ctx, NULL, args, GRPC_SERVER_CHANNEL, transport); @@ -1179,16 +1182,16 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, gpr_mu_unlock(&s->mu_global); GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity"); - memset(&op, 0, sizeof(op)); - 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; + op = grpc_make_transport_op(NULL); + 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; if (gpr_atm_acq_load(&s->shutdown_flag) != 0) { - op.disconnect_with_error = GRPC_ERROR_CREATE("Server shutdown"); + op->disconnect_with_error = GRPC_ERROR_CREATE("Server shutdown"); } - grpc_transport_perform_op(exec_ctx, transport, &op); + grpc_transport_perform_op(exec_ctx, transport, op); } void done_published_shutdown(grpc_exec_ctx *exec_ctx, void *done_arg, diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c index 857c3909d2..08f9d7e8d9 100644 --- a/src/core/lib/transport/transport.c +++ b/src/core/lib/transport/transport.c @@ -32,10 +32,14 @@ */ #include "src/core/lib/transport/transport.h" + +#include + #include #include #include #include + #include "src/core/lib/support/string.h" #include "src/core/lib/transport/transport_impl.h" @@ -247,3 +251,26 @@ void grpc_transport_stream_op_add_close(grpc_transport_stream_op *op, error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, status); add_error(op, &op->close_error, error); } + +typedef struct { + grpc_closure outer_on_complete; + grpc_closure *inner_on_complete; + grpc_transport_op op; +} made_transport_op; + +static void destroy_made_transport_op(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + made_transport_op *op = arg; + grpc_exec_ctx_sched(exec_ctx, op->inner_on_complete, GRPC_ERROR_REF(error), + NULL); + gpr_free(op); +} + +grpc_transport_op *grpc_make_transport_op(grpc_closure *on_complete) { + made_transport_op *op = gpr_malloc(sizeof(*op)); + grpc_closure_init(&op->outer_on_complete, destroy_made_transport_op, op); + op->inner_on_complete = on_complete; + memset(&op->op, 0, sizeof(op->op)); + op->op.on_consumed = &op->outer_on_complete; + return &op->op; +} diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 26ed6cb839..8dc393fd61 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -100,6 +100,11 @@ void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats *from, void grpc_transport_move_stats(grpc_transport_stream_stats *from, grpc_transport_stream_stats *to); +typedef struct { + grpc_closure closure; + void *args[2]; +} grpc_transport_private_op_data; + /* Transport stream op: a set of operations to perform on a transport against a single stream */ typedef struct grpc_transport_stream_op { @@ -149,6 +154,12 @@ typedef struct grpc_transport_stream_op { /* Indexes correspond to grpc_context_index enum values */ grpc_call_context_element *context; + + /*************************************************************************** + * remaining fields are initialized and used at the discretion of the + * transport implementation */ + + grpc_transport_private_op_data transport_private; } grpc_transport_stream_op; /** Transport op: a set of operations to perform on a transport as a whole */ @@ -182,6 +193,12 @@ typedef struct grpc_transport_op { grpc_pollset_set *bind_pollset_set; /** send a ping, call this back if not NULL */ grpc_closure *send_ping; + + /*************************************************************************** + * remaining fields are initialized and used at the discretion of the + * transport implementation */ + + grpc_transport_private_op_data transport_private; } grpc_transport_op; /* Returns the amount of memory required to store a grpc_stream for this @@ -273,6 +290,10 @@ void grpc_transport_destroy(grpc_exec_ctx *exec_ctx, grpc_transport *transport); char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *transport); +/* Allocate a grpc_transport_op, and preconfigure the on_consumed closure to + \a on_consumed and then delete the returned transport op */ +grpc_transport_op *grpc_make_transport_op(grpc_closure *on_consumed); + #ifdef __cplusplus } #endif diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index be7f30c29b..d53f46b18b 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -50,6 +50,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/support/log_linux.c', 'src/core/lib/support/log_posix.c', 'src/core/lib/support/log_windows.c', + 'src/core/lib/support/mpscq.c', 'src/core/lib/support/murmur_hash.c', 'src/core/lib/support/percent_encoding.c', 'src/core/lib/support/slice.c', @@ -92,6 +93,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', 'src/core/lib/iomgr/closure.c', + 'src/core/lib/iomgr/combiner.c', 'src/core/lib/iomgr/endpoint.c', 'src/core/lib/iomgr/endpoint_pair_posix.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', diff --git a/test/core/iomgr/combiner_test.c b/test/core/iomgr/combiner_test.c new file mode 100644 index 0000000000..197998c1e5 --- /dev/null +++ b/test/core/iomgr/combiner_test.c @@ -0,0 +1,164 @@ +/* + * + * 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. + * + */ + +#include "src/core/lib/iomgr/combiner.h" + +#include +#include +#include +#include +#include + +#include "test/core/util/test_config.h" + +static void test_no_op(void) { + gpr_log(GPR_DEBUG, "test_no_op"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_combiner_destroy(&exec_ctx, grpc_combiner_create(NULL)); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void set_bool_to_true(grpc_exec_ctx *exec_ctx, void *value, + grpc_error *error) { + *(bool *)value = true; +} + +static void test_execute_one(void) { + gpr_log(GPR_DEBUG, "test_execute_one"); + + grpc_combiner *lock = grpc_combiner_create(NULL); + bool done = false; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_combiner_execute(&exec_ctx, lock, + grpc_closure_create(set_bool_to_true, &done), + GRPC_ERROR_NONE); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(done); + grpc_combiner_destroy(&exec_ctx, lock); + grpc_exec_ctx_finish(&exec_ctx); +} + +typedef struct { + size_t ctr; + grpc_combiner *lock; +} thd_args; + +typedef struct { + size_t *ctr; + size_t value; +} ex_args; + +static void check_one(grpc_exec_ctx *exec_ctx, void *a, grpc_error *error) { + ex_args *args = a; + GPR_ASSERT(*args->ctr == args->value - 1); + *args->ctr = args->value; + gpr_free(a); +} + +static void execute_many_loop(void *a) { + thd_args *args = a; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + size_t n = 1; + for (size_t i = 0; i < 10; i++) { + for (size_t j = 0; j < 10000; j++) { + ex_args *c = gpr_malloc(sizeof(*c)); + c->ctr = &args->ctr; + c->value = n++; + grpc_combiner_execute(&exec_ctx, args->lock, + grpc_closure_create(check_one, c), GRPC_ERROR_NONE); + grpc_exec_ctx_flush(&exec_ctx); + } + // sleep for a little bit, to test a combiner draining and another thread + // picking it up + gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); + } + grpc_exec_ctx_finish(&exec_ctx); +} + +static void test_execute_many(void) { + gpr_log(GPR_DEBUG, "test_execute_many"); + + grpc_combiner *lock = grpc_combiner_create(NULL); + gpr_thd_id thds[100]; + thd_args ta[GPR_ARRAY_SIZE(thds)]; + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + ta[i].ctr = 0; + ta[i].lock = lock; + GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &ta[i], &options)); + } + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_join(thds[i]); + } + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_combiner_destroy(&exec_ctx, lock); + grpc_exec_ctx_finish(&exec_ctx); +} + +static bool got_in_finally = false; + +static void in_finally(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + got_in_finally = true; +} + +static void add_finally(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + grpc_combiner_execute_finally(exec_ctx, arg, + grpc_closure_create(in_finally, NULL), + GRPC_ERROR_NONE, false); +} + +static void test_execute_finally(void) { + gpr_log(GPR_DEBUG, "test_execute_finally"); + + grpc_combiner *lock = grpc_combiner_create(NULL); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_combiner_execute(&exec_ctx, lock, grpc_closure_create(add_finally, lock), + GRPC_ERROR_NONE); + grpc_exec_ctx_flush(&exec_ctx); + GPR_ASSERT(got_in_finally); + grpc_combiner_destroy(&exec_ctx, lock); + grpc_exec_ctx_finish(&exec_ctx); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + grpc_init(); + test_no_op(); + test_execute_one(); + test_execute_finally(); + test_execute_many(); + grpc_shutdown(); + + return 0; +} diff --git a/test/core/support/mpscq_test.c b/test/core/support/mpscq_test.c new file mode 100644 index 0000000000..491eb9148b --- /dev/null +++ b/test/core/support/mpscq_test.c @@ -0,0 +1,206 @@ +/* + * + * 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/lib/support/mpscq.h" + +#include + +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" + +typedef struct test_node { + gpr_mpscq_node node; + size_t i; + size_t *ctr; +} test_node; + +static test_node *new_node(size_t i, size_t *ctr) { + test_node *n = gpr_malloc(sizeof(test_node)); + n->i = i; + n->ctr = ctr; + return n; +} + +static void test_serial(void) { + gpr_log(GPR_DEBUG, "test_serial"); + gpr_mpscq q; + gpr_mpscq_init(&q); + for (size_t i = 0; i < 10000000; i++) { + gpr_mpscq_push(&q, &new_node(i, NULL)->node); + } + for (size_t i = 0; i < 10000000; i++) { + test_node *n = (test_node *)gpr_mpscq_pop(&q); + GPR_ASSERT(n); + GPR_ASSERT(n->i == i); + gpr_free(n); + } +} + +typedef struct { + size_t ctr; + gpr_mpscq *q; + gpr_event *start; +} thd_args; + +#define THREAD_ITERATIONS 100000 + +static void test_thread(void *args) { + thd_args *a = args; + gpr_event_wait(a->start, gpr_inf_future(GPR_CLOCK_REALTIME)); + for (size_t i = 1; i <= THREAD_ITERATIONS; i++) { + gpr_mpscq_push(a->q, &new_node(i, &a->ctr)->node); + } +} + +static void test_mt(void) { + gpr_log(GPR_DEBUG, "test_mt"); + gpr_event start; + gpr_event_init(&start); + gpr_thd_id thds[100]; + thd_args ta[GPR_ARRAY_SIZE(thds)]; + gpr_mpscq q; + gpr_mpscq_init(&q); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + ta[i].ctr = 0; + ta[i].q = &q; + ta[i].start = &start; + GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); + } + size_t num_done = 0; + size_t spins = 0; + gpr_event_set(&start, (void *)1); + while (num_done != GPR_ARRAY_SIZE(thds)) { + gpr_mpscq_node *n; + while ((n = gpr_mpscq_pop(&q)) == NULL) { + spins++; + } + test_node *tn = (test_node *)n; + GPR_ASSERT(*tn->ctr == tn->i - 1); + *tn->ctr = tn->i; + if (tn->i == THREAD_ITERATIONS) num_done++; + gpr_free(tn); + } + gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, spins); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_join(thds[i]); + } + gpr_mpscq_destroy(&q); +} + +typedef struct { + thd_args *ta; + size_t num_thds; + gpr_mu mu; + size_t num_done; + size_t spins; + gpr_mpscq *q; + gpr_event *start; +} pull_args; + +static void pull_thread(void *arg) { + pull_args *pa = arg; + gpr_event_wait(pa->start, gpr_inf_future(GPR_CLOCK_REALTIME)); + + for (;;) { + gpr_mu_lock(&pa->mu); + if (pa->num_done == pa->num_thds) { + gpr_mu_unlock(&pa->mu); + return; + } + gpr_mpscq_node *n; + while ((n = gpr_mpscq_pop(pa->q)) == NULL) { + pa->spins++; + } + test_node *tn = (test_node *)n; + GPR_ASSERT(*tn->ctr == tn->i - 1); + *tn->ctr = tn->i; + if (tn->i == THREAD_ITERATIONS) pa->num_done++; + gpr_free(tn); + gpr_mu_unlock(&pa->mu); + } +} + +static void test_mt_multipop(void) { + gpr_log(GPR_DEBUG, "test_mt_multipop"); + gpr_event start; + gpr_event_init(&start); + gpr_thd_id thds[100]; + gpr_thd_id pull_thds[100]; + thd_args ta[GPR_ARRAY_SIZE(thds)]; + gpr_mpscq q; + gpr_mpscq_init(&q); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + ta[i].ctr = 0; + ta[i].q = &q; + ta[i].start = &start; + GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options)); + } + pull_args pa; + pa.ta = ta; + pa.num_thds = GPR_ARRAY_SIZE(thds); + pa.spins = 0; + pa.num_done = 0; + pa.q = &q; + pa.start = &start; + gpr_mu_init(&pa.mu); + for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + GPR_ASSERT(gpr_thd_new(&pull_thds[i], pull_thread, &pa, &options)); + } + gpr_event_set(&start, (void *)1); + for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) { + gpr_thd_join(pull_thds[i]); + } + gpr_log(GPR_DEBUG, "spins: %" PRIdPTR, pa.spins); + for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) { + gpr_thd_join(thds[i]); + } + gpr_mpscq_destroy(&q); +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_serial(); + test_mt(); + test_mt_multipop(); + return 0; +} diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index 2894b0c66f..6afcefca92 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -49,32 +49,31 @@ static void *tag(intptr_t x) { return (void *)x; } void verify_connectivity(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { - grpc_transport_op *op = arg; - GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *op->connectivity_state); + grpc_connectivity_state *state = arg; + GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == *state); GPR_ASSERT(error == GRPC_ERROR_NONE); } void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} void test_transport_op(grpc_channel *channel) { - grpc_transport_op op; + grpc_transport_op *op; grpc_channel_element *elem; grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - memset(&op, 0, sizeof(op)); - grpc_closure_init(&transport_op_cb, verify_connectivity, &op); + grpc_closure_init(&transport_op_cb, verify_connectivity, &state); - op.on_connectivity_state_change = &transport_op_cb; - op.connectivity_state = &state; + op = grpc_make_transport_op(NULL); + op->on_connectivity_state_change = &transport_op_cb; + op->connectivity_state = &state; elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); - elem->filter->start_transport_op(&exec_ctx, elem, &op); + elem->filter->start_transport_op(&exec_ctx, elem, op); grpc_exec_ctx_finish(&exec_ctx); - memset(&op, 0, sizeof(op)); grpc_closure_init(&transport_op_cb, do_nothing, NULL); - op.on_consumed = &transport_op_cb; - elem->filter->start_transport_op(&exec_ctx, elem, &op); + op = grpc_make_transport_op(&transport_op_cb); + elem->filter->start_transport_op(&exec_ctx, elem, op); grpc_exec_ctx_finish(&exec_ctx); } diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 06b68c3b74..0a412dd706 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -889,6 +889,7 @@ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ src/core/lib/http/parser.h \ src/core/lib/iomgr/closure.h \ +src/core/lib/iomgr/combiner.h \ src/core/lib/iomgr/endpoint.h \ src/core/lib/iomgr/endpoint_pair.h \ src/core/lib/iomgr/error.h \ @@ -1001,6 +1002,7 @@ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ +src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 02590db421..1c55859d26 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -806,6 +806,7 @@ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ src/core/lib/http/parser.h \ src/core/lib/iomgr/closure.h \ +src/core/lib/iomgr/combiner.h \ src/core/lib/iomgr/endpoint.h \ src/core/lib/iomgr/endpoint_pair.h \ src/core/lib/iomgr/error.h \ @@ -965,6 +966,7 @@ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ src/core/lib/iomgr/closure.c \ +src/core/lib/iomgr/combiner.c \ src/core/lib/iomgr/endpoint.c \ src/core/lib/iomgr/endpoint_pair_posix.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ @@ -1185,6 +1187,7 @@ src/core/lib/profiling/timers.h \ src/core/lib/support/backoff.h \ src/core/lib/support/block_annotate.h \ src/core/lib/support/env.h \ +src/core/lib/support/mpscq.h \ src/core/lib/support/murmur_hash.h \ src/core/lib/support/percent_encoding.h \ src/core/lib/support/stack_lockfree.h \ @@ -1213,6 +1216,7 @@ src/core/lib/support/log_android.c \ src/core/lib/support/log_linux.c \ src/core/lib/support/log_posix.c \ src/core/lib/support/log_windows.c \ +src/core/lib/support/mpscq.c \ src/core/lib/support/murmur_hash.c \ src/core/lib/support/percent_encoding.c \ src/core/lib/support/slice.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index db84f21968..37355c7e11 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -252,6 +252,22 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "language": "c", + "name": "combiner_test", + "src": [ + "test/core/iomgr/combiner_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -624,6 +640,20 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util" + ], + "headers": [], + "language": "c", + "name": "gpr_mpscq_test", + "src": [ + "test/core/support/mpscq_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -5735,6 +5765,7 @@ "src/core/lib/support/backoff.h", "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", + "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/percent_encoding.h", "src/core/lib/support/stack_lockfree.h", @@ -5799,6 +5830,8 @@ "src/core/lib/support/log_linux.c", "src/core/lib/support/log_posix.c", "src/core/lib/support/log_windows.c", + "src/core/lib/support/mpscq.c", + "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.c", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/percent_encoding.c", @@ -5905,6 +5938,7 @@ "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", @@ -6011,6 +6045,8 @@ "src/core/lib/http/parser.h", "src/core/lib/iomgr/closure.c", "src/core/lib/iomgr/closure.h", + "src/core/lib/iomgr/combiner.c", + "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/endpoint.c", "src/core/lib/iomgr/endpoint.h", "src/core/lib/iomgr/endpoint_pair.h", diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index 51e1dff96e..fcd1bafce0 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -295,6 +295,27 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 30, + "exclude_configs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "combiner_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, { "args": [], "ci_platforms": [ @@ -697,6 +718,27 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 30, + "exclude_configs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "gpr_mpscq_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, { "args": [], "ci_platforms": [ diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index 8f3546f7be..04f487689c 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -175,6 +175,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chttp2_varint_test", "vcxpr {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "combiner_test", "vcxproj\test\combiner_test\combiner_test.vcxproj", "{C237D1E4-8825-80BA-1FC3-5E147E53E96E}" + 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}") = "compression_test", "vcxproj\test\compression_test\compression_test.vcxproj", "{5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}" ProjectSection(myProperties) = preProject lib = "False" @@ -382,6 +393,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_log_test", "vcxproj\tes {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gpr_mpscq_test", "vcxproj\test\gpr_mpscq_test\gpr_mpscq_test.vcxproj", "{B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {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}") = "gpr_percent_encoding_test", "vcxproj\test\gpr_percent_encoding_test\gpr_percent_encoding_test.vcxproj", "{8313AE17-FCFA-8110-95C7-7AF2F814D188}" ProjectSection(myProperties) = preProject lib = "False" @@ -1720,6 +1740,22 @@ Global {6B29F634-1277-74B8-47F6-78756190BA7B}.Release-DLL|Win32.Build.0 = Release|Win32 {6B29F634-1277-74B8-47F6-78756190BA7B}.Release-DLL|x64.ActiveCfg = Release|x64 {6B29F634-1277-74B8-47F6-78756190BA7B}.Release-DLL|x64.Build.0 = Release|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|Win32.ActiveCfg = Debug|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|x64.ActiveCfg = Debug|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|Win32.ActiveCfg = Release|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|x64.ActiveCfg = Release|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|Win32.Build.0 = Debug|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug|x64.Build.0 = Debug|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|Win32.Build.0 = Release|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release|x64.Build.0 = Release|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Debug-DLL|x64.Build.0 = Debug|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|Win32.Build.0 = Release|Win32 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|x64.ActiveCfg = Release|x64 + {C237D1E4-8825-80BA-1FC3-5E147E53E96E}.Release-DLL|x64.Build.0 = Release|x64 {5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Debug|Win32.ActiveCfg = Debug|Win32 {5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Debug|x64.ActiveCfg = Debug|x64 {5AFE7D17-A4A7-D68E-4491-CBC852F9D2A0}.Release|Win32.ActiveCfg = Release|Win32 @@ -2072,6 +2108,22 @@ Global {38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release-DLL|Win32.Build.0 = Release|Win32 {38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release-DLL|x64.ActiveCfg = Release|x64 {38797EE3-62CC-3CBF-18D5-009ED6DD0BEC}.Release-DLL|x64.Build.0 = Release|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|Win32.ActiveCfg = Debug|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|x64.ActiveCfg = Debug|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|Win32.ActiveCfg = Release|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|x64.ActiveCfg = Release|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|Win32.Build.0 = Debug|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug|x64.Build.0 = Debug|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|Win32.Build.0 = Release|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release|x64.Build.0 = Release|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Debug-DLL|x64.Build.0 = Debug|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|Win32.Build.0 = Release|Win32 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|x64.ActiveCfg = Release|x64 + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6}.Release-DLL|x64.Build.0 = Release|x64 {8313AE17-FCFA-8110-95C7-7AF2F814D188}.Debug|Win32.ActiveCfg = Debug|Win32 {8313AE17-FCFA-8110-95C7-7AF2F814D188}.Debug|x64.ActiveCfg = Debug|x64 {8313AE17-FCFA-8110-95C7-7AF2F814D188}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index 519b5d9250..6ad67dda72 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -195,6 +195,7 @@ + @@ -245,6 +246,8 @@ + + diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index 9eac1ec519..95e56e9956 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -61,6 +61,9 @@ src\core\lib\support + + src\core\lib\support + src\core\lib\support @@ -281,6 +284,9 @@ src\core\lib\support + + src\core\lib\support + src\core\lib\support diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index 1bcb263911..354351364e 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -389,6 +389,7 @@ + @@ -551,6 +552,8 @@ + + diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index 7343c80cc4..e284e3f7f3 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -145,6 +145,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -761,6 +764,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index 3241bafa6b..ac1593464f 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -385,6 +385,7 @@ + @@ -537,6 +538,8 @@ + + diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index 3df26646fc..9352918fb0 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -130,6 +130,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -734,6 +737,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 7c120bcf02..98873ca8d7 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -315,6 +315,7 @@ + @@ -492,6 +493,8 @@ + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 9cbb2ce45b..f3d7958f7c 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -49,6 +49,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -713,6 +716,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index 80dd6b2dcb..b1bdde584d 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -206,6 +206,7 @@ + @@ -336,6 +337,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 8dc28d1cb9..b78c7bfb36 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -97,6 +97,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -494,6 +497,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index d4a85768c3..0ea880833a 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -305,6 +305,7 @@ + @@ -460,6 +461,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index fba5a02099..7549a9609d 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -52,6 +52,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -623,6 +626,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj b/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj new file mode 100644 index 0000000000..f889d21e2d --- /dev/null +++ b/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj @@ -0,0 +1,199 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {C237D1E4-8825-80BA-1FC3-5E147E53E96E} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + combiner_test + static + Debug + static + Debug + + + combiner_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + 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}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters b/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters new file mode 100644 index 0000000000..e8ebb09898 --- /dev/null +++ b/vsprojects/vcxproj/test/combiner_test/combiner_test.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\iomgr + + + + + + {82bca2af-d499-b405-fd05-4d345372496c} + + + {c32d8e20-b719-532d-ba23-bd9d523fac15} + + + {b4fa8ca1-e6c7-dec5-6d62-8a62396825c6} + + + + diff --git a/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj b/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj new file mode 100644 index 0000000000..01342868b0 --- /dev/null +++ b/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj @@ -0,0 +1,193 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B3D7760B-8BEA-2EF6-F1D4-9F9020E166D6} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + gpr_mpscq_test + static + Debug + static + Debug + + + gpr_mpscq_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + 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}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters b/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters new file mode 100644 index 0000000000..9cceb9f3e2 --- /dev/null +++ b/vsprojects/vcxproj/test/gpr_mpscq_test/gpr_mpscq_test.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\support + + + + + + {e82fb80c-10ba-2959-55d6-8653715f1e4f} + + + {32120233-25e6-f3e4-f828-c6408d47ec04} + + + {aa3a22bc-229a-c00a-dd4a-924c818c6a49} + + + + -- cgit v1.2.3 From 930c2983d34507765305a56c329c2e354168184b Mon Sep 17 00:00:00 2001 From: Dan Born Date: Thu, 8 Sep 2016 19:12:18 -0700 Subject: Safe server shutdown. --- .../chttp2/server/secure/server_secure_chttp2.c | 196 +++++++++++---------- src/core/lib/iomgr/tcp_server_posix.c | 36 ++-- test/core/iomgr/tcp_server_posix_test.c | 3 +- 3 files changed, 131 insertions(+), 104 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c index da3e284fcf..563271f4f8 100644 --- a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c @@ -61,13 +61,12 @@ typedef struct server_secure_state { grpc_server_credentials *creds; bool is_shutdown; gpr_mu mu; - gpr_refcount refcount; - grpc_closure destroy_closure; - grpc_closure *destroy_callback; + grpc_closure tcp_server_shutdown_complete; + grpc_closure *server_destroy_listener_done; } server_secure_state; typedef struct server_secure_connect { - server_secure_state *state; + server_secure_state *server_state; grpc_pollset *accepting_pollset; grpc_tcp_server_acceptor *acceptor; grpc_handshake_manager *handshake_mgr; @@ -77,39 +76,28 @@ typedef struct server_secure_connect { grpc_channel_args *args; } server_secure_connect; -static void state_ref(server_secure_state *state) { gpr_ref(&state->refcount); } - -static void state_unref(server_secure_state *state) { - if (gpr_unref(&state->refcount)) { - /* ensure all threads have unlocked */ - gpr_mu_lock(&state->mu); - gpr_mu_unlock(&state->mu); - /* clean up */ - GRPC_SECURITY_CONNECTOR_UNREF(&state->sc->base, "server"); - grpc_server_credentials_unref(state->creds); - gpr_free(state); - } -} - static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep, grpc_security_status status, grpc_endpoint *secure_endpoint, grpc_auth_context *auth_context) { - server_secure_connect *state = statep; + server_secure_connect *connection_state = statep; if (status == GRPC_SECURITY_OK) { if (secure_endpoint) { - gpr_mu_lock(&state->state->mu); - if (!state->state->is_shutdown) { + gpr_mu_lock(&connection_state->server_state->mu); + if (!connection_state->server_state->is_shutdown) { grpc_transport *transport = grpc_create_chttp2_transport( - exec_ctx, grpc_server_get_channel_args(state->state->server), + exec_ctx, grpc_server_get_channel_args( + connection_state->server_state->server), secure_endpoint, 0); grpc_arg args_to_add[2]; - args_to_add[0] = grpc_server_credentials_to_arg(state->state->creds); + args_to_add[0] = grpc_server_credentials_to_arg( + connection_state->server_state->creds); args_to_add[1] = grpc_auth_context_to_arg(auth_context); grpc_channel_args *args_copy = grpc_channel_args_copy_and_add( - state->args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); - grpc_server_setup_transport(exec_ctx, state->state->server, transport, - state->accepting_pollset, args_copy); + connection_state->args, args_to_add, GPR_ARRAY_SIZE(args_to_add)); + grpc_server_setup_transport( + exec_ctx, connection_state->server_state->server, transport, + connection_state->accepting_pollset, args_copy); grpc_channel_args_destroy(args_copy); grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL); } else { @@ -117,21 +105,21 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep, * gone away. */ grpc_endpoint_destroy(exec_ctx, secure_endpoint); } - gpr_mu_unlock(&state->state->mu); + gpr_mu_unlock(&connection_state->server_state->mu); } } else { gpr_log(GPR_ERROR, "Secure transport failed with error %d", status); } - grpc_channel_args_destroy(state->args); - state_unref(state->state); - gpr_free(state); + grpc_channel_args_destroy(connection_state->args); + grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp); + gpr_free(connection_state); } static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, grpc_channel_args *args, gpr_slice_buffer *read_buffer, void *user_data, grpc_error *error) { - server_secure_connect *state = user_data; + server_secure_connect *connection_state = user_data; if (error != GRPC_ERROR_NONE) { const char *error_str = grpc_error_string(error); gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str); @@ -139,81 +127,107 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint, GRPC_ERROR_UNREF(error); grpc_channel_args_destroy(args); gpr_free(read_buffer); - grpc_handshake_manager_shutdown(exec_ctx, state->handshake_mgr); - grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr); - state_unref(state->state); - gpr_free(state); + grpc_handshake_manager_shutdown(exec_ctx, connection_state->handshake_mgr); + grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); + grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp); + gpr_free(connection_state); return; } - grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr); - state->handshake_mgr = NULL; + grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr); + connection_state->handshake_mgr = NULL; // TODO(roth, jboeuf): Convert security connector handshaking to use new // handshake API, and then move the code from on_secure_handshake_done() // into this function. - state->args = args; + connection_state->args = args; grpc_server_security_connector_do_handshake( - exec_ctx, state->state->sc, state->acceptor, endpoint, read_buffer, - state->deadline, on_secure_handshake_done, state); + exec_ctx, connection_state->server_state->sc, connection_state->acceptor, + endpoint, read_buffer, connection_state->deadline, + on_secure_handshake_done, connection_state); } static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp, grpc_pollset *accepting_pollset, grpc_tcp_server_acceptor *acceptor) { - server_secure_connect *state = gpr_malloc(sizeof(*state)); - state->state = statep; - state_ref(state->state); - state->accepting_pollset = accepting_pollset; - state->acceptor = acceptor; - state->handshake_mgr = grpc_handshake_manager_create(); + server_secure_state *server_state = statep; + server_secure_connect *connection_state = NULL; + gpr_mu_lock(&server_state->mu); + if (server_state->is_shutdown) { + gpr_mu_unlock(&server_state->mu); + grpc_endpoint_destroy(exec_ctx, tcp); + return; + } + gpr_mu_unlock(&server_state->mu); + grpc_tcp_server_ref(server_state->tcp); + connection_state = gpr_malloc(sizeof(*connection_state)); + connection_state->server_state = server_state; + connection_state->accepting_pollset = accepting_pollset; + connection_state->acceptor = acceptor; + connection_state->handshake_mgr = grpc_handshake_manager_create(); // TODO(roth): We should really get this timeout value from channel // args instead of hard-coding it. - state->deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_seconds(120, GPR_TIMESPAN)); + connection_state->deadline = gpr_time_add( + gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN)); grpc_handshake_manager_do_handshake( - exec_ctx, state->handshake_mgr, tcp, - grpc_server_get_channel_args(state->state->server), state->deadline, - acceptor, on_handshake_done, state); + exec_ctx, connection_state->handshake_mgr, tcp, + grpc_server_get_channel_args(connection_state->server_state->server), + connection_state->deadline, acceptor, on_handshake_done, + connection_state); } /* Server callback: start listening on our ports */ -static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep, - grpc_pollset **pollsets, size_t pollset_count) { - server_secure_state *state = statep; - grpc_tcp_server_start(exec_ctx, state->tcp, pollsets, pollset_count, - on_accept, state); +static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server, + void *statep, grpc_pollset **pollsets, + size_t pollset_count) { + server_secure_state *server_state = statep; + gpr_mu_lock(&server_state->mu); + server_state->is_shutdown = false; + gpr_mu_unlock(&server_state->mu); + grpc_tcp_server_start(exec_ctx, server_state->tcp, pollsets, pollset_count, + on_accept, server_state); } -static void destroy_done(grpc_exec_ctx *exec_ctx, void *statep, - grpc_error *error) { - server_secure_state *state = statep; - if (state->destroy_callback != NULL) { - state->destroy_callback->cb(exec_ctx, state->destroy_callback->cb_arg, - GRPC_ERROR_REF(error)); +static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *statep, + grpc_error *error) { + server_secure_state *server_state = statep; + /* ensure all threads have unlocked */ + gpr_mu_lock(&server_state->mu); + grpc_closure *destroy_done = server_state->server_destroy_listener_done; + GPR_ASSERT(server_state->is_shutdown); + gpr_mu_unlock(&server_state->mu); + /* clean up */ + grpc_server_security_connector_shutdown(exec_ctx, server_state->sc); + + /* Flush queued work before a synchronous unref. */ + grpc_exec_ctx_flush(exec_ctx); + GRPC_SECURITY_CONNECTOR_UNREF(&server_state->sc->base, "server"); + grpc_server_credentials_unref(server_state->creds); + + if (destroy_done != NULL) { + destroy_done->cb(exec_ctx, destroy_done->cb_arg, GRPC_ERROR_REF(error)); + grpc_exec_ctx_flush(exec_ctx); } - grpc_server_security_connector_shutdown(exec_ctx, state->sc); - state_unref(state); + gpr_free(server_state); } -/* Server callback: destroy the tcp listener (so we don't generate further - callbacks) */ -static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep, - grpc_closure *callback) { - server_secure_state *state = statep; +static void server_destroy_listener(grpc_exec_ctx *exec_ctx, + grpc_server *server, void *statep, + grpc_closure *callback) { + server_secure_state *server_state = statep; grpc_tcp_server *tcp; - gpr_mu_lock(&state->mu); - state->is_shutdown = true; - state->destroy_callback = callback; - tcp = state->tcp; - gpr_mu_unlock(&state->mu); + gpr_mu_lock(&server_state->mu); + server_state->is_shutdown = true; + server_state->server_destroy_listener_done = callback; + tcp = server_state->tcp; + gpr_mu_unlock(&server_state->mu); grpc_tcp_server_shutdown_listeners(exec_ctx, tcp); - grpc_tcp_server_unref(exec_ctx, tcp); + grpc_tcp_server_unref(exec_ctx, server_state->tcp); } int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) { grpc_resolved_addresses *resolved = NULL; grpc_tcp_server *tcp = NULL; - server_secure_state *state = NULL; + server_secure_state *server_state = NULL; size_t i; size_t count = 0; int port_num = -1; @@ -253,22 +267,22 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, if (err != GRPC_ERROR_NONE) { goto error; } - state = gpr_malloc(sizeof(*state)); - memset(state, 0, sizeof(*state)); - grpc_closure_init(&state->destroy_closure, destroy_done, state); - err = grpc_tcp_server_create(&state->destroy_closure, + server_state = gpr_malloc(sizeof(*server_state)); + memset(server_state, 0, sizeof(*server_state)); + grpc_closure_init(&server_state->tcp_server_shutdown_complete, + tcp_server_shutdown_complete, server_state); + err = grpc_tcp_server_create(&server_state->tcp_server_shutdown_complete, grpc_server_get_channel_args(server), &tcp); if (err != GRPC_ERROR_NONE) { goto error; } - state->server = server; - state->tcp = tcp; - state->sc = sc; - state->creds = grpc_server_credentials_ref(creds); - state->is_shutdown = false; - gpr_mu_init(&state->mu); - gpr_ref_init(&state->refcount, 1); + server_state->server = server; + server_state->tcp = tcp; + server_state->sc = sc; + server_state->creds = grpc_server_credentials_ref(creds); + server_state->is_shutdown = true; + gpr_mu_init(&server_state->mu); errors = gpr_malloc(sizeof(*errors) * resolved->naddrs); for (i = 0; i < resolved->naddrs; i++) { @@ -313,7 +327,8 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_resolved_addresses_destroy(resolved); /* Register with the server only upon success */ - grpc_server_add_listener(&exec_ctx, server, state, start, destroy); + grpc_server_add_listener(&exec_ctx, server, server_state, + server_start_listener, server_destroy_listener); grpc_exec_ctx_finish(&exec_ctx); return port_num; @@ -334,10 +349,11 @@ error: grpc_tcp_server_unref(&exec_ctx, tcp); } else { if (sc) { + grpc_exec_ctx_flush(&exec_ctx); GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "server"); } - if (state) { - gpr_free(state); + if (server_state) { + gpr_free(server_state); } } grpc_exec_ctx_finish(&exec_ctx); diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c index 2d3f6cf9a7..5f846c8afb 100644 --- a/src/core/lib/iomgr/tcp_server_posix.c +++ b/src/core/lib/iomgr/tcp_server_posix.c @@ -191,6 +191,9 @@ grpc_error *grpc_tcp_server_create(grpc_closure *shutdown_complete, } static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { + gpr_mu_lock(&s->mu); + GPR_ASSERT(s->shutdown); + gpr_mu_unlock(&s->mu); if (s->shutdown_complete != NULL) { grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL); } @@ -652,6 +655,7 @@ unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, unsigned port_index) { unsigned num_fds = 0; grpc_tcp_listener *sp; + gpr_mu_lock(&s->mu); for (sp = s->head; sp && port_index != 0; sp = sp->next) { if (!sp->is_sibling) { --port_index; @@ -659,12 +663,15 @@ unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, } for (; sp; sp = sp->sibling, ++num_fds) ; + gpr_mu_unlock(&s->mu); return num_fds; } int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index, unsigned fd_index) { grpc_tcp_listener *sp; + int fd; + gpr_mu_lock(&s->mu); for (sp = s->head; sp && port_index != 0; sp = sp->next) { if (!sp->is_sibling) { --port_index; @@ -673,10 +680,12 @@ int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index, for (; sp && fd_index != 0; sp = sp->sibling, --fd_index) ; if (sp) { - return sp->fd; + fd = sp->fd; } else { - return -1; + fd = -1; } + gpr_mu_unlock(&s->mu); + return fd; } void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, @@ -722,7 +731,7 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, } grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { - gpr_ref(&s->refs); + gpr_ref_non_zero(&s->refs); return s; } @@ -736,18 +745,21 @@ void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { if (gpr_unref(&s->refs)) { - /* Complete shutdown_starting work before destroying. */ grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT; + bool finish_ctx = false; + /* FIXME: API allows a NULL exec_ctx, although this might cause us to delete + ourself before some enqueued work in some other exec_ctx runs. */ + if (exec_ctx == NULL) { + exec_ctx = &local_exec_ctx; + finish_ctx = true; + } + grpc_tcp_server_shutdown_listeners(exec_ctx, s); gpr_mu_lock(&s->mu); - grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL); + grpc_exec_ctx_enqueue_list(exec_ctx, &s->shutdown_starting, NULL); gpr_mu_unlock(&s->mu); - if (exec_ctx == NULL) { - grpc_exec_ctx_flush(&local_exec_ctx); - tcp_server_destroy(&local_exec_ctx, s); - grpc_exec_ctx_finish(&local_exec_ctx); - } else { - grpc_exec_ctx_finish(&local_exec_ctx); - tcp_server_destroy(exec_ctx, s); + tcp_server_destroy(exec_ctx, s); + if (finish_ctx) { + grpc_exec_ctx_finish(exec_ctx); } } } diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c index 6e2d1d0fc9..6b1dd428a1 100644 --- a/test/core/iomgr/tcp_server_posix_test.c +++ b/test/core/iomgr/tcp_server_posix_test.c @@ -314,11 +314,10 @@ static void test_connect(unsigned n) { GPR_ASSERT(grpc_tcp_server_port_fd(s, 0, 0) >= 0); grpc_tcp_server_unref(&exec_ctx, s); + grpc_exec_ctx_finish(&exec_ctx); /* Weak ref lost. */ GPR_ASSERT(weak_ref.server == NULL); - - grpc_exec_ctx_finish(&exec_ctx); } static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, -- cgit v1.2.3 From 331b9c02f9372ef832e612d48b90991c181ba8a7 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Mon, 12 Sep 2016 18:37:05 -0700 Subject: Moved LB token changes solely into grpclb.c --- src/core/ext/client_config/client_channel.c | 2 +- src/core/ext/client_config/lb_policy.c | 5 +- src/core/ext/client_config/lb_policy.h | 20 +- src/core/ext/client_config/lb_policy_factory.h | 25 ++- src/core/ext/lb_policy/grpclb/grpclb.c | 240 ++++++++++++++------- src/core/ext/lb_policy/pick_first/pick_first.c | 18 +- src/core/ext/lb_policy/round_robin/round_robin.c | 89 +++----- src/core/ext/resolver/dns/native/dns_resolver.c | 9 +- src/core/ext/resolver/sockaddr/sockaddr_resolver.c | 10 +- src/core/lib/transport/metadata.c | 18 +- src/core/lib/transport/metadata.h | 2 +- 11 files changed, 269 insertions(+), 169 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c index 8f1c821ebb..58ef629be0 100644 --- a/src/core/ext/client_config/client_channel.c +++ b/src/core/ext/client_config/client_channel.c @@ -572,7 +572,7 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, initial_metadata_flags, &calld->lb_token_mdelem}; r = grpc_lb_policy_pick(exec_ctx, lb_policy, &inputs, connected_subchannel, - on_ready); + NULL, on_ready); GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel"); GPR_TIMER_END("pick_subchannel", 0); return r; diff --git a/src/core/ext/client_config/lb_policy.c b/src/core/ext/client_config/lb_policy.c index 71170f5655..903563ef6b 100644 --- a/src/core/ext/client_config/lb_policy.c +++ b/src/core/ext/client_config/lb_policy.c @@ -101,9 +101,10 @@ void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const grpc_lb_policy_pick_args *pick_args, - grpc_connected_subchannel **target, + grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete) { - return policy->vtable->pick(exec_ctx, policy, pick_args, target, on_complete); + return policy->vtable->pick(exec_ctx, policy, pick_args, target, user_data, + on_complete); } void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, diff --git a/src/core/ext/client_config/lb_policy.h b/src/core/ext/client_config/lb_policy.h index 6f133a2948..734b3bff97 100644 --- a/src/core/ext/client_config/lb_policy.h +++ b/src/core/ext/client_config/lb_policy.h @@ -72,7 +72,8 @@ struct grpc_lb_policy_vtable { /** \see grpc_lb_policy_pick */ int (*pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const grpc_lb_policy_pick_args *pick_args, - grpc_connected_subchannel **target, grpc_closure *on_complete); + grpc_connected_subchannel **target, void **user_data, + grpc_closure *on_complete); /** \see grpc_lb_policy_cancel_pick */ void (*cancel_pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, @@ -138,14 +139,19 @@ void grpc_lb_policy_init(grpc_lb_policy *policy, const grpc_lb_policy_vtable *vtable); /** Find an appropriate target for this call, based on \a pick_args. - Upon completion \a on_complete will be called, with \a *target set to an - appropriate connected subchannel if the pick was successful or NULL - otherwise. - Picking can be asynchronous. Any IO should be done under \a - pick_args->pollent. */ + Picking can be synchronous or asynchronous. In the synchronous case, when a + pick is readily available, it'll be returned in \a target and a non-zero + value will be returned. + In the asynchronous case, zero is returned and \a on_complete will be called + once \a target and \a user_data have been set. Any IO should be done under + \a + pick_args->pollent. + The opaque \a user_data output argument corresponds to information that may + need be propagated from the LB policy. It may be NULL. + Errors are signaled by receiving a NULL \a *target. */ int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const grpc_lb_policy_pick_args *pick_args, - grpc_connected_subchannel **target, + grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete); /** Perform a connected subchannel ping (see \a grpc_connected_subchannel_ping) diff --git a/src/core/ext/client_config/lb_policy_factory.h b/src/core/ext/client_config/lb_policy_factory.h index 2125eaba70..e1d67633b4 100644 --- a/src/core/ext/client_config/lb_policy_factory.h +++ b/src/core/ext/client_config/lb_policy_factory.h @@ -47,16 +47,25 @@ struct grpc_lb_policy_factory { const grpc_lb_policy_factory_vtable *vtable; }; -typedef struct grpc_lb_policy_address_token { - uint8_t *token; - size_t token_size; -} grpc_lb_policy_address_token; +/** A resolved address alongside any LB related information associated with it. + * \a user_data, if not \a NULL, is opaque and meant to be consumed by the gRPC + * LB policy. Anywhere else, refer to the functions in \a + * grpc_lb_policy_user_data_vtable to operate with it */ +typedef struct grpc_lb_address { + grpc_resolved_address *resolved_address; + void *user_data; +} grpc_lb_address; + +/** Functions acting upon the opaque \a grpc_lb_address.user_data */ +typedef struct grpc_lb_policy_user_data_vtable { + void *(*copy)(void *); + void (*destroy)(void *); +} grpc_lb_policy_user_data_vtable; typedef struct grpc_lb_policy_args { - grpc_resolved_addresses *addresses; - /* If not NULL, array of load balancing tokens associated with \a addresses, - * on a 1:1 correspondence. Some indices may be NULL for missing tokens. */ - grpc_lb_policy_address_token *tokens; + grpc_lb_address *lb_addresses; + size_t num_addresses; + grpc_lb_policy_user_data_vtable user_data_vtable; grpc_client_channel_factory *client_channel_factory; } grpc_lb_policy_args; diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c index c3294b7988..ad070e458a 100644 --- a/src/core/ext/lb_policy/grpclb/grpclb.c +++ b/src/core/ext/lb_policy/grpclb/grpclb.c @@ -116,14 +116,50 @@ #include "src/core/lib/support/string.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" +#include "src/core/lib/transport/static_metadata.h" int grpc_lb_glb_trace = 0; +static void *user_data_copy(void *user_data) { + if (user_data == NULL) return NULL; + return GRPC_MDELEM_REF(user_data); +} + +static void user_data_destroy(void *user_data) { + if (user_data == NULL) return; + GRPC_MDELEM_UNREF(user_data); +} + +/* add lb_token of selected subchannel (address) to the call's initial + * metadata */ +static void initial_metadata_add_lb_token( + grpc_metadata_batch *initial_metadata, + grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem *lb_token) { + GPR_ASSERT(lb_token_mdelem_storage != NULL); + GPR_ASSERT(lb_token != NULL); + grpc_metadata_batch_add_tail(initial_metadata, lb_token_mdelem_storage, + lb_token); +} + typedef struct wrapped_rr_closure_arg { /* the original closure. Usually a on_complete/notify cb for pick() and ping() * calls against the internal RR instance, respectively. */ grpc_closure *wrapped_closure; + /* the pick's initial metadata, kept in order to append the LB token for the + * pick */ + grpc_metadata_batch *initial_metadata; + + /* the picked target, used to determine which LB token to add to the pick's + * initial metadata */ + grpc_connected_subchannel **target; + + /* the LB token associated with the pick */ + grpc_mdelem *lb_token; + + /* storage for the lb token initial metadata mdelem */ + grpc_linked_mdelem *lb_token_mdelem_storage; + /* The RR instance related to the closure */ grpc_lb_policy *rr_policy; @@ -146,6 +182,11 @@ static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg, GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure"); } GPR_ASSERT(wc_arg->wrapped_closure != NULL); + + initial_metadata_add_lb_token(wc_arg->initial_metadata, + wc_arg->lb_token_mdelem_storage, + wc_arg->lb_token); + grpc_exec_ctx_sched(exec_ctx, wc_arg->wrapped_closure, error, NULL); gpr_free(wc_arg->owning_pending_node); } @@ -194,12 +235,15 @@ static void add_pending_pick(pending_pick **root, memset(pp, 0, sizeof(pending_pick)); memset(&pp->wrapped_on_complete_arg, 0, sizeof(wrapped_rr_closure_arg)); pp->next = *root; - pp->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage; pp->pollent = pick_args->pollent; pp->target = target; pp->initial_metadata = pick_args->initial_metadata; pp->initial_metadata_flags = pick_args->initial_metadata_flags; + pp->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage; pp->wrapped_on_complete_arg.wrapped_closure = on_complete; + pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata; + pp->wrapped_on_complete_arg.lb_token_mdelem_storage = + pick_args->lb_token_mdelem_storage; grpc_closure_init(&pp->wrapped_on_complete, wrapped_rr_closure, &pp->wrapped_on_complete_arg); *root = pp; @@ -285,37 +329,90 @@ struct rr_connectivity_data { glb_lb_policy *glb_policy; }; -static bool process_serverlist(const grpc_grpclb_server *server, - struct sockaddr_storage *sa, size_t *sa_len) { - if (server->port >> 16 != 0) { - gpr_log(GPR_ERROR, "Invalid port '%d'.", server->port); - return false; +/* populate \a addresses according to \a serverlist. Returns the number of + * addresses successfully parsed and added to \a addresses */ +static size_t process_serverlist(const grpc_grpclb_serverlist *serverlist, + grpc_lb_address **lb_addresses) { + size_t num_valid = 0; + /* first pass: count how many are valid in order to allocate the necessary + * memory in a single block */ + for (size_t i = 0; i < serverlist->num_servers; ++i) { + const grpc_grpclb_server *server = serverlist->servers[i]; + const grpc_grpclb_ip_address *ip = &server->ip_address; + + if (server->port >> 16 != 0) { + gpr_log(GPR_ERROR, + "Invalid port '%d' at index %zu of serverlist. Ignoring.", + server->port, i); + continue; + } + + if (ip->size != 4 && ip->size != 16) { + gpr_log(GPR_ERROR, + "Expected IP to be 4 or 16 bytes, got %d at index %zu of " + "serverlist. Ignoring", + ip->size, i); + continue; + } + ++num_valid; } - const uint16_t netorder_port = htons((uint16_t)server->port); - /* the addresses are given in binary format (a in(6)_addr struct) in - * server->ip_address.bytes. */ - const grpc_grpclb_ip_address *ip = &server->ip_address; - *sa_len = 0; - if (ip->size == 4) { - struct sockaddr_in *addr4 = (struct sockaddr_in *)sa; - *sa_len = sizeof(struct sockaddr_in); - memset(addr4, 0, *sa_len); - addr4->sin_family = AF_INET; - memcpy(&addr4->sin_addr, ip->bytes, ip->size); - addr4->sin_port = netorder_port; - } else if (ip->size == 6) { - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)sa; - *sa_len = sizeof(struct sockaddr_in6); - memset(addr6, 0, *sa_len); - addr6->sin6_family = AF_INET; - memcpy(&addr6->sin6_addr, ip->bytes, ip->size); - addr6->sin6_port = netorder_port; - } else { - gpr_log(GPR_ERROR, "Expected IP to be 4 or 16 bytes. Got %d.", ip->size); - return false; + if (num_valid == 0) { + return 0; } - GPR_ASSERT(*sa_len > 0); - return true; + + /* allocate the memory block for the "resolved" addresses. */ + grpc_resolved_address *r_addrs_memblock = + gpr_malloc(sizeof(grpc_resolved_address) * num_valid); + memset(r_addrs_memblock, 0, sizeof(grpc_resolved_address) * num_valid); + grpc_lb_address *lb_addrs = gpr_malloc(sizeof(grpc_lb_address) * num_valid); + memset(lb_addrs, 0, sizeof(grpc_lb_address) * num_valid); + + /* second pass: actually populate the addresses and LB tokens (aka user data + * to the outside world) to be read by the RR policy during its creation */ + for (size_t i = 0; i < num_valid; ++i) { + const grpc_grpclb_server *server = serverlist->servers[i]; + grpc_lb_address *const lb_addr = &lb_addrs[i]; + + /* lb token processing */ + if (server->has_load_balance_token) { + const size_t lb_token_size = + GPR_ARRAY_SIZE(server->load_balance_token) - 1; + grpc_mdstr *lb_token_mdstr = grpc_mdstr_from_buffer( + (uint8_t *)server->load_balance_token, lb_token_size); + lb_addr->user_data = grpc_mdelem_from_metadata_strings( + GRPC_MDSTR_LOAD_REPORTING_INITIAL, lb_token_mdstr); + } + + /* address processing */ + const uint16_t netorder_port = htons((uint16_t)server->port); + /* the addresses are given in binary format (a in(6)_addr struct) in + * server->ip_address.bytes. */ + const grpc_grpclb_ip_address *ip = &server->ip_address; + + lb_addr->resolved_address = &r_addrs_memblock[i]; + struct sockaddr_storage *sa = + (struct sockaddr_storage *)lb_addr->resolved_address->addr; + size_t *sa_len = &lb_addr->resolved_address->len; + *sa_len = 0; + if (ip->size == 4) { + struct sockaddr_in *addr4 = (struct sockaddr_in *)sa; + *sa_len = sizeof(struct sockaddr_in); + memset(addr4, 0, *sa_len); + addr4->sin_family = AF_INET; + memcpy(&addr4->sin_addr, ip->bytes, ip->size); + addr4->sin_port = netorder_port; + } else if (ip->size == 16) { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)sa; + *sa_len = sizeof(struct sockaddr_in6); + memset(addr6, 0, *sa_len); + addr6->sin6_family = AF_INET; + memcpy(&addr6->sin6_addr, ip->bytes, ip->size); + addr6->sin6_port = netorder_port; + } + GPR_ASSERT(*sa_len > 0); + } + *lb_addresses = lb_addrs; + return num_valid; } static grpc_lb_policy *create_rr(grpc_exec_ctx *exec_ctx, @@ -326,36 +423,19 @@ static grpc_lb_policy *create_rr(grpc_exec_ctx *exec_ctx, grpc_lb_policy_args args; memset(&args, 0, sizeof(args)); args.client_channel_factory = glb_policy->cc_factory; - args.tokens = gpr_malloc(sizeof(grpc_lb_policy_address_token) * - serverlist->num_servers); - args.addresses = gpr_malloc(sizeof(grpc_resolved_addresses)); - args.addresses->addrs = - gpr_malloc(sizeof(grpc_resolved_address) * serverlist->num_servers); - size_t addr_idx = 0; - for (size_t i = 0; i < serverlist->num_servers; ++i) { - const grpc_grpclb_server *server = serverlist->servers[i]; - grpc_resolved_address *raddr = &args.addresses->addrs[addr_idx]; - if (!process_serverlist(server, (struct sockaddr_storage *)raddr->addr, - &raddr->len)) { - gpr_log(GPR_INFO, - "Problem processing server at index %zu of received serverlist, " - "ignoring.", - i); - continue; - } - ++addr_idx; - args.tokens[i].token_size = GPR_ARRAY_SIZE(server->load_balance_token) - 1; - args.tokens[i].token = gpr_malloc(args.tokens[i].token_size); - memcpy(args.tokens[i].token, server->load_balance_token, - args.tokens[i].token_size); - } - args.addresses->naddrs = addr_idx; + args.num_addresses = process_serverlist(serverlist, &args.lb_addresses); + args.user_data_vtable.copy = user_data_copy; + args.user_data_vtable.destroy = user_data_destroy; grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args); - - gpr_free(args.addresses->addrs); - gpr_free(args.addresses); - gpr_free(args.tokens); + if (args.num_addresses > 0) { + /* free "resolved" addresses memblock */ + gpr_free(args.lb_addresses->resolved_address); + } + for (size_t i = 0; i < args.num_addresses; ++i) { + args.user_data_vtable.destroy(args.lb_addresses[i].user_data); + } + gpr_free(args.lb_addresses); return rr; } @@ -395,6 +475,7 @@ static void rr_handover(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy, pp->pollent, pp->initial_metadata, pp->initial_metadata_flags, pp->lb_token_mdelem_storage}; grpc_lb_policy_pick(exec_ctx, glb_policy->rr_policy, &pick_args, pp->target, + (void **)&pp->wrapped_on_complete_arg.lb_token, &pp->wrapped_on_complete); pp->wrapped_on_complete_arg.owning_pending_node = pp; } @@ -457,25 +538,26 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, * Create a client channel over them to communicate with a LB service */ glb_policy->cc_factory = args->client_channel_factory; GPR_ASSERT(glb_policy->cc_factory != NULL); - if (args->addresses->naddrs == 0) { + if (args->num_addresses == 0) { return NULL; } - /* construct a target from the args->addresses, in the form + /* construct a target from the addresses in args, given in the form * ipvX://ip1:port1,ip2:port2,... * TODO(dgq): support mixed ip version */ - char **addr_strs = gpr_malloc(sizeof(char *) * args->addresses->naddrs); - addr_strs[0] = - grpc_sockaddr_to_uri((const struct sockaddr *)&args->addresses->addrs[0]); - for (size_t i = 1; i < args->addresses->naddrs; i++) { - GPR_ASSERT(grpc_sockaddr_to_string( - &addr_strs[i], - (const struct sockaddr *)&args->addresses->addrs[i], - true) == 0); + char **addr_strs = gpr_malloc(sizeof(char *) * args->num_addresses); + addr_strs[0] = grpc_sockaddr_to_uri( + (const struct sockaddr *)&args->lb_addresses[0].resolved_address->addr); + for (size_t i = 1; i < args->num_addresses; i++) { + GPR_ASSERT( + grpc_sockaddr_to_string(&addr_strs[i], + (const struct sockaddr *)&args->lb_addresses[i] + .resolved_address->addr, + true) == 0); } size_t uri_path_len; char *target_uri_str = gpr_strjoin_sep( - (const char **)addr_strs, args->addresses->naddrs, ",", &uri_path_len); + (const char **)addr_strs, args->num_addresses, ",", &uri_path_len); /* will pick using pick_first */ glb_policy->lb_channel = grpc_client_channel_factory_create_channel( @@ -483,7 +565,7 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, NULL); gpr_free(target_uri_str); - for (size_t i = 0; i < args->addresses->naddrs; i++) { + for (size_t i = 0; i < args->num_addresses; i++) { gpr_free(addr_strs[i]); } gpr_free(addr_strs); @@ -635,7 +717,7 @@ static void glb_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, const grpc_lb_policy_pick_args *pick_args, - grpc_connected_subchannel **target, + grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete) { glb_lb_policy *glb_policy = (glb_lb_policy *)pol; @@ -662,22 +744,28 @@ static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, memset(&glb_policy->wc_arg, 0, sizeof(wrapped_rr_closure_arg)); glb_policy->wc_arg.rr_policy = glb_policy->rr_policy; glb_policy->wc_arg.wrapped_closure = on_complete; + glb_policy->wc_arg.lb_token_mdelem_storage = + pick_args->lb_token_mdelem_storage; + glb_policy->wc_arg.initial_metadata = pick_args->initial_metadata; + glb_policy->wc_arg.owning_pending_node = NULL; grpc_closure_init(&glb_policy->wrapped_on_complete, wrapped_rr_closure, &glb_policy->wc_arg); r = grpc_lb_policy_pick(exec_ctx, glb_policy->rr_policy, pick_args, target, + (void **)&glb_policy->wc_arg.lb_token, &glb_policy->wrapped_on_complete); if (r != 0) { - /* the call to grpc_lb_policy_pick has been sychronous. Unreffing the RR - * policy and notify the original callback */ - glb_policy->wc_arg.wrapped_closure = NULL; + /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */ if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")", (intptr_t)glb_policy->wc_arg.rr_policy); } GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->wc_arg.rr_policy, "glb_pick"); - grpc_exec_ctx_sched(exec_ctx, glb_policy->wc_arg.wrapped_closure, - GRPC_ERROR_NONE, NULL); + + /* add the load reporting initial metadata */ + initial_metadata_add_lb_token(pick_args->initial_metadata, + pick_args->lb_token_mdelem_storage, + glb_policy->wc_arg.lb_token); } } else { grpc_polling_entity_add_to_pollset_set(exec_ctx, pick_args->pollent, diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c index e1277b353f..21d948033a 100644 --- a/src/core/ext/lb_policy/pick_first/pick_first.c +++ b/src/core/ext/lb_policy/pick_first/pick_first.c @@ -200,7 +200,7 @@ static void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, const grpc_lb_policy_pick_args *pick_args, - grpc_connected_subchannel **target, + grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; pending_pick *pp; @@ -438,23 +438,23 @@ static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {} static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { - GPR_ASSERT(args->addresses != NULL); + GPR_ASSERT(args->lb_addresses != NULL); GPR_ASSERT(args->client_channel_factory != NULL); - if (args->addresses->naddrs == 0) return NULL; + if (args->num_addresses == 0) return NULL; pick_first_lb_policy *p = gpr_malloc(sizeof(*p)); memset(p, 0, sizeof(*p)); - p->subchannels = - gpr_malloc(sizeof(grpc_subchannel *) * args->addresses->naddrs); - memset(p->subchannels, 0, sizeof(*p->subchannels) * args->addresses->naddrs); + p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * args->num_addresses); + memset(p->subchannels, 0, sizeof(*p->subchannels) * args->num_addresses); grpc_subchannel_args sc_args; size_t subchannel_idx = 0; - for (size_t i = 0; i < args->addresses->naddrs; i++) { + for (size_t i = 0; i < args->num_addresses; i++) { memset(&sc_args, 0, sizeof(grpc_subchannel_args)); - sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr); - sc_args.addr_len = (size_t)args->addresses->addrs[i].len; + sc_args.addr = + (struct sockaddr *)(args->lb_addresses[i].resolved_address->addr); + sc_args.addr_len = (size_t)args->lb_addresses[i].resolved_address->len; grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c index 8fda405fb8..2069dc192c 100644 --- a/src/core/ext/lb_policy/round_robin/round_robin.c +++ b/src/core/ext/lb_policy/round_robin/round_robin.c @@ -84,8 +84,10 @@ typedef struct pending_pick { /* the initial metadata for the pick. See grpc_lb_policy_pick() */ grpc_metadata_batch *initial_metadata; - /* storage for the lb token initial metadata mdelem */ - grpc_linked_mdelem *lb_token_mdelem_storage; + /* output argument where to store the pick()ed user_data. It'll be NULL if no + * such data is present or there's an error (the definite test for errors is + * \a target being NULL). */ + void **user_data; /* bitmask passed to pick() and used for selective cancelling. See * grpc_lb_policy_cancel_picks() */ @@ -103,7 +105,7 @@ typedef struct pending_pick { typedef struct ready_list { grpc_subchannel *subchannel; /* references namesake entry in subchannel_data */ - grpc_lb_policy_address_token *lb_token; + void *user_data; struct ready_list *next; struct ready_list *prev; } ready_list; @@ -121,8 +123,8 @@ typedef struct { ready_list *ready_list_node; /** last observed connectivity */ grpc_connectivity_state connectivity_state; - /** the subchannel's target LB token */ - grpc_lb_policy_address_token *lb_token; + /** the subchannel's target user data */ + void *user_data; } subchannel_data; struct round_robin_lb_policy { @@ -131,8 +133,10 @@ struct round_robin_lb_policy { /** total number of addresses received at creation time */ size_t num_addresses; - /** load balancing tokens, one per incoming address */ - grpc_lb_policy_address_token *lb_tokens; + /** user data, one per incoming address */ + void **user_data; + /** functions to operate over \a user_data elements */ + grpc_lb_policy_user_data_vtable user_data_vtable; /** all our subchannels */ size_t num_subchannels; @@ -204,7 +208,7 @@ static ready_list *add_connected_sc_locked(round_robin_lb_policy *p, ready_list *new_elem = gpr_malloc(sizeof(ready_list)); memset(new_elem, 0, sizeof(ready_list)); new_elem->subchannel = sd->subchannel; - new_elem->lb_token = sd->lb_token; + new_elem->user_data = sd->user_data; if (p->ready_list.prev == NULL) { /* first element */ new_elem->next = &p->ready_list; @@ -246,7 +250,7 @@ static void remove_disconnected_sc_locked(round_robin_lb_policy *p, } if (grpc_lb_round_robin_trace) { - gpr_log(GPR_DEBUG, "[READYLIST] REMOVED NODE %p (SC %p)", node, + gpr_log(GPR_DEBUG, "[READYLIST] REMOVED NODE %p (SC %p)", (void *)node, (void *)node->subchannel); } @@ -259,9 +263,8 @@ static void remove_disconnected_sc_locked(round_robin_lb_policy *p, static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; - size_t i; ready_list *elem; - for (i = 0; i < p->num_subchannels; i++) { + for (size_t i = 0; i < p->num_subchannels; i++) { subchannel_data *sd = p->subchannels[i]; GRPC_SUBCHANNEL_UNREF(exec_ctx, sd->subchannel, "round_robin"); gpr_free(sd); @@ -282,12 +285,10 @@ static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { elem = tmp; } - if (p->lb_tokens != NULL) { - for (i = 0; i < p->num_addresses; i++) { - gpr_free(p->lb_tokens[i].token); - } - gpr_free(p->lb_tokens); + for (size_t i = 0; i < p->num_addresses; i++) { + p->user_data_vtable.destroy(p->user_data[i]); } + gpr_free(p->user_data); gpr_free(p); } @@ -397,26 +398,9 @@ static void rr_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { gpr_mu_unlock(&p->mu); } -/* add lb_token of selected subchannel (address) to the call's initial - * metadata */ -static void initial_metadata_add_lb_token( - grpc_metadata_batch *initial_metadata, - grpc_linked_mdelem *lb_token_mdelem_storage, - grpc_lb_policy_address_token *lb_token) { - if (lb_token != NULL && lb_token->token_size > 0) { - GPR_ASSERT(lb_token->token != NULL); - grpc_mdstr *lb_token_mdstr = - grpc_mdstr_from_buffer(lb_token->token, lb_token->token_size); - grpc_metadata_batch_add_tail( - initial_metadata, lb_token_mdelem_storage, - grpc_mdelem_from_metadata_strings(GRPC_MDSTR_LOAD_REPORTING_INITIAL, - lb_token_mdstr)); - } -} - static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, const grpc_lb_policy_pick_args *pick_args, - grpc_connected_subchannel **target, + grpc_connected_subchannel **target, void **user_data, grpc_closure *on_complete) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; pending_pick *pp; @@ -426,9 +410,7 @@ static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, /* readily available, report right away */ gpr_mu_unlock(&p->mu); *target = grpc_subchannel_get_connected_subchannel(selected->subchannel); - initial_metadata_add_lb_token(pick_args->initial_metadata, - pick_args->lb_token_mdelem_storage, - selected->lb_token); + *user_data = p->user_data_vtable.copy(selected->user_data); if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "[RR PICK] TARGET <-- CONNECTED SUBCHANNEL %p (NODE %p)", @@ -451,7 +433,7 @@ static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, pp->on_complete = on_complete; pp->initial_metadata = pick_args->initial_metadata; pp->initial_metadata_flags = pick_args->initial_metadata_flags; - pp->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage; + pp->user_data = user_data; p->pending_picks = pp; gpr_mu_unlock(&p->mu); return 0; @@ -493,11 +475,9 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg, while ((pp = p->pending_picks)) { p->pending_picks = pp->next; - initial_metadata_add_lb_token(pp->initial_metadata, - pp->lb_token_mdelem_storage, - selected->lb_token); *pp->target = grpc_subchannel_get_connected_subchannel(selected->subchannel); + *pp->user_data = p->user_data_vtable.copy(selected->user_data); if (grpc_lb_round_robin_trace) { gpr_log(GPR_DEBUG, "[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (NODE %p)", @@ -631,30 +611,29 @@ static void round_robin_factory_unref(grpc_lb_policy_factory *factory) {} static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) { - GPR_ASSERT(args->addresses != NULL); + GPR_ASSERT(args->lb_addresses != NULL); GPR_ASSERT(args->client_channel_factory != NULL); + if (args->num_addresses == 0) return NULL; round_robin_lb_policy *p = gpr_malloc(sizeof(*p)); memset(p, 0, sizeof(*p)); - p->num_addresses = args->addresses->naddrs; - if (args->tokens != NULL) { - /* we need to copy because args contents aren't owned */ - p->lb_tokens = - gpr_malloc(sizeof(grpc_lb_policy_address_token) * p->num_addresses); - memcpy(p->lb_tokens, args->tokens, - sizeof(grpc_lb_policy_address_token) * p->num_addresses); - } - + p->num_addresses = args->num_addresses; p->subchannels = gpr_malloc(sizeof(subchannel_data) * p->num_addresses); memset(p->subchannels, 0, sizeof(*p->subchannels) * p->num_addresses); + p->user_data = gpr_malloc(sizeof(void *) * p->num_addresses); + memset(p->user_data, 0, sizeof(void *) * p->num_addresses); + p->user_data_vtable = args->user_data_vtable; grpc_subchannel_args sc_args; size_t subchannel_idx = 0; for (size_t i = 0; i < p->num_addresses; i++) { memset(&sc_args, 0, sizeof(grpc_subchannel_args)); - sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr); - sc_args.addr_len = (size_t)args->addresses->addrs[i].len; + sc_args.addr = + (struct sockaddr *)args->lb_addresses[i].resolved_address->addr; + sc_args.addr_len = args->lb_addresses[i].resolved_address->len; + + p->user_data[i] = p->user_data_vtable.copy(args->lb_addresses[i].user_data); grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); @@ -666,9 +645,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, sd->policy = p; sd->index = subchannel_idx; sd->subchannel = subchannel; - if (p->lb_tokens != NULL) { - sd->lb_token = &p->lb_tokens[i]; - } + sd->user_data = p->user_data[i]; ++subchannel_idx; grpc_closure_init(&sd->connectivity_changed_closure, rr_connectivity_changed, sd); diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c index 79682e78b5..1841a75845 100644 --- a/src/core/ext/resolver/dns/native/dns_resolver.c +++ b/src/core/ext/resolver/dns/native/dns_resolver.c @@ -175,7 +175,14 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg, grpc_lb_policy_args lb_policy_args; result = grpc_resolver_result_create(); memset(&lb_policy_args, 0, sizeof(lb_policy_args)); - lb_policy_args.addresses = addresses; + lb_policy_args.num_addresses = addresses->naddrs; + lb_policy_args.lb_addresses = + gpr_malloc(sizeof(grpc_lb_address) * lb_policy_args.num_addresses); + memset(lb_policy_args.lb_addresses, 0, + sizeof(grpc_lb_address) * lb_policy_args.num_addresses); + for (size_t i = 0; i < addresses->naddrs; ++i) { + lb_policy_args.lb_addresses[i].resolved_address = &r->addresses->addrs[i]; + } lb_policy_args.client_channel_factory = r->client_channel_factory; lb_policy = grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args); diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c index 3807522d2b..54a7e1c84c 100644 --- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c @@ -125,10 +125,18 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver_result *result = grpc_resolver_result_create(); grpc_lb_policy_args lb_policy_args; memset(&lb_policy_args, 0, sizeof(lb_policy_args)); - lb_policy_args.addresses = r->addresses; + lb_policy_args.num_addresses = r->addresses->naddrs; + lb_policy_args.lb_addresses = + gpr_malloc(sizeof(grpc_lb_address) * lb_policy_args.num_addresses); + memset(lb_policy_args.lb_addresses, 0, + sizeof(grpc_lb_address) * lb_policy_args.num_addresses); + for (size_t i = 0; i < lb_policy_args.num_addresses; ++i) { + lb_policy_args.lb_addresses[i].resolved_address = &r->addresses->addrs[i]; + } lb_policy_args.client_channel_factory = r->client_channel_factory; grpc_lb_policy *lb_policy = grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args); + gpr_free(lb_policy_args.lb_addresses); grpc_resolver_result_set_lb_policy(result, lb_policy); GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "sockaddr"); r->published = 1; diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c index 0677f29766..4b40c275ad 100644 --- a/src/core/lib/transport/metadata.c +++ b/src/core/lib/transport/metadata.c @@ -278,7 +278,7 @@ static void ref_md_locked(mdtab_shard *shard, internal_metadata *md DEBUG_ARGS) { #ifdef GRPC_METADATA_REFCOUNT_DEBUG gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "ELM REF:%p:%d->%d: '%s' = '%s'", md, + "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), gpr_atm_no_barrier_load(&md->refcnt) + 1, grpc_mdstr_as_c_string((grpc_mdstr *)md->key), @@ -566,7 +566,7 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdstr *mkey, shard->elems[idx] = md; gpr_mu_init(&md->mu_user_data); #ifdef GRPC_METADATA_REFCOUNT_DEBUG - gpr_log(GPR_DEBUG, "ELM NEW:%p:%d: '%s' = '%s'", md, + gpr_log(GPR_DEBUG, "ELM NEW:%p:%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), grpc_mdstr_as_c_string((grpc_mdstr *)md->key), grpc_mdstr_as_c_string((grpc_mdstr *)md->value)); @@ -639,7 +639,7 @@ grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) { if (is_mdelem_static(gmd)) return gmd; #ifdef GRPC_METADATA_REFCOUNT_DEBUG gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "ELM REF:%p:%d->%d: '%s' = '%s'", md, + "ELM REF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), gpr_atm_no_barrier_load(&md->refcnt) + 1, grpc_mdstr_as_c_string((grpc_mdstr *)md->key), @@ -649,7 +649,7 @@ grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) { this function - meaning that no adjustment to mdtab_free is necessary, simplifying the logic here to be just an atomic increment */ /* use C assert to have this removed in opt builds */ - assert(gpr_atm_no_barrier_load(&md->refcnt) >= 1); + GPR_ASSERT(gpr_atm_no_barrier_load(&md->refcnt) >= 1); gpr_atm_no_barrier_fetch_add(&md->refcnt, 1); return gmd; } @@ -660,14 +660,16 @@ void grpc_mdelem_unref(grpc_mdelem *gmd DEBUG_ARGS) { if (is_mdelem_static(gmd)) return; #ifdef GRPC_METADATA_REFCOUNT_DEBUG gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "ELM UNREF:%p:%d->%d: '%s' = '%s'", md, + "ELM UNREF:%p:%zu->%zu: '%s' = '%s'", (void *)md, gpr_atm_no_barrier_load(&md->refcnt), gpr_atm_no_barrier_load(&md->refcnt) - 1, grpc_mdstr_as_c_string((grpc_mdstr *)md->key), grpc_mdstr_as_c_string((grpc_mdstr *)md->value)); #endif uint32_t hash = GRPC_MDSTR_KV_HASH(md->key->hash, md->value->hash); - if (1 == gpr_atm_full_fetch_add(&md->refcnt, -1)) { + const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1); + GPR_ASSERT(prev_refcount >= 1); + if (1 == prev_refcount) { /* once the refcount hits zero, some other thread can come along and free md at any time: it's unsafe from this point on to access it */ mdtab_shard *shard = @@ -676,10 +678,12 @@ void grpc_mdelem_unref(grpc_mdelem *gmd DEBUG_ARGS) { } } -const char *grpc_mdstr_as_c_string(grpc_mdstr *s) { +const char *grpc_mdstr_as_c_string(const grpc_mdstr *s) { return (const char *)GPR_SLICE_START_PTR(s->slice); } +size_t grpc_mdstr_length(const grpc_mdstr *s) { return GRPC_MDSTR_LENGTH(s); } + grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) { internal_string *s = (internal_string *)gs; if (is_mdstr_static(gs)) return gs; diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h index 2b0921c8d7..71eff0acf2 100644 --- a/src/core/lib/transport/metadata.h +++ b/src/core/lib/transport/metadata.h @@ -147,7 +147,7 @@ void grpc_mdelem_unref(grpc_mdelem *md); /* Recover a char* from a grpc_mdstr. The returned string is null terminated. Does not promise that the returned string has no embedded nulls however. */ -const char *grpc_mdstr_as_c_string(grpc_mdstr *s); +const char *grpc_mdstr_as_c_string(const grpc_mdstr *s); #define GRPC_MDSTR_LENGTH(s) (GPR_SLICE_LENGTH(s->slice)) -- cgit v1.2.3 From d5130f2fb3c03310b90607957beea026ab428618 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 13 Sep 2016 11:33:54 -0700 Subject: Fix build problem from merge. --- src/core/lib/channel/channel_stack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c index 4994b2484c..f5fa0b0390 100644 --- a/src/core/lib/channel/channel_stack.c +++ b/src/core/lib/channel/channel_stack.c @@ -275,7 +275,7 @@ void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx, grpc_transport_stream_op op; memset(&op, 0, sizeof(op)); op.cancel_error = GRPC_ERROR_CANCELLED; - elem->filter->start_transport_stream_op(exec_ctx, elem, op); + elem->filter->start_transport_stream_op(exec_ctx, elem, &op); } void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx, @@ -286,7 +286,7 @@ void grpc_call_element_send_cancel_with_message(grpc_exec_ctx *exec_ctx, memset(&op, 0, sizeof(op)); grpc_transport_stream_op_add_cancellation_with_message(&op, status, optional_message); - elem->filter->start_transport_stream_op(exec_ctx, elem, op); + elem->filter->start_transport_stream_op(exec_ctx, elem, &op); } void grpc_call_element_send_close_with_message(grpc_exec_ctx *exec_ctx, -- cgit v1.2.3 From bf3596ef5f552190e9350e7376b3b533753e890c Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 13 Sep 2016 11:35:35 -0700 Subject: Minor cleanup. --- src/core/lib/surface/call.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index ad5a722384..424cd00d96 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -769,8 +769,8 @@ static void done_termination(grpc_exec_ctx *exec_ctx, void *tcp, } static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { - grpc_transport_stream_op op; termination_closure *tc = tcp; + grpc_transport_stream_op op; memset(&op, 0, sizeof(op)); op.cancel_error = tc->error; /* reuse closure to catch completion */ @@ -780,8 +780,8 @@ static void send_cancel(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { } static void send_close(grpc_exec_ctx *exec_ctx, void *tcp, grpc_error *error) { - grpc_transport_stream_op op; termination_closure *tc = tcp; + grpc_transport_stream_op op; memset(&op, 0, sizeof(op)); op.close_error = tc->error; /* reuse closure to catch completion */ -- cgit v1.2.3 From e2bdd54126ac0003f3b7b5880f2c0c69743f5b82 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 13 Sep 2016 14:30:18 -0700 Subject: Fix setting deadline in server call. --- src/core/lib/surface/call.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 424cd00d96..0ced42a571 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -1216,6 +1216,13 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx, GPR_TIMER_BEGIN("validate_filtered_metadata", 0); validate_filtered_metadata(exec_ctx, bctl); GPR_TIMER_END("validate_filtered_metadata", 0); + + if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) != + 0 && + !call->is_client) { + call->send_deadline = gpr_convert_clock_type(md->deadline, + GPR_CLOCK_MONOTONIC); + } } call->has_initial_md_been_received = true; -- cgit v1.2.3 From a99e02cc0d165a226bf57eb49a290f3a626168d7 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 14 Sep 2016 09:39:49 -0700 Subject: Use GPR_ARRAY_SIZE(). --- src/core/lib/iomgr/error.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c index e13f37f8ed..3d9f1a8ca5 100644 --- a/src/core/lib/iomgr/error.c +++ b/src/core/lib/iomgr/error.c @@ -356,8 +356,7 @@ static grpc_error *recursively_find_error_with_status(grpc_error *error, void grpc_error_get_status(grpc_error *error, grpc_status_code *code, const char **msg) { // Handle special errors via the static map. - for (size_t i = 0; - i < sizeof(error_status_map) / sizeof(special_error_status_map); ++i) { + for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); ++i) { if (error == error_status_map[i].error) { *code = error_status_map[i].code; *msg = error_status_map[i].msg; -- cgit v1.2.3 From 31caabdead52000354c4fdd88b68bb3041ca8c4a Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Sat, 6 Aug 2016 21:27:29 -0700 Subject: Add shim to support condition variable wakeup fds where pipe/eventfd is not available --- BUILD | 12 + CMakeLists.txt | 5 + Makefile | 42 +++ binding.gyp | 1 + build.yaml | 16 + config.m4 | 1 + gRPC-Core.podspec | 3 + grpc.gemspec | 2 + package.xml | 2 + src/core/lib/iomgr/wakeup_fd_cv.c | 328 +++++++++++++++++++++ src/core/lib/iomgr/wakeup_fd_cv.h | 58 ++++ src/core/lib/iomgr/wakeup_fd_pipe.c | 9 +- src/core/lib/iomgr/wakeup_fd_posix.c | 15 +- src/core/lib/iomgr/wakeup_fd_posix.h | 1 + src/python/grpcio/grpc_core_dependencies.py | 1 + test/core/iomgr/wakeup_fd_cv_test.c | 246 ++++++++++++++++ tools/doxygen/Doxyfile.c++.internal | 2 + tools/doxygen/Doxyfile.core.internal | 2 + tools/run_tests/sources_and_headers.json | 19 ++ tools/run_tests/tests.json | 19 ++ vsprojects/vcxproj/grpc++/grpc++.vcxproj | 3 + vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters | 6 + .../grpc++_unsecure/grpc++_unsecure.vcxproj | 3 + .../grpc++_unsecure.vcxproj.filters | 6 + vsprojects/vcxproj/grpc/grpc.vcxproj | 3 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 6 + .../vcxproj/grpc_test_util/grpc_test_util.vcxproj | 3 + .../grpc_test_util/grpc_test_util.vcxproj.filters | 6 + .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 3 + .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 + 30 files changed, 825 insertions(+), 4 deletions(-) create mode 100644 src/core/lib/iomgr/wakeup_fd_cv.c create mode 100644 src/core/lib/iomgr/wakeup_fd_cv.h create mode 100644 test/core/iomgr/wakeup_fd_cv_test.c (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index ee41d1ab21..67e481e0d2 100644 --- a/BUILD +++ b/BUILD @@ -215,6 +215,7 @@ cc_library( "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", @@ -372,6 +373,7 @@ cc_library( "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", @@ -610,6 +612,7 @@ cc_library( "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", @@ -753,6 +756,7 @@ cc_library( "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", @@ -962,6 +966,7 @@ cc_library( "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", @@ -1096,6 +1101,7 @@ cc_library( "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", @@ -1309,6 +1315,7 @@ cc_library( "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", @@ -1423,6 +1430,7 @@ cc_library( "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", @@ -1719,6 +1727,7 @@ cc_library( "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", @@ -1828,6 +1837,7 @@ cc_library( "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", @@ -2218,6 +2228,7 @@ objc_library( "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", @@ -2435,6 +2446,7 @@ objc_library( "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 05aa323ca9..f07fa26e63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -345,6 +345,7 @@ add_library(grpc src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c + src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c @@ -603,6 +604,7 @@ add_library(grpc_cronet src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c + src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c @@ -834,6 +836,7 @@ add_library(grpc_unsecure src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c + src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c @@ -1091,6 +1094,7 @@ add_library(grpc++ src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c + src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c @@ -1448,6 +1452,7 @@ add_library(grpc++_unsecure src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c + src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c diff --git a/Makefile b/Makefile index e454ad6cd7..a23e12687d 100644 --- a/Makefile +++ b/Makefile @@ -1021,6 +1021,7 @@ transport_security_test: $(BINDIR)/$(CONFIG)/transport_security_test udp_server_test: $(BINDIR)/$(CONFIG)/udp_server_test uri_fuzzer_test: $(BINDIR)/$(CONFIG)/uri_fuzzer_test uri_parser_test: $(BINDIR)/$(CONFIG)/uri_parser_test +wakeup_fd_cv_test: $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test @@ -1329,6 +1330,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/transport_security_test \ $(BINDIR)/$(CONFIG)/udp_server_test \ $(BINDIR)/$(CONFIG)/uri_parser_test \ + $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test \ $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 \ $(BINDIR)/$(CONFIG)/badreq_bad_client_test \ $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \ @@ -1717,6 +1719,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/udp_server_test || ( echo test udp_server_test failed ; exit 1 ) $(E) "[RUN] Testing uri_parser_test" $(Q) $(BINDIR)/$(CONFIG)/uri_parser_test || ( echo test uri_parser_test failed ; exit 1 ) + $(E) "[RUN] Testing wakeup_fd_cv_test" + $(Q) $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test || ( echo test wakeup_fd_cv_test failed ; exit 1 ) $(E) "[RUN] Testing public_headers_must_be_c89" $(Q) $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 || ( echo test public_headers_must_be_c89 failed ; exit 1 ) $(E) "[RUN] Testing badreq_bad_client_test" @@ -2566,6 +2570,7 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ @@ -2842,6 +2847,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ @@ -3107,6 +3113,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ @@ -3300,6 +3307,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ @@ -3640,6 +3648,7 @@ LIBGRPC++_SRC = \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ @@ -4275,6 +4284,7 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ @@ -10805,6 +10815,38 @@ endif endif +WAKEUP_FD_CV_TEST_SRC = \ + test/core/iomgr/wakeup_fd_cv_test.c \ + +WAKEUP_FD_CV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(WAKEUP_FD_CV_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/wakeup_fd_cv_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/wakeup_fd_cv_test: $(WAKEUP_FD_CV_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) $(WAKEUP_FD_CV_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)/wakeup_fd_cv_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/wakeup_fd_cv_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_wakeup_fd_cv_test: $(WAKEUP_FD_CV_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(WAKEUP_FD_CV_TEST_OBJS:.o=.dep) +endif +endif + + ALARM_CPP_TEST_SRC = \ test/cpp/common/alarm_cpp_test.cc \ diff --git a/binding.gyp b/binding.gyp index 7cc8a58c01..1b68b63d22 100644 --- a/binding.gyp +++ b/binding.gyp @@ -617,6 +617,7 @@ 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', 'src/core/lib/iomgr/unix_sockets_posix_noop.c', + 'src/core/lib/iomgr/wakeup_fd_cv.c', 'src/core/lib/iomgr/wakeup_fd_eventfd.c', 'src/core/lib/iomgr/wakeup_fd_nospecial.c', 'src/core/lib/iomgr/wakeup_fd_pipe.c', diff --git a/build.yaml b/build.yaml index 6eb23d6fb7..d4f731e85f 100644 --- a/build.yaml +++ b/build.yaml @@ -217,6 +217,7 @@ filegroups: - src/core/lib/iomgr/timer_heap.h - src/core/lib/iomgr/udp_server.h - src/core/lib/iomgr/unix_sockets_posix.h + - src/core/lib/iomgr/wakeup_fd_cv.h - src/core/lib/iomgr/wakeup_fd_pipe.h - src/core/lib/iomgr/wakeup_fd_posix.h - src/core/lib/iomgr/workqueue.h @@ -299,6 +300,7 @@ filegroups: - src/core/lib/iomgr/udp_server.c - src/core/lib/iomgr/unix_sockets_posix.c - src/core/lib/iomgr/unix_sockets_posix_noop.c + - src/core/lib/iomgr/wakeup_fd_cv.c - src/core/lib/iomgr/wakeup_fd_eventfd.c - src/core/lib/iomgr/wakeup_fd_nospecial.c - src/core/lib/iomgr/wakeup_fd_pipe.c @@ -2535,6 +2537,20 @@ targets: - grpc - gpr_test_util - gpr +- name: wakeup_fd_cv_test + build: test + language: c + src: + - test/core/iomgr/wakeup_fd_cv_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + platforms: + - mac + - linux + - posix - name: alarm_cpp_test gtest: true build: test diff --git a/config.m4 b/config.m4 index 5384585dd6..6b605fbcd6 100644 --- a/config.m4 +++ b/config.m4 @@ -136,6 +136,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index deffa1653e..92b3022cf7 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -306,6 +306,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/timer_heap.h', 'src/core/lib/iomgr/udp_server.h', 'src/core/lib/iomgr/unix_sockets_posix.h', + 'src/core/lib/iomgr/wakeup_fd_cv.h', 'src/core/lib/iomgr/wakeup_fd_pipe.h', 'src/core/lib/iomgr/wakeup_fd_posix.h', 'src/core/lib/iomgr/workqueue.h', @@ -467,6 +468,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', 'src/core/lib/iomgr/unix_sockets_posix_noop.c', + 'src/core/lib/iomgr/wakeup_fd_cv.c', 'src/core/lib/iomgr/wakeup_fd_eventfd.c', 'src/core/lib/iomgr/wakeup_fd_nospecial.c', 'src/core/lib/iomgr/wakeup_fd_pipe.c', @@ -668,6 +670,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/timer_heap.h', 'src/core/lib/iomgr/udp_server.h', 'src/core/lib/iomgr/unix_sockets_posix.h', + 'src/core/lib/iomgr/wakeup_fd_cv.h', 'src/core/lib/iomgr/wakeup_fd_pipe.h', 'src/core/lib/iomgr/wakeup_fd_posix.h', 'src/core/lib/iomgr/workqueue.h', diff --git a/grpc.gemspec b/grpc.gemspec index f249006065..d672bb1284 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -226,6 +226,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/timer_heap.h ) s.files += %w( src/core/lib/iomgr/udp_server.h ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix.h ) + s.files += %w( src/core/lib/iomgr/wakeup_fd_cv.h ) s.files += %w( src/core/lib/iomgr/wakeup_fd_pipe.h ) s.files += %w( src/core/lib/iomgr/wakeup_fd_posix.h ) s.files += %w( src/core/lib/iomgr/workqueue.h ) @@ -387,6 +388,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/udp_server.c ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix.c ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix_noop.c ) + s.files += %w( src/core/lib/iomgr/wakeup_fd_cv.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_eventfd.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_nospecial.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_pipe.c ) diff --git a/package.xml b/package.xml index 93210ee47b..02cc271fe5 100644 --- a/package.xml +++ b/package.xml @@ -233,6 +233,7 @@ + @@ -394,6 +395,7 @@ + diff --git a/src/core/lib/iomgr/wakeup_fd_cv.c b/src/core/lib/iomgr/wakeup_fd_cv.c new file mode 100644 index 0000000000..bfdc2cb422 --- /dev/null +++ b/src/core/lib/iomgr/wakeup_fd_cv.c @@ -0,0 +1,328 @@ +/* + * + * 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 + +#ifdef GPR_POSIX_WAKEUP_FD + +#include "src/core/lib/iomgr/wakeup_fd_posix.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/ev_posix.h" + +#define MAX_TABLE_RESIZE 256 +#define DEFAULT_TABLE_SIZE 16 +#define POLL_PERIOD_MS 1000 + +#define FD_TO_IDX(fd) (-(fd)-1) +#define IDX_TO_FD(idx) (-(idx)-1) + +typedef struct cv_node { + gpr_cv* cv; + struct cv_node* next; +} cv_node; + +typedef struct fd_node { + int is_set; + cv_node* cvs; + struct fd_node* next_free; +} fd_node; + +typedef struct cv_fd_table { + fd_node* cvfds; + fd_node* free_fds; + unsigned int size; + grpc_poll_function_type poll; +} cv_fd_table; + +typedef struct poll_result { + struct pollfd* fds; + gpr_cv* cv; + int completed; + int res; + int err; +} poll_result; + +typedef struct poll_args { + struct pollfd* fds; + nfds_t nfds; + int timeout; + poll_result* result; +} poll_args; + +static gpr_mu g_mu = PTHREAD_MUTEX_INITIALIZER; +static cv_fd_table g_cvfds; + +// Some environments do not implement pthread_cancel(), so we run +// this poll in a detached thread, and wake up periodically and +// check if the calling thread is still waiting on a result +static void run_poll(void* arg) { + int result, timeout; + poll_args* pargs = (poll_args*)arg; + gpr_mu_lock(&g_mu); + if (pargs->result != NULL) { + while (pargs->result != NULL) { + if (pargs->timeout < 0) { + timeout = POLL_PERIOD_MS; + } else { + timeout = GPR_MIN(POLL_PERIOD_MS, pargs->timeout); + pargs->timeout -= timeout; + } + gpr_mu_unlock(&g_mu); + result = g_cvfds.poll(pargs->fds, pargs->nfds, timeout); + gpr_mu_lock(&g_mu); + if (pargs->result != NULL) { + if (result != 0 || pargs->timeout == 0) { + memcpy(pargs->result->fds, pargs->fds, + sizeof(struct pollfd) * pargs->nfds); + pargs->result->res = result; + pargs->result->err = errno; + pargs->result->completed = 1; + gpr_cv_signal(pargs->result->cv); + break; + } + } + } + } + gpr_free(pargs->fds); + gpr_free(pargs); + gpr_mu_unlock(&g_mu); +} + +int cvfd_poll(struct pollfd* fds, nfds_t nfds, int timeout) { + unsigned int i; + int res, idx; + cv_node *cvn, *prev; + struct pollfd* sockfds; + nfds_t nsockfds = 0; + gpr_cv pollcv; + gpr_thd_id t_id; + gpr_thd_options opt; + poll_args* pargs; + poll_result* pres; + gpr_mu_lock(&g_mu); + gpr_cv_init(&pollcv); + for (i = 0; i < nfds; i++) { + fds[i].revents = 0; + if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { + idx = FD_TO_IDX(fds[i].fd); + cvn = gpr_malloc(sizeof(cv_node)); + cvn->cv = &pollcv; + cvn->next = g_cvfds.cvfds[idx].cvs; + g_cvfds.cvfds[idx].cvs = cvn; + // We should return immediately if there are pending events, + // but we still need to call poll() to check for socket events + if (g_cvfds.cvfds[idx].is_set) { + timeout = 0; + } + } else if (fds[i].fd >= 0) { + nsockfds++; + } + } + sockfds = gpr_malloc(sizeof(struct pollfd) * nsockfds); + idx = 0; + for (i = 0; i < nfds; i++) { + if (fds[i].fd >= 0) { + sockfds[idx].fd = fds[i].fd; + sockfds[idx].events = fds[i].events; + sockfds[idx].revents = 0; + idx++; + } + } + + errno = 0; + if (nsockfds > 0) { + pres = gpr_malloc(sizeof(struct poll_result)); + pargs = gpr_malloc(sizeof(struct poll_args)); + + pargs->fds = gpr_malloc(sizeof(struct pollfd) * nsockfds); + memcpy(pargs->fds, sockfds, sizeof(struct pollfd) * nsockfds); + pargs->nfds = nsockfds; + pargs->timeout = timeout; + pargs->result = pres; + + pres->fds = sockfds; + pres->cv = &pollcv; + pres->completed = 0; + pres->res = 0; + pres->err = 0; + + opt = gpr_thd_options_default(); + gpr_thd_options_set_detached(&opt); + gpr_thd_new(&t_id, &run_poll, pargs, &opt); + // We want the poll() thread to trigger the deadline, so wait forever here + gpr_cv_wait(&pollcv, &g_mu, gpr_inf_future(GPR_CLOCK_MONOTONIC)); + if (!pres->completed) { + pargs->result = NULL; + } + res = pres->res; + errno = pres->err; + gpr_free(pres); + } else { + gpr_timespec deadline = gpr_now(GPR_CLOCK_REALTIME); + deadline = + gpr_time_add(deadline, gpr_time_from_millis(timeout, GPR_TIMESPAN)); + gpr_cv_wait(&pollcv, &g_mu, deadline); + res = 0; + } + idx = 0; + for (i = 0; i < nfds; i++) { + if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { + cvn = g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs; + prev = NULL; + while (cvn->cv != &pollcv) { + prev = cvn; + cvn = cvn->next; + GPR_ASSERT(cvn); + } + if (!prev) { + g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs = cvn->next; + } else { + prev->next = cvn->next; + } + gpr_free(cvn); + + if (g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].is_set) { + fds[i].revents = POLLIN; + if (res >= 0) res++; + } + } else if (fds[i].fd >= 0) { + fds[i].revents = sockfds[idx].revents; + idx++; + } + } + gpr_free(sockfds); + gpr_cv_destroy(&pollcv); + gpr_mu_unlock(&g_mu); + + return res; +} + +static grpc_error* cv_fd_init(grpc_wakeup_fd* fd_info) { + unsigned int i, newsize; + int idx; + gpr_mu_lock(&g_mu); + if (!g_cvfds.free_fds) { + newsize = GPR_MIN(g_cvfds.size * 2, g_cvfds.size + MAX_TABLE_RESIZE); + g_cvfds.cvfds = gpr_realloc(g_cvfds.cvfds, sizeof(fd_node) * newsize); + for (i = g_cvfds.size; i < newsize; i++) { + g_cvfds.cvfds[i].is_set = 0; + g_cvfds.cvfds[i].cvs = NULL; + g_cvfds.cvfds[i].next_free = g_cvfds.free_fds; + g_cvfds.free_fds = &g_cvfds.cvfds[i]; + } + g_cvfds.size = newsize; + } + + idx = (int)(g_cvfds.free_fds - g_cvfds.cvfds); + g_cvfds.free_fds = g_cvfds.free_fds->next_free; + g_cvfds.cvfds[idx].cvs = NULL; + g_cvfds.cvfds[idx].is_set = 0; + fd_info->read_fd = IDX_TO_FD(idx); + fd_info->write_fd = -1; + gpr_mu_unlock(&g_mu); + return GRPC_ERROR_NONE; +} + +void grpc_global_cv_fd_table_init() { + gpr_mu_lock(&g_mu); + g_cvfds.size = DEFAULT_TABLE_SIZE; + g_cvfds.cvfds = gpr_malloc(sizeof(fd_node) * DEFAULT_TABLE_SIZE); + g_cvfds.free_fds = NULL; + for (int i = 0; i < DEFAULT_TABLE_SIZE; i++) { + g_cvfds.cvfds[i].is_set = 0; + g_cvfds.cvfds[i].cvs = NULL; + g_cvfds.cvfds[i].next_free = g_cvfds.free_fds; + g_cvfds.free_fds = &g_cvfds.cvfds[i]; + } + // Override the poll function with one that supports cvfds + g_cvfds.poll = grpc_poll_function; + grpc_poll_function = &cvfd_poll; + gpr_mu_unlock(&g_mu); +} + +void grpc_global_cv_fd_table_shutdown() { + gpr_mu_lock(&g_mu); + grpc_poll_function = g_cvfds.poll; + gpr_free(g_cvfds.cvfds); + gpr_mu_unlock(&g_mu); +} + +static grpc_error* cv_fd_wakeup(grpc_wakeup_fd* fd_info) { + cv_node* cvn; + gpr_mu_lock(&g_mu); + g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].is_set = 1; + cvn = g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].cvs; + while (cvn) { + gpr_cv_signal(cvn->cv); + cvn = cvn->next; + } + gpr_mu_unlock(&g_mu); + return GRPC_ERROR_NONE; +} + +static grpc_error* cv_fd_consume(grpc_wakeup_fd* fd_info) { + gpr_mu_lock(&g_mu); + g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].is_set = 0; + gpr_mu_unlock(&g_mu); + return GRPC_ERROR_NONE; +} + +static void cv_fd_destroy(grpc_wakeup_fd* fd_info) { + if (fd_info->read_fd == 0) { + return; + } + gpr_mu_lock(&g_mu); + // Assert that there are no active pollers + GPR_ASSERT(!g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].cvs); + g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].next_free = g_cvfds.free_fds; + g_cvfds.free_fds = &g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)]; + gpr_mu_unlock(&g_mu); +} + +static int cv_check_availability(void) { return 1; } + +const grpc_wakeup_fd_vtable grpc_cv_wakeup_fd_vtable = { + cv_fd_init, cv_fd_consume, cv_fd_wakeup, cv_fd_destroy, + cv_check_availability}; + +#endif /* GPR_POSIX_WAKUP_FD */ diff --git a/src/core/lib/iomgr/wakeup_fd_cv.h b/src/core/lib/iomgr/wakeup_fd_cv.h new file mode 100644 index 0000000000..22ee6c0bbe --- /dev/null +++ b/src/core/lib/iomgr/wakeup_fd_cv.h @@ -0,0 +1,58 @@ +/* + * + * 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. + * + */ + +/* + * wakeup_fd_cv uses condition variables to implement wakeup fds. + * + * It is intended for use only in cases when eventfd() and pipe() are not + * available. It can only be used with the "poll" engine. + * + * Implementation: + * A global table of cv wakeup fds is mantained. A cv wakeup fd is a negative + * file descriptor. poll() is then run in a background thread with only the + * real socket fds while we wait on a condition variable trigged by either the + * poll() called or a wakeup_fd() call. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H +#define GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H + +#include "src/core/lib/iomgr/wakeup_fd_posix.h" + +void grpc_global_cv_fd_table_init(); +void grpc_global_cv_fd_table_shutdown(); + +extern grpc_wakeup_fd_vtable grpc_cv_wakeup_fd_vtable; + +#endif /* GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H */ diff --git a/src/core/lib/iomgr/wakeup_fd_pipe.c b/src/core/lib/iomgr/wakeup_fd_pipe.c index 4e5dbdcb73..3dc94c94ba 100644 --- a/src/core/lib/iomgr/wakeup_fd_pipe.c +++ b/src/core/lib/iomgr/wakeup_fd_pipe.c @@ -95,8 +95,13 @@ static void pipe_destroy(grpc_wakeup_fd* fd_info) { } static int pipe_check_availability(void) { - /* Assume that pipes are always available. */ - return 1; + grpc_wakeup_fd fd; + if (pipe_init(&fd) == GRPC_ERROR_NONE) { + pipe_destroy(&fd); + return 1; + } else { + return 0; + } } const grpc_wakeup_fd_vtable grpc_pipe_wakeup_fd_vtable = { diff --git a/src/core/lib/iomgr/wakeup_fd_posix.c b/src/core/lib/iomgr/wakeup_fd_posix.c index 046208abc8..564b836154 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.c +++ b/src/core/lib/iomgr/wakeup_fd_posix.c @@ -36,22 +36,33 @@ #ifdef GPR_POSIX_WAKEUP_FD #include +#include "src/core/lib/iomgr/wakeup_fd_cv.h" #include "src/core/lib/iomgr/wakeup_fd_pipe.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL; int grpc_allow_specialized_wakeup_fd = 1; +int grpc_allow_pipe_wakeup_fd = 1; void grpc_wakeup_fd_global_init(void) { if (grpc_allow_specialized_wakeup_fd && grpc_specialized_wakeup_fd_vtable.check_availability()) { wakeup_fd_vtable = &grpc_specialized_wakeup_fd_vtable; - } else { + } else if (grpc_allow_pipe_wakeup_fd && + grpc_pipe_wakeup_fd_vtable.check_availability()) { wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable; + } else { + wakeup_fd_vtable = &grpc_cv_wakeup_fd_vtable; + grpc_global_cv_fd_table_init(); } } -void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; } +void grpc_wakeup_fd_global_destroy(void) { + if (wakeup_fd_vtable == &grpc_cv_wakeup_fd_vtable) { + grpc_global_cv_fd_table_shutdown(); + } + wakeup_fd_vtable = NULL; +} grpc_error *grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) { return wakeup_fd_vtable->init(fd_info); diff --git a/src/core/lib/iomgr/wakeup_fd_posix.h b/src/core/lib/iomgr/wakeup_fd_posix.h index e269f242d8..a9f902bc9f 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.h +++ b/src/core/lib/iomgr/wakeup_fd_posix.h @@ -88,6 +88,7 @@ struct grpc_wakeup_fd { }; extern int grpc_allow_specialized_wakeup_fd; +extern int grpc_allow_pipe_wakeup_fd; #define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd) diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index be7f30c29b..dc2ce46979 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -130,6 +130,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', 'src/core/lib/iomgr/unix_sockets_posix_noop.c', + 'src/core/lib/iomgr/wakeup_fd_cv.c', 'src/core/lib/iomgr/wakeup_fd_eventfd.c', 'src/core/lib/iomgr/wakeup_fd_nospecial.c', 'src/core/lib/iomgr/wakeup_fd_pipe.c', diff --git a/test/core/iomgr/wakeup_fd_cv_test.c b/test/core/iomgr/wakeup_fd_cv_test.c new file mode 100644 index 0000000000..2cd777536d --- /dev/null +++ b/test/core/iomgr/wakeup_fd_cv_test.c @@ -0,0 +1,246 @@ +/* + * + * 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 + +#include +#include +#include +#include + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include "src/core/lib/support/env.h" + +typedef struct poll_args { + struct pollfd *fds; + nfds_t nfds; + int timeout; + int result; +} poll_args; + +gpr_cv poll_cv; +gpr_mu poll_mu; +static int socket_event = 0; + +// Trigger a "socket" POLLIN in mock_poll() +void trigger_socket_event() { + gpr_mu_lock(&poll_mu); + socket_event = 1; + gpr_cv_broadcast(&poll_cv); + gpr_mu_unlock(&poll_mu); +} + +void reset_socket_event() { + gpr_mu_lock(&poll_mu); + socket_event = 0; + gpr_mu_unlock(&poll_mu); +} + +// Mocks posix poll() function +int mock_poll(struct pollfd *fds, nfds_t nfds, int timeout) { + int res = 0; + gpr_timespec poll_time; + gpr_mu_lock(&poll_mu); + GPR_ASSERT(nfds == 3); + GPR_ASSERT(fds[0].fd == 20); + GPR_ASSERT(fds[1].fd == 30); + GPR_ASSERT(fds[2].fd == 50); + GPR_ASSERT(fds[0].events == (POLLIN | POLLHUP)); + GPR_ASSERT(fds[1].events == (POLLIN | POLLHUP)); + GPR_ASSERT(fds[2].events == POLLIN); + + if (timeout < 0) { + poll_time = gpr_inf_future(GPR_CLOCK_REALTIME); + } else { + poll_time = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(timeout, GPR_TIMESPAN)); + } + + if (socket_event || !gpr_cv_wait(&poll_cv, &poll_mu, poll_time)) { + fds[0].revents = POLLIN; + res = 1; + } + gpr_mu_unlock(&poll_mu); + return res; +} + +void background_poll(void *args) { + poll_args *pargs = (poll_args *)args; + pargs->result = grpc_poll_function(pargs->fds, pargs->nfds, pargs->timeout); +} + +void test_many_fds(void) { + int i; + grpc_wakeup_fd_global_init(); + grpc_wakeup_fd fd[1000]; + for (i = 0; i < 1000; i++) { + GPR_ASSERT(grpc_wakeup_fd_init(&fd[i]) == GRPC_ERROR_NONE); + } + for (i = 0; i < 1000; i++) { + grpc_wakeup_fd_destroy(&fd[i]); + } + grpc_wakeup_fd_global_destroy(); +} + +void test_poll_cv_trigger(void) { + grpc_wakeup_fd cvfd1, cvfd2, cvfd3; + struct pollfd pfds[6]; + poll_args pargs; + gpr_thd_id t_id; + gpr_thd_options opt; + grpc_poll_function = &mock_poll; + grpc_wakeup_fd_global_init(); + + GPR_ASSERT(grpc_wakeup_fd_init(&cvfd1) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_wakeup_fd_init(&cvfd2) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_wakeup_fd_init(&cvfd3) == GRPC_ERROR_NONE); + GPR_ASSERT(cvfd1.read_fd < 0); + GPR_ASSERT(cvfd2.read_fd < 0); + GPR_ASSERT(cvfd3.read_fd < 0); + GPR_ASSERT(cvfd1.read_fd != cvfd2.read_fd); + GPR_ASSERT(cvfd2.read_fd != cvfd3.read_fd); + GPR_ASSERT(cvfd1.read_fd != cvfd3.read_fd); + + pfds[0].fd = cvfd1.read_fd; + pfds[1].fd = cvfd2.read_fd; + pfds[2].fd = 20; + pfds[3].fd = 30; + pfds[4].fd = cvfd3.read_fd; + pfds[5].fd = 50; + + pfds[0].events = 0; + pfds[1].events = POLLIN; + pfds[2].events = POLLIN | POLLHUP; + pfds[3].events = POLLIN | POLLHUP; + pfds[4].events = POLLIN; + pfds[5].events = POLLIN; + + pargs.fds = pfds; + pargs.nfds = 6; + pargs.timeout = 1000; + pargs.result = -2; + + opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + + // Wakeup wakeup_fd not listening for events + GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd1) == GRPC_ERROR_NONE); + gpr_thd_join(t_id); + GPR_ASSERT(pargs.result == 0); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == 0); + GPR_ASSERT(pfds[2].revents == 0); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // Pollin on socket fd + pargs.timeout = -1; + pargs.result = -2; + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + trigger_socket_event(); + gpr_thd_join(t_id); + GPR_ASSERT(pargs.result == 1); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == 0); + GPR_ASSERT(pfds[2].revents == POLLIN); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // Pollin on wakeup fd + reset_socket_event(); + pargs.result = -2; + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd2) == GRPC_ERROR_NONE); + gpr_thd_join(t_id); + + GPR_ASSERT(pargs.result == 1); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == POLLIN); + GPR_ASSERT(pfds[2].revents == 0); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // Pollin on wakeup fd + socket fd + trigger_socket_event(); + pargs.result = -2; + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + gpr_thd_join(t_id); + + GPR_ASSERT(pargs.result == 2); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == POLLIN); + GPR_ASSERT(pfds[2].revents == POLLIN); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // No Events + pargs.result = -2; + pargs.timeout = 1000; + reset_socket_event(); + GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd1) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd2) == GRPC_ERROR_NONE); + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + gpr_thd_join(t_id); + + GPR_ASSERT(pargs.result == 0); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == 0); + GPR_ASSERT(pfds[2].revents == 0); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + grpc_wakeup_fd_global_destroy(); +} + +int main(int argc, char **argv) { + gpr_setenv("GRPC_POLL_STRATEGY", "poll"); + grpc_allow_specialized_wakeup_fd = 0; + grpc_allow_pipe_wakeup_fd = 0; + gpr_mu_init(&poll_mu); + gpr_cv_init(&poll_cv); + test_many_fds(); + test_poll_cv_trigger(); + // Make sure detached polling threads have chance + // to exit and clean up memory. pthread_exit() causes tsan/msan + // issues, so we just wait an ample amount of time + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(5, GPR_TIMESPAN))); + return 0; +} diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 06b68c3b74..6e08a1977c 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -925,6 +925,7 @@ src/core/lib/iomgr/timer.h \ src/core/lib/iomgr/timer_heap.h \ src/core/lib/iomgr/udp_server.h \ src/core/lib/iomgr/unix_sockets_posix.h \ +src/core/lib/iomgr/wakeup_fd_cv.h \ src/core/lib/iomgr/wakeup_fd_pipe.h \ src/core/lib/iomgr/wakeup_fd_posix.h \ src/core/lib/iomgr/workqueue.h \ @@ -1039,6 +1040,7 @@ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ +src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 02590db421..2328194c3a 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -842,6 +842,7 @@ src/core/lib/iomgr/timer.h \ src/core/lib/iomgr/timer_heap.h \ src/core/lib/iomgr/udp_server.h \ src/core/lib/iomgr/unix_sockets_posix.h \ +src/core/lib/iomgr/wakeup_fd_cv.h \ src/core/lib/iomgr/wakeup_fd_pipe.h \ src/core/lib/iomgr/wakeup_fd_posix.h \ src/core/lib/iomgr/workqueue.h \ @@ -1003,6 +1004,7 @@ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ +src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index db84f21968..2ce0e3b05c 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -1891,6 +1891,22 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "language": "c", + "name": "wakeup_fd_cv_test", + "src": [ + "test/core/iomgr/wakeup_fd_cv_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -5941,6 +5957,7 @@ "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", @@ -6085,6 +6102,8 @@ "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix.h", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index f97ee835c1..de9c3d1053 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -1977,6 +1977,25 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "wakeup_fd_cv_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [], "ci_platforms": [ diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index 1bcb263911..2afda35d34 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -425,6 +425,7 @@ + @@ -627,6 +628,8 @@ + + diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index 7343c80cc4..1f88ae0e93 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -259,6 +259,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -869,6 +872,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index 3241bafa6b..be20aef6dc 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -421,6 +421,7 @@ + @@ -613,6 +614,8 @@ + + diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index 3df26646fc..628173dbbe 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -244,6 +244,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -842,6 +845,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 7c120bcf02..ae24e8f066 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -351,6 +351,7 @@ + @@ -568,6 +569,8 @@ + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 9cbb2ce45b..a849795dc9 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -163,6 +163,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -821,6 +824,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index 80dd6b2dcb..3c3fae370f 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -242,6 +242,7 @@ + @@ -412,6 +413,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 8dc28d1cb9..b81431cafa 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -211,6 +211,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -602,6 +605,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index d4a85768c3..69d631e452 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -341,6 +341,7 @@ + @@ -536,6 +537,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index fba5a02099..36e80b4a13 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -166,6 +166,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -731,6 +734,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr -- cgit v1.2.3 From 98d5f5cb3fb6d89efbbae557a2fa4e12e2b3a74e Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Wed, 14 Sep 2016 14:34:22 -0700 Subject: Renamed grpc-census-bin to grpc-stats-bin --- src/core/lib/transport/static_metadata.c | 4 ++-- src/core/lib/transport/static_metadata.h | 12 ++++++------ test/core/end2end/fuzzers/hpack.dictionary | 2 +- tools/codegen/core/gen_static_metadata.py | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c index fce591f346..5e0352a467 100644 --- a/src/core/lib/transport/static_metadata.c +++ b/src/core/lib/transport/static_metadata.c @@ -54,7 +54,7 @@ const uint8_t grpc_static_metadata_elem_indices[GRPC_STATIC_MDELEM_COUNT * 2] = {11, 33, 10, 33, 12, 33, 12, 50, 13, 33, 14, 33, 15, 33, 16, 33, 17, 33, 19, 33, 20, 33, 21, 33, 22, 33, 23, 33, 24, 33, 25, 33, 26, 33, 27, 33, 28, 18, 28, 33, 29, 33, 30, 33, 34, 33, 35, 33, 36, 33, 37, 33, 40, 31, - 40, 32, 40, 49, 40, 54, 40, 55, 40, 56, 40, 57, 42, 31, 42, 49, 42, 54, + 40, 32, 40, 49, 40, 54, 40, 55, 40, 56, 40, 57, 41, 31, 41, 49, 41, 54, 46, 0, 46, 1, 46, 2, 51, 33, 58, 33, 59, 33, 60, 33, 61, 33, 62, 33, 63, 33, 64, 33, 65, 33, 66, 33, 67, 33, 68, 33, 69, 38, 69, 71, 69, 74, 70, 82, 70, 83, 72, 33, 73, 33, 75, 33, 76, 33, 77, 33, 78, 33, 79, 39, @@ -103,11 +103,11 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "GET", "grpc", "grpc-accept-encoding", - "grpc-census-bin", "grpc-encoding", "grpc-internal-encoding-request", "grpc-message", "grpc-payload-bin", + "grpc-stats-bin", "grpc-status", "grpc-timeout", "grpc-tracing-bin", diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h index 54b6f38be1..5b9ee1a60a 100644 --- a/src/core/lib/transport/static_metadata.h +++ b/src/core/lib/transport/static_metadata.h @@ -128,16 +128,16 @@ extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; #define GRPC_MDSTR_GRPC (&grpc_static_mdstr_table[39]) /* "grpc-accept-encoding" */ #define GRPC_MDSTR_GRPC_ACCEPT_ENCODING (&grpc_static_mdstr_table[40]) -/* "grpc-census-bin" */ -#define GRPC_MDSTR_GRPC_CENSUS_BIN (&grpc_static_mdstr_table[41]) /* "grpc-encoding" */ -#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[42]) +#define GRPC_MDSTR_GRPC_ENCODING (&grpc_static_mdstr_table[41]) /* "grpc-internal-encoding-request" */ -#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[43]) +#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST (&grpc_static_mdstr_table[42]) /* "grpc-message" */ -#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[44]) +#define GRPC_MDSTR_GRPC_MESSAGE (&grpc_static_mdstr_table[43]) /* "grpc-payload-bin" */ -#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (&grpc_static_mdstr_table[45]) +#define GRPC_MDSTR_GRPC_PAYLOAD_BIN (&grpc_static_mdstr_table[44]) +/* "grpc-stats-bin" */ +#define GRPC_MDSTR_GRPC_STATS_BIN (&grpc_static_mdstr_table[45]) /* "grpc-status" */ #define GRPC_MDSTR_GRPC_STATUS (&grpc_static_mdstr_table[46]) /* "grpc-timeout" */ diff --git a/test/core/end2end/fuzzers/hpack.dictionary b/test/core/end2end/fuzzers/hpack.dictionary index e5a73d523f..a93bccfa0d 100644 --- a/test/core/end2end/fuzzers/hpack.dictionary +++ b/test/core/end2end/fuzzers/hpack.dictionary @@ -40,11 +40,11 @@ "\x03GET" "\x04grpc" "\x14grpc-accept-encoding" -"\x0Fgrpc-census-bin" "\x0Dgrpc-encoding" "\x1Egrpc-internal-encoding-request" "\x0Cgrpc-message" "\x10grpc-payload-bin" +"\x0Egrpc-stats-bin" "\x0Bgrpc-status" "\x0Cgrpc-timeout" "\x10grpc-tracing-bin" diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py index 2a16baa1b9..6f400102e4 100755 --- a/tools/codegen/core/gen_static_metadata.py +++ b/tools/codegen/core/gen_static_metadata.py @@ -52,7 +52,7 @@ CONFIG = [ 'grpc-message', 'grpc-status', 'grpc-tracing-bin', - 'grpc-census-bin', + 'grpc-stats-bin', '', ('grpc-status', '0'), ('grpc-status', '1'), -- cgit v1.2.3 From f28763c68c9b3caf539f4d38ff123ae5de69e6d8 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 14 Sep 2016 15:18:40 -0700 Subject: Pass deadline into filters via grpc_call_element_args, so that we can start the timer before the first op is sent down. --- src/core/ext/client_config/client_channel.c | 28 +++++++--- src/core/ext/client_config/subchannel.c | 5 +- src/core/ext/client_config/subchannel.h | 3 +- src/core/lib/channel/channel_stack.c | 13 +++-- src/core/lib/channel/channel_stack.h | 13 +++-- src/core/lib/channel/deadline_filter.c | 58 +++++++++++++++------ src/core/lib/channel/deadline_filter.h | 22 ++++---- src/core/lib/surface/call.c | 72 +++++++++++++++----------- test/core/end2end/invalid_call_argument_test.c | 10 ---- test/core/end2end/tests/negative_deadline.c | 16 +++--- 10 files changed, 140 insertions(+), 100 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c index 5a8030b23e..76c2f38a5d 100644 --- a/src/core/ext/client_config/client_channel.c +++ b/src/core/ext/client_config/client_channel.c @@ -385,6 +385,9 @@ typedef struct client_channel_call_data { // stack and each has its own mutex. If/when we have time, find a way // to avoid this without breaking the grpc_deadline_state abstraction. grpc_deadline_state deadline_state; + gpr_timespec deadline; + + grpc_error *cancel_error; /** either 0 for no call, 1 for cancelled, or a pointer to a grpc_subchannel_call */ @@ -482,7 +485,7 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, } else { grpc_subchannel_call *subchannel_call = NULL; grpc_error *new_error = grpc_connected_subchannel_create_call( - exec_ctx, calld->connected_subchannel, calld->pollent, + exec_ctx, calld->connected_subchannel, calld->pollent, calld->deadline, &subchannel_call); if (new_error != GRPC_ERROR_NONE) { new_error = grpc_error_add_child(new_error, error); @@ -627,8 +630,8 @@ static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx, grpc_subchannel_call *call = GET_CALL(calld); GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0); if (call == CANCELLED_CALL) { - grpc_transport_stream_op_finish_with_failure(exec_ctx, op, - GRPC_ERROR_CANCELLED); + grpc_transport_stream_op_finish_with_failure( + exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error)); GPR_TIMER_END("cc_start_transport_stream_op", 0); return; } @@ -644,8 +647,8 @@ retry: call = GET_CALL(calld); if (call == CANCELLED_CALL) { gpr_mu_unlock(&calld->mu); - grpc_transport_stream_op_finish_with_failure(exec_ctx, op, - GRPC_ERROR_CANCELLED); + grpc_transport_stream_op_finish_with_failure( + exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error)); GPR_TIMER_END("cc_start_transport_stream_op", 0); return; } @@ -661,6 +664,12 @@ retry: (gpr_atm)(uintptr_t)CANCELLED_CALL)) { goto retry; } else { + // Stash a copy of cancel_error in our call data, so that we can use + // it for subsequent operations. This ensures that if the call is + // cancelled before any ops are passed down (e.g., if the deadline + // is in the past when the call starts), we can return the right + // error to the caller when the first op does get passed down. + calld->cancel_error = GRPC_ERROR_REF(op->cancel_error); switch (calld->creation_phase) { case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING: fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error)); @@ -697,7 +706,7 @@ retry: calld->connected_subchannel != NULL) { grpc_subchannel_call *subchannel_call = NULL; grpc_error *error = grpc_connected_subchannel_create_call( - exec_ctx, calld->connected_subchannel, calld->pollent, + exec_ctx, calld->connected_subchannel, calld->pollent, calld->deadline, &subchannel_call); if (error != GRPC_ERROR_NONE) { subchannel_call = CANCELLED_CALL; @@ -720,7 +729,9 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_call_element_args *args) { call_data *calld = elem->call_data; - grpc_deadline_state_init(&calld->deadline_state, args->call_stack); + grpc_deadline_state_init(exec_ctx, elem, args); + calld->deadline = args->deadline; + calld->cancel_error = GRPC_ERROR_NONE; gpr_atm_rel_store(&calld->subchannel_call, 0); gpr_mu_init(&calld->mu); calld->connected_subchannel = NULL; @@ -739,7 +750,8 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx, const grpc_call_final_info *final_info, void *and_free_memory) { call_data *calld = elem->call_data; - grpc_deadline_state_destroy(exec_ctx, &calld->deadline_state); + grpc_deadline_state_destroy(exec_ctx, elem); + GRPC_ERROR_UNREF(calld->cancel_error); grpc_subchannel_call *call = GET_CALL(calld); if (call != NULL && call != CANCELLED_CALL) { GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call"); diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c index 456cc44635..8f4a2f9e3e 100644 --- a/src/core/ext/client_config/subchannel.c +++ b/src/core/ext/client_config/subchannel.c @@ -706,14 +706,15 @@ grpc_connected_subchannel *grpc_subchannel_get_connected_subchannel( grpc_error *grpc_connected_subchannel_create_call( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *con, - grpc_polling_entity *pollent, grpc_subchannel_call **call) { + grpc_polling_entity *pollent, gpr_timespec deadline, + grpc_subchannel_call **call) { grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con); *call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size); grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); (*call)->connection = con; // Ref is added below. grpc_error *error = grpc_call_stack_init(exec_ctx, chanstk, 1, subchannel_call_destroy, *call, - NULL, NULL, callstk); + NULL, NULL, deadline, callstk); if (error != GRPC_ERROR_NONE) { const char *error_string = grpc_error_string(error); gpr_log(GPR_ERROR, "error: %s", error_string); diff --git a/src/core/ext/client_config/subchannel.h b/src/core/ext/client_config/subchannel.h index ae1d96e640..763ff85757 100644 --- a/src/core/ext/client_config/subchannel.h +++ b/src/core/ext/client_config/subchannel.h @@ -110,7 +110,8 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx, /** construct a subchannel call */ grpc_error *grpc_connected_subchannel_create_call( grpc_exec_ctx *exec_ctx, grpc_connected_subchannel *connected_subchannel, - grpc_polling_entity *pollent, grpc_subchannel_call **subchannel_call); + grpc_polling_entity *pollent, gpr_timespec deadline, + grpc_subchannel_call **subchannel_call); /** process a transport level op */ void grpc_connected_subchannel_process_transport_op( diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c index f5fa0b0390..98177f439b 100644 --- a/src/core/lib/channel/channel_stack.c +++ b/src/core/lib/channel/channel_stack.c @@ -157,13 +157,11 @@ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx, } } -grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx, - grpc_channel_stack *channel_stack, - int initial_refs, grpc_iomgr_cb_func destroy, - void *destroy_arg, - grpc_call_context_element *context, - const void *transport_server_data, - grpc_call_stack *call_stack) { +grpc_error *grpc_call_stack_init( + grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack, + int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, + grpc_call_context_element *context, const void *transport_server_data, + gpr_timespec deadline, grpc_call_stack *call_stack) { grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack); grpc_call_element_args args; size_t count = channel_stack->count; @@ -184,6 +182,7 @@ grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx, args.call_stack = call_stack; args.server_transport_data = transport_server_data; args.context = context; + args.deadline = deadline; call_elems[i].filter = channel_elems[i].filter; call_elems[i].channel_data = channel_elems[i].channel_data; call_elems[i].call_data = user_data; diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index eeaab17d39..1cfe2885d8 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -74,6 +74,7 @@ typedef struct { grpc_call_stack *call_stack; const void *server_transport_data; grpc_call_context_element *context; + gpr_timespec deadline; } grpc_call_element_args; typedef struct { @@ -220,13 +221,11 @@ void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx, /* Initialize a call stack given a channel stack. transport_server_data is expected to be NULL on a client, or an opaque transport owned pointer on the server. */ -grpc_error *grpc_call_stack_init(grpc_exec_ctx *exec_ctx, - grpc_channel_stack *channel_stack, - int initial_refs, grpc_iomgr_cb_func destroy, - void *destroy_arg, - grpc_call_context_element *context, - const void *transport_server_data, - grpc_call_stack *call_stack); +grpc_error *grpc_call_stack_init( + grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack, + int initial_refs, grpc_iomgr_cb_func destroy, void *destroy_arg, + grpc_call_context_element *context, const void *transport_server_data, + gpr_timespec deadline, grpc_call_stack *call_stack); /* Set a pollset or a pollset_set for a call stack: must occur before the first * op is started */ void grpc_call_stack_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx, diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c index 010fedd7b7..079b98a2f8 100644 --- a/src/core/lib/channel/deadline_filter.c +++ b/src/core/lib/channel/deadline_filter.c @@ -34,10 +34,12 @@ #include #include +#include #include #include #include +#include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/timer.h" // @@ -106,15 +108,49 @@ static void inject_on_complete_cb(grpc_deadline_state* deadline_state, op->on_complete = &deadline_state->on_complete; } -void grpc_deadline_state_init(grpc_deadline_state* deadline_state, - grpc_call_stack* call_stack) { +// Callback and associated state for starting the timer after call stack +// initialization has been completed. +struct start_timer_after_init_state { + grpc_call_element* elem; + gpr_timespec deadline; + grpc_closure closure; +}; +static void start_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + struct start_timer_after_init_state* state = arg; + start_timer_if_needed(exec_ctx, state->elem, state->deadline); + gpr_free(state); +} + +void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, + grpc_call_element_args* args) { + grpc_deadline_state* deadline_state = elem->call_data; memset(deadline_state, 0, sizeof(*deadline_state)); - deadline_state->call_stack = call_stack; + deadline_state->call_stack = args->call_stack; gpr_mu_init(&deadline_state->timer_mu); + // Deadline will always be infinite on servers, so the timer will only be + // set on clients with a finite deadline. + const gpr_timespec deadline = + gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC); + if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) { + // When the deadline passes, we indicate the failure by sending down + // an op with cancel_error set. However, we can't send down any ops + // until after the call stack is fully initialized. If we start the + // timer here, we have no guarantee that the timer won't pop before + // call stack initialization is finished. To avoid that problem, we + // create a closure to start the timer, and we schedule that closure + // to be run after call stack initialization is done. + struct start_timer_after_init_state* state = gpr_malloc(sizeof(*state)); + state->elem = elem; + state->deadline = deadline; + grpc_closure_init(&state->closure, start_timer_after_init, state); + grpc_exec_ctx_sched(exec_ctx, &state->closure, GRPC_ERROR_NONE, NULL); + } } void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, - grpc_deadline_state* deadline_state) { + grpc_call_element* elem) { + grpc_deadline_state* deadline_state = elem->call_data; cancel_timer_if_needed(exec_ctx, deadline_state); gpr_mu_destroy(&deadline_state->timer_mu); } @@ -127,12 +163,6 @@ void grpc_deadline_state_client_start_transport_stream_op( op->close_error != GRPC_ERROR_NONE) { cancel_timer_if_needed(exec_ctx, deadline_state); } else { - // If we're sending initial metadata, get the deadline from the metadata - // and start the timer if needed. - if (op->send_initial_metadata != NULL) { - start_timer_if_needed(exec_ctx, elem, - op->send_initial_metadata->deadline); - } // Make sure we know when the call is complete, so that we can cancel // the timer. if (op->recv_trailing_metadata != NULL) { @@ -177,10 +207,9 @@ typedef struct server_call_data { static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_call_element_args* args) { - base_call_data* calld = elem->call_data; // Note: size of call data is different between client and server. - memset(calld, 0, elem->filter->sizeof_call_data); - grpc_deadline_state_init(&calld->deadline_state, args->call_stack); + memset(elem->call_data, 0, elem->filter->sizeof_call_data); + grpc_deadline_state_init(exec_ctx, elem, args); return GRPC_ERROR_NONE; } @@ -188,8 +217,7 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, const grpc_call_final_info* final_info, void* and_free_memory) { - base_call_data* calld = elem->call_data; - grpc_deadline_state_destroy(exec_ctx, &calld->deadline_state); + grpc_deadline_state_destroy(exec_ctx, elem); } // Method for starting a call op for client filter. diff --git a/src/core/lib/channel/deadline_filter.h b/src/core/lib/channel/deadline_filter.h index a09f85afe6..685df87761 100644 --- a/src/core/lib/channel/deadline_filter.h +++ b/src/core/lib/channel/deadline_filter.h @@ -36,7 +36,7 @@ #include "src/core/lib/iomgr/timer.h" // State used for filters that enforce call deadlines. -// Should be the first field in the filter's call_data. +// Must be the first field in the filter's call_data. typedef struct grpc_deadline_state { // We take a reference to the call stack for the timer callback. grpc_call_stack* call_stack; @@ -54,16 +54,18 @@ typedef struct grpc_deadline_state { grpc_closure* next_on_complete; } grpc_deadline_state; -void grpc_deadline_state_init(grpc_deadline_state* call_data, - grpc_call_stack* call_stack); -void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, - grpc_deadline_state* call_data); - -// To be used in a filter's start_transport_stream_op() method to -// enforce call deadlines. -// It is the caller's responsibility to chain to the next filter if -// necessary after this function returns. +// To be used in a filter's init_call_elem(), destroy_call_elem(), and +// start_transport_stream_op() methods to enforce call deadlines. +// // REQUIRES: The first field in elem->call_data is a grpc_deadline_state. +// +// For grpc_deadline_state_client_start_transport_stream_op(), it is the +// caller's responsibility to chain to the next filter if necessary +// after the function returns. +void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, + grpc_call_element_args* args); +void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, + grpc_call_element* elem); void grpc_deadline_state_client_start_transport_stream_op( grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op); diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 0ced42a571..f8b7c9bf90 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -254,34 +254,7 @@ grpc_call *grpc_call_create( } } send_deadline = gpr_convert_clock_type(send_deadline, GPR_CLOCK_MONOTONIC); - GRPC_CHANNEL_INTERNAL_REF(channel, "call"); - /* initial refcount dropped by grpc_call_destroy */ - grpc_error *error = grpc_call_stack_init( - &exec_ctx, channel_stack, 1, destroy_call, call, call->context, - server_transport_data, CALL_STACK_FROM_CALL(call)); - if (error != GRPC_ERROR_NONE) { - grpc_status_code status; - const char *error_str; - grpc_error_get_status(error, &status, &error_str); - close_with_status(&exec_ctx, call, status, error_str); - GRPC_ERROR_UNREF(error); - } - if (cq != NULL) { - GPR_ASSERT( - pollset_set_alternative == NULL && - "Only one of 'cq' and 'pollset_set_alternative' should be non-NULL."); - GRPC_CQ_INTERNAL_REF(cq, "bind"); - call->pollent = - grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq)); - } - if (pollset_set_alternative != NULL) { - call->pollent = - grpc_polling_entity_create_from_pollset_set(pollset_set_alternative); - } - if (!grpc_polling_entity_is_empty(&call->pollent)) { - grpc_call_stack_set_pollset_or_pollset_set( - &exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent); - } + if (parent_call != NULL) { GRPC_CALL_INTERNAL_REF(parent_call, "child"); GPR_ASSERT(call->is_client); @@ -323,7 +296,38 @@ grpc_call *grpc_call_create( gpr_mu_unlock(&parent_call->mu); } + call->send_deadline = send_deadline; + + GRPC_CHANNEL_INTERNAL_REF(channel, "call"); + /* initial refcount dropped by grpc_call_destroy */ + grpc_error *error = grpc_call_stack_init( + &exec_ctx, channel_stack, 1, destroy_call, call, call->context, + server_transport_data, send_deadline, CALL_STACK_FROM_CALL(call)); + if (error != GRPC_ERROR_NONE) { + grpc_status_code status; + const char *error_str; + grpc_error_get_status(error, &status, &error_str); + close_with_status(&exec_ctx, call, status, error_str); + GRPC_ERROR_UNREF(error); + } + if (cq != NULL) { + GPR_ASSERT( + pollset_set_alternative == NULL && + "Only one of 'cq' and 'pollset_set_alternative' should be non-NULL."); + GRPC_CQ_INTERNAL_REF(cq, "bind"); + call->pollent = + grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq)); + } + if (pollset_set_alternative != NULL) { + call->pollent = + grpc_polling_entity_create_from_pollset_set(pollset_set_alternative); + } + if (!grpc_polling_entity_is_empty(&call->pollent)) { + grpc_call_stack_set_pollset_or_pollset_set( + &exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent); + } + grpc_exec_ctx_finish(&exec_ctx); GPR_TIMER_END("grpc_call_create", 0); return call; @@ -1220,8 +1224,8 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx, if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) != 0 && !call->is_client) { - call->send_deadline = gpr_convert_clock_type(md->deadline, - GPR_CLOCK_MONOTONIC); + call->send_deadline = + gpr_convert_clock_type(md->deadline, GPR_CLOCK_MONOTONIC); } } @@ -1250,6 +1254,14 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, GRPC_ERROR_REF(error); gpr_mu_lock(&call->mu); + + // If the error has an associated status code, set the call's status. + intptr_t status; + if (error != GRPC_ERROR_NONE && + grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &status)) { + set_status_from_error(call, STATUS_FROM_CORE, error); + } + if (bctl->send_initial_metadata) { if (error != GRPC_ERROR_NONE) { set_status_from_error(call, STATUS_FROM_CORE, error); diff --git a/test/core/end2end/invalid_call_argument_test.c b/test/core/end2end/invalid_call_argument_test.c index dd2147e609..2b9904a244 100644 --- a/test/core/end2end/invalid_call_argument_test.c +++ b/test/core/end2end/invalid_call_argument_test.c @@ -304,11 +304,6 @@ static void test_receive_initial_metadata_twice_at_client() { grpc_op *op; prepare_test(1); op = g_state.ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = NULL; - op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &g_state.initial_metadata_recv; op->flags = 0; @@ -397,11 +392,6 @@ static void test_recv_status_on_client_twice() { prepare_test(1); op = g_state.ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = NULL; - op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &g_state.trailing_metadata_recv; diff --git a/test/core/end2end/tests/negative_deadline.c b/test/core/end2end/tests/negative_deadline.c index 36632f6a5d..c999ac116a 100644 --- a/test/core/end2end/tests/negative_deadline.c +++ b/test/core/end2end/tests/negative_deadline.c @@ -122,11 +122,6 @@ static void simple_request_body(grpc_end2end_test_fixture f, size_t num_ops) { memset(ops, 0, sizeof(ops)); op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = NULL; - op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; @@ -140,14 +135,15 @@ static void simple_request_body(grpc_end2end_test_fixture f, size_t num_ops) { op->flags = 0; op->reserved = NULL; op++; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; - // Need to send at least the SEND_INITIAL_METADATA and - // RECV_STATUS_ON_CLIENT ops, since the former allows the client to set - // the deadline timer, and the latter returns status to the test. - GPR_ASSERT(num_ops >= 2); GPR_ASSERT(num_ops <= (size_t)(op - ops)); error = grpc_call_start_batch(c, ops, num_ops, tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); @@ -178,7 +174,7 @@ static void test_invoke_simple_request(grpc_end2end_test_config config, void negative_deadline(grpc_end2end_test_config config) { size_t i; - for (i = 2; i <= 4; i++) { + for (i = 1; i <= 4; i++) { test_invoke_simple_request(config, i); } } -- cgit v1.2.3 From 0e256107e812807967aa37ee1dc0ca5e954e9a2c Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 15 Sep 2016 09:01:05 -0700 Subject: Code review changes. --- include/grpc++/server_builder.h | 2 +- include/grpc/impl/codegen/grpc_types.h | 2 +- src/core/lib/channel/channel_args.h | 2 +- src/core/lib/channel/message_size_filter.c | 13 +++++-------- src/cpp/server/server_builder.cc | 4 ++-- test/core/end2end/tests/max_message_length.c | 2 +- 6 files changed, 11 insertions(+), 14 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h index 326962bf78..37f1f8cb80 100644 --- a/include/grpc++/server_builder.h +++ b/include/grpc++/server_builder.h @@ -90,7 +90,7 @@ class ServerBuilder { return *this; } - /// For backward compatibility. + /// \deprecated For backward compatibility. ServerBuilder& SetMaxMessageSize(int max_message_size) { return SetMaxReceiveMessageSize(max_message_size); } diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 7ba6b96868..1a3cb65083 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -128,7 +128,7 @@ typedef struct { #define GRPC_ARG_MAX_CONCURRENT_STREAMS "grpc.max_concurrent_streams" /** Maximum message length that the channel can receive. Int valued, bytes. */ #define GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH "grpc.max_receive_message_length" -/** Backward compatibility. */ +/** \deprecated For backward compatibility. */ #define GRPC_ARG_MAX_MESSAGE_LENGTH GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH /** Maximum message length that the channel can send. Int valued, bytes. */ #define GRPC_ARG_MAX_SEND_MESSAGE_LENGTH "grpc.max_send_message_length" diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h index 71fde5ad7e..586a296d1f 100644 --- a/src/core/lib/channel/channel_args.h +++ b/src/core/lib/channel/channel_args.h @@ -89,12 +89,12 @@ uint32_t grpc_channel_args_compression_algorithm_get_states( int grpc_channel_args_compare(const grpc_channel_args *a, const grpc_channel_args *b); -/** Returns the value of \a arg, subject to the contraints in \a options. */ typedef struct grpc_integer_options { int default_value; // Return this if value is outside of expected bounds. int min_value; int max_value; } grpc_integer_options; +/** Returns the value of \a arg, subject to the contraints in \a options. */ int grpc_channel_arg_get_integer(grpc_arg *arg, grpc_integer_options options); #endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H */ diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index e2d7ff795c..f8bb1134ec 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -70,17 +70,15 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, (*calld->recv_message)->length > chand->max_recv_size) { char* message_string; gpr_asprintf(&message_string, - "Received message larger than max (%lu vs. %lu)", - (unsigned long)(*calld->recv_message)->length, - (unsigned long)chand->max_recv_size); + "Received message larger than max (%u vs. %zu)", + (*calld->recv_message)->length, chand->max_recv_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_cancel_with_message( exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message); } // Invoke the next callback. - calld->next_recv_message_ready->cb( - exec_ctx, calld->next_recv_message_ready->cb_arg, error); + grpc_exec_ctx_sched(exec_ctx, calld->next_recv_message_ready, error, NULL); } // Start transport op. @@ -93,9 +91,8 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, if (op->send_message != NULL && op->send_message->length > chand->max_send_size) { char* message_string; - gpr_asprintf(&message_string, "Sent message larger than max (%lu vs. %lu)", - (unsigned long)op->send_message->length, - (unsigned long)chand->max_send_size); + gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %zu)", + op->send_message->length, chand->max_send_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_cancel_with_message( diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index 960ebd640d..2980b16c56 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -162,10 +162,10 @@ std::unique_ptr ServerBuilder::BuildAndStart() { } (*plugin)->UpdateChannelArguments(&args); } - if (max_receive_message_size_ > 0) { + if (max_receive_message_size_ >= 0) { args.SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, max_receive_message_size_); } - if (max_send_message_size_ > 0) { + if (max_send_message_size_ >= 0) { args.SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, max_send_message_size_); } args.SetInt(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET, diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c index 63bc5ebc0c..cdca3e6748 100644 --- a/test/core/end2end/tests/max_message_length.c +++ b/test/core/end2end/tests/max_message_length.c @@ -105,7 +105,7 @@ static void test_max_message_length(grpc_end2end_test_config config, grpc_end2end_test_fixture f; grpc_arg channel_arg; grpc_channel_args channel_args; - grpc_call *c; + grpc_call *c = NULL; grpc_call *s = NULL; cq_verifier *cqv; grpc_op ops[6]; -- cgit v1.2.3 From c580af37e0bae96b5ef5ae13960742afe22d949e Mon Sep 17 00:00:00 2001 From: yang-g Date: Thu, 15 Sep 2016 15:28:38 -0700 Subject: Add a check for metadata from auth plugin --- .../credentials/plugin/plugin_credentials.c | 25 ++++++++++-- test/cpp/end2end/end2end_test.cc | 46 ++++++++++++++++++---- 2 files changed, 59 insertions(+), 12 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.c b/src/core/lib/security/credentials/plugin/plugin_credentials.c index 824ff081dc..905de3723e 100644 --- a/src/core/lib/security/credentials/plugin/plugin_credentials.c +++ b/src/core/lib/security/credentials/plugin/plugin_credentials.c @@ -37,6 +37,7 @@ #include "src/core/lib/surface/api_trace.h" +#include #include #include #include @@ -71,17 +72,33 @@ static void plugin_md_request_metadata_ready(void *request, error_details); } else { size_t i; + bool seen_illegal_header = false; grpc_credentials_md *md_array = NULL; - if (num_md > 0) { + for (i = 0; i < num_md; i++) { + if (!grpc_header_key_is_legal(md[i].key, strlen(md[i].key))) { + gpr_log(GPR_ERROR, "Plugin added invalid metadata key: %s", md[i].key); + seen_illegal_header = true; + break; + } else if (!grpc_is_binary_header(md[i].key, strlen(md[i].key)) && + !grpc_header_nonbin_value_is_legal(md[i].value, + md[i].value_length)) { + gpr_log(GPR_ERROR, "Plugin added invalid metadata value."); + seen_illegal_header = true; + break; + } + } + if (seen_illegal_header) { + r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR, + "Illegal metadata"); + } else if (num_md > 0) { md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md)); for (i = 0; i < num_md; i++) { md_array[i].key = gpr_slice_from_copied_string(md[i].key); md_array[i].value = gpr_slice_from_copied_buffer(md[i].value, md[i].value_length); } - } - r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK, NULL); - if (md_array != NULL) { + r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK, + NULL); for (i = 0; i < num_md; i++) { gpr_slice_unref(md_array[i].key); gpr_slice_unref(md_array[i].value); diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 66614922f1..1d78f4a911 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -80,11 +80,14 @@ const char kTestCredsPluginErrorMsg[] = "Could not find plugin metadata."; class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin { public: - static const char kMetadataKey[]; + static const char kGoodMetadataKey[]; + static const char kBadMetadataKey[]; - TestMetadataCredentialsPlugin(grpc::string_ref metadata_value, + TestMetadataCredentialsPlugin(grpc::string_ref metadata_key, + grpc::string_ref metadata_value, bool is_blocking, bool is_successful) - : metadata_value_(metadata_value.data(), metadata_value.length()), + : metadata_key_(metadata_key.data(), metadata_key.length()), + metadata_value_(metadata_value.data(), metadata_value.length()), is_blocking_(is_blocking), is_successful_(is_successful) {} @@ -99,7 +102,7 @@ class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin { EXPECT_TRUE(channel_auth_context.IsPeerAuthenticated()); EXPECT_TRUE(metadata != nullptr); if (is_successful_) { - metadata->insert(std::make_pair(kMetadataKey, metadata_value_)); + metadata->insert(std::make_pair(metadata_key_, metadata_value_)); return Status::OK; } else { return Status(StatusCode::NOT_FOUND, kTestCredsPluginErrorMsg); @@ -107,12 +110,16 @@ class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin { } private: + grpc::string metadata_key_; grpc::string metadata_value_; bool is_blocking_; bool is_successful_; }; -const char TestMetadataCredentialsPlugin::kMetadataKey[] = "TestPluginMetadata"; +const char TestMetadataCredentialsPlugin::kBadMetadataKey[] = + "TestPluginMetadata"; +const char TestMetadataCredentialsPlugin::kGoodMetadataKey[] = + "test-plugin-metadata"; class TestAuthMetadataProcessor : public AuthMetadataProcessor { public: @@ -123,13 +130,17 @@ class TestAuthMetadataProcessor : public AuthMetadataProcessor { std::shared_ptr GetCompatibleClientCreds() { return MetadataCredentialsFromPlugin( std::unique_ptr( - new TestMetadataCredentialsPlugin(kGoodGuy, is_blocking_, true))); + new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kGoodMetadataKey, kGoodGuy, + is_blocking_, true))); } std::shared_ptr GetIncompatibleClientCreds() { return MetadataCredentialsFromPlugin( std::unique_ptr( - new TestMetadataCredentialsPlugin("Mr Hyde", is_blocking_, true))); + new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kGoodMetadataKey, "Mr Hyde", + is_blocking_, true))); } // Interface implementation @@ -142,7 +153,7 @@ class TestAuthMetadataProcessor : public AuthMetadataProcessor { EXPECT_TRUE(context != nullptr); EXPECT_TRUE(response_metadata != nullptr); auto auth_md = - auth_metadata.find(TestMetadataCredentialsPlugin::kMetadataKey); + auth_metadata.find(TestMetadataCredentialsPlugin::kGoodMetadataKey); EXPECT_NE(auth_md, auth_metadata.end()); string_ref auth_md_value = auth_md->second; if (auth_md_value == kGoodGuy) { @@ -1322,6 +1333,23 @@ TEST_P(SecureEnd2endTest, OverridePerCallCredentials) { EXPECT_TRUE(s.ok()); } +TEST_P(SecureEnd2endTest, AuthMetadataPluginKeyFailure) { + ResetStub(); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials( + MetadataCredentialsFromPlugin(std::unique_ptr( + new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kBadMetadataKey, + "Does not matter, will fail the key is invalid.", false, true)))); + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); +} + TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) { ResetStub(); EchoRequest request; @@ -1330,6 +1358,7 @@ TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) { context.set_credentials( MetadataCredentialsFromPlugin(std::unique_ptr( new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kGoodMetadataKey, "Does not matter, will fail anyway (see 3rd param)", false, false)))); request.set_message("Hello"); @@ -1388,6 +1417,7 @@ TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginFailure) { context.set_credentials( MetadataCredentialsFromPlugin(std::unique_ptr( new TestMetadataCredentialsPlugin( + TestMetadataCredentialsPlugin::kGoodMetadataKey, "Does not matter, will fail anyway (see 3rd param)", true, false)))); request.set_message("Hello"); -- cgit v1.2.3 From 843ec78263a2b19f935855bb58f858abd9ac0054 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Mon, 19 Sep 2016 07:19:15 -0700 Subject: Fix Windows printf formatting bug. --- src/core/lib/channel/message_size_filter.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index f8bb1134ec..6613785dea 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -69,9 +69,9 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, if (*calld->recv_message != NULL && (*calld->recv_message)->length > chand->max_recv_size) { char* message_string; - gpr_asprintf(&message_string, - "Received message larger than max (%u vs. %zu)", - (*calld->recv_message)->length, chand->max_recv_size); + gpr_asprintf( + &message_string, "Received message larger than max (%u vs. %lu)", + (*calld->recv_message)->length, (unsigned long)chand->max_recv_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_cancel_with_message( @@ -91,8 +91,8 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, if (op->send_message != NULL && op->send_message->length > chand->max_send_size) { char* message_string; - gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %zu)", - op->send_message->length, chand->max_send_size); + gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %lu)", + op->send_message->length, (unsigned long)chand->max_send_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_cancel_with_message( -- cgit v1.2.3 From 219db50d39c2b5754e86838a56d7c8b0bc7273df Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 20 Sep 2016 08:13:16 -0700 Subject: Fix message size filter to use close instead of cancel. --- src/core/lib/channel/message_size_filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index 6613785dea..a254fe3997 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -74,7 +74,7 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, (*calld->recv_message)->length, (unsigned long)chand->max_recv_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); - grpc_call_element_send_cancel_with_message( + grpc_call_element_send_close_with_message( exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message); } // Invoke the next callback. @@ -95,7 +95,7 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, op->send_message->length, (unsigned long)chand->max_send_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); - grpc_call_element_send_cancel_with_message( + grpc_call_element_send_close_with_message( exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message); } // Inject callback for receiving a message. -- cgit v1.2.3 From bbfe1472959d5d73bf217f306c1a231f9c788c3f Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 22 Sep 2016 07:35:20 -0700 Subject: Set default max send message size to unlimited. --- include/grpc/impl/codegen/grpc_types.h | 6 ++++-- src/core/lib/channel/message_size_filter.c | 20 ++++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index a8e8ebe6ea..191cdd0e5f 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -148,11 +148,13 @@ typedef struct { /** Maximum number of concurrent incoming streams to allow on a http2 connection. Int valued. */ #define GRPC_ARG_MAX_CONCURRENT_STREAMS "grpc.max_concurrent_streams" -/** Maximum message length that the channel can receive. Int valued, bytes. */ +/** Maximum message length that the channel can receive. Int valued, bytes. + -1 means unlimited. */ #define GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH "grpc.max_receive_message_length" /** \deprecated For backward compatibility. */ #define GRPC_ARG_MAX_MESSAGE_LENGTH GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH -/** Maximum message length that the channel can send. Int valued, bytes. */ +/** Maximum message length that the channel can send. Int valued, bytes. + -1 means unlimited. */ #define GRPC_ARG_MAX_SEND_MESSAGE_LENGTH "grpc.max_send_message_length" /** Initial sequence number for http2 transports. Int valued. */ #define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \ diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index 6613785dea..7528184d89 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -40,8 +40,9 @@ #include "src/core/lib/channel/channel_args.h" +#define DEFAULT_MAX_SEND_MESSAGE_LENGTH -1 // Unlimited. // The protobuf library will (by default) start warning at 100 megs. -#define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024) +#define DEFAULT_MAX_RECV_MESSAGE_LENGTH (4 * 1024 * 1024) typedef struct call_data { // Receive closures are chained: we inject this closure as the @@ -55,8 +56,8 @@ typedef struct call_data { } call_data; typedef struct channel_data { - size_t max_send_size; - size_t max_recv_size; + long max_send_size; + long max_recv_size; } channel_data; // Callback invoked when we receive a message. Here we check the max @@ -66,7 +67,7 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, grpc_call_element* elem = user_data; call_data* calld = elem->call_data; channel_data* chand = elem->channel_data; - if (*calld->recv_message != NULL && + if (*calld->recv_message != NULL && chand->max_recv_size >= 0 && (*calld->recv_message)->length > chand->max_recv_size) { char* message_string; gpr_asprintf( @@ -88,7 +89,7 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, call_data* calld = elem->call_data; channel_data* chand = elem->channel_data; // Check max send message size. - if (op->send_message != NULL && + if (op->send_message != NULL && chand->max_send_size >= 0 && op->send_message->length > chand->max_send_size) { char* message_string; gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %lu)", @@ -130,17 +131,20 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx, GPR_ASSERT(!args->is_last); channel_data* chand = elem->channel_data; memset(chand, 0, sizeof(*chand)); - chand->max_send_size = DEFAULT_MAX_MESSAGE_LENGTH; - chand->max_recv_size = DEFAULT_MAX_MESSAGE_LENGTH; - const grpc_integer_options options = {DEFAULT_MAX_MESSAGE_LENGTH, 0, INT_MAX}; + chand->max_send_size = DEFAULT_MAX_SEND_MESSAGE_LENGTH; + chand->max_recv_size = DEFAULT_MAX_RECV_MESSAGE_LENGTH; for (size_t i = 0; i < args->channel_args->num_args; ++i) { if (strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) { + const grpc_integer_options options = {DEFAULT_MAX_SEND_MESSAGE_LENGTH, 0, + INT_MAX}; chand->max_send_size = (size_t)grpc_channel_arg_get_integer( &args->channel_args->args[i], options); } if (strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) { + const grpc_integer_options options = {DEFAULT_MAX_RECV_MESSAGE_LENGTH, 0, + INT_MAX}; chand->max_recv_size = (size_t)grpc_channel_arg_get_integer( &args->channel_args->args[i], options); } -- cgit v1.2.3 From c44972ac261fe476230e70c29f83a4460ebe1f03 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 22 Sep 2016 11:08:29 -0700 Subject: Fix type problems. --- src/core/lib/channel/message_size_filter.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index 7528184d89..5a28479426 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -56,8 +56,8 @@ typedef struct call_data { } call_data; typedef struct channel_data { - long max_send_size; - long max_recv_size; + int max_send_size; + int max_recv_size; } channel_data; // Callback invoked when we receive a message. Here we check the max @@ -68,11 +68,11 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, call_data* calld = elem->call_data; channel_data* chand = elem->channel_data; if (*calld->recv_message != NULL && chand->max_recv_size >= 0 && - (*calld->recv_message)->length > chand->max_recv_size) { + (*calld->recv_message)->length > (size_t)chand->max_recv_size) { char* message_string; gpr_asprintf( - &message_string, "Received message larger than max (%u vs. %lu)", - (*calld->recv_message)->length, (unsigned long)chand->max_recv_size); + &message_string, "Received message larger than max (%u vs. %d)", + (*calld->recv_message)->length, chand->max_recv_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_cancel_with_message( @@ -90,10 +90,10 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, channel_data* chand = elem->channel_data; // Check max send message size. if (op->send_message != NULL && chand->max_send_size >= 0 && - op->send_message->length > chand->max_send_size) { + op->send_message->length > (size_t)chand->max_send_size) { char* message_string; - gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %lu)", - op->send_message->length, (unsigned long)chand->max_send_size); + gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %d)", + op->send_message->length, chand->max_send_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_cancel_with_message( @@ -138,14 +138,14 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx, GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) { const grpc_integer_options options = {DEFAULT_MAX_SEND_MESSAGE_LENGTH, 0, INT_MAX}; - chand->max_send_size = (size_t)grpc_channel_arg_get_integer( + chand->max_send_size = grpc_channel_arg_get_integer( &args->channel_args->args[i], options); } if (strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) { const grpc_integer_options options = {DEFAULT_MAX_RECV_MESSAGE_LENGTH, 0, INT_MAX}; - chand->max_recv_size = (size_t)grpc_channel_arg_get_integer( + chand->max_recv_size = grpc_channel_arg_get_integer( &args->channel_args->args[i], options); } } -- cgit v1.2.3 From 923354b39bea315a53393387b4c373d448c30a3f Mon Sep 17 00:00:00 2001 From: Perumaal S Date: Thu, 22 Sep 2016 11:35:22 -0700 Subject: Fix Android+CPP build --- src/core/lib/support/cpu_linux.c | 2 +- src/core/lib/support/cpu_posix.c | 2 +- src/core/lib/support/log_linux.c | 2 +- src/core/lib/support/log_posix.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/support/cpu_linux.c b/src/core/lib/support/cpu_linux.c index d6f7e7d3da..db6c5a2cac 100644 --- a/src/core/lib/support/cpu_linux.c +++ b/src/core/lib/support/cpu_linux.c @@ -37,7 +37,7 @@ #include -#ifdef GPR_CPU_LINUX +#if defined (GPR_CPU_LINUX) && !defined (GPR_ANDROID) #include #include diff --git a/src/core/lib/support/cpu_posix.c b/src/core/lib/support/cpu_posix.c index 667bde7cad..1340c4fd62 100644 --- a/src/core/lib/support/cpu_posix.c +++ b/src/core/lib/support/cpu_posix.c @@ -33,7 +33,7 @@ #include -#ifdef GPR_CPU_POSIX +#if defined (GPR_CPU_POSIX) || defined (GPR_ANDROID) #include #include diff --git a/src/core/lib/support/log_linux.c b/src/core/lib/support/log_linux.c index 299b377373..f3fead10f9 100644 --- a/src/core/lib/support/log_linux.c +++ b/src/core/lib/support/log_linux.c @@ -41,7 +41,7 @@ #include -#ifdef GPR_LINUX_LOG +#if defined(GPR_LINUX_LOG) && !defined(GPR_ANDROID) #include #include diff --git a/src/core/lib/support/log_posix.c b/src/core/lib/support/log_posix.c index 6ae6320767..868d565af8 100644 --- a/src/core/lib/support/log_posix.c +++ b/src/core/lib/support/log_posix.c @@ -33,7 +33,7 @@ #include -#if defined(GPR_POSIX_LOG) +#if defined (GPR_POSIX_LOG) && !defined (GPR_ANDROID) #include #include -- cgit v1.2.3 From e26ab6c5610b9cc4878f6db77700b918272dfc80 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Thu, 22 Sep 2016 15:13:07 -0700 Subject: Adding a method in channel creds to remove any attached call creds. This will be useful when talking to non-trusted load balancer (balancers which are not able to impersonate real backends) as these balancers should not receive bearer tokens. --- .../credentials/composite/composite_credentials.c | 11 +++++++- .../credentials/composite/composite_credentials.h | 4 +-- src/core/lib/security/credentials/credentials.c | 12 +++++++++ src/core/lib/security/credentials/credentials.h | 10 +++++++ .../security/credentials/fake/fake_credentials.c | 2 +- .../lib/security/credentials/ssl/ssl_credentials.c | 2 +- test/core/security/credentials_test.c | 31 ++++++++++++++++++++-- 7 files changed, 65 insertions(+), 7 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/security/credentials/composite/composite_credentials.c b/src/core/lib/security/credentials/composite/composite_credentials.c index 850e41e646..d55d00b7b6 100644 --- a/src/core/lib/security/credentials/composite/composite_credentials.c +++ b/src/core/lib/security/credentials/composite/composite_credentials.c @@ -242,8 +242,17 @@ static grpc_security_status composite_channel_create_security_connector( return status; } +static grpc_channel_credentials * +composite_channel_duplicate_without_call_credentials( + grpc_channel_credentials *creds) { + grpc_composite_channel_credentials *c = + (grpc_composite_channel_credentials *)creds; + return grpc_channel_credentials_ref(c->inner_creds); +} + static grpc_channel_credentials_vtable composite_channel_credentials_vtable = { - composite_channel_destruct, composite_channel_create_security_connector}; + composite_channel_destruct, composite_channel_create_security_connector, + composite_channel_duplicate_without_call_credentials}; grpc_channel_credentials *grpc_composite_channel_credentials_create( grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds, diff --git a/src/core/lib/security/credentials/composite/composite_credentials.h b/src/core/lib/security/credentials/composite/composite_credentials.h index 0d8966f464..f8425c2b76 100644 --- a/src/core/lib/security/credentials/composite/composite_credentials.h +++ b/src/core/lib/security/credentials/composite/composite_credentials.h @@ -53,7 +53,7 @@ grpc_call_credentials *grpc_credentials_contains_type( grpc_call_credentials *creds, const char *type, grpc_call_credentials **composite_creds); -/* -- Channel composite credentials. -- */ +/* -- Composite channel credentials. -- */ typedef struct { grpc_channel_credentials base; @@ -61,7 +61,7 @@ typedef struct { grpc_call_credentials *call_creds; } grpc_composite_channel_credentials; -/* -- Composite credentials. -- */ +/* -- Composite call credentials. -- */ typedef struct { grpc_call_credentials base; diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c index 029a357261..1149e5c2ed 100644 --- a/src/core/lib/security/credentials/credentials.c +++ b/src/core/lib/security/credentials/credentials.c @@ -138,6 +138,18 @@ grpc_security_status grpc_channel_credentials_create_security_connector( channel_creds, NULL, target, args, sc, new_args); } +grpc_channel_credentials * +grpc_channel_credentials_duplicate_without_call_credentials( + grpc_channel_credentials *channel_creds) { + if (channel_creds != NULL && channel_creds->vtable != NULL && + channel_creds->vtable->duplicate_without_call_credentials != NULL) { + return channel_creds->vtable->duplicate_without_call_credentials( + channel_creds); + } else { + return grpc_channel_credentials_ref(channel_creds); + } +} + grpc_server_credentials *grpc_server_credentials_ref( grpc_server_credentials *creds) { if (creds == NULL) return NULL; diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h index 8e9d842ead..6fb5b5b15a 100644 --- a/src/core/lib/security/credentials/credentials.h +++ b/src/core/lib/security/credentials/credentials.h @@ -107,6 +107,9 @@ typedef struct { grpc_channel_credentials *c, grpc_call_credentials *call_creds, const char *target, const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args); + + grpc_channel_credentials *(*duplicate_without_call_credentials)( + grpc_channel_credentials *c); } grpc_channel_credentials_vtable; struct grpc_channel_credentials { @@ -128,6 +131,13 @@ grpc_security_status grpc_channel_credentials_create_security_connector( const grpc_channel_args *args, grpc_channel_security_connector **sc, grpc_channel_args **new_args); +/* Creates a version of the channel credentials without any attached call + credentials. This can be used in order to open a channel to a non-trusted + gRPC load balancer. */ +grpc_channel_credentials * +grpc_channel_credentials_duplicate_without_call_credentials( + grpc_channel_credentials *creds); + /* --- grpc_credentials_md. --- */ typedef struct { diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c index 51cafd986f..ea4cb76fb9 100644 --- a/src/core/lib/security/credentials/fake/fake_credentials.c +++ b/src/core/lib/security/credentials/fake/fake_credentials.c @@ -61,7 +61,7 @@ fake_transport_security_server_create_security_connector( static grpc_channel_credentials_vtable fake_transport_security_credentials_vtable = { - NULL, fake_transport_security_create_security_connector}; + NULL, fake_transport_security_create_security_connector, NULL}; static grpc_server_credentials_vtable fake_transport_security_server_credentials_vtable = { diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.c b/src/core/lib/security/credentials/ssl/ssl_credentials.c index 545bca9d98..0dc1fccec4 100644 --- a/src/core/lib/security/credentials/ssl/ssl_credentials.c +++ b/src/core/lib/security/credentials/ssl/ssl_credentials.c @@ -95,7 +95,7 @@ static grpc_security_status ssl_create_security_connector( } static grpc_channel_credentials_vtable ssl_vtable = { - ssl_destruct, ssl_create_security_connector}; + ssl_destruct, ssl_create_security_connector, NULL}; static void ssl_build_config(const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index 7043953154..2f8ffe4da6 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -46,6 +46,7 @@ #include "src/core/lib/http/httpcli.h" #include "src/core/lib/security/credentials/composite/composite_credentials.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/security/credentials/google_default/google_default_credentials.h" #include "src/core/lib/security/credentials/jwt/jwt_credentials.h" #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h" @@ -411,7 +412,7 @@ static grpc_security_status check_channel_oauth2_create_security_connector( static void test_channel_oauth2_composite_creds(void) { grpc_channel_args *new_args; grpc_channel_credentials_vtable vtable = { - NULL, check_channel_oauth2_create_security_connector}; + NULL, check_channel_oauth2_create_security_connector, NULL}; grpc_channel_credentials *channel_creds = grpc_mock_channel_credentials_create(&vtable); grpc_call_credentials *oauth2_creds = @@ -495,7 +496,7 @@ check_channel_oauth2_google_iam_create_security_connector( static void test_channel_oauth2_google_iam_composite_creds(void) { grpc_channel_args *new_args; grpc_channel_credentials_vtable vtable = { - NULL, check_channel_oauth2_google_iam_create_security_connector}; + NULL, check_channel_oauth2_google_iam_create_security_connector, NULL}; grpc_channel_credentials *channel_creds = grpc_mock_channel_credentials_create(&vtable); grpc_call_credentials *oauth2_creds = @@ -1148,6 +1149,31 @@ static void test_get_well_known_google_credentials_file_path(void) { #endif } +static void test_channel_creds_duplicate_without_call_creds(void) { + grpc_channel_credentials *channel_creds = + grpc_fake_transport_security_credentials_create(); + + grpc_channel_credentials *dup = + grpc_channel_credentials_duplicate_without_call_credentials( + channel_creds); + GPR_ASSERT(dup == channel_creds); + grpc_channel_credentials_unref(dup); + + grpc_call_credentials *call_creds = + grpc_access_token_credentials_create("blah", NULL); + grpc_channel_credentials *composite_creds = + grpc_composite_channel_credentials_create(channel_creds, call_creds, + NULL); + grpc_call_credentials_unref(call_creds); + dup = grpc_channel_credentials_duplicate_without_call_credentials( + composite_creds); + GPR_ASSERT(dup == channel_creds); + grpc_channel_credentials_unref(dup); + + grpc_channel_credentials_unref(channel_creds); + grpc_channel_credentials_unref(composite_creds); +} + int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_init(); @@ -1182,6 +1208,7 @@ int main(int argc, char **argv) { test_metadata_plugin_success(); test_metadata_plugin_failure(); test_get_well_known_google_credentials_file_path(); + test_channel_creds_duplicate_without_call_creds(); grpc_shutdown(); return 0; } -- cgit v1.2.3 From 8a6c8258842c30c4185e1c57b2309daf3d14396e Mon Sep 17 00:00:00 2001 From: Perumaal S Date: Thu, 22 Sep 2016 15:49:02 -0700 Subject: Fix Android CPP Build issues --- include/grpc/impl/codegen/port_platform.h | 4 ++-- src/core/lib/support/cpu_linux.c | 2 +- src/core/lib/support/cpu_posix.c | 2 +- src/core/lib/support/log_linux.c | 2 +- src/core/lib/support/log_posix.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index f97e386289..4e9be4d018 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -155,7 +155,7 @@ #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ -#define GPR_CPU_LINUX 1 +#define GPR_CPU_POSIX 1 #define GPR_GCC_SYNC 1 #define GPR_GCC_TLS 1 #define GPR_POSIX_MULTIPOLL_WITH_POLL 1 @@ -167,7 +167,7 @@ #define GPR_POSIX_ENV 1 #define GPR_POSIX_FILE 1 #define GPR_POSIX_TMPFILE 1 -#define GPR_POSIX_LOG +#define GPR_ANDROID_LOG 1 #define GPR_POSIX_STRING 1 #define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SYNC 1 diff --git a/src/core/lib/support/cpu_linux.c b/src/core/lib/support/cpu_linux.c index db6c5a2cac..d6f7e7d3da 100644 --- a/src/core/lib/support/cpu_linux.c +++ b/src/core/lib/support/cpu_linux.c @@ -37,7 +37,7 @@ #include -#if defined (GPR_CPU_LINUX) && !defined (GPR_ANDROID) +#ifdef GPR_CPU_LINUX #include #include diff --git a/src/core/lib/support/cpu_posix.c b/src/core/lib/support/cpu_posix.c index 1340c4fd62..667bde7cad 100644 --- a/src/core/lib/support/cpu_posix.c +++ b/src/core/lib/support/cpu_posix.c @@ -33,7 +33,7 @@ #include -#if defined (GPR_CPU_POSIX) || defined (GPR_ANDROID) +#ifdef GPR_CPU_POSIX #include #include diff --git a/src/core/lib/support/log_linux.c b/src/core/lib/support/log_linux.c index f3fead10f9..299b377373 100644 --- a/src/core/lib/support/log_linux.c +++ b/src/core/lib/support/log_linux.c @@ -41,7 +41,7 @@ #include -#if defined(GPR_LINUX_LOG) && !defined(GPR_ANDROID) +#ifdef GPR_LINUX_LOG #include #include diff --git a/src/core/lib/support/log_posix.c b/src/core/lib/support/log_posix.c index 868d565af8..f972da0887 100644 --- a/src/core/lib/support/log_posix.c +++ b/src/core/lib/support/log_posix.c @@ -33,7 +33,7 @@ #include -#if defined (GPR_POSIX_LOG) && !defined (GPR_ANDROID) +#ifdef GPR_POSIX_LOG #include #include -- cgit v1.2.3 From e425ce6c958a7b13a10a3cc96cccf4e07db71381 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 23 Sep 2016 09:29:12 -0700 Subject: clang-format --- src/core/lib/channel/message_size_filter.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index 5a28479426..f8a6dd3491 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -70,9 +70,9 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, if (*calld->recv_message != NULL && chand->max_recv_size >= 0 && (*calld->recv_message)->length > (size_t)chand->max_recv_size) { char* message_string; - gpr_asprintf( - &message_string, "Received message larger than max (%u vs. %d)", - (*calld->recv_message)->length, chand->max_recv_size); + gpr_asprintf(&message_string, + "Received message larger than max (%u vs. %d)", + (*calld->recv_message)->length, chand->max_recv_size); gpr_slice message = gpr_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_cancel_with_message( @@ -138,15 +138,15 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx, GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) { const grpc_integer_options options = {DEFAULT_MAX_SEND_MESSAGE_LENGTH, 0, INT_MAX}; - chand->max_send_size = grpc_channel_arg_get_integer( - &args->channel_args->args[i], options); + chand->max_send_size = + grpc_channel_arg_get_integer(&args->channel_args->args[i], options); } if (strcmp(args->channel_args->args[i].key, GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) { const grpc_integer_options options = {DEFAULT_MAX_RECV_MESSAGE_LENGTH, 0, INT_MAX}; - chand->max_recv_size = grpc_channel_arg_get_integer( - &args->channel_args->args[i], options); + chand->max_recv_size = + grpc_channel_arg_get_integer(&args->channel_args->args[i], options); } } } -- cgit v1.2.3 From 966a448a55fa64a5c4654b8cd9656b79cc4b5ba8 Mon Sep 17 00:00:00 2001 From: Dan Born Date: Mon, 26 Sep 2016 15:51:42 -0700 Subject: Require non-NULL exec_ctx to unref. --- src/core/lib/iomgr/tcp_server.h | 4 ++-- src/core/lib/iomgr/tcp_server_posix.c | 11 ----------- src/core/lib/iomgr/tcp_server_windows.c | 19 +++++++------------ 3 files changed, 9 insertions(+), 25 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/tcp_server.h b/src/core/lib/iomgr/tcp_server.h index 5a25d39a0c..9a390699b4 100644 --- a/src/core/lib/iomgr/tcp_server.h +++ b/src/core/lib/iomgr/tcp_server.h @@ -101,8 +101,8 @@ grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s); void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, grpc_closure *shutdown_starting); -/* If the refcount drops to zero, delete s, and call (exec_ctx==NULL) or enqueue - a call (exec_ctx!=NULL) to shutdown_complete. */ +/* If the refcount drops to zero, enqueue calls on exec_ctx to + shutdown_listeners and delete s. */ void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s); /* Shutdown the fds of listeners. */ diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c index 5f846c8afb..73df5477e6 100644 --- a/src/core/lib/iomgr/tcp_server_posix.c +++ b/src/core/lib/iomgr/tcp_server_posix.c @@ -745,22 +745,11 @@ void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { if (gpr_unref(&s->refs)) { - grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT; - bool finish_ctx = false; - /* FIXME: API allows a NULL exec_ctx, although this might cause us to delete - ourself before some enqueued work in some other exec_ctx runs. */ - if (exec_ctx == NULL) { - exec_ctx = &local_exec_ctx; - finish_ctx = true; - } grpc_tcp_server_shutdown_listeners(exec_ctx, s); gpr_mu_lock(&s->mu); grpc_exec_ctx_enqueue_list(exec_ctx, &s->shutdown_starting, NULL); gpr_mu_unlock(&s->mu); tcp_server_destroy(exec_ctx, s); - if (finish_ctx) { - grpc_exec_ctx_finish(exec_ctx); - } } } diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c index 1b125e7005..35faded993 100644 --- a/src/core/lib/iomgr/tcp_server_windows.c +++ b/src/core/lib/iomgr/tcp_server_windows.c @@ -121,6 +121,9 @@ grpc_error *grpc_tcp_server_create(grpc_closure *shutdown_complete, } static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { + gpr_mu_lock(&s->mu); + GPR_ASSERT(s->shutdown); + gpr_mu_unlock(&s->mu); if (s->shutdown_complete != NULL) { grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL); } @@ -139,7 +142,7 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { } grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { - gpr_ref(&s->refs); + gpr_ref_non_zero(&s->refs); return s; } @@ -174,19 +177,11 @@ static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { if (gpr_unref(&s->refs)) { - /* Complete shutdown_starting work before destroying. */ - grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_tcp_server_shutdown_listeners(exec_ctx, s); gpr_mu_lock(&s->mu); - grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL); + grpc_exec_ctx_enqueue_list(exec_ctx, &s->shutdown_starting, NULL); gpr_mu_unlock(&s->mu); - if (exec_ctx == NULL) { - grpc_exec_ctx_flush(&local_exec_ctx); - tcp_server_destroy(&local_exec_ctx, s); - grpc_exec_ctx_finish(&local_exec_ctx); - } else { - grpc_exec_ctx_finish(&local_exec_ctx); - tcp_server_destroy(exec_ctx, s); - } + tcp_server_destroy(exec_ctx, s); } } -- cgit v1.2.3 From bd48c9162a158f4c55acd29ef449b6b12906616b Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Tue, 27 Sep 2016 16:48:25 -0700 Subject: Use SIGMINRT + 6 as the default signal for gRPC epoll engine --- include/grpc/grpc_posix.h | 2 +- src/core/lib/iomgr/ev_epoll_linux.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/include/grpc/grpc_posix.h b/include/grpc/grpc_posix.h index 5e89ae3b1e..6d77f0fb82 100644 --- a/include/grpc/grpc_posix.h +++ b/include/grpc/grpc_posix.h @@ -64,7 +64,7 @@ GRPCAPI void grpc_server_add_insecure_channel_from_fd(grpc_server *server, int fd); /** GRPC Core POSIX library may internally use signals to optimize some work. - The library uses (SIGRTMIN + 2) signal by default. Use this API to instruct + The library uses (SIGRTMIN + 6) signal by default. Use this API to instruct the library to use a different signal i.e 'signum' instead. Note: - To prevent GRPC library from using any signals, pass a 'signum' of -1 diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c index 740920d760..ab77ebc78b 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epoll_linux.c @@ -1897,7 +1897,7 @@ const grpc_event_engine_vtable *grpc_init_epoll_linux(void) { } if (!is_grpc_wakeup_signal_initialized) { - grpc_use_signal(SIGRTMIN + 2); + grpc_use_signal(SIGRTMIN + 6); } fd_global_init(); -- cgit v1.2.3 From fa242cba900ece728d2910e7396d02ebab4ddb2c Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 29 Sep 2016 00:54:02 +0200 Subject: Plugging memory leak. --- src/core/lib/iomgr/tcp_windows.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/tcp_windows.c b/src/core/lib/iomgr/tcp_windows.c index 35054c42b5..448a72671c 100644 --- a/src/core/lib/iomgr/tcp_windows.c +++ b/src/core/lib/iomgr/tcp_windows.c @@ -319,6 +319,7 @@ static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, ? GRPC_ERROR_NONE : GRPC_WSA_ERROR(info->wsa_error, "WSASend"); grpc_exec_ctx_sched(exec_ctx, cb, error, NULL); + if (allocated) gpr_free(allocated); return; } -- cgit v1.2.3 From e02c7ed37b1f98ed95b8f47e053d4a617fd7c530 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Thu, 29 Sep 2016 09:15:49 -0700 Subject: Broke cv polling into seperate engine --- BUILD | 12 + CMakeLists.txt | 5 + Makefile | 6 + binding.gyp | 1 + build.yaml | 2 + config.m4 | 1 + gRPC-Core.podspec | 3 + grpc.gemspec | 2 + package.xml | 2 + src/core/lib/iomgr/ev_poll_cv_posix.c | 282 +++++++++++++++++++++ src/core/lib/iomgr/ev_poll_cv_posix.h | 65 +++++ src/core/lib/iomgr/ev_posix.c | 2 + src/core/lib/iomgr/wakeup_fd_cv.c | 230 +---------------- src/core/lib/iomgr/wakeup_fd_cv.h | 5 +- src/core/lib/iomgr/wakeup_fd_posix.c | 9 +- src/core/lib/iomgr/wakeup_fd_posix.h | 1 + src/python/grpcio/grpc_core_dependencies.py | 1 + test/core/iomgr/wakeup_fd_cv_test.c | 19 +- tools/doxygen/Doxyfile.c++.internal | 2 + tools/doxygen/Doxyfile.core.internal | 2 + tools/run_tests/run_tests.py | 2 +- tools/run_tests/sources_and_headers.json | 3 + vsprojects/vcxproj/grpc++/grpc++.vcxproj | 3 + vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters | 6 + .../grpc++_unsecure/grpc++_unsecure.vcxproj | 3 + .../grpc++_unsecure.vcxproj.filters | 6 + vsprojects/vcxproj/grpc/grpc.vcxproj | 3 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 6 + .../vcxproj/grpc_test_util/grpc_test_util.vcxproj | 3 + .../grpc_test_util/grpc_test_util.vcxproj.filters | 6 + .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 3 + .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 + 32 files changed, 463 insertions(+), 239 deletions(-) create mode 100644 src/core/lib/iomgr/ev_poll_cv_posix.c create mode 100644 src/core/lib/iomgr/ev_poll_cv_posix.h (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index 67e481e0d2..a8d1b4a5b9 100644 --- a/BUILD +++ b/BUILD @@ -184,6 +184,7 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -341,6 +342,7 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -581,6 +583,7 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -724,6 +727,7 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -935,6 +939,7 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -1069,6 +1074,7 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -1284,6 +1290,7 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -1398,6 +1405,7 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -1696,6 +1704,7 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -1805,6 +1814,7 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -2196,6 +2206,7 @@ objc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -2415,6 +2426,7 @@ objc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index f07fa26e63..1f8c4ca0f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -313,6 +313,7 @@ add_library(grpc src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c + src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -572,6 +573,7 @@ add_library(grpc_cronet src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c + src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -804,6 +806,7 @@ add_library(grpc_unsecure src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c + src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -1062,6 +1065,7 @@ add_library(grpc++ src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c + src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -1420,6 +1424,7 @@ add_library(grpc++_unsecure src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c + src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c diff --git a/Makefile b/Makefile index a23e12687d..0b23fc44bc 100644 --- a/Makefile +++ b/Makefile @@ -2538,6 +2538,7 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -2815,6 +2816,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -3081,6 +3083,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -3275,6 +3278,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -3616,6 +3620,7 @@ LIBGRPC++_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -4252,6 +4257,7 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ diff --git a/binding.gyp b/binding.gyp index 1b68b63d22..d97b1410e1 100644 --- a/binding.gyp +++ b/binding.gyp @@ -585,6 +585,7 @@ 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', + 'src/core/lib/iomgr/ev_poll_cv_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', diff --git a/build.yaml b/build.yaml index d4f731e85f..7693c911f9 100644 --- a/build.yaml +++ b/build.yaml @@ -186,6 +186,7 @@ filegroups: - src/core/lib/iomgr/error.h - src/core/lib/iomgr/ev_epoll_linux.h - src/core/lib/iomgr/ev_poll_and_epoll_posix.h + - src/core/lib/iomgr/ev_poll_cv_posix.h - src/core/lib/iomgr/ev_poll_posix.h - src/core/lib/iomgr/ev_posix.h - src/core/lib/iomgr/exec_ctx.h @@ -268,6 +269,7 @@ filegroups: - src/core/lib/iomgr/error.c - src/core/lib/iomgr/ev_epoll_linux.c - src/core/lib/iomgr/ev_poll_and_epoll_posix.c + - src/core/lib/iomgr/ev_poll_cv_posix.c - src/core/lib/iomgr/ev_poll_posix.c - src/core/lib/iomgr/ev_posix.c - src/core/lib/iomgr/exec_ctx.c diff --git a/config.m4 b/config.m4 index 6b605fbcd6..bebcab601a 100644 --- a/config.m4 +++ b/config.m4 @@ -104,6 +104,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 92b3022cf7..73953cc8bd 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -275,6 +275,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/ev_epoll_linux.h', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.h', + 'src/core/lib/iomgr/ev_poll_cv_posix.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', @@ -436,6 +437,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', + 'src/core/lib/iomgr/ev_poll_cv_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', @@ -639,6 +641,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/ev_epoll_linux.h', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.h', + 'src/core/lib/iomgr/ev_poll_cv_posix.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', diff --git a/grpc.gemspec b/grpc.gemspec index d672bb1284..64441ead59 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -195,6 +195,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/error.h ) s.files += %w( src/core/lib/iomgr/ev_epoll_linux.h ) s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.h ) + s.files += %w( src/core/lib/iomgr/ev_poll_cv_posix.h ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.h ) s.files += %w( src/core/lib/iomgr/ev_posix.h ) s.files += %w( src/core/lib/iomgr/exec_ctx.h ) @@ -356,6 +357,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/error.c ) s.files += %w( src/core/lib/iomgr/ev_epoll_linux.c ) s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.c ) + s.files += %w( src/core/lib/iomgr/ev_poll_cv_posix.c ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.c ) s.files += %w( src/core/lib/iomgr/ev_posix.c ) s.files += %w( src/core/lib/iomgr/exec_ctx.c ) diff --git a/package.xml b/package.xml index 02cc271fe5..3e2d9d278c 100644 --- a/package.xml +++ b/package.xml @@ -202,6 +202,7 @@ + @@ -363,6 +364,7 @@ + diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.c b/src/core/lib/iomgr/ev_poll_cv_posix.c new file mode 100644 index 0000000000..596a3025eb --- /dev/null +++ b/src/core/lib/iomgr/ev_poll_cv_posix.c @@ -0,0 +1,282 @@ +/* + * + * 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 + +#ifdef GPR_POSIX_SOCKET + +#include "src/core/lib/iomgr/ev_poll_cv_posix.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/ev_poll_posix.h" +#include "src/core/lib/iomgr/wakeup_fd_posix.h" + +#define POLL_PERIOD_MS 1000 +#define DEFAULT_TABLE_SIZE 16 + +// poll_result is owned by parent thread +typedef struct poll_result { + struct pollfd* fds; + gpr_cv* cv; + int completed; + int res; + int err; +} poll_result; + +// poll_args is owned by spawned thread +typedef struct poll_args { + struct pollfd* fds; + nfds_t nfds; + int timeout; + poll_result* result; +} poll_args; + +cv_fd_table g_cvfds; + +// Poll in a background thread +static void run_poll(void* arg) { + int result, timeout; + poll_args* pargs = (poll_args*)arg; + gpr_mu_lock(&g_cvfds.mu); + if (pargs->result != NULL) { + while (pargs->result != NULL) { + if (pargs->timeout < 0) { + timeout = POLL_PERIOD_MS; + } else { + timeout = GPR_MIN(POLL_PERIOD_MS, pargs->timeout); + pargs->timeout -= timeout; + } + gpr_mu_unlock(&g_cvfds.mu); + result = g_cvfds.poll(pargs->fds, pargs->nfds, timeout); + gpr_mu_lock(&g_cvfds.mu); + if (pargs->result != NULL) { + if (result != 0 || pargs->timeout == 0) { + memcpy(pargs->result->fds, pargs->fds, + sizeof(struct pollfd) * pargs->nfds); + pargs->result->res = result; + pargs->result->err = errno; + pargs->result->completed = 1; + gpr_cv_signal(pargs->result->cv); + break; + } + } + } + } + gpr_free(pargs->fds); + gpr_free(pargs); + gpr_mu_unlock(&g_cvfds.mu); +} + +// This function overrides poll() to handle condition variable wakeup fds +static int cvfd_poll(struct pollfd* fds, nfds_t nfds, int timeout) { + unsigned int i; + int res, idx; + cv_node *cvn, *prev; + struct pollfd* sockfds; + nfds_t nsockfds = 0; + gpr_cv pollcv; + gpr_thd_id t_id; + gpr_thd_options opt; + poll_args* pargs; + poll_result* pres; + gpr_mu_lock(&g_cvfds.mu); + gpr_cv_init(&pollcv); + for (i = 0; i < nfds; i++) { + fds[i].revents = 0; + if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { + idx = FD_TO_IDX(fds[i].fd); + cvn = gpr_malloc(sizeof(cv_node)); + cvn->cv = &pollcv; + cvn->next = g_cvfds.cvfds[idx].cvs; + g_cvfds.cvfds[idx].cvs = cvn; + // We should return immediately if there are pending events, + // but we still need to call poll() to check for socket events + if (g_cvfds.cvfds[idx].is_set) { + timeout = 0; + } + } else if (fds[i].fd >= 0) { + nsockfds++; + } + } + sockfds = gpr_malloc(sizeof(struct pollfd) * nsockfds); + idx = 0; + for (i = 0; i < nfds; i++) { + if (fds[i].fd >= 0) { + sockfds[idx].fd = fds[i].fd; + sockfds[idx].events = fds[i].events; + sockfds[idx].revents = 0; + idx++; + } + } + + errno = 0; + if (nsockfds > 0) { + pres = gpr_malloc(sizeof(struct poll_result)); + pargs = gpr_malloc(sizeof(struct poll_args)); + + pargs->fds = gpr_malloc(sizeof(struct pollfd) * nsockfds); + memcpy(pargs->fds, sockfds, sizeof(struct pollfd) * nsockfds); + pargs->nfds = nsockfds; + pargs->timeout = timeout; + pargs->result = pres; + + pres->fds = sockfds; + pres->cv = &pollcv; + pres->completed = 0; + pres->res = 0; + pres->err = 0; + + opt = gpr_thd_options_default(); + gpr_thd_options_set_detached(&opt); + gpr_thd_new(&t_id, &run_poll, pargs, &opt); + // We want the poll() thread to trigger the deadline, so wait forever here + gpr_cv_wait(&pollcv, &g_cvfds.mu, gpr_inf_future(GPR_CLOCK_MONOTONIC)); + if (!pres->completed) { + pargs->result = NULL; + } + res = pres->res; + errno = pres->err; + gpr_free(pres); + } else { + gpr_timespec deadline = gpr_now(GPR_CLOCK_REALTIME); + deadline = + gpr_time_add(deadline, gpr_time_from_millis(timeout, GPR_TIMESPAN)); + gpr_cv_wait(&pollcv, &g_cvfds.mu, deadline); + res = 0; + } + idx = 0; + for (i = 0; i < nfds; i++) { + if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { + cvn = g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs; + prev = NULL; + while (cvn->cv != &pollcv) { + prev = cvn; + cvn = cvn->next; + GPR_ASSERT(cvn); + } + if (!prev) { + g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs = cvn->next; + } else { + prev->next = cvn->next; + } + gpr_free(cvn); + + if (g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].is_set) { + fds[i].revents = POLLIN; + if (res >= 0) res++; + } + } else if (fds[i].fd >= 0) { + fds[i].revents = sockfds[idx].revents; + idx++; + } + } + gpr_free(sockfds); + gpr_cv_destroy(&pollcv); + gpr_mu_unlock(&g_cvfds.mu); + + return res; +} + +static void grpc_global_cv_fd_table_init() { + gpr_mu_init(&g_cvfds.mu); + gpr_mu_lock(&g_cvfds.mu); + g_cvfds.size = DEFAULT_TABLE_SIZE; + g_cvfds.cvfds = gpr_malloc(sizeof(fd_node) * DEFAULT_TABLE_SIZE); + g_cvfds.free_fds = NULL; + for (int i = 0; i < DEFAULT_TABLE_SIZE; i++) { + g_cvfds.cvfds[i].is_set = 0; + g_cvfds.cvfds[i].cvs = NULL; + g_cvfds.cvfds[i].next_free = g_cvfds.free_fds; + g_cvfds.free_fds = &g_cvfds.cvfds[i]; + } + // Override the poll function with one that supports cvfds + g_cvfds.poll = grpc_poll_function; + grpc_poll_function = &cvfd_poll; + gpr_mu_unlock(&g_cvfds.mu); +} + +static void grpc_global_cv_fd_table_shutdown() { + gpr_mu_lock(&g_cvfds.mu); + grpc_poll_function = g_cvfds.poll; + gpr_free(g_cvfds.cvfds); + gpr_mu_unlock(&g_cvfds.mu); + gpr_mu_destroy(&g_cvfds.mu); +} + +/******************************************************************************* + * event engine binding + */ + +static const grpc_event_engine_vtable* ev_poll_vtable; +static grpc_event_engine_vtable vtable; + +static void shutdown_engine(void) { + ev_poll_vtable->shutdown_engine(); + grpc_global_cv_fd_table_shutdown(); +} + +const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void) { + int has_wakeup_fd = grpc_has_wakeup_fd; + int allow_specialized_wakeup_fd = grpc_allow_specialized_wakeup_fd; + int allow_pipe_wakeup_fd = grpc_allow_pipe_wakeup_fd; + grpc_global_cv_fd_table_init(); + grpc_has_wakeup_fd = 1; + grpc_allow_specialized_wakeup_fd = 0; + grpc_allow_pipe_wakeup_fd = 0; + grpc_wakeup_fd_global_init(); + ev_poll_vtable = grpc_init_poll_posix(); + if (!ev_poll_vtable) { + grpc_global_cv_fd_table_shutdown(); + grpc_has_wakeup_fd = has_standard_wakeup_fd; + grpc_allow_specialized_wakeup_fd = allow_specialized_wakeup_fd; + grpc_allow_pipe_wakeup_fd = allow_pipe_wakeup_fd; + grpc_has_wakeup_fd = has_standard_wakeup_fd; + grpc_global_cv_fd_table_init(); + return NULL; + } + + vtable = *ev_poll_vtable; + vtable.shutdown_engine = shutdown_engine; + return &vtable; +} + +#endif /* GPR_POSIX_SOCKET */ diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.h b/src/core/lib/iomgr/ev_poll_cv_posix.h new file mode 100644 index 0000000000..0fd3e5bbb4 --- /dev/null +++ b/src/core/lib/iomgr/ev_poll_cv_posix.h @@ -0,0 +1,65 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_EV_POLL_CV_POSIX_H +#define GRPC_CORE_LIB_IOMGR_EV_POLL_CV_POSIX_H + +#include + +#include "src/core/lib/iomgr/ev_posix.h" + +#define FD_TO_IDX(fd) (-(fd)-1) +#define IDX_TO_FD(idx) (-(idx)-1) + +typedef struct cv_node { + gpr_cv* cv; + struct cv_node* next; +} cv_node; + +typedef struct fd_node { + int is_set; + cv_node* cvs; + struct fd_node* next_free; +} fd_node; + +typedef struct cv_fd_table { + gpr_mu mu; + fd_node* cvfds; + fd_node* free_fds; + unsigned int size; + grpc_poll_function_type poll; +} cv_fd_table; + +const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void); + +#endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H */ diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c index 6536672685..2fc8ccfa91 100644 --- a/src/core/lib/iomgr/ev_posix.c +++ b/src/core/lib/iomgr/ev_posix.c @@ -46,6 +46,7 @@ #include "src/core/lib/iomgr/ev_epoll_linux.h" #include "src/core/lib/iomgr/ev_poll_and_epoll_posix.h" +#include "src/core/lib/iomgr/ev_poll_cv_posix.h" #include "src/core/lib/iomgr/ev_poll_posix.h" #include "src/core/lib/support/env.h" @@ -66,6 +67,7 @@ typedef struct { static const event_engine_factory g_factories[] = { {"epoll", grpc_init_epoll_linux}, {"poll", grpc_init_poll_posix}, + {"poll-cv", grpc_init_poll_cv_posix}, {"legacy", grpc_init_poll_and_epoll_posix}, }; diff --git a/src/core/lib/iomgr/wakeup_fd_cv.c b/src/core/lib/iomgr/wakeup_fd_cv.c index bfdc2cb422..651e2f663d 100644 --- a/src/core/lib/iomgr/wakeup_fd_cv.c +++ b/src/core/lib/iomgr/wakeup_fd_cv.c @@ -35,8 +35,6 @@ #ifdef GPR_POSIX_WAKEUP_FD -#include "src/core/lib/iomgr/wakeup_fd_posix.h" - #include #include @@ -47,200 +45,16 @@ #include #include -#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/ev_poll_cv_posix.h" #define MAX_TABLE_RESIZE 256 -#define DEFAULT_TABLE_SIZE 16 -#define POLL_PERIOD_MS 1000 - -#define FD_TO_IDX(fd) (-(fd)-1) -#define IDX_TO_FD(idx) (-(idx)-1) - -typedef struct cv_node { - gpr_cv* cv; - struct cv_node* next; -} cv_node; - -typedef struct fd_node { - int is_set; - cv_node* cvs; - struct fd_node* next_free; -} fd_node; - -typedef struct cv_fd_table { - fd_node* cvfds; - fd_node* free_fds; - unsigned int size; - grpc_poll_function_type poll; -} cv_fd_table; - -typedef struct poll_result { - struct pollfd* fds; - gpr_cv* cv; - int completed; - int res; - int err; -} poll_result; - -typedef struct poll_args { - struct pollfd* fds; - nfds_t nfds; - int timeout; - poll_result* result; -} poll_args; - -static gpr_mu g_mu = PTHREAD_MUTEX_INITIALIZER; -static cv_fd_table g_cvfds; - -// Some environments do not implement pthread_cancel(), so we run -// this poll in a detached thread, and wake up periodically and -// check if the calling thread is still waiting on a result -static void run_poll(void* arg) { - int result, timeout; - poll_args* pargs = (poll_args*)arg; - gpr_mu_lock(&g_mu); - if (pargs->result != NULL) { - while (pargs->result != NULL) { - if (pargs->timeout < 0) { - timeout = POLL_PERIOD_MS; - } else { - timeout = GPR_MIN(POLL_PERIOD_MS, pargs->timeout); - pargs->timeout -= timeout; - } - gpr_mu_unlock(&g_mu); - result = g_cvfds.poll(pargs->fds, pargs->nfds, timeout); - gpr_mu_lock(&g_mu); - if (pargs->result != NULL) { - if (result != 0 || pargs->timeout == 0) { - memcpy(pargs->result->fds, pargs->fds, - sizeof(struct pollfd) * pargs->nfds); - pargs->result->res = result; - pargs->result->err = errno; - pargs->result->completed = 1; - gpr_cv_signal(pargs->result->cv); - break; - } - } - } - } - gpr_free(pargs->fds); - gpr_free(pargs); - gpr_mu_unlock(&g_mu); -} - -int cvfd_poll(struct pollfd* fds, nfds_t nfds, int timeout) { - unsigned int i; - int res, idx; - cv_node *cvn, *prev; - struct pollfd* sockfds; - nfds_t nsockfds = 0; - gpr_cv pollcv; - gpr_thd_id t_id; - gpr_thd_options opt; - poll_args* pargs; - poll_result* pres; - gpr_mu_lock(&g_mu); - gpr_cv_init(&pollcv); - for (i = 0; i < nfds; i++) { - fds[i].revents = 0; - if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { - idx = FD_TO_IDX(fds[i].fd); - cvn = gpr_malloc(sizeof(cv_node)); - cvn->cv = &pollcv; - cvn->next = g_cvfds.cvfds[idx].cvs; - g_cvfds.cvfds[idx].cvs = cvn; - // We should return immediately if there are pending events, - // but we still need to call poll() to check for socket events - if (g_cvfds.cvfds[idx].is_set) { - timeout = 0; - } - } else if (fds[i].fd >= 0) { - nsockfds++; - } - } - sockfds = gpr_malloc(sizeof(struct pollfd) * nsockfds); - idx = 0; - for (i = 0; i < nfds; i++) { - if (fds[i].fd >= 0) { - sockfds[idx].fd = fds[i].fd; - sockfds[idx].events = fds[i].events; - sockfds[idx].revents = 0; - idx++; - } - } - - errno = 0; - if (nsockfds > 0) { - pres = gpr_malloc(sizeof(struct poll_result)); - pargs = gpr_malloc(sizeof(struct poll_args)); - - pargs->fds = gpr_malloc(sizeof(struct pollfd) * nsockfds); - memcpy(pargs->fds, sockfds, sizeof(struct pollfd) * nsockfds); - pargs->nfds = nsockfds; - pargs->timeout = timeout; - pargs->result = pres; - - pres->fds = sockfds; - pres->cv = &pollcv; - pres->completed = 0; - pres->res = 0; - pres->err = 0; - - opt = gpr_thd_options_default(); - gpr_thd_options_set_detached(&opt); - gpr_thd_new(&t_id, &run_poll, pargs, &opt); - // We want the poll() thread to trigger the deadline, so wait forever here - gpr_cv_wait(&pollcv, &g_mu, gpr_inf_future(GPR_CLOCK_MONOTONIC)); - if (!pres->completed) { - pargs->result = NULL; - } - res = pres->res; - errno = pres->err; - gpr_free(pres); - } else { - gpr_timespec deadline = gpr_now(GPR_CLOCK_REALTIME); - deadline = - gpr_time_add(deadline, gpr_time_from_millis(timeout, GPR_TIMESPAN)); - gpr_cv_wait(&pollcv, &g_mu, deadline); - res = 0; - } - idx = 0; - for (i = 0; i < nfds; i++) { - if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { - cvn = g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs; - prev = NULL; - while (cvn->cv != &pollcv) { - prev = cvn; - cvn = cvn->next; - GPR_ASSERT(cvn); - } - if (!prev) { - g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs = cvn->next; - } else { - prev->next = cvn->next; - } - gpr_free(cvn); - - if (g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].is_set) { - fds[i].revents = POLLIN; - if (res >= 0) res++; - } - } else if (fds[i].fd >= 0) { - fds[i].revents = sockfds[idx].revents; - idx++; - } - } - gpr_free(sockfds); - gpr_cv_destroy(&pollcv); - gpr_mu_unlock(&g_mu); - return res; -} +extern cv_fd_table g_cvfds; static grpc_error* cv_fd_init(grpc_wakeup_fd* fd_info) { unsigned int i, newsize; int idx; - gpr_mu_lock(&g_mu); + gpr_mu_lock(&g_cvfds.mu); if (!g_cvfds.free_fds) { newsize = GPR_MIN(g_cvfds.size * 2, g_cvfds.size + MAX_TABLE_RESIZE); g_cvfds.cvfds = gpr_realloc(g_cvfds.cvfds, sizeof(fd_node) * newsize); @@ -259,51 +73,27 @@ static grpc_error* cv_fd_init(grpc_wakeup_fd* fd_info) { g_cvfds.cvfds[idx].is_set = 0; fd_info->read_fd = IDX_TO_FD(idx); fd_info->write_fd = -1; - gpr_mu_unlock(&g_mu); + gpr_mu_unlock(&g_cvfds.mu); return GRPC_ERROR_NONE; } -void grpc_global_cv_fd_table_init() { - gpr_mu_lock(&g_mu); - g_cvfds.size = DEFAULT_TABLE_SIZE; - g_cvfds.cvfds = gpr_malloc(sizeof(fd_node) * DEFAULT_TABLE_SIZE); - g_cvfds.free_fds = NULL; - for (int i = 0; i < DEFAULT_TABLE_SIZE; i++) { - g_cvfds.cvfds[i].is_set = 0; - g_cvfds.cvfds[i].cvs = NULL; - g_cvfds.cvfds[i].next_free = g_cvfds.free_fds; - g_cvfds.free_fds = &g_cvfds.cvfds[i]; - } - // Override the poll function with one that supports cvfds - g_cvfds.poll = grpc_poll_function; - grpc_poll_function = &cvfd_poll; - gpr_mu_unlock(&g_mu); -} - -void grpc_global_cv_fd_table_shutdown() { - gpr_mu_lock(&g_mu); - grpc_poll_function = g_cvfds.poll; - gpr_free(g_cvfds.cvfds); - gpr_mu_unlock(&g_mu); -} - static grpc_error* cv_fd_wakeup(grpc_wakeup_fd* fd_info) { cv_node* cvn; - gpr_mu_lock(&g_mu); + gpr_mu_lock(&g_cvfds.mu); g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].is_set = 1; cvn = g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].cvs; while (cvn) { gpr_cv_signal(cvn->cv); cvn = cvn->next; } - gpr_mu_unlock(&g_mu); + gpr_mu_unlock(&g_cvfds.mu); return GRPC_ERROR_NONE; } static grpc_error* cv_fd_consume(grpc_wakeup_fd* fd_info) { - gpr_mu_lock(&g_mu); + gpr_mu_lock(&g_cvfds.mu); g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].is_set = 0; - gpr_mu_unlock(&g_mu); + gpr_mu_unlock(&g_cvfds.mu); return GRPC_ERROR_NONE; } @@ -311,12 +101,12 @@ static void cv_fd_destroy(grpc_wakeup_fd* fd_info) { if (fd_info->read_fd == 0) { return; } - gpr_mu_lock(&g_mu); + gpr_mu_lock(&g_cvfds.mu); // Assert that there are no active pollers GPR_ASSERT(!g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].cvs); g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].next_free = g_cvfds.free_fds; g_cvfds.free_fds = &g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)]; - gpr_mu_unlock(&g_mu); + gpr_mu_unlock(&g_cvfds.mu); } static int cv_check_availability(void) { return 1; } diff --git a/src/core/lib/iomgr/wakeup_fd_cv.h b/src/core/lib/iomgr/wakeup_fd_cv.h index 22ee6c0bbe..e57fc28363 100644 --- a/src/core/lib/iomgr/wakeup_fd_cv.h +++ b/src/core/lib/iomgr/wakeup_fd_cv.h @@ -41,7 +41,7 @@ * A global table of cv wakeup fds is mantained. A cv wakeup fd is a negative * file descriptor. poll() is then run in a background thread with only the * real socket fds while we wait on a condition variable trigged by either the - * poll() called or a wakeup_fd() call. + * poll() completion or a wakeup_fd() call. * */ @@ -50,9 +50,6 @@ #include "src/core/lib/iomgr/wakeup_fd_posix.h" -void grpc_global_cv_fd_table_init(); -void grpc_global_cv_fd_table_shutdown(); - extern grpc_wakeup_fd_vtable grpc_cv_wakeup_fd_vtable; #endif /* GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H */ diff --git a/src/core/lib/iomgr/wakeup_fd_posix.c b/src/core/lib/iomgr/wakeup_fd_posix.c index 564b836154..48ed92abe8 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.c +++ b/src/core/lib/iomgr/wakeup_fd_posix.c @@ -33,7 +33,7 @@ #include -#ifdef GPR_POSIX_WAKEUP_FD +#ifdef GPR_POSIX_SOCKET #include #include "src/core/lib/iomgr/wakeup_fd_cv.h" @@ -43,6 +43,8 @@ static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL; int grpc_allow_specialized_wakeup_fd = 1; int grpc_allow_pipe_wakeup_fd = 1; +int grpc_has_wakeup_fd = 1; + void grpc_wakeup_fd_global_init(void) { if (grpc_allow_specialized_wakeup_fd && @@ -52,15 +54,12 @@ void grpc_wakeup_fd_global_init(void) { grpc_pipe_wakeup_fd_vtable.check_availability()) { wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable; } else { + grpc_has_wakeup_fd = 0; wakeup_fd_vtable = &grpc_cv_wakeup_fd_vtable; - grpc_global_cv_fd_table_init(); } } void grpc_wakeup_fd_global_destroy(void) { - if (wakeup_fd_vtable == &grpc_cv_wakeup_fd_vtable) { - grpc_global_cv_fd_table_shutdown(); - } wakeup_fd_vtable = NULL; } diff --git a/src/core/lib/iomgr/wakeup_fd_posix.h b/src/core/lib/iomgr/wakeup_fd_posix.h index a9f902bc9f..bd0fb46da1 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.h +++ b/src/core/lib/iomgr/wakeup_fd_posix.h @@ -89,6 +89,7 @@ struct grpc_wakeup_fd { extern int grpc_allow_specialized_wakeup_fd; extern int grpc_allow_pipe_wakeup_fd; +extern int grpc_has_wakeup_fd; #define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd) diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index dc2ce46979..0d4c7d1c0e 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -98,6 +98,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', + 'src/core/lib/iomgr/ev_poll_cv_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', diff --git a/test/core/iomgr/wakeup_fd_cv_test.c b/test/core/iomgr/wakeup_fd_cv_test.c index 2cd777536d..8ac78a2f41 100644 --- a/test/core/iomgr/wakeup_fd_cv_test.c +++ b/test/core/iomgr/wakeup_fd_cv_test.c @@ -39,7 +39,7 @@ #include #include "src/core/lib/iomgr/ev_posix.h" -#include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include "src/core/lib/iomgr/iomgr_posix.h" #include "src/core/lib/support/env.h" typedef struct poll_args { @@ -102,7 +102,6 @@ void background_poll(void *args) { void test_many_fds(void) { int i; - grpc_wakeup_fd_global_init(); grpc_wakeup_fd fd[1000]; for (i = 0; i < 1000; i++) { GPR_ASSERT(grpc_wakeup_fd_init(&fd[i]) == GRPC_ERROR_NONE); @@ -110,7 +109,6 @@ void test_many_fds(void) { for (i = 0; i < 1000; i++) { grpc_wakeup_fd_destroy(&fd[i]); } - grpc_wakeup_fd_global_destroy(); } void test_poll_cv_trigger(void) { @@ -119,8 +117,6 @@ void test_poll_cv_trigger(void) { poll_args pargs; gpr_thd_id t_id; gpr_thd_options opt; - grpc_poll_function = &mock_poll; - grpc_wakeup_fd_global_init(); GPR_ASSERT(grpc_wakeup_fd_init(&cvfd1) == GRPC_ERROR_NONE); GPR_ASSERT(grpc_wakeup_fd_init(&cvfd2) == GRPC_ERROR_NONE); @@ -226,17 +222,22 @@ void test_poll_cv_trigger(void) { GPR_ASSERT(pfds[4].revents == 0); GPR_ASSERT(pfds[5].revents == 0); - grpc_wakeup_fd_global_destroy(); } int main(int argc, char **argv) { - gpr_setenv("GRPC_POLL_STRATEGY", "poll"); - grpc_allow_specialized_wakeup_fd = 0; - grpc_allow_pipe_wakeup_fd = 0; + gpr_setenv("GRPC_POLL_STRATEGY", "poll-cv"); + grpc_poll_function = &mock_poll; gpr_mu_init(&poll_mu); gpr_cv_init(&poll_cv); + + grpc_iomgr_platform_init(); test_many_fds(); + grpc_iomgr_platform_shutdown(); + + grpc_iomgr_platform_init(); test_poll_cv_trigger(); + grpc_iomgr_platform_shutdown(); + // Make sure detached polling threads have chance // to exit and clean up memory. pthread_exit() causes tsan/msan // issues, so we just wait an ample amount of time diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 6e08a1977c..2ea042a4f4 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -894,6 +894,7 @@ src/core/lib/iomgr/endpoint_pair.h \ src/core/lib/iomgr/error.h \ src/core/lib/iomgr/ev_epoll_linux.h \ src/core/lib/iomgr/ev_poll_and_epoll_posix.h \ +src/core/lib/iomgr/ev_poll_cv_posix.h \ src/core/lib/iomgr/ev_poll_posix.h \ src/core/lib/iomgr/ev_posix.h \ src/core/lib/iomgr/exec_ctx.h \ @@ -1008,6 +1009,7 @@ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ +src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 2328194c3a..a59ff043b1 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -811,6 +811,7 @@ src/core/lib/iomgr/endpoint_pair.h \ src/core/lib/iomgr/error.h \ src/core/lib/iomgr/ev_epoll_linux.h \ src/core/lib/iomgr/ev_poll_and_epoll_posix.h \ +src/core/lib/iomgr/ev_poll_cv_posix.h \ src/core/lib/iomgr/ev_poll_posix.h \ src/core/lib/iomgr/ev_posix.h \ src/core/lib/iomgr/exec_ctx.h \ @@ -972,6 +973,7 @@ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ +src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 146018ba3a..7d8a18d8fe 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -69,7 +69,7 @@ _FORCE_ENVIRON_FOR_WRAPPERS = { _POLLING_STRATEGIES = { - 'linux': ['epoll', 'poll', 'legacy'] + 'linux': ['epoll', 'poll', 'poll-cv', 'legacy'] } diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 2ce0e3b05c..f6abb4641f 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -5926,6 +5926,7 @@ "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -6039,6 +6040,8 @@ "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.c", diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index 2afda35d34..eb830eb45d 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -394,6 +394,7 @@ + @@ -564,6 +565,8 @@ + + diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index 1f88ae0e93..acee5ed3c9 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -163,6 +163,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -779,6 +782,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index be20aef6dc..fbdc6c3bdf 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -390,6 +390,7 @@ + @@ -550,6 +551,8 @@ + + diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index 628173dbbe..600e6475a4 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -148,6 +148,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -752,6 +755,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index ae24e8f066..3ae2ade070 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -320,6 +320,7 @@ + @@ -505,6 +506,8 @@ + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index a849795dc9..2a401e1695 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -67,6 +67,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -731,6 +734,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index 3c3fae370f..e54b369ec6 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -211,6 +211,7 @@ + @@ -349,6 +350,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index b81431cafa..f391f29729 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -115,6 +115,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -512,6 +515,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 69d631e452..3eaae7fe18 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -310,6 +310,7 @@ + @@ -473,6 +474,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 36e80b4a13..31ba6e97bf 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -70,6 +70,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -641,6 +644,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr -- cgit v1.2.3 From 84a4bdd5d8c0d20d6cdc93ce09167adc24431ada Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Thu, 29 Sep 2016 09:24:09 -0700 Subject: Fix Typo --- src/core/lib/iomgr/ev_poll_cv_posix.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.c b/src/core/lib/iomgr/ev_poll_cv_posix.c index 596a3025eb..cb2c2ba824 100644 --- a/src/core/lib/iomgr/ev_poll_cv_posix.c +++ b/src/core/lib/iomgr/ev_poll_cv_posix.c @@ -266,10 +266,9 @@ const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void) { ev_poll_vtable = grpc_init_poll_posix(); if (!ev_poll_vtable) { grpc_global_cv_fd_table_shutdown(); - grpc_has_wakeup_fd = has_standard_wakeup_fd; + grpc_has_wakeup_fd = has_wakeup_fd; grpc_allow_specialized_wakeup_fd = allow_specialized_wakeup_fd; grpc_allow_pipe_wakeup_fd = allow_pipe_wakeup_fd; - grpc_has_wakeup_fd = has_standard_wakeup_fd; grpc_global_cv_fd_table_init(); return NULL; } -- cgit v1.2.3 From 65818729dc871e991c452738c221bf3f0f28812b Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Thu, 29 Sep 2016 11:28:23 -0700 Subject: Clang format --- src/core/lib/iomgr/ev_poll_cv_posix.h | 2 +- src/core/lib/iomgr/wakeup_fd_posix.c | 5 +---- tools/run_tests/run_tests.py | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.h b/src/core/lib/iomgr/ev_poll_cv_posix.h index 0fd3e5bbb4..89e4929fbb 100644 --- a/src/core/lib/iomgr/ev_poll_cv_posix.h +++ b/src/core/lib/iomgr/ev_poll_cv_posix.h @@ -62,4 +62,4 @@ typedef struct cv_fd_table { const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void); -#endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H */ +#endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_CV_POSIX_H */ diff --git a/src/core/lib/iomgr/wakeup_fd_posix.c b/src/core/lib/iomgr/wakeup_fd_posix.c index 48ed92abe8..d8eafc4192 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.c +++ b/src/core/lib/iomgr/wakeup_fd_posix.c @@ -45,7 +45,6 @@ int grpc_allow_specialized_wakeup_fd = 1; int grpc_allow_pipe_wakeup_fd = 1; int grpc_has_wakeup_fd = 1; - void grpc_wakeup_fd_global_init(void) { if (grpc_allow_specialized_wakeup_fd && grpc_specialized_wakeup_fd_vtable.check_availability()) { @@ -59,9 +58,7 @@ void grpc_wakeup_fd_global_init(void) { } } -void grpc_wakeup_fd_global_destroy(void) { - wakeup_fd_vtable = NULL; -} +void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; } grpc_error *grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) { return wakeup_fd_vtable->init(fd_info); diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 7d8a18d8fe..0777274694 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -1027,7 +1027,7 @@ argp.add_argument('--force_default_poller', default=False, action='store_const', args = argp.parse_args() if args.force_default_poller: - _POLLING_STRATEGIES = {} + _POLLING_STRATEGIES = {'linux': ['poll-cv']} jobset.measure_cpu_costs = args.measure_cpu_costs -- cgit v1.2.3 From 8725870c5822a8d2f96e275e46475594567d5ccd Mon Sep 17 00:00:00 2001 From: Dan Born Date: Mon, 3 Oct 2016 12:46:16 -0700 Subject: Fix Windows server --- src/core/lib/iomgr/tcp_server_windows.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c index 35faded993..4ff05601fa 100644 --- a/src/core/lib/iomgr/tcp_server_windows.c +++ b/src/core/lib/iomgr/tcp_server_windows.c @@ -121,9 +121,6 @@ grpc_error *grpc_tcp_server_create(grpc_closure *shutdown_complete, } static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - gpr_mu_lock(&s->mu); - GPR_ASSERT(s->shutdown); - gpr_mu_unlock(&s->mu); if (s->shutdown_complete != NULL) { grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL); } -- cgit v1.2.3 From 274c8ed001aca0dc563ee7e04ecd2f9a486b77ec Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 4 Oct 2016 09:21:42 -0700 Subject: Fix handling of max receive message size on client side. --- src/core/lib/channel/message_size_filter.c | 14 ++- src/core/lib/surface/call.c | 15 ++- test/core/end2end/tests/max_message_length.c | 165 ++++++++++++++++++++++++++- 3 files changed, 179 insertions(+), 15 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c index 02fc68fc3a..f067a3a51c 100644 --- a/src/core/lib/channel/message_size_filter.c +++ b/src/core/lib/channel/message_size_filter.c @@ -73,16 +73,22 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data, gpr_asprintf(&message_string, "Received message larger than max (%u vs. %d)", (*calld->recv_message)->length, chand->max_recv_size); - gpr_slice message = gpr_slice_from_copied_string(message_string); + grpc_error* new_error = grpc_error_set_int( + GRPC_ERROR_CREATE(message_string), GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_INVALID_ARGUMENT); + if (error == GRPC_ERROR_NONE) { + error = new_error; + } else { + error = grpc_error_add_child(error, new_error); + GRPC_ERROR_UNREF(new_error); + } gpr_free(message_string); - grpc_call_element_send_close_with_message( - exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message); } // Invoke the next callback. grpc_exec_ctx_sched(exec_ctx, calld->next_recv_message_ready, error, NULL); } -// Start transport op. +// Start transport stream op. static void start_transport_stream_op(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, grpc_transport_stream_op* op) { diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 5690bcab1e..b0f66f4f61 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -1103,8 +1103,8 @@ static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp, } } -static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl, - bool success) { +static void process_data_after_md(grpc_exec_ctx *exec_ctx, + batch_control *bctl) { grpc_call *call = bctl->call; if (call->receiving_stream == NULL) { *call->receiving_buffer = NULL; @@ -1124,8 +1124,6 @@ static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl, grpc_closure_init(&call->receiving_slice_ready, receiving_slice_ready, bctl); continue_receiving_slices(exec_ctx, bctl); - /* early out */ - return; } } @@ -1133,12 +1131,17 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp, grpc_error *error) { batch_control *bctl = bctlp; grpc_call *call = bctl->call; - + if (error != GRPC_ERROR_NONE) { + grpc_status_code status; + const char *msg; + grpc_error_get_status(error, &status, &msg); + close_with_status(exec_ctx, call, status, msg); + } gpr_mu_lock(&bctl->call->mu); if (bctl->call->has_initial_md_been_received || error != GRPC_ERROR_NONE || call->receiving_stream == NULL) { gpr_mu_unlock(&bctl->call->mu); - process_data_after_md(exec_ctx, bctlp, error); + process_data_after_md(exec_ctx, bctlp); } else { call->saved_receiving_stream_ready_bctlp = bctlp; gpr_mu_unlock(&bctl->call->mu); diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c index cdca3e6748..d27ccedb4e 100644 --- a/test/core/end2end/tests/max_message_length.c +++ b/test/core/end2end/tests/max_message_length.c @@ -98,9 +98,12 @@ static void end_test(grpc_end2end_test_fixture *f) { grpc_completion_queue_destroy(f->cq); } -static void test_max_message_length(grpc_end2end_test_config config, - bool send_limit) { - gpr_log(GPR_INFO, "testing with send_limit=%d", send_limit); +// Test with request larger than the limit. +// If send_limit is true, applies send limit on client; otherwise, applies +// recv limit on server. +static void test_max_message_length_on_request(grpc_end2end_test_config config, + bool send_limit) { + gpr_log(GPR_INFO, "testing request with send_limit=%d", send_limit); grpc_end2end_test_fixture f; grpc_arg channel_arg; @@ -239,9 +242,161 @@ done: config.tear_down_data(&f); } +// Test with response larger than the limit. +// If send_limit is true, applies send limit on server; otherwise, applies +// recv limit on client. +static void test_max_message_length_on_response(grpc_end2end_test_config config, + bool send_limit) { + gpr_log(GPR_INFO, "testing response with send_limit=%d", send_limit); + + grpc_end2end_test_fixture f; + grpc_arg channel_arg; + grpc_channel_args channel_args; + grpc_call *c = NULL; + grpc_call *s = NULL; + cq_verifier *cqv; + grpc_op ops[6]; + grpc_op *op; + gpr_slice response_payload_slice = + gpr_slice_from_copied_string("hello world"); + grpc_byte_buffer *response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + grpc_byte_buffer *recv_payload = NULL; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + char *details = NULL; + size_t details_capacity = 0; + int was_cancelled = 2; + + channel_arg.key = send_limit ? GRPC_ARG_MAX_SEND_MESSAGE_LENGTH + : GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH; + channel_arg.type = GRPC_ARG_INTEGER; + channel_arg.value.integer = 5; + + channel_args.num_args = 1; + channel_args.args = &channel_arg; + + f = begin_test(config, "test_max_message_length", + send_limit ? NULL : &channel_args, + send_limit ? &channel_args : NULL); + cqv = cq_verifier_create(f.cq); + + c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + "/foo", "foo.test.google.fr:1234", + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &recv_payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->data.recv_status_on_client.status_details_capacity = &details_capacity; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message = response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + op->data.send_status_from_server.status_details = "xyz"; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); + GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234")); + GPR_ASSERT(was_cancelled == 0); + + GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT); + GPR_ASSERT(strcmp(details, + send_limit + ? "Sent message larger than max (11 vs. 5)" + : "Received message larger than max (11 vs. 5)") == 0); + + gpr_free(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(recv_payload); + + grpc_call_destroy(c); + if (s != NULL) grpc_call_destroy(s); + + cq_verifier_destroy(cqv); + + end_test(&f); + config.tear_down_data(&f); +} + void max_message_length(grpc_end2end_test_config config) { - test_max_message_length(config, true); - test_max_message_length(config, false); + test_max_message_length_on_request(config, false /* send_limit */); + test_max_message_length_on_request(config, true /* send_limit */); + test_max_message_length_on_response(config, false /* send_limit */); + test_max_message_length_on_response(config, true /* send_limit */); } void max_message_length_pre_init(void) {} -- cgit v1.2.3 From 53ab32be86d0747af636070674f5830123c5a45c Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Tue, 4 Oct 2016 13:09:36 -0700 Subject: added missing line to UDP server --- src/core/lib/iomgr/udp_server.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c index 12e929fa6a..6650ef022d 100644 --- a/src/core/lib/iomgr/udp_server.c +++ b/src/core/lib/iomgr/udp_server.c @@ -199,6 +199,7 @@ void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s, /* shutdown all fd's */ if (s->active_ports) { for (i = 0; i < s->nports; i++) { + server_port *sp = &s->ports[i]; /* Call the orphan_cb to signal that the FD is about to be closed and * should no longer be used. */ GPR_ASSERT(sp->orphan_cb); -- cgit v1.2.3 From a3570f22d06ce2aa3bc6bf20784b79243db935e8 Mon Sep 17 00:00:00 2001 From: Lizan Zhou Date: Mon, 5 Sep 2016 13:29:17 +0900 Subject: Fix grpc_byte_buffer_copy to copy compression algorithm --- src/core/lib/surface/byte_buffer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/surface/byte_buffer.c b/src/core/lib/surface/byte_buffer.c index a093a37af3..054a6e6c58 100644 --- a/src/core/lib/surface/byte_buffer.c +++ b/src/core/lib/surface/byte_buffer.c @@ -72,8 +72,9 @@ grpc_byte_buffer *grpc_raw_byte_buffer_from_reader( grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb) { switch (bb->type) { case GRPC_BB_RAW: - return grpc_raw_byte_buffer_create(bb->data.raw.slice_buffer.slices, - bb->data.raw.slice_buffer.count); + return grpc_raw_compressed_byte_buffer_create( + bb->data.raw.slice_buffer.slices, bb->data.raw.slice_buffer.count, + bb->data.raw.compression); } GPR_UNREACHABLE_CODE(return NULL); } -- cgit v1.2.3 From 757e84ef1cfd50661cb8242debd7a7990448dde1 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 6 Oct 2016 13:07:53 -0700 Subject: Add 'extern "C"' to error.h. --- src/core/lib/iomgr/error.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h index 7e2fd7a3bd..00ace8a7a9 100644 --- a/src/core/lib/iomgr/error.h +++ b/src/core/lib/iomgr/error.h @@ -40,6 +40,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /// Opaque representation of an error. /// Errors are refcounted objects that represent the result of an operation. /// Ownership laws: @@ -204,4 +208,8 @@ bool grpc_log_if_error(const char *what, grpc_error *error, const char *file, #define GRPC_LOG_IF_ERROR(what, error) \ grpc_log_if_error((what), (error), __FILE__, __LINE__) +#ifdef __cplusplus +} +#endif + #endif /* GRPC_CORE_LIB_IOMGR_ERROR_H */ -- cgit v1.2.3 From bc544be002b864e808cbca54ea64fa9b68262302 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Thu, 6 Oct 2016 19:23:47 -0700 Subject: Fix platform detection --- src/core/lib/iomgr/ev_epoll_linux.c | 4 ++++ src/core/lib/iomgr/ev_poll_posix.c | 3 +++ src/core/lib/iomgr/ev_posix.c | 1 + src/core/lib/iomgr/wakeup_fd_pipe.c | 3 +-- 4 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c index ab77ebc78b..249bc98735 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epoll_linux.c @@ -1892,6 +1892,10 @@ const grpc_event_engine_vtable *grpc_init_epoll_linux(void) { return NULL; } + if (!grpc_has_wakeup_fd) { + return NULL; + } + if (!is_epoll_available()) { return NULL; } diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c index 16a5e3083e..97e71d968e 100644 --- a/src/core/lib/iomgr/ev_poll_posix.c +++ b/src/core/lib/iomgr/ev_poll_posix.c @@ -1277,6 +1277,9 @@ static const grpc_event_engine_vtable vtable = { }; const grpc_event_engine_vtable *grpc_init_poll_posix(void) { + if (!grpc_has_wakeup_fd) { + return NULL; + } if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { return NULL; } diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c index 2fc8ccfa91..a4102b429f 100644 --- a/src/core/lib/iomgr/ev_posix.c +++ b/src/core/lib/iomgr/ev_posix.c @@ -65,6 +65,7 @@ typedef struct { } event_engine_factory; static const event_engine_factory g_factories[] = { + {"poll-cv", grpc_init_poll_cv_posix}, {"epoll", grpc_init_epoll_linux}, {"poll", grpc_init_poll_posix}, {"poll-cv", grpc_init_poll_cv_posix}, diff --git a/src/core/lib/iomgr/wakeup_fd_pipe.c b/src/core/lib/iomgr/wakeup_fd_pipe.c index 3dc94c94ba..d0ea216aa0 100644 --- a/src/core/lib/iomgr/wakeup_fd_pipe.c +++ b/src/core/lib/iomgr/wakeup_fd_pipe.c @@ -47,11 +47,10 @@ static grpc_error* pipe_init(grpc_wakeup_fd* fd_info) { int pipefd[2]; - /* TODO(klempner): Make this nonfatal */ int r = pipe(pipefd); if (0 != r) { gpr_log(GPR_ERROR, "pipe creation failed (%d): %s", errno, strerror(errno)); - abort(); + return GRPC_OS_ERROR(errno, "pipe"); } grpc_error* err; err = grpc_set_socket_nonblocking(pipefd[0], 1); -- cgit v1.2.3 From d526e82a8340c5ad169a6bbb770cee23e1c0a441 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Fri, 7 Oct 2016 10:17:01 -0700 Subject: fix small bug --- src/core/lib/iomgr/ev_poll_cv_posix.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.c b/src/core/lib/iomgr/ev_poll_cv_posix.c index cb2c2ba824..1ea811e445 100644 --- a/src/core/lib/iomgr/ev_poll_cv_posix.c +++ b/src/core/lib/iomgr/ev_poll_cv_posix.c @@ -259,10 +259,10 @@ const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void) { int allow_specialized_wakeup_fd = grpc_allow_specialized_wakeup_fd; int allow_pipe_wakeup_fd = grpc_allow_pipe_wakeup_fd; grpc_global_cv_fd_table_init(); - grpc_has_wakeup_fd = 1; grpc_allow_specialized_wakeup_fd = 0; grpc_allow_pipe_wakeup_fd = 0; grpc_wakeup_fd_global_init(); + grpc_has_wakeup_fd = 1; ev_poll_vtable = grpc_init_poll_posix(); if (!ev_poll_vtable) { grpc_global_cv_fd_table_shutdown(); @@ -272,7 +272,6 @@ const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void) { grpc_global_cv_fd_table_init(); return NULL; } - vtable = *ev_poll_vtable; vtable.shutdown_engine = shutdown_engine; return &vtable; -- cgit v1.2.3 From 131a1065fb23d9fd4be60361dffb9f8a0042f0cc Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Fri, 7 Oct 2016 14:03:30 -0700 Subject: Remove test-forcing hack --- src/core/lib/iomgr/ev_posix.c | 1 - src/core/lib/iomgr/wakeup_fd_posix.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c index a4102b429f..2fc8ccfa91 100644 --- a/src/core/lib/iomgr/ev_posix.c +++ b/src/core/lib/iomgr/ev_posix.c @@ -65,7 +65,6 @@ typedef struct { } event_engine_factory; static const event_engine_factory g_factories[] = { - {"poll-cv", grpc_init_poll_cv_posix}, {"epoll", grpc_init_epoll_linux}, {"poll", grpc_init_poll_posix}, {"poll-cv", grpc_init_poll_cv_posix}, diff --git a/src/core/lib/iomgr/wakeup_fd_posix.c b/src/core/lib/iomgr/wakeup_fd_posix.c index d8eafc4192..041c221de3 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.c +++ b/src/core/lib/iomgr/wakeup_fd_posix.c @@ -33,7 +33,7 @@ #include -#ifdef GPR_POSIX_SOCKET +#ifdef GPR_POSIX_WAKEUP_FD #include #include "src/core/lib/iomgr/wakeup_fd_cv.h" -- cgit v1.2.3 From d195cf589d3f03b4f08017f3e2885c2c2fff125b Mon Sep 17 00:00:00 2001 From: kpayson64 Date: Sun, 9 Oct 2016 18:04:00 -0700 Subject: Add condition variable polling engine --- BUILD | 16 ++ CMakeLists.txt | 6 + Makefile | 44 +++ binding.gyp | 2 + build.yaml | 18 ++ config.m4 | 2 + gRPC-Core.podspec | 6 + grpc.gemspec | 4 + package.xml | 4 + src/core/lib/iomgr/ev_epoll_linux.c | 4 + src/core/lib/iomgr/ev_poll_cv_posix.c | 297 +++++++++++++++++++++ src/core/lib/iomgr/ev_poll_cv_posix.h | 68 +++++ src/core/lib/iomgr/ev_poll_posix.c | 3 + src/core/lib/iomgr/ev_posix.c | 2 + src/core/lib/iomgr/wakeup_fd_cv.c | 118 ++++++++ src/core/lib/iomgr/wakeup_fd_cv.h | 55 ++++ src/core/lib/iomgr/wakeup_fd_pipe.c | 12 +- src/core/lib/iomgr/wakeup_fd_posix.c | 9 +- src/core/lib/iomgr/wakeup_fd_posix.h | 2 + src/python/grpcio/grpc_core_dependencies.py | 2 + test/core/iomgr/wakeup_fd_cv_test.c | 240 +++++++++++++++++ tools/doxygen/Doxyfile.core.internal | 4 + tools/run_tests/run_tests.py | 2 +- tools/run_tests/sources_and_headers.json | 23 ++ tools/run_tests/tests.json | 19 ++ vsprojects/vcxproj/grpc/grpc.vcxproj | 6 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 12 + .../vcxproj/grpc_test_util/grpc_test_util.vcxproj | 6 + .../grpc_test_util/grpc_test_util.vcxproj.filters | 12 + .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 6 + .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 12 + 31 files changed, 1010 insertions(+), 6 deletions(-) create mode 100644 src/core/lib/iomgr/ev_poll_cv_posix.c create mode 100644 src/core/lib/iomgr/ev_poll_cv_posix.h create mode 100644 src/core/lib/iomgr/wakeup_fd_cv.c create mode 100644 src/core/lib/iomgr/wakeup_fd_cv.h create mode 100644 test/core/iomgr/wakeup_fd_cv_test.c (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index bad6f3f075..ba44367dbb 100644 --- a/BUILD +++ b/BUILD @@ -186,6 +186,7 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -217,6 +218,7 @@ cc_library( "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", @@ -347,6 +349,7 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -379,6 +382,7 @@ cc_library( "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", @@ -587,6 +591,7 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -618,6 +623,7 @@ cc_library( "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", @@ -733,6 +739,7 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -765,6 +772,7 @@ cc_library( "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", @@ -943,6 +951,7 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -974,6 +983,7 @@ cc_library( "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", @@ -1081,6 +1091,7 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -1113,6 +1124,7 @@ cc_library( "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", @@ -1844,6 +1856,7 @@ objc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -1876,6 +1889,7 @@ objc_library( "src/core/lib/iomgr/udp_server.c", "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", @@ -2063,6 +2077,7 @@ objc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -2094,6 +2109,7 @@ objc_library( "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index c4191521bd..747d1fab4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -314,6 +314,7 @@ add_library(grpc src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c + src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -346,6 +347,7 @@ add_library(grpc src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c + src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c @@ -573,6 +575,7 @@ add_library(grpc_cronet src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c + src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -605,6 +608,7 @@ add_library(grpc_cronet src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c + src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c @@ -804,6 +808,7 @@ add_library(grpc_unsecure src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c + src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -836,6 +841,7 @@ add_library(grpc_unsecure src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c src/core/lib/iomgr/unix_sockets_posix_noop.c + src/core/lib/iomgr/wakeup_fd_cv.c src/core/lib/iomgr/wakeup_fd_eventfd.c src/core/lib/iomgr/wakeup_fd_nospecial.c src/core/lib/iomgr/wakeup_fd_pipe.c diff --git a/Makefile b/Makefile index 62c65822b0..1f4c9b5c32 100644 --- a/Makefile +++ b/Makefile @@ -1025,6 +1025,7 @@ transport_security_test: $(BINDIR)/$(CONFIG)/transport_security_test udp_server_test: $(BINDIR)/$(CONFIG)/udp_server_test uri_fuzzer_test: $(BINDIR)/$(CONFIG)/uri_fuzzer_test uri_parser_test: $(BINDIR)/$(CONFIG)/uri_parser_test +wakeup_fd_cv_test: $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test @@ -1340,6 +1341,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/transport_security_test \ $(BINDIR)/$(CONFIG)/udp_server_test \ $(BINDIR)/$(CONFIG)/uri_parser_test \ + $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test \ $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 \ $(BINDIR)/$(CONFIG)/badreq_bad_client_test \ $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \ @@ -1738,6 +1740,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/udp_server_test || ( echo test udp_server_test failed ; exit 1 ) $(E) "[RUN] Testing uri_parser_test" $(Q) $(BINDIR)/$(CONFIG)/uri_parser_test || ( echo test uri_parser_test failed ; exit 1 ) + $(E) "[RUN] Testing wakeup_fd_cv_test" + $(Q) $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test || ( echo test wakeup_fd_cv_test failed ; exit 1 ) $(E) "[RUN] Testing public_headers_must_be_c89" $(Q) $(BINDIR)/$(CONFIG)/public_headers_must_be_c89 || ( echo test public_headers_must_be_c89 failed ; exit 1 ) $(E) "[RUN] Testing badreq_bad_client_test" @@ -2558,6 +2562,7 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -2590,6 +2595,7 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ @@ -2835,6 +2841,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -2867,6 +2874,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ @@ -3102,6 +3110,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -3134,6 +3143,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ @@ -3296,6 +3306,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -3328,6 +3339,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ @@ -10757,6 +10769,38 @@ endif endif +WAKEUP_FD_CV_TEST_SRC = \ + test/core/iomgr/wakeup_fd_cv_test.c \ + +WAKEUP_FD_CV_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(WAKEUP_FD_CV_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/wakeup_fd_cv_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/wakeup_fd_cv_test: $(WAKEUP_FD_CV_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) $(WAKEUP_FD_CV_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)/wakeup_fd_cv_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/wakeup_fd_cv_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_wakeup_fd_cv_test: $(WAKEUP_FD_CV_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(WAKEUP_FD_CV_TEST_OBJS:.o=.dep) +endif +endif + + ALARM_CPP_TEST_SRC = \ test/cpp/common/alarm_cpp_test.cc \ diff --git a/binding.gyp b/binding.gyp index 58edda2e63..85070e5cac 100644 --- a/binding.gyp +++ b/binding.gyp @@ -589,6 +589,7 @@ 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', + 'src/core/lib/iomgr/ev_poll_cv_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', @@ -621,6 +622,7 @@ 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', 'src/core/lib/iomgr/unix_sockets_posix_noop.c', + 'src/core/lib/iomgr/wakeup_fd_cv.c', 'src/core/lib/iomgr/wakeup_fd_eventfd.c', 'src/core/lib/iomgr/wakeup_fd_nospecial.c', 'src/core/lib/iomgr/wakeup_fd_pipe.c', diff --git a/build.yaml b/build.yaml index 584084ff86..3e64ce8f37 100644 --- a/build.yaml +++ b/build.yaml @@ -190,6 +190,7 @@ filegroups: - src/core/lib/iomgr/error.h - src/core/lib/iomgr/ev_epoll_linux.h - src/core/lib/iomgr/ev_poll_and_epoll_posix.h + - src/core/lib/iomgr/ev_poll_cv_posix.h - src/core/lib/iomgr/ev_poll_posix.h - src/core/lib/iomgr/ev_posix.h - src/core/lib/iomgr/exec_ctx.h @@ -221,6 +222,7 @@ filegroups: - src/core/lib/iomgr/timer_heap.h - src/core/lib/iomgr/udp_server.h - src/core/lib/iomgr/unix_sockets_posix.h + - src/core/lib/iomgr/wakeup_fd_cv.h - src/core/lib/iomgr/wakeup_fd_pipe.h - src/core/lib/iomgr/wakeup_fd_posix.h - src/core/lib/iomgr/workqueue.h @@ -274,6 +276,7 @@ filegroups: - src/core/lib/iomgr/error.c - src/core/lib/iomgr/ev_epoll_linux.c - src/core/lib/iomgr/ev_poll_and_epoll_posix.c + - src/core/lib/iomgr/ev_poll_cv_posix.c - src/core/lib/iomgr/ev_poll_posix.c - src/core/lib/iomgr/ev_posix.c - src/core/lib/iomgr/exec_ctx.c @@ -306,6 +309,7 @@ filegroups: - src/core/lib/iomgr/udp_server.c - src/core/lib/iomgr/unix_sockets_posix.c - src/core/lib/iomgr/unix_sockets_posix_noop.c + - src/core/lib/iomgr/wakeup_fd_cv.c - src/core/lib/iomgr/wakeup_fd_eventfd.c - src/core/lib/iomgr/wakeup_fd_nospecial.c - src/core/lib/iomgr/wakeup_fd_pipe.c @@ -2592,6 +2596,20 @@ targets: - grpc - gpr_test_util - gpr +- name: wakeup_fd_cv_test + build: test + language: c + src: + - test/core/iomgr/wakeup_fd_cv_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + platforms: + - mac + - linux + - posix - name: alarm_cpp_test gtest: true build: test diff --git a/config.m4 b/config.m4 index 0f103655a8..1452798897 100644 --- a/config.m4 +++ b/config.m4 @@ -108,6 +108,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ + src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -140,6 +141,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ + src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 6886bdfb5a..3ac0b841cf 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -273,6 +273,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/ev_epoll_linux.h', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.h', + 'src/core/lib/iomgr/ev_poll_cv_posix.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', @@ -304,6 +305,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/timer_heap.h', 'src/core/lib/iomgr/udp_server.h', 'src/core/lib/iomgr/unix_sockets_posix.h', + 'src/core/lib/iomgr/wakeup_fd_cv.h', 'src/core/lib/iomgr/wakeup_fd_pipe.h', 'src/core/lib/iomgr/wakeup_fd_posix.h', 'src/core/lib/iomgr/workqueue.h', @@ -438,6 +440,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', + 'src/core/lib/iomgr/ev_poll_cv_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', @@ -470,6 +473,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', 'src/core/lib/iomgr/unix_sockets_posix_noop.c', + 'src/core/lib/iomgr/wakeup_fd_cv.c', 'src/core/lib/iomgr/wakeup_fd_eventfd.c', 'src/core/lib/iomgr/wakeup_fd_nospecial.c', 'src/core/lib/iomgr/wakeup_fd_pipe.c', @@ -646,6 +650,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/ev_epoll_linux.h', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.h', + 'src/core/lib/iomgr/ev_poll_cv_posix.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', @@ -677,6 +682,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/timer_heap.h', 'src/core/lib/iomgr/udp_server.h', 'src/core/lib/iomgr/unix_sockets_posix.h', + 'src/core/lib/iomgr/wakeup_fd_cv.h', 'src/core/lib/iomgr/wakeup_fd_pipe.h', 'src/core/lib/iomgr/wakeup_fd_posix.h', 'src/core/lib/iomgr/workqueue.h', diff --git a/grpc.gemspec b/grpc.gemspec index 6079ea2aef..85135a5327 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -193,6 +193,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/error.h ) s.files += %w( src/core/lib/iomgr/ev_epoll_linux.h ) s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.h ) + s.files += %w( src/core/lib/iomgr/ev_poll_cv_posix.h ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.h ) s.files += %w( src/core/lib/iomgr/ev_posix.h ) s.files += %w( src/core/lib/iomgr/exec_ctx.h ) @@ -224,6 +225,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/timer_heap.h ) s.files += %w( src/core/lib/iomgr/udp_server.h ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix.h ) + s.files += %w( src/core/lib/iomgr/wakeup_fd_cv.h ) s.files += %w( src/core/lib/iomgr/wakeup_fd_pipe.h ) s.files += %w( src/core/lib/iomgr/wakeup_fd_posix.h ) s.files += %w( src/core/lib/iomgr/workqueue.h ) @@ -358,6 +360,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/error.c ) s.files += %w( src/core/lib/iomgr/ev_epoll_linux.c ) s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.c ) + s.files += %w( src/core/lib/iomgr/ev_poll_cv_posix.c ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.c ) s.files += %w( src/core/lib/iomgr/ev_posix.c ) s.files += %w( src/core/lib/iomgr/exec_ctx.c ) @@ -390,6 +393,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/udp_server.c ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix.c ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix_noop.c ) + s.files += %w( src/core/lib/iomgr/wakeup_fd_cv.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_eventfd.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_nospecial.c ) s.files += %w( src/core/lib/iomgr/wakeup_fd_pipe.c ) diff --git a/package.xml b/package.xml index 7bac695787..4631fc1c39 100644 --- a/package.xml +++ b/package.xml @@ -200,6 +200,7 @@ + @@ -231,6 +232,7 @@ + @@ -365,6 +367,7 @@ + @@ -397,6 +400,7 @@ + diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c index ab77ebc78b..249bc98735 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epoll_linux.c @@ -1892,6 +1892,10 @@ const grpc_event_engine_vtable *grpc_init_epoll_linux(void) { return NULL; } + if (!grpc_has_wakeup_fd) { + return NULL; + } + if (!is_epoll_available()) { return NULL; } diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.c b/src/core/lib/iomgr/ev_poll_cv_posix.c new file mode 100644 index 0000000000..dd1bbedcc1 --- /dev/null +++ b/src/core/lib/iomgr/ev_poll_cv_posix.c @@ -0,0 +1,297 @@ +/* + * + * 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 + +#ifdef GPR_POSIX_SOCKET + +#include "src/core/lib/iomgr/ev_poll_cv_posix.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/ev_poll_posix.h" +#include "src/core/lib/iomgr/wakeup_fd_posix.h" + +#define POLL_PERIOD_MS 1000 +#define DEFAULT_TABLE_SIZE 16 + +typedef enum status_t { INPROGRESS, COMPLETED, CANCELLED } status_t; + +typedef struct poll_args { + gpr_refcount refcount; + gpr_cv* cv; + struct pollfd* fds; + nfds_t nfds; + int timeout; + int retval; + int err; + status_t status; +} poll_args; + +cv_fd_table g_cvfds; + +static void decref_poll_args(poll_args* args) { + if (gpr_unref(&args->refcount)) { + gpr_free(args->fds); + gpr_cv_destroy(args->cv); + gpr_free(args->cv); + gpr_free(args); + } +} + +// Poll in a background thread +static void run_poll(void* arg) { + int timeout, retval; + poll_args* pargs = (poll_args*)arg; + while (pargs->status == INPROGRESS) { + if (pargs->timeout < 0) { + timeout = POLL_PERIOD_MS; + } else { + timeout = GPR_MIN(POLL_PERIOD_MS, pargs->timeout); + pargs->timeout -= timeout; + } + retval = g_cvfds.poll(pargs->fds, pargs->nfds, timeout); + if (retval != 0 || pargs->timeout == 0) { + pargs->retval = retval; + pargs->err = errno; + break; + } + } + gpr_mu_lock(&g_cvfds.mu); + if (pargs->status == INPROGRESS) { + // Signal main thread that the poll completed + pargs->status = COMPLETED; + gpr_cv_signal(pargs->cv); + } + decref_poll_args(pargs); + g_cvfds.pollcount--; + if (g_cvfds.shutdown && g_cvfds.pollcount == 0) { + gpr_cv_signal(&g_cvfds.shutdown_complete); + } + gpr_mu_unlock(&g_cvfds.mu); +} + +// This function overrides poll() to handle condition variable wakeup fds +static int cvfd_poll(struct pollfd* fds, nfds_t nfds, int timeout) { + unsigned int i; + int res, idx; + gpr_cv* pollcv; + cv_node *cvn, *prev; + nfds_t nsockfds = 0; + gpr_thd_id t_id; + gpr_thd_options opt; + poll_args* pargs = NULL; + gpr_mu_lock(&g_cvfds.mu); + pollcv = gpr_malloc(sizeof(gpr_cv)); + gpr_cv_init(pollcv); + for (i = 0; i < nfds; i++) { + fds[i].revents = 0; + if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { + idx = FD_TO_IDX(fds[i].fd); + cvn = gpr_malloc(sizeof(cv_node)); + cvn->cv = pollcv; + cvn->next = g_cvfds.cvfds[idx].cvs; + g_cvfds.cvfds[idx].cvs = cvn; + // We should return immediately if there are pending events, + // but we still need to call poll() to check for socket events + if (g_cvfds.cvfds[idx].is_set) { + timeout = 0; + } + } else if (fds[i].fd >= 0) { + nsockfds++; + } + } + + if (nsockfds > 0) { + pargs = gpr_malloc(sizeof(struct poll_args)); + // Both the main thread and calling thread get a reference + gpr_ref_init(&pargs->refcount, 2); + pargs->cv = pollcv; + pargs->fds = gpr_malloc(sizeof(struct pollfd) * nsockfds); + pargs->nfds = nsockfds; + pargs->timeout = timeout; + pargs->retval = 0; + pargs->err = 0; + pargs->status = INPROGRESS; + idx = 0; + for (i = 0; i < nfds; i++) { + if (fds[i].fd >= 0) { + pargs->fds[idx].fd = fds[i].fd; + pargs->fds[idx].events = fds[i].events; + pargs->fds[idx].revents = 0; + idx++; + } + } + g_cvfds.pollcount++; + opt = gpr_thd_options_default(); + gpr_thd_options_set_detached(&opt); + gpr_thd_new(&t_id, &run_poll, pargs, &opt); + // We want the poll() thread to trigger the deadline, so wait forever here + gpr_cv_wait(pollcv, &g_cvfds.mu, gpr_inf_future(GPR_CLOCK_MONOTONIC)); + if (pargs->status == COMPLETED) { + res = pargs->retval; + errno = pargs->err; + } else { + res = 0; + errno = 0; + pargs->status = CANCELLED; + } + } else { + gpr_timespec deadline = gpr_now(GPR_CLOCK_REALTIME); + deadline = + gpr_time_add(deadline, gpr_time_from_millis(timeout, GPR_TIMESPAN)); + gpr_cv_wait(pollcv, &g_cvfds.mu, deadline); + res = 0; + } + + idx = 0; + for (i = 0; i < nfds; i++) { + if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { + cvn = g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs; + prev = NULL; + while (cvn->cv != pollcv) { + prev = cvn; + cvn = cvn->next; + GPR_ASSERT(cvn); + } + if (!prev) { + g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs = cvn->next; + } else { + prev->next = cvn->next; + } + gpr_free(cvn); + + if (g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].is_set) { + fds[i].revents = POLLIN; + if (res >= 0) res++; + } + } else if (fds[i].fd >= 0 && pargs->status == COMPLETED) { + fds[i].revents = pargs->fds[idx].revents; + idx++; + } + } + + if (pargs) { + decref_poll_args(pargs); + } else { + gpr_cv_destroy(pollcv); + gpr_free(pollcv); + } + gpr_mu_unlock(&g_cvfds.mu); + + return res; +} + +static void grpc_global_cv_fd_table_init() { + gpr_mu_init(&g_cvfds.mu); + gpr_mu_lock(&g_cvfds.mu); + gpr_cv_init(&g_cvfds.shutdown_complete); + g_cvfds.shutdown = 0; + g_cvfds.pollcount = 0; + g_cvfds.size = DEFAULT_TABLE_SIZE; + g_cvfds.cvfds = gpr_malloc(sizeof(fd_node) * DEFAULT_TABLE_SIZE); + g_cvfds.free_fds = NULL; + for (int i = 0; i < DEFAULT_TABLE_SIZE; i++) { + g_cvfds.cvfds[i].is_set = 0; + g_cvfds.cvfds[i].cvs = NULL; + g_cvfds.cvfds[i].next_free = g_cvfds.free_fds; + g_cvfds.free_fds = &g_cvfds.cvfds[i]; + } + // Override the poll function with one that supports cvfds + g_cvfds.poll = grpc_poll_function; + grpc_poll_function = &cvfd_poll; + gpr_mu_unlock(&g_cvfds.mu); +} + +static void grpc_global_cv_fd_table_shutdown() { + gpr_mu_lock(&g_cvfds.mu); + g_cvfds.shutdown = 1; + // Attempt to wait for all abandoned poll() threads to terminate + // Not doing so will result in reported memory leaks + if (g_cvfds.pollcount > 0) { + int res = gpr_cv_wait(&g_cvfds.shutdown_complete, &g_cvfds.mu, + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(3, GPR_TIMESPAN))); + GPR_ASSERT(res == 0); + } + gpr_cv_destroy(&g_cvfds.shutdown_complete); + grpc_poll_function = g_cvfds.poll; + gpr_free(g_cvfds.cvfds); + gpr_mu_unlock(&g_cvfds.mu); + gpr_mu_destroy(&g_cvfds.mu); +} + +/******************************************************************************* + * event engine binding + */ + +static const grpc_event_engine_vtable* ev_poll_vtable; +static grpc_event_engine_vtable vtable; + +static void shutdown_engine(void) { + ev_poll_vtable->shutdown_engine(); + grpc_global_cv_fd_table_shutdown(); +} + +const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void) { + int has_wakeup_fd = grpc_has_wakeup_fd; + int allow_specialized_wakeup_fd = grpc_allow_specialized_wakeup_fd; + int allow_pipe_wakeup_fd = grpc_allow_pipe_wakeup_fd; + grpc_global_cv_fd_table_init(); + grpc_allow_specialized_wakeup_fd = 0; + grpc_allow_pipe_wakeup_fd = 0; + grpc_wakeup_fd_global_init(); + grpc_has_wakeup_fd = 1; + ev_poll_vtable = grpc_init_poll_posix(); + if (!ev_poll_vtable) { + grpc_global_cv_fd_table_shutdown(); + grpc_has_wakeup_fd = has_wakeup_fd; + grpc_allow_specialized_wakeup_fd = allow_specialized_wakeup_fd; + grpc_allow_pipe_wakeup_fd = allow_pipe_wakeup_fd; + grpc_global_cv_fd_table_init(); + return NULL; + } + vtable = *ev_poll_vtable; + vtable.shutdown_engine = shutdown_engine; + return &vtable; +} + +#endif /* GPR_POSIX_SOCKET */ diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.h b/src/core/lib/iomgr/ev_poll_cv_posix.h new file mode 100644 index 0000000000..885711d1c5 --- /dev/null +++ b/src/core/lib/iomgr/ev_poll_cv_posix.h @@ -0,0 +1,68 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_EV_POLL_CV_POSIX_H +#define GRPC_CORE_LIB_IOMGR_EV_POLL_CV_POSIX_H + +#include + +#include "src/core/lib/iomgr/ev_posix.h" + +#define FD_TO_IDX(fd) (-(fd)-1) +#define IDX_TO_FD(idx) (-(idx)-1) + +typedef struct cv_node { + gpr_cv* cv; + struct cv_node* next; +} cv_node; + +typedef struct fd_node { + int is_set; + cv_node* cvs; + struct fd_node* next_free; +} fd_node; + +typedef struct cv_fd_table { + gpr_mu mu; + int pollcount; + int shutdown; + gpr_cv shutdown_complete; + fd_node* cvfds; + fd_node* free_fds; + unsigned int size; + grpc_poll_function_type poll; +} cv_fd_table; + +const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void); + +#endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_CV_POSIX_H */ diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c index 16a5e3083e..97e71d968e 100644 --- a/src/core/lib/iomgr/ev_poll_posix.c +++ b/src/core/lib/iomgr/ev_poll_posix.c @@ -1277,6 +1277,9 @@ static const grpc_event_engine_vtable vtable = { }; const grpc_event_engine_vtable *grpc_init_poll_posix(void) { + if (!grpc_has_wakeup_fd) { + return NULL; + } if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { return NULL; } diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c index 6536672685..2fc8ccfa91 100644 --- a/src/core/lib/iomgr/ev_posix.c +++ b/src/core/lib/iomgr/ev_posix.c @@ -46,6 +46,7 @@ #include "src/core/lib/iomgr/ev_epoll_linux.h" #include "src/core/lib/iomgr/ev_poll_and_epoll_posix.h" +#include "src/core/lib/iomgr/ev_poll_cv_posix.h" #include "src/core/lib/iomgr/ev_poll_posix.h" #include "src/core/lib/support/env.h" @@ -66,6 +67,7 @@ typedef struct { static const event_engine_factory g_factories[] = { {"epoll", grpc_init_epoll_linux}, {"poll", grpc_init_poll_posix}, + {"poll-cv", grpc_init_poll_cv_posix}, {"legacy", grpc_init_poll_and_epoll_posix}, }; diff --git a/src/core/lib/iomgr/wakeup_fd_cv.c b/src/core/lib/iomgr/wakeup_fd_cv.c new file mode 100644 index 0000000000..651e2f663d --- /dev/null +++ b/src/core/lib/iomgr/wakeup_fd_cv.c @@ -0,0 +1,118 @@ +/* + * + * 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 + +#ifdef GPR_POSIX_WAKEUP_FD + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/iomgr/ev_poll_cv_posix.h" + +#define MAX_TABLE_RESIZE 256 + +extern cv_fd_table g_cvfds; + +static grpc_error* cv_fd_init(grpc_wakeup_fd* fd_info) { + unsigned int i, newsize; + int idx; + gpr_mu_lock(&g_cvfds.mu); + if (!g_cvfds.free_fds) { + newsize = GPR_MIN(g_cvfds.size * 2, g_cvfds.size + MAX_TABLE_RESIZE); + g_cvfds.cvfds = gpr_realloc(g_cvfds.cvfds, sizeof(fd_node) * newsize); + for (i = g_cvfds.size; i < newsize; i++) { + g_cvfds.cvfds[i].is_set = 0; + g_cvfds.cvfds[i].cvs = NULL; + g_cvfds.cvfds[i].next_free = g_cvfds.free_fds; + g_cvfds.free_fds = &g_cvfds.cvfds[i]; + } + g_cvfds.size = newsize; + } + + idx = (int)(g_cvfds.free_fds - g_cvfds.cvfds); + g_cvfds.free_fds = g_cvfds.free_fds->next_free; + g_cvfds.cvfds[idx].cvs = NULL; + g_cvfds.cvfds[idx].is_set = 0; + fd_info->read_fd = IDX_TO_FD(idx); + fd_info->write_fd = -1; + gpr_mu_unlock(&g_cvfds.mu); + return GRPC_ERROR_NONE; +} + +static grpc_error* cv_fd_wakeup(grpc_wakeup_fd* fd_info) { + cv_node* cvn; + gpr_mu_lock(&g_cvfds.mu); + g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].is_set = 1; + cvn = g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].cvs; + while (cvn) { + gpr_cv_signal(cvn->cv); + cvn = cvn->next; + } + gpr_mu_unlock(&g_cvfds.mu); + return GRPC_ERROR_NONE; +} + +static grpc_error* cv_fd_consume(grpc_wakeup_fd* fd_info) { + gpr_mu_lock(&g_cvfds.mu); + g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].is_set = 0; + gpr_mu_unlock(&g_cvfds.mu); + return GRPC_ERROR_NONE; +} + +static void cv_fd_destroy(grpc_wakeup_fd* fd_info) { + if (fd_info->read_fd == 0) { + return; + } + gpr_mu_lock(&g_cvfds.mu); + // Assert that there are no active pollers + GPR_ASSERT(!g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].cvs); + g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)].next_free = g_cvfds.free_fds; + g_cvfds.free_fds = &g_cvfds.cvfds[FD_TO_IDX(fd_info->read_fd)]; + gpr_mu_unlock(&g_cvfds.mu); +} + +static int cv_check_availability(void) { return 1; } + +const grpc_wakeup_fd_vtable grpc_cv_wakeup_fd_vtable = { + cv_fd_init, cv_fd_consume, cv_fd_wakeup, cv_fd_destroy, + cv_check_availability}; + +#endif /* GPR_POSIX_WAKUP_FD */ diff --git a/src/core/lib/iomgr/wakeup_fd_cv.h b/src/core/lib/iomgr/wakeup_fd_cv.h new file mode 100644 index 0000000000..e57fc28363 --- /dev/null +++ b/src/core/lib/iomgr/wakeup_fd_cv.h @@ -0,0 +1,55 @@ +/* + * + * 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. + * + */ + +/* + * wakeup_fd_cv uses condition variables to implement wakeup fds. + * + * It is intended for use only in cases when eventfd() and pipe() are not + * available. It can only be used with the "poll" engine. + * + * Implementation: + * A global table of cv wakeup fds is mantained. A cv wakeup fd is a negative + * file descriptor. poll() is then run in a background thread with only the + * real socket fds while we wait on a condition variable trigged by either the + * poll() completion or a wakeup_fd() call. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H +#define GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H + +#include "src/core/lib/iomgr/wakeup_fd_posix.h" + +extern grpc_wakeup_fd_vtable grpc_cv_wakeup_fd_vtable; + +#endif /* GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H */ diff --git a/src/core/lib/iomgr/wakeup_fd_pipe.c b/src/core/lib/iomgr/wakeup_fd_pipe.c index 4e5dbdcb73..d0ea216aa0 100644 --- a/src/core/lib/iomgr/wakeup_fd_pipe.c +++ b/src/core/lib/iomgr/wakeup_fd_pipe.c @@ -47,11 +47,10 @@ static grpc_error* pipe_init(grpc_wakeup_fd* fd_info) { int pipefd[2]; - /* TODO(klempner): Make this nonfatal */ int r = pipe(pipefd); if (0 != r) { gpr_log(GPR_ERROR, "pipe creation failed (%d): %s", errno, strerror(errno)); - abort(); + return GRPC_OS_ERROR(errno, "pipe"); } grpc_error* err; err = grpc_set_socket_nonblocking(pipefd[0], 1); @@ -95,8 +94,13 @@ static void pipe_destroy(grpc_wakeup_fd* fd_info) { } static int pipe_check_availability(void) { - /* Assume that pipes are always available. */ - return 1; + grpc_wakeup_fd fd; + if (pipe_init(&fd) == GRPC_ERROR_NONE) { + pipe_destroy(&fd); + return 1; + } else { + return 0; + } } const grpc_wakeup_fd_vtable grpc_pipe_wakeup_fd_vtable = { diff --git a/src/core/lib/iomgr/wakeup_fd_posix.c b/src/core/lib/iomgr/wakeup_fd_posix.c index 046208abc8..041c221de3 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.c +++ b/src/core/lib/iomgr/wakeup_fd_posix.c @@ -36,18 +36,25 @@ #ifdef GPR_POSIX_WAKEUP_FD #include +#include "src/core/lib/iomgr/wakeup_fd_cv.h" #include "src/core/lib/iomgr/wakeup_fd_pipe.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL; int grpc_allow_specialized_wakeup_fd = 1; +int grpc_allow_pipe_wakeup_fd = 1; +int grpc_has_wakeup_fd = 1; void grpc_wakeup_fd_global_init(void) { if (grpc_allow_specialized_wakeup_fd && grpc_specialized_wakeup_fd_vtable.check_availability()) { wakeup_fd_vtable = &grpc_specialized_wakeup_fd_vtable; - } else { + } else if (grpc_allow_pipe_wakeup_fd && + grpc_pipe_wakeup_fd_vtable.check_availability()) { wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable; + } else { + grpc_has_wakeup_fd = 0; + wakeup_fd_vtable = &grpc_cv_wakeup_fd_vtable; } } diff --git a/src/core/lib/iomgr/wakeup_fd_posix.h b/src/core/lib/iomgr/wakeup_fd_posix.h index e269f242d8..bd0fb46da1 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.h +++ b/src/core/lib/iomgr/wakeup_fd_posix.h @@ -88,6 +88,8 @@ struct grpc_wakeup_fd { }; extern int grpc_allow_specialized_wakeup_fd; +extern int grpc_allow_pipe_wakeup_fd; +extern int grpc_has_wakeup_fd; #define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd) diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 2bebf48c70..62d9729e13 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -102,6 +102,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', + 'src/core/lib/iomgr/ev_poll_cv_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', @@ -134,6 +135,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', 'src/core/lib/iomgr/unix_sockets_posix_noop.c', + 'src/core/lib/iomgr/wakeup_fd_cv.c', 'src/core/lib/iomgr/wakeup_fd_eventfd.c', 'src/core/lib/iomgr/wakeup_fd_nospecial.c', 'src/core/lib/iomgr/wakeup_fd_pipe.c', diff --git a/test/core/iomgr/wakeup_fd_cv_test.c b/test/core/iomgr/wakeup_fd_cv_test.c new file mode 100644 index 0000000000..952985ed7e --- /dev/null +++ b/test/core/iomgr/wakeup_fd_cv_test.c @@ -0,0 +1,240 @@ +/* + * + * 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 + +#include +#include +#include +#include + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/iomgr_posix.h" +#include "src/core/lib/support/env.h" + +typedef struct poll_args { + struct pollfd *fds; + nfds_t nfds; + int timeout; + int result; +} poll_args; + +gpr_cv poll_cv; +gpr_mu poll_mu; +static int socket_event = 0; + +// Trigger a "socket" POLLIN in mock_poll() +void trigger_socket_event() { + gpr_mu_lock(&poll_mu); + socket_event = 1; + gpr_cv_broadcast(&poll_cv); + gpr_mu_unlock(&poll_mu); +} + +void reset_socket_event() { + gpr_mu_lock(&poll_mu); + socket_event = 0; + gpr_mu_unlock(&poll_mu); +} + +// Mocks posix poll() function +int mock_poll(struct pollfd *fds, nfds_t nfds, int timeout) { + int res = 0; + gpr_timespec poll_time; + gpr_mu_lock(&poll_mu); + GPR_ASSERT(nfds == 3); + GPR_ASSERT(fds[0].fd == 20); + GPR_ASSERT(fds[1].fd == 30); + GPR_ASSERT(fds[2].fd == 50); + GPR_ASSERT(fds[0].events == (POLLIN | POLLHUP)); + GPR_ASSERT(fds[1].events == (POLLIN | POLLHUP)); + GPR_ASSERT(fds[2].events == POLLIN); + + if (timeout < 0) { + poll_time = gpr_inf_future(GPR_CLOCK_REALTIME); + } else { + poll_time = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(timeout, GPR_TIMESPAN)); + } + + if (socket_event || !gpr_cv_wait(&poll_cv, &poll_mu, poll_time)) { + fds[0].revents = POLLIN; + res = 1; + } + gpr_mu_unlock(&poll_mu); + return res; +} + +void background_poll(void *args) { + poll_args *pargs = (poll_args *)args; + pargs->result = grpc_poll_function(pargs->fds, pargs->nfds, pargs->timeout); +} + +void test_many_fds(void) { + int i; + grpc_wakeup_fd fd[1000]; + for (i = 0; i < 1000; i++) { + GPR_ASSERT(grpc_wakeup_fd_init(&fd[i]) == GRPC_ERROR_NONE); + } + for (i = 0; i < 1000; i++) { + grpc_wakeup_fd_destroy(&fd[i]); + } +} + +void test_poll_cv_trigger(void) { + grpc_wakeup_fd cvfd1, cvfd2, cvfd3; + struct pollfd pfds[6]; + poll_args pargs; + gpr_thd_id t_id; + gpr_thd_options opt; + + GPR_ASSERT(grpc_wakeup_fd_init(&cvfd1) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_wakeup_fd_init(&cvfd2) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_wakeup_fd_init(&cvfd3) == GRPC_ERROR_NONE); + GPR_ASSERT(cvfd1.read_fd < 0); + GPR_ASSERT(cvfd2.read_fd < 0); + GPR_ASSERT(cvfd3.read_fd < 0); + GPR_ASSERT(cvfd1.read_fd != cvfd2.read_fd); + GPR_ASSERT(cvfd2.read_fd != cvfd3.read_fd); + GPR_ASSERT(cvfd1.read_fd != cvfd3.read_fd); + + pfds[0].fd = cvfd1.read_fd; + pfds[1].fd = cvfd2.read_fd; + pfds[2].fd = 20; + pfds[3].fd = 30; + pfds[4].fd = cvfd3.read_fd; + pfds[5].fd = 50; + + pfds[0].events = 0; + pfds[1].events = POLLIN; + pfds[2].events = POLLIN | POLLHUP; + pfds[3].events = POLLIN | POLLHUP; + pfds[4].events = POLLIN; + pfds[5].events = POLLIN; + + pargs.fds = pfds; + pargs.nfds = 6; + pargs.timeout = 1000; + pargs.result = -2; + + opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + + // Wakeup wakeup_fd not listening for events + GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd1) == GRPC_ERROR_NONE); + gpr_thd_join(t_id); + GPR_ASSERT(pargs.result == 0); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == 0); + GPR_ASSERT(pfds[2].revents == 0); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // Pollin on socket fd + pargs.timeout = -1; + pargs.result = -2; + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + trigger_socket_event(); + gpr_thd_join(t_id); + GPR_ASSERT(pargs.result == 1); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == 0); + GPR_ASSERT(pfds[2].revents == POLLIN); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // Pollin on wakeup fd + reset_socket_event(); + pargs.result = -2; + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd2) == GRPC_ERROR_NONE); + gpr_thd_join(t_id); + + GPR_ASSERT(pargs.result == 1); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == POLLIN); + GPR_ASSERT(pfds[2].revents == 0); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // Pollin on wakeup fd + socket fd + trigger_socket_event(); + pargs.result = -2; + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + gpr_thd_join(t_id); + + GPR_ASSERT(pargs.result == 2); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == POLLIN); + GPR_ASSERT(pfds[2].revents == POLLIN); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); + + // No Events + pargs.result = -2; + pargs.timeout = 1000; + reset_socket_event(); + GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd1) == GRPC_ERROR_NONE); + GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd2) == GRPC_ERROR_NONE); + gpr_thd_new(&t_id, &background_poll, &pargs, &opt); + gpr_thd_join(t_id); + + GPR_ASSERT(pargs.result == 0); + GPR_ASSERT(pfds[0].revents == 0); + GPR_ASSERT(pfds[1].revents == 0); + GPR_ASSERT(pfds[2].revents == 0); + GPR_ASSERT(pfds[3].revents == 0); + GPR_ASSERT(pfds[4].revents == 0); + GPR_ASSERT(pfds[5].revents == 0); +} + +int main(int argc, char **argv) { + gpr_setenv("GRPC_POLL_STRATEGY", "poll-cv"); + grpc_poll_function = &mock_poll; + gpr_mu_init(&poll_mu); + gpr_cv_init(&poll_cv); + + grpc_iomgr_platform_init(); + test_many_fds(); + grpc_iomgr_platform_shutdown(); + + grpc_iomgr_platform_init(); + test_poll_cv_trigger(); + grpc_iomgr_platform_shutdown(); + return 0; +} diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 44f147aeb1..1ec177cdf3 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -810,6 +810,7 @@ src/core/lib/iomgr/endpoint_pair.h \ src/core/lib/iomgr/error.h \ src/core/lib/iomgr/ev_epoll_linux.h \ src/core/lib/iomgr/ev_poll_and_epoll_posix.h \ +src/core/lib/iomgr/ev_poll_cv_posix.h \ src/core/lib/iomgr/ev_poll_posix.h \ src/core/lib/iomgr/ev_posix.h \ src/core/lib/iomgr/exec_ctx.h \ @@ -841,6 +842,7 @@ src/core/lib/iomgr/timer.h \ src/core/lib/iomgr/timer_heap.h \ src/core/lib/iomgr/udp_server.h \ src/core/lib/iomgr/unix_sockets_posix.h \ +src/core/lib/iomgr/wakeup_fd_cv.h \ src/core/lib/iomgr/wakeup_fd_pipe.h \ src/core/lib/iomgr/wakeup_fd_posix.h \ src/core/lib/iomgr/workqueue.h \ @@ -975,6 +977,7 @@ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ +src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -1007,6 +1010,7 @@ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ src/core/lib/iomgr/unix_sockets_posix_noop.c \ +src/core/lib/iomgr/wakeup_fd_cv.c \ src/core/lib/iomgr/wakeup_fd_eventfd.c \ src/core/lib/iomgr/wakeup_fd_nospecial.c \ src/core/lib/iomgr/wakeup_fd_pipe.c \ diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index a6f3d405dc..a9925ed976 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -69,7 +69,7 @@ _FORCE_ENVIRON_FOR_WRAPPERS = { _POLLING_STRATEGIES = { - 'linux': ['epoll', 'poll', 'legacy'] + 'linux': ['epoll', 'poll', 'poll-cv', 'legacy'] } diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index c05d194e19..35b21d4e20 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -2079,6 +2079,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "wakeup_fd_cv_test", + "src": [ + "test/core/iomgr/wakeup_fd_cv_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -6374,6 +6391,7 @@ "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -6405,6 +6423,7 @@ "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_pipe.h", "src/core/lib/iomgr/wakeup_fd_posix.h", "src/core/lib/iomgr/workqueue.h", @@ -6493,6 +6512,8 @@ "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", + "src/core/lib/iomgr/ev_poll_cv_posix.c", + "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.c", @@ -6556,6 +6577,8 @@ "src/core/lib/iomgr/unix_sockets_posix.c", "src/core/lib/iomgr/unix_sockets_posix.h", "src/core/lib/iomgr/unix_sockets_posix_noop.c", + "src/core/lib/iomgr/wakeup_fd_cv.c", + "src/core/lib/iomgr/wakeup_fd_cv.h", "src/core/lib/iomgr/wakeup_fd_eventfd.c", "src/core/lib/iomgr/wakeup_fd_nospecial.c", "src/core/lib/iomgr/wakeup_fd_pipe.c", diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index c3395067c9..323c09c77f 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -2061,6 +2061,25 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "wakeup_fd_cv_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [], "ci_platforms": [ diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 965d06d1d5..7d5e0ee56f 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -319,6 +319,7 @@ + @@ -350,6 +351,7 @@ + @@ -511,6 +513,8 @@ + + @@ -575,6 +579,8 @@ + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index dddd4ecce5..72bf449c3e 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -76,6 +76,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -172,6 +175,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -740,6 +746,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -833,6 +842,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index b724c217ed..44cbe8bf0c 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -212,6 +212,7 @@ + @@ -243,6 +244,7 @@ + @@ -359,6 +361,8 @@ + + @@ -423,6 +427,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 92806fa04a..57466022f4 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -130,6 +130,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -226,6 +229,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -527,6 +533,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -620,6 +629,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index b46773632c..aa47cc800d 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -309,6 +309,7 @@ + @@ -340,6 +341,7 @@ + @@ -479,6 +481,8 @@ + + @@ -543,6 +547,8 @@ + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 6ffc1eab70..4706c90af2 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -79,6 +79,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -175,6 +178,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -650,6 +656,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr @@ -743,6 +752,9 @@ src\core\lib\iomgr + + src\core\lib\iomgr + src\core\lib\iomgr -- cgit v1.2.3 From cd7d0479a2aa51166ca251ed0f460f1c2ea5d1e7 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Tue, 11 Oct 2016 12:24:20 -0700 Subject: Cleanup poll-cv setup --- src/core/lib/iomgr/ev_epoll_linux.c | 2 +- src/core/lib/iomgr/ev_poll_cv_posix.c | 13 ++----------- src/core/lib/iomgr/ev_poll_posix.c | 2 +- src/core/lib/iomgr/wakeup_fd_posix.c | 30 ++++++++++++++++++++++++++---- src/core/lib/iomgr/wakeup_fd_posix.h | 5 ++++- 5 files changed, 34 insertions(+), 18 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c index 249bc98735..ad1cfc2031 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epoll_linux.c @@ -1892,7 +1892,7 @@ const grpc_event_engine_vtable *grpc_init_epoll_linux(void) { return NULL; } - if (!grpc_has_wakeup_fd) { + if (!grpc_has_wakeup_fd()) { return NULL; } diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.c b/src/core/lib/iomgr/ev_poll_cv_posix.c index 1ea811e445..0cb414ba88 100644 --- a/src/core/lib/iomgr/ev_poll_cv_posix.c +++ b/src/core/lib/iomgr/ev_poll_cv_posix.c @@ -255,21 +255,12 @@ static void shutdown_engine(void) { } const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void) { - int has_wakeup_fd = grpc_has_wakeup_fd; - int allow_specialized_wakeup_fd = grpc_allow_specialized_wakeup_fd; - int allow_pipe_wakeup_fd = grpc_allow_pipe_wakeup_fd; grpc_global_cv_fd_table_init(); - grpc_allow_specialized_wakeup_fd = 0; - grpc_allow_pipe_wakeup_fd = 0; - grpc_wakeup_fd_global_init(); - grpc_has_wakeup_fd = 1; + grpc_enable_cv_wakeup_fds(1); ev_poll_vtable = grpc_init_poll_posix(); if (!ev_poll_vtable) { grpc_global_cv_fd_table_shutdown(); - grpc_has_wakeup_fd = has_wakeup_fd; - grpc_allow_specialized_wakeup_fd = allow_specialized_wakeup_fd; - grpc_allow_pipe_wakeup_fd = allow_pipe_wakeup_fd; - grpc_global_cv_fd_table_init(); + grpc_enable_cv_wakeup_fds(0); return NULL; } vtable = *ev_poll_vtable; diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c index 97e71d968e..0dca51bc78 100644 --- a/src/core/lib/iomgr/ev_poll_posix.c +++ b/src/core/lib/iomgr/ev_poll_posix.c @@ -1277,7 +1277,7 @@ static const grpc_event_engine_vtable vtable = { }; const grpc_event_engine_vtable *grpc_init_poll_posix(void) { - if (!grpc_has_wakeup_fd) { + if (!grpc_has_wakeup_fd()) { return NULL; } if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { diff --git a/src/core/lib/iomgr/wakeup_fd_posix.c b/src/core/lib/iomgr/wakeup_fd_posix.c index 041c221de3..f75ae78c22 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.c +++ b/src/core/lib/iomgr/wakeup_fd_posix.c @@ -41,9 +41,11 @@ #include "src/core/lib/iomgr/wakeup_fd_posix.h" static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL; + int grpc_allow_specialized_wakeup_fd = 1; int grpc_allow_pipe_wakeup_fd = 1; -int grpc_has_wakeup_fd = 1; +int grpc_has_real_wakeup_fd = 1; +int grpc_cv_wakeup_fds_enabled = 0; void grpc_wakeup_fd_global_init(void) { if (grpc_allow_specialized_wakeup_fd && @@ -53,27 +55,47 @@ void grpc_wakeup_fd_global_init(void) { grpc_pipe_wakeup_fd_vtable.check_availability()) { wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable; } else { - grpc_has_wakeup_fd = 0; - wakeup_fd_vtable = &grpc_cv_wakeup_fd_vtable; + grpc_has_real_wakeup_fd = 0; } } void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; } +int grpc_has_wakeup_fd(void) { + return grpc_has_real_wakeup_fd || grpc_cv_wakeup_fds_enabled; +} + +void grpc_enable_cv_wakeup_fds(int enable) { + grpc_cv_wakeup_fds_enabled = enable; +} + grpc_error *grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) { + if (grpc_cv_wakeup_fds_enabled) { + return grpc_cv_wakeup_fd_vtable.init(fd_info); + } return wakeup_fd_vtable->init(fd_info); } grpc_error *grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd *fd_info) { + if (grpc_cv_wakeup_fds_enabled) { + return grpc_cv_wakeup_fd_vtable.consume(fd_info); + } return wakeup_fd_vtable->consume(fd_info); } grpc_error *grpc_wakeup_fd_wakeup(grpc_wakeup_fd *fd_info) { + if (grpc_cv_wakeup_fds_enabled) { + return grpc_cv_wakeup_fd_vtable.wakeup(fd_info); + } return wakeup_fd_vtable->wakeup(fd_info); } void grpc_wakeup_fd_destroy(grpc_wakeup_fd *fd_info) { - wakeup_fd_vtable->destroy(fd_info); + if (grpc_cv_wakeup_fds_enabled) { + grpc_cv_wakeup_fd_vtable.destroy(fd_info); + } else { + wakeup_fd_vtable->destroy(fd_info); + } } #endif /* GPR_POSIX_WAKEUP_FD */ diff --git a/src/core/lib/iomgr/wakeup_fd_posix.h b/src/core/lib/iomgr/wakeup_fd_posix.h index bd0fb46da1..243c452751 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.h +++ b/src/core/lib/iomgr/wakeup_fd_posix.h @@ -71,6 +71,9 @@ void grpc_wakeup_fd_global_destroy(void); * purposes only.*/ void grpc_wakeup_fd_global_init_force_fallback(void); +int grpc_has_wakeup_fd(void); +void grpc_enable_cv_wakeup_fds(int enable); + typedef struct grpc_wakeup_fd grpc_wakeup_fd; typedef struct grpc_wakeup_fd_vtable { @@ -89,7 +92,7 @@ struct grpc_wakeup_fd { extern int grpc_allow_specialized_wakeup_fd; extern int grpc_allow_pipe_wakeup_fd; -extern int grpc_has_wakeup_fd; +extern int grpc_has_real_wakeup_fd; #define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd) -- cgit v1.2.3 From 7e73f8c2d8f46f9ea3491a897345047bed7a0ea0 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Tue, 11 Oct 2016 12:55:40 -0700 Subject: Changes --- src/core/lib/iomgr/ev_poll_cv_posix.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.h b/src/core/lib/iomgr/ev_poll_cv_posix.h index ff667a54c2..885711d1c5 100644 --- a/src/core/lib/iomgr/ev_poll_cv_posix.h +++ b/src/core/lib/iomgr/ev_poll_cv_posix.h @@ -54,12 +54,9 @@ typedef struct fd_node { typedef struct cv_fd_table { gpr_mu mu; -<<<<<<< HEAD -======= int pollcount; int shutdown; gpr_cv shutdown_complete; ->>>>>>> d195cf589d3f03b4f08017f3e2885c2c2fff125b fd_node* cvfds; fd_node* free_fds; unsigned int size; -- cgit v1.2.3 From a3654db631f02eb7f566ea775d78f3ff2b27830a Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Tue, 11 Oct 2016 15:52:39 -0700 Subject: Renamed LB-related metadata keys --- src/core/ext/lb_policy/grpclb/grpclb.c | 6 +++--- src/core/ext/load_reporting/load_reporting.h | 4 ++-- src/core/ext/load_reporting/load_reporting_filter.c | 4 ++-- src/core/lib/transport/static_metadata.c | 4 ++-- src/core/lib/transport/static_metadata.h | 21 ++++++++++----------- test/core/end2end/fuzzers/hpack.dictionary | 8 ++++---- test/core/end2end/tests/load_reporting_hook.c | 4 ++-- test/cpp/grpclb/grpclb_test.cc | 3 +-- tools/codegen/core/gen_static_metadata.py | 4 ++-- 9 files changed, 28 insertions(+), 30 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c index ae1f2a3b4c..0442c864f5 100644 --- a/src/core/ext/lb_policy/grpclb/grpclb.c +++ b/src/core/ext/lb_policy/grpclb/grpclb.c @@ -399,14 +399,14 @@ static grpc_lb_addresses *process_serverlist( GPR_ARRAY_SIZE(server->load_balance_token) - 1; grpc_mdstr *lb_token_mdstr = grpc_mdstr_from_buffer( (uint8_t *)server->load_balance_token, lb_token_size); - user_data = grpc_mdelem_from_metadata_strings( - GRPC_MDSTR_LOAD_REPORTING_INITIAL, lb_token_mdstr); + user_data = grpc_mdelem_from_metadata_strings(GRPC_MDSTR_LB_TOKEN, + lb_token_mdstr); } else { gpr_log(GPR_ERROR, "Missing LB token for backend address '%s'. The empty token will " "be used instead", grpc_sockaddr_to_uri((struct sockaddr *)&addr.addr)); - user_data = GRPC_MDELEM_LOAD_REPORTING_INITIAL_EMPTY; + user_data = GRPC_MDELEM_LB_TOKEN_EMPTY; } grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len, diff --git a/src/core/ext/load_reporting/load_reporting.h b/src/core/ext/load_reporting/load_reporting.h index e37817d8c2..a0db780c3a 100644 --- a/src/core/ext/load_reporting/load_reporting.h +++ b/src/core/ext/load_reporting/load_reporting.h @@ -39,11 +39,11 @@ /** Metadata key for initial metadata coming from clients */ /* TODO(dgq): change to the final value TBD */ -#define GRPC_LOAD_REPORTING_INITIAL_MD_KEY "load-reporting-initial" +#define GRPC_LB_TOKEN_MD_KEY "lb-token" /** Metadata key for trailing metadata from servers */ /* TODO(dgq): change to the final value TBD */ -#define GRPC_LOAD_REPORTING_TRAILING_MD_KEY "load-reporting-trailing" +#define GRPC_LB_COST_MD_KEY "lb-cost" /** Identifiers for the invocation point of the users LR callback */ typedef enum grpc_load_reporting_source { diff --git a/src/core/ext/load_reporting/load_reporting_filter.c b/src/core/ext/load_reporting/load_reporting_filter.c index 394f0cb832..22bf36367f 100644 --- a/src/core/ext/load_reporting/load_reporting_filter.c +++ b/src/core/ext/load_reporting/load_reporting_filter.c @@ -75,7 +75,7 @@ static grpc_mdelem *recv_md_filter(void *user_data, grpc_mdelem *md) { if (md->key == GRPC_MDSTR_PATH) { calld->service_method = grpc_mdstr_as_c_string(md->value); - } else if (md->key == GRPC_MDSTR_LOAD_REPORTING_INITIAL) { + } else if (md->key == GRPC_MDSTR_LB_TOKEN) { calld->initial_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value)); return NULL; } @@ -193,7 +193,7 @@ static grpc_mdelem *lr_trailing_md_filter(void *user_data, grpc_mdelem *md) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; - if (md->key == GRPC_MDSTR_LOAD_REPORTING_TRAILING) { + if (md->key == GRPC_MDSTR_LB_COST) { calld->trailing_md_string = gpr_strdup(grpc_mdstr_as_c_string(md->value)); return NULL; } diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c index 5e0352a467..f019ef156a 100644 --- a/src/core/lib/transport/static_metadata.c +++ b/src/core/lib/transport/static_metadata.c @@ -126,9 +126,9 @@ const char *const grpc_static_metadata_strings[GRPC_STATIC_MDSTR_COUNT] = { "if-range", "if-unmodified-since", "last-modified", + "lb-cost", + "lb-token", "link", - "load-reporting-initial", - "load-reporting-trailing", "location", "max-forwards", ":method", diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h index 5b9ee1a60a..e0a8196419 100644 --- a/src/core/lib/transport/static_metadata.h +++ b/src/core/lib/transport/static_metadata.h @@ -175,12 +175,12 @@ extern grpc_mdstr grpc_static_mdstr_table[GRPC_STATIC_MDSTR_COUNT]; #define GRPC_MDSTR_IF_UNMODIFIED_SINCE (&grpc_static_mdstr_table[62]) /* "last-modified" */ #define GRPC_MDSTR_LAST_MODIFIED (&grpc_static_mdstr_table[63]) +/* "lb-cost" */ +#define GRPC_MDSTR_LB_COST (&grpc_static_mdstr_table[64]) +/* "lb-token" */ +#define GRPC_MDSTR_LB_TOKEN (&grpc_static_mdstr_table[65]) /* "link" */ -#define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[64]) -/* "load-reporting-initial" */ -#define GRPC_MDSTR_LOAD_REPORTING_INITIAL (&grpc_static_mdstr_table[65]) -/* "load-reporting-trailing" */ -#define GRPC_MDSTR_LOAD_REPORTING_TRAILING (&grpc_static_mdstr_table[66]) +#define GRPC_MDSTR_LINK (&grpc_static_mdstr_table[66]) /* "location" */ #define GRPC_MDSTR_LOCATION (&grpc_static_mdstr_table[67]) /* "max-forwards" */ @@ -337,13 +337,12 @@ extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT]; #define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY (&grpc_static_mdelem_table[44]) /* "last-modified": "" */ #define GRPC_MDELEM_LAST_MODIFIED_EMPTY (&grpc_static_mdelem_table[45]) +/* "lb-cost": "" */ +#define GRPC_MDELEM_LB_COST_EMPTY (&grpc_static_mdelem_table[46]) +/* "lb-token": "" */ +#define GRPC_MDELEM_LB_TOKEN_EMPTY (&grpc_static_mdelem_table[47]) /* "link": "" */ -#define GRPC_MDELEM_LINK_EMPTY (&grpc_static_mdelem_table[46]) -/* "load-reporting-initial": "" */ -#define GRPC_MDELEM_LOAD_REPORTING_INITIAL_EMPTY (&grpc_static_mdelem_table[47]) -/* "load-reporting-trailing": "" */ -#define GRPC_MDELEM_LOAD_REPORTING_TRAILING_EMPTY \ - (&grpc_static_mdelem_table[48]) +#define GRPC_MDELEM_LINK_EMPTY (&grpc_static_mdelem_table[48]) /* "location": "" */ #define GRPC_MDELEM_LOCATION_EMPTY (&grpc_static_mdelem_table[49]) /* "max-forwards": "" */ diff --git a/test/core/end2end/fuzzers/hpack.dictionary b/test/core/end2end/fuzzers/hpack.dictionary index a93bccfa0d..181bbe845e 100644 --- a/test/core/end2end/fuzzers/hpack.dictionary +++ b/test/core/end2end/fuzzers/hpack.dictionary @@ -63,9 +63,9 @@ "\x08if-range" "\x13if-unmodified-since" "\x0Dlast-modified" +"\x07lb-cost" +"\x08lb-token" "\x04link" -"\x16load-reporting-initial" -"\x17load-reporting-trailing" "\x08location" "\x0Cmax-forwards" "\x07:method" @@ -138,9 +138,9 @@ "\x00\x08if-range\x00" "\x00\x13if-unmodified-since\x00" "\x00\x0Dlast-modified\x00" +"\x00\x07lb-cost\x00" +"\x00\x08lb-token\x00" "\x00\x04link\x00" -"\x00\x16load-reporting-initial\x00" -"\x00\x17load-reporting-trailing\x00" "\x00\x08location\x00" "\x00\x0Cmax-forwards\x00" "\x00\x07:method\x03GET" diff --git a/test/core/end2end/tests/load_reporting_hook.c b/test/core/end2end/tests/load_reporting_hook.c index 59d054cf87..7f95dfd949 100644 --- a/test/core/end2end/tests/load_reporting_hook.c +++ b/test/core/end2end/tests/load_reporting_hook.c @@ -295,13 +295,13 @@ static void test_load_reporting_hook(grpc_end2end_test_config config) { grpc_metadata initial_lr_metadata; grpc_metadata trailing_lr_metadata; - initial_lr_metadata.key = GRPC_LOAD_REPORTING_INITIAL_MD_KEY; + initial_lr_metadata.key = GRPC_LB_TOKEN_MD_KEY; initial_lr_metadata.value = "client-token"; initial_lr_metadata.value_length = strlen(initial_lr_metadata.value); memset(&initial_lr_metadata.internal_data, 0, sizeof(initial_lr_metadata.internal_data)); - trailing_lr_metadata.key = GRPC_LOAD_REPORTING_TRAILING_MD_KEY; + trailing_lr_metadata.key = GRPC_LB_COST_MD_KEY; trailing_lr_metadata.value = "server-token"; trailing_lr_metadata.value_length = strlen(trailing_lr_metadata.value); memset(&trailing_lr_metadata.internal_data, 0, diff --git a/test/cpp/grpclb/grpclb_test.cc b/test/cpp/grpclb/grpclb_test.cc index 7666c4e60b..80f2fa4f4d 100644 --- a/test/cpp/grpclb/grpclb_test.cc +++ b/test/cpp/grpclb/grpclb_test.cc @@ -334,8 +334,7 @@ static void start_backend_server(server_fixture *sf) { // have a version for int but does have one for long long int. string expected_token = "token" + std::to_string((long long int)sf->port); expected_token.resize(64, '-'); - GPR_ASSERT(contains_metadata(&request_metadata_recv, - "load-reporting-initial", + GPR_ASSERT(contains_metadata(&request_metadata_recv, "lb-token", expected_token.c_str())); gpr_log(GPR_INFO, "Server[%s] after tag 100", sf->servers_hostport); diff --git a/tools/codegen/core/gen_static_metadata.py b/tools/codegen/core/gen_static_metadata.py index 6f400102e4..6f8cad279c 100755 --- a/tools/codegen/core/gen_static_metadata.py +++ b/tools/codegen/core/gen_static_metadata.py @@ -109,8 +109,8 @@ CONFIG = [ ('if-range', ''), ('if-unmodified-since', ''), ('last-modified', ''), - ('load-reporting-initial', ''), - ('load-reporting-trailing', ''), + ('lb-token', ''), + ('lb-cost', ''), ('link', ''), ('location', ''), ('max-forwards', ''), -- cgit v1.2.3 From 82e4ec741ba3e564d1223f0f20355a6e27e70136 Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Thu, 13 Oct 2016 12:26:01 -0700 Subject: Moved cv polling into ev_poll_posix.c --- BUILD | 8 - CMakeLists.txt | 3 - Makefile | 4 - binding.gyp | 1 - build.yaml | 2 - config.m4 | 1 - gRPC-Core.podspec | 3 - grpc.gemspec | 2 - package.xml | 2 - src/core/lib/iomgr/ev_poll_cv_posix.c | 288 --------------------- src/core/lib/iomgr/ev_poll_cv_posix.h | 68 ----- src/core/lib/iomgr/ev_poll_posix.c | 237 ++++++++++++++++- src/core/lib/iomgr/ev_poll_posix.h | 1 + src/core/lib/iomgr/ev_posix.c | 1 - src/core/lib/iomgr/wakeup_fd_cv.c | 4 +- src/core/lib/iomgr/wakeup_fd_cv.h | 29 ++- src/core/lib/iomgr/wakeup_fd_posix.c | 26 +- src/core/lib/iomgr/wakeup_fd_posix.h | 2 +- src/python/grpcio/grpc_core_dependencies.py | 1 - tools/doxygen/Doxyfile.core.internal | 2 - tools/run_tests/sources_and_headers.json | 3 - vsprojects/vcxproj/grpc/grpc.vcxproj | 3 - vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 6 - .../vcxproj/grpc_test_util/grpc_test_util.vcxproj | 3 - .../grpc_test_util/grpc_test_util.vcxproj.filters | 6 - .../vcxproj/grpc_unsecure/grpc_unsecure.vcxproj | 3 - .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 6 - 27 files changed, 280 insertions(+), 435 deletions(-) delete mode 100644 src/core/lib/iomgr/ev_poll_cv_posix.c delete mode 100644 src/core/lib/iomgr/ev_poll_cv_posix.h (limited to 'src/core/lib') diff --git a/BUILD b/BUILD index ba44367dbb..72cb046a60 100644 --- a/BUILD +++ b/BUILD @@ -186,7 +186,6 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", - "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -349,7 +348,6 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", - "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -591,7 +589,6 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", - "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -739,7 +736,6 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", - "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -951,7 +947,6 @@ cc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", - "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -1091,7 +1086,6 @@ cc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", - "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -1856,7 +1850,6 @@ objc_library( "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/ev_epoll_linux.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", - "src/core/lib/iomgr/ev_poll_cv_posix.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -2077,7 +2070,6 @@ objc_library( "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", - "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 747d1fab4d..9ba5135593 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -314,7 +314,6 @@ add_library(grpc src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c - src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -575,7 +574,6 @@ add_library(grpc_cronet src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c - src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -808,7 +806,6 @@ add_library(grpc_unsecure src/core/lib/iomgr/error.c src/core/lib/iomgr/ev_epoll_linux.c src/core/lib/iomgr/ev_poll_and_epoll_posix.c - src/core/lib/iomgr/ev_poll_cv_posix.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c diff --git a/Makefile b/Makefile index 1f4c9b5c32..65d715c67c 100644 --- a/Makefile +++ b/Makefile @@ -2562,7 +2562,6 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ - src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -2841,7 +2840,6 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ - src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -3110,7 +3108,6 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ - src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -3306,7 +3303,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ - src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ diff --git a/binding.gyp b/binding.gyp index 85070e5cac..6dfae41860 100644 --- a/binding.gyp +++ b/binding.gyp @@ -589,7 +589,6 @@ 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', - 'src/core/lib/iomgr/ev_poll_cv_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', diff --git a/build.yaml b/build.yaml index 3e64ce8f37..93ebf44ef8 100644 --- a/build.yaml +++ b/build.yaml @@ -190,7 +190,6 @@ filegroups: - src/core/lib/iomgr/error.h - src/core/lib/iomgr/ev_epoll_linux.h - src/core/lib/iomgr/ev_poll_and_epoll_posix.h - - src/core/lib/iomgr/ev_poll_cv_posix.h - src/core/lib/iomgr/ev_poll_posix.h - src/core/lib/iomgr/ev_posix.h - src/core/lib/iomgr/exec_ctx.h @@ -276,7 +275,6 @@ filegroups: - src/core/lib/iomgr/error.c - src/core/lib/iomgr/ev_epoll_linux.c - src/core/lib/iomgr/ev_poll_and_epoll_posix.c - - src/core/lib/iomgr/ev_poll_cv_posix.c - src/core/lib/iomgr/ev_poll_posix.c - src/core/lib/iomgr/ev_posix.c - src/core/lib/iomgr/exec_ctx.c diff --git a/config.m4 b/config.m4 index 1452798897..347686bd11 100644 --- a/config.m4 +++ b/config.m4 @@ -108,7 +108,6 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ - src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 3ac0b841cf..6becf4c608 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -273,7 +273,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/ev_epoll_linux.h', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.h', - 'src/core/lib/iomgr/ev_poll_cv_posix.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', @@ -440,7 +439,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', - 'src/core/lib/iomgr/ev_poll_cv_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', @@ -650,7 +648,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/ev_epoll_linux.h', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.h', - 'src/core/lib/iomgr/ev_poll_cv_posix.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', diff --git a/grpc.gemspec b/grpc.gemspec index 85135a5327..6a898b85ff 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -193,7 +193,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/error.h ) s.files += %w( src/core/lib/iomgr/ev_epoll_linux.h ) s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.h ) - s.files += %w( src/core/lib/iomgr/ev_poll_cv_posix.h ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.h ) s.files += %w( src/core/lib/iomgr/ev_posix.h ) s.files += %w( src/core/lib/iomgr/exec_ctx.h ) @@ -360,7 +359,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/error.c ) s.files += %w( src/core/lib/iomgr/ev_epoll_linux.c ) s.files += %w( src/core/lib/iomgr/ev_poll_and_epoll_posix.c ) - s.files += %w( src/core/lib/iomgr/ev_poll_cv_posix.c ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.c ) s.files += %w( src/core/lib/iomgr/ev_posix.c ) s.files += %w( src/core/lib/iomgr/exec_ctx.c ) diff --git a/package.xml b/package.xml index 4631fc1c39..1f9846a516 100644 --- a/package.xml +++ b/package.xml @@ -200,7 +200,6 @@ - @@ -367,7 +366,6 @@ - diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.c b/src/core/lib/iomgr/ev_poll_cv_posix.c deleted file mode 100644 index ed4c9e9143..0000000000 --- a/src/core/lib/iomgr/ev_poll_cv_posix.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * - * 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 - -#ifdef GPR_POSIX_SOCKET - -#include "src/core/lib/iomgr/ev_poll_cv_posix.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/iomgr/ev_poll_posix.h" -#include "src/core/lib/iomgr/wakeup_fd_posix.h" - -#define POLL_PERIOD_MS 1000 -#define DEFAULT_TABLE_SIZE 16 - -typedef enum status_t { INPROGRESS, COMPLETED, CANCELLED } status_t; - -typedef struct poll_args { - gpr_refcount refcount; - gpr_cv* cv; - struct pollfd* fds; - nfds_t nfds; - int timeout; - int retval; - int err; - status_t status; -} poll_args; - -cv_fd_table g_cvfds; - -static void decref_poll_args(poll_args* args) { - if (gpr_unref(&args->refcount)) { - gpr_free(args->fds); - gpr_cv_destroy(args->cv); - gpr_free(args->cv); - gpr_free(args); - } -} - -// Poll in a background thread -static void run_poll(void* arg) { - int timeout, retval; - poll_args* pargs = (poll_args*)arg; - while (pargs->status == INPROGRESS) { - if (pargs->timeout < 0) { - timeout = POLL_PERIOD_MS; - } else { - timeout = GPR_MIN(POLL_PERIOD_MS, pargs->timeout); - pargs->timeout -= timeout; - } - retval = g_cvfds.poll(pargs->fds, pargs->nfds, timeout); - if (retval != 0 || pargs->timeout == 0) { - pargs->retval = retval; - pargs->err = errno; - break; - } - } - gpr_mu_lock(&g_cvfds.mu); - if (pargs->status == INPROGRESS) { - // Signal main thread that the poll completed - pargs->status = COMPLETED; - gpr_cv_signal(pargs->cv); - } - decref_poll_args(pargs); - g_cvfds.pollcount--; - if (g_cvfds.shutdown && g_cvfds.pollcount == 0) { - gpr_cv_signal(&g_cvfds.shutdown_complete); - } - gpr_mu_unlock(&g_cvfds.mu); -} - -// This function overrides poll() to handle condition variable wakeup fds -static int cvfd_poll(struct pollfd* fds, nfds_t nfds, int timeout) { - unsigned int i; - int res, idx; - gpr_cv* pollcv; - cv_node *cvn, *prev; - nfds_t nsockfds = 0; - gpr_thd_id t_id; - gpr_thd_options opt; - poll_args* pargs = NULL; - gpr_mu_lock(&g_cvfds.mu); - pollcv = gpr_malloc(sizeof(gpr_cv)); - gpr_cv_init(pollcv); - for (i = 0; i < nfds; i++) { - fds[i].revents = 0; - if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { - idx = FD_TO_IDX(fds[i].fd); - cvn = gpr_malloc(sizeof(cv_node)); - cvn->cv = pollcv; - cvn->next = g_cvfds.cvfds[idx].cvs; - g_cvfds.cvfds[idx].cvs = cvn; - // We should return immediately if there are pending events, - // but we still need to call poll() to check for socket events - if (g_cvfds.cvfds[idx].is_set) { - timeout = 0; - } - } else if (fds[i].fd >= 0) { - nsockfds++; - } - } - - if (nsockfds > 0) { - pargs = gpr_malloc(sizeof(struct poll_args)); - // Both the main thread and calling thread get a reference - gpr_ref_init(&pargs->refcount, 2); - pargs->cv = pollcv; - pargs->fds = gpr_malloc(sizeof(struct pollfd) * nsockfds); - pargs->nfds = nsockfds; - pargs->timeout = timeout; - pargs->retval = 0; - pargs->err = 0; - pargs->status = INPROGRESS; - idx = 0; - for (i = 0; i < nfds; i++) { - if (fds[i].fd >= 0) { - pargs->fds[idx].fd = fds[i].fd; - pargs->fds[idx].events = fds[i].events; - pargs->fds[idx].revents = 0; - idx++; - } - } - g_cvfds.pollcount++; - opt = gpr_thd_options_default(); - gpr_thd_options_set_detached(&opt); - gpr_thd_new(&t_id, &run_poll, pargs, &opt); - // We want the poll() thread to trigger the deadline, so wait forever here - gpr_cv_wait(pollcv, &g_cvfds.mu, gpr_inf_future(GPR_CLOCK_MONOTONIC)); - if (pargs->status == COMPLETED) { - res = pargs->retval; - errno = pargs->err; - } else { - res = 0; - errno = 0; - pargs->status = CANCELLED; - } - } else { - gpr_timespec deadline = gpr_now(GPR_CLOCK_REALTIME); - deadline = - gpr_time_add(deadline, gpr_time_from_millis(timeout, GPR_TIMESPAN)); - gpr_cv_wait(pollcv, &g_cvfds.mu, deadline); - res = 0; - } - - idx = 0; - for (i = 0; i < nfds; i++) { - if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { - cvn = g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs; - prev = NULL; - while (cvn->cv != pollcv) { - prev = cvn; - cvn = cvn->next; - GPR_ASSERT(cvn); - } - if (!prev) { - g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs = cvn->next; - } else { - prev->next = cvn->next; - } - gpr_free(cvn); - - if (g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].is_set) { - fds[i].revents = POLLIN; - if (res >= 0) res++; - } - } else if (fds[i].fd >= 0 && pargs->status == COMPLETED) { - fds[i].revents = pargs->fds[idx].revents; - idx++; - } - } - - if (pargs) { - decref_poll_args(pargs); - } else { - gpr_cv_destroy(pollcv); - gpr_free(pollcv); - } - gpr_mu_unlock(&g_cvfds.mu); - - return res; -} - -static void grpc_global_cv_fd_table_init() { - gpr_mu_init(&g_cvfds.mu); - gpr_mu_lock(&g_cvfds.mu); - gpr_cv_init(&g_cvfds.shutdown_complete); - g_cvfds.shutdown = 0; - g_cvfds.pollcount = 0; - g_cvfds.size = DEFAULT_TABLE_SIZE; - g_cvfds.cvfds = gpr_malloc(sizeof(fd_node) * DEFAULT_TABLE_SIZE); - g_cvfds.free_fds = NULL; - for (int i = 0; i < DEFAULT_TABLE_SIZE; i++) { - g_cvfds.cvfds[i].is_set = 0; - g_cvfds.cvfds[i].cvs = NULL; - g_cvfds.cvfds[i].next_free = g_cvfds.free_fds; - g_cvfds.free_fds = &g_cvfds.cvfds[i]; - } - // Override the poll function with one that supports cvfds - g_cvfds.poll = grpc_poll_function; - grpc_poll_function = &cvfd_poll; - gpr_mu_unlock(&g_cvfds.mu); -} - -static void grpc_global_cv_fd_table_shutdown() { - gpr_mu_lock(&g_cvfds.mu); - g_cvfds.shutdown = 1; - // Attempt to wait for all abandoned poll() threads to terminate - // Not doing so will result in reported memory leaks - if (g_cvfds.pollcount > 0) { - int res = gpr_cv_wait(&g_cvfds.shutdown_complete, &g_cvfds.mu, - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_seconds(3, GPR_TIMESPAN))); - GPR_ASSERT(res == 0); - } - gpr_cv_destroy(&g_cvfds.shutdown_complete); - grpc_poll_function = g_cvfds.poll; - gpr_free(g_cvfds.cvfds); - gpr_mu_unlock(&g_cvfds.mu); - gpr_mu_destroy(&g_cvfds.mu); -} - -/******************************************************************************* - * event engine binding - */ - -static const grpc_event_engine_vtable* ev_poll_vtable; -static grpc_event_engine_vtable vtable; - -static void shutdown_engine(void) { - ev_poll_vtable->shutdown_engine(); - grpc_global_cv_fd_table_shutdown(); -} - -const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void) { - grpc_global_cv_fd_table_init(); - grpc_enable_cv_wakeup_fds(1); - ev_poll_vtable = grpc_init_poll_posix(); - if (!ev_poll_vtable) { - grpc_global_cv_fd_table_shutdown(); - grpc_enable_cv_wakeup_fds(0); - return NULL; - } - vtable = *ev_poll_vtable; - vtable.shutdown_engine = shutdown_engine; - return &vtable; -} - -#endif /* GPR_POSIX_SOCKET */ diff --git a/src/core/lib/iomgr/ev_poll_cv_posix.h b/src/core/lib/iomgr/ev_poll_cv_posix.h deleted file mode 100644 index 885711d1c5..0000000000 --- a/src/core/lib/iomgr/ev_poll_cv_posix.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef GRPC_CORE_LIB_IOMGR_EV_POLL_CV_POSIX_H -#define GRPC_CORE_LIB_IOMGR_EV_POLL_CV_POSIX_H - -#include - -#include "src/core/lib/iomgr/ev_posix.h" - -#define FD_TO_IDX(fd) (-(fd)-1) -#define IDX_TO_FD(idx) (-(idx)-1) - -typedef struct cv_node { - gpr_cv* cv; - struct cv_node* next; -} cv_node; - -typedef struct fd_node { - int is_set; - cv_node* cvs; - struct fd_node* next_free; -} fd_node; - -typedef struct cv_fd_table { - gpr_mu mu; - int pollcount; - int shutdown; - gpr_cv shutdown_complete; - fd_node* cvfds; - fd_node* free_fds; - unsigned int size; - grpc_poll_function_type poll; -} cv_fd_table; - -const grpc_event_engine_vtable* grpc_init_poll_cv_posix(void); - -#endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_CV_POSIX_H */ diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c index 0dca51bc78..d9e5255ddc 100644 --- a/src/core/lib/iomgr/ev_poll_posix.c +++ b/src/core/lib/iomgr/ev_poll_posix.c @@ -47,10 +47,12 @@ #include #include #include +#include #include #include #include "src/core/lib/iomgr/iomgr_internal.h" +#include "src/core/lib/iomgr/wakeup_fd_cv.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/block_annotate.h" @@ -245,6 +247,28 @@ struct grpc_pollset_set { grpc_fd **fds; }; +/******************************************************************************* + * condition variable polling definitions + */ + +#define CV_POLL_PERIOD_MS 1000 +#define CV_DEFAULT_TABLE_SIZE 16 + +typedef enum status_t { INPROGRESS, COMPLETED, CANCELLED } status_t; + +typedef struct poll_args { + gpr_refcount refcount; + gpr_cv *cv; + struct pollfd *fds; + nfds_t nfds; + int timeout; + int retval; + int err; + status_t status; +} poll_args; + +cv_fd_table g_cvfds; + /******************************************************************************* * fd_posix.c */ @@ -1235,11 +1259,211 @@ static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, gpr_mu_unlock(&pollset_set->mu); } +/******************************************************************************* + * Condition Variable polling extensions + */ + +static void decref_poll_args(poll_args *args) { + if (gpr_unref(&args->refcount)) { + gpr_free(args->fds); + gpr_cv_destroy(args->cv); + gpr_free(args->cv); + gpr_free(args); + } +} + +// Poll in a background thread +static void run_poll(void *arg) { + int timeout, retval; + poll_args *pargs = (poll_args *)arg; + while (pargs->status == INPROGRESS) { + if (pargs->timeout < 0) { + timeout = CV_POLL_PERIOD_MS; + } else { + timeout = GPR_MIN(CV_POLL_PERIOD_MS, pargs->timeout); + pargs->timeout -= timeout; + } + retval = g_cvfds.poll(pargs->fds, pargs->nfds, timeout); + if (retval != 0 || pargs->timeout == 0) { + pargs->retval = retval; + pargs->err = errno; + break; + } + } + gpr_mu_lock(&g_cvfds.mu); + if (pargs->status == INPROGRESS) { + // Signal main thread that the poll completed + pargs->status = COMPLETED; + gpr_cv_signal(pargs->cv); + } + decref_poll_args(pargs); + g_cvfds.pollcount--; + if (g_cvfds.shutdown && g_cvfds.pollcount == 0) { + gpr_cv_signal(&g_cvfds.shutdown_complete); + } + gpr_mu_unlock(&g_cvfds.mu); +} + +// This function overrides poll() to handle condition variable wakeup fds +static int cvfd_poll(struct pollfd *fds, nfds_t nfds, int timeout) { + unsigned int i; + int res, idx; + gpr_cv *pollcv; + cv_node *cvn, *prev; + nfds_t nsockfds = 0; + gpr_thd_id t_id; + gpr_thd_options opt; + poll_args *pargs = NULL; + gpr_mu_lock(&g_cvfds.mu); + pollcv = gpr_malloc(sizeof(gpr_cv)); + gpr_cv_init(pollcv); + for (i = 0; i < nfds; i++) { + fds[i].revents = 0; + if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { + idx = FD_TO_IDX(fds[i].fd); + cvn = gpr_malloc(sizeof(cv_node)); + cvn->cv = pollcv; + cvn->next = g_cvfds.cvfds[idx].cvs; + g_cvfds.cvfds[idx].cvs = cvn; + // We should return immediately if there are pending events, + // but we still need to call poll() to check for socket events + if (g_cvfds.cvfds[idx].is_set) { + timeout = 0; + } + } else if (fds[i].fd >= 0) { + nsockfds++; + } + } + + if (nsockfds > 0) { + pargs = gpr_malloc(sizeof(struct poll_args)); + // Both the main thread and calling thread get a reference + gpr_ref_init(&pargs->refcount, 2); + pargs->cv = pollcv; + pargs->fds = gpr_malloc(sizeof(struct pollfd) * nsockfds); + pargs->nfds = nsockfds; + pargs->timeout = timeout; + pargs->retval = 0; + pargs->err = 0; + pargs->status = INPROGRESS; + idx = 0; + for (i = 0; i < nfds; i++) { + if (fds[i].fd >= 0) { + pargs->fds[idx].fd = fds[i].fd; + pargs->fds[idx].events = fds[i].events; + pargs->fds[idx].revents = 0; + idx++; + } + } + g_cvfds.pollcount++; + opt = gpr_thd_options_default(); + gpr_thd_options_set_detached(&opt); + gpr_thd_new(&t_id, &run_poll, pargs, &opt); + // We want the poll() thread to trigger the deadline, so wait forever here + gpr_cv_wait(pollcv, &g_cvfds.mu, gpr_inf_future(GPR_CLOCK_MONOTONIC)); + if (pargs->status == COMPLETED) { + res = pargs->retval; + errno = pargs->err; + } else { + res = 0; + errno = 0; + pargs->status = CANCELLED; + } + } else { + gpr_timespec deadline = gpr_now(GPR_CLOCK_REALTIME); + deadline = + gpr_time_add(deadline, gpr_time_from_millis(timeout, GPR_TIMESPAN)); + gpr_cv_wait(pollcv, &g_cvfds.mu, deadline); + res = 0; + } + + idx = 0; + for (i = 0; i < nfds; i++) { + if (fds[i].fd < 0 && (fds[i].events & POLLIN)) { + cvn = g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs; + prev = NULL; + while (cvn->cv != pollcv) { + prev = cvn; + cvn = cvn->next; + GPR_ASSERT(cvn); + } + if (!prev) { + g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].cvs = cvn->next; + } else { + prev->next = cvn->next; + } + gpr_free(cvn); + + if (g_cvfds.cvfds[FD_TO_IDX(fds[i].fd)].is_set) { + fds[i].revents = POLLIN; + if (res >= 0) res++; + } + } else if (fds[i].fd >= 0 && pargs->status == COMPLETED) { + fds[i].revents = pargs->fds[idx].revents; + idx++; + } + } + + if (pargs) { + decref_poll_args(pargs); + } else { + gpr_cv_destroy(pollcv); + gpr_free(pollcv); + } + gpr_mu_unlock(&g_cvfds.mu); + + return res; +} + +static void global_cv_fd_table_init() { + gpr_mu_init(&g_cvfds.mu); + gpr_mu_lock(&g_cvfds.mu); + gpr_cv_init(&g_cvfds.shutdown_complete); + g_cvfds.shutdown = 0; + g_cvfds.pollcount = 0; + g_cvfds.size = CV_DEFAULT_TABLE_SIZE; + g_cvfds.cvfds = gpr_malloc(sizeof(fd_node) * CV_DEFAULT_TABLE_SIZE); + g_cvfds.free_fds = NULL; + for (int i = 0; i < CV_DEFAULT_TABLE_SIZE; i++) { + g_cvfds.cvfds[i].is_set = 0; + g_cvfds.cvfds[i].cvs = NULL; + g_cvfds.cvfds[i].next_free = g_cvfds.free_fds; + g_cvfds.free_fds = &g_cvfds.cvfds[i]; + } + // Override the poll function with one that supports cvfds + g_cvfds.poll = grpc_poll_function; + grpc_poll_function = &cvfd_poll; + gpr_mu_unlock(&g_cvfds.mu); +} + +static void global_cv_fd_table_shutdown() { + gpr_mu_lock(&g_cvfds.mu); + g_cvfds.shutdown = 1; + // Attempt to wait for all abandoned poll() threads to terminate + // Not doing so will result in reported memory leaks + if (g_cvfds.pollcount > 0) { + int res = gpr_cv_wait(&g_cvfds.shutdown_complete, &g_cvfds.mu, + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(3, GPR_TIMESPAN))); + GPR_ASSERT(res == 0); + } + gpr_cv_destroy(&g_cvfds.shutdown_complete); + grpc_poll_function = g_cvfds.poll; + gpr_free(g_cvfds.cvfds); + gpr_mu_unlock(&g_cvfds.mu); + gpr_mu_destroy(&g_cvfds.mu); +} + /******************************************************************************* * event engine binding */ -static void shutdown_engine(void) { pollset_global_shutdown(); } +static void shutdown_engine(void) { + pollset_global_shutdown(); + if (grpc_cv_wakeup_fds_enabled()) { + global_cv_fd_table_shutdown(); + } +} static const grpc_event_engine_vtable vtable = { .pollset_size = sizeof(grpc_pollset), @@ -1286,4 +1510,15 @@ const grpc_event_engine_vtable *grpc_init_poll_posix(void) { return &vtable; } +const grpc_event_engine_vtable *grpc_init_poll_cv_posix(void) { + global_cv_fd_table_init(); + grpc_enable_cv_wakeup_fds(1); + if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { + global_cv_fd_table_shutdown(); + grpc_enable_cv_wakeup_fds(0); + return NULL; + } + return &vtable; +} + #endif diff --git a/src/core/lib/iomgr/ev_poll_posix.h b/src/core/lib/iomgr/ev_poll_posix.h index 291736a2db..202ffca14c 100644 --- a/src/core/lib/iomgr/ev_poll_posix.h +++ b/src/core/lib/iomgr/ev_poll_posix.h @@ -37,5 +37,6 @@ #include "src/core/lib/iomgr/ev_posix.h" const grpc_event_engine_vtable *grpc_init_poll_posix(void); +const grpc_event_engine_vtable *grpc_init_poll_cv_posix(void); #endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H */ diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c index 2fc8ccfa91..0637f80421 100644 --- a/src/core/lib/iomgr/ev_posix.c +++ b/src/core/lib/iomgr/ev_posix.c @@ -46,7 +46,6 @@ #include "src/core/lib/iomgr/ev_epoll_linux.h" #include "src/core/lib/iomgr/ev_poll_and_epoll_posix.h" -#include "src/core/lib/iomgr/ev_poll_cv_posix.h" #include "src/core/lib/iomgr/ev_poll_posix.h" #include "src/core/lib/support/env.h" diff --git a/src/core/lib/iomgr/wakeup_fd_cv.c b/src/core/lib/iomgr/wakeup_fd_cv.c index 651e2f663d..b4165208ed 100644 --- a/src/core/lib/iomgr/wakeup_fd_cv.c +++ b/src/core/lib/iomgr/wakeup_fd_cv.c @@ -35,6 +35,8 @@ #ifdef GPR_POSIX_WAKEUP_FD +#include "src/core/lib/iomgr/wakeup_fd_cv.h" + #include #include @@ -45,8 +47,6 @@ #include #include -#include "src/core/lib/iomgr/ev_poll_cv_posix.h" - #define MAX_TABLE_RESIZE 256 extern cv_fd_table g_cvfds; diff --git a/src/core/lib/iomgr/wakeup_fd_cv.h b/src/core/lib/iomgr/wakeup_fd_cv.h index e57fc28363..ac16be1750 100644 --- a/src/core/lib/iomgr/wakeup_fd_cv.h +++ b/src/core/lib/iomgr/wakeup_fd_cv.h @@ -48,8 +48,33 @@ #ifndef GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H #define GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H -#include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include -extern grpc_wakeup_fd_vtable grpc_cv_wakeup_fd_vtable; +#include "src/core/lib/iomgr/ev_posix.h" + +#define FD_TO_IDX(fd) (-(fd)-1) +#define IDX_TO_FD(idx) (-(idx)-1) + +typedef struct cv_node { + gpr_cv* cv; + struct cv_node* next; +} cv_node; + +typedef struct fd_node { + int is_set; + cv_node* cvs; + struct fd_node* next_free; +} fd_node; + +typedef struct cv_fd_table { + gpr_mu mu; + int pollcount; + int shutdown; + gpr_cv shutdown_complete; + fd_node* cvfds; + fd_node* free_fds; + unsigned int size; + grpc_poll_function_type poll; +} cv_fd_table; #endif /* GRPC_CORE_LIB_IOMGR_WAKEUP_FD_CV_H */ diff --git a/src/core/lib/iomgr/wakeup_fd_posix.c b/src/core/lib/iomgr/wakeup_fd_posix.c index f75ae78c22..5c894bef37 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.c +++ b/src/core/lib/iomgr/wakeup_fd_posix.c @@ -40,12 +40,14 @@ #include "src/core/lib/iomgr/wakeup_fd_pipe.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" +extern grpc_wakeup_fd_vtable grpc_cv_wakeup_fd_vtable; static const grpc_wakeup_fd_vtable *wakeup_fd_vtable = NULL; int grpc_allow_specialized_wakeup_fd = 1; int grpc_allow_pipe_wakeup_fd = 1; -int grpc_has_real_wakeup_fd = 1; -int grpc_cv_wakeup_fds_enabled = 0; + +int has_real_wakeup_fd = 1; +int cv_wakeup_fds_enabled = 0; void grpc_wakeup_fd_global_init(void) { if (grpc_allow_specialized_wakeup_fd && @@ -55,43 +57,41 @@ void grpc_wakeup_fd_global_init(void) { grpc_pipe_wakeup_fd_vtable.check_availability()) { wakeup_fd_vtable = &grpc_pipe_wakeup_fd_vtable; } else { - grpc_has_real_wakeup_fd = 0; + has_real_wakeup_fd = 0; } } void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = NULL; } -int grpc_has_wakeup_fd(void) { - return grpc_has_real_wakeup_fd || grpc_cv_wakeup_fds_enabled; -} +int grpc_has_wakeup_fd(void) { return has_real_wakeup_fd; } -void grpc_enable_cv_wakeup_fds(int enable) { - grpc_cv_wakeup_fds_enabled = enable; -} +int grpc_cv_wakeup_fds_enabled(void) { return cv_wakeup_fds_enabled; } + +void grpc_enable_cv_wakeup_fds(int enable) { cv_wakeup_fds_enabled = enable; } grpc_error *grpc_wakeup_fd_init(grpc_wakeup_fd *fd_info) { - if (grpc_cv_wakeup_fds_enabled) { + if (cv_wakeup_fds_enabled) { return grpc_cv_wakeup_fd_vtable.init(fd_info); } return wakeup_fd_vtable->init(fd_info); } grpc_error *grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd *fd_info) { - if (grpc_cv_wakeup_fds_enabled) { + if (cv_wakeup_fds_enabled) { return grpc_cv_wakeup_fd_vtable.consume(fd_info); } return wakeup_fd_vtable->consume(fd_info); } grpc_error *grpc_wakeup_fd_wakeup(grpc_wakeup_fd *fd_info) { - if (grpc_cv_wakeup_fds_enabled) { + if (cv_wakeup_fds_enabled) { return grpc_cv_wakeup_fd_vtable.wakeup(fd_info); } return wakeup_fd_vtable->wakeup(fd_info); } void grpc_wakeup_fd_destroy(grpc_wakeup_fd *fd_info) { - if (grpc_cv_wakeup_fds_enabled) { + if (cv_wakeup_fds_enabled) { grpc_cv_wakeup_fd_vtable.destroy(fd_info); } else { wakeup_fd_vtable->destroy(fd_info); diff --git a/src/core/lib/iomgr/wakeup_fd_posix.h b/src/core/lib/iomgr/wakeup_fd_posix.h index 243c452751..71d32d97ba 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.h +++ b/src/core/lib/iomgr/wakeup_fd_posix.h @@ -72,6 +72,7 @@ void grpc_wakeup_fd_global_destroy(void); void grpc_wakeup_fd_global_init_force_fallback(void); int grpc_has_wakeup_fd(void); +int grpc_cv_wakeup_fds_enabled(void); void grpc_enable_cv_wakeup_fds(int enable); typedef struct grpc_wakeup_fd grpc_wakeup_fd; @@ -92,7 +93,6 @@ struct grpc_wakeup_fd { extern int grpc_allow_specialized_wakeup_fd; extern int grpc_allow_pipe_wakeup_fd; -extern int grpc_has_real_wakeup_fd; #define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd) diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 62d9729e13..98974878fc 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -102,7 +102,6 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/error.c', 'src/core/lib/iomgr/ev_epoll_linux.c', 'src/core/lib/iomgr/ev_poll_and_epoll_posix.c', - 'src/core/lib/iomgr/ev_poll_cv_posix.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1ec177cdf3..0c92e270c8 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -810,7 +810,6 @@ src/core/lib/iomgr/endpoint_pair.h \ src/core/lib/iomgr/error.h \ src/core/lib/iomgr/ev_epoll_linux.h \ src/core/lib/iomgr/ev_poll_and_epoll_posix.h \ -src/core/lib/iomgr/ev_poll_cv_posix.h \ src/core/lib/iomgr/ev_poll_posix.h \ src/core/lib/iomgr/ev_posix.h \ src/core/lib/iomgr/exec_ctx.h \ @@ -977,7 +976,6 @@ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/ev_epoll_linux.c \ src/core/lib/iomgr/ev_poll_and_epoll_posix.c \ -src/core/lib/iomgr/ev_poll_cv_posix.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 35b21d4e20..c9ded1ff58 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -6391,7 +6391,6 @@ "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", - "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -6512,8 +6511,6 @@ "src/core/lib/iomgr/ev_epoll_linux.h", "src/core/lib/iomgr/ev_poll_and_epoll_posix.c", "src/core/lib/iomgr/ev_poll_and_epoll_posix.h", - "src/core/lib/iomgr/ev_poll_cv_posix.c", - "src/core/lib/iomgr/ev_poll_cv_posix.h", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.c", diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 7d5e0ee56f..4a62af0276 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -319,7 +319,6 @@ - @@ -513,8 +512,6 @@ - - diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 72bf449c3e..dacdcd7608 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -76,9 +76,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr @@ -746,9 +743,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index 44cbe8bf0c..cb5963d0e8 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -212,7 +212,6 @@ - @@ -361,8 +360,6 @@ - - diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 57466022f4..362284339f 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -130,9 +130,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr @@ -533,9 +530,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index aa47cc800d..b7b72a05df 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -309,7 +309,6 @@ - @@ -481,8 +480,6 @@ - - diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 4706c90af2..ca32c0b4b4 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -79,9 +79,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr @@ -656,9 +653,6 @@ src\core\lib\iomgr - - src\core\lib\iomgr - src\core\lib\iomgr -- cgit v1.2.3 From b97cbd7acc3107f8cbd5fcf2d07ad48e1431513b Mon Sep 17 00:00:00 2001 From: Ken Payson Date: Thu, 13 Oct 2016 15:06:01 -0700 Subject: Use atomics for poll status to prevent tsan race complaints --- src/core/lib/iomgr/ev_poll_posix.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/core/lib') diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c index d9e5255ddc..f137e4dacc 100644 --- a/src/core/lib/iomgr/ev_poll_posix.c +++ b/src/core/lib/iomgr/ev_poll_posix.c @@ -254,7 +254,7 @@ struct grpc_pollset_set { #define CV_POLL_PERIOD_MS 1000 #define CV_DEFAULT_TABLE_SIZE 16 -typedef enum status_t { INPROGRESS, COMPLETED, CANCELLED } status_t; +typedef enum poll_status_t { INPROGRESS, COMPLETED, CANCELLED } poll_status_t; typedef struct poll_args { gpr_refcount refcount; @@ -264,7 +264,7 @@ typedef struct poll_args { int timeout; int retval; int err; - status_t status; + gpr_atm status; } poll_args; cv_fd_table g_cvfds; @@ -1276,7 +1276,7 @@ static void decref_poll_args(poll_args *args) { static void run_poll(void *arg) { int timeout, retval; poll_args *pargs = (poll_args *)arg; - while (pargs->status == INPROGRESS) { + while (gpr_atm_no_barrier_load(&pargs->status) == INPROGRESS) { if (pargs->timeout < 0) { timeout = CV_POLL_PERIOD_MS; } else { @@ -1291,9 +1291,9 @@ static void run_poll(void *arg) { } } gpr_mu_lock(&g_cvfds.mu); - if (pargs->status == INPROGRESS) { + if (gpr_atm_no_barrier_load(&pargs->status) == INPROGRESS) { // Signal main thread that the poll completed - pargs->status = COMPLETED; + gpr_atm_no_barrier_store(&pargs->status, COMPLETED); gpr_cv_signal(pargs->cv); } decref_poll_args(pargs); @@ -1345,7 +1345,7 @@ static int cvfd_poll(struct pollfd *fds, nfds_t nfds, int timeout) { pargs->timeout = timeout; pargs->retval = 0; pargs->err = 0; - pargs->status = INPROGRESS; + gpr_atm_no_barrier_store(&pargs->status, INPROGRESS); idx = 0; for (i = 0; i < nfds; i++) { if (fds[i].fd >= 0) { @@ -1361,13 +1361,13 @@ static int cvfd_poll(struct pollfd *fds, nfds_t nfds, int timeout) { gpr_thd_new(&t_id, &run_poll, pargs, &opt); // We want the poll() thread to trigger the deadline, so wait forever here gpr_cv_wait(pollcv, &g_cvfds.mu, gpr_inf_future(GPR_CLOCK_MONOTONIC)); - if (pargs->status == COMPLETED) { + if (gpr_atm_no_barrier_load(&pargs->status) == COMPLETED) { res = pargs->retval; errno = pargs->err; } else { res = 0; errno = 0; - pargs->status = CANCELLED; + gpr_atm_no_barrier_store(&pargs->status, CANCELLED); } } else { gpr_timespec deadline = gpr_now(GPR_CLOCK_REALTIME); @@ -1398,7 +1398,8 @@ static int cvfd_poll(struct pollfd *fds, nfds_t nfds, int timeout) { fds[i].revents = POLLIN; if (res >= 0) res++; } - } else if (fds[i].fd >= 0 && pargs->status == COMPLETED) { + } else if (fds[i].fd >= 0 && + gpr_atm_no_barrier_load(&pargs->status) == COMPLETED) { fds[i].revents = pargs->fds[idx].revents; idx++; } -- cgit v1.2.3