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.

Files changed (286) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +581 -450
  3. data/include/grpc/census.h +49 -49
  4. data/include/grpc/grpc.h +16 -70
  5. data/include/grpc/grpc_security.h +59 -59
  6. data/include/grpc/grpc_security_constants.h +9 -9
  7. data/include/grpc/impl/codegen/atm.h +1 -1
  8. data/include/grpc/impl/codegen/atm_windows.h +4 -4
  9. data/include/grpc/impl/codegen/byte_buffer_reader.h +2 -2
  10. data/include/grpc/impl/codegen/compression_types.h +4 -5
  11. data/include/grpc/impl/codegen/gpr_slice.h +5 -5
  12. data/include/grpc/impl/codegen/gpr_types.h +6 -7
  13. data/include/grpc/impl/codegen/grpc_types.h +128 -59
  14. data/include/grpc/impl/codegen/port_platform.h +6 -0
  15. data/include/grpc/impl/codegen/propagation_bits.h +2 -2
  16. data/include/grpc/impl/codegen/slice.h +13 -12
  17. data/include/grpc/impl/codegen/status.h +23 -18
  18. data/include/grpc/impl/codegen/sync.h +1 -1
  19. data/include/grpc/load_reporting.h +6 -6
  20. data/include/grpc/slice.h +47 -25
  21. data/include/grpc/slice_buffer.h +18 -14
  22. data/include/grpc/support/alloc.h +7 -7
  23. data/include/grpc/support/cmdline.h +10 -10
  24. data/include/grpc/support/cpu.h +3 -3
  25. data/include/grpc/support/histogram.h +1 -1
  26. data/include/grpc/support/host_port.h +2 -2
  27. data/include/grpc/support/log.h +9 -9
  28. data/include/grpc/support/log_windows.h +1 -1
  29. data/include/grpc/support/string_util.h +3 -3
  30. data/include/grpc/support/subprocess.h +3 -3
  31. data/include/grpc/support/sync.h +31 -31
  32. data/include/grpc/support/thd.h +11 -11
  33. data/include/grpc/support/time.h +12 -12
  34. data/include/grpc/support/tls.h +1 -1
  35. data/include/grpc/support/tls_gcc.h +2 -2
  36. data/include/grpc/support/tls_msvc.h +1 -1
  37. data/include/grpc/support/tls_pthread.h +1 -1
  38. data/include/grpc/support/useful.h +2 -2
  39. data/include/grpc/support/workaround_list.h +46 -0
  40. data/src/core/ext/census/context.c +1 -1
  41. data/src/core/ext/census/intrusive_hash_map.c +319 -0
  42. data/src/core/ext/census/intrusive_hash_map.h +167 -0
  43. data/src/core/ext/census/intrusive_hash_map_internal.h +63 -0
  44. data/src/core/ext/census/resource.c +3 -1
  45. data/src/core/ext/filters/client_channel/channel_connectivity.c +1 -1
  46. data/src/core/ext/filters/client_channel/client_channel.c +173 -103
  47. data/src/core/ext/filters/client_channel/client_channel_plugin.c +3 -2
  48. data/src/core/ext/filters/client_channel/lb_policy.c +2 -1
  49. data/src/core/ext/filters/client_channel/lb_policy.h +8 -7
  50. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c +153 -0
  51. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h +42 -0
  52. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c +405 -102
  53. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c +133 -0
  54. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +65 -0
  55. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c +90 -51
  56. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +7 -1
  57. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +19 -8
  58. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +63 -34
  59. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c +2 -1
  60. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c +188 -294
  61. data/src/core/ext/filters/client_channel/lb_policy_factory.c +28 -5
  62. data/src/core/ext/filters/client_channel/lb_policy_factory.h +18 -4
  63. data/src/core/ext/filters/client_channel/parse_address.c +90 -59
  64. data/src/core/ext/filters/client_channel/parse_address.h +17 -8
  65. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c +11 -7
  66. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c +59 -14
  67. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +6 -0
  68. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c +3 -3
  69. data/src/core/ext/filters/client_channel/subchannel.c +20 -17
  70. data/src/core/ext/filters/client_channel/subchannel.h +1 -0
  71. data/src/core/ext/filters/client_channel/subchannel_index.c +11 -1
  72. data/src/core/ext/filters/client_channel/uri_parser.c +36 -22
  73. data/src/core/ext/filters/client_channel/uri_parser.h +1 -1
  74. data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.c +42 -17
  75. data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.h +8 -9
  76. data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.c +19 -11
  77. data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.h +3 -6
  78. data/src/core/ext/filters/http/http_filters_plugin.c +104 -0
  79. data/src/core/{lib/channel/compress_filter.c → ext/filters/http/message_compress/message_compress_filter.c} +124 -23
  80. data/src/core/{lib/channel/compress_filter.h → ext/filters/http/message_compress/message_compress_filter.h} +5 -6
  81. data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.c +4 -6
  82. data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.h +3 -3
  83. data/src/core/ext/filters/load_reporting/load_reporting.c +2 -25
  84. data/src/core/ext/filters/load_reporting/load_reporting_filter.c +26 -1
  85. data/src/core/ext/filters/max_age/max_age_filter.c +14 -14
  86. data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.c +91 -47
  87. data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.h +3 -3
  88. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.c +223 -0
  89. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h +40 -0
  90. data/src/core/ext/filters/workarounds/workaround_utils.c +65 -0
  91. data/src/core/ext/filters/workarounds/workaround_utils.h +52 -0
  92. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +1 -1
  93. data/src/core/ext/transport/chttp2/server/chttp2_server.c +3 -2
  94. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +2 -2
  95. data/src/core/ext/transport/chttp2/transport/bin_encoder.c +3 -3
  96. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +319 -175
  97. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +3 -2
  98. data/src/core/ext/transport/chttp2/transport/frame_data.c +203 -164
  99. data/src/core/ext/transport/chttp2/transport/frame_data.h +8 -14
  100. data/src/core/ext/transport/chttp2/transport/frame_goaway.c +1 -1
  101. data/src/core/ext/transport/chttp2/transport/frame_ping.c +1 -1
  102. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +1 -1
  103. data/src/core/ext/transport/chttp2/transport/frame_settings.c +5 -5
  104. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +1 -1
  105. data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +4 -4
  106. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +2 -4
  107. data/src/core/ext/transport/chttp2/transport/hpack_table.c +4 -3
  108. data/src/core/ext/transport/chttp2/transport/internal.h +50 -33
  109. data/src/core/ext/transport/chttp2/transport/parsing.c +10 -11
  110. data/src/core/ext/transport/chttp2/transport/writing.c +32 -13
  111. data/src/core/lib/channel/channel_args.c +30 -9
  112. data/src/core/lib/channel/channel_args.h +5 -1
  113. data/src/core/lib/channel/channel_stack.c +1 -1
  114. data/src/core/lib/channel/channel_stack.h +2 -2
  115. data/src/core/lib/channel/channel_stack_builder.c +13 -1
  116. data/src/core/lib/channel/channel_stack_builder.h +5 -1
  117. data/src/core/lib/channel/connected_channel.c +3 -1
  118. data/src/core/lib/channel/context.h +2 -2
  119. data/src/core/lib/compression/message_compress.c +2 -2
  120. data/src/core/lib/debug/trace.c +13 -6
  121. data/src/core/lib/debug/trace.h +27 -1
  122. data/src/core/lib/http/httpcli.c +1 -1
  123. data/src/core/lib/http/httpcli_security_connector.c +9 -11
  124. data/src/core/lib/http/parser.c +2 -2
  125. data/src/core/lib/http/parser.h +2 -1
  126. data/src/core/lib/iomgr/combiner.c +6 -6
  127. data/src/core/lib/iomgr/combiner.h +2 -1
  128. data/src/core/lib/iomgr/error.c +12 -5
  129. data/src/core/lib/iomgr/error.h +13 -13
  130. data/src/core/lib/iomgr/ev_epoll1_linux.c +984 -0
  131. data/src/core/lib/iomgr/ev_epoll1_linux.h +44 -0
  132. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c +2146 -0
  133. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h +43 -0
  134. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c +1337 -0
  135. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.h +43 -0
  136. data/src/core/lib/iomgr/ev_epollex_linux.c +1511 -0
  137. data/src/core/lib/iomgr/ev_epollex_linux.h +43 -0
  138. data/src/core/lib/iomgr/{ev_epoll_linux.c → ev_epollsig_linux.c} +41 -33
  139. data/src/core/lib/iomgr/{ev_epoll_linux.h → ev_epollsig_linux.h} +4 -4
  140. data/src/core/lib/iomgr/ev_poll_posix.c +12 -27
  141. data/src/core/lib/iomgr/ev_poll_posix.h +2 -2
  142. data/src/core/lib/iomgr/ev_posix.c +22 -8
  143. data/src/core/lib/iomgr/ev_posix.h +4 -3
  144. data/src/core/lib/iomgr/ev_windows.c +43 -0
  145. data/src/core/lib/iomgr/exec_ctx.c +5 -0
  146. data/src/core/lib/iomgr/exec_ctx.h +2 -0
  147. data/src/core/lib/iomgr/iomgr.c +4 -0
  148. data/src/core/lib/iomgr/iomgr.h +3 -0
  149. data/src/core/lib/iomgr/is_epollexclusive_available.c +116 -0
  150. data/src/core/lib/iomgr/is_epollexclusive_available.h +41 -0
  151. data/src/core/lib/iomgr/lockfree_event.c +16 -0
  152. data/src/core/lib/iomgr/pollset.h +2 -5
  153. data/src/core/lib/iomgr/pollset_uv.c +1 -1
  154. data/src/core/lib/iomgr/pollset_windows.c +3 -3
  155. data/src/core/lib/iomgr/resource_quota.c +9 -8
  156. data/src/core/lib/iomgr/resource_quota.h +2 -1
  157. data/src/core/lib/iomgr/sockaddr_utils.h +1 -1
  158. data/src/core/lib/iomgr/socket_mutator.h +2 -0
  159. data/src/core/lib/iomgr/sys_epoll_wrapper.h +43 -0
  160. data/src/core/lib/iomgr/tcp_client_posix.c +6 -6
  161. data/src/core/lib/iomgr/tcp_client_uv.c +3 -3
  162. data/src/core/lib/iomgr/tcp_posix.c +7 -7
  163. data/src/core/lib/iomgr/tcp_posix.h +2 -1
  164. data/src/core/lib/iomgr/tcp_server_posix.c +1 -1
  165. data/src/core/lib/iomgr/tcp_uv.c +6 -6
  166. data/src/core/lib/iomgr/tcp_uv.h +2 -1
  167. data/src/core/lib/iomgr/tcp_windows.c +1 -1
  168. data/src/core/lib/iomgr/timer_generic.c +24 -25
  169. data/src/core/lib/iomgr/timer_manager.c +276 -0
  170. data/src/core/lib/iomgr/timer_manager.h +52 -0
  171. data/src/core/lib/iomgr/timer_uv.c +6 -0
  172. data/src/core/lib/iomgr/udp_server.c +42 -9
  173. data/src/core/lib/iomgr/udp_server.h +3 -1
  174. data/src/core/lib/security/credentials/credentials.c +0 -1
  175. data/src/core/lib/security/credentials/fake/fake_credentials.c +23 -0
  176. data/src/core/lib/security/credentials/fake/fake_credentials.h +12 -9
  177. data/src/core/lib/security/credentials/google_default/google_default_credentials.c +1 -1
  178. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -1
  179. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +1 -1
  180. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +24 -53
  181. data/src/core/lib/security/transport/client_auth_filter.c +9 -3
  182. data/src/core/lib/security/transport/secure_endpoint.c +7 -7
  183. data/src/core/lib/security/transport/secure_endpoint.h +1 -1
  184. data/src/core/lib/security/transport/security_connector.c +45 -57
  185. data/src/core/lib/security/transport/security_connector.h +10 -14
  186. data/src/core/lib/security/transport/security_handshaker.c +123 -97
  187. data/src/core/lib/slice/b64.c +1 -1
  188. data/src/core/lib/slice/percent_encoding.c +3 -3
  189. data/src/core/lib/slice/slice.c +66 -33
  190. data/src/core/lib/slice/slice_buffer.c +25 -6
  191. data/src/core/lib/slice/slice_hash_table.c +33 -35
  192. data/src/core/lib/slice/slice_hash_table.h +7 -12
  193. data/src/core/lib/support/atomic.h +45 -0
  194. data/src/core/lib/support/atomic_with_atm.h +70 -0
  195. data/src/core/lib/support/atomic_with_std.h +48 -0
  196. data/src/core/lib/support/avl.c +14 -14
  197. data/src/core/lib/support/cmdline.c +3 -3
  198. data/src/core/lib/support/histogram.c +2 -2
  199. data/src/core/lib/support/host_port.c +1 -1
  200. data/src/core/lib/support/memory.h +74 -0
  201. data/src/core/lib/support/mpscq.c +36 -2
  202. data/src/core/lib/support/mpscq.h +28 -1
  203. data/src/core/lib/support/stack_lockfree.c +3 -36
  204. data/src/core/lib/support/string.c +12 -12
  205. data/src/core/lib/support/string_posix.c +1 -1
  206. data/src/core/lib/support/subprocess_posix.c +2 -2
  207. data/src/core/lib/support/thd_posix.c +1 -1
  208. data/src/core/lib/support/time_posix.c +8 -0
  209. data/src/core/lib/support/tmpfile_posix.c +10 -10
  210. data/src/core/lib/surface/alarm.c +3 -1
  211. data/src/core/lib/surface/api_trace.c +2 -1
  212. data/src/core/lib/surface/api_trace.h +2 -2
  213. data/src/core/lib/surface/byte_buffer_reader.c +1 -1
  214. data/src/core/lib/surface/call.c +65 -22
  215. data/src/core/lib/surface/call.h +4 -2
  216. data/src/core/lib/surface/channel_init.c +2 -19
  217. data/src/core/lib/surface/channel_stack_type.c +18 -0
  218. data/src/core/lib/surface/channel_stack_type.h +2 -0
  219. data/src/core/lib/surface/completion_queue.c +694 -247
  220. data/src/core/lib/surface/completion_queue.h +30 -13
  221. data/src/core/lib/surface/completion_queue_factory.c +24 -9
  222. data/src/core/lib/surface/init.c +1 -52
  223. data/src/core/lib/surface/{lame_client.c → lame_client.cc} +37 -26
  224. data/src/core/lib/surface/server.c +79 -110
  225. data/src/core/lib/surface/server.h +2 -1
  226. data/src/core/lib/surface/version.c +2 -2
  227. data/src/core/lib/transport/bdp_estimator.c +25 -9
  228. data/src/core/lib/transport/bdp_estimator.h +7 -1
  229. data/src/core/lib/transport/byte_stream.c +23 -9
  230. data/src/core/lib/transport/byte_stream.h +15 -6
  231. data/src/core/lib/transport/connectivity_state.c +6 -6
  232. data/src/core/lib/transport/connectivity_state.h +2 -1
  233. data/src/core/lib/transport/service_config.c +6 -13
  234. data/src/core/lib/transport/service_config.h +2 -2
  235. data/src/core/lib/transport/static_metadata.c +403 -389
  236. data/src/core/lib/transport/static_metadata.h +127 -114
  237. data/src/core/plugin_registry/grpc_plugin_registry.c +16 -0
  238. data/src/core/tsi/fake_transport_security.c +5 -4
  239. data/src/core/tsi/ssl_transport_security.c +71 -82
  240. data/src/core/tsi/ssl_transport_security.h +39 -61
  241. data/src/core/tsi/transport_security.c +83 -2
  242. data/src/core/tsi/transport_security.h +27 -2
  243. data/src/core/tsi/transport_security_adapter.c +236 -0
  244. data/src/core/tsi/transport_security_adapter.h +62 -0
  245. data/src/core/tsi/transport_security_interface.h +179 -66
  246. data/src/ruby/ext/grpc/extconf.rb +2 -1
  247. data/src/ruby/ext/grpc/rb_byte_buffer.c +8 -6
  248. data/src/ruby/ext/grpc/rb_call.c +56 -48
  249. data/src/ruby/ext/grpc/rb_call.h +3 -4
  250. data/src/ruby/ext/grpc/rb_call_credentials.c +23 -22
  251. data/src/ruby/ext/grpc/rb_channel.c +2 -3
  252. data/src/ruby/ext/grpc/rb_channel_args.c +11 -9
  253. data/src/ruby/ext/grpc/rb_channel_credentials.c +16 -12
  254. data/src/ruby/ext/grpc/rb_completion_queue.c +7 -9
  255. data/src/ruby/ext/grpc/rb_compression_options.c +7 -6
  256. data/src/ruby/ext/grpc/rb_event_thread.c +10 -12
  257. data/src/ruby/ext/grpc/rb_event_thread.h +1 -2
  258. data/src/ruby/ext/grpc/rb_grpc.c +11 -15
  259. data/src/ruby/ext/grpc/rb_grpc.h +2 -2
  260. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +16 -6
  261. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +25 -10
  262. data/src/ruby/ext/grpc/rb_server.c +26 -28
  263. data/src/ruby/lib/grpc/grpc.rb +1 -1
  264. data/src/ruby/lib/grpc/version.rb +1 -1
  265. data/third_party/cares/config_linux/ares_config.h +36 -2
  266. data/third_party/zlib/adler32.c +14 -7
  267. data/third_party/zlib/compress.c +24 -18
  268. data/third_party/zlib/crc32.c +29 -12
  269. data/third_party/zlib/deflate.c +499 -303
  270. data/third_party/zlib/deflate.h +19 -16
  271. data/third_party/zlib/gzguts.h +16 -7
  272. data/third_party/zlib/gzlib.c +17 -14
  273. data/third_party/zlib/gzread.c +108 -48
  274. data/third_party/zlib/gzwrite.c +210 -122
  275. data/third_party/zlib/infback.c +2 -2
  276. data/third_party/zlib/inffast.c +34 -51
  277. data/third_party/zlib/inflate.c +86 -37
  278. data/third_party/zlib/inflate.h +7 -4
  279. data/third_party/zlib/inftrees.c +12 -14
  280. data/third_party/zlib/trees.c +38 -61
  281. data/third_party/zlib/uncompr.c +66 -32
  282. data/third_party/zlib/zconf.h +32 -9
  283. data/third_party/zlib/zlib.h +298 -154
  284. data/third_party/zlib/zutil.c +25 -24
  285. data/third_party/zlib/zutil.h +35 -17
  286. 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 *template;
