Craig Tiller | 298751c | 2015-09-22 09:41:05 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 3 | * Copyright 2015 gRPC authors. |
Craig Tiller | 298751c | 2015-09-22 09:41:05 -0700 | [diff] [blame] | 4 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 5 | * 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 Tiller | 298751c | 2015-09-22 09:41:05 -0700 | [diff] [blame] | 8 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
Craig Tiller | 298751c | 2015-09-22 09:41:05 -0700 | [diff] [blame] | 10 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 11 | * 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 Tiller | 298751c | 2015-09-22 09:41:05 -0700 | [diff] [blame] | 16 | * |
| 17 | */ |
| 18 | |
Craig Tiller | 9a4dddd | 2016-03-25 17:08:13 -0700 | [diff] [blame] | 19 | #ifndef GRPC_CORE_LIB_IOMGR_EXEC_CTX_H |
| 20 | #define GRPC_CORE_LIB_IOMGR_EXEC_CTX_H |
Craig Tiller | 298751c | 2015-09-22 09:41:05 -0700 | [diff] [blame] | 21 | |
Craig Tiller | dc3998e | 2017-05-12 09:55:30 -0700 | [diff] [blame] | 22 | #include <grpc/support/atm.h> |
Craig Tiller | 2808668 | 2017-07-18 14:22:19 -0700 | [diff] [blame] | 23 | #include <grpc/support/cpu.h> |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 24 | #include <grpc/support/log.h> |
| 25 | #include <grpc/support/tls.h> |
Craig Tiller | dc3998e | 2017-05-12 09:55:30 -0700 | [diff] [blame] | 26 | |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 27 | #include "src/core/lib/iomgr/closure.h" |
Craig Tiller | 298751c | 2015-09-22 09:41:05 -0700 | [diff] [blame] | 28 | |
Craig Tiller | dc3998e | 2017-05-12 09:55:30 -0700 | [diff] [blame] | 29 | typedef gpr_atm grpc_millis; |
| 30 | |
| 31 | #define GRPC_MILLIS_INF_FUTURE GPR_ATM_MAX |
Craig Tiller | 18c77cc | 2017-09-19 15:22:04 -0700 | [diff] [blame] | 32 | #define GRPC_MILLIS_INF_PAST GPR_ATM_MIN |
Craig Tiller | ef1bf87 | 2016-02-28 17:37:33 -0800 | [diff] [blame] | 33 | |
| 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 Tiller | ef1bf87 | 2016-02-28 17:37:33 -0800 | [diff] [blame] | 36 | typedef struct grpc_workqueue grpc_workqueue; |
Craig Tiller | e0221ff | 2016-07-11 15:56:08 -0700 | [diff] [blame] | 37 | typedef struct grpc_combiner grpc_combiner; |
Craig Tiller | ef1bf87 | 2016-02-28 17:37:33 -0800 | [diff] [blame] | 38 | |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 39 | /* 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 Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 46 | extern grpc_closure_scheduler* grpc_schedule_on_exec_ctx; |
| 47 | |
| 48 | gpr_timespec grpc_millis_to_timespec(grpc_millis millis, gpr_clock_type clock); |
| 49 | grpc_millis grpc_timespec_to_millis_round_down(gpr_timespec timespec); |
| 50 | grpc_millis grpc_timespec_to_millis_round_up(gpr_timespec timespec); |
| 51 | |
| 52 | namespace grpc_core { |
Craig Tiller | 8b52f85 | 2015-09-22 16:38:57 -0700 | [diff] [blame] | 53 | /** Execution context. |
| 54 | * A bag of data that collects information along a callstack. |
Craig Tiller | 565b18b | 2015-09-23 10:09:42 -0700 | [diff] [blame] | 55 | * Generally created at public API entry points, and passed down as |
Craig Tiller | 8b52f85 | 2015-09-22 16:38:57 -0700 | [diff] [blame] | 56 | * 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 Tiller | 56aa023 | 2016-05-11 12:37:04 -0700 | [diff] [blame] | 62 | * - 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 Tiller | 8b52f85 | 2015-09-22 16:38:57 -0700 | [diff] [blame] | 65 | * |
| 66 | * CONVENTIONS: |
Mark D. Roth | 3cfc5a7 | 2016-07-27 07:48:39 -0700 | [diff] [blame] | 67 | * - 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 Tiller | 8b52f85 | 2015-09-22 16:38:57 -0700 | [diff] [blame] | 72 | */ |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 73 | class ExecCtx { |
| 74 | public: |
| 75 | /** Default Constructor */ |
Yash Tibrewal | 81fc8c9 | 2017-11-28 13:23:36 -0800 | [diff] [blame] | 76 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 77 | ExecCtx() : flags_(GRPC_EXEC_CTX_FLAG_IS_FINISHED) { Set(this); } |
Yash Tibrewal | ad4d2dd | 2017-12-06 09:05:05 -0800 | [diff] [blame] | 78 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 79 | /** Parameterised Constructor */ |
| 80 | ExecCtx(uintptr_t fl) : flags_(fl) { Set(this); } |
| 81 | |
| 82 | /** Destructor */ |
Yash Tibrewal | caaf416 | 2017-12-07 21:09:11 -0800 | [diff] [blame] | 83 | virtual ~ExecCtx() { |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 84 | flags_ |= GRPC_EXEC_CTX_FLAG_IS_FINISHED; |
| 85 | Flush(); |
| 86 | Set(last_exec_ctx_); |
Yash Tibrewal | ad4d2dd | 2017-12-06 09:05:05 -0800 | [diff] [blame] | 87 | } |
| 88 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 89 | /** Disallow copy and assignment operators */ |
| 90 | ExecCtx(const ExecCtx&) = delete; |
| 91 | ExecCtx& operator=(const ExecCtx&) = delete; |
Yash Tibrewal | ad4d2dd | 2017-12-06 09:05:05 -0800 | [diff] [blame] | 92 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 93 | /** Return starting_cpu */ |
| 94 | unsigned starting_cpu() const { return starting_cpu_; } |
Yash Tibrewal | ad4d2dd | 2017-12-06 09:05:05 -0800 | [diff] [blame] | 95 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 96 | 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 Tibrewal | ad4d2dd | 2017-12-06 09:05:05 -0800 | [diff] [blame] | 102 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 103 | /** Only to be used by grpc-combiner code */ |
| 104 | CombinerData* combiner_data() { return &combiner_data_; } |
Yash Tibrewal | ad4d2dd | 2017-12-06 09:05:05 -0800 | [diff] [blame] | 105 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 106 | /** Return pointer to grpc_closure_list */ |
| 107 | grpc_closure_list* closure_list() { return &closure_list_; } |
Yash Tibrewal | ad4d2dd | 2017-12-06 09:05:05 -0800 | [diff] [blame] | 108 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 109 | /** Return flags */ |
| 110 | uintptr_t flags() { return flags_; } |
Yash Tibrewal | ad4d2dd | 2017-12-06 09:05:05 -0800 | [diff] [blame] | 111 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 112 | /** Checks if there is work to be done */ |
| 113 | bool HasWork() { |
ncteisen | 5219f3f | 2018-01-03 21:26:23 -0800 | [diff] [blame] | 114 | return combiner_data_.active_combiner != nullptr || |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 115 | !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 |
| 124 | possible: useful for deciding whether to do something more or not depending |
| 125 | on 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 Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 161 | /** 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 Tibrewal | 9e5dc24 | 2017-12-08 00:07:31 -0800 | [diff] [blame] | 176 | /** Disallow delete on ExecCtx */ |
| 177 | static void operator delete(void* p) { abort(); } |
| 178 | |
Yash Tibrewal | 8cf1470 | 2017-12-06 09:47:54 -0800 | [diff] [blame] | 179 | 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 Tiller | 8af4c33 | 2015-09-22 12:32:31 -0700 | [diff] [blame] | 197 | |
Craig Tiller | 9a4dddd | 2016-03-25 17:08:13 -0700 | [diff] [blame] | 198 | #endif /* GRPC_CORE_LIB_IOMGR_EXEC_CTX_H */ |