blob: e9e6d0a4bb239462b6655ef163daa84713258b8d [file] [log] [blame]
David Garcia Quintas4bc34632015-10-07 16:12:35 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
David Garcia Quintas4bc34632015-10-07 16:12:35 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
David Garcia Quintas4bc34632015-10-07 16:12:35 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
David Garcia Quintas4bc34632015-10-07 16:12:35 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
David Garcia Quintas4bc34632015-10-07 16:12:35 -070016 *
17 */
18
Alexander Polcyndb3e8982018-02-21 16:59:24 -080019#include <grpc/support/port_platform.h>
20
Craig Tiller9533d042016-03-25 17:11:06 -070021#include "src/core/lib/iomgr/executor.h"
David Garcia Quintas4bc34632015-10-07 16:12:35 -070022
23#include <string.h>
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -070024#include <functional>
David Garcia Quintas4bc34632015-10-07 16:12:35 -070025
26#include <grpc/support/alloc.h>
Craig Tiller3e9f98e2017-05-12 13:17:47 -070027#include <grpc/support/cpu.h>
David Garcia Quintas4bc34632015-10-07 16:12:35 -070028#include <grpc/support/log.h>
29#include <grpc/support/sync.h>
Craig Tiller3e9f98e2017-05-12 13:17:47 -070030
Craig Tiller57bb9a92017-08-31 16:44:15 -070031#include "src/core/lib/debug/stats.h"
Vijay Paib6cf1232018-01-25 21:02:26 -080032#include "src/core/lib/gpr/tls.h"
Vijay Paid4d0a302018-01-25 13:24:03 -080033#include "src/core/lib/gpr/useful.h"
Craig Tiller9533d042016-03-25 17:11:06 -070034#include "src/core/lib/iomgr/exec_ctx.h"
David Garcia Quintas4bc34632015-10-07 16:12:35 -070035
Craig Tiller2477cf32017-09-26 12:20:35 -070036#define MAX_DEPTH 2
37
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -070038#define EXECUTOR_TRACE(format, ...) \
39 if (executor_trace.enabled()) { \
40 gpr_log(GPR_INFO, format, __VA_ARGS__); \
41 }
Craig Tiller3e9f98e2017-05-12 13:17:47 -070042
ncteisen72afb762017-11-10 12:23:12 -080043grpc_core::TraceFlag executor_trace(false, "executor");
Craig Tilleraf723b02017-07-17 17:56:28 -070044
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -070045GPR_TLS_DECL(g_this_thread_state);
David Garcia Quintas4bc34632015-10-07 16:12:35 -070046
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -070047GrpcExecutor::GrpcExecutor(const char* executor_name) : name(executor_name) {
48 adding_thread_lock = GPR_SPINLOCK_STATIC_INITIALIZER;
49 gpr_atm_no_barrier_store(&num_threads, 0);
50}
51
52void GrpcExecutor::Init() { SetThreading(true); }
53
54size_t GrpcExecutor::RunClosures(grpc_closure_list list) {
Craig Tiller2477cf32017-09-26 12:20:35 -070055 size_t n = 0;
David Garcia Quintas4bc34632015-10-07 16:12:35 -070056
Craig Tillerbaa14a92017-11-03 09:09:36 -070057 grpc_closure* c = list.head;
Craig Tiller4782d922017-11-10 09:53:21 -080058 while (c != nullptr) {
Craig Tillerbaa14a92017-11-03 09:09:36 -070059 grpc_closure* next = c->next_data.next;
60 grpc_error* error = c->error_data.error;
Craig Tilleraf723b02017-07-17 17:56:28 -070061#ifndef NDEBUG
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -070062 EXECUTOR_TRACE("EXECUTOR: run %p [created by %s:%d]", c, c->file_created,
63 c->line_created);
Craig Tiller2477cf32017-09-26 12:20:35 -070064 c->scheduled = false;
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -070065#else
66 EXECUTOR_TRACE("EXECUTOR: run %p", c);
Craig Tiller2477cf32017-09-26 12:20:35 -070067#endif
Yash Tibrewal8cf14702017-12-06 09:47:54 -080068 c->cb(c->cb_arg, error);
Craig Tiller2477cf32017-09-26 12:20:35 -070069 GRPC_ERROR_UNREF(error);
70 c = next;
71 n++;
Yash Tibrewal8cf14702017-12-06 09:47:54 -080072 grpc_core::ExecCtx::Get()->Flush();
Craig Tiller061ef742016-12-29 10:54:09 -080073 }
Craig Tiller3e9f98e2017-05-12 13:17:47 -070074
Craig Tiller2477cf32017-09-26 12:20:35 -070075 return n;
Craig Tiller3e9f98e2017-05-12 13:17:47 -070076}
77
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -070078bool GrpcExecutor::IsThreaded() {
79 return gpr_atm_no_barrier_load(&num_threads) > 0;
Craig Tiller5e56f002017-05-16 15:02:50 -070080}
81
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -070082void GrpcExecutor::SetThreading(bool threading) {
83 gpr_atm curr_num_threads = gpr_atm_no_barrier_load(&num_threads);
84
Craig Tiller5e56f002017-05-16 15:02:50 -070085 if (threading) {
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -070086 if (curr_num_threads > 0) return;
87
88 // TODO (sreek): max_threads initialization can be moved into the
89 // constructor
90 max_threads = GPR_MAX(1, 2 * gpr_cpu_num_cores());
91 gpr_atm_no_barrier_store(&num_threads, 1);
Craig Tiller5e56f002017-05-16 15:02:50 -070092 gpr_tls_init(&g_this_thread_state);
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -070093 thd_state = static_cast<thread_state*>(
94 gpr_zalloc(sizeof(thread_state) * max_threads));
95
96 for (size_t i = 0; i < max_threads; i++) {
97 gpr_mu_init(&thd_state[i].mu);
98 gpr_cv_init(&thd_state[i].cv);
99 thd_state[i].id = i;
100 thd_state[i].thd = grpc_core::Thread();
101 thd_state[i].elems = GRPC_CLOSURE_LIST_INIT;
Craig Tiller5e56f002017-05-16 15:02:50 -0700102 }
103
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700104 thd_state[0].thd =
105 grpc_core::Thread(name, &GrpcExecutor::ThreadMain, &thd_state[0]);
106 thd_state[0].thd.Start();
Craig Tiller5e56f002017-05-16 15:02:50 -0700107 } else {
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700108 if (curr_num_threads == 0) return;
109
110 for (size_t i = 0; i < max_threads; i++) {
111 gpr_mu_lock(&thd_state[i].mu);
112 thd_state[i].shutdown = true;
113 gpr_cv_signal(&thd_state[i].cv);
114 gpr_mu_unlock(&thd_state[i].mu);
Craig Tiller5e56f002017-05-16 15:02:50 -0700115 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700116
117 /* Ensure no thread is adding a new thread. Once this is past, then no
118 * thread will try to add a new one either (since shutdown is true) */
119 gpr_spinlock_lock(&adding_thread_lock);
120 gpr_spinlock_unlock(&adding_thread_lock);
121
122 for (gpr_atm i = 0; i < num_threads; i++) {
123 thd_state[i].thd.Join();
Craig Tiller5e56f002017-05-16 15:02:50 -0700124 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700125
126 gpr_atm_no_barrier_store(&num_threads, 0);
127 for (size_t i = 0; i < max_threads; i++) {
128 gpr_mu_destroy(&thd_state[i].mu);
129 gpr_cv_destroy(&thd_state[i].cv);
130 RunClosures(thd_state[i].elems);
Craig Tiller5e56f002017-05-16 15:02:50 -0700131 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700132
133 gpr_free(thd_state);
Craig Tiller5e56f002017-05-16 15:02:50 -0700134 gpr_tls_destroy(&g_this_thread_state);
David Garcia Quintas4bc34632015-10-07 16:12:35 -0700135 }
Craig Tiller5e56f002017-05-16 15:02:50 -0700136}
137
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700138void GrpcExecutor::Shutdown() { SetThreading(false); }
Craig Tiller5e56f002017-05-16 15:02:50 -0700139
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700140void GrpcExecutor::ThreadMain(void* arg) {
Noah Eisenbe82e642018-02-09 09:16:55 -0800141 thread_state* ts = static_cast<thread_state*>(arg);
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700142 gpr_tls_set(&g_this_thread_state, (intptr_t)ts);
143
kpayson6446a60592018-06-20 15:18:38 -0700144 grpc_core::ExecCtx exec_ctx(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);
Craig Tiller89962082017-05-12 14:30:42 -0700145
Craig Tiller2477cf32017-09-26 12:20:35 -0700146 size_t subtract_depth = 0;
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700147 for (;;) {
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700148 EXECUTOR_TRACE("EXECUTOR[%ld]: step (sub_depth=%" PRIdPTR ")", ts->id,
149 subtract_depth);
150
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700151 gpr_mu_lock(&ts->mu);
Craig Tiller2477cf32017-09-26 12:20:35 -0700152 ts->depth -= subtract_depth;
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700153 // Wait for closures to be enqueued or for the executor to be shutdown
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700154 while (grpc_closure_list_empty(ts->elems) && !ts->shutdown) {
Craig Tiller1ab56d82017-07-19 09:55:57 -0700155 ts->queued_long_job = false;
Sree Kuchibhotla54961bb2017-12-04 12:50:27 -0800156 gpr_cv_wait(&ts->cv, &ts->mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700157 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700158
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700159 if (ts->shutdown) {
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700160 EXECUTOR_TRACE("EXECUTOR[%ld]: shutdown", ts->id);
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700161 gpr_mu_unlock(&ts->mu);
162 break;
163 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700164
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800165 GRPC_STATS_INC_EXECUTOR_QUEUE_DRAINED();
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700166 grpc_closure_list closures = ts->elems;
Yash Tibrewal37fdb732017-09-25 16:45:02 -0700167 ts->elems = GRPC_CLOSURE_LIST_INIT;
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700168 gpr_mu_unlock(&ts->mu);
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700169
170 EXECUTOR_TRACE("EXECUTOR[%ld]: execute", ts->id);
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700171
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800172 grpc_core::ExecCtx::Get()->InvalidateNow();
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700173 subtract_depth = RunClosures(closures);
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700174 }
175}
176
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700177void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
178 bool is_short) {
Craig Tiller2f767eb2017-07-20 12:06:14 -0700179 bool retry_push;
Craig Tiller07d2fa72017-09-07 13:13:36 -0700180 if (is_short) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800181 GRPC_STATS_INC_EXECUTOR_SCHEDULED_SHORT_ITEMS();
Craig Tiller07d2fa72017-09-07 13:13:36 -0700182 } else {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800183 GRPC_STATS_INC_EXECUTOR_SCHEDULED_LONG_ITEMS();
Craig Tiller07d2fa72017-09-07 13:13:36 -0700184 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700185
Craig Tiller2f767eb2017-07-20 12:06:14 -0700186 do {
187 retry_push = false;
Noah Eisen4d20a662018-02-09 09:34:04 -0800188 size_t cur_thread_count =
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700189 static_cast<size_t>(gpr_atm_no_barrier_load(&num_threads));
190
191 // If the number of threads is zero(i.e either the executor is not threaded
192 // or already shutdown), then queue the closure on the exec context itself
Craig Tiller2f767eb2017-07-20 12:06:14 -0700193 if (cur_thread_count == 0) {
Craig Tillerc2fb83e2017-07-18 12:38:25 -0700194#ifndef NDEBUG
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700195 EXECUTOR_TRACE("EXECUTOR: schedule %p (created %s:%d) inline", closure,
196 closure->file_created, closure->line_created);
Craig Tillerc2fb83e2017-07-18 12:38:25 -0700197#else
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700198 EXECUTOR_TRACE("EXECUTOR: schedule %p inline", closure);
Craig Tillerc2fb83e2017-07-18 12:38:25 -0700199#endif
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800200 grpc_closure_list_append(grpc_core::ExecCtx::Get()->closure_list(),
201 closure, error);
Craig Tiller2f767eb2017-07-20 12:06:14 -0700202 return;
Craig Tillerc2fb83e2017-07-18 12:38:25 -0700203 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700204
Craig Tillerbaa14a92017-11-03 09:09:36 -0700205 thread_state* ts = (thread_state*)gpr_tls_get(&g_this_thread_state);
Craig Tiller4782d922017-11-10 09:53:21 -0800206 if (ts == nullptr) {
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700207 ts = &thd_state[GPR_HASH_POINTER(grpc_core::ExecCtx::Get(),
208 cur_thread_count)];
Craig Tiller022ad3a2017-09-07 13:01:56 -0700209 } else {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800210 GRPC_STATS_INC_EXECUTOR_SCHEDULED_TO_SELF();
Craig Tillerc2fb83e2017-07-18 12:38:25 -0700211 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700212
Craig Tillerbaa14a92017-11-03 09:09:36 -0700213 thread_state* orig_ts = ts;
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700214
Craig Tiller2f767eb2017-07-20 12:06:14 -0700215 bool try_new_thread;
216 for (;;) {
Craig Tiller2f767eb2017-07-20 12:06:14 -0700217#ifndef NDEBUG
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700218 EXECUTOR_TRACE(
219 "EXECUTOR: try to schedule %p (%s) (created %s:%d) to thread %ld",
220 closure, is_short ? "short" : "long", closure->file_created,
221 closure->line_created, ts->id);
Craig Tiller2f767eb2017-07-20 12:06:14 -0700222#else
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700223 EXECUTOR_TRACE("EXECUTOR: try to schedule %p (%s) to thread %ld", closure,
224 is_short ? "short" : "long", ts->id);
Craig Tiller2f767eb2017-07-20 12:06:14 -0700225#endif
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700226
Craig Tiller2f767eb2017-07-20 12:06:14 -0700227 gpr_mu_lock(&ts->mu);
228 if (ts->queued_long_job) {
Craig Tillerb0ce25e2017-09-08 14:42:26 -0700229 // if there's a long job queued, we never queue anything else to this
230 // queue (since long jobs can take 'infinite' time and we need to
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700231 // guarantee no starvation). Spin through queues and try again
Craig Tiller2f767eb2017-07-20 12:06:14 -0700232 gpr_mu_unlock(&ts->mu);
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700233 size_t idx = ts->id;
234 ts = &thd_state[(idx + 1) % cur_thread_count];
Craig Tiller2f767eb2017-07-20 12:06:14 -0700235 if (ts == orig_ts) {
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700236 // We cycled through all the threads. Retry enqueue again (by creating
237 // a new thread)
Craig Tiller2f767eb2017-07-20 12:06:14 -0700238 retry_push = true;
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700239 // TODO (sreek): What if the executor is shutdown OR if
240 // cur_thread_count is already equal to max_threads ? (currently - as
241 // of July 2018, we do not run in to this issue because there is only
242 // one instance of long job in gRPC. This has to be fixed soon)
Craig Tiller2f767eb2017-07-20 12:06:14 -0700243 try_new_thread = true;
244 break;
245 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700246
Craig Tiller2f767eb2017-07-20 12:06:14 -0700247 continue;
248 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700249
250 // == Found the thread state (i.e thread) to enqueue this closure! ==
251
252 // Also, if this thread has been waiting for closures, wake it up.
253 // - If grpc_closure_list_empty() is true and the Executor is not
254 // shutdown, it means that the thread must be waiting in ThreadMain()
255 // - Note that gpr_cv_signal() won't immediately wakeup the thread. That
256 // happens after we release the mutex &ts->mu a few lines below
ncteisenc0b00c32017-12-14 11:30:38 -0800257 if (grpc_closure_list_empty(ts->elems) && !ts->shutdown) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800258 GRPC_STATS_INC_EXECUTOR_WAKEUP_INITIATED();
Craig Tiller2f767eb2017-07-20 12:06:14 -0700259 gpr_cv_signal(&ts->cv);
260 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700261
Craig Tiller2f767eb2017-07-20 12:06:14 -0700262 grpc_closure_list_append(&ts->elems, closure, error);
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700263
264 // If we already queued more than MAX_DEPTH number of closures on this
265 // thread, use this as a hint to create more threads
Craig Tiller2477cf32017-09-26 12:20:35 -0700266 ts->depth++;
267 try_new_thread = ts->depth > MAX_DEPTH &&
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700268 cur_thread_count < max_threads && !ts->shutdown;
269
270 ts->queued_long_job = !is_short;
271
Craig Tiller2f767eb2017-07-20 12:06:14 -0700272 gpr_mu_unlock(&ts->mu);
273 break;
Craig Tiller3e9f98e2017-05-12 13:17:47 -0700274 }
Craig Tiller2f767eb2017-07-20 12:06:14 -0700275
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700276 if (try_new_thread && gpr_spinlock_trylock(&adding_thread_lock)) {
277 cur_thread_count =
278 static_cast<size_t>(gpr_atm_no_barrier_load(&num_threads));
279 if (cur_thread_count < max_threads) {
280 // Increment num_threads (Safe to do a no_barrier_store instead of a
281 // cas because we always increment num_threads under the
282 // 'adding_thread_lock')
283 gpr_atm_no_barrier_store(&num_threads, cur_thread_count + 1);
284
285 thd_state[cur_thread_count].thd = grpc_core::Thread(
286 name, &GrpcExecutor::ThreadMain, &thd_state[cur_thread_count]);
287 thd_state[cur_thread_count].thd.Start();
Craig Tiller2f767eb2017-07-20 12:06:14 -0700288 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700289 gpr_spinlock_unlock(&adding_thread_lock);
Craig Tiller2f767eb2017-07-20 12:06:14 -0700290 }
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700291
Craig Tiller07d2fa72017-09-07 13:13:36 -0700292 if (retry_push) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800293 GRPC_STATS_INC_EXECUTOR_PUSH_RETRIES();
Craig Tiller07d2fa72017-09-07 13:13:36 -0700294 }
Craig Tiller2f767eb2017-07-20 12:06:14 -0700295 } while (retry_push);
David Garcia Quintas4bc34632015-10-07 16:12:35 -0700296}
Craig Tiller91031da2016-12-28 15:44:25 -0800297
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700298static GrpcExecutor g_global_executor("grpc-executor");
299
300void enqueue_long(grpc_closure* closure, grpc_error* error) {
301 g_global_executor.Enqueue(closure, error, false);
Craig Tiller7a82afd2017-07-18 09:40:40 -0700302}
303
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700304void enqueue_short(grpc_closure* closure, grpc_error* error) {
305 g_global_executor.Enqueue(closure, error, true);
Craig Tiller7a82afd2017-07-18 09:40:40 -0700306}
307
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700308// Short-Job executor scheduler
309static const grpc_closure_scheduler_vtable global_executor_vtable_short = {
310 enqueue_short, enqueue_short, "executor-short"};
311static grpc_closure_scheduler global_scheduler_short = {
312 &global_executor_vtable_short};
Craig Tiller7a82afd2017-07-18 09:40:40 -0700313
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700314// Long-job executor scheduler
315static const grpc_closure_scheduler_vtable global_executor_vtable_long = {
316 enqueue_long, enqueue_long, "executor-long"};
317static grpc_closure_scheduler global_scheduler_long = {
318 &global_executor_vtable_long};
319
320void grpc_executor_init() { g_global_executor.Init(); }
321
322void grpc_executor_shutdown() { g_global_executor.Shutdown(); }
323
324bool grpc_executor_is_threaded() { return g_global_executor.IsThreaded(); }
325
326void grpc_executor_set_threading(bool enable) {
327 g_global_executor.SetThreading(enable);
328}
Craig Tiller7a82afd2017-07-18 09:40:40 -0700329
Craig Tillerbaa14a92017-11-03 09:09:36 -0700330grpc_closure_scheduler* grpc_executor_scheduler(
Craig Tiller7a82afd2017-07-18 09:40:40 -0700331 grpc_executor_job_length length) {
Sree Kuchibhotla7e9d5252018-07-09 14:53:54 -0700332 return length == GRPC_EXECUTOR_SHORT ? &global_scheduler_short
333 : &global_scheduler_long;
Craig Tiller7a82afd2017-07-18 09:40:40 -0700334}