grpc 1.14.2 → 1.15.0.pre1

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +307 -12
  3. data/etc/roots.pem +40 -163
  4. data/include/grpc/grpc.h +49 -0
  5. data/include/grpc/grpc_security.h +0 -6
  6. data/include/grpc/grpc_security_constants.h +6 -0
  7. data/include/grpc/impl/codegen/grpc_types.h +17 -2
  8. data/include/grpc/impl/codegen/port_platform.h +41 -4
  9. data/include/grpc/support/sync.h +0 -16
  10. data/src/{cpp → core}/ext/filters/census/grpc_context.cc +0 -0
  11. data/src/core/ext/filters/client_channel/client_channel.cc +40 -11
  12. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +11 -9
  13. data/src/core/ext/filters/client_channel/client_channel_channelz.h +4 -2
  14. data/src/core/ext/filters/client_channel/lb_policy.h +14 -11
  15. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +67 -90
  16. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +108 -91
  17. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +79 -25
  18. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +40 -0
  19. data/src/core/ext/filters/client_channel/resolver.h +8 -0
  20. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +11 -3
  21. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +13 -10
  22. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +18 -4
  23. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +13 -5
  24. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +537 -0
  25. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +6 -5
  26. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +11 -0
  27. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +29 -0
  28. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +29 -0
  29. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +9 -0
  30. data/src/core/ext/filters/client_channel/subchannel.cc +21 -8
  31. data/src/core/ext/filters/client_channel/subchannel.h +7 -0
  32. data/src/core/ext/filters/http/client_authority_filter.cc +1 -1
  33. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +24 -0
  34. data/src/core/ext/transport/chttp2/transport/flow_control.cc +10 -7
  35. data/src/core/lib/channel/channel_stack.h +1 -1
  36. data/src/core/lib/channel/channel_trace.cc +1 -1
  37. data/src/core/lib/channel/channel_trace.h +1 -1
  38. data/src/core/lib/channel/channelz.cc +37 -27
  39. data/src/core/lib/channel/channelz.h +13 -4
  40. data/src/core/lib/channel/channelz_registry.cc +89 -4
  41. data/src/core/lib/channel/channelz_registry.h +56 -39
  42. data/src/core/lib/gpr/arena.cc +33 -40
  43. data/src/core/lib/gprpp/fork.cc +41 -33
  44. data/src/core/lib/gprpp/fork.h +13 -4
  45. data/src/core/lib/gprpp/mutex_lock.h +42 -0
  46. data/src/core/lib/gprpp/orphanable.h +4 -2
  47. data/src/core/lib/gprpp/ref_counted.h +4 -2
  48. data/src/core/lib/gprpp/ref_counted_ptr.h +65 -13
  49. data/src/core/lib/iomgr/call_combiner.h +4 -1
  50. data/src/core/lib/iomgr/ev_epoll1_linux.cc +77 -17
  51. data/src/core/lib/iomgr/ev_epollex_linux.cc +8 -26
  52. data/src/core/lib/iomgr/ev_epollsig_linux.cc +10 -28
  53. data/src/core/lib/iomgr/ev_poll_posix.cc +144 -35
  54. data/src/core/lib/iomgr/ev_posix.cc +58 -9
  55. data/src/core/lib/iomgr/ev_posix.h +22 -8
  56. data/src/core/lib/iomgr/exec_ctx.cc +6 -0
  57. data/src/core/lib/iomgr/exec_ctx.h +2 -0
  58. data/src/core/lib/iomgr/executor.cc +148 -72
  59. data/src/core/lib/iomgr/executor.h +39 -6
  60. data/src/core/lib/iomgr/fork_posix.cc +12 -1
  61. data/src/core/lib/iomgr/iocp_windows.cc +9 -4
  62. data/src/core/lib/iomgr/lockfree_event.cc +5 -1
  63. data/src/core/lib/iomgr/port.h +15 -2
  64. data/src/core/lib/iomgr/resolve_address_posix.cc +3 -2
  65. data/src/core/lib/iomgr/resolve_address_windows.cc +3 -2
  66. data/src/core/lib/iomgr/resource_quota.cc +78 -0
  67. data/src/core/lib/iomgr/resource_quota.h +16 -0
  68. data/src/core/lib/iomgr/socket_mutator.cc +1 -1
  69. data/src/core/lib/iomgr/socket_mutator.h +1 -1
  70. data/src/core/lib/iomgr/socket_windows.cc +33 -0
  71. data/src/core/lib/iomgr/socket_windows.h +6 -0
  72. data/src/core/lib/iomgr/tcp_windows.cc +2 -2
  73. data/src/core/lib/iomgr/tcp_windows.h +2 -0
  74. data/src/core/lib/iomgr/timer.h +3 -2
  75. data/src/core/lib/json/json.cc +2 -1
  76. data/src/core/lib/security/credentials/jwt/json_token.h +2 -0
  77. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +2 -0
  78. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -1
  79. data/src/core/lib/security/security_connector/load_system_roots.h +29 -0
  80. data/src/core/lib/security/security_connector/load_system_roots_fallback.cc +32 -0
  81. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +165 -0
  82. data/src/core/lib/security/security_connector/load_system_roots_linux.h +44 -0
  83. data/src/core/lib/security/security_connector/security_connector.cc +23 -4
  84. data/src/core/lib/security/transport/client_auth_filter.cc +0 -4
  85. data/src/core/lib/security/transport/server_auth_filter.cc +0 -2
  86. data/src/core/lib/surface/call.cc +7 -3
  87. data/src/core/lib/surface/channel.cc +18 -2
  88. data/src/core/lib/surface/completion_queue.cc +152 -15
  89. data/src/core/lib/surface/completion_queue.h +20 -1
  90. data/src/core/lib/surface/completion_queue_factory.cc +13 -4
  91. data/src/core/lib/surface/init.cc +2 -2
  92. data/src/core/lib/surface/init.h +0 -1
  93. data/src/core/lib/surface/version.cc +2 -2
  94. data/src/core/lib/transport/service_config.cc +2 -2
  95. data/src/core/lib/transport/service_config.h +3 -3
  96. data/src/core/lib/transport/transport.h +2 -0
  97. data/src/core/tsi/alts/crypt/aes_gcm.cc +2 -0
  98. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +8 -0
  99. data/src/core/tsi/grpc_shadow_boringssl.h +3006 -0
  100. data/src/core/tsi/ssl/session_cache/ssl_session.h +2 -0
  101. data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +5 -5
  102. data/src/core/tsi/ssl/session_cache/ssl_session_cache.h +2 -0
  103. data/src/core/tsi/ssl_transport_security.cc +5 -3
  104. data/src/core/tsi/ssl_types.h +2 -0
  105. data/src/ruby/ext/grpc/extconf.rb +1 -26
  106. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +12 -0
  107. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +18 -0
  108. data/src/ruby/lib/grpc/version.rb +1 -1
  109. data/src/ruby/spec/generic/client_stub_spec.rb +3 -3
  110. data/third_party/address_sorting/address_sorting.c +7 -2
  111. data/third_party/address_sorting/address_sorting_windows.c +43 -3
  112. data/third_party/address_sorting/include/address_sorting/address_sorting.h +3 -0
  113. metadata +40 -31
