blob: 893fe4515c7b8419c91c7daeb22906458ecfbb14 [file] [log] [blame]
Craig Tiller8af4c332015-09-22 12:32:31 -07001/*
2 *
Craig Tillera93a25f2016-01-28 13:55:49 -08003 * Copyright 2015-2016, Google Inc.
Craig Tiller8af4c332015-09-22 12:32:31 -07004 * 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/iomgr/exec_ctx.h"
35
Craig Tiller258f8de2015-09-23 12:32:40 -070036#include <grpc/support/log.h>
Craig Tilleref1bf872016-02-28 17:37:33 -080037#include <grpc/support/sync.h>
38#include <grpc/support/thd.h>
Craig Tiller258f8de2015-09-23 12:32:40 -070039
Craig Tiller86253ca2015-10-08 13:31:02 -070040#include "src/core/profiling/timers.h"
41
Craig Tilleref1bf872016-02-28 17:37:33 -080042#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
Craig Tiller6c396862016-01-28 13:53:40 -080043bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
44 bool did_something = 0;
Craig Tiller0ba432d2015-10-09 16:57:11 -070045 GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0);
Craig Tillera82950e2015-09-22 12:33:20 -070046 while (!grpc_closure_list_empty(exec_ctx->closure_list)) {
Craig Tillerb8b1a462015-09-22 12:50:03 -070047 grpc_closure *c = exec_ctx->closure_list.head;
48 exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -070049 while (c != NULL) {
Craig Tiller6c396862016-01-28 13:53:40 -080050 bool success = (bool)(c->final_data & 1);
Craig Tiller7536af02015-12-22 13:49:30 -080051 grpc_closure *next = (grpc_closure *)(c->final_data & ~(uintptr_t)1);
Craig Tiller6c396862016-01-28 13:53:40 -080052 did_something = true;
Craig Tiller0ba432d2015-10-09 16:57:11 -070053 GPR_TIMER_BEGIN("grpc_exec_ctx_flush.cb", 0);
Craig Tillere8b5f622015-11-02 14:15:03 -080054 c->cb(exec_ctx, c->cb_arg, success);
Craig Tiller0ba432d2015-10-09 16:57:11 -070055 GPR_TIMER_END("grpc_exec_ctx_flush.cb", 0);
Craig Tillera82950e2015-09-22 12:33:20 -070056 c = next;
Craig Tiller8af4c332015-09-22 12:32:31 -070057 }
Craig Tillera82950e2015-09-22 12:33:20 -070058 }
Craig Tiller0ba432d2015-10-09 16:57:11 -070059 GPR_TIMER_END("grpc_exec_ctx_flush", 0);
Craig Tiller40864742015-09-30 08:35:31 -070060 return did_something;
Craig Tiller8af4c332015-09-22 12:32:31 -070061}
62
63void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {
64 grpc_exec_ctx_flush(exec_ctx);
65}
66
Craig Tillera82950e2015-09-22 12:33:20 -070067void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
Craig Tiller6c396862016-01-28 13:53:40 -080068 bool success,
69 grpc_workqueue *offload_target_or_null) {
70 GPR_ASSERT(offload_target_or_null == NULL);
Craig Tiller8af4c332015-09-22 12:32:31 -070071 grpc_closure_list_add(&exec_ctx->closure_list, closure, success);
72}
73
Craig Tillera82950e2015-09-22 12:33:20 -070074void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
Craig Tiller6c396862016-01-28 13:53:40 -080075 grpc_closure_list *list,
76 grpc_workqueue *offload_target_or_null) {
77 GPR_ASSERT(offload_target_or_null == NULL);
Craig Tiller8af4c332015-09-22 12:32:31 -070078 grpc_closure_list_move(list, &exec_ctx->closure_list);
79}
Craig Tilleref1bf872016-02-28 17:37:33 -080080
81void grpc_exec_ctx_global_init(void) {}
82void grpc_exec_ctx_global_shutdown(void) {}
83#else
84static gpr_mu g_mu;
85static gpr_cv g_cv;
86static int g_threads = 0;
87
88static void run_closure(void *arg) {
89 grpc_closure *closure = arg;
90 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
91 closure->cb(&exec_ctx, closure->cb_arg, (closure->final_data & 1) != 0);
92 grpc_exec_ctx_finish(&exec_ctx);
93 gpr_mu_lock(&g_mu);
94 if (--g_threads == 0) {
95 gpr_cv_signal(&g_cv);
96 }
97 gpr_mu_unlock(&g_mu);
98}
99
100static void start_closure(grpc_closure *closure) {
101 gpr_thd_id id;
102 gpr_mu_lock(&g_mu);
103 g_threads++;
104 gpr_mu_unlock(&g_mu);
105 gpr_thd_new(&id, run_closure, closure, NULL);
106}
107
Craig Tiller3af3f742016-02-28 21:53:13 -0800108bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) { return false; }
Craig Tilleref1bf872016-02-28 17:37:33 -0800109
Craig Tiller3af3f742016-02-28 21:53:13 -0800110void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {}
Craig Tilleref1bf872016-02-28 17:37:33 -0800111
112void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
113 bool success,
114 grpc_workqueue *offload_target_or_null) {
115 GPR_ASSERT(offload_target_or_null == NULL);
Craig Tiller3af3f742016-02-28 21:53:13 -0800116 if (closure == NULL) return;
Craig Tilleref1bf872016-02-28 17:37:33 -0800117 closure->final_data = success;
118 start_closure(closure);
119}
120
121void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
122 grpc_closure_list *list,
123 grpc_workqueue *offload_target_or_null) {
Craig Tiller3af3f742016-02-28 21:53:13 -0800124 GPR_ASSERT(offload_target_or_null == NULL);
125 if (list == NULL) return;
Craig Tilleref1bf872016-02-28 17:37:33 -0800126 grpc_closure *p = list->head;
127 while (p) {
128 grpc_closure *start = p;
129 p = grpc_closure_next(start);
130 start_closure(start);
131 }
132 grpc_closure_list r = GRPC_CLOSURE_LIST_INIT;
133 *list = r;
134}
135
136void grpc_exec_ctx_global_init(void) {
137 gpr_mu_init(&g_mu);
138 gpr_cv_init(&g_cv);
139}
140
141void grpc_exec_ctx_global_shutdown(void) {
142 gpr_mu_lock(&g_mu);
143 while (g_threads != 0) {
144 gpr_cv_wait(&g_cv, &g_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
145 }
146 gpr_mu_unlock(&g_mu);
147
148 gpr_mu_destroy(&g_mu);
149 gpr_cv_destroy(&g_cv);
150}
151#endif