1 /* 2 * Copyright 2006, Brian Swetland <swetland@frotz.net> 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define TRACE_TAG FDEVENT 18 19 #include "sysdeps.h" 20 21 #include <inttypes.h> 22 23 #include <android-base/logging.h> 24 #include <android-base/stringprintf.h> 25 #include <android-base/threads.h> 26 27 #include "adb_utils.h" 28 #include "fdevent.h" 29 #include "fdevent_epoll.h" 30 31 #if !defined(__linux__) 32 #include "fdevent_poll.h" 33 #endif 34 35 using namespace std::chrono_literals; 36 using std::chrono::duration_cast; 37 38 void invoke_fde(struct fdevent* fde, unsigned events) { 39 if (auto f = std::get_if<fd_func>(&fde->func)) { 40 (*f)(fde->fd.get(), events, fde->arg); 41 } else if (auto f = std::get_if<fd_func2>(&fde->func)) { 42 (*f)(fde, events, fde->arg); 43 } else { 44 __builtin_unreachable(); 45 } 46 } 47 48 std::string dump_fde(const fdevent* fde) { 49 std::string state; 50 if (fde->state & FDE_READ) { 51 state += "R"; 52 } 53 if (fde->state & FDE_WRITE) { 54 state += "W"; 55 } 56 if (fde->state & FDE_ERROR) { 57 state += "E"; 58 } 59 return android::base::StringPrintf("(fdevent %" PRIu64 ": fd %d %s)", fde->id, fde->fd.get(), 60 state.c_str()); 61 } 62 63 fdevent* fdevent_context::Create(unique_fd fd, std::variant<fd_func, fd_func2> func, void* arg) { 64 CheckMainThread(); 65 CHECK_GE(fd.get(), 0); 66 67 int fd_num = fd.get(); 68 69 auto [it, inserted] = this->installed_fdevents_.emplace(fd_num, fdevent{}); 70 CHECK(inserted); 71 72 fdevent* fde = &it->second; 73 fde->id = fdevent_id_++; 74 fde->state = 0; 75 fde->fd = std::move(fd); 76 fde->func = func; 77 fde->arg = arg; 78 if (!set_file_block_mode(fde->fd, false)) { 79 // Here is not proper to handle the error. If it fails here, some error is 80 // likely to be detected by poll(), then we can let the callback function 81 // to handle it. 82 LOG(ERROR) << "failed to set non-blocking mode for fd " << fde->fd.get(); 83 } 84 85 this->Register(fde); 86 return fde; 87 } 88 89 unique_fd fdevent_context::Destroy(fdevent* fde) { 90 CheckMainThread(); 91 if (!fde) { 92 return {}; 93 } 94 95 this->Unregister(fde); 96 97 unique_fd fd = std::move(fde->fd); 98 99 auto erased = this->installed_fdevents_.erase(fd.get()); 100 CHECK_EQ(1UL, erased); 101 102 return fd; 103 } 104 105 void fdevent_context::Add(fdevent* fde, unsigned events) { 106 CHECK(!(events & FDE_TIMEOUT)); 107 Set(fde, fde->state | events); 108 } 109 110 void fdevent_context::Del(fdevent* fde, unsigned events) { 111 CHECK(!(events & FDE_TIMEOUT)); 112 Set(fde, fde->state & ~events); 113 } 114 115 void fdevent_context::SetTimeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout) { 116 CheckMainThread(); 117 fde->timeout = timeout; 118 fde->last_active = std::chrono::steady_clock::now(); 119 } 120 121 std::optional<std::chrono::milliseconds> fdevent_context::CalculatePollDuration() { 122 std::optional<std::chrono::milliseconds> result = std::nullopt; 123 auto now = std::chrono::steady_clock::now(); 124 CheckMainThread(); 125 126 for (const auto& [fd, fde] : this->installed_fdevents_) { 127 UNUSED(fd); 128 auto timeout_opt = fde.timeout; 129 if (timeout_opt) { 130 auto deadline = fde.last_active + *timeout_opt; 131 auto time_left = duration_cast<std::chrono::milliseconds>(deadline - now); 132 if (time_left < 0ms) { 133 time_left = 0ms; 134 } 135 136 if (!result) { 137 result = time_left; 138 } else { 139 result = std::min(*result, time_left); 140 } 141 } 142 } 143 144 return result; 145 } 146 147 void fdevent_context::HandleEvents(const std::vector<fdevent_event>& events) { 148 for (const auto& event : events) { 149 invoke_fde(event.fde, event.events); 150 } 151 FlushRunQueue(); 152 } 153 154 void fdevent_context::FlushRunQueue() { 155 // We need to be careful around reentrancy here, since a function we call can queue up another 156 // function. 157 while (true) { 158 std::function<void()> fn; 159 { 160 std::lock_guard<std::mutex> lock(this->run_queue_mutex_); 161 if (this->run_queue_.empty()) { 162 break; 163 } 164 fn = std::move(this->run_queue_.front()); 165 this->run_queue_.pop_front(); 166 } 167 fn(); 168 } 169 } 170 171 void fdevent_context::CheckMainThread() { 172 if (main_thread_id_) { 173 CHECK_EQ(*main_thread_id_, android::base::GetThreadId()); 174 } 175 } 176 177 void fdevent_context::Run(std::function<void()> fn) { 178 { 179 std::lock_guard<std::mutex> lock(run_queue_mutex_); 180 run_queue_.push_back(std::move(fn)); 181 } 182 183 Interrupt(); 184 } 185 186 void fdevent_context::TerminateLoop() { 187 terminate_loop_ = true; 188 Interrupt(); 189 } 190 191 static std::unique_ptr<fdevent_context> fdevent_create_context() { 192 #if defined(__linux__) 193 return std::make_unique<fdevent_context_epoll>(); 194 #else 195 return std::make_unique<fdevent_context_poll>(); 196 #endif 197 } 198 199 static auto& g_ambient_fdevent_context() { 200 static auto context = fdevent_create_context().release(); 201 return context; 202 } 203 204 static fdevent_context* fdevent_get_ambient() { 205 return g_ambient_fdevent_context(); 206 } 207 208 fdevent* fdevent_create(int fd, fd_func func, void* arg) { 209 unique_fd ufd(fd); 210 return fdevent_get_ambient()->Create(std::move(ufd), func, arg); 211 } 212 213 fdevent* fdevent_create(int fd, fd_func2 func, void* arg) { 214 unique_fd ufd(fd); 215 return fdevent_get_ambient()->Create(std::move(ufd), func, arg); 216 } 217 218 unique_fd fdevent_release(fdevent* fde) { 219 return fdevent_get_ambient()->Destroy(fde); 220 } 221 222 void fdevent_destroy(fdevent* fde) { 223 fdevent_get_ambient()->Destroy(fde); 224 } 225 226 void fdevent_set(fdevent* fde, unsigned events) { 227 fdevent_get_ambient()->Set(fde, events); 228 } 229 230 void fdevent_add(fdevent* fde, unsigned events) { 231 fdevent_get_ambient()->Add(fde, events); 232 } 233 234 void fdevent_del(fdevent* fde, unsigned events) { 235 fdevent_get_ambient()->Del(fde, events); 236 } 237 238 void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout) { 239 fdevent_get_ambient()->SetTimeout(fde, timeout); 240 } 241 242 void fdevent_run_on_main_thread(std::function<void()> fn) { 243 fdevent_get_ambient()->Run(std::move(fn)); 244 } 245 246 void fdevent_loop() { 247 fdevent_get_ambient()->Loop(); 248 } 249 250 void check_main_thread() { 251 fdevent_get_ambient()->CheckMainThread(); 252 } 253 254 void fdevent_terminate_loop() { 255 fdevent_get_ambient()->TerminateLoop(); 256 } 257 258 size_t fdevent_installed_count() { 259 return fdevent_get_ambient()->InstalledCount(); 260 } 261 262 void fdevent_reset() { 263 auto old = std::exchange(g_ambient_fdevent_context(), fdevent_create_context().release()); 264 delete old; 265 } 266