blob: 28b8f37ce6ad382e545bc7813291f0bae6cd6a9a [file] [log] [blame]
Josh Gao95068bb2019-07-08 15:23:17 -07001/*
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 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080016
Yabin Cuiaed3c612015-09-22 15:52:57 -070017#define TRACE_TAG FDEVENT
JP Abgrall408fa572011-03-16 15:57:42 -070018
Dan Albert33134262015-03-19 15:21:08 -070019#include "sysdeps.h"
Dan Albert33134262015-03-19 15:21:08 -070020
Josh Gaoded557f2018-06-18 14:55:27 -070021#include <inttypes.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080022
Josh Gao2c95bf72019-07-08 18:05:16 -070023#include <android-base/logging.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080024#include <android-base/stringprintf.h>
Josh Gao2c95bf72019-07-08 18:05:16 -070025#include <android-base/threads.h>
Yabin Cuia1080162015-09-04 16:19:56 -070026
Josh Gao33944a22019-07-08 18:16:19 -070027#include "adb_utils.h"
Josh Gao95068bb2019-07-08 15:23:17 -070028#include "fdevent.h"
29#include "fdevent_poll.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030
Josh Gao95068bb2019-07-08 15:23:17 -070031std::string dump_fde(const fdevent* fde) {
Yabin Cuia1080162015-09-04 16:19:56 -070032 std::string state;
33 if (fde->state & FDE_ACTIVE) {
34 state += "A";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080035 }
Yabin Cuia1080162015-09-04 16:19:56 -070036 if (fde->state & FDE_PENDING) {
37 state += "P";
38 }
Yabin Cuia1080162015-09-04 16:19:56 -070039 if (fde->state & FDE_READ) {
40 state += "R";
41 }
42 if (fde->state & FDE_WRITE) {
43 state += "W";
44 }
45 if (fde->state & FDE_ERROR) {
46 state += "E";
47 }
Josh Gaoded557f2018-06-18 14:55:27 -070048 return android::base::StringPrintf("(fdevent %" PRIu64 ": fd %d %s)", fde->id, fde->fd.get(),
49 state.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050}
51
Josh Gao33944a22019-07-08 18:16:19 -070052fdevent* fdevent_context::Create(unique_fd fd, std::variant<fd_func, fd_func2> func, void* arg) {
53 CheckMainThread();
54 CHECK_GE(fd.get(), 0);
55
56 fdevent* fde = new fdevent();
57 fde->id = fdevent_id_++;
58 fde->state = FDE_ACTIVE;
59 fde->fd = std::move(fd);
60 fde->func = func;
61 fde->arg = arg;
62 if (!set_file_block_mode(fde->fd, false)) {
63 // Here is not proper to handle the error. If it fails here, some error is
64 // likely to be detected by poll(), then we can let the callback function
65 // to handle it.
66 LOG(ERROR) << "failed to set non-blocking mode for fd " << fde->fd.get();
67 }
68
69 this->Register(fde);
70 return fde;
71}
72
73unique_fd fdevent_context::Destroy(fdevent* fde) {
74 CheckMainThread();
75 if (!fde) {
76 return {};
77 }
78
79 this->Unregister(fde);
80
81 unique_fd result = std::move(fde->fd);
82 delete fde;
83 return result;
84}
85
Josh Gao35b29362019-07-08 18:17:41 -070086void fdevent_context::Add(fdevent* fde, unsigned events) {
87 Set(fde, (fde->state & FDE_EVENTMASK) | events);
88}
89
90void fdevent_context::Del(fdevent* fde, unsigned events) {
91 CHECK(!(events & FDE_TIMEOUT));
92 Set(fde, (fde->state & FDE_EVENTMASK) & ~events);
93}
94
95void fdevent_context::SetTimeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout) {
96 CheckMainThread();
97 fde->timeout = timeout;
98 fde->last_active = std::chrono::steady_clock::now();
99}
100
Josh Gao2c95bf72019-07-08 18:05:16 -0700101void fdevent_context::CheckMainThread() {
102 if (main_thread_id_) {
103 CHECK_EQ(*main_thread_id_, android::base::GetThreadId());
104 }
105}
106
Josh Gao95eef6b2019-07-08 17:37:23 -0700107void fdevent_context::Run(std::function<void()> fn) {
108 {
109 std::lock_guard<std::mutex> lock(run_queue_mutex_);
110 run_queue_.push_back(std::move(fn));
111 }
112
113 Interrupt();
114}
115
Josh Gaoebaa3482019-07-08 18:08:06 -0700116void fdevent_context::TerminateLoop() {
117 terminate_loop_ = true;
118 Interrupt();
119}
120
Josh Gao95eef6b2019-07-08 17:37:23 -0700121void fdevent_context::FlushRunQueue() {
122 // We need to be careful around reentrancy here, since a function we call can queue up another
123 // function.
124 while (true) {
125 std::function<void()> fn;
126 {
127 std::lock_guard<std::mutex> lock(this->run_queue_mutex_);
128 if (this->run_queue_.empty()) {
129 break;
130 }
131 fn = this->run_queue_.front();
132 this->run_queue_.pop_front();
133 }
134 fn();
135 }
136}
137
Josh Gao7adca932019-07-08 17:31:47 -0700138static auto& g_ambient_fdevent_context =
139 *new std::unique_ptr<fdevent_context>(new fdevent_context_poll());
Josh Gaoc2cf1212019-06-28 16:34:36 -0700140
141static fdevent_context* fdevent_get_ambient() {
Josh Gao7adca932019-07-08 17:31:47 -0700142 return g_ambient_fdevent_context.get();
Josh Gaoc2cf1212019-06-28 16:34:36 -0700143}
144
Josh Gaoc2cf1212019-06-28 16:34:36 -0700145fdevent* fdevent_create(int fd, fd_func func, void* arg) {
146 unique_fd ufd(fd);
147 return fdevent_get_ambient()->Create(std::move(ufd), func, arg);
148}
149
150fdevent* fdevent_create(int fd, fd_func2 func, void* arg) {
151 unique_fd ufd(fd);
152 return fdevent_get_ambient()->Create(std::move(ufd), func, arg);
153}
154
155unique_fd fdevent_release(fdevent* fde) {
156 return fdevent_get_ambient()->Destroy(fde);
157}
158
159void fdevent_destroy(fdevent* fde) {
160 fdevent_get_ambient()->Destroy(fde);
161}
162
163void fdevent_set(fdevent* fde, unsigned events) {
164 fdevent_get_ambient()->Set(fde, events);
165}
166
167void fdevent_add(fdevent* fde, unsigned events) {
168 fdevent_get_ambient()->Add(fde, events);
169}
170
171void fdevent_del(fdevent* fde, unsigned events) {
172 fdevent_get_ambient()->Del(fde, events);
173}
174
175void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout) {
176 fdevent_get_ambient()->SetTimeout(fde, timeout);
177}
178
179void fdevent_run_on_main_thread(std::function<void()> fn) {
180 fdevent_get_ambient()->Run(std::move(fn));
181}
182
183void fdevent_loop() {
184 fdevent_get_ambient()->Loop();
185}
186
187void check_main_thread() {
188 fdevent_get_ambient()->CheckMainThread();
189}
190
Josh Gao022d4472016-02-10 14:49:00 -0800191void fdevent_terminate_loop() {
Josh Gaoc2cf1212019-06-28 16:34:36 -0700192 fdevent_get_ambient()->TerminateLoop();
Josh Gao022d4472016-02-10 14:49:00 -0800193}
194
Yabin Cuic1b1f6f2015-09-15 16:27:09 -0700195size_t fdevent_installed_count() {
Josh Gaoc2cf1212019-06-28 16:34:36 -0700196 return fdevent_get_ambient()->InstalledCount();
Yabin Cuic1b1f6f2015-09-15 16:27:09 -0700197}
198
199void fdevent_reset() {
Josh Gao7adca932019-07-08 17:31:47 -0700200 g_ambient_fdevent_context.reset(new fdevent_context_poll());
Yabin Cuic1b1f6f2015-09-15 16:27:09 -0700201}