53
+ char *filename_template;
54
54
  int fd;
55
55
 
56
56
  if (tmp_filename != NULL) *tmp_filename = NULL;
57
57
 
58
- gpr_asprintf(&template, "/tmp/%s_XXXXXX", prefix);
59
- GPR_ASSERT(template != NULL);
58
+ gpr_asprintf(&filename_template, "/tmp/%s_XXXXXX", prefix);
59
+ GPR_ASSERT(filename_template != NULL);
60
60
 
61
- fd = mkstemp(template);
61
+ fd = mkstemp(filename_template);
62
62
  if (fd == -1) {
63
- gpr_log(GPR_ERROR, "mkstemp failed for template %s with error %s.",
64
- template, strerror(errno));
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
- template, fd, strerror(errno));
71
- unlink(template);
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 = template;
78
+ *tmp_filename = filename_template;
79
79
  } else {
80
- gpr_free(template);
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
  }
@@ -32,5 +32,6 @@
32
32
  */
33
33
 
34
34
  #include "src/core/lib/surface/api_trace.h"
35
+ #include "src/core/lib/debug/trace.h"
35
36
 
36
- int grpc_api_trace = 0;
37
+ grpc_tracer_flag grpc_api_trace = GRPC_TRACER_INITIALIZER(false);
@@ -37,7 +37,7 @@
37
37
  #include <grpc/support/log.h>
