blob: 2e71482fb705974cfcfca8672b2351f81a02b9c4 [file] [log] [blame]
Craig Tiller298751c2015-09-22 09:41:05 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
Craig Tiller298751c2015-09-22 09:41:05 -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
Craig Tiller298751c2015-09-22 09:41:05 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Craig Tiller298751c2015-09-22 09:41:05 -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.
Craig Tiller298751c2015-09-22 09:41:05 -070016 *
17 */
18
Craig Tiller9a4dddd2016-03-25 17:08:13 -070019#ifndef GRPC_CORE_LIB_IOMGR_EXEC_CTX_H
20#define GRPC_CORE_LIB_IOMGR_EXEC_CTX_H
Craig Tiller298751c2015-09-22 09:41:05 -070021
Craig Tillerdc3998e2017-05-12 09:55:30 -070022#include <grpc/support/atm.h>
Craig Tiller28086682017-07-18 14:22:19 -070023#include <grpc/support/cpu.h>
Yash Tibrewal8cf14702017-12-06 09:47:54 -080024#include <grpc/support/log.h>
25#include <grpc/support/tls.h>
Craig Tillerdc3998e2017-05-12 09:55:30 -070026
Craig Tiller9533d042016-03-25 17:11:06 -070027#include "src/core/lib/iomgr/closure.h"
Craig Tiller298751c2015-09-22 09:41:05 -070028
Craig Tillerdc3998e2017-05-12 09:55:30 -070029typedef gpr_atm grpc_millis;
30
31#define GRPC_MILLIS_INF_FUTURE GPR_ATM_MAX
Craig Tiller18c77cc2017-09-19 15:22:04 -070032#define GRPC_MILLIS_INF_PAST GPR_ATM_MIN
Craig Tilleref1bf872016-02-28 17:37:33 -080033
34/** A workqueue represents a list of work to be executed asynchronously.
35 Forward declared here to avoid a circular dependency with workqueue.h. */
Craig Tilleref1bf872016-02-28 17:37:33 -080036typedef struct grpc_workqueue grpc_workqueue;
Craig Tillere0221ff2016-07-11 15:56:08 -070037typedef struct grpc_combiner grpc_combiner;
Craig Tilleref1bf872016-02-28 17:37:33 -080038
Craig Tiller7c70b6c2017-01-23 07:48:42 -080039/* This exec_ctx is ready to return: either pre-populated, or cached as soon as
40 the finish_check returns true */
41#define GRPC_EXEC_CTX_FLAG_IS_FINISHED 1
42/* The exec_ctx's thread is (potentially) owned by a call or channel: care
43 should be given to not delete said call/channel from this exec_ctx */
44#define GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP 2
45
Yash Tibrewal8cf14702017-12-06 09:47:54 -080046extern grpc_closure_scheduler* grpc_schedule_on_exec_ctx;
47
48gpr_timespec grpc_millis_to_timespec(grpc_millis millis, gpr_clock_type clock);
49grpc_millis grpc_timespec_to_millis_round_down(gpr_timespec timespec);
50grpc_millis grpc_timespec_to_millis_round_up(gpr_timespec timespec);
51
52namespace grpc_core {
Craig Tiller8b52f852015-09-22 16:38:57 -070053/** Execution context.
54 * A bag of data that collects information along a callstack.
Craig Tiller565b18b2015-09-23 10:09:42 -070055 * Generally created at public API entry points, and passed down as
Craig Tiller8b52f852015-09-22 16:38:57 -070056 * pointer to child functions that manipulate it.
57 *
58 * Specific responsibilities (this may grow in the future):
59 * - track a list of work that needs to be delayed until the top of the
60 * call stack (this provides a convenient mechanism to run callbacks
61 * without worrying about locking issues)
Craig Tiller56aa0232016-05-11 12:37:04 -070062 * - provide a decision maker (via grpc_exec_ctx_ready_to_finish) that provides
63 * signal as to whether a borrowed thread should continue to do work or
64 * should actively try to finish up and get this thread back to its owner
Craig Tiller8b52f852015-09-22 16:38:57 -070065 *
66 * CONVENTIONS:
Mark D. Roth3cfc5a72016-07-27 07:48:39 -070067 * - Instance of this must ALWAYS be constructed on the stack, never
68 * heap allocated.
69 * - Instances and pointers to them must always be called exec_ctx.
70 * - Instances are always passed as the first argument to a function that
71 * takes it, and always as a pointer (grpc_exec_ctx is never copied).
Craig Tiller8b52f852015-09-22 16:38:57 -070072 */
Yash Tibrewal8cf14702017-12-06 09:47:54 -080073class ExecCtx {
74 public:
75 /** Default Constructor */
Yash Tibrewal81fc8c92017-11-28 13:23:36 -080076
Yash Tibrewal8cf14702017-12-06 09:47:54 -080077 ExecCtx() : flags_(GRPC_EXEC_CTX_FLAG_IS_FINISHED) { Set(this); }
Yash Tibrewalad4d2dd2017-12-06 09:05:05 -080078
Yash Tibrewal8cf14702017-12-06 09:47:54 -080079 /** Parameterised Constructor */
80 ExecCtx(uintptr_t fl) : flags_(fl) { Set(this); }
81
82 /** Destructor */
Yash Tibrewalcaaf4162017-12-07 21:09:11 -080083 virtual ~ExecCtx() {
Yash Tibrewal8cf14702017-12-06 09:47:54 -080084 flags_ |= GRPC_EXEC_CTX_FLAG_IS_FINISHED;
85 Flush();
86 Set(last_exec_ctx_);
Yash Tibrewalad4d2dd2017-12-06 09:05:05 -080087 }
88
Yash Tibrewal8cf14702017-12-06 09:47:54 -080089 /** Disallow copy and assignment operators */
90 ExecCtx(const ExecCtx&) = delete;
91 ExecCtx& operator=(const ExecCtx&) = delete;
Yash Tibrewalad4d2dd2017-12-06 09:05:05 -080092
Yash Tibrewal8cf14702017-12-06 09:47:54 -080093 /** Return starting_cpu */
94 unsigned starting_cpu() const { return starting_cpu_; }
Yash Tibrewalad4d2dd2017-12-06 09:05:05 -080095
Yash Tibrewal8cf14702017-12-06 09:47:54 -080096 struct CombinerData {
97 /* currently active combiner: updated only via combiner.c */
98 grpc_combiner* active_combiner;
99 /* last active combiner in the active combiner list */
100 grpc_combiner* last_combiner;
101 };
Yash Tibrewalad4d2dd2017-12-06 09:05:05 -0800102
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800103 /** Only to be used by grpc-combiner code */
104 CombinerData* combiner_data() { return &combiner_data_; }
Yash Tibrewalad4d2dd2017-12-06 09:05:05 -0800105
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800106 /** Return pointer to grpc_closure_list */
107 grpc_closure_list* closure_list() { return &closure_list_; }
Yash Tibrewalad4d2dd2017-12-06 09:05:05 -0800108
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800109 /** Return flags */
110 uintptr_t flags() { return flags_; }
Yash Tibrewalad4d2dd2017-12-06 09:05:05 -0800111
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800112 /** Checks if there is work to be done */
113 bool HasWork() {
ncteisen5219f3f2018-01-03 21:26:23 -0800114 return combiner_data_.active_combiner != nullptr ||
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800115 !grpc_closure_list_empty(closure_list_);
116 }
117
118 /** Flush any work that has been enqueued onto this grpc_exec_ctx.
119 * Caller must guarantee that no interfering locks are held.
120 * Returns true if work was performed, false otherwise. */
121 bool Flush();
122
123 /** Returns true if we'd like to leave this execution context as soon as
124possible: useful for deciding whether to do something more or not depending
125on outside context */
126 bool IsReadyToFinish() {
127 if ((flags_ & GRPC_EXEC_CTX_FLAG_IS_FINISHED) == 0) {
128 if (CheckReadyToFinish()) {
129 flags_ |= GRPC_EXEC_CTX_FLAG_IS_FINISHED;
130 return true;
131 }
132 return false;
133 } else {
134 return true;
135 }
136 }
137
138 /** Returns the stored current time relative to start if valid,
139 * otherwise refreshes the stored time, sets it valid and returns the new
140 * value */
141 grpc_millis Now();
142
143 /** Invalidates the stored time value. A new time value will be set on calling
144 * Now() */
145 void InvalidateNow() { now_is_valid_ = false; }
146
147 /** To be used only by shutdown code in iomgr */
148 void SetNowIomgrShutdown() {
149 now_ = GRPC_MILLIS_INF_FUTURE;
150 now_is_valid_ = true;
151 }
152
153 /** To be used only for testing.
154 * Sets the now value
155 */
156 void TestOnlySetNow(grpc_millis new_val) {
157 now_ = new_val;
158 now_is_valid_ = true;
159 }
160
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800161 /** Global initialization for ExecCtx. Called by iomgr */
162 static void GlobalInit(void);
163
164 /** Global shutdown for ExecCtx. Called by iomgr */
165 static void GlobalShutdown(void) { gpr_tls_destroy(&exec_ctx_); }
166
167 /** Gets pointer to current exec_ctx */
168 static ExecCtx* Get() {
169 return reinterpret_cast<ExecCtx*>(gpr_tls_get(&exec_ctx_));
170 }
171
172 protected:
173 /** Check if ready to finish */
174 virtual bool CheckReadyToFinish() { return false; }
175
Yash Tibrewal9e5dc242017-12-08 00:07:31 -0800176 /** Disallow delete on ExecCtx */
177 static void operator delete(void* p) { abort(); }
178
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800179 private:
180 /** Set exec_ctx_ to exec_ctx */
181 void Set(ExecCtx* exec_ctx) {
182 gpr_tls_set(&exec_ctx_, reinterpret_cast<intptr_t>(exec_ctx));
183 }
184
185 grpc_closure_list closure_list_ = GRPC_CLOSURE_LIST_INIT;
186 CombinerData combiner_data_ = {nullptr, nullptr};
187 uintptr_t flags_;
188 unsigned starting_cpu_ = gpr_cpu_current_cpu();
189
190 bool now_is_valid_ = false;
191 grpc_millis now_ = 0;
192
193 GPR_TLS_CLASS_DECL(exec_ctx_);
194 ExecCtx* last_exec_ctx_ = Get();
195};
196} // namespace grpc_core
Craig Tiller8af4c332015-09-22 12:32:31 -0700197
Craig Tiller9a4dddd2016-03-25 17:08:13 -0700198#endif /* GRPC_CORE_LIB_IOMGR_EXEC_CTX_H */