grpc 1.3.4 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Makefile +581 -450
- data/include/grpc/census.h +49 -49
- data/include/grpc/grpc.h +16 -70
- data/include/grpc/grpc_security.h +59 -59
- data/include/grpc/grpc_security_constants.h +9 -9
- data/include/grpc/impl/codegen/atm.h +1 -1
- data/include/grpc/impl/codegen/atm_windows.h +4 -4
- data/include/grpc/impl/codegen/byte_buffer_reader.h +2 -2
- data/include/grpc/impl/codegen/compression_types.h +4 -5
- data/include/grpc/impl/codegen/gpr_slice.h +5 -5
- data/include/grpc/impl/codegen/gpr_types.h +6 -7
- data/include/grpc/impl/codegen/grpc_types.h +128 -59
- data/include/grpc/impl/codegen/port_platform.h +6 -0
- data/include/grpc/impl/codegen/propagation_bits.h +2 -2
- data/include/grpc/impl/codegen/slice.h +13 -12
- data/include/grpc/impl/codegen/status.h +23 -18
- data/include/grpc/impl/codegen/sync.h +1 -1
- data/include/grpc/load_reporting.h +6 -6
- data/include/grpc/slice.h +47 -25
- data/include/grpc/slice_buffer.h +18 -14
- data/include/grpc/support/alloc.h +7 -7
- data/include/grpc/support/cmdline.h +10 -10
- data/include/grpc/support/cpu.h +3 -3
- data/include/grpc/support/histogram.h +1 -1
- data/include/grpc/support/host_port.h +2 -2
- data/include/grpc/support/log.h +9 -9
- data/include/grpc/support/log_windows.h +1 -1
- data/include/grpc/support/string_util.h +3 -3
- data/include/grpc/support/subprocess.h +3 -3
- data/include/grpc/support/sync.h +31 -31
- data/include/grpc/support/thd.h +11 -11
- data/include/grpc/support/time.h +12 -12
- data/include/grpc/support/tls.h +1 -1
- data/include/grpc/support/tls_gcc.h +2 -2
- data/include/grpc/support/tls_msvc.h +1 -1
- data/include/grpc/support/tls_pthread.h +1 -1
- data/include/grpc/support/useful.h +2 -2
- data/include/grpc/support/workaround_list.h +46 -0
- data/src/core/ext/census/context.c +1 -1
- data/src/core/ext/census/intrusive_hash_map.c +319 -0
- data/src/core/ext/census/intrusive_hash_map.h +167 -0
- data/src/core/ext/census/intrusive_hash_map_internal.h +63 -0
- data/src/core/ext/census/resource.c +3 -1
- data/src/core/ext/filters/client_channel/channel_connectivity.c +1 -1
- data/src/core/ext/filters/client_channel/client_channel.c +173 -103
- data/src/core/ext/filters/client_channel/client_channel_plugin.c +3 -2
- data/src/core/ext/filters/client_channel/lb_policy.c +2 -1
- data/src/core/ext/filters/client_channel/lb_policy.h +8 -7
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c +153 -0
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h +42 -0
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c +405 -102
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c +133 -0
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +65 -0
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c +90 -51
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +7 -1
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +19 -8
- data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +63 -34
- data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c +2 -1
- data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c +188 -294
- data/src/core/ext/filters/client_channel/lb_policy_factory.c +28 -5
- data/src/core/ext/filters/client_channel/lb_policy_factory.h +18 -4
- data/src/core/ext/filters/client_channel/parse_address.c +90 -59
- data/src/core/ext/filters/client_channel/parse_address.h +17 -8
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c +11 -7
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c +59 -14
- data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +6 -0
- data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c +3 -3
- data/src/core/ext/filters/client_channel/subchannel.c +20 -17
- data/src/core/ext/filters/client_channel/subchannel.h +1 -0
- data/src/core/ext/filters/client_channel/subchannel_index.c +11 -1
- data/src/core/ext/filters/client_channel/uri_parser.c +36 -22
- data/src/core/ext/filters/client_channel/uri_parser.h +1 -1
- data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.c +42 -17
- data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.h +8 -9
- data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.c +19 -11
- data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.h +3 -6
- data/src/core/ext/filters/http/http_filters_plugin.c +104 -0
- data/src/core/{lib/channel/compress_filter.c → ext/filters/http/message_compress/message_compress_filter.c} +124 -23
- data/src/core/{lib/channel/compress_filter.h → ext/filters/http/message_compress/message_compress_filter.h} +5 -6
- data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.c +4 -6
- data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.h +3 -3
- data/src/core/ext/filters/load_reporting/load_reporting.c +2 -25
- data/src/core/ext/filters/load_reporting/load_reporting_filter.c +26 -1
- data/src/core/ext/filters/max_age/max_age_filter.c +14 -14
- data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.c +91 -47
- data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.h +3 -3
- data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.c +223 -0
- data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h +40 -0
- data/src/core/ext/filters/workarounds/workaround_utils.c +65 -0
- data/src/core/ext/filters/workarounds/workaround_utils.h +52 -0
- data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +1 -1
- data/src/core/ext/transport/chttp2/server/chttp2_server.c +3 -2
- data/src/core/ext/transport/chttp2/transport/bin_decoder.c +2 -2
- data/src/core/ext/transport/chttp2/transport/bin_encoder.c +3 -3
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +319 -175
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +3 -2
- data/src/core/ext/transport/chttp2/transport/frame_data.c +203 -164
- data/src/core/ext/transport/chttp2/transport/frame_data.h +8 -14
- data/src/core/ext/transport/chttp2/transport/frame_goaway.c +1 -1
- data/src/core/ext/transport/chttp2/transport/frame_ping.c +1 -1
- data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +1 -1
- data/src/core/ext/transport/chttp2/transport/frame_settings.c +5 -5
- data/src/core/ext/transport/chttp2/transport/frame_window_update.c +1 -1
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +4 -4
- data/src/core/ext/transport/chttp2/transport/hpack_parser.c +2 -4
- data/src/core/ext/transport/chttp2/transport/hpack_table.c +4 -3
- data/src/core/ext/transport/chttp2/transport/internal.h +50 -33
- data/src/core/ext/transport/chttp2/transport/parsing.c +10 -11
- data/src/core/ext/transport/chttp2/transport/writing.c +32 -13
- data/src/core/lib/channel/channel_args.c +30 -9
- data/src/core/lib/channel/channel_args.h +5 -1
- data/src/core/lib/channel/channel_stack.c +1 -1
- data/src/core/lib/channel/channel_stack.h +2 -2
- data/src/core/lib/channel/channel_stack_builder.c +13 -1
- data/src/core/lib/channel/channel_stack_builder.h +5 -1
- data/src/core/lib/channel/connected_channel.c +3 -1
- data/src/core/lib/channel/context.h +2 -2
- data/src/core/lib/compression/message_compress.c +2 -2
- data/src/core/lib/debug/trace.c +13 -6
- data/src/core/lib/debug/trace.h +27 -1
- data/src/core/lib/http/httpcli.c +1 -1
- data/src/core/lib/http/httpcli_security_connector.c +9 -11
- data/src/core/lib/http/parser.c +2 -2
- data/src/core/lib/http/parser.h +2 -1
- data/src/core/lib/iomgr/combiner.c +6 -6
- data/src/core/lib/iomgr/combiner.h +2 -1
- data/src/core/lib/iomgr/error.c +12 -5
- data/src/core/lib/iomgr/error.h +13 -13
- data/src/core/lib/iomgr/ev_epoll1_linux.c +984 -0
- data/src/core/lib/iomgr/ev_epoll1_linux.h +44 -0
- data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c +2146 -0
- data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h +43 -0
- data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c +1337 -0
- data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.h +43 -0
- data/src/core/lib/iomgr/ev_epollex_linux.c +1511 -0
- data/src/core/lib/iomgr/ev_epollex_linux.h +43 -0
- data/src/core/lib/iomgr/{ev_epoll_linux.c → ev_epollsig_linux.c} +41 -33
- data/src/core/lib/iomgr/{ev_epoll_linux.h → ev_epollsig_linux.h} +4 -4
- data/src/core/lib/iomgr/ev_poll_posix.c +12 -27
- data/src/core/lib/iomgr/ev_poll_posix.h +2 -2
- data/src/core/lib/iomgr/ev_posix.c +22 -8
- data/src/core/lib/iomgr/ev_posix.h +4 -3
- data/src/core/lib/iomgr/ev_windows.c +43 -0
- data/src/core/lib/iomgr/exec_ctx.c +5 -0
- data/src/core/lib/iomgr/exec_ctx.h +2 -0
- data/src/core/lib/iomgr/iomgr.c +4 -0
- data/src/core/lib/iomgr/iomgr.h +3 -0
- data/src/core/lib/iomgr/is_epollexclusive_available.c +116 -0
- data/src/core/lib/iomgr/is_epollexclusive_available.h +41 -0
- data/src/core/lib/iomgr/lockfree_event.c +16 -0
- data/src/core/lib/iomgr/pollset.h +2 -5
- data/src/core/lib/iomgr/pollset_uv.c +1 -1
- data/src/core/lib/iomgr/pollset_windows.c +3 -3
- data/src/core/lib/iomgr/resource_quota.c +9 -8
- data/src/core/lib/iomgr/resource_quota.h +2 -1
- data/src/core/lib/iomgr/sockaddr_utils.h +1 -1
- data/src/core/lib/iomgr/socket_mutator.h +2 -0
- data/src/core/lib/iomgr/sys_epoll_wrapper.h +43 -0
- data/src/core/lib/iomgr/tcp_client_posix.c +6 -6
- data/src/core/lib/iomgr/tcp_client_uv.c +3 -3
- data/src/core/lib/iomgr/tcp_posix.c +7 -7
- data/src/core/lib/iomgr/tcp_posix.h +2 -1
- data/src/core/lib/iomgr/tcp_server_posix.c +1 -1
- data/src/core/lib/iomgr/tcp_uv.c +6 -6
- data/src/core/lib/iomgr/tcp_uv.h +2 -1
- data/src/core/lib/iomgr/tcp_windows.c +1 -1
- data/src/core/lib/iomgr/timer_generic.c +24 -25
- data/src/core/lib/iomgr/timer_manager.c +276 -0
- data/src/core/lib/iomgr/timer_manager.h +52 -0
- data/src/core/lib/iomgr/timer_uv.c +6 -0
- data/src/core/lib/iomgr/udp_server.c +42 -9
- data/src/core/lib/iomgr/udp_server.h +3 -1
- data/src/core/lib/security/credentials/credentials.c +0 -1
- data/src/core/lib/security/credentials/fake/fake_credentials.c +23 -0
- data/src/core/lib/security/credentials/fake/fake_credentials.h +12 -9
- data/src/core/lib/security/credentials/google_default/google_default_credentials.c +1 -1
- data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -1
- data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +1 -1
- data/src/core/lib/security/credentials/ssl/ssl_credentials.c +24 -53
- data/src/core/lib/security/transport/client_auth_filter.c +9 -3
- data/src/core/lib/security/transport/secure_endpoint.c +7 -7
- data/src/core/lib/security/transport/secure_endpoint.h +1 -1
- data/src/core/lib/security/transport/security_connector.c +45 -57
- data/src/core/lib/security/transport/security_connector.h +10 -14
- data/src/core/lib/security/transport/security_handshaker.c +123 -97
- data/src/core/lib/slice/b64.c +1 -1
- data/src/core/lib/slice/percent_encoding.c +3 -3
- data/src/core/lib/slice/slice.c +66 -33
- data/src/core/lib/slice/slice_buffer.c +25 -6
- data/src/core/lib/slice/slice_hash_table.c +33 -35
- data/src/core/lib/slice/slice_hash_table.h +7 -12
- data/src/core/lib/support/atomic.h +45 -0
- data/src/core/lib/support/atomic_with_atm.h +70 -0
- data/src/core/lib/support/atomic_with_std.h +48 -0
- data/src/core/lib/support/avl.c +14 -14
- data/src/core/lib/support/cmdline.c +3 -3
- data/src/core/lib/support/histogram.c +2 -2
- data/src/core/lib/support/host_port.c +1 -1
- data/src/core/lib/support/memory.h +74 -0
- data/src/core/lib/support/mpscq.c +36 -2
- data/src/core/lib/support/mpscq.h +28 -1
- data/src/core/lib/support/stack_lockfree.c +3 -36
- data/src/core/lib/support/string.c +12 -12
- data/src/core/lib/support/string_posix.c +1 -1
- data/src/core/lib/support/subprocess_posix.c +2 -2
- data/src/core/lib/support/thd_posix.c +1 -1
- data/src/core/lib/support/time_posix.c +8 -0
- data/src/core/lib/support/tmpfile_posix.c +10 -10
- data/src/core/lib/surface/alarm.c +3 -1
- data/src/core/lib/surface/api_trace.c +2 -1
- data/src/core/lib/surface/api_trace.h +2 -2
- data/src/core/lib/surface/byte_buffer_reader.c +1 -1
- data/src/core/lib/surface/call.c +65 -22
- data/src/core/lib/surface/call.h +4 -2
- data/src/core/lib/surface/channel_init.c +2 -19
- data/src/core/lib/surface/channel_stack_type.c +18 -0
- data/src/core/lib/surface/channel_stack_type.h +2 -0
- data/src/core/lib/surface/completion_queue.c +694 -247
- data/src/core/lib/surface/completion_queue.h +30 -13
- data/src/core/lib/surface/completion_queue_factory.c +24 -9
- data/src/core/lib/surface/init.c +1 -52
- data/src/core/lib/surface/{lame_client.c → lame_client.cc} +37 -26
- data/src/core/lib/surface/server.c +79 -110
- data/src/core/lib/surface/server.h +2 -1
- data/src/core/lib/surface/version.c +2 -2
- data/src/core/lib/transport/bdp_estimator.c +25 -9
- data/src/core/lib/transport/bdp_estimator.h +7 -1
- data/src/core/lib/transport/byte_stream.c +23 -9
- data/src/core/lib/transport/byte_stream.h +15 -6
- data/src/core/lib/transport/connectivity_state.c +6 -6
- data/src/core/lib/transport/connectivity_state.h +2 -1
- data/src/core/lib/transport/service_config.c +6 -13
- data/src/core/lib/transport/service_config.h +2 -2
- data/src/core/lib/transport/static_metadata.c +403 -389
- data/src/core/lib/transport/static_metadata.h +127 -114
- data/src/core/plugin_registry/grpc_plugin_registry.c +16 -0
- data/src/core/tsi/fake_transport_security.c +5 -4
- data/src/core/tsi/ssl_transport_security.c +71 -82
- data/src/core/tsi/ssl_transport_security.h +39 -61
- data/src/core/tsi/transport_security.c +83 -2
- data/src/core/tsi/transport_security.h +27 -2
- data/src/core/tsi/transport_security_adapter.c +236 -0
- data/src/core/tsi/transport_security_adapter.h +62 -0
- data/src/core/tsi/transport_security_interface.h +179 -66
- data/src/ruby/ext/grpc/extconf.rb +2 -1
- data/src/ruby/ext/grpc/rb_byte_buffer.c +8 -6
- data/src/ruby/ext/grpc/rb_call.c +56 -48
- data/src/ruby/ext/grpc/rb_call.h +3 -4
- data/src/ruby/ext/grpc/rb_call_credentials.c +23 -22
- data/src/ruby/ext/grpc/rb_channel.c +2 -3
- data/src/ruby/ext/grpc/rb_channel_args.c +11 -9
- data/src/ruby/ext/grpc/rb_channel_credentials.c +16 -12
- data/src/ruby/ext/grpc/rb_completion_queue.c +7 -9
- data/src/ruby/ext/grpc/rb_compression_options.c +7 -6
- data/src/ruby/ext/grpc/rb_event_thread.c +10 -12
- data/src/ruby/ext/grpc/rb_event_thread.h +1 -2
- data/src/ruby/ext/grpc/rb_grpc.c +11 -15
- data/src/ruby/ext/grpc/rb_grpc.h +2 -2
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +16 -6
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +25 -10
- data/src/ruby/ext/grpc/rb_server.c +26 -28
- data/src/ruby/lib/grpc/grpc.rb +1 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/third_party/cares/config_linux/ares_config.h +36 -2
- data/third_party/zlib/adler32.c +14 -7
- data/third_party/zlib/compress.c +24 -18
- data/third_party/zlib/crc32.c +29 -12
- data/third_party/zlib/deflate.c +499 -303
- data/third_party/zlib/deflate.h +19 -16
- data/third_party/zlib/gzguts.h +16 -7
- data/third_party/zlib/gzlib.c +17 -14
- data/third_party/zlib/gzread.c +108 -48
- data/third_party/zlib/gzwrite.c +210 -122
- data/third_party/zlib/infback.c +2 -2
- data/third_party/zlib/inffast.c +34 -51
- data/third_party/zlib/inflate.c +86 -37
- data/third_party/zlib/inflate.h +7 -4
- data/third_party/zlib/inftrees.c +12 -14
- data/third_party/zlib/trees.c +38 -61
- data/third_party/zlib/uncompr.c +66 -32
- data/third_party/zlib/zconf.h +32 -9
- data/third_party/zlib/zlib.h +298 -154
- data/third_party/zlib/zutil.c +25 -24
- data/third_party/zlib/zutil.h +35 -17
- metadata +63 -30
@@ -50,34 +50,34 @@
|
|
50
50
|
|
51
51
|
FILE *gpr_tmpfile(const char *prefix, char **tmp_filename) {
|
52
52
|
FILE *result = NULL;
|
53
|
-
char *
|
53
|
+
char *filename_template;
|
54
54
|
int fd;
|
55
55
|
|
56
56
|
if (tmp_filename != NULL) *tmp_filename = NULL;
|
57
57
|
|
58
|
-
gpr_asprintf(&
|
59
|
-
GPR_ASSERT(
|
58
|
+
gpr_asprintf(&filename_template, "/tmp/%s_XXXXXX", prefix);
|
59
|
+
GPR_ASSERT(filename_template != NULL);
|
60
60
|
|
61
|
-
fd = mkstemp(
|
61
|
+
fd = mkstemp(filename_template);
|
62
62
|
if (fd == -1) {
|
63
|
-
gpr_log(GPR_ERROR, "mkstemp failed for
|
64
|
-
|
63
|
+
gpr_log(GPR_ERROR, "mkstemp failed for filename_template %s with error %s.",
|
64
|
+
filename_template, strerror(errno));
|
65
65
|
goto end;
|
66
66
|
}
|
67
67
|
result = fdopen(fd, "w+");
|
68
68
|
if (result == NULL) {
|
69
69
|
gpr_log(GPR_ERROR, "Could not open file %s from fd %d (error = %s).",
|
70
|
-
|
71
|
-
unlink(
|
70
|
+
filename_template, fd, strerror(errno));
|
71
|
+
unlink(filename_template);
|
72
72
|
close(fd);
|
73
73
|
goto end;
|
74
74
|
}
|
75
75
|
|
76
76
|
end:
|
77
77
|
if (result != NULL && tmp_filename != NULL) {
|
78
|
-
*tmp_filename =
|
78
|
+
*tmp_filename = filename_template;
|
79
79
|
} else {
|
80
|
-
gpr_free(
|
80
|
+
gpr_free(filename_template);
|
81
81
|
}
|
82
82
|
return result;
|
83
83
|
}
|
@@ -81,7 +81,9 @@ void grpc_alarm_cancel(grpc_alarm *alarm) {
|
|
81
81
|
}
|
82
82
|
|
83
83
|
void grpc_alarm_destroy(grpc_alarm *alarm) {
|
84
|
+
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
84
85
|
grpc_alarm_cancel(alarm);
|
85
|
-
GRPC_CQ_INTERNAL_UNREF(alarm->cq, "alarm");
|
86
|
+
GRPC_CQ_INTERNAL_UNREF(&exec_ctx, alarm->cq, "alarm");
|
86
87
|
gpr_free(alarm);
|
88
|
+
grpc_exec_ctx_finish(&exec_ctx);
|
87
89
|
}
|
@@ -37,7 +37,7 @@
|
|
37
37
|
#include <grpc/support/log.h>
|
38
38
|
#include "src/core/lib/debug/trace.h"
|
39
39
|
|
40
|
-
extern
|
40
|
+
extern grpc_tracer_flag grpc_api_trace;
|
41
41
|
|
42
42
|
/* Provide unwrapping macros because we're in C89 and variadic macros weren't
|
43
43
|
introduced until C99... */
|
@@ -58,7 +58,7 @@ extern int grpc_api_trace;
|
|
58
58
|
/* Due to the limitations of C89's preprocessor, the arity of the var-arg list
|
59
59
|
'nargs' must be specified. */
|
60
60
|
#define GRPC_API_TRACE(fmt, nargs, args) \
|
61
|
-
if (grpc_api_trace) {
|
61
|
+
if (GRPC_TRACER_ON(grpc_api_trace)) { \
|
62
62
|
gpr_log(GPR_INFO, fmt GRPC_API_TRACE_UNWRAP##nargs args); \
|
63
63
|
}
|
64
64
|
|
@@ -124,7 +124,7 @@ grpc_slice grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader) {
|
|
124
124
|
grpc_slice in_slice;
|
125
125
|
size_t bytes_read = 0;
|
126
126
|
const size_t input_size = grpc_byte_buffer_length(reader->buffer_out);
|
127
|
-
grpc_slice out_slice =
|
127
|
+
grpc_slice out_slice = GRPC_SLICE_MALLOC(input_size);
|
128
128
|
uint8_t *const outbuf = GRPC_SLICE_START_PTR(out_slice); /* just an alias */
|
129
129
|
|
130
130
|
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
data/src/core/lib/surface/call.c
CHANGED
@@ -160,6 +160,7 @@ typedef struct {
|
|
160
160
|
} child_call;
|
161
161
|
|
162
162
|
struct grpc_call {
|
163
|
+
gpr_refcount ext_ref;
|
163
164
|
gpr_arena *arena;
|
164
165
|
grpc_completion_queue *cq;
|
165
166
|
grpc_polling_entity pollent;
|
@@ -170,7 +171,7 @@ struct grpc_call {
|
|
170
171
|
|
171
172
|
/* client or server call */
|
172
173
|
bool is_client;
|
173
|
-
/** has
|
174
|
+
/** has grpc_call_unref been called */
|
174
175
|
bool destroy_called;
|
175
176
|
/** flag indicating that cancellation is inherited */
|
176
177
|
bool cancellation_is_inherited;
|
@@ -243,7 +244,8 @@ struct grpc_call {
|
|
243
244
|
void *saved_receiving_stream_ready_bctlp;
|
244
245
|
};
|
245
246
|
|
246
|
-
|
247
|
+
grpc_tracer_flag grpc_call_error_trace = GRPC_TRACER_INITIALIZER(false);
|
248
|
+
grpc_tracer_flag grpc_compression_trace = GRPC_TRACER_INITIALIZER(false);
|
247
249
|
|
248
250
|
#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
|
249
251
|
#define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1)
|
@@ -282,6 +284,10 @@ static void add_init_error(grpc_error **composite, grpc_error *new) {
|
|
282
284
|
*composite = grpc_error_add_child(*composite, new);
|
283
285
|
}
|
284
286
|
|
287
|
+
void *grpc_call_arena_alloc(grpc_call *call, size_t size) {
|
288
|
+
return gpr_arena_alloc(call->arena, size);
|
289
|
+
}
|
290
|
+
|
285
291
|
static parent_call *get_or_create_parent_call(grpc_call *call) {
|
286
292
|
parent_call *p = (parent_call *)gpr_atm_acq_load(&call->parent_call_atm);
|
287
293
|
if (p == NULL) {
|
@@ -312,6 +318,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
|
|
312
318
|
gpr_arena_create(grpc_channel_get_call_size_estimate(args->channel));
|
313
319
|
call = gpr_arena_alloc(arena,
|
314
320
|
sizeof(grpc_call) + channel_stack->call_stack_size);
|
321
|
+
gpr_ref_init(&call->ext_ref, 1);
|
315
322
|
call->arena = arena;
|
316
323
|
*out_call = call;
|
317
324
|
call->channel = args->channel;
|
@@ -346,6 +353,8 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
|
|
346
353
|
gpr_timespec send_deadline =
|
347
354
|
gpr_convert_clock_type(args->send_deadline, GPR_CLOCK_MONOTONIC);
|
348
355
|
|
356
|
+
bool immediately_cancel = false;
|
357
|
+
|
349
358
|
if (args->parent_call != NULL) {
|
350
359
|
child_call *cc = call->child_call =
|
351
360
|
gpr_arena_alloc(arena, sizeof(child_call));
|
@@ -386,8 +395,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
|
|
386
395
|
if (args->propagation_mask & GRPC_PROPAGATE_CANCELLATION) {
|
387
396
|
call->cancellation_is_inherited = 1;
|
388
397
|
if (gpr_atm_acq_load(&args->parent_call->received_final_op_atm)) {
|
389
|
-
|
390
|
-
GRPC_ERROR_CANCELLED);
|
398
|
+
immediately_cancel = true;
|
391
399
|
}
|
392
400
|
}
|
393
401
|
|
@@ -407,7 +415,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
|
|
407
415
|
call->send_deadline = send_deadline;
|
408
416
|
|
409
417
|
GRPC_CHANNEL_INTERNAL_REF(args->channel, "call");
|
410
|
-
/* initial refcount dropped by
|
418
|
+
/* initial refcount dropped by grpc_call_unref */
|
411
419
|
grpc_call_element_args call_args = {
|
412
420
|
.call_stack = CALL_STACK_FROM_CALL(call),
|
413
421
|
.server_transport_data = args->server_transport_data,
|
@@ -422,6 +430,10 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
|
|
422
430
|
cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
|
423
431
|
GRPC_ERROR_REF(error));
|
424
432
|
}
|
433
|
+
if (immediately_cancel) {
|
434
|
+
cancel_with_error(exec_ctx, call, STATUS_FROM_API_OVERRIDE,
|
435
|
+
GRPC_ERROR_CANCELLED);
|
436
|
+
}
|
425
437
|
if (args->cq != NULL) {
|
426
438
|
GPR_ASSERT(
|
427
439
|
args->pollset_set_alternative == NULL &&
|
@@ -509,7 +521,7 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
|
|
509
521
|
}
|
510
522
|
}
|
511
523
|
if (c->cq) {
|
512
|
-
GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
|
524
|
+
GRPC_CQ_INTERNAL_UNREF(exec_ctx, c->cq, "bind");
|
513
525
|
}
|
514
526
|
|
515
527
|
get_final_status(call, set_status_value_directly, &c->final_info.final_status,
|
@@ -528,12 +540,16 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
|
|
528
540
|
GPR_TIMER_END("destroy_call", 0);
|
529
541
|
}
|
530
542
|
|
531
|
-
void
|
543
|
+
void grpc_call_ref(grpc_call *c) { gpr_ref(&c->ext_ref); }
|
544
|
+
|
545
|
+
void grpc_call_unref(grpc_call *c) {
|
546
|
+
if (!gpr_unref(&c->ext_ref)) return;
|
547
|
+
|
532
548
|
child_call *cc = c->child_call;
|
533
549
|
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
534
550
|
|
535
|
-
GPR_TIMER_BEGIN("
|
536
|
-
GRPC_API_TRACE("
|
551
|
+
GPR_TIMER_BEGIN("grpc_call_unref", 0);
|
552
|
+
GRPC_API_TRACE("grpc_call_unref(c=%p)", 1, (c));
|
537
553
|
|
538
554
|
if (cc) {
|
539
555
|
parent_call *pc = get_parent_call(cc->parent);
|
@@ -560,7 +576,7 @@ void grpc_call_destroy(grpc_call *c) {
|
|
560
576
|
}
|
561
577
|
GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
|
562
578
|
grpc_exec_ctx_finish(&exec_ctx);
|
563
|
-
GPR_TIMER_END("
|
579
|
+
GPR_TIMER_END("grpc_call_unref", 0);
|
564
580
|
}
|
565
581
|
|
566
582
|
grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) {
|
@@ -686,7 +702,7 @@ static void get_final_status(grpc_call *call,
|
|
686
702
|
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
|
687
703
|
status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i]));
|
688
704
|
}
|
689
|
-
if (grpc_call_error_trace) {
|
705
|
+
if (GRPC_TRACER_ON(grpc_call_error_trace)) {
|
690
706
|
gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR");
|
691
707
|
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
|
692
708
|
if (status[i].is_set) {
|
@@ -1187,6 +1203,7 @@ static void finish_batch_step(grpc_exec_ctx *exec_ctx, batch_control *bctl) {
|
|
1187
1203
|
|
1188
1204
|
static void continue_receiving_slices(grpc_exec_ctx *exec_ctx,
|
1189
1205
|
batch_control *bctl) {
|
1206
|
+
grpc_error *error;
|
1190
1207
|
grpc_call *call = bctl->call;
|
1191
1208
|
for (;;) {
|
1192
1209
|
size_t remaining = call->receiving_stream->length -
|
@@ -1198,11 +1215,22 @@ static void continue_receiving_slices(grpc_exec_ctx *exec_ctx,
|
|
1198
1215
|
finish_batch_step(exec_ctx, bctl);
|
1199
1216
|
return;
|
1200
1217
|
}
|
1201
|
-
if (grpc_byte_stream_next(exec_ctx, call->receiving_stream,
|
1202
|
-
&call->receiving_slice, remaining,
|
1218
|
+
if (grpc_byte_stream_next(exec_ctx, call->receiving_stream, remaining,
|
1203
1219
|
&call->receiving_slice_ready)) {
|
1204
|
-
|
1205
|
-
|
1220
|
+
error = grpc_byte_stream_pull(exec_ctx, call->receiving_stream,
|
1221
|
+
&call->receiving_slice);
|
1222
|
+
if (error == GRPC_ERROR_NONE) {
|
1223
|
+
grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
|
1224
|
+
call->receiving_slice);
|
1225
|
+
} else {
|
1226
|
+
grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
|
1227
|
+
call->receiving_stream = NULL;
|
1228
|
+
grpc_byte_buffer_destroy(*call->receiving_buffer);
|
1229
|
+
*call->receiving_buffer = NULL;
|
1230
|
+
call->receiving_message = 0;
|
1231
|
+
finish_batch_step(exec_ctx, bctl);
|
1232
|
+
return;
|
1233
|
+
}
|
1206
1234
|
} else {
|
1207
1235
|
return;
|
1208
1236
|
}
|
@@ -1213,20 +1241,36 @@ static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
|
|
1213
1241
|
grpc_error *error) {
|
1214
1242
|
batch_control *bctl = bctlp;
|
1215
1243
|
grpc_call *call = bctl->call;
|
1244
|
+
grpc_byte_stream *bs = call->receiving_stream;
|
1245
|
+
bool release_error = false;
|
1216
1246
|
|
1217
1247
|
if (error == GRPC_ERROR_NONE) {
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1248
|
+
grpc_slice slice;
|
1249
|
+
error = grpc_byte_stream_pull(exec_ctx, bs, &slice);
|
1250
|
+
if (error == GRPC_ERROR_NONE) {
|
1251
|
+
grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
|
1252
|
+
slice);
|
1253
|
+
continue_receiving_slices(exec_ctx, bctl);
|
1254
|
+
} else {
|
1255
|
+
/* Error returned by grpc_byte_stream_pull needs to be released manually
|
1256
|
+
*/
|
1257
|
+
release_error = true;
|
1258
|
+
}
|
1259
|
+
}
|
1260
|
+
|
1261
|
+
if (error != GRPC_ERROR_NONE) {
|
1262
|
+
if (GRPC_TRACER_ON(grpc_trace_operation_failures)) {
|
1223
1263
|
GRPC_LOG_IF_ERROR("receiving_slice_ready", GRPC_ERROR_REF(error));
|
1224
1264
|
}
|
1225
1265
|
grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
|
1226
1266
|
call->receiving_stream = NULL;
|
1227
1267
|
grpc_byte_buffer_destroy(*call->receiving_buffer);
|
1228
1268
|
*call->receiving_buffer = NULL;
|
1269
|
+
call->receiving_message = 0;
|
1229
1270
|
finish_batch_step(exec_ctx, bctl);
|
1271
|
+
if (release_error) {
|
1272
|
+
GRPC_ERROR_UNREF(error);
|
1273
|
+
}
|
1230
1274
|
}
|
1231
1275
|
}
|
1232
1276
|
|
@@ -1311,8 +1355,7 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
|
|
1311
1355
|
GPR_ASSERT(call->encodings_accepted_by_peer != 0);
|
1312
1356
|
if (!GPR_BITGET(call->encodings_accepted_by_peer,
|
1313
1357
|
call->incoming_compression_algorithm)) {
|
1314
|
-
|
1315
|
-
if (grpc_compression_trace) {
|
1358
|
+
if (GRPC_TRACER_ON(grpc_compression_trace)) {
|
1316
1359
|
char *algo_name = NULL;
|
1317
1360
|
grpc_compression_algorithm_name(call->incoming_compression_algorithm,
|
1318
1361
|
&algo_name);
|
data/src/core/lib/surface/call.h
CHANGED
@@ -117,7 +117,8 @@ void grpc_call_context_set(grpc_call *call, grpc_context_index elem,
|
|
117
117
|
void *grpc_call_context_get(grpc_call *call, grpc_context_index elem);
|
118
118
|
|
119
119
|
#define GRPC_CALL_LOG_BATCH(sev, call, ops, nops, tag) \
|
120
|
-
if (grpc_api_trace)
|
120
|
+
if (GRPC_TRACER_ON(grpc_api_trace)) \
|
121
|
+
grpc_call_log_batch(sev, call, ops, nops, tag)
|
121
122
|
|
122
123
|
uint8_t grpc_call_is_client(grpc_call *call);
|
123
124
|
|
@@ -126,7 +127,8 @@ uint8_t grpc_call_is_client(grpc_call *call);
|
|
126
127
|
grpc_compression_algorithm grpc_call_compression_for_level(
|
127
128
|
grpc_call *call, grpc_compression_level level);
|
128
129
|
|
129
|
-
extern
|
130
|
+
extern grpc_tracer_flag grpc_call_error_trace;
|
131
|
+
extern grpc_tracer_flag grpc_compression_trace;
|
130
132
|
|
131
133
|
#ifdef __cplusplus
|
132
134
|
}
|
@@ -104,30 +104,13 @@ void grpc_channel_init_shutdown(void) {
|
|
104
104
|
}
|
105
105
|
}
|
106
106
|
|
107
|
-
static const char *name_for_type(grpc_channel_stack_type type) {
|
108
|
-
switch (type) {
|
109
|
-
case GRPC_CLIENT_CHANNEL:
|
110
|
-
return "CLIENT_CHANNEL";
|
111
|
-
case GRPC_CLIENT_SUBCHANNEL:
|
112
|
-
return "CLIENT_SUBCHANNEL";
|
113
|
-
case GRPC_SERVER_CHANNEL:
|
114
|
-
return "SERVER_CHANNEL";
|
115
|
-
case GRPC_CLIENT_LAME_CHANNEL:
|
116
|
-
return "CLIENT_LAME_CHANNEL";
|
117
|
-
case GRPC_CLIENT_DIRECT_CHANNEL:
|
118
|
-
return "CLIENT_DIRECT_CHANNEL";
|
119
|
-
case GRPC_NUM_CHANNEL_STACK_TYPES:
|
120
|
-
break;
|
121
|
-
}
|
122
|
-
GPR_UNREACHABLE_CODE(return "UNKNOWN");
|
123
|
-
}
|
124
|
-
|
125
107
|
bool grpc_channel_init_create_stack(grpc_exec_ctx *exec_ctx,
|
126
108
|
grpc_channel_stack_builder *builder,
|
127
109
|
grpc_channel_stack_type type) {
|
128
110
|
GPR_ASSERT(g_finalized);
|
129
111
|
|
130
|
-
grpc_channel_stack_builder_set_name(builder,
|
112
|
+
grpc_channel_stack_builder_set_name(builder,
|
113
|
+
grpc_channel_stack_type_string(type));
|
131
114
|
|
132
115
|
for (size_t i = 0; i < g_slots[type].num_slots; i++) {
|
133
116
|
const stage_slot *slot = &g_slots[type].slots[i];
|
@@ -52,3 +52,21 @@ bool grpc_channel_stack_type_is_client(grpc_channel_stack_type type) {
|
|
52
52
|
}
|
53
53
|
GPR_UNREACHABLE_CODE(return true;);
|
54
54
|
}
|
55
|
+
|
56
|
+
const char *grpc_channel_stack_type_string(grpc_channel_stack_type type) {
|
57
|
+
switch (type) {
|
58
|
+
case GRPC_CLIENT_CHANNEL:
|
59
|
+
return "CLIENT_CHANNEL";
|
60
|
+
case GRPC_CLIENT_SUBCHANNEL:
|
61
|
+
return "CLIENT_SUBCHANNEL";
|
62
|
+
case GRPC_SERVER_CHANNEL:
|
63
|
+
return "SERVER_CHANNEL";
|
64
|
+
case GRPC_CLIENT_LAME_CHANNEL:
|
65
|
+
return "CLIENT_LAME_CHANNEL";
|
66
|
+
case GRPC_CLIENT_DIRECT_CHANNEL:
|
67
|
+
return "CLIENT_DIRECT_CHANNEL";
|
68
|
+
case GRPC_NUM_CHANNEL_STACK_TYPES:
|
69
|
+
break;
|
70
|
+
}
|
71
|
+
GPR_UNREACHABLE_CODE(return "UNKNOWN");
|
72
|
+
}
|
@@ -30,7 +30,6 @@
|
|
30
30
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
31
|
*
|
32
32
|
*/
|
33
|
-
|
34
33
|
#include "src/core/lib/surface/completion_queue.h"
|
35
34
|
|
36
35
|
#include <stdio.h>
|
@@ -45,14 +44,15 @@
|
|
45
44
|
#include "src/core/lib/iomgr/pollset.h"
|
46
45
|
#include "src/core/lib/iomgr/timer.h"
|
47
46
|
#include "src/core/lib/profiling/timers.h"
|
47
|
+
#include "src/core/lib/support/spinlock.h"
|
48
48
|
#include "src/core/lib/support/string.h"
|
49
49
|
#include "src/core/lib/surface/api_trace.h"
|
50
50
|
#include "src/core/lib/surface/call.h"
|
51
51
|
#include "src/core/lib/surface/event_string.h"
|
52
52
|
|
53
|
-
|
53
|
+
grpc_tracer_flag grpc_trace_operation_failures = GRPC_TRACER_INITIALIZER(false);
|
54
54
|
#ifndef NDEBUG
|
55
|
-
|
55
|
+
grpc_tracer_flag grpc_trace_pending_tags = GRPC_TRACER_INITIALIZER(false);
|
56
56
|
#endif
|
57
57
|
|
58
58
|
typedef struct {
|
@@ -60,27 +60,209 @@ typedef struct {
|
|
60
60
|
void *tag;
|
61
61
|
} plucker;
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
typedef struct {
|
64
|
+
bool can_get_pollset;
|
65
|
+
bool can_listen;
|
66
|
+
size_t (*size)(void);
|
67
|
+
void (*init)(grpc_pollset *pollset, gpr_mu **mu);
|
68
|
+
grpc_error *(*kick)(grpc_pollset *pollset,
|
69
|
+
grpc_pollset_worker *specific_worker);
|
70
|
+
grpc_error *(*work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
71
|
+
grpc_pollset_worker **worker, gpr_timespec now,
|
72
|
+
gpr_timespec deadline);
|
73
|
+
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
|
74
|
+
grpc_closure *closure);
|
75
|
+
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset);
|
76
|
+
} cq_poller_vtable;
|
77
|
+
|
78
|
+
typedef struct non_polling_worker {
|
79
|
+
gpr_cv cv;
|
80
|
+
bool kicked;
|
81
|
+
struct non_polling_worker *next;
|
82
|
+
struct non_polling_worker *prev;
|
83
|
+
} non_polling_worker;
|
84
|
+
|
85
|
+
typedef struct {
|
86
|
+
gpr_mu mu;
|
87
|
+
non_polling_worker *root;
|
88
|
+
grpc_closure *shutdown;
|
89
|
+
} non_polling_poller;
|
90
|
+
|
91
|
+
static size_t non_polling_poller_size(void) {
|
92
|
+
return sizeof(non_polling_poller);
|
93
|
+
}
|
94
|
+
|
95
|
+
static void non_polling_poller_init(grpc_pollset *pollset, gpr_mu **mu) {
|
96
|
+
non_polling_poller *npp = (non_polling_poller *)pollset;
|
97
|
+
gpr_mu_init(&npp->mu);
|
98
|
+
*mu = &npp->mu;
|
99
|
+
}
|
100
|
+
|
101
|
+
static void non_polling_poller_destroy(grpc_exec_ctx *exec_ctx,
|
102
|
+
grpc_pollset *pollset) {
|
103
|
+
non_polling_poller *npp = (non_polling_poller *)pollset;
|
104
|
+
gpr_mu_destroy(&npp->mu);
|
105
|
+
}
|
106
|
+
|
107
|
+
static grpc_error *non_polling_poller_work(grpc_exec_ctx *exec_ctx,
|
108
|
+
grpc_pollset *pollset,
|
109
|
+
grpc_pollset_worker **worker,
|
110
|
+
gpr_timespec now,
|
111
|
+
gpr_timespec deadline) {
|
112
|
+
non_polling_poller *npp = (non_polling_poller *)pollset;
|
113
|
+
if (npp->shutdown) return GRPC_ERROR_NONE;
|
114
|
+
non_polling_worker w;
|
115
|
+
gpr_cv_init(&w.cv);
|
116
|
+
if (worker != NULL) *worker = (grpc_pollset_worker *)&w;
|
117
|
+
if (npp->root == NULL) {
|
118
|
+
npp->root = w.next = w.prev = &w;
|
119
|
+
} else {
|
120
|
+
w.next = npp->root;
|
121
|
+
w.prev = w.next->prev;
|
122
|
+
w.next->prev = w.prev->next = &w;
|
123
|
+
}
|
124
|
+
w.kicked = false;
|
125
|
+
while (!npp->shutdown && !w.kicked && !gpr_cv_wait(&w.cv, &npp->mu, deadline))
|
126
|
+
;
|
127
|
+
if (&w == npp->root) {
|
128
|
+
npp->root = w.next;
|
129
|
+
if (&w == npp->root) {
|
130
|
+
if (npp->shutdown) {
|
131
|
+
grpc_closure_sched(exec_ctx, npp->shutdown, GRPC_ERROR_NONE);
|
132
|
+
}
|
133
|
+
npp->root = NULL;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
w.next->prev = w.prev;
|
137
|
+
w.prev->next = w.next;
|
138
|
+
gpr_cv_destroy(&w.cv);
|
139
|
+
if (worker != NULL) *worker = NULL;
|
140
|
+
return GRPC_ERROR_NONE;
|
141
|
+
}
|
142
|
+
|
143
|
+
static grpc_error *non_polling_poller_kick(
|
144
|
+
grpc_pollset *pollset, grpc_pollset_worker *specific_worker) {
|
145
|
+
non_polling_poller *p = (non_polling_poller *)pollset;
|
146
|
+
if (specific_worker == NULL) specific_worker = (grpc_pollset_worker *)p->root;
|
147
|
+
if (specific_worker != NULL) {
|
148
|
+
non_polling_worker *w = (non_polling_worker *)specific_worker;
|
149
|
+
if (!w->kicked) {
|
150
|
+
w->kicked = true;
|
151
|
+
gpr_cv_signal(&w->cv);
|
152
|
+
}
|
153
|
+
}
|
154
|
+
return GRPC_ERROR_NONE;
|
155
|
+
}
|
156
|
+
|
157
|
+
static void non_polling_poller_shutdown(grpc_exec_ctx *exec_ctx,
|
158
|
+
grpc_pollset *pollset,
|
159
|
+
grpc_closure *closure) {
|
160
|
+
non_polling_poller *p = (non_polling_poller *)pollset;
|
161
|
+
GPR_ASSERT(closure != NULL);
|
162
|
+
p->shutdown = closure;
|
163
|
+
if (p->root == NULL) {
|
164
|
+
grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE);
|
165
|
+
} else {
|
166
|
+
non_polling_worker *w = p->root;
|
167
|
+
do {
|
168
|
+
gpr_cv_signal(&w->cv);
|
169
|
+
w = w->next;
|
170
|
+
} while (w != p->root);
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
static const cq_poller_vtable g_poller_vtable_by_poller_type[] = {
|
175
|
+
/* GRPC_CQ_DEFAULT_POLLING */
|
176
|
+
{.can_get_pollset = true,
|
177
|
+
.can_listen = true,
|
178
|
+
.size = grpc_pollset_size,
|
179
|
+
.init = grpc_pollset_init,
|
180
|
+
.kick = grpc_pollset_kick,
|
181
|
+
.work = grpc_pollset_work,
|
182
|
+
.shutdown = grpc_pollset_shutdown,
|
183
|
+
.destroy = grpc_pollset_destroy},
|
184
|
+
/* GRPC_CQ_NON_LISTENING */
|
185
|
+
{.can_get_pollset = true,
|
186
|
+
.can_listen = false,
|
187
|
+
.size = grpc_pollset_size,
|
188
|
+
.init = grpc_pollset_init,
|
189
|
+
.kick = grpc_pollset_kick,
|
190
|
+
.work = grpc_pollset_work,
|
191
|
+
.shutdown = grpc_pollset_shutdown,
|
192
|
+
.destroy = grpc_pollset_destroy},
|
193
|
+
/* GRPC_CQ_NON_POLLING */
|
194
|
+
{.can_get_pollset = false,
|
195
|
+
.can_listen = false,
|
196
|
+
.size = non_polling_poller_size,
|
197
|
+
.init = non_polling_poller_init,
|
198
|
+
.kick = non_polling_poller_kick,
|
199
|
+
.work = non_polling_poller_work,
|
200
|
+
.shutdown = non_polling_poller_shutdown,
|
201
|
+
.destroy = non_polling_poller_destroy},
|
202
|
+
};
|
203
|
+
|
204
|
+
typedef struct cq_vtable {
|
205
|
+
grpc_cq_completion_type cq_completion_type;
|
206
|
+
size_t (*size)();
|
207
|
+
void (*begin_op)(grpc_completion_queue *cc, void *tag);
|
208
|
+
void (*end_op)(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc, void *tag,
|
209
|
+
grpc_error *error,
|
210
|
+
void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
|
211
|
+
grpc_cq_completion *storage),
|
212
|
+
void *done_arg, grpc_cq_completion *storage);
|
213
|
+
grpc_event (*next)(grpc_completion_queue *cc, gpr_timespec deadline,
|
214
|
+
void *reserved);
|
215
|
+
grpc_event (*pluck)(grpc_completion_queue *cc, void *tag,
|
216
|
+
gpr_timespec deadline, void *reserved);
|
217
|
+
} cq_vtable;
|
218
|
+
|
219
|
+
/* Queue that holds the cq_completion_events. Internally uses gpr_mpscq queue
|
220
|
+
* (a lockfree multiproducer single consumer queue). It uses a queue_lock
|
221
|
+
* to support multiple consumers.
|
222
|
+
* Only used in completion queues whose completion_type is GRPC_CQ_NEXT */
|
223
|
+
typedef struct grpc_cq_event_queue {
|
224
|
+
/* Spinlock to serialize consumers i.e pop() operations */
|
225
|
+
gpr_spinlock queue_lock;
|
226
|
+
|
227
|
+
gpr_mpscq queue;
|
228
|
+
|
229
|
+
/* A lazy counter of number of items in the queue. This is NOT atomically
|
230
|
+
incremented/decremented along with push/pop operations and hence is only
|
231
|
+
eventually consistent */
|
232
|
+
gpr_atm num_queue_items;
|
233
|
+
} grpc_cq_event_queue;
|
234
|
+
|
235
|
+
/* TODO: sreek Refactor this based on the completion_type. Put completion-type
|
236
|
+
* specific data in a different structure (and co-allocate memory for it along
|
237
|
+
* with completion queue + pollset )*/
|
238
|
+
typedef struct cq_data {
|
66
239
|
gpr_mu *mu;
|
67
|
-
|
240
|
+
|
241
|
+
/** Completed events for completion-queues of type GRPC_CQ_PLUCK */
|
68
242
|
grpc_cq_completion completed_head;
|
69
243
|
grpc_cq_completion *completed_tail;
|
244
|
+
|
245
|
+
/** Completed events for completion-queues of type GRPC_CQ_NEXT */
|
246
|
+
grpc_cq_event_queue queue;
|
247
|
+
|
70
248
|
/** Number of pending events (+1 if we're not shutdown) */
|
71
249
|
gpr_refcount pending_events;
|
250
|
+
|
72
251
|
/** Once owning_refs drops to zero, we will destroy the cq */
|
73
252
|
gpr_refcount owning_refs;
|
74
|
-
|
253
|
+
|
254
|
+
/** Counter of how many things have ever been queued on this completion queue
|
75
255
|
useful for avoiding locks to check the queue */
|
76
256
|
gpr_atm things_queued_ever;
|
257
|
+
|
77
258
|
/** 0 initially, 1 once we've begun shutting down */
|
78
|
-
|
259
|
+
gpr_atm shutdown;
|
79
260
|
int shutdown_called;
|
261
|
+
|
80
262
|
int is_server_cq;
|
81
|
-
|
82
|
-
int is_non_listening_server_cq;
|
263
|
+
|
83
264
|
int num_pluckers;
|
265
|
+
int num_polls;
|
84
266
|
plucker pluckers[GRPC_MAX_COMPLETION_QUEUE_PLUCKERS];
|
85
267
|
grpc_closure pollset_shutdown_done;
|
86
268
|
|
@@ -89,179 +271,397 @@ struct grpc_completion_queue {
|
|
89
271
|
size_t outstanding_tag_count;
|
90
272
|
size_t outstanding_tag_capacity;
|
91
273
|
#endif
|
274
|
+
} cq_data;
|
92
275
|
|
93
|
-
|
276
|
+
/* Completion queue structure */
|
277
|
+
struct grpc_completion_queue {
|
278
|
+
cq_data data;
|
279
|
+
const cq_vtable *vtable;
|
280
|
+
const cq_poller_vtable *poller_vtable;
|
281
|
+
};
|
282
|
+
|
283
|
+
/* Forward declarations */
|
284
|
+
static void cq_finish_shutdown(grpc_exec_ctx *exec_ctx,
|
285
|
+
grpc_completion_queue *cc);
|
286
|
+
|
287
|
+
static size_t cq_size(grpc_completion_queue *cc);
|
288
|
+
|
289
|
+
static void cq_begin_op(grpc_completion_queue *cc, void *tag);
|
290
|
+
|
291
|
+
static void cq_end_op_for_next(grpc_exec_ctx *exec_ctx,
|
292
|
+
grpc_completion_queue *cc, void *tag,
|
293
|
+
grpc_error *error,
|
294
|
+
void (*done)(grpc_exec_ctx *exec_ctx,
|
295
|
+
void *done_arg,
|
296
|
+
grpc_cq_completion *storage),
|
297
|
+
void *done_arg, grpc_cq_completion *storage);
|
298
|
+
|
299
|
+
static void cq_end_op_for_pluck(grpc_exec_ctx *exec_ctx,
|
300
|
+
grpc_completion_queue *cc, void *tag,
|
301
|
+
grpc_error *error,
|
302
|
+
void (*done)(grpc_exec_ctx *exec_ctx,
|
303
|
+
void *done_arg,
|
304
|
+
grpc_cq_completion *storage),
|
305
|
+
void *done_arg, grpc_cq_completion *storage);
|
306
|
+
|
307
|
+
static grpc_event cq_next(grpc_completion_queue *cc, gpr_timespec deadline,
|
308
|
+
void *reserved);
|
309
|
+
|
310
|
+
static grpc_event cq_pluck(grpc_completion_queue *cc, void *tag,
|
311
|
+
gpr_timespec deadline, void *reserved);
|
312
|
+
|
313
|
+
/* Completion queue vtables based on the completion-type */
|
314
|
+
static const cq_vtable g_cq_vtable[] = {
|
315
|
+
/* GRPC_CQ_NEXT */
|
316
|
+
{.cq_completion_type = GRPC_CQ_NEXT,
|
317
|
+
.size = cq_size,
|
318
|
+
.begin_op = cq_begin_op,
|
319
|
+
.end_op = cq_end_op_for_next,
|
320
|
+
.next = cq_next,
|
321
|
+
.pluck = NULL},
|
322
|
+
/* GRPC_CQ_PLUCK */
|
323
|
+
{.cq_completion_type = GRPC_CQ_PLUCK,
|
324
|
+
.size = cq_size,
|
325
|
+
.begin_op = cq_begin_op,
|
326
|
+
.end_op = cq_end_op_for_pluck,
|
327
|
+
.next = NULL,
|
328
|
+
.pluck = cq_pluck},
|
94
329
|
};
|
95
330
|
|
96
331
|
#define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1))
|
97
332
|
#define CQ_FROM_POLLSET(ps) (((grpc_completion_queue *)ps) - 1)
|
98
333
|
|
99
|
-
|
100
|
-
|
334
|
+
grpc_tracer_flag grpc_cq_pluck_trace = GRPC_TRACER_INITIALIZER(true);
|
335
|
+
grpc_tracer_flag grpc_cq_event_timeout_trace = GRPC_TRACER_INITIALIZER(true);
|
101
336
|
|
102
|
-
#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event)
|
103
|
-
if (grpc_api_trace &&
|
104
|
-
(grpc_cq_pluck_trace ||
|
105
|
-
|
106
|
-
|
107
|
-
|
337
|
+
#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \
|
338
|
+
if (GRPC_TRACER_ON(grpc_api_trace) && \
|
339
|
+
(GRPC_TRACER_ON(grpc_cq_pluck_trace) || \
|
340
|
+
(event)->type != GRPC_QUEUE_TIMEOUT)) { \
|
341
|
+
char *_ev = grpc_event_string(event); \
|
342
|
+
gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \
|
343
|
+
gpr_free(_ev); \
|
108
344
|
}
|
109
345
|
|
110
346
|
static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
|
111
347
|
grpc_error *error);
|
112
348
|
|
113
|
-
|
349
|
+
static void cq_event_queue_init(grpc_cq_event_queue *q) {
|
350
|
+
gpr_mpscq_init(&q->queue);
|
351
|
+
q->queue_lock = GPR_SPINLOCK_INITIALIZER;
|
352
|
+
gpr_atm_no_barrier_store(&q->num_queue_items, 0);
|
353
|
+
}
|
354
|
+
|
355
|
+
static void cq_event_queue_destroy(grpc_cq_event_queue *q) {
|
356
|
+
gpr_mpscq_destroy(&q->queue);
|
357
|
+
}
|
358
|
+
|
359
|
+
static void cq_event_queue_push(grpc_cq_event_queue *q, grpc_cq_completion *c) {
|
360
|
+
gpr_mpscq_push(&q->queue, (gpr_mpscq_node *)c);
|
361
|
+
gpr_atm_no_barrier_fetch_add(&q->num_queue_items, 1);
|
362
|
+
}
|
363
|
+
|
364
|
+
static grpc_cq_completion *cq_event_queue_pop(grpc_cq_event_queue *q) {
|
365
|
+
grpc_cq_completion *c = NULL;
|
366
|
+
if (gpr_spinlock_trylock(&q->queue_lock)) {
|
367
|
+
c = (grpc_cq_completion *)gpr_mpscq_pop(&q->queue);
|
368
|
+
gpr_spinlock_unlock(&q->queue_lock);
|
369
|
+
}
|
370
|
+
|
371
|
+
if (c) {
|
372
|
+
gpr_atm_no_barrier_fetch_add(&q->num_queue_items, -1);
|
373
|
+
}
|
374
|
+
|
375
|
+
return c;
|
376
|
+
}
|
377
|
+
|
378
|
+
/* Note: The counter is not incremented/decremented atomically with push/pop.
|
379
|
+
* The count is only eventually consistent */
|
380
|
+
static long cq_event_queue_num_items(grpc_cq_event_queue *q) {
|
381
|
+
return (long)gpr_atm_no_barrier_load(&q->num_queue_items);
|
382
|
+
}
|
383
|
+
|
384
|
+
static size_t cq_size(grpc_completion_queue *cc) {
|
385
|
+
/* Size of the completion queue and the size of the pollset whose memory is
|
386
|
+
allocated right after that of completion queue */
|
387
|
+
return sizeof(grpc_completion_queue) + cc->poller_vtable->size();
|
388
|
+
}
|
389
|
+
|
390
|
+
grpc_completion_queue *grpc_completion_queue_create_internal(
|
391
|
+
grpc_cq_completion_type completion_type,
|
392
|
+
grpc_cq_polling_type polling_type) {
|
114
393
|
grpc_completion_queue *cc;
|
115
|
-
GPR_ASSERT(!reserved);
|
116
394
|
|
117
|
-
GPR_TIMER_BEGIN("
|
395
|
+
GPR_TIMER_BEGIN("grpc_completion_queue_create_internal", 0);
|
396
|
+
|
397
|
+
GRPC_API_TRACE(
|
398
|
+
"grpc_completion_queue_create_internal(completion_type=%d, "
|
399
|
+
"polling_type=%d)",
|
400
|
+
2, (completion_type, polling_type));
|
401
|
+
|
402
|
+
const cq_vtable *vtable = &g_cq_vtable[completion_type];
|
403
|
+
const cq_poller_vtable *poller_vtable =
|
404
|
+
&g_poller_vtable_by_poller_type[polling_type];
|
405
|
+
|
406
|
+
cc = gpr_zalloc(sizeof(grpc_completion_queue) + poller_vtable->size());
|
407
|
+
cq_data *cqd = &cc->data;
|
118
408
|
|
119
|
-
|
409
|
+
cc->vtable = vtable;
|
410
|
+
cc->poller_vtable = poller_vtable;
|
411
|
+
|
412
|
+
poller_vtable->init(POLLSET_FROM_CQ(cc), &cc->data.mu);
|
120
413
|
|
121
|
-
cc = gpr_zalloc(sizeof(grpc_completion_queue) + grpc_pollset_size());
|
122
|
-
grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu);
|
123
414
|
#ifndef NDEBUG
|
124
|
-
|
125
|
-
|
415
|
+
cqd->outstanding_tags = NULL;
|
416
|
+
cqd->outstanding_tag_capacity = 0;
|
126
417
|
#endif
|
127
418
|
|
128
419
|
/* Initial ref is dropped by grpc_completion_queue_shutdown */
|
129
|
-
gpr_ref_init(&
|
420
|
+
gpr_ref_init(&cqd->pending_events, 1);
|
130
421
|
/* One for destroy(), one for pollset_shutdown */
|
131
|
-
gpr_ref_init(&
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
gpr_atm_no_barrier_store(&
|
422
|
+
gpr_ref_init(&cqd->owning_refs, 2);
|
423
|
+
cqd->completed_tail = &cqd->completed_head;
|
424
|
+
cqd->completed_head.next = (uintptr_t)cqd->completed_tail;
|
425
|
+
gpr_atm_no_barrier_store(&cqd->shutdown, 0);
|
426
|
+
cqd->shutdown_called = 0;
|
427
|
+
cqd->is_server_cq = 0;
|
428
|
+
cqd->num_pluckers = 0;
|
429
|
+
cqd->num_polls = 0;
|
430
|
+
gpr_atm_no_barrier_store(&cqd->things_queued_ever, 0);
|
140
431
|
#ifndef NDEBUG
|
141
|
-
|
432
|
+
cqd->outstanding_tag_count = 0;
|
142
433
|
#endif
|
143
|
-
|
434
|
+
cq_event_queue_init(&cqd->queue);
|
435
|
+
grpc_closure_init(&cqd->pollset_shutdown_done, on_pollset_shutdown_done, cc,
|
144
436
|
grpc_schedule_on_exec_ctx);
|
145
437
|
|
146
|
-
GPR_TIMER_END("
|
438
|
+
GPR_TIMER_END("grpc_completion_queue_create_internal", 0);
|
147
439
|
|
148
440
|
return cc;
|
149
441
|
}
|
150
442
|
|
443
|
+
grpc_cq_completion_type grpc_get_cq_completion_type(grpc_completion_queue *cc) {
|
444
|
+
return cc->vtable->cq_completion_type;
|
445
|
+
}
|
446
|
+
|
447
|
+
int grpc_get_cq_poll_num(grpc_completion_queue *cc) {
|
448
|
+
int cur_num_polls;
|
449
|
+
gpr_mu_lock(cc->data.mu);
|
450
|
+
cur_num_polls = cc->data.num_polls;
|
451
|
+
gpr_mu_unlock(cc->data.mu);
|
452
|
+
return cur_num_polls;
|
453
|
+
}
|
454
|
+
|
151
455
|
#ifdef GRPC_CQ_REF_COUNT_DEBUG
|
152
456
|
void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
|
153
457
|
const char *file, int line) {
|
458
|
+
cq_data *cqd = &cc->data;
|
154
459
|
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p ref %d -> %d %s", cc,
|
155
|
-
(int)
|
460
|
+
(int)cqd->owning_refs.count, (int)cqd->owning_refs.count + 1, reason);
|
156
461
|
#else
|
157
462
|
void grpc_cq_internal_ref(grpc_completion_queue *cc) {
|
463
|
+
cq_data *cqd = &cc->data;
|
158
464
|
#endif
|
159
|
-
gpr_ref(&
|
465
|
+
gpr_ref(&cqd->owning_refs);
|
160
466
|
}
|
161
467
|
|
162
468
|
static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *arg,
|
163
469
|
grpc_error *error) {
|
164
470
|
grpc_completion_queue *cc = arg;
|
165
|
-
GRPC_CQ_INTERNAL_UNREF(cc, "pollset_destroy");
|
471
|
+
GRPC_CQ_INTERNAL_UNREF(exec_ctx, cc, "pollset_destroy");
|
166
472
|
}
|
167
473
|
|
168
474
|
#ifdef GRPC_CQ_REF_COUNT_DEBUG
|
169
475
|
void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason,
|
170
476
|
const char *file, int line) {
|
477
|
+
cq_data *cqd = &cc->data;
|
171
478
|
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s", cc,
|
172
|
-
(int)
|
479
|
+
(int)cqd->owning_refs.count, (int)cqd->owning_refs.count - 1, reason);
|
173
480
|
#else
|
174
|
-
void grpc_cq_internal_unref(
|
481
|
+
void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx,
|
482
|
+
grpc_completion_queue *cc) {
|
483
|
+
cq_data *cqd = &cc->data;
|
175
484
|
#endif
|
176
|
-
if (gpr_unref(&
|
177
|
-
GPR_ASSERT(
|
178
|
-
|
485
|
+
if (gpr_unref(&cqd->owning_refs)) {
|
486
|
+
GPR_ASSERT(cqd->completed_head.next == (uintptr_t)&cqd->completed_head);
|
487
|
+
cc->poller_vtable->destroy(exec_ctx, POLLSET_FROM_CQ(cc));
|
488
|
+
cq_event_queue_destroy(&cqd->queue);
|
179
489
|
#ifndef NDEBUG
|
180
|
-
gpr_free(
|
490
|
+
gpr_free(cqd->outstanding_tags);
|
181
491
|
#endif
|
182
492
|
gpr_free(cc);
|
183
493
|
}
|
184
494
|
}
|
185
495
|
|
186
|
-
void
|
496
|
+
static void cq_begin_op(grpc_completion_queue *cc, void *tag) {
|
497
|
+
cq_data *cqd = &cc->data;
|
187
498
|
#ifndef NDEBUG
|
188
|
-
gpr_mu_lock(
|
189
|
-
GPR_ASSERT(!
|
190
|
-
if (
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
499
|
+
gpr_mu_lock(cqd->mu);
|
500
|
+
GPR_ASSERT(!cqd->shutdown_called);
|
501
|
+
if (cqd->outstanding_tag_count == cqd->outstanding_tag_capacity) {
|
502
|
+
cqd->outstanding_tag_capacity =
|
503
|
+
GPR_MAX(4, 2 * cqd->outstanding_tag_capacity);
|
504
|
+
cqd->outstanding_tags =
|
505
|
+
gpr_realloc(cqd->outstanding_tags, sizeof(*cqd->outstanding_tags) *
|
506
|
+
cqd->outstanding_tag_capacity);
|
195
507
|
}
|
196
|
-
|
197
|
-
gpr_mu_unlock(
|
508
|
+
cqd->outstanding_tags[cqd->outstanding_tag_count++] = tag;
|
509
|
+
gpr_mu_unlock(cqd->mu);
|
198
510
|
#endif
|
199
|
-
gpr_ref(&
|
511
|
+
gpr_ref(&cqd->pending_events);
|
512
|
+
}
|
513
|
+
|
514
|
+
void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag) {
|
515
|
+
cc->vtable->begin_op(cc, tag);
|
200
516
|
}
|
201
517
|
|
202
|
-
/* Signal the end of an operation - if this is the last waiting-to-be-queued
|
203
|
-
event, then enter shutdown mode */
|
204
|
-
/* Queue a GRPC_OP_COMPLETED operation */
|
205
|
-
void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
|
206
|
-
void *tag, grpc_error *error,
|
207
|
-
void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
|
208
|
-
grpc_cq_completion *storage),
|
209
|
-
void *done_arg, grpc_cq_completion *storage) {
|
210
|
-
int shutdown;
|
211
|
-
int i;
|
212
|
-
grpc_pollset_worker *pluck_worker;
|
213
518
|
#ifndef NDEBUG
|
519
|
+
static void cq_check_tag(grpc_completion_queue *cc, void *tag, bool lock_cq) {
|
520
|
+
cq_data *cqd = &cc->data;
|
214
521
|
int found = 0;
|
522
|
+
if (lock_cq) {
|
523
|
+
gpr_mu_lock(cqd->mu);
|
524
|
+
}
|
525
|
+
|
526
|
+
for (int i = 0; i < (int)cqd->outstanding_tag_count; i++) {
|
527
|
+
if (cqd->outstanding_tags[i] == tag) {
|
528
|
+
cqd->outstanding_tag_count--;
|
529
|
+
GPR_SWAP(void *, cqd->outstanding_tags[i],
|
530
|
+
cqd->outstanding_tags[cqd->outstanding_tag_count]);
|
531
|
+
found = 1;
|
532
|
+
break;
|
533
|
+
}
|
534
|
+
}
|
535
|
+
|
536
|
+
if (lock_cq) {
|
537
|
+
gpr_mu_unlock(cqd->mu);
|
538
|
+
}
|
539
|
+
|
540
|
+
GPR_ASSERT(found);
|
541
|
+
}
|
542
|
+
#else
|
543
|
+
static void cq_check_tag(grpc_completion_queue *cc, void *tag, bool lock_cq) {}
|
215
544
|
#endif
|
216
545
|
|
217
|
-
|
218
|
-
|
219
|
-
|
546
|
+
/* Queue a GRPC_OP_COMPLETED operation to a completion queue (with a completion
|
547
|
+
* type of GRPC_CQ_NEXT) */
|
548
|
+
static void cq_end_op_for_next(grpc_exec_ctx *exec_ctx,
|
549
|
+
grpc_completion_queue *cc, void *tag,
|
550
|
+
grpc_error *error,
|
551
|
+
void (*done)(grpc_exec_ctx *exec_ctx,
|
552
|
+
void *done_arg,
|
553
|
+
grpc_cq_completion *storage),
|
554
|
+
void *done_arg, grpc_cq_completion *storage) {
|
555
|
+
GPR_TIMER_BEGIN("cq_end_op_for_next", 0);
|
556
|
+
|
557
|
+
if (GRPC_TRACER_ON(grpc_api_trace) ||
|
558
|
+
(GRPC_TRACER_ON(grpc_trace_operation_failures) &&
|
559
|
+
error != GRPC_ERROR_NONE)) {
|
220
560
|
const char *errmsg = grpc_error_string(error);
|
221
561
|
GRPC_API_TRACE(
|
222
|
-
"
|
223
|
-
"done_arg=%p, storage=%p)",
|
562
|
+
"cq_end_op_for_next(exec_ctx=%p, cc=%p, tag=%p, error=%s, "
|
563
|
+
"done=%p, done_arg=%p, storage=%p)",
|
224
564
|
7, (exec_ctx, cc, tag, errmsg, done, done_arg, storage));
|
225
|
-
if (grpc_trace_operation_failures &&
|
565
|
+
if (GRPC_TRACER_ON(grpc_trace_operation_failures) &&
|
566
|
+
error != GRPC_ERROR_NONE) {
|
226
567
|
gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg);
|
227
568
|
}
|
228
569
|
}
|
229
570
|
|
571
|
+
cq_data *cqd = &cc->data;
|
572
|
+
int is_success = (error == GRPC_ERROR_NONE);
|
573
|
+
|
230
574
|
storage->tag = tag;
|
231
575
|
storage->done = done;
|
232
576
|
storage->done_arg = done_arg;
|
233
|
-
storage->next = (
|
234
|
-
((uintptr_t)(error == GRPC_ERROR_NONE));
|
577
|
+
storage->next = (uintptr_t)(is_success);
|
235
578
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
579
|
+
cq_check_tag(cc, tag, true); /* Used in debug builds only */
|
580
|
+
|
581
|
+
/* Add the completion to the queue */
|
582
|
+
cq_event_queue_push(&cqd->queue, storage);
|
583
|
+
gpr_atm_no_barrier_fetch_add(&cqd->things_queued_ever, 1);
|
584
|
+
|
585
|
+
gpr_mu_lock(cqd->mu);
|
586
|
+
|
587
|
+
int shutdown = gpr_unref(&cqd->pending_events);
|
588
|
+
if (!shutdown) {
|
589
|
+
grpc_error *kick_error = cc->poller_vtable->kick(POLLSET_FROM_CQ(cc), NULL);
|
590
|
+
gpr_mu_unlock(cqd->mu);
|
591
|
+
|
592
|
+
if (kick_error != GRPC_ERROR_NONE) {
|
593
|
+
const char *msg = grpc_error_string(kick_error);
|
594
|
+
gpr_log(GPR_ERROR, "Kick failed: %s", msg);
|
595
|
+
|
596
|
+
GRPC_ERROR_UNREF(kick_error);
|
245
597
|
}
|
598
|
+
} else {
|
599
|
+
cq_finish_shutdown(exec_ctx, cc);
|
600
|
+
gpr_mu_unlock(cqd->mu);
|
246
601
|
}
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
602
|
+
|
603
|
+
GPR_TIMER_END("cq_end_op_for_next", 0);
|
604
|
+
|
605
|
+
GRPC_ERROR_UNREF(error);
|
606
|
+
}
|
607
|
+
|
608
|
+
/* Queue a GRPC_OP_COMPLETED operation to a completion queue (with a completion
|
609
|
+
* type of GRPC_CQ_PLUCK) */
|
610
|
+
static void cq_end_op_for_pluck(grpc_exec_ctx *exec_ctx,
|
611
|
+
grpc_completion_queue *cc, void *tag,
|
612
|
+
grpc_error *error,
|
613
|
+
void (*done)(grpc_exec_ctx *exec_ctx,
|
614
|
+
void *done_arg,
|
615
|
+
grpc_cq_completion *storage),
|
616
|
+
void *done_arg, grpc_cq_completion *storage) {
|
617
|
+
cq_data *cqd = &cc->data;
|
618
|
+
int is_success = (error == GRPC_ERROR_NONE);
|
619
|
+
|
620
|
+
GPR_TIMER_BEGIN("cq_end_op_for_pluck", 0);
|
621
|
+
|
622
|
+
if (GRPC_TRACER_ON(grpc_api_trace) ||
|
623
|
+
(GRPC_TRACER_ON(grpc_trace_operation_failures) &&
|
624
|
+
error != GRPC_ERROR_NONE)) {
|
625
|
+
const char *errmsg = grpc_error_string(error);
|
626
|
+
GRPC_API_TRACE(
|
627
|
+
"cq_end_op_for_pluck(exec_ctx=%p, cc=%p, tag=%p, error=%s, "
|
628
|
+
"done=%p, done_arg=%p, storage=%p)",
|
629
|
+
7, (exec_ctx, cc, tag, errmsg, done, done_arg, storage));
|
630
|
+
if (GRPC_TRACER_ON(grpc_trace_operation_failures) &&
|
631
|
+
error != GRPC_ERROR_NONE) {
|
632
|
+
gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg);
|
633
|
+
}
|
634
|
+
}
|
635
|
+
|
636
|
+
storage->tag = tag;
|
637
|
+
storage->done = done;
|
638
|
+
storage->done_arg = done_arg;
|
639
|
+
storage->next = ((uintptr_t)&cqd->completed_head) | ((uintptr_t)(is_success));
|
640
|
+
|
641
|
+
gpr_mu_lock(cqd->mu);
|
642
|
+
cq_check_tag(cc, tag, false); /* Used in debug builds only */
|
643
|
+
|
644
|
+
/* Add to the list of completions */
|
645
|
+
gpr_atm_no_barrier_fetch_add(&cqd->things_queued_ever, 1);
|
646
|
+
cqd->completed_tail->next =
|
647
|
+
((uintptr_t)storage) | (1u & (uintptr_t)cqd->completed_tail->next);
|
648
|
+
cqd->completed_tail = storage;
|
649
|
+
|
650
|
+
int shutdown = gpr_unref(&cqd->pending_events);
|
251
651
|
if (!shutdown) {
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
for (i = 0; i < cc->num_pluckers; i++) {
|
257
|
-
if (cc->pluckers[i].tag == tag) {
|
258
|
-
pluck_worker = *cc->pluckers[i].worker;
|
652
|
+
grpc_pollset_worker *pluck_worker = NULL;
|
653
|
+
for (int i = 0; i < cqd->num_pluckers; i++) {
|
654
|
+
if (cqd->pluckers[i].tag == tag) {
|
655
|
+
pluck_worker = *cqd->pluckers[i].worker;
|
259
656
|
break;
|
260
657
|
}
|
261
658
|
}
|
659
|
+
|
262
660
|
grpc_error *kick_error =
|
263
|
-
|
264
|
-
|
661
|
+
cc->poller_vtable->kick(POLLSET_FROM_CQ(cc), pluck_worker);
|
662
|
+
|
663
|
+
gpr_mu_unlock(cqd->mu);
|
664
|
+
|
265
665
|
if (kick_error != GRPC_ERROR_NONE) {
|
266
666
|
const char *msg = grpc_error_string(kick_error);
|
267
667
|
gpr_log(GPR_ERROR, "Kick failed: %s", msg);
|
@@ -269,22 +669,23 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
|
|
269
669
|
GRPC_ERROR_UNREF(kick_error);
|
270
670
|
}
|
271
671
|
} else {
|
272
|
-
cc
|
273
|
-
|
274
|
-
cc->completed_tail = storage;
|
275
|
-
GPR_ASSERT(!cc->shutdown);
|
276
|
-
GPR_ASSERT(cc->shutdown_called);
|
277
|
-
cc->shutdown = 1;
|
278
|
-
grpc_pollset_shutdown(exec_ctx, POLLSET_FROM_CQ(cc),
|
279
|
-
&cc->pollset_shutdown_done);
|
280
|
-
gpr_mu_unlock(cc->mu);
|
672
|
+
cq_finish_shutdown(exec_ctx, cc);
|
673
|
+
gpr_mu_unlock(cqd->mu);
|
281
674
|
}
|
282
675
|
|
283
|
-
GPR_TIMER_END("
|
676
|
+
GPR_TIMER_END("cq_end_op_for_pluck", 0);
|
284
677
|
|
285
678
|
GRPC_ERROR_UNREF(error);
|
286
679
|
}
|
287
680
|
|
681
|
+
void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc,
|
682
|
+
void *tag, grpc_error *error,
|
683
|
+
void (*done)(grpc_exec_ctx *exec_ctx, void *done_arg,
|
684
|
+
grpc_cq_completion *storage),
|
685
|
+
void *done_arg, grpc_cq_completion *storage) {
|
686
|
+
cc->vtable->end_op(exec_ctx, cc, tag, error, done, done_arg, storage);
|
687
|
+
}
|
688
|
+
|
288
689
|
typedef struct {
|
289
690
|
gpr_atm last_seen_things_queued_ever;
|
290
691
|
grpc_completion_queue *cq;
|
@@ -297,23 +698,24 @@ typedef struct {
|
|
297
698
|
static bool cq_is_next_finished(grpc_exec_ctx *exec_ctx, void *arg) {
|
298
699
|
cq_is_finished_arg *a = arg;
|
299
700
|
grpc_completion_queue *cq = a->cq;
|
701
|
+
cq_data *cqd = &cq->data;
|
300
702
|
GPR_ASSERT(a->stolen_completion == NULL);
|
703
|
+
|
301
704
|
gpr_atm current_last_seen_things_queued_ever =
|
302
|
-
gpr_atm_no_barrier_load(&
|
705
|
+
gpr_atm_no_barrier_load(&cqd->things_queued_ever);
|
706
|
+
|
303
707
|
if (current_last_seen_things_queued_ever != a->last_seen_things_queued_ever) {
|
304
|
-
gpr_mu_lock(cq->mu);
|
305
708
|
a->last_seen_things_queued_ever =
|
306
|
-
gpr_atm_no_barrier_load(&
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
709
|
+
gpr_atm_no_barrier_load(&cqd->things_queued_ever);
|
710
|
+
|
711
|
+
/* Pop a cq_completion from the queue. Returns NULL if the queue is empty
|
712
|
+
* might return NULL in some cases even if the queue is not empty; but that
|
713
|
+
* is ok and doesn't affect correctness. Might effect the tail latencies a
|
714
|
+
* bit) */
|
715
|
+
a->stolen_completion = cq_event_queue_pop(&cqd->queue);
|
716
|
+
if (a->stolen_completion != NULL) {
|
314
717
|
return true;
|
315
718
|
}
|
316
|
-
gpr_mu_unlock(cq->mu);
|
317
719
|
}
|
318
720
|
return !a->first_loop &&
|
319
721
|
gpr_time_cmp(a->deadline, gpr_now(a->deadline.clock_type)) < 0;
|
@@ -321,18 +723,20 @@ static bool cq_is_next_finished(grpc_exec_ctx *exec_ctx, void *arg) {
|
|
321
723
|
|
322
724
|
#ifndef NDEBUG
|
323
725
|
static void dump_pending_tags(grpc_completion_queue *cc) {
|
324
|
-
if (!grpc_trace_pending_tags) return;
|
726
|
+
if (!GRPC_TRACER_ON(grpc_trace_pending_tags)) return;
|
727
|
+
|
728
|
+
cq_data *cqd = &cc->data;
|
325
729
|
|
326
730
|
gpr_strvec v;
|
327
731
|
gpr_strvec_init(&v);
|
328
732
|
gpr_strvec_add(&v, gpr_strdup("PENDING TAGS:"));
|
329
|
-
gpr_mu_lock(
|
330
|
-
for (size_t i = 0; i <
|
733
|
+
gpr_mu_lock(cqd->mu);
|
734
|
+
for (size_t i = 0; i < cqd->outstanding_tag_count; i++) {
|
331
735
|
char *s;
|
332
|
-
gpr_asprintf(&s, " %p",
|
736
|
+
gpr_asprintf(&s, " %p", cqd->outstanding_tags[i]);
|
333
737
|
gpr_strvec_add(&v, s);
|
334
738
|
}
|
335
|
-
gpr_mu_unlock(
|
739
|
+
gpr_mu_unlock(cqd->mu);
|
336
740
|
char *out = gpr_strvec_flatten(&v, NULL);
|
337
741
|
gpr_strvec_destroy(&v);
|
338
742
|
gpr_log(GPR_DEBUG, "%s", out);
|
@@ -342,10 +746,11 @@ static void dump_pending_tags(grpc_completion_queue *cc) {
|
|
342
746
|
static void dump_pending_tags(grpc_completion_queue *cc) {}
|
343
747
|
#endif
|
344
748
|
|
345
|
-
grpc_event
|
346
|
-
|
749
|
+
static grpc_event cq_next(grpc_completion_queue *cc, gpr_timespec deadline,
|
750
|
+
void *reserved) {
|
347
751
|
grpc_event ret;
|
348
752
|
gpr_timespec now;
|
753
|
+
cq_data *cqd = &cc->data;
|
349
754
|
|
350
755
|
GPR_TIMER_BEGIN("grpc_completion_queue_next", 0);
|
351
756
|
|
@@ -364,10 +769,10 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
|
|
364
769
|
deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
|
365
770
|
|
366
771
|
GRPC_CQ_INTERNAL_REF(cc, "next");
|
367
|
-
|
772
|
+
|
368
773
|
cq_is_finished_arg is_finished_arg = {
|
369
774
|
.last_seen_things_queued_ever =
|
370
|
-
gpr_atm_no_barrier_load(&
|
775
|
+
gpr_atm_no_barrier_load(&cqd->things_queued_ever),
|
371
776
|
.cq = cc,
|
372
777
|
.deadline = deadline,
|
373
778
|
.stolen_completion = NULL,
|
@@ -375,9 +780,11 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
|
|
375
780
|
.first_loop = true};
|
376
781
|
grpc_exec_ctx exec_ctx =
|
377
782
|
GRPC_EXEC_CTX_INITIALIZER(0, cq_is_next_finished, &is_finished_arg);
|
783
|
+
|
378
784
|
for (;;) {
|
785
|
+
gpr_timespec iteration_deadline = deadline;
|
786
|
+
|
379
787
|
if (is_finished_arg.stolen_completion != NULL) {
|
380
|
-
gpr_mu_unlock(cc->mu);
|
381
788
|
grpc_cq_completion *c = is_finished_arg.stolen_completion;
|
382
789
|
is_finished_arg.stolen_completion = NULL;
|
383
790
|
ret.type = GRPC_OP_COMPLETE;
|
@@ -386,63 +793,73 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
|
|
386
793
|
c->done(&exec_ctx, c->done_arg, c);
|
387
794
|
break;
|
388
795
|
}
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
cc->completed_tail = &cc->completed_head;
|
394
|
-
}
|
395
|
-
gpr_mu_unlock(cc->mu);
|
796
|
+
|
797
|
+
grpc_cq_completion *c = cq_event_queue_pop(&cqd->queue);
|
798
|
+
|
799
|
+
if (c != NULL) {
|
396
800
|
ret.type = GRPC_OP_COMPLETE;
|
397
801
|
ret.success = c->next & 1u;
|
398
802
|
ret.tag = c->tag;
|
399
803
|
c->done(&exec_ctx, c->done_arg, c);
|
400
804
|
break;
|
805
|
+
} else {
|
806
|
+
/* If c == NULL it means either the queue is empty OR in an transient
|
807
|
+
inconsistent state. If it is the latter, we shold do a 0-timeout poll
|
808
|
+
so that the thread comes back quickly from poll to make a second
|
809
|
+
attempt at popping. Not doing this can potentially deadlock this thread
|
810
|
+
forever (if the deadline is infinity) */
|
811
|
+
if (cq_event_queue_num_items(&cqd->queue) > 0) {
|
812
|
+
iteration_deadline = gpr_time_0(GPR_CLOCK_MONOTONIC);
|
813
|
+
}
|
401
814
|
}
|
402
|
-
|
403
|
-
|
815
|
+
|
816
|
+
if (gpr_atm_no_barrier_load(&cqd->shutdown)) {
|
817
|
+
/* Before returning, check if the queue has any items left over (since
|
818
|
+
gpr_mpscq_pop() can sometimes return NULL even if the queue is not
|
819
|
+
empty. If so, keep retrying but do not return GRPC_QUEUE_SHUTDOWN */
|
820
|
+
if (cq_event_queue_num_items(&cqd->queue) > 0) {
|
821
|
+
/* Go to the beginning of the loop. No point doing a poll because
|
822
|
+
(cc->shutdown == true) is only possible when there is no pending work
|
823
|
+
(i.e cc->pending_events == 0) and any outstanding grpc_cq_completion
|
824
|
+
events are already queued on this cq */
|
825
|
+
continue;
|
826
|
+
}
|
827
|
+
|
404
828
|
memset(&ret, 0, sizeof(ret));
|
405
829
|
ret.type = GRPC_QUEUE_SHUTDOWN;
|
406
830
|
break;
|
407
831
|
}
|
832
|
+
|
408
833
|
now = gpr_now(GPR_CLOCK_MONOTONIC);
|
409
834
|
if (!is_finished_arg.first_loop && gpr_time_cmp(now, deadline) >= 0) {
|
410
|
-
gpr_mu_unlock(cc->mu);
|
411
835
|
memset(&ret, 0, sizeof(ret));
|
412
836
|
ret.type = GRPC_QUEUE_TIMEOUT;
|
413
837
|
dump_pending_tags(cc);
|
414
838
|
break;
|
415
839
|
}
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg);
|
434
|
-
|
435
|
-
GRPC_ERROR_UNREF(err);
|
436
|
-
memset(&ret, 0, sizeof(ret));
|
437
|
-
ret.type = GRPC_QUEUE_TIMEOUT;
|
438
|
-
dump_pending_tags(cc);
|
439
|
-
break;
|
440
|
-
}
|
840
|
+
|
841
|
+
/* The main polling work happens in grpc_pollset_work */
|
842
|
+
gpr_mu_lock(cqd->mu);
|
843
|
+
cqd->num_polls++;
|
844
|
+
grpc_error *err = cc->poller_vtable->work(&exec_ctx, POLLSET_FROM_CQ(cc),
|
845
|
+
NULL, now, iteration_deadline);
|
846
|
+
gpr_mu_unlock(cqd->mu);
|
847
|
+
|
848
|
+
if (err != GRPC_ERROR_NONE) {
|
849
|
+
const char *msg = grpc_error_string(err);
|
850
|
+
gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg);
|
851
|
+
|
852
|
+
GRPC_ERROR_UNREF(err);
|
853
|
+
memset(&ret, 0, sizeof(ret));
|
854
|
+
ret.type = GRPC_QUEUE_TIMEOUT;
|
855
|
+
dump_pending_tags(cc);
|
856
|
+
break;
|
441
857
|
}
|
442
858
|
is_finished_arg.first_loop = false;
|
443
859
|
}
|
860
|
+
|
444
861
|
GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
|
445
|
-
GRPC_CQ_INTERNAL_UNREF(cc, "next");
|
862
|
+
GRPC_CQ_INTERNAL_UNREF(&exec_ctx, cc, "next");
|
446
863
|
grpc_exec_ctx_finish(&exec_ctx);
|
447
864
|
GPR_ASSERT(is_finished_arg.stolen_completion == NULL);
|
448
865
|
|
@@ -451,24 +868,30 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
|
|
451
868
|
return ret;
|
452
869
|
}
|
453
870
|
|
871
|
+
grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
|
872
|
+
gpr_timespec deadline, void *reserved) {
|
873
|
+
return cc->vtable->next(cc, deadline, reserved);
|
874
|
+
}
|
875
|
+
|
454
876
|
static int add_plucker(grpc_completion_queue *cc, void *tag,
|
455
877
|
grpc_pollset_worker **worker) {
|
456
|
-
|
878
|
+
cq_data *cqd = &cc->data;
|
879
|
+
if (cqd->num_pluckers == GRPC_MAX_COMPLETION_QUEUE_PLUCKERS) {
|
457
880
|
return 0;
|
458
881
|
}
|
459
|
-
|
460
|
-
|
461
|
-
|
882
|
+
cqd->pluckers[cqd->num_pluckers].tag = tag;
|
883
|
+
cqd->pluckers[cqd->num_pluckers].worker = worker;
|
884
|
+
cqd->num_pluckers++;
|
462
885
|
return 1;
|
463
886
|
}
|
464
887
|
|
465
888
|
static void del_plucker(grpc_completion_queue *cc, void *tag,
|
466
889
|
grpc_pollset_worker **worker) {
|
467
|
-
|
468
|
-
for (i = 0; i <
|
469
|
-
if (
|
470
|
-
|
471
|
-
GPR_SWAP(plucker,
|
890
|
+
cq_data *cqd = &cc->data;
|
891
|
+
for (int i = 0; i < cqd->num_pluckers; i++) {
|
892
|
+
if (cqd->pluckers[i].tag == tag && cqd->pluckers[i].worker == worker) {
|
893
|
+
cqd->num_pluckers--;
|
894
|
+
GPR_SWAP(plucker, cqd->pluckers[i], cqd->pluckers[cqd->num_pluckers]);
|
472
895
|
return;
|
473
896
|
}
|
474
897
|
}
|
@@ -478,45 +901,48 @@ static void del_plucker(grpc_completion_queue *cc, void *tag,
|
|
478
901
|
static bool cq_is_pluck_finished(grpc_exec_ctx *exec_ctx, void *arg) {
|
479
902
|
cq_is_finished_arg *a = arg;
|
480
903
|
grpc_completion_queue *cq = a->cq;
|
904
|
+
cq_data *cqd = &cq->data;
|
905
|
+
|
481
906
|
GPR_ASSERT(a->stolen_completion == NULL);
|
482
907
|
gpr_atm current_last_seen_things_queued_ever =
|
483
|
-
gpr_atm_no_barrier_load(&
|
908
|
+
gpr_atm_no_barrier_load(&cqd->things_queued_ever);
|
484
909
|
if (current_last_seen_things_queued_ever != a->last_seen_things_queued_ever) {
|
485
|
-
gpr_mu_lock(
|
910
|
+
gpr_mu_lock(cqd->mu);
|
486
911
|
a->last_seen_things_queued_ever =
|
487
|
-
gpr_atm_no_barrier_load(&
|
912
|
+
gpr_atm_no_barrier_load(&cqd->things_queued_ever);
|
488
913
|
grpc_cq_completion *c;
|
489
|
-
grpc_cq_completion *prev = &
|
914
|
+
grpc_cq_completion *prev = &cqd->completed_head;
|
490
915
|
while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) !=
|
491
|
-
&
|
916
|
+
&cqd->completed_head) {
|
492
917
|
if (c->tag == a->tag) {
|
493
918
|
prev->next = (prev->next & (uintptr_t)1) | (c->next & ~(uintptr_t)1);
|
494
|
-
if (c ==
|
495
|
-
|
919
|
+
if (c == cqd->completed_tail) {
|
920
|
+
cqd->completed_tail = prev;
|
496
921
|
}
|
497
|
-
gpr_mu_unlock(
|
922
|
+
gpr_mu_unlock(cqd->mu);
|
498
923
|
a->stolen_completion = c;
|
499
924
|
return true;
|
500
925
|
}
|
501
926
|
prev = c;
|
502
927
|
}
|
503
|
-
gpr_mu_unlock(
|
928
|
+
gpr_mu_unlock(cqd->mu);
|
504
929
|
}
|
505
930
|
return !a->first_loop &&
|
506
931
|
gpr_time_cmp(a->deadline, gpr_now(a->deadline.clock_type)) < 0;
|
507
932
|
}
|
508
933
|
|
509
|
-
grpc_event
|
510
|
-
|
934
|
+
static grpc_event cq_pluck(grpc_completion_queue *cc, void *tag,
|
935
|
+
gpr_timespec deadline, void *reserved) {
|
511
936
|
grpc_event ret;
|
512
937
|
grpc_cq_completion *c;
|
513
938
|
grpc_cq_completion *prev;
|
514
939
|
grpc_pollset_worker *worker = NULL;
|
515
940
|
gpr_timespec now;
|
941
|
+
cq_data *cqd = &cc->data;
|
516
942
|
|
517
943
|
GPR_TIMER_BEGIN("grpc_completion_queue_pluck", 0);
|
518
944
|
|
519
|
-
if (grpc_cq_pluck_trace) {
|
945
|
+
if (GRPC_TRACER_ON(grpc_cq_pluck_trace)) {
|
520
946
|
GRPC_API_TRACE(
|
521
947
|
"grpc_completion_queue_pluck("
|
522
948
|
"cc=%p, tag=%p, "
|
@@ -533,10 +959,10 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
|
|
533
959
|
deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
|
534
960
|
|
535
961
|
GRPC_CQ_INTERNAL_REF(cc, "pluck");
|
536
|
-
gpr_mu_lock(
|
962
|
+
gpr_mu_lock(cqd->mu);
|
537
963
|
cq_is_finished_arg is_finished_arg = {
|
538
964
|
.last_seen_things_queued_ever =
|
539
|
-
gpr_atm_no_barrier_load(&
|
965
|
+
gpr_atm_no_barrier_load(&cqd->things_queued_ever),
|
540
966
|
.cq = cc,
|
541
967
|
.deadline = deadline,
|
542
968
|
.stolen_completion = NULL,
|
@@ -546,7 +972,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
|
|
546
972
|
GRPC_EXEC_CTX_INITIALIZER(0, cq_is_pluck_finished, &is_finished_arg);
|
547
973
|
for (;;) {
|
548
974
|
if (is_finished_arg.stolen_completion != NULL) {
|
549
|
-
gpr_mu_unlock(
|
975
|
+
gpr_mu_unlock(cqd->mu);
|
550
976
|
c = is_finished_arg.stolen_completion;
|
551
977
|
is_finished_arg.stolen_completion = NULL;
|
552
978
|
ret.type = GRPC_OP_COMPLETE;
|
@@ -555,15 +981,15 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
|
|
555
981
|
c->done(&exec_ctx, c->done_arg, c);
|
556
982
|
break;
|
557
983
|
}
|
558
|
-
prev = &
|
984
|
+
prev = &cqd->completed_head;
|
559
985
|
while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) !=
|
560
|
-
&
|
986
|
+
&cqd->completed_head) {
|
561
987
|
if (c->tag == tag) {
|
562
988
|
prev->next = (prev->next & (uintptr_t)1) | (c->next & ~(uintptr_t)1);
|
563
|
-
if (c ==
|
564
|
-
|
989
|
+
if (c == cqd->completed_tail) {
|
990
|
+
cqd->completed_tail = prev;
|
565
991
|
}
|
566
|
-
gpr_mu_unlock(
|
992
|
+
gpr_mu_unlock(cqd->mu);
|
567
993
|
ret.type = GRPC_OP_COMPLETE;
|
568
994
|
ret.success = c->next & 1u;
|
569
995
|
ret.tag = c->tag;
|
@@ -572,8 +998,8 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
|
|
572
998
|
}
|
573
999
|
prev = c;
|
574
1000
|
}
|
575
|
-
if (
|
576
|
-
gpr_mu_unlock(
|
1001
|
+
if (gpr_atm_no_barrier_load(&cqd->shutdown)) {
|
1002
|
+
gpr_mu_unlock(cqd->mu);
|
577
1003
|
memset(&ret, 0, sizeof(ret));
|
578
1004
|
ret.type = GRPC_QUEUE_SHUTDOWN;
|
579
1005
|
break;
|
@@ -583,7 +1009,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
|
|
583
1009
|
"Too many outstanding grpc_completion_queue_pluck calls: maximum "
|
584
1010
|
"is %d",
|
585
1011
|
GRPC_MAX_COMPLETION_QUEUE_PLUCKERS);
|
586
|
-
gpr_mu_unlock(
|
1012
|
+
gpr_mu_unlock(cqd->mu);
|
587
1013
|
memset(&ret, 0, sizeof(ret));
|
588
1014
|
/* TODO(ctiller): should we use a different result here */
|
589
1015
|
ret.type = GRPC_QUEUE_TIMEOUT;
|
@@ -593,44 +1019,34 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
|
|
593
1019
|
now = gpr_now(GPR_CLOCK_MONOTONIC);
|
594
1020
|
if (!is_finished_arg.first_loop && gpr_time_cmp(now, deadline) >= 0) {
|
595
1021
|
del_plucker(cc, tag, &worker);
|
596
|
-
gpr_mu_unlock(
|
1022
|
+
gpr_mu_unlock(cqd->mu);
|
597
1023
|
memset(&ret, 0, sizeof(ret));
|
598
1024
|
ret.type = GRPC_QUEUE_TIMEOUT;
|
599
1025
|
dump_pending_tags(cc);
|
600
1026
|
break;
|
601
1027
|
}
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
gpr_mu_unlock(cc->mu);
|
618
|
-
const char *msg = grpc_error_string(err);
|
619
|
-
gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg);
|
620
|
-
|
621
|
-
GRPC_ERROR_UNREF(err);
|
622
|
-
memset(&ret, 0, sizeof(ret));
|
623
|
-
ret.type = GRPC_QUEUE_TIMEOUT;
|
624
|
-
dump_pending_tags(cc);
|
625
|
-
break;
|
626
|
-
}
|
1028
|
+
|
1029
|
+
cqd->num_polls++;
|
1030
|
+
grpc_error *err = cc->poller_vtable->work(&exec_ctx, POLLSET_FROM_CQ(cc),
|
1031
|
+
&worker, now, deadline);
|
1032
|
+
if (err != GRPC_ERROR_NONE) {
|
1033
|
+
del_plucker(cc, tag, &worker);
|
1034
|
+
gpr_mu_unlock(cqd->mu);
|
1035
|
+
const char *msg = grpc_error_string(err);
|
1036
|
+
gpr_log(GPR_ERROR, "Completion queue pluck failed: %s", msg);
|
1037
|
+
|
1038
|
+
GRPC_ERROR_UNREF(err);
|
1039
|
+
memset(&ret, 0, sizeof(ret));
|
1040
|
+
ret.type = GRPC_QUEUE_TIMEOUT;
|
1041
|
+
dump_pending_tags(cc);
|
1042
|
+
break;
|
627
1043
|
}
|
628
1044
|
is_finished_arg.first_loop = false;
|
629
1045
|
del_plucker(cc, tag, &worker);
|
630
1046
|
}
|
631
1047
|
done:
|
632
1048
|
GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
|
633
|
-
GRPC_CQ_INTERNAL_UNREF(cc, "pluck");
|
1049
|
+
GRPC_CQ_INTERNAL_UNREF(&exec_ctx, cc, "pluck");
|
634
1050
|
grpc_exec_ctx_finish(&exec_ctx);
|
635
1051
|
GPR_ASSERT(is_finished_arg.stolen_completion == NULL);
|
636
1052
|
|
@@ -639,26 +1055,48 @@ done:
|
|
639
1055
|
return ret;
|
640
1056
|
}
|
641
1057
|
|
1058
|
+
grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
|
1059
|
+
gpr_timespec deadline, void *reserved) {
|
1060
|
+
return cc->vtable->pluck(cc, tag, deadline, reserved);
|
1061
|
+
}
|
1062
|
+
|
1063
|
+
/* Finishes the completion queue shutdown. This means that there are no more
|
1064
|
+
completion events / tags expected from the completion queue
|
1065
|
+
- Must be called under completion queue lock
|
1066
|
+
- Must be called only once in completion queue's lifetime
|
1067
|
+
- grpc_completion_queue_shutdown() MUST have been called before calling
|
1068
|
+
this function */
|
1069
|
+
static void cq_finish_shutdown(grpc_exec_ctx *exec_ctx,
|
1070
|
+
grpc_completion_queue *cc) {
|
1071
|
+
cq_data *cqd = &cc->data;
|
1072
|
+
|
1073
|
+
GPR_ASSERT(cqd->shutdown_called);
|
1074
|
+
GPR_ASSERT(!gpr_atm_no_barrier_load(&cqd->shutdown));
|
1075
|
+
gpr_atm_no_barrier_store(&cqd->shutdown, 1);
|
1076
|
+
|
1077
|
+
cc->poller_vtable->shutdown(exec_ctx, POLLSET_FROM_CQ(cc),
|
1078
|
+
&cqd->pollset_shutdown_done);
|
1079
|
+
}
|
1080
|
+
|
642
1081
|
/* Shutdown simply drops a ref that we reserved at creation time; if we drop
|
643
1082
|
to zero here, then enter shutdown mode and wake up any waiters */
|
644
1083
|
void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
|
645
1084
|
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
646
1085
|
GPR_TIMER_BEGIN("grpc_completion_queue_shutdown", 0);
|
647
1086
|
GRPC_API_TRACE("grpc_completion_queue_shutdown(cc=%p)", 1, (cc));
|
648
|
-
|
649
|
-
|
650
|
-
|
1087
|
+
cq_data *cqd = &cc->data;
|
1088
|
+
|
1089
|
+
gpr_mu_lock(cqd->mu);
|
1090
|
+
if (cqd->shutdown_called) {
|
1091
|
+
gpr_mu_unlock(cqd->mu);
|
651
1092
|
GPR_TIMER_END("grpc_completion_queue_shutdown", 0);
|
652
1093
|
return;
|
653
1094
|
}
|
654
|
-
|
655
|
-
if (gpr_unref(&
|
656
|
-
|
657
|
-
cc->shutdown = 1;
|
658
|
-
grpc_pollset_shutdown(&exec_ctx, POLLSET_FROM_CQ(cc),
|
659
|
-
&cc->pollset_shutdown_done);
|
1095
|
+
cqd->shutdown_called = 1;
|
1096
|
+
if (gpr_unref(&cqd->pending_events)) {
|
1097
|
+
cq_finish_shutdown(&exec_ctx, cc);
|
660
1098
|
}
|
661
|
-
gpr_mu_unlock(
|
1099
|
+
gpr_mu_unlock(cqd->mu);
|
662
1100
|
grpc_exec_ctx_finish(&exec_ctx);
|
663
1101
|
GPR_TIMER_END("grpc_completion_queue_shutdown", 0);
|
664
1102
|
}
|
@@ -667,26 +1105,35 @@ void grpc_completion_queue_destroy(grpc_completion_queue *cc) {
|
|
667
1105
|
GRPC_API_TRACE("grpc_completion_queue_destroy(cc=%p)", 1, (cc));
|
668
1106
|
GPR_TIMER_BEGIN("grpc_completion_queue_destroy", 0);
|
669
1107
|
grpc_completion_queue_shutdown(cc);
|
670
|
-
|
1108
|
+
|
1109
|
+
/* TODO (sreek): This should not ideally be here. Refactor it into the
|
1110
|
+
* cq_vtable (perhaps have a create/destroy methods in the cq vtable) */
|
1111
|
+
if (cc->vtable->cq_completion_type == GRPC_CQ_NEXT) {
|
1112
|
+
GPR_ASSERT(cq_event_queue_num_items(&cc->data.queue) == 0);
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
|
1116
|
+
GRPC_CQ_INTERNAL_UNREF(&exec_ctx, cc, "destroy");
|
1117
|
+
grpc_exec_ctx_finish(&exec_ctx);
|
671
1118
|
GPR_TIMER_END("grpc_completion_queue_destroy", 0);
|
672
1119
|
}
|
673
1120
|
|
674
1121
|
grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc) {
|
675
|
-
return POLLSET_FROM_CQ(cc);
|
1122
|
+
return cc->poller_vtable->can_get_pollset ? POLLSET_FROM_CQ(cc) : NULL;
|
676
1123
|
}
|
677
1124
|
|
678
1125
|
grpc_completion_queue *grpc_cq_from_pollset(grpc_pollset *ps) {
|
679
1126
|
return CQ_FROM_POLLSET(ps);
|
680
1127
|
}
|
681
1128
|
|
682
|
-
void
|
683
|
-
cc->
|
1129
|
+
void grpc_cq_mark_server_cq(grpc_completion_queue *cc) {
|
1130
|
+
cc->data.is_server_cq = 1;
|
684
1131
|
}
|
685
1132
|
|
686
|
-
bool
|
687
|
-
return
|
1133
|
+
bool grpc_cq_is_server_cq(grpc_completion_queue *cc) {
|
1134
|
+
return cc->data.is_server_cq;
|
688
1135
|
}
|
689
1136
|
|
690
|
-
|
691
|
-
|
692
|
-
|
1137
|
+
bool grpc_cq_can_listen(grpc_completion_queue *cc) {
|
1138
|
+
return cc->poller_vtable->can_listen;
|
1139
|
+
}
|