38
38
  #include "src/core/lib/debug/trace.h"
39
39
 
40
- extern int grpc_api_trace;
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 = grpc_slice_malloc(input_size);
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;
@@ -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 grpc_call_destroy been called */
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
- int grpc_call_error_trace = 0;
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
- cancel_with_error(exec_ctx, call, STATUS_FROM_API_OVERRIDE,
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 grpc_call_destroy */
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 grpc_call_destroy(grpc_call *c) {
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("grpc_call_destroy", 0);
536
- GRPC_API_TRACE("grpc_call_destroy(c=%p)", 1, (c));
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("grpc_call_destroy", 0);
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
- grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
1205
- call->receiving_slice);
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
- grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
1219
- call->receiving_slice);
1220
- continue_receiving_slices(exec_ctx, bctl);
1221
- } else {
1222
- if (grpc_trace_operation_failures) {
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
- extern int grpc_compression_trace;
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);
@@ -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) grpc_call_log_batch(sev, call, ops, nops, tag)
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 int grpc_call_error_trace;
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, name_for_type(type));
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
+ }
@@ -55,4 +55,6 @@ typedef enum {
55
55
 
56
56
  bool grpc_channel_stack_type_is_client(grpc_channel_stack_type type);
57
57
 
58
+ const char *grpc_channel_stack_type_string(grpc_channel_stack_type type);
59
+
58
60
  #endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_STACK_TYPE_H */
@@ -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
- int grpc_trace_operation_failures;
53
+ grpc_tracer_flag grpc_trace_operation_failures = GRPC_TRACER_INITIALIZER(false);
54
54
  #ifndef NDEBUG
55
- int grpc_trace_pending_tags;
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
- /* Completion queue structure */
64
- struct grpc_completion_queue {
65
- /** owned by pollset */
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
- /** completed events */
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
- /** counter of how many things have ever been queued on this completion queue
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
- int shutdown;
259
+ gpr_atm shutdown;
79
260
  int shutdown_called;
261
+
80
262
  int is_server_cq;
81
- /** Can the server cq accept incoming channels */
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
- grpc_completion_queue *next_free;
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
- int grpc_cq_pluck_trace;
100
- int grpc_cq_event_timeout_trace;
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 || (event)->type != GRPC_QUEUE_TIMEOUT)) { \
105
- char *_ev = grpc_event_string(event); \
106
- gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \
107
- gpr_free(_ev); \
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
- grpc_completion_queue *grpc_completion_queue_create(void *reserved) {
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("grpc_completion_queue_create", 0);
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
- GRPC_API_TRACE("grpc_completion_queue_create(reserved=%p)", 1, (reserved));
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
- cc->outstanding_tags = NULL;
125
- cc->outstanding_tag_capacity = 0;
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(&cc->pending_events, 1);
420
+ gpr_ref_init(&cqd->pending_events, 1);
130
421
  /* One for destroy(), one for pollset_shutdown */
131
- gpr_ref_init(&cc->owning_refs, 2);
132
- cc->completed_tail = &cc->completed_head;
133
- cc->completed_head.next = (uintptr_t)cc->completed_tail;
134
- cc->shutdown = 0;
135
- cc->shutdown_called = 0;
136
- cc->is_server_cq = 0;
137
- cc->is_non_listening_server_cq = 0;
138
- cc->num_pluckers = 0;
139
- gpr_atm_no_barrier_store(&cc->things_queued_ever, 0);
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
- cc->outstanding_tag_count = 0;
432
+ cqd->outstanding_tag_count = 0;
142
433
  #endif
143
- grpc_closure_init(&cc->pollset_shutdown_done, on_pollset_shutdown_done, cc,
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("grpc_completion_queue_create", 0);
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)cc->owning_refs.count, (int)cc->owning_refs.count + 1, reason);
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(&cc->owning_refs);
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)cc->owning_refs.count, (int)cc->owning_refs.count - 1, reason);
479
+ (int)cqd->owning_refs.count, (int)cqd->owning_refs.count - 1, reason);
173
480
  #else