@@ -59,7 +59,14 @@ grpc_core::DebugOnlyTraceFlag grpc_polling_api_trace(false, "polling_api");
59
59
 
60
60
  /** Default poll() function - a pointer so that it can be overridden by some
61
61
  * tests */
62
+ #ifndef GPR_AIX
62
63
  grpc_poll_function_type grpc_poll_function = poll;
64
+ #else
65
+ int aix_poll(struct pollfd fds[], nfds_t nfds, int timeout) {
66
+ return poll(fds, nfds, timeout);
67
+ }
68
+ grpc_poll_function_type grpc_poll_function = aix_poll;
69
+ #endif
63
70
 
64
71
  grpc_wakeup_fd grpc_global_wakeup_fd;
65
72
 
@@ -101,10 +108,28 @@ const grpc_event_engine_vtable* init_non_polling(bool explicit_request) {
101
108
  }
102
109
  } // namespace
103
110
 
104
- static const event_engine_factory g_factories[] = {
111
+ #define ENGINE_HEAD_CUSTOM "head_custom"
112
+ #define ENGINE_TAIL_CUSTOM "tail_custom"
113
+
114
+ // The global array of event-engine factories. Each entry is a pair with a name
115
+ // and an event-engine generator function (nullptr if there is no generator
116
+ // registered for this name). The middle entries are the engines predefined by
117
+ // open-source gRPC. The head entries represent an opportunity for specific
118
+ // high-priority custom pollers to be added by the initializer plugins of
119
+ // custom-built gRPC libraries. The tail entries represent the same, but for
120
+ // low-priority custom pollers. The actual poller selected is either the first
121
+ // available one in the list if no specific poller is requested, or the first
122
+ // specific poller that is requested by name in the GRPC_POLL_STRATEGY
123
+ // environment variable if that variable is set (which should be a
124
+ // comma-separated list of one or more event engine names)
125
+ static event_engine_factory g_factories[] = {
126
+ {ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr},
127
+ {ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr},
105
128
  {"epollex", grpc_init_epollex_linux}, {"epoll1", grpc_init_epoll1_linux},
106
129
  {"epollsig", grpc_init_epollsig_linux}, {"poll", grpc_init_poll_posix},
107
130
  {"poll-cv", grpc_init_poll_cv_posix}, {"none", init_non_polling},
131
+ {ENGINE_TAIL_CUSTOM, nullptr}, {ENGINE_TAIL_CUSTOM, nullptr},
132
+ {ENGINE_TAIL_CUSTOM, nullptr}, {ENGINE_TAIL_CUSTOM, nullptr},
108
133
  };
109
134
 
110
135
  static void add(const char* beg, const char* end, char*** ss, size_t* ns) {
@@ -138,7 +163,7 @@ static bool is(const char* want, const char* have) {
138
163
 
139
164
  static void try_engine(const char* engine) {
140
165
  for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) {
141
- if (is(engine, g_factories[i].name)) {
166
+ if (g_factories[i].factory != nullptr && is(engine, g_factories[i].name)) {
142
167
  if ((g_event_engine = g_factories[i].factory(
143
168
  0 == strcmp(engine, g_factories[i].name)))) {
144
169
  g_poll_strategy_name = g_factories[i].name;
@@ -149,14 +174,32 @@ static void try_engine(const char* engine) {
149
174
  }
150
175
  }
151
176
 
152
- /* This should be used for testing purposes ONLY */
153
- void grpc_set_event_engine_test_only(
154
- const grpc_event_engine_vtable* ev_engine) {
155
- g_event_engine = ev_engine;
156
- }
177
+ /* Call this before calling grpc_event_engine_init() */
178
+ void grpc_register_event_engine_factory(const char* name,
179
+ event_engine_factory_fn factory,
180
+ bool add_at_head) {
181
+ const char* custom_match =
182
+ add_at_head ? ENGINE_HEAD_CUSTOM : ENGINE_TAIL_CUSTOM;
183
+
184
+ // Overwrite an existing registration if already registered
185
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) {
186
+ if (0 == strcmp(name, g_factories[i].name)) {
187
+ g_factories[i].factory = factory;
188
+ return;
189
+ }
190
+ }
157
191
 
158
- const grpc_event_engine_vtable* grpc_get_event_engine_test_only() {
159
- return g_event_engine;
192
+ // Otherwise fill in an available custom slot
193
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) {
194
+ if (0 == strcmp(g_factories[i].name, custom_match)) {
195
+ g_factories[i].name = name;
196
+ g_factories[i].factory = factory;
197
+ return;
198
+ }
199
+ }
200
+
201
+ // Otherwise fail
202
+ GPR_ASSERT(false);
160
203
  }
161
204
 
162
205
  /* Call this only after calling grpc_event_engine_init() */
@@ -239,6 +282,12 @@ void grpc_fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) {
239
282
  g_event_engine->fd_notify_on_error(fd, closure);
240
283
  }
241
284
 
285
+ void grpc_fd_set_readable(grpc_fd* fd) { g_event_engine->fd_set_readable(fd); }
286
+
287
+ void grpc_fd_set_writable(grpc_fd* fd) { g_event_engine->fd_set_writable(fd); }
288
+
289
+ void grpc_fd_set_error(grpc_fd* fd) { g_event_engine->fd_set_error(fd); }
290
+
242
291
  static size_t pollset_size(void) { return g_event_engine->pollset_size; }
243
292
 
244
293
  static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) {
@@ -51,8 +51,10 @@ typedef struct grpc_event_engine_vtable {
51
51
  void (*fd_notify_on_read)(grpc_fd* fd, grpc_closure* closure);
52
52
  void (*fd_notify_on_write)(grpc_fd* fd, grpc_closure* closure);
53
53
  void (*fd_notify_on_error)(grpc_fd* fd, grpc_closure* closure);
54
+ void (*fd_set_readable)(grpc_fd* fd);
55
+ void (*fd_set_writable)(grpc_fd* fd);
56
+ void (*fd_set_error)(grpc_fd* fd);
54
57
  bool (*fd_is_shutdown)(grpc_fd* fd);
55
- grpc_pollset* (*fd_get_read_notifier_pollset)(grpc_fd* fd);
56
58
 
57
59
  void (*pollset_init)(grpc_pollset* pollset, gpr_mu** mu);
58
60
  void (*pollset_shutdown)(grpc_pollset* pollset, grpc_closure* closure);
@@ -80,6 +82,11 @@ typedef struct grpc_event_engine_vtable {
80
82
  void (*shutdown_engine)(void);
81
83
  } grpc_event_engine_vtable;
82
84
 
85
+ /* register a new event engine factory */
86
+ void grpc_register_event_engine_factory(
87
+ const char* name, const grpc_event_engine_vtable* (*factory)(bool),
88
+ bool add_at_head);
89
+
83
90
  void grpc_event_engine_init(void);
84
91
  void grpc_event_engine_shutdown(void);
85
92
 
@@ -142,8 +149,20 @@ void grpc_fd_notify_on_write(grpc_fd* fd, grpc_closure* closure);
142
149
  * needs to have been set on grpc_fd_create */
143
150
  void grpc_fd_notify_on_error(grpc_fd* fd, grpc_closure* closure);
144
151
 
145
- /* Return the read notifier pollset from the fd */
146
- grpc_pollset* grpc_fd_get_read_notifier_pollset(grpc_fd* fd);
152
+ /* Forcibly set the fd to be readable, resulting in the closure registered with
153
+ * grpc_fd_notify_on_read being invoked.
154
+ */
155
+ void grpc_fd_set_readable(grpc_fd* fd);
156
+
157
+ /* Forcibly set the fd to be writable, resulting in the closure registered with
158
+ * grpc_fd_notify_on_write being invoked.
159
+ */
160
+ void grpc_fd_set_writable(grpc_fd* fd);
161
+
162
+ /* Forcibly set the fd to have errored, resulting in the closure registered with
163
+ * grpc_fd_notify_on_error being invoked.
164
+ */
165
+ void grpc_fd_set_error(grpc_fd* fd);
147
166
 
148
167
  /* pollset_posix functions */
149
168
 
@@ -159,9 +178,4 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd);
159
178
  typedef int (*grpc_poll_function_type)(struct pollfd*, nfds_t, int);
160
179
  extern grpc_poll_function_type grpc_poll_function;
161
180
 
162
- /* WARNING: The following two functions should be used for testing purposes
163
- * ONLY */
164
- void grpc_set_event_engine_test_only(const grpc_event_engine_vtable*);
165
- const grpc_event_engine_vtable* grpc_get_event_engine_test_only();
166
-
167
181
  #endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */
@@ -109,6 +109,12 @@ grpc_closure_scheduler* grpc_schedule_on_exec_ctx = &exec_ctx_scheduler;
109
109
  namespace grpc_core {
110
110
  GPR_TLS_CLASS_DEF(ExecCtx::exec_ctx_);
111
111
 
112
+ // WARNING: for testing purposes only!
113
+ void ExecCtx::TestOnlyGlobalInit(gpr_timespec new_val) {
114
+ g_start_time = new_val;
115
+ gpr_tls_init(&exec_ctx_);
116
+ }
117
+
112
118
  void ExecCtx::GlobalInit(void) {
113
119
  g_start_time = gpr_now(GPR_CLOCK_MONOTONIC);
114
120
  gpr_tls_init(&exec_ctx_);
@@ -192,6 +192,8 @@ class ExecCtx {
192
192
  now_is_valid_ = true;
193
193
  }
194
194
 
195
+ static void TestOnlyGlobalInit(gpr_timespec new_val);
196
+
195
197
  /** Global initialization for ExecCtx. Called by iomgr. */
196
198
  static void GlobalInit(void);
197
199
 
@@ -40,19 +40,25 @@
40
40
  gpr_log(GPR_INFO, "EXECUTOR " format, __VA_ARGS__); \
41
41
  }
42
42
 
43
+ #define EXECUTOR_TRACE0(str) \
44
+ if (executor_trace.enabled()) { \
45
+ gpr_log(GPR_INFO, "EXECUTOR " str); \
46
+ }
47
+
43
48
  grpc_core::TraceFlag executor_trace(false, "executor");
44
49
 
45
50
  GPR_TLS_DECL(g_this_thread_state);
46
51
 
47
- GrpcExecutor::GrpcExecutor(const char* executor_name) : name_(executor_name) {
52
+ GrpcExecutor::GrpcExecutor(const char* name) : name_(name) {
48
53
  adding_thread_lock_ = GPR_SPINLOCK_STATIC_INITIALIZER;
49
- gpr_atm_no_barrier_store(&num_threads_, 0);
54
+ gpr_atm_rel_store(&num_threads_, 0);
50
55
  max_threads_ = GPR_MAX(1, 2 * gpr_cpu_num_cores());
51
56
  }
52
57
 
53
58
  void GrpcExecutor::Init() { SetThreading(true); }
54
59
 
55
- size_t GrpcExecutor::RunClosures(grpc_closure_list list) {
60
+ size_t GrpcExecutor::RunClosures(const char* executor_name,
61
+ grpc_closure_list list) {
56
62
  size_t n = 0;
57
63
 
58
64
  grpc_closure* c = list.head;
@@ -60,11 +66,11 @@ size_t GrpcExecutor::RunClosures(grpc_closure_list list) {
60
66
  grpc_closure* next = c->next_data.next;
61
67
  grpc_error* error = c->error_data.error;
62
68
  #ifndef NDEBUG
63
- EXECUTOR_TRACE("run %p [created by %s:%d]", c, c->file_created,
64
- c->line_created);
69
+ EXECUTOR_TRACE("(%s) run %p [created by %s:%d]", executor_name, c,
70
+ c->file_created, c->line_created);
65
71
  c->scheduled = false;
66
72
  #else
67
- EXECUTOR_TRACE("run %p", c);
73
+ EXECUTOR_TRACE("(%s) run %p", executor_name, c);
68
74
  #endif
69
75
  c->cb(c->cb_arg, error);
70
76
  GRPC_ERROR_UNREF(error);
@@ -77,17 +83,21 @@ size_t GrpcExecutor::RunClosures(grpc_closure_list list) {
77
83
  }
78
84
 
79
85
  bool GrpcExecutor::IsThreaded() const {
80
- return gpr_atm_no_barrier_load(&num_threads_) > 0;
86
+ return gpr_atm_acq_load(&num_threads_) > 0;
81
87
  }
82
88
 
83
89
  void GrpcExecutor::SetThreading(bool threading) {
84
- gpr_atm curr_num_threads = gpr_atm_no_barrier_load(&num_threads_);
90
+ gpr_atm curr_num_threads = gpr_atm_acq_load(&num_threads_);
91
+ EXECUTOR_TRACE("(%s) SetThreading(%d) begin", name_, threading);
85
92
 
86
93
  if (threading) {
87
- if (curr_num_threads > 0) return;
94
+ if (curr_num_threads > 0) {
95
+ EXECUTOR_TRACE("(%s) SetThreading(true). curr_num_threads == 0", name_);
96
+ return;
97
+ }
88
98
 
89
99
  GPR_ASSERT(num_threads_ == 0);
90
- gpr_atm_no_barrier_store(&num_threads_, 1);
100
+ gpr_atm_rel_store(&num_threads_, 1);
91
101
  gpr_tls_init(&g_this_thread_state);
92
102
  thd_state_ = static_cast<ThreadState*>(
93
103
  gpr_zalloc(sizeof(ThreadState) * max_threads_));
@@ -96,6 +106,7 @@ void GrpcExecutor::SetThreading(bool threading) {
96
106
  gpr_mu_init(&thd_state_[i].mu);
97
107
  gpr_cv_init(&thd_state_[i].cv);
98
108
  thd_state_[i].id = i;
109
+ thd_state_[i].name = name_;
99
110
  thd_state_[i].thd = grpc_core::Thread();
100
111
  thd_state_[i].elems = GRPC_CLOSURE_LIST_INIT;
101
112
  }
@@ -104,7 +115,10 @@ void GrpcExecutor::SetThreading(bool threading) {
104
115
  grpc_core::Thread(name_, &GrpcExecutor::ThreadMain, &thd_state_[0]);
105
116
  thd_state_[0].thd.Start();
106
117
  } else { // !threading
107
- if (curr_num_threads == 0) return;
118
+ if (curr_num_threads == 0) {
119
+ EXECUTOR_TRACE("(%s) SetThreading(false). curr_num_threads == 0", name_);
120
+ return;
121
+ }
108
122
 
109
123
  for (size_t i = 0; i < max_threads_; i++) {
110
124
  gpr_mu_lock(&thd_state_[i].mu);
@@ -121,20 +135,22 @@ void GrpcExecutor::SetThreading(bool threading) {
121
135
  curr_num_threads = gpr_atm_no_barrier_load(&num_threads_);
122
136
  for (gpr_atm i = 0; i < curr_num_threads; i++) {
123
137
  thd_state_[i].thd.Join();
124
- EXECUTOR_TRACE(" Thread %" PRIdPTR " of %" PRIdPTR " joined", i,
125
- curr_num_threads);
138
+ EXECUTOR_TRACE("(%s) Thread %" PRIdPTR " of %" PRIdPTR " joined", name_,
139
+ i + 1, curr_num_threads);
126
140
  }
127
141
 
128
- gpr_atm_no_barrier_store(&num_threads_, 0);
142
+ gpr_atm_rel_store(&num_threads_, 0);
129
143
  for (size_t i = 0; i < max_threads_; i++) {
130
144
  gpr_mu_destroy(&thd_state_[i].mu);
131
145
  gpr_cv_destroy(&thd_state_[i].cv);
132
- RunClosures(thd_state_[i].elems);
146
+ RunClosures(thd_state_[i].name, thd_state_[i].elems);
133
147
  }
134
148
 
135
149
  gpr_free(thd_state_);
136
150
  gpr_tls_destroy(&g_this_thread_state);
137
151
  }
152
+
153
+ EXECUTOR_TRACE("(%s) SetThreading(%d) done", name_, threading);
138
154
  }
139
155
 
140
156
  void GrpcExecutor::Shutdown() { SetThreading(false); }
@@ -147,8 +163,8 @@ void GrpcExecutor::ThreadMain(void* arg) {
147
163
 
148
164
  size_t subtract_depth = 0;
149
165
  for (;;) {
150
- EXECUTOR_TRACE("[%" PRIdPTR "]: step (sub_depth=%" PRIdPTR ")", ts->id,
151
- subtract_depth);
166
+ EXECUTOR_TRACE("(%s) [%" PRIdPTR "]: step (sub_depth=%" PRIdPTR ")",
167
+ ts->name, ts->id, subtract_depth);
152
168
 
153
169
  gpr_mu_lock(&ts->mu);
154
170
  ts->depth -= subtract_depth;
@@ -159,7 +175,7 @@ void GrpcExecutor::ThreadMain(void* arg) {
159
175
  }
160
176
 
161
177
  if (ts->shutdown) {
162
- EXECUTOR_TRACE("[%" PRIdPTR "]: shutdown", ts->id);
178
+ EXECUTOR_TRACE("(%s) [%" PRIdPTR "]: shutdown", ts->name, ts->id);
163
179
  gpr_mu_unlock(&ts->mu);
164
180
  break;
165
181
  }
@@ -169,10 +185,10 @@ void GrpcExecutor::ThreadMain(void* arg) {
169
185
  ts->elems = GRPC_CLOSURE_LIST_INIT;
170
186
  gpr_mu_unlock(&ts->mu);
171
187
 
172
- EXECUTOR_TRACE("[%" PRIdPTR "]: execute", ts->id);
188
+ EXECUTOR_TRACE("(%s) [%" PRIdPTR "]: execute", ts->name, ts->id);
173
189
 
174
190
  grpc_core::ExecCtx::Get()->InvalidateNow();
175
- subtract_depth = RunClosures(closures);
191
+ subtract_depth = RunClosures(ts->name, closures);
176
192
  }
177
193
  }
178
194
 
@@ -188,16 +204,16 @@ void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
188
204
  do {
189
205
  retry_push = false;
190
206
  size_t cur_thread_count =
191
- static_cast<size_t>(gpr_atm_no_barrier_load(&num_threads_));
207
+ static_cast<size_t>(gpr_atm_acq_load(&num_threads_));
192
208
 
193
209
  // If the number of threads is zero(i.e either the executor is not threaded
194
210
  // or already shutdown), then queue the closure on the exec context itself
195
211
  if (cur_thread_count == 0) {
196
212
  #ifndef NDEBUG
197
- EXECUTOR_TRACE("schedule %p (created %s:%d) inline", closure,
213
+ EXECUTOR_TRACE("(%s) schedule %p (created %s:%d) inline", name_, closure,
198
214
  closure->file_created, closure->line_created);
199
215
  #else
200
- EXECUTOR_TRACE("schedule %p inline", closure);
216
+ EXECUTOR_TRACE("(%s) schedule %p inline", name_, closure);
201
217
  #endif
202
218
  grpc_closure_list_append(grpc_core::ExecCtx::Get()->closure_list(),
203
219
  closure, error);
@@ -213,18 +229,18 @@ void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
213
229
  }
214
230
 
215
231
  ThreadState* orig_ts = ts;
216
-
217
232
  bool try_new_thread = false;
233
+
218
234
  for (;;) {
219
235
  #ifndef NDEBUG
220
236
  EXECUTOR_TRACE(
221
- "try to schedule %p (%s) (created %s:%d) to thread "
237
+ "(%s) try to schedule %p (%s) (created %s:%d) to thread "
222
238
  "%" PRIdPTR,
223
- closure, is_short ? "short" : "long", closure->file_created,
239
+ name_, closure, is_short ? "short" : "long", closure->file_created,
224
240
  closure->line_created, ts->id);
225
241
  #else
226
- EXECUTOR_TRACE("try to schedule %p (%s) to thread %" PRIdPTR, closure,
227
- is_short ? "short" : "long", ts->id);
242
+ EXECUTOR_TRACE("(%s) try to schedule %p (%s) to thread %" PRIdPTR, name_,
243
+ closure, is_short ? "short" : "long", ts->id);
228
244
  #endif
229
245
 
230
246
  gpr_mu_lock(&ts->mu);
@@ -236,18 +252,22 @@ void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
236
252
  size_t idx = ts->id;
237
253
  ts = &thd_state_[(idx + 1) % cur_thread_count];
238
254
  if (ts == orig_ts) {
239
- // We cycled through all the threads. Retry enqueue again (by creating
240
- // a new thread)
255
+ // We cycled through all the threads. Retry enqueue again by creating
256
+ // a new thread
257
+ //
258
+ // TODO (sreek): There is a potential issue here. We are
259
+ // unconditionally setting try_new_thread to true here. What if the
260
+ // executor is shutdown OR if cur_thread_count is already equal to
261
+ // max_threads ?
262
+ // (Fortunately, this is not an issue yet (as of july 2018) because
263
+ // there is only one instance of long job in gRPC and hence we will
264
+ // not hit this code path)
241
265
  retry_push = true;
242
- // TODO (sreek): What if the executor is shutdown OR if
243
- // cur_thread_count is already equal to max_threads ? (currently - as
244
- // of July 2018, we do not run in to this issue because there is only
245
- // one instance of long job in gRPC. This has to be fixed soon)
246
266
  try_new_thread = true;
247
267
  break;
248
268
  }
249
269
 
250
- continue;
270
+ continue; // Try the next thread-state
251
271
  }
252
272
 
253
273
  // == Found the thread state (i.e thread) to enqueue this closure! ==
@@ -277,13 +297,11 @@ void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
277
297
  }
278
298
 
279
299
  if (try_new_thread && gpr_spinlock_trylock(&adding_thread_lock_)) {
280
- cur_thread_count =
281
- static_cast<size_t>(gpr_atm_no_barrier_load(&num_threads_));
300
+ cur_thread_count = static_cast<size_t>(gpr_atm_acq_load(&num_threads_));
282
301
  if (cur_thread_count < max_threads_) {
283
- // Increment num_threads (Safe to do a no_barrier_store instead of a
284
- // cas because we always increment num_threads under the
285
- // 'adding_thread_lock')
286
- gpr_atm_no_barrier_store(&num_threads_, cur_thread_count + 1);
302
+ // Increment num_threads (safe to do a store instead of a cas because we
303
+ // always increment num_threads under the 'adding_thread_lock')
304
+ gpr_atm_rel_store(&num_threads_, cur_thread_count + 1);
287
305
 
288
306
  thd_state_[cur_thread_count].thd = grpc_core::Thread(
289
307
  name_, &GrpcExecutor::ThreadMain, &thd_state_[cur_thread_count]);
@@ -298,60 +316,118 @@ void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
298
316
  } while (retry_push);
299
317
  }
300
318
 
301
- static GrpcExecutor* global_executor;
319
+ static GrpcExecutor* executors[GRPC_NUM_EXECUTORS];
302
320
 
303
- void enqueue_long(grpc_closure* closure, grpc_error* error) {
304
- global_executor->Enqueue(closure, error, false /* is_short */);
321
+ void default_enqueue_short(grpc_closure* closure, grpc_error* error) {
322
+ executors[GRPC_DEFAULT_EXECUTOR]->Enqueue(closure, error,
323
+ true /* is_short */);
305
324
  }
306
325
 
307
- void enqueue_short(grpc_closure* closure, grpc_error* error) {
308
- global_executor->Enqueue(closure, error, true /* is_short */);
326
+ void default_enqueue_long(grpc_closure* closure, grpc_error* error) {
327
+ executors[GRPC_DEFAULT_EXECUTOR]->Enqueue(closure, error,
328
+ false /* is_short */);
309
329
  }
310
330
 
311
- // Short-Job executor scheduler
312
- static const grpc_closure_scheduler_vtable global_executor_vtable_short = {
313
- enqueue_short, enqueue_short, "executor-short"};
314
- static grpc_closure_scheduler global_scheduler_short = {
315
- &global_executor_vtable_short};
331
+ void resolver_enqueue_short(grpc_closure* closure, grpc_error* error) {
332
+ executors[GRPC_RESOLVER_EXECUTOR]->Enqueue(closure, error,
333
+ true /* is_short */);
334
+ }
316
335
 
317
- // Long-job executor scheduler
318
- static const grpc_closure_scheduler_vtable global_executor_vtable_long = {
319
- enqueue_long, enqueue_long, "executor-long"};
320
- static grpc_closure_scheduler global_scheduler_long = {
321
- &global_executor_vtable_long};
336
+ void resolver_enqueue_long(grpc_closure* closure, grpc_error* error) {
337
+ executors[GRPC_RESOLVER_EXECUTOR]->Enqueue(closure, error,
338
+ false /* is_short */);
339
+ }
340
+
341
+ static const grpc_closure_scheduler_vtable
342
+ vtables_[GRPC_NUM_EXECUTORS][GRPC_NUM_EXECUTOR_JOB_TYPES] = {
343
+ {{&default_enqueue_short, &default_enqueue_short, "def-ex-short"},
344
+ {&default_enqueue_long, &default_enqueue_long, "def-ex-long"}},
345
+ {{&resolver_enqueue_short, &resolver_enqueue_short, "res-ex-short"},
346
+ {&resolver_enqueue_long, &resolver_enqueue_long, "res-ex-long"}}};
347
+
348
+ static grpc_closure_scheduler
349
+ schedulers_[GRPC_NUM_EXECUTORS][GRPC_NUM_EXECUTOR_JOB_TYPES] = {
350
+ {{&vtables_[GRPC_DEFAULT_EXECUTOR][GRPC_EXECUTOR_SHORT]},
351
+ {&vtables_[GRPC_DEFAULT_EXECUTOR][GRPC_EXECUTOR_LONG]}},
352
+ {{&vtables_[GRPC_RESOLVER_EXECUTOR][GRPC_EXECUTOR_SHORT]},
353
+ {&vtables_[GRPC_RESOLVER_EXECUTOR][GRPC_EXECUTOR_LONG]}}};
322
354
 
323
355
  // grpc_executor_init() and grpc_executor_shutdown() functions are called in the
324
356
  // the grpc_init() and grpc_shutdown() code paths which are protected by a
325
357
  // global mutex. So it is okay to assume that these functions are thread-safe
326
358
  void grpc_executor_init() {
327
- if (global_executor != nullptr) {
328
- // grpc_executor_init() already called once (and grpc_executor_shutdown()
329
- // wasn't called)
359
+ EXECUTOR_TRACE0("grpc_executor_init() enter");
360
+
361
+ // Return if grpc_executor_init() is already called earlier
362
+ if (executors[GRPC_DEFAULT_EXECUTOR] != nullptr) {
363
+ GPR_ASSERT(executors[GRPC_RESOLVER_EXECUTOR] != nullptr);
330
364
  return;
331
365
  }
332
366
 
333
- global_executor = grpc_core::New<GrpcExecutor>("global-executor");
334
- global_executor->Init();
367
+ executors[GRPC_DEFAULT_EXECUTOR] =
368
+ grpc_core::New<GrpcExecutor>("default-executor");
369
+ executors[GRPC_RESOLVER_EXECUTOR] =
370
+ grpc_core::New<GrpcExecutor>("resolver-executor");
371
+
372
+ executors[GRPC_DEFAULT_EXECUTOR]->Init();
373
+ executors[GRPC_RESOLVER_EXECUTOR]->Init();
374
+
375
+ EXECUTOR_TRACE0("grpc_executor_init() done");
376
+ }
377
+
378
+ grpc_closure_scheduler* grpc_executor_scheduler(GrpcExecutorType executor_type,
379
+ GrpcExecutorJobType job_type) {
380
+ return &schedulers_[executor_type][job_type];
381
+ }
382
+
383
+ grpc_closure_scheduler* grpc_executor_scheduler(GrpcExecutorJobType job_type) {
384
+ return grpc_executor_scheduler(GRPC_DEFAULT_EXECUTOR, job_type);
335
385
  }
336
386
 
337
387
  void grpc_executor_shutdown() {
338
- // Shutdown already called
339
- if (global_executor == nullptr) {
388
+ EXECUTOR_TRACE0("grpc_executor_shutdown() enter");
389
+
390
+ // Return if grpc_executor_shutdown() is already called earlier
391
+ if (executors[GRPC_DEFAULT_EXECUTOR] == nullptr) {
392
+ GPR_ASSERT(executors[GRPC_RESOLVER_EXECUTOR] == nullptr);
340
393
  return;
341
394
  }
342
395
 
343
- global_executor->Shutdown();
344
- grpc_core::Delete<GrpcExecutor>(global_executor);
345
- global_executor = nullptr;
396
+ executors[GRPC_DEFAULT_EXECUTOR]->Shutdown();
397
+ executors[GRPC_RESOLVER_EXECUTOR]->Shutdown();
398
+
399
+ // Delete the executor objects.
400
+ //
401
+ // NOTE: It is important to call Shutdown() on all executors first before
402
+ // calling Delete() because it is possible for one executor (that is not
403
+ // shutdown yet) to call Enqueue() on a different executor which is already
404
+ // shutdown. This is legal and in such cases, the Enqueue() operation
405
+ // effectively "fails" and enqueues that closure on the calling thread's
406
+ // exec_ctx.
407
+ //
408
+ // By ensuring that all executors are shutdown first, we are also ensuring
409
+ // that no thread is active across all executors.
410
+
411
+ grpc_core::Delete<GrpcExecutor>(executors[GRPC_DEFAULT_EXECUTOR]);
412
+ grpc_core::Delete<GrpcExecutor>(executors[GRPC_RESOLVER_EXECUTOR]);
413
+ executors[GRPC_DEFAULT_EXECUTOR] = nullptr;
414
+ executors[GRPC_RESOLVER_EXECUTOR] = nullptr;
415
+
416
+ EXECUTOR_TRACE0("grpc_executor_shutdown() done");
346
417
  }
347
418
 
348
- bool grpc_executor_is_threaded() { return global_executor->IsThreaded(); }
419
+ bool grpc_executor_is_threaded(GrpcExecutorType executor_type) {
420
+ GPR_ASSERT(executor_type < GRPC_NUM_EXECUTORS);
421
+ return executors[executor_type]->IsThreaded();
422
+ }
349
423
 
350
- void grpc_executor_set_threading(bool enable) {
351
- global_executor->SetThreading(enable);
424
+ bool grpc_executor_is_threaded() {
425
+ return grpc_executor_is_threaded(GRPC_DEFAULT_EXECUTOR);
352
426
  }
353
427
 
354
- grpc_closure_scheduler* grpc_executor_scheduler(GrpcExecutorJobType job_type) {
355
- return job_type == GRPC_EXECUTOR_SHORT ? &global_scheduler_short
356
- : &global_scheduler_long;
428
+ void grpc_executor_set_threading(bool enable) {
429
+ EXECUTOR_TRACE("grpc_executor_set_threading(%d) called", enable);
430
+ for (int i = 0; i < GRPC_NUM_EXECUTORS; i++) {
431
+ executors[i]->SetThreading(enable);
432
+ }
357
433
  }