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 
invoke_fde(struct fdevent * fde,unsigned events)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 
dump_fde(const fdevent * fde)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 
Create(unique_fd fd,std::variant<fd_func,fd_func2> func,void * arg)63 fdevent* fdevent_context::Create(unique_fd fd, std::variant<fd_func, fd_func2> func, void* arg) {
64     CheckLooperThread();
65 
66     CHECK_GE(fd.get(), 0);
67 
68     int fd_num = fd.get();
69 
70     auto [it, inserted] = this->installed_fdevents_.emplace(fd_num, fdevent{});
71     CHECK(inserted);
72 
73     fdevent* fde = &it->second;
74     fde->id = fdevent_id_++;
75     fde->state = 0;
76     fde->fd = std::move(fd);
77     fde->func = func;
78     fde->arg = arg;
79     if (!set_file_block_mode(fde->fd, false)) {
80         // Here is not proper to handle the error. If it fails here, some error is
81         // likely to be detected by poll(), then we can let the callback function
82         // to handle it.
83         LOG(ERROR) << "failed to set non-blocking mode for fd " << fde->fd.get();
84     }
85 
86     this->fdevent_set_.insert(fde);
87     this->Register(fde);
88     return fde;
89 }
90 
Destroy(fdevent * fde)91 unique_fd fdevent_context::Destroy(fdevent* fde) {
92     CheckLooperThread();
93 
94     if (!fde) {
95         return {};
96     }
97 
98     this->Unregister(fde);
99 
100     unique_fd fd = std::move(fde->fd);
101 
102     auto erased = this->installed_fdevents_.erase(fd.get());
103     CHECK_EQ(1UL, erased);
104     erased = this->fdevent_set_.erase(fde);
105     CHECK_EQ(1UL, erased);
106 
107     return fd;
108 }
109 
Add(fdevent * fde,unsigned events)110 void fdevent_context::Add(fdevent* fde, unsigned events) {
111     CHECK(!(events & FDE_TIMEOUT));
112     Set(fde, fde->state | events);
113 }
114 
Del(fdevent * fde,unsigned events)115 void fdevent_context::Del(fdevent* fde, unsigned events) {
116     CHECK(!(events & FDE_TIMEOUT));
117     Set(fde, fde->state & ~events);
118 }
119 
SetTimeout(fdevent * fde,std::optional<std::chrono::milliseconds> timeout)120 void fdevent_context::SetTimeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout) {
121     CheckLooperThread();  // Caller thread is expected to have already
122                           // initialized the looper thread instance variable.
123     fde->timeout = timeout;
124     fde->last_active = std::chrono::steady_clock::now();
125 }
126 
CalculatePollDuration()127 std::optional<std::chrono::milliseconds> fdevent_context::CalculatePollDuration() {
128     std::optional<std::chrono::milliseconds> result = std::nullopt;
129     auto now = std::chrono::steady_clock::now();
130 
131     CheckLooperThread();
132 
133     for (const auto& [fd, fde] : this->installed_fdevents_) {
134         UNUSED(fd);
135         auto timeout_opt = fde.timeout;
136         if (timeout_opt) {
137             auto deadline = fde.last_active + *timeout_opt;
138             auto time_left = duration_cast<std::chrono::milliseconds>(deadline - now);
139             if (time_left < 0ms) {
140                 time_left = 0ms;
141             }
142 
143             if (!result) {
144                 result = time_left;
145             } else {
146                 result = std::min(*result, time_left);
147             }
148         }
149     }
150 
151     return result;
152 }
153 
HandleEvents(const std::vector<fdevent_event> & events)154 void fdevent_context::HandleEvents(const std::vector<fdevent_event>& events) {
155     for (const auto& event : events) {
156         // Verify the fde is still installed before invoking it.  It could have been unregistered
157         // and destroyed inside an earlier event handler.
158         if (this->fdevent_set_.find(event.fde) != this->fdevent_set_.end()) {
159             invoke_fde(event.fde, event.events);
160             break;
161         }
162     }
163     FlushRunQueue();
164 }
165 
FlushRunQueue()166 void fdevent_context::FlushRunQueue() {
167     // We need to be careful around reentrancy here, since a function we call can queue up another
168     // function.
169     while (true) {
170         std::function<void()> fn;
171         {
172             std::lock_guard<std::mutex> lock(this->run_queue_mutex_);
173             if (this->run_queue_.empty()) {
174                 break;
175             }
176             fn = std::move(this->run_queue_.front());
177             this->run_queue_.pop_front();
178         }
179         fn();
180     }
181 }
182 
CheckLooperThread() const183 void fdevent_context::CheckLooperThread() const {
184     if (looper_thread_id_) {
185         CHECK_EQ(*looper_thread_id_, android::base::GetThreadId());
186     }
187 }
188 
Run(std::function<void ()> fn)189 void fdevent_context::Run(std::function<void()> fn) {
190     {
191         std::lock_guard<std::mutex> lock(run_queue_mutex_);
192         run_queue_.push_back(std::move(fn));
193     }
194 
195     Interrupt();
196 }
197 
TerminateLoop()198 void fdevent_context::TerminateLoop() {
199     terminate_loop_ = true;
200     Interrupt();
201 }
202 
fdevent_create_context()203 static std::unique_ptr<fdevent_context> fdevent_create_context() {
204 #if defined(__linux__)
205     return std::make_unique<fdevent_context_epoll>();
206 #else
207     return std::make_unique<fdevent_context_poll>();
208 #endif
209 }
210 
g_ambient_fdevent_context()211 static auto& g_ambient_fdevent_context() {
212     static auto context = fdevent_create_context().release();
213     return context;
214 }
215 
fdevent_get_ambient()216 static fdevent_context* fdevent_get_ambient() {
217     return g_ambient_fdevent_context();
218 }
219 
fdevent_create(int fd,fd_func func,void * arg)220 fdevent* fdevent_create(int fd, fd_func func, void* arg) {
221     unique_fd ufd(fd);
222     return fdevent_get_ambient()->Create(std::move(ufd), func, arg);
223 }
224 
fdevent_create(int fd,fd_func2 func,void * arg)225 fdevent* fdevent_create(int fd, fd_func2 func, void* arg) {
226     unique_fd ufd(fd);
227     return fdevent_get_ambient()->Create(std::move(ufd), func, arg);
228 }
229 
fdevent_release(fdevent * fde)230 unique_fd fdevent_release(fdevent* fde) {
231     return fdevent_get_ambient()->Destroy(fde);
232 }
233 
fdevent_destroy(fdevent * fde)234 void fdevent_destroy(fdevent* fde) {
235     fdevent_get_ambient()->Destroy(fde);
236 }
237 
fdevent_set(fdevent * fde,unsigned events)238 void fdevent_set(fdevent* fde, unsigned events) {
239     fdevent_get_ambient()->Set(fde, events);
240 }
241 
fdevent_add(fdevent * fde,unsigned events)242 void fdevent_add(fdevent* fde, unsigned events) {
243     fdevent_get_ambient()->Add(fde, events);
244 }
245 
fdevent_del(fdevent * fde,unsigned events)246 void fdevent_del(fdevent* fde, unsigned events) {
247     fdevent_get_ambient()->Del(fde, events);
248 }
249 
fdevent_set_timeout(fdevent * fde,std::optional<std::chrono::milliseconds> timeout)250 void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout) {
251     fdevent_get_ambient()->SetTimeout(fde, timeout);
252 }
253 
fdevent_run_on_looper(std::function<void ()> fn)254 void fdevent_run_on_looper(std::function<void()> fn) {
255     fdevent_get_ambient()->Run(std::move(fn));
256 }
257 
fdevent_loop()258 void fdevent_loop() {
259     fdevent_get_ambient()->Loop();
260 }
261 
fdevent_check_looper()262 void fdevent_check_looper() {
263     fdevent_get_ambient()->CheckLooperThread();
264 }
265 
fdevent_terminate_loop()266 void fdevent_terminate_loop() {
267     fdevent_get_ambient()->TerminateLoop();
268 }
269 
fdevent_installed_count()270 size_t fdevent_installed_count() {
271     return fdevent_get_ambient()->InstalledCount();
272 }
273 
fdevent_reset()274 void fdevent_reset() {
275     auto old = std::exchange(g_ambient_fdevent_context(), fdevent_create_context().release());
276     delete old;
277 }
278