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
@@ -138,7 +138,7 @@ typedef enum {
138
138
  const char *grpc_error_string(grpc_error *error);
139
139
 
140
140
  /// Create an error - but use GRPC_ERROR_CREATE instead
141
- grpc_error *grpc_error_create(grpc_slice file, int line, grpc_slice desc,
141
+ grpc_error *grpc_error_create(const char *file, int line, grpc_slice desc,
142
142
  grpc_error **referencing, size_t num_referencing);
143
143
  /// Create an error (this is the preferred way of generating an error that is
144
144
  /// not due to a system call - for system calls, use GRPC_OS_ERROR or
@@ -148,21 +148,21 @@ grpc_error *grpc_error_create(grpc_slice file, int line, grpc_slice desc,
148
148
  /// err = grpc_error_create(x, y, z, r, nr) is equivalent to:
149
149
  /// err = grpc_error_create(x, y, z, NULL, 0);
150
150
  /// for (i=0; i<nr; i++) err = grpc_error_add_child(err, r[i]);
151
- #define GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc) \
152
- grpc_error_create(grpc_slice_from_static_string(__FILE__), __LINE__, \
153
- grpc_slice_from_static_string(desc), NULL, 0)
154
- #define GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc) \
155
- grpc_error_create(grpc_slice_from_static_string(__FILE__), __LINE__, \
156
- grpc_slice_from_copied_string(desc), NULL, 0)
151
+ #define GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc) \
152
+ grpc_error_create(__FILE__, __LINE__, grpc_slice_from_static_string(desc), \
153
+ NULL, 0)
154
+ #define GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc) \
155
+ grpc_error_create(__FILE__, __LINE__, grpc_slice_from_copied_string(desc), \
156
+ NULL, 0)
157
157
 
158
158
  // Create an error that references some other errors. This function adds a
159
159
  // reference to each error in errs - it does not consume an existing reference
160
- #define GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(desc, errs, count) \
161
- grpc_error_create(grpc_slice_from_static_string(__FILE__), __LINE__, \
162
- grpc_slice_from_static_string(desc), errs, count)
163
- #define GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(desc, errs, count) \
164
- grpc_error_create(grpc_slice_from_static_string(__FILE__), __LINE__, \
165
- grpc_slice_from_copied_string(desc), errs, count)
160
+ #define GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(desc, errs, count) \
161
+ grpc_error_create(__FILE__, __LINE__, grpc_slice_from_static_string(desc), \
162
+ errs, count)
163
+ #define GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(desc, errs, count) \
164
+ grpc_error_create(__FILE__, __LINE__, grpc_slice_from_copied_string(desc), \
165
+ errs, count)
166
166
 
167
167
  //#define GRPC_ERROR_REFCOUNT_DEBUG
168
168
  #ifdef GRPC_ERROR_REFCOUNT_DEBUG
@@ -0,0 +1,984 @@
1
+ /*
2
+ *
3
+ * Copyright 2017, Google Inc.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are
8
+ * met:
9
+ *
10
+ * * Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above
13
+ * copyright notice, this list of conditions and the following disclaimer
14
+ * in the documentation and/or other materials provided with the
15
+ * distribution.
16
+ * * Neither the name of Google Inc. nor the names of its
17
+ * contributors may be used to endorse or promote products derived from
18
+ * this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ *
32
+ */
33
+
34
+ #include "src/core/lib/iomgr/port.h"
35
+
36
+ /* This polling engine is only relevant on linux kernels supporting epoll() */
37
+ #ifdef GRPC_LINUX_EPOLL
38
+
39
+ #include "src/core/lib/iomgr/ev_epoll1_linux.h"
40
+
41
+ #include <assert.h>
42
+ #include <errno.h>
43
+ #include <poll.h>
44
+ #include <pthread.h>
45
+ #include <string.h>
46
+ #include <sys/epoll.h>
47
+ #include <sys/socket.h>
48
+ #include <unistd.h>
49
+
50
+ #include <grpc/support/alloc.h>
51
+ #include <grpc/support/cpu.h>
52
+ #include <grpc/support/log.h>
53
+ #include <grpc/support/string_util.h>
54
+ #include <grpc/support/tls.h>
55
+ #include <grpc/support/useful.h>
56
+
57
+ #include "src/core/lib/iomgr/ev_posix.h"
58
+ #include "src/core/lib/iomgr/iomgr_internal.h"
59
+ #include "src/core/lib/iomgr/lockfree_event.h"
60
+ #include "src/core/lib/iomgr/wakeup_fd_posix.h"
61
+ #include "src/core/lib/iomgr/workqueue.h"
62
+ #include "src/core/lib/profiling/timers.h"
63
+ #include "src/core/lib/support/block_annotate.h"
64
+
65
+ static grpc_wakeup_fd global_wakeup_fd;
66
+ static int g_epfd;
67
+
68
+ /*******************************************************************************
69
+ * Fd Declarations
70
+ */
71
+
72
+ struct grpc_fd {
73
+ int fd;
74
+
75
+ gpr_atm read_closure;
76
+ gpr_atm write_closure;
77
+
78
+ struct grpc_fd *freelist_next;
79
+
80
+ /* The pollset that last noticed that the fd is readable. The actual type
81
+ * stored in this is (grpc_pollset *) */
82
+ gpr_atm read_notifier_pollset;
83
+
84
+ grpc_iomgr_object iomgr_object;
85
+ };
86
+
87
+ static void fd_global_init(void);
88
+ static void fd_global_shutdown(void);
89
+
90
+ /*******************************************************************************
91
+ * Pollset Declarations
92
+ */
93
+
94
+ typedef enum { UNKICKED, KICKED, DESIGNATED_POLLER } kick_state;
95
+
96
+ struct grpc_pollset_worker {
97
+ kick_state kick_state;
98
+ bool initialized_cv;
99
+ grpc_pollset_worker *next;
100
+ grpc_pollset_worker *prev;
101
+ gpr_cv cv;
102
+ grpc_closure_list schedule_on_end_work;
103
+ };
104
+
105
+ #define MAX_NEIGHBOURHOODS 1024
106
+
107
+ typedef struct pollset_neighbourhood {
108
+ gpr_mu mu;
109
+ grpc_pollset *active_root;
110
+ char pad[GPR_CACHELINE_SIZE];
111
+ } pollset_neighbourhood;
112
+
113
+ struct grpc_pollset {
114
+ gpr_mu mu;
115
+ pollset_neighbourhood *neighbourhood;
116
+ bool reassigning_neighbourhood;
117
+ grpc_pollset_worker *root_worker;
118
+ bool kicked_without_poller;
119
+ bool seen_inactive;
120
+ bool shutting_down; /* Is the pollset shutting down ? */
121
+ bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */
122
+ grpc_closure *shutdown_closure; /* Called after after shutdown is complete */
123
+ int begin_refs;
124
+
125
+ grpc_pollset *next;
126
+ grpc_pollset *prev;
127
+ };
128
+
129
+ /*******************************************************************************
130
+ * Pollset-set Declarations
131
+ */
132
+
133
+ struct grpc_pollset_set {};
134
+
135
+ /*******************************************************************************
136
+ * Common helpers
137
+ */
138
+
139
+ static bool append_error(grpc_error **composite, grpc_error *error,
140
+ const char *desc) {
141
+ if (error == GRPC_ERROR_NONE) return true;
142
+ if (*composite == GRPC_ERROR_NONE) {
143
+ *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc);
144
+ }
145
+ *composite = grpc_error_add_child(*composite, error);
146
+ return false;
147
+ }
148
+
149
+ /*******************************************************************************
150
+ * Fd Definitions
151
+ */
152
+
153
+ /* We need to keep a freelist not because of any concerns of malloc performance
154
+ * but instead so that implementations with multiple threads in (for example)
155
+ * epoll_wait deal with the race between pollset removal and incoming poll
156
+ * notifications.
157
+ *
158
+ * The problem is that the poller ultimately holds a reference to this
159
+ * object, so it is very difficult to know when is safe to free it, at least
160
+ * without some expensive synchronization.
161
+ *
162
+ * If we keep the object freelisted, in the worst case losing this race just
163
+ * becomes a spurious read notification on a reused fd.
164
+ */
165
+
166
+ /* The alarm system needs to be able to wakeup 'some poller' sometimes
167
+ * (specifically when a new alarm needs to be triggered earlier than the next
168
+ * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a
169
+ * case occurs. */
170
+
171
+ static grpc_fd *fd_freelist = NULL;
172
+ static gpr_mu fd_freelist_mu;
173
+
174
+ static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
175
+
176
+ static void fd_global_shutdown(void) {
177
+ gpr_mu_lock(&fd_freelist_mu);
178
+ gpr_mu_unlock(&fd_freelist_mu);
179
+ while (fd_freelist != NULL) {
180
+ grpc_fd *fd = fd_freelist;
181
+ fd_freelist = fd_freelist->freelist_next;
182
+ gpr_free(fd);
183
+ }
184
+ gpr_mu_destroy(&fd_freelist_mu);
185
+ }
186
+
187
+ static grpc_fd *fd_create(int fd, const char *name) {
188
+ grpc_fd *new_fd = NULL;
189
+
190
+ gpr_mu_lock(&fd_freelist_mu);
191
+ if (fd_freelist != NULL) {
192
+ new_fd = fd_freelist;
193
+ fd_freelist = fd_freelist->freelist_next;
194
+ }
195
+ gpr_mu_unlock(&fd_freelist_mu);
196
+
197
+ if (new_fd == NULL) {
198
+ new_fd = gpr_malloc(sizeof(grpc_fd));
199
+ }
200
+
201
+ new_fd->fd = fd;
202
+ grpc_lfev_init(&new_fd->read_closure);
203
+ grpc_lfev_init(&new_fd->write_closure);
204
+ gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
205
+
206
+ new_fd->freelist_next = NULL;
207
+
208
+ char *fd_name;
209
+ gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
210
+ grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name);
211
+ #ifdef GRPC_FD_REF_COUNT_DEBUG
212
+ gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name);
213
+ #endif
214
+ gpr_free(fd_name);
215
+
216
+ struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET),
217
+ .data.ptr = new_fd};
218
+ if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, fd, &ev) != 0) {
219
+ gpr_log(GPR_ERROR, "epoll_ctl failed: %s", strerror(errno));
220
+ }
221
+
222
+ return new_fd;
223
+ }
224
+
225
+ static int fd_wrapped_fd(grpc_fd *fd) { return fd->fd; }
226
+
227
+ /* Might be called multiple times */
228
+ static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
229
+ if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure,
230
+ GRPC_ERROR_REF(why))) {
231
+ shutdown(fd->fd, SHUT_RDWR);
232
+ grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why));
233
+ }
234
+ GRPC_ERROR_UNREF(why);
235
+ }
236
+
237
+ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
238
+ grpc_closure *on_done, int *release_fd,
239
+ const char *reason) {
240
+ grpc_error *error = GRPC_ERROR_NONE;
241
+
242
+ if (!grpc_lfev_is_shutdown(&fd->read_closure)) {
243
+ fd_shutdown(exec_ctx, fd, GRPC_ERROR_CREATE_FROM_COPIED_STRING(reason));
244
+ }
245
+
246
+ /* If release_fd is not NULL, we should be relinquishing control of the file
247
+ descriptor fd->fd (but we still own the grpc_fd structure). */
248
+ if (release_fd != NULL) {
249
+ *release_fd = fd->fd;
250
+ } else {
251
+ close(fd->fd);
252
+ }
253
+
254
+ grpc_closure_sched(exec_ctx, on_done, GRPC_ERROR_REF(error));
255
+
256
+ grpc_iomgr_unregister_object(&fd->iomgr_object);
257
+ grpc_lfev_destroy(&fd->read_closure);
258
+ grpc_lfev_destroy(&fd->write_closure);
259
+
260
+ gpr_mu_lock(&fd_freelist_mu);
261
+ fd->freelist_next = fd_freelist;
262
+ fd_freelist = fd;
263
+ gpr_mu_unlock(&fd_freelist_mu);
264
+ }
265
+
266
+ static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx,
267
+ grpc_fd *fd) {
268
+ gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset);
269
+ return (grpc_pollset *)notifier;
270
+ }
271
+
272
+ static bool fd_is_shutdown(grpc_fd *fd) {
273
+ return grpc_lfev_is_shutdown(&fd->read_closure);
274
+ }
275
+
276
+ static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
277
+ grpc_closure *closure) {
278
+ grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure);
279
+ }
280
+
281
+ static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
282
+ grpc_closure *closure) {
283
+ grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure);
284
+ }
285
+
286
+ static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) {
287
+ return (grpc_workqueue *)0xb0b51ed;
288
+ }
289
+
290
+ static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
291
+ grpc_pollset *notifier) {
292
+ grpc_lfev_set_ready(exec_ctx, &fd->read_closure);
293
+
294
+ /* Note, it is possible that fd_become_readable might be called twice with
295
+ different 'notifier's when an fd becomes readable and it is in two epoll
296
+ sets (This can happen briefly during polling island merges). In such cases
297
+ it does not really matter which notifer is set as the read_notifier_pollset
298
+ (They would both point to the same polling island anyway) */
299
+ /* Use release store to match with acquire load in fd_get_read_notifier */
300
+ gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier);
301
+ }
302
+
303
+ static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
304
+ grpc_lfev_set_ready(exec_ctx, &fd->write_closure);
305
+ }
306
+
307
+ /*******************************************************************************
308
+ * Pollset Definitions
309
+ */
310
+
311
+ GPR_TLS_DECL(g_current_thread_pollset);
312
+ GPR_TLS_DECL(g_current_thread_worker);
313
+ static gpr_atm g_active_poller;
314
+ static pollset_neighbourhood *g_neighbourhoods;
315
+ static size_t g_num_neighbourhoods;
316
+ static gpr_mu g_wq_mu;
317
+ static grpc_closure_list g_wq_items;
318
+
319
+ /* Return true if first in list */
320
+ static bool worker_insert(grpc_pollset *pollset, grpc_pollset_worker *worker) {
321
+ if (pollset->root_worker == NULL) {
322
+ pollset->root_worker = worker;
323
+ worker->next = worker->prev = worker;
324
+ return true;
325
+ } else {
326
+ worker->next = pollset->root_worker;
327
+ worker->prev = worker->next->prev;
328
+ worker->next->prev = worker;
329
+ worker->prev->next = worker;
330
+ return false;
331
+ }
332
+ }
333
+
334
+ /* Return true if last in list */
335
+ typedef enum { EMPTIED, NEW_ROOT, REMOVED } worker_remove_result;
336
+
337
+ static worker_remove_result worker_remove(grpc_pollset *pollset,
338
+ grpc_pollset_worker *worker) {
339
+ if (worker == pollset->root_worker) {
340
+ if (worker == worker->next) {
341
+ pollset->root_worker = NULL;
342
+ return EMPTIED;
343
+ } else {
344
+ pollset->root_worker = worker->next;
345
+ worker->prev->next = worker->next;
346
+ worker->next->prev = worker->prev;
347
+ return NEW_ROOT;
348
+ }
349
+ } else {
350
+ worker->prev->next = worker->next;
351
+ worker->next->prev = worker->prev;
352
+ return REMOVED;
353
+ }
354
+ }
355
+
356
+ static size_t choose_neighbourhood(void) {
357
+ return (size_t)gpr_cpu_current_cpu() % g_num_neighbourhoods;
358
+ }
359
+
360
+ static grpc_error *pollset_global_init(void) {
361
+ gpr_tls_init(&g_current_thread_pollset);
362
+ gpr_tls_init(&g_current_thread_worker);
363
+ gpr_atm_no_barrier_store(&g_active_poller, 0);
364
+ global_wakeup_fd.read_fd = -1;
365
+ grpc_error *err = grpc_wakeup_fd_init(&global_wakeup_fd);
366
+ gpr_mu_init(&g_wq_mu);
367
+ g_wq_items = (grpc_closure_list)GRPC_CLOSURE_LIST_INIT;
368
+ if (err != GRPC_ERROR_NONE) return err;
369
+ struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLET),
370
+ .data.ptr = &global_wakeup_fd};
371
+ if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, global_wakeup_fd.read_fd, &ev) != 0) {
372
+ return GRPC_OS_ERROR(errno, "epoll_ctl");
373
+ }
374
+ g_num_neighbourhoods = GPR_CLAMP(gpr_cpu_num_cores(), 1, MAX_NEIGHBOURHOODS);
375
+ g_neighbourhoods =
376
+ gpr_zalloc(sizeof(*g_neighbourhoods) * g_num_neighbourhoods);
377
+ for (size_t i = 0; i < g_num_neighbourhoods; i++) {
378
+ gpr_mu_init(&g_neighbourhoods[i].mu);
379
+ }
380
+ return GRPC_ERROR_NONE;
381
+ }
382
+
383
+ static void pollset_global_shutdown(void) {
384
+ gpr_tls_destroy(&g_current_thread_pollset);
385
+ gpr_tls_destroy(&g_current_thread_worker);
386
+ gpr_mu_destroy(&g_wq_mu);
387
+ if (global_wakeup_fd.read_fd != -1) grpc_wakeup_fd_destroy(&global_wakeup_fd);
388
+ for (size_t i = 0; i < g_num_neighbourhoods; i++) {
389
+ gpr_mu_destroy(&g_neighbourhoods[i].mu);
390
+ }
391
+ gpr_free(g_neighbourhoods);
392
+ }
393
+
394
+ static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
395
+ gpr_mu_init(&pollset->mu);
396
+ *mu = &pollset->mu;
397
+ pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()];
398
+ pollset->seen_inactive = true;
399
+ }
400
+
401
+ static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
402
+ gpr_mu_lock(&pollset->mu);
403
+ if (!pollset->seen_inactive) {
404
+ pollset_neighbourhood *neighbourhood = pollset->neighbourhood;
405
+ gpr_mu_unlock(&pollset->mu);
406
+ retry_lock_neighbourhood:
407
+ gpr_mu_lock(&neighbourhood->mu);
408
+ gpr_mu_lock(&pollset->mu);
409
+ if (!pollset->seen_inactive) {
410
+ if (pollset->neighbourhood != neighbourhood) {
411
+ gpr_mu_unlock(&neighbourhood->mu);
412
+ neighbourhood = pollset->neighbourhood;
413
+ gpr_mu_unlock(&pollset->mu);
414
+ goto retry_lock_neighbourhood;
415
+ }
416
+ pollset->prev->next = pollset->next;
417
+ pollset->next->prev = pollset->prev;
418
+ if (pollset == pollset->neighbourhood->active_root) {
419
+ pollset->neighbourhood->active_root =
420
+ pollset->next == pollset ? NULL : pollset->next;
421
+ }
422
+ }
423
+ gpr_mu_unlock(&pollset->neighbourhood->mu);
424
+ }
425
+ gpr_mu_unlock(&pollset->mu);
426
+ gpr_mu_destroy(&pollset->mu);
427
+ }
428
+
429
+ static grpc_error *pollset_kick_all(grpc_pollset *pollset) {
430
+ grpc_error *error = GRPC_ERROR_NONE;
431
+ if (pollset->root_worker != NULL) {
432
+ grpc_pollset_worker *worker = pollset->root_worker;
433
+ do {
434
+ if (worker->initialized_cv) {
435
+ worker->kick_state = KICKED;
436
+ gpr_cv_signal(&worker->cv);
437
+ } else {
438
+ worker->kick_state = KICKED;
439
+ append_error(&error, grpc_wakeup_fd_wakeup(&global_wakeup_fd),
440
+ "pollset_shutdown");
441
+ }
442
+
443
+ worker = worker->next;
444
+ } while (worker != pollset->root_worker);
445
+ }
446
+ return error;
447
+ }
448
+
449
+ static void pollset_maybe_finish_shutdown(grpc_exec_ctx *exec_ctx,
450
+ grpc_pollset *pollset) {
451
+ if (pollset->shutdown_closure != NULL && pollset->root_worker == NULL &&
452
+ pollset->begin_refs == 0) {
453
+ grpc_closure_sched(exec_ctx, pollset->shutdown_closure, GRPC_ERROR_NONE);
454
+ pollset->shutdown_closure = NULL;
455
+ }
456
+ }
457
+
458
+ static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
459
+ grpc_closure *closure) {
460
+ GPR_ASSERT(pollset->shutdown_closure == NULL);
461
+ pollset->shutdown_closure = closure;
462
+ GRPC_LOG_IF_ERROR("pollset_shutdown", pollset_kick_all(pollset));
463
+ pollset_maybe_finish_shutdown(exec_ctx, pollset);
464
+ }
465
+
466
+ #define MAX_EPOLL_EVENTS 100
467
+
468
+ static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
469
+ gpr_timespec now) {
470
+ gpr_timespec timeout;
471
+ if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) {
472
+ return -1;
473
+ }
474
+
475
+ if (gpr_time_cmp(deadline, now) <= 0) {
476
+ return 0;
477
+ }
478
+
479
+ static const gpr_timespec round_up = {
480
+ .clock_type = GPR_TIMESPAN, .tv_sec = 0, .tv_nsec = GPR_NS_PER_MS - 1};
481
+ timeout = gpr_time_sub(deadline, now);
482
+ int millis = gpr_time_to_millis(gpr_time_add(timeout, round_up));
483
+ return millis >= 1 ? millis : 1;
484
+ }
485
+
486
+ static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
487
+ gpr_timespec now, gpr_timespec deadline) {
488
+ struct epoll_event events[MAX_EPOLL_EVENTS];
489
+ static const char *err_desc = "pollset_poll";
490
+
491
+ int timeout = poll_deadline_to_millis_timeout(deadline, now);
492
+
493
+ if (timeout != 0) {
494
+ GRPC_SCHEDULING_START_BLOCKING_REGION;
495
+ }
496
+ int r;
497
+ do {
498
+ r = epoll_wait(g_epfd, events, MAX_EPOLL_EVENTS, timeout);
499
+ } while (r < 0 && errno == EINTR);
500
+ if (timeout != 0) {
501
+ GRPC_SCHEDULING_END_BLOCKING_REGION;
502
+ }
503
+
504
+ if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait");
505
+
506
+ grpc_error *error = GRPC_ERROR_NONE;
507
+ for (int i = 0; i < r; i++) {
508
+ void *data_ptr = events[i].data.ptr;
509
+ if (data_ptr == &global_wakeup_fd) {
510
+ gpr_mu_lock(&g_wq_mu);
511
+ grpc_closure_list_move(&g_wq_items, &exec_ctx->closure_list);
512
+ gpr_mu_unlock(&g_wq_mu);
513
+ append_error(&error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd),
514
+ err_desc);
515
+ } else {
516
+ grpc_fd *fd = (grpc_fd *)(data_ptr);
517
+ bool cancel = (events[i].events & (EPOLLERR | EPOLLHUP)) != 0;
518
+ bool read_ev = (events[i].events & (EPOLLIN | EPOLLPRI)) != 0;
519
+ bool write_ev = (events[i].events & EPOLLOUT) != 0;
520
+ if (read_ev || cancel) {
521
+ fd_become_readable(exec_ctx, fd, pollset);
522
+ }
523
+ if (write_ev || cancel) {
524
+ fd_become_writable(exec_ctx, fd);
525
+ }
526
+ }
527
+ }
528
+
529
+ return error;
530
+ }
531
+
532
+ static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker,
533
+ grpc_pollset_worker **worker_hdl, gpr_timespec *now,
534
+ gpr_timespec deadline) {
535
+ if (worker_hdl != NULL) *worker_hdl = worker;
536
+ worker->initialized_cv = false;
537
+ worker->kick_state = UNKICKED;
538
+ worker->schedule_on_end_work = (grpc_closure_list)GRPC_CLOSURE_LIST_INIT;
539
+ pollset->begin_refs++;
540
+
541
+ if (pollset->seen_inactive) {
542
+ // pollset has been observed to be inactive, we need to move back to the
543
+ // active list
544
+ bool is_reassigning = false;
545
+ if (!pollset->reassigning_neighbourhood) {
546
+ is_reassigning = true;
547
+ pollset->reassigning_neighbourhood = true;
548
+ pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()];
549
+ }
550
+ pollset_neighbourhood *neighbourhood = pollset->neighbourhood;
551
+ gpr_mu_unlock(&pollset->mu);
552
+ // pollset unlocked: state may change (even worker->kick_state)
553
+ retry_lock_neighbourhood:
554
+ gpr_mu_lock(&neighbourhood->mu);
555
+ gpr_mu_lock(&pollset->mu);
556
+ if (pollset->seen_inactive) {
557
+ if (neighbourhood != pollset->neighbourhood) {
558
+ gpr_mu_unlock(&neighbourhood->mu);
559
+ neighbourhood = pollset->neighbourhood;
560
+ gpr_mu_unlock(&pollset->mu);
561
+ goto retry_lock_neighbourhood;
562
+ }
563
+ pollset->seen_inactive = false;
564
+ if (neighbourhood->active_root == NULL) {
565
+ neighbourhood->active_root = pollset->next = pollset->prev = pollset;
566
+ if (gpr_atm_no_barrier_cas(&g_active_poller, 0, (gpr_atm)worker)) {
567
+ worker->kick_state = DESIGNATED_POLLER;
568
+ }
569
+ } else {
570
+ pollset->next = neighbourhood->active_root;
571
+ pollset->prev = pollset->next->prev;
572
+ pollset->next->prev = pollset->prev->next = pollset;
573
+ }
574
+ }
575
+ if (is_reassigning) {
576
+ GPR_ASSERT(pollset->reassigning_neighbourhood);
577
+ pollset->reassigning_neighbourhood = false;
578
+ }
579
+ gpr_mu_unlock(&neighbourhood->mu);
580
+ }
581
+ worker_insert(pollset, worker);
582
+ pollset->begin_refs--;
583
+ if (worker->kick_state == UNKICKED) {
584
+ GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker);
585
+ worker->initialized_cv = true;
586
+ gpr_cv_init(&worker->cv);
587
+ while (worker->kick_state == UNKICKED &&
588
+ pollset->shutdown_closure == NULL) {
589
+ if (gpr_cv_wait(&worker->cv, &pollset->mu, deadline) &&
590
+ worker->kick_state == UNKICKED) {
591
+ worker->kick_state = KICKED;
592
+ }
593
+ }
594
+ *now = gpr_now(now->clock_type);
595
+ }
596
+
597
+ return worker->kick_state == DESIGNATED_POLLER &&
598
+ pollset->shutdown_closure == NULL;
599
+ }
600
+
601
+ static bool check_neighbourhood_for_available_poller(
602
+ pollset_neighbourhood *neighbourhood) {
603
+ bool found_worker = false;
604
+ do {
605
+ grpc_pollset *inspect = neighbourhood->active_root;
606
+ if (inspect == NULL) {
607
+ break;
608
+ }
609
+ gpr_mu_lock(&inspect->mu);
610
+ GPR_ASSERT(!inspect->seen_inactive);
611
+ grpc_pollset_worker *inspect_worker = inspect->root_worker;
612
+ if (inspect_worker != NULL) {
613
+ do {
614
+ switch (inspect_worker->kick_state) {
615
+ case UNKICKED:
616
+ if (gpr_atm_no_barrier_cas(&g_active_poller, 0,
617
+ (gpr_atm)inspect_worker)) {
618
+ inspect_worker->kick_state = DESIGNATED_POLLER;
619
+ if (inspect_worker->initialized_cv) {
620
+ gpr_cv_signal(&inspect_worker->cv);
621
+ }
622
+ }
623
+ // even if we didn't win the cas, there's a worker, we can stop
624
+ found_worker = true;
625
+ break;
626
+ case KICKED:
627
+ break;
628
+ case DESIGNATED_POLLER:
629
+ found_worker = true; // ok, so someone else found the worker, but
630
+ // we'll accept that
631
+ break;
632
+ }
633
+ inspect_worker = inspect_worker->next;
634
+ } while (inspect_worker != inspect->root_worker);
635
+ }
636
+ if (!found_worker) {
637
+ inspect->seen_inactive = true;
638
+ if (inspect == neighbourhood->active_root) {
639
+ neighbourhood->active_root =
640
+ inspect->next == inspect ? NULL : inspect->next;
641
+ }
642
+ inspect->next->prev = inspect->prev;
643
+ inspect->prev->next = inspect->next;
644
+ inspect->next = inspect->prev = NULL;
645
+ }
646
+ gpr_mu_unlock(&inspect->mu);
647
+ } while (!found_worker);
648
+ return found_worker;
649
+ }
650
+
651
+ static void end_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
652
+ grpc_pollset_worker *worker,
653
+ grpc_pollset_worker **worker_hdl) {
654
+ if (worker_hdl != NULL) *worker_hdl = NULL;
655
+ worker->kick_state = KICKED;
656
+ grpc_closure_list_move(&worker->schedule_on_end_work,
657
+ &exec_ctx->closure_list);
658
+ if (gpr_atm_no_barrier_load(&g_active_poller) == (gpr_atm)worker) {
659
+ if (worker->next != worker && worker->next->kick_state == UNKICKED) {
660
+ GPR_ASSERT(worker->next->initialized_cv);
661
+ gpr_atm_no_barrier_store(&g_active_poller, (gpr_atm)worker->next);
662
+ worker->next->kick_state = DESIGNATED_POLLER;
663
+ gpr_cv_signal(&worker->next->cv);
664
+ if (grpc_exec_ctx_has_work(exec_ctx)) {
665
+ gpr_mu_unlock(&pollset->mu);
666
+ grpc_exec_ctx_flush(exec_ctx);
667
+ gpr_mu_lock(&pollset->mu);
668
+ }
669
+ } else {
670
+ gpr_atm_no_barrier_store(&g_active_poller, 0);
671
+ gpr_mu_unlock(&pollset->mu);
672
+ size_t poller_neighbourhood_idx =
673
+ (size_t)(pollset->neighbourhood - g_neighbourhoods);
674
+ bool found_worker = false;
675
+ bool scan_state[MAX_NEIGHBOURHOODS];
676
+ for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) {
677
+ pollset_neighbourhood *neighbourhood =
678
+ &g_neighbourhoods[(poller_neighbourhood_idx + i) %
679
+ g_num_neighbourhoods];
680
+ if (gpr_mu_trylock(&neighbourhood->mu)) {
681
+ found_worker =
682
+ check_neighbourhood_for_available_poller(neighbourhood);
683
+ gpr_mu_unlock(&neighbourhood->mu);
684
+ scan_state[i] = true;
685
+ } else {
686
+ scan_state[i] = false;
687
+ }
688
+ }
689
+ for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) {
690
+ if (scan_state[i]) continue;
691
+ pollset_neighbourhood *neighbourhood =
692
+ &g_neighbourhoods[(poller_neighbourhood_idx + i) %
693
+ g_num_neighbourhoods];
694
+ gpr_mu_lock(&neighbourhood->mu);
695
+ found_worker = check_neighbourhood_for_available_poller(neighbourhood);
696
+ gpr_mu_unlock(&neighbourhood->mu);
697
+ }
698
+ grpc_exec_ctx_flush(exec_ctx);
699
+ gpr_mu_lock(&pollset->mu);
700
+ }
701
+ } else if (grpc_exec_ctx_has_work(exec_ctx)) {
702
+ gpr_mu_unlock(&pollset->mu);
703
+ grpc_exec_ctx_flush(exec_ctx);
704
+ gpr_mu_lock(&pollset->mu);
705
+ }
706
+ if (worker->initialized_cv) {
707
+ gpr_cv_destroy(&worker->cv);
708
+ }
709
+ if (EMPTIED == worker_remove(pollset, worker)) {
710
+ pollset_maybe_finish_shutdown(exec_ctx, pollset);
711
+ }
712
+ GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker);
713
+ }
714
+
715
+ /* pollset->po.mu lock must be held by the caller before calling this.
716
+ The function pollset_work() may temporarily release the lock (pollset->po.mu)
717
+ during the course of its execution but it will always re-acquire the lock and
718
+ ensure that it is held by the time the function returns */
719
+ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
720
+ grpc_pollset_worker **worker_hdl,
721
+ gpr_timespec now, gpr_timespec deadline) {
722
+ grpc_pollset_worker worker;
723
+ grpc_error *error = GRPC_ERROR_NONE;
724
+ static const char *err_desc = "pollset_work";
725
+ if (pollset->kicked_without_poller) {
726
+ pollset->kicked_without_poller = false;
727
+ return GRPC_ERROR_NONE;
728
+ }
729
+ gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset);
730
+ if (begin_worker(pollset, &worker, worker_hdl, &now, deadline)) {
731
+ gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker);
732
+ GPR_ASSERT(!pollset->shutdown_closure);
733
+ GPR_ASSERT(!pollset->seen_inactive);
734
+ gpr_mu_unlock(&pollset->mu);
735
+ append_error(&error, pollset_epoll(exec_ctx, pollset, now, deadline),
736
+ err_desc);
737
+ gpr_mu_lock(&pollset->mu);
738
+ gpr_tls_set(&g_current_thread_worker, 0);
739
+ }
740
+ end_worker(exec_ctx, pollset, &worker, worker_hdl);
741
+ gpr_tls_set(&g_current_thread_pollset, 0);
742
+ return error;
743
+ }
744
+
745
+ static grpc_error *pollset_kick(grpc_pollset *pollset,
746
+ grpc_pollset_worker *specific_worker) {
747
+ if (specific_worker == NULL) {
748
+ if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
749
+ grpc_pollset_worker *root_worker = pollset->root_worker;
750
+ if (root_worker == NULL) {
751
+ pollset->kicked_without_poller = true;
752
+ return GRPC_ERROR_NONE;
753
+ }
754
+ grpc_pollset_worker *next_worker = root_worker->next;
755
+ if (root_worker == next_worker &&
756
+ root_worker == (grpc_pollset_worker *)gpr_atm_no_barrier_load(
757
+ &g_active_poller)) {
758
+ root_worker->kick_state = KICKED;
759
+ return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
760
+ } else if (next_worker->kick_state == UNKICKED) {
761
+ GPR_ASSERT(next_worker->initialized_cv);
762
+ next_worker->kick_state = KICKED;
763
+ gpr_cv_signal(&next_worker->cv);
764
+ return GRPC_ERROR_NONE;
765
+ } else {
766
+ return GRPC_ERROR_NONE;
767
+ }
768
+ } else {
769
+ return GRPC_ERROR_NONE;
770
+ }
771
+ } else if (specific_worker->kick_state == KICKED) {
772
+ return GRPC_ERROR_NONE;
773
+ } else if (gpr_tls_get(&g_current_thread_worker) ==
774
+ (intptr_t)specific_worker) {
775
+ specific_worker->kick_state = KICKED;
776
+ return GRPC_ERROR_NONE;
777
+ } else if (specific_worker ==
778
+ (grpc_pollset_worker *)gpr_atm_no_barrier_load(&g_active_poller)) {
779
+ specific_worker->kick_state = KICKED;
780
+ return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
781
+ } else if (specific_worker->initialized_cv) {
782
+ specific_worker->kick_state = KICKED;
783
+ gpr_cv_signal(&specific_worker->cv);
784
+ return GRPC_ERROR_NONE;
785
+ } else {
786
+ specific_worker->kick_state = KICKED;
787
+ return GRPC_ERROR_NONE;
788
+ }
789
+ }
790
+
791
+ static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
792
+ grpc_fd *fd) {}
793
+
794
+ /*******************************************************************************
795
+ * Workqueue Definitions
796
+ */
797
+
798
+ #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG
799
+ static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue,
800
+ const char *file, int line,
801
+ const char *reason) {
802
+ return workqueue;
803
+ }
804
+
805
+ static void workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue,
806
+ const char *file, int line, const char *reason) {}
807
+ #else
808
+ static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue) {
809
+ return workqueue;
810
+ }
811
+
812
+ static void workqueue_unref(grpc_exec_ctx *exec_ctx,
813
+ grpc_workqueue *workqueue) {}
814
+ #endif
815
+
816
+ static void wq_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
817
+ grpc_error *error) {
818
+ // find a neighbourhood to wakeup
819
+ bool scheduled = false;
820
+ size_t initial_neighbourhood = choose_neighbourhood();
821
+ for (size_t i = 0; !scheduled && i < g_num_neighbourhoods; i++) {
822
+ pollset_neighbourhood *neighbourhood =
823
+ &g_neighbourhoods[(initial_neighbourhood + i) % g_num_neighbourhoods];
824
+ if (gpr_mu_trylock(&neighbourhood->mu)) {
825
+ if (neighbourhood->active_root != NULL) {
826
+ grpc_pollset *inspect = neighbourhood->active_root;
827
+ do {
828
+ if (gpr_mu_trylock(&inspect->mu)) {
829
+ if (inspect->root_worker != NULL) {
830
+ grpc_pollset_worker *inspect_worker = inspect->root_worker;
831
+ do {
832
+ if (inspect_worker->kick_state == UNKICKED) {
833
+ inspect_worker->kick_state = KICKED;
834
+ grpc_closure_list_append(
835
+ &inspect_worker->schedule_on_end_work, closure, error);
836
+ if (inspect_worker->initialized_cv) {
837
+ gpr_cv_signal(&inspect_worker->cv);
838
+ }
839
+ scheduled = true;
840
+ }
841
+ inspect_worker = inspect_worker->next;
842
+ } while (!scheduled && inspect_worker != inspect->root_worker);
843
+ }
844
+ gpr_mu_unlock(&inspect->mu);
845
+ }
846
+ inspect = inspect->next;
847
+ } while (!scheduled && inspect != neighbourhood->active_root);
848
+ }
849
+ gpr_mu_unlock(&neighbourhood->mu);
850
+ }
851
+ }
852
+ if (!scheduled) {
853
+ gpr_mu_lock(&g_wq_mu);
854
+ grpc_closure_list_append(&g_wq_items, closure, error);
855
+ gpr_mu_unlock(&g_wq_mu);
856
+ GRPC_LOG_IF_ERROR("workqueue_scheduler",
857
+ grpc_wakeup_fd_wakeup(&global_wakeup_fd));
858
+ }
859
+ }
860
+
861
+ static const grpc_closure_scheduler_vtable
862
+ singleton_workqueue_scheduler_vtable = {wq_sched, wq_sched,
863
+ "epoll1_workqueue"};
864
+
865
+ static grpc_closure_scheduler singleton_workqueue_scheduler = {
866
+ &singleton_workqueue_scheduler_vtable};
867
+
868
+ static grpc_closure_scheduler *workqueue_scheduler(grpc_workqueue *workqueue) {
869
+ return &singleton_workqueue_scheduler;
870
+ }
871
+
872
+ /*******************************************************************************
873
+ * Pollset-set Definitions
874
+ */
875
+
876
+ static grpc_pollset_set *pollset_set_create(void) {
877
+ return (grpc_pollset_set *)((intptr_t)0xdeafbeef);
878
+ }
879
+
880
+ static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
881
+ grpc_pollset_set *pss) {}
882
+
883
+ static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss,
884
+ grpc_fd *fd) {}
885
+
886
+ static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss,
887
+ grpc_fd *fd) {}
888
+
889
+ static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
890
+ grpc_pollset_set *pss, grpc_pollset *ps) {}
891
+
892
+ static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
893
+ grpc_pollset_set *pss, grpc_pollset *ps) {}
894
+
895
+ static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
896
+ grpc_pollset_set *bag,
897
+ grpc_pollset_set *item) {}
898
+
899
+ static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx,
900
+ grpc_pollset_set *bag,
901
+ grpc_pollset_set *item) {}
902
+
903
+ /*******************************************************************************
904
+ * Event engine binding
905
+ */
906
+
907
+ static void shutdown_engine(void) {
908
+ fd_global_shutdown();
909
+ pollset_global_shutdown();
910
+ }
911
+
912
+ static const grpc_event_engine_vtable vtable = {
913
+ .pollset_size = sizeof(grpc_pollset),
914
+
915
+ .fd_create = fd_create,
916
+ .fd_wrapped_fd = fd_wrapped_fd,
917
+ .fd_orphan = fd_orphan,
918
+ .fd_shutdown = fd_shutdown,
919
+ .fd_is_shutdown = fd_is_shutdown,
920
+ .fd_notify_on_read = fd_notify_on_read,
921
+ .fd_notify_on_write = fd_notify_on_write,
922
+ .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset,
923
+ .fd_get_workqueue = fd_get_workqueue,
924
+
925
+ .pollset_init = pollset_init,
926
+ .pollset_shutdown = pollset_shutdown,
927
+ .pollset_destroy = pollset_destroy,
928
+ .pollset_work = pollset_work,
929
+ .pollset_kick = pollset_kick,
930
+ .pollset_add_fd = pollset_add_fd,
931
+
932
+ .pollset_set_create = pollset_set_create,
933
+ .pollset_set_destroy = pollset_set_destroy,
934
+ .pollset_set_add_pollset = pollset_set_add_pollset,
935
+ .pollset_set_del_pollset = pollset_set_del_pollset,
936
+ .pollset_set_add_pollset_set = pollset_set_add_pollset_set,
937
+ .pollset_set_del_pollset_set = pollset_set_del_pollset_set,
938
+ .pollset_set_add_fd = pollset_set_add_fd,
939
+ .pollset_set_del_fd = pollset_set_del_fd,
940
+
941
+ .workqueue_ref = workqueue_ref,
942
+ .workqueue_unref = workqueue_unref,
943
+ .workqueue_scheduler = workqueue_scheduler,
944
+
945
+ .shutdown_engine = shutdown_engine,
946
+ };
947
+
948
+ /* It is possible that GLIBC has epoll but the underlying kernel doesn't.
949
+ * Create a dummy epoll_fd to make sure epoll support is available */
950
+ const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
951
+ /* TODO(ctiller): temporary, until this stabilizes */
952
+ if (!explicit_request) return NULL;
953
+
954
+ if (!grpc_has_wakeup_fd()) {
955
+ return NULL;
956
+ }
957
+
958
+ g_epfd = epoll_create1(EPOLL_CLOEXEC);
959
+ if (g_epfd < 0) {
960
+ gpr_log(GPR_ERROR, "epoll unavailable");
961
+ return NULL;
962
+ }
963
+
964
+ fd_global_init();
965
+
966
+ if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) {
967
+ close(g_epfd);
968
+ fd_global_shutdown();
969
+ return NULL;
970
+ }
971
+
972
+ return &vtable;
973
+ }
974
+
975
+ #else /* defined(GRPC_LINUX_EPOLL) */
976
+ #if defined(GRPC_POSIX_SOCKET)
977
+ #include "src/core/lib/iomgr/ev_posix.h"
978
+ /* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return
979
+ * NULL */
980
+ const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) {
981
+ return NULL;
982
+ }
983
+ #endif /* defined(GRPC_POSIX_SOCKET) */
984
+ #endif /* !defined(GRPC_LINUX_EPOLL) */