174
- void grpc_cq_internal_unref(grpc_completion_queue *cc) {
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(&cc->owning_refs)) {
177
- GPR_ASSERT(cc->completed_head.next == (uintptr_t)&cc->completed_head);
178
- grpc_pollset_destroy(POLLSET_FROM_CQ(cc));
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(cc->outstanding_tags);
490
+ gpr_free(cqd->outstanding_tags);
181
491
  #endif
182
492
  gpr_free(cc);
183
493
  }
184
494
  }
185
495
 
186
- void grpc_cq_begin_op(grpc_completion_queue *cc, void *tag) {
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(cc->mu);
189
- GPR_ASSERT(!cc->shutdown_called);
190
- if (cc->outstanding_tag_count == cc->outstanding_tag_capacity) {
191
- cc->outstanding_tag_capacity = GPR_MAX(4, 2 * cc->outstanding_tag_capacity);
192
- cc->outstanding_tags =
193
- gpr_realloc(cc->outstanding_tags, sizeof(*cc->outstanding_tags) *
194
- cc->outstanding_tag_capacity);
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
- cc->outstanding_tags[cc->outstanding_tag_count++] = tag;
197
- gpr_mu_unlock(cc->mu);
508
+ cqd->outstanding_tags[cqd->outstanding_tag_count++] = tag;
509
+ gpr_mu_unlock(cqd->mu);
198
510
  #endif
199
- gpr_ref(&cc->pending_events);
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
- GPR_TIMER_BEGIN("grpc_cq_end_op", 0);
218
- if (grpc_api_trace ||
219
- (grpc_trace_operation_failures && error != GRPC_ERROR_NONE)) {
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
- "grpc_cq_end_op(exec_ctx=%p, cc=%p, tag=%p, error=%s, done=%p, "
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 && error != GRPC_ERROR_NONE) {
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 = ((uintptr_t)&cc->completed_head) |
234
- ((uintptr_t)(error == GRPC_ERROR_NONE));
577
+ storage->next = (uintptr_t)(is_success);
235
578
 
236
- gpr_mu_lock(cc->mu);
237
- #ifndef NDEBUG
238
- for (i = 0; i < (int)cc->outstanding_tag_count; i++) {
239
- if (cc->outstanding_tags[i] == tag) {
240
- cc->outstanding_tag_count--;
241
- GPR_SWAP(void *, cc->outstanding_tags[i],
242
- cc->outstanding_tags[cc->outstanding_tag_count]);
243
- found = 1;
244
- break;
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
- GPR_ASSERT(found);
248
- #endif
249
- shutdown = gpr_unref(&cc->pending_events);
250
- gpr_atm_no_barrier_fetch_add(&cc->things_queued_ever, 1);
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
- cc->completed_tail->next =
253
- ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next);
254
- cc->completed_tail = storage;
255
- pluck_worker = NULL;
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
- grpc_pollset_kick(POLLSET_FROM_CQ(cc), pluck_worker);
264
- gpr_mu_unlock(cc->mu);
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->completed_tail->next =
273
- ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next);
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("grpc_cq_end_op", 0);
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(&cq->things_queued_ever);
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(&cq->things_queued_ever);
307
- if (cq->completed_tail != &cq->completed_head) {
308
- a->stolen_completion = (grpc_cq_completion *)cq->completed_head.next;
309
- cq->completed_head.next = a->stolen_completion->next & ~(uintptr_t)1;
310
- if (a->stolen_completion == cq->completed_tail) {
311
- cq->completed_tail = &cq->completed_head;
312
- }
313
- gpr_mu_unlock(cq->mu);
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(cc->mu);
330
- for (size_t i = 0; i < cc->outstanding_tag_count; 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", cc->outstanding_tags[i]);
736
+ gpr_asprintf(&s, " %p", cqd->outstanding_tags[i]);
333
737
  gpr_strvec_add(&v, s);
334
738
  }
335
- gpr_mu_unlock(cc->mu);
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 grpc_completion_queue_next(grpc_completion_queue *cc,
346
- gpr_timespec deadline, void *reserved) {
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
- gpr_mu_lock(cc->mu);
772
+
368
773
  cq_is_finished_arg is_finished_arg = {
369
774
  .last_seen_things_queued_ever =
370
- gpr_atm_no_barrier_load(&cc->things_queued_ever),
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
- if (cc->completed_tail != &cc->completed_head) {
390
- grpc_cq_completion *c = (grpc_cq_completion *)cc->completed_head.next;
391
- cc->completed_head.next = c->next & ~(uintptr_t)1;
392
- if (c == cc->completed_tail) {
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
- if (cc->shutdown) {
403
- gpr_mu_unlock(cc->mu);
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
- /* Check alarms - these are a global resource so we just ping
417
- each time through on every pollset.
418
- May update deadline to ensure timely wakeups.
419
- TODO(ctiller): can this work be localized? */
420
- gpr_timespec iteration_deadline = deadline;
421
- if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) {
422
- GPR_TIMER_MARK("alarm_triggered", 0);
423
- gpr_mu_unlock(cc->mu);
424
- grpc_exec_ctx_flush(&exec_ctx);
425
- gpr_mu_lock(cc->mu);
426
- continue;
427
- } else {
428
- grpc_error *err = grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc), NULL,
429
- now, iteration_deadline);
430
- if (err != GRPC_ERROR_NONE) {
431
- gpr_mu_unlock(cc->mu);
432
- const char *msg = grpc_error_string(err);
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
- if (cc->num_pluckers == GRPC_MAX_COMPLETION_QUEUE_PLUCKERS) {
878
+ cq_data *cqd = &cc->data;
879
+ if (cqd->num_pluckers == GRPC_MAX_COMPLETION_QUEUE_PLUCKERS) {
457
880
  return 0;
458
881
  }
459
- cc->pluckers[cc->num_pluckers].tag = tag;
460
- cc->pluckers[cc->num_pluckers].worker = worker;
461
- cc->num_pluckers++;
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
- int i;
468
- for (i = 0; i < cc->num_pluckers; i++) {
469
- if (cc->pluckers[i].tag == tag && cc->pluckers[i].worker == worker) {
470
- cc->num_pluckers--;
471
- GPR_SWAP(plucker, cc->pluckers[i], cc->pluckers[cc->num_pluckers]);
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(&cq->things_queued_ever);
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(cq->mu);
910
+ gpr_mu_lock(cqd->mu);
486
911
  a->last_seen_things_queued_ever =
487
- gpr_atm_no_barrier_load(&cq->things_queued_ever);
912
+ gpr_atm_no_barrier_load(&cqd->things_queued_ever);
488
913
  grpc_cq_completion *c;
489
- grpc_cq_completion *prev = &cq->completed_head;
914
+ grpc_cq_completion *prev = &cqd->completed_head;
490
915
  while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) !=
491
- &cq->completed_head) {
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 == cq->completed_tail) {
495
- cq->completed_tail = prev;
919
+ if (c == cqd->completed_tail) {
920
+ cqd->completed_tail = prev;
496
921
  }
497
- gpr_mu_unlock(cq->mu);
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(cq->mu);
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 grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
510
- gpr_timespec deadline, void *reserved) {
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(cc->mu);
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(&cc->things_queued_ever),
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(cc->mu);
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 = &cc->completed_head;
984
+ prev = &cqd->completed_head;
559
985
  while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) !=
560
- &cc->completed_head) {
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 == cc->completed_tail) {
564
- cc->completed_tail = prev;
989
+ if (c == cqd->completed_tail) {
990
+ cqd->completed_tail = prev;
565
991
  }
566
- gpr_mu_unlock(cc->mu);
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 (cc->shutdown) {
576
- gpr_mu_unlock(cc->mu);
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(cc->mu);
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(cc->mu);
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
- /* Check alarms - these are a global resource so we just ping
603
- each time through on every pollset.
604
- May update deadline to ensure timely wakeups.
605
- TODO(ctiller): can this work be localized? */
606
- gpr_timespec iteration_deadline = deadline;
607
- if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) {
608
- GPR_TIMER_MARK("alarm_triggered", 0);
609
- gpr_mu_unlock(cc->mu);
610
- grpc_exec_ctx_flush(&exec_ctx);
611
- gpr_mu_lock(cc->mu);
612
- } else {
613
- grpc_error *err = grpc_pollset_work(&exec_ctx, POLLSET_FROM_CQ(cc),
614
- &worker, now, iteration_deadline);
615
- if (err != GRPC_ERROR_NONE) {
616
- del_plucker(cc, tag, &worker);
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
- gpr_mu_lock(cc->mu);
649
- if (cc->shutdown_called) {
650
- gpr_mu_unlock(cc->mu);
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
- cc->shutdown_called = 1;
655
- if (gpr_unref(&cc->pending_events)) {
656
- GPR_ASSERT(!cc->shutdown);
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(cc->mu);
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
- GRPC_CQ_INTERNAL_UNREF(cc, "destroy");
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 grpc_cq_mark_non_listening_server_cq(grpc_completion_queue *cc) {
683
- cc->is_non_listening_server_cq = 1;
1129
+ void grpc_cq_mark_server_cq(grpc_completion_queue *cc) {
1130
+ cc->data.is_server_cq = 1;
684
1131
  }
685
1132
 
686
- bool grpc_cq_is_non_listening_server_cq(grpc_completion_queue *cc) {
687
- return (cc->is_non_listening_server_cq == 1);
1133
+ bool grpc_cq_is_server_cq(grpc_completion_queue *cc) {
1134
+ return cc->data.is_server_cq;
688
1135
  }
689
1136
 
690
- void grpc_cq_mark_server_cq(grpc_completion_queue *cc) { cc->is_server_cq = 1; }
691
-
692
- int grpc_cq_is_server_cq(grpc_completion_queue *cc) { return cc->is_server_cq; }
1137
+ bool grpc_cq_can_listen(grpc_completion_queue *cc) {
1138
+ return cc->poller_vtable->can_listen;
1139
+ }