wearefair-grpc 1.3.1.pre.c → 1.4.0.fair

Sign up to get free protection for your applications and to get access to all the features.
Files changed (219) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +418 -126
  3. data/include/grpc/grpc.h +15 -69
  4. data/include/grpc/grpc_security.h +1 -1
  5. data/include/grpc/impl/codegen/compression_types.h +3 -4
  6. data/include/grpc/impl/codegen/gpr_types.h +0 -1
  7. data/include/grpc/impl/codegen/grpc_types.h +69 -3
  8. data/include/grpc/impl/codegen/port_platform.h +6 -0
  9. data/include/grpc/impl/codegen/slice.h +2 -1
  10. data/include/grpc/load_reporting.h +6 -6
  11. data/include/grpc/slice.h +25 -3
  12. data/include/grpc/slice_buffer.h +4 -0
  13. data/src/core/ext/census/context.c +1 -1
  14. data/src/core/ext/census/resource.c +3 -1
  15. data/src/core/ext/filters/client_channel/channel_connectivity.c +1 -1
  16. data/src/core/ext/filters/client_channel/client_channel.c +158 -100
  17. data/src/core/ext/filters/client_channel/client_channel_plugin.c +3 -2
  18. data/src/core/ext/filters/client_channel/lb_policy.c +2 -1
  19. data/src/core/ext/filters/client_channel/lb_policy.h +5 -6
  20. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c +153 -0
  21. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h +42 -0
  22. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c +344 -88
  23. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c +133 -0
  24. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +65 -0
  25. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c +47 -5
  26. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +6 -0
  27. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +19 -8
  28. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +63 -34
  29. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c +2 -1
  30. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c +13 -12
  31. data/src/core/ext/filters/client_channel/lb_policy_factory.c +28 -5
  32. data/src/core/ext/filters/client_channel/lb_policy_factory.h +18 -4
  33. data/src/core/ext/filters/client_channel/parse_address.c +37 -7
  34. data/src/core/ext/filters/client_channel/parse_address.h +11 -8
  35. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c +3 -3
  36. data/src/core/ext/filters/client_channel/subchannel.c +19 -16
  37. data/src/core/ext/filters/client_channel/subchannel.h +1 -0
  38. data/src/core/ext/filters/client_channel/uri_parser.c +36 -22
  39. data/src/core/ext/filters/client_channel/uri_parser.h +1 -1
  40. data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.c +42 -17
  41. data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.h +8 -9
  42. data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.c +19 -11
  43. data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.h +3 -6
  44. data/src/core/ext/filters/http/http_filters_plugin.c +104 -0
  45. data/src/core/{lib/channel/compress_filter.c → ext/filters/http/message_compress/message_compress_filter.c} +124 -23
  46. data/src/core/{lib/channel/compress_filter.h → ext/filters/http/message_compress/message_compress_filter.h} +5 -6
  47. data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.c +4 -6
  48. data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.h +3 -3
  49. data/src/core/ext/filters/load_reporting/load_reporting.c +2 -25
  50. data/src/core/ext/filters/load_reporting/load_reporting_filter.c +26 -1
  51. data/src/core/ext/filters/max_age/max_age_filter.c +14 -14
  52. data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.c +91 -47
  53. data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.h +3 -3
  54. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +1 -1
  55. data/src/core/ext/transport/chttp2/server/chttp2_server.c +2 -2
  56. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +2 -2
  57. data/src/core/ext/transport/chttp2/transport/bin_encoder.c +3 -3
  58. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +296 -172
  59. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +3 -2
  60. data/src/core/ext/transport/chttp2/transport/frame_data.c +203 -164
  61. data/src/core/ext/transport/chttp2/transport/frame_data.h +8 -14
  62. data/src/core/ext/transport/chttp2/transport/frame_goaway.c +1 -1
  63. data/src/core/ext/transport/chttp2/transport/frame_ping.c +1 -1
  64. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +1 -1
  65. data/src/core/ext/transport/chttp2/transport/frame_settings.c +5 -5
  66. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +1 -1
  67. data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +4 -4
  68. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +2 -4
  69. data/src/core/ext/transport/chttp2/transport/hpack_table.c +4 -3
  70. data/src/core/ext/transport/chttp2/transport/internal.h +50 -33
  71. data/src/core/ext/transport/chttp2/transport/parsing.c +10 -11
  72. data/src/core/ext/transport/chttp2/transport/writing.c +32 -13
  73. data/src/core/lib/channel/channel_args.c +28 -9
  74. data/src/core/lib/channel/channel_args.h +5 -1
  75. data/src/core/lib/channel/channel_stack.c +1 -1
  76. data/src/core/lib/channel/channel_stack.h +2 -2
  77. data/src/core/lib/channel/channel_stack_builder.c +13 -1
  78. data/src/core/lib/channel/channel_stack_builder.h +5 -1
  79. data/src/core/lib/channel/connected_channel.c +3 -1
  80. data/src/core/lib/channel/context.h +2 -2
  81. data/src/core/lib/compression/message_compress.c +2 -2
  82. data/src/core/lib/debug/trace.c +13 -6
  83. data/src/core/lib/debug/trace.h +27 -1
  84. data/src/core/lib/http/httpcli.c +1 -1
  85. data/src/core/lib/http/httpcli_security_connector.c +6 -10
  86. data/src/core/lib/http/parser.c +2 -2
  87. data/src/core/lib/http/parser.h +2 -1
  88. data/src/core/lib/iomgr/combiner.c +6 -6
  89. data/src/core/lib/iomgr/combiner.h +2 -1
  90. data/src/core/lib/iomgr/error.c +12 -5
  91. data/src/core/lib/iomgr/error.h +13 -13
  92. data/src/core/lib/iomgr/ev_epoll1_linux.c +984 -0
  93. data/src/core/lib/iomgr/ev_epoll1_linux.h +44 -0
  94. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c +2146 -0
  95. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h +43 -0
  96. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c +1337 -0
  97. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.h +43 -0
  98. data/src/core/lib/iomgr/ev_epollex_linux.c +1511 -0
  99. data/src/core/lib/iomgr/ev_epollex_linux.h +43 -0
  100. data/src/core/lib/iomgr/{ev_epoll_linux.c → ev_epollsig_linux.c} +24 -31
  101. data/src/core/lib/iomgr/{ev_epoll_linux.h → ev_epollsig_linux.h} +4 -4
  102. data/src/core/lib/iomgr/ev_poll_posix.c +12 -27
  103. data/src/core/lib/iomgr/ev_poll_posix.h +2 -2
  104. data/src/core/lib/iomgr/ev_posix.c +22 -8
  105. data/src/core/lib/iomgr/ev_posix.h +4 -3
  106. data/src/core/lib/iomgr/exec_ctx.c +5 -0
  107. data/src/core/lib/iomgr/exec_ctx.h +2 -0
  108. data/src/core/lib/iomgr/iomgr.c +4 -0
  109. data/src/core/lib/iomgr/iomgr.h +3 -0
  110. data/src/core/lib/iomgr/is_epollexclusive_available.c +116 -0
  111. data/src/core/lib/iomgr/is_epollexclusive_available.h +41 -0
  112. data/src/core/lib/iomgr/lockfree_event.c +16 -0
  113. data/src/core/lib/iomgr/pollset.h +2 -5
  114. data/src/core/lib/iomgr/pollset_uv.c +1 -1
  115. data/src/core/lib/iomgr/pollset_windows.c +3 -3
  116. data/src/core/lib/iomgr/resource_quota.c +9 -8
  117. data/src/core/lib/iomgr/resource_quota.h +2 -1
  118. data/src/core/lib/iomgr/sockaddr_utils.h +1 -1
  119. data/src/core/lib/iomgr/socket_mutator.h +2 -0
  120. data/src/core/lib/iomgr/sys_epoll_wrapper.h +43 -0
  121. data/src/core/lib/iomgr/tcp_client_posix.c +6 -6
  122. data/src/core/lib/iomgr/tcp_client_uv.c +3 -3
  123. data/src/core/lib/iomgr/tcp_posix.c +7 -7
  124. data/src/core/lib/iomgr/tcp_posix.h +2 -1
  125. data/src/core/lib/iomgr/tcp_server_posix.c +1 -1
  126. data/src/core/lib/iomgr/tcp_uv.c +6 -6
  127. data/src/core/lib/iomgr/tcp_uv.h +2 -1
  128. data/src/core/lib/iomgr/tcp_windows.c +1 -1
  129. data/src/core/lib/iomgr/timer_generic.c +24 -25
  130. data/src/core/lib/iomgr/timer_manager.c +276 -0
  131. data/src/core/lib/iomgr/timer_manager.h +52 -0
  132. data/src/core/lib/iomgr/timer_uv.c +6 -0
  133. data/src/core/lib/iomgr/udp_server.c +42 -9
  134. data/src/core/lib/iomgr/udp_server.h +3 -1
  135. data/src/core/lib/security/credentials/credentials.c +0 -1
  136. data/src/core/lib/security/credentials/fake/fake_credentials.c +23 -0
  137. data/src/core/lib/security/credentials/fake/fake_credentials.h +12 -9
  138. data/src/core/lib/security/credentials/google_default/google_default_credentials.c +1 -1
  139. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -1
  140. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +1 -1
  141. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +24 -53
  142. data/src/core/lib/security/transport/client_auth_filter.c +9 -3
  143. data/src/core/lib/security/transport/secure_endpoint.c +7 -7
  144. data/src/core/lib/security/transport/secure_endpoint.h +1 -1
  145. data/src/core/lib/security/transport/security_connector.c +32 -51
  146. data/src/core/lib/security/transport/security_connector.h +10 -14
  147. data/src/core/lib/slice/b64.c +1 -1
  148. data/src/core/lib/slice/percent_encoding.c +3 -3
  149. data/src/core/lib/slice/slice.c +66 -33
  150. data/src/core/lib/slice/slice_buffer.c +25 -6
  151. data/src/core/lib/slice/slice_hash_table.c +33 -35
  152. data/src/core/lib/slice/slice_hash_table.h +7 -12
  153. data/src/core/lib/support/atomic.h +45 -0
  154. data/src/core/lib/support/atomic_with_atm.h +70 -0
  155. data/src/core/lib/support/atomic_with_std.h +48 -0
  156. data/src/core/lib/support/avl.c +14 -14
  157. data/src/core/lib/support/memory.h +74 -0
  158. data/src/core/lib/support/mpscq.c +12 -1
  159. data/src/core/lib/support/mpscq.h +4 -0
  160. data/src/core/lib/support/stack_lockfree.c +3 -36
  161. data/src/core/lib/support/time_posix.c +8 -0
  162. data/src/core/lib/support/tmpfile_posix.c +10 -10
  163. data/src/core/lib/surface/alarm.c +3 -1
  164. data/src/core/lib/surface/api_trace.c +2 -1
  165. data/src/core/lib/surface/api_trace.h +2 -2
  166. data/src/core/lib/surface/byte_buffer_reader.c +1 -1
  167. data/src/core/lib/surface/call.c +65 -22
  168. data/src/core/lib/surface/call.h +4 -2
  169. data/src/core/lib/surface/channel_init.c +2 -19
  170. data/src/core/lib/surface/channel_stack_type.c +18 -0
  171. data/src/core/lib/surface/channel_stack_type.h +2 -0
  172. data/src/core/lib/surface/completion_queue.c +249 -83
  173. data/src/core/lib/surface/completion_queue.h +18 -13
  174. data/src/core/lib/surface/completion_queue_factory.c +24 -9
  175. data/src/core/lib/surface/init.c +1 -52
  176. data/src/core/lib/surface/{lame_client.c → lame_client.cc} +37 -26
  177. data/src/core/lib/surface/server.c +50 -27
  178. data/src/core/lib/surface/server.h +2 -1
  179. data/src/core/lib/surface/version.c +2 -2
  180. data/src/core/lib/transport/bdp_estimator.c +20 -9
  181. data/src/core/lib/transport/bdp_estimator.h +5 -1
  182. data/src/core/lib/transport/byte_stream.c +23 -9
  183. data/src/core/lib/transport/byte_stream.h +15 -6
  184. data/src/core/lib/transport/connectivity_state.c +6 -6
  185. data/src/core/lib/transport/connectivity_state.h +2 -1
  186. data/src/core/lib/transport/service_config.c +6 -13
  187. data/src/core/lib/transport/service_config.h +2 -2
  188. data/src/core/lib/transport/static_metadata.c +403 -389
  189. data/src/core/lib/transport/static_metadata.h +127 -114
  190. data/src/core/plugin_registry/grpc_plugin_registry.c +12 -0
  191. data/src/core/tsi/fake_transport_security.c +5 -4
  192. data/src/core/tsi/ssl_transport_security.c +71 -82
  193. data/src/core/tsi/ssl_transport_security.h +39 -61
  194. data/src/core/tsi/transport_security.c +83 -2
  195. data/src/core/tsi/transport_security.h +27 -2
  196. data/src/core/tsi/transport_security_adapter.c +236 -0
  197. data/src/core/tsi/transport_security_adapter.h +62 -0
  198. data/src/core/tsi/transport_security_interface.h +179 -66
  199. data/src/ruby/ext/grpc/extconf.rb +2 -1
  200. data/src/ruby/ext/grpc/rb_byte_buffer.c +8 -6
  201. data/src/ruby/ext/grpc/rb_call.c +56 -48
  202. data/src/ruby/ext/grpc/rb_call.h +3 -4
  203. data/src/ruby/ext/grpc/rb_call_credentials.c +23 -22
  204. data/src/ruby/ext/grpc/rb_channel.c +45 -29
  205. data/src/ruby/ext/grpc/rb_channel_args.c +11 -9
  206. data/src/ruby/ext/grpc/rb_channel_credentials.c +16 -12
  207. data/src/ruby/ext/grpc/rb_completion_queue.c +7 -9
  208. data/src/ruby/ext/grpc/rb_compression_options.c +7 -6
  209. data/src/ruby/ext/grpc/rb_event_thread.c +10 -12
  210. data/src/ruby/ext/grpc/rb_event_thread.h +1 -2
  211. data/src/ruby/ext/grpc/rb_grpc.c +11 -15
  212. data/src/ruby/ext/grpc/rb_grpc.h +2 -2
  213. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +14 -6
  214. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +22 -10
  215. data/src/ruby/ext/grpc/rb_server.c +26 -28
  216. data/src/ruby/lib/grpc/version.rb +1 -1
  217. metadata +40 -18
  218. data/src/ruby/lib/grpc/grpc_c.bundle +0 -0
  219. data/src/ruby/lib/grpc/grpc_c.so +0 -0
@@ -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) */