blob: d25bbfb5251dafd48c2f3194fdb384825cc171dd [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
2**
3** Copyright 2006, Brian Swetland <swetland@frotz.net>
4**
Elliott Hughesaa245492015-08-03 10:38:08 -07005** 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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08008**
Elliott Hughesaa245492015-08-03 10:38:08 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080010**
Elliott Hughesaa245492015-08-03 10:38:08 -070011** 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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080015** limitations under the License.
16*/
17
Dan Albert33134262015-03-19 15:21:08 -070018#define TRACE_TAG TRACE_FDEVENT
JP Abgrall408fa572011-03-16 15:57:42 -070019
Dan Albert33134262015-03-19 15:21:08 -070020#include "sysdeps.h"
21#include "fdevent.h"
22
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <fcntl.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025#include <stdarg.h>
26#include <stddef.h>
Dan Albert33134262015-03-19 15:21:08 -070027#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <sys/ioctl.h>
31#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080032
Dan Albertcc731cc2015-02-24 21:26:58 -080033#include "adb_io.h"
leozwangd3fc15f2014-07-29 12:50:02 -070034#include "adb_trace.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080035
JP Abgrall408fa572011-03-16 15:57:42 -070036/* !!! Do not enable DEBUG for the adb that will run as the server:
37** both stdout and stderr are used to communicate between the client
38** and server. Any extra output will cause failures.
39*/
40#define DEBUG 0 /* non-0 will break adb server */
41
42// This socket is used when a subproc shell service exists.
43// It wakes up the fdevent_loop() and cause the correct handling
44// of the shell's pseudo-tty master. I.e. force close it.
Alex Vallée947cb3e2015-07-17 15:30:59 -040045#if !ADB_HOST
JP Abgrall408fa572011-03-16 15:57:42 -070046int SHELL_EXIT_NOTIFY_FD = -1;
Alex Vallée947cb3e2015-07-17 15:30:59 -040047#endif // !ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048
49static void fatal(const char *fn, const char *fmt, ...)
50{
51 va_list ap;
52 va_start(ap, fmt);
53 fprintf(stderr, "%s:", fn);
54 vfprintf(stderr, fmt, ap);
55 va_end(ap);
56 abort();
57}
58
59#define FATAL(x...) fatal(__FUNCTION__, x)
60
61#if DEBUG
62static void dump_fde(fdevent *fde, const char *info)
63{
JP Abgrall408fa572011-03-16 15:57:42 -070064 adb_mutex_lock(&D_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080065 fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
66 fde->state & FDE_READ ? 'R' : ' ',
67 fde->state & FDE_WRITE ? 'W' : ' ',
68 fde->state & FDE_ERROR ? 'E' : ' ',
69 info);
JP Abgrall408fa572011-03-16 15:57:42 -070070 adb_mutex_unlock(&D_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071}
72#else
73#define dump_fde(fde, info) do { } while(0)
74#endif
75
76#define FDE_EVENTMASK 0x00ff
77#define FDE_STATEMASK 0xff00
78
79#define FDE_ACTIVE 0x0100
80#define FDE_PENDING 0x0200
81#define FDE_CREATED 0x0400
82
83static void fdevent_plist_enqueue(fdevent *node);
84static void fdevent_plist_remove(fdevent *node);
85static fdevent *fdevent_plist_dequeue(void);
86
87static fdevent list_pending = {
88 .next = &list_pending,
89 .prev = &list_pending,
Dan Albert630b9af2014-11-24 23:34:35 -080090 .fd = -1,
91 .force_eof = 0,
92 .state = 0,
93 .events = 0,
94 .func = nullptr,
95 .arg = nullptr,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080096};
97
98static fdevent **fd_table = 0;
99static int fd_table_max = 0;
100
Dan Albert45741ae2014-09-25 15:10:34 -0700101#ifdef CRAPTASTIC
102//HAVE_EPOLL
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800103
104#include <sys/epoll.h>
105
106static int epoll_fd = -1;
107
108static void fdevent_init()
109{
Dan Albert45741ae2014-09-25 15:10:34 -0700110 /* XXX: what's a good size for the passed in hint? */
111 epoll_fd = epoll_create(256);
112
113 if(epoll_fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800114 perror("epoll_create() failed");
115 exit(1);
116 }
Dan Albert45741ae2014-09-25 15:10:34 -0700117
118 /* mark for close-on-exec */
119 fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800120}
121
122static void fdevent_connect(fdevent *fde)
123{
Dan Albert45741ae2014-09-25 15:10:34 -0700124 struct epoll_event ev;
125
126 memset(&ev, 0, sizeof(ev));
127 ev.events = 0;
128 ev.data.ptr = fde;
129
130#if 0
131 if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
132 perror("epoll_ctl() failed\n");
133 exit(1);
134 }
135#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800136}
137
138static void fdevent_disconnect(fdevent *fde)
139{
140 struct epoll_event ev;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200141
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800142 memset(&ev, 0, sizeof(ev));
143 ev.events = 0;
144 ev.data.ptr = fde;
145
146 /* technically we only need to delete if we
147 ** were actively monitoring events, but let's
148 ** be aggressive and do it anyway, just in case
149 ** something's out of sync
150 */
151 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
152}
153
154static void fdevent_update(fdevent *fde, unsigned events)
155{
156 struct epoll_event ev;
157 int active;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200158
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800159 active = (fde->state & FDE_EVENTMASK) != 0;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200160
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800161 memset(&ev, 0, sizeof(ev));
162 ev.events = 0;
163 ev.data.ptr = fde;
164
165 if(events & FDE_READ) ev.events |= EPOLLIN;
166 if(events & FDE_WRITE) ev.events |= EPOLLOUT;
167 if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
168
169 fde->state = (fde->state & FDE_STATEMASK) | events;
170
171 if(active) {
172 /* we're already active. if we're changing to *no*
173 ** events being monitored, we need to delete, otherwise
174 ** we need to just modify
175 */
176 if(ev.events) {
177 if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
178 perror("epoll_ctl() failed\n");
179 exit(1);
180 }
181 } else {
182 if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
183 perror("epoll_ctl() failed\n");
184 exit(1);
185 }
186 }
187 } else {
188 /* we're not active. if we're watching events, we need
189 ** to add, otherwise we can just do nothing
190 */
191 if(ev.events) {
192 if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
193 perror("epoll_ctl() failed\n");
194 exit(1);
195 }
196 }
197 }
198}
199
200static void fdevent_process()
201{
202 struct epoll_event events[256];
203 fdevent *fde;
204 int i, n;
205
206 n = epoll_wait(epoll_fd, events, 256, -1);
207
Elliott Hughes8fcd8bc2015-08-25 10:59:45 -0700208 if (n < 0) {
209 if (errno == EINTR) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800210 perror("epoll_wait");
211 exit(1);
212 }
213
214 for(i = 0; i < n; i++) {
215 struct epoll_event *ev = events + i;
216 fde = ev->data.ptr;
217
218 if(ev->events & EPOLLIN) {
219 fde->events |= FDE_READ;
220 }
221 if(ev->events & EPOLLOUT) {
222 fde->events |= FDE_WRITE;
223 }
224 if(ev->events & (EPOLLERR | EPOLLHUP)) {
225 fde->events |= FDE_ERROR;
226 }
227 if(fde->events) {
228 if(fde->state & FDE_PENDING) continue;
229 fde->state |= FDE_PENDING;
230 fdevent_plist_enqueue(fde);
231 }
232 }
233}
234
235#else /* USE_SELECT */
236
Elliott Hughesadbf4422015-07-29 17:45:24 -0700237#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800238#include <winsock2.h>
239#else
240#include <sys/select.h>
241#endif
242
243static fd_set read_fds;
244static fd_set write_fds;
245static fd_set error_fds;
246
247static int select_n = 0;
248
249static void fdevent_init(void)
250{
251 FD_ZERO(&read_fds);
252 FD_ZERO(&write_fds);
253 FD_ZERO(&error_fds);
254}
255
256static void fdevent_connect(fdevent *fde)
257{
258 if(fde->fd >= select_n) {
259 select_n = fde->fd + 1;
260 }
261}
262
263static void fdevent_disconnect(fdevent *fde)
264{
265 int i, n;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200266
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267 FD_CLR(fde->fd, &read_fds);
268 FD_CLR(fde->fd, &write_fds);
269 FD_CLR(fde->fd, &error_fds);
270
271 for(n = 0, i = 0; i < select_n; i++) {
272 if(fd_table[i] != 0) n = i;
273 }
274 select_n = n + 1;
275}
276
277static void fdevent_update(fdevent *fde, unsigned events)
278{
279 if(events & FDE_READ) {
280 FD_SET(fde->fd, &read_fds);
281 } else {
282 FD_CLR(fde->fd, &read_fds);
283 }
284 if(events & FDE_WRITE) {
285 FD_SET(fde->fd, &write_fds);
286 } else {
287 FD_CLR(fde->fd, &write_fds);
288 }
289 if(events & FDE_ERROR) {
290 FD_SET(fde->fd, &error_fds);
291 } else {
292 FD_CLR(fde->fd, &error_fds);
293 }
294
JP Abgrall408fa572011-03-16 15:57:42 -0700295 fde->state = (fde->state & FDE_STATEMASK) | events;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800296}
297
JP Abgrall408fa572011-03-16 15:57:42 -0700298/* Looks at fd_table[] for bad FDs and sets bit in fds.
299** Returns the number of bad FDs.
300*/
301static int fdevent_fd_check(fd_set *fds)
302{
303 int i, n = 0;
304 fdevent *fde;
305
306 for(i = 0; i < select_n; i++) {
307 fde = fd_table[i];
308 if(fde == 0) continue;
309 if(fcntl(i, F_GETFL, NULL) < 0) {
310 FD_SET(i, fds);
311 n++;
312 // fde->state |= FDE_DONT_CLOSE;
313
314 }
315 }
316 return n;
317}
318
319#if !DEBUG
Dan Albert630b9af2014-11-24 23:34:35 -0800320static inline void dump_all_fds(const char* /* extra_msg */) {}
JP Abgrall408fa572011-03-16 15:57:42 -0700321#else
322static void dump_all_fds(const char *extra_msg)
323{
324int i;
325 fdevent *fde;
326 // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
327 char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
328 size_t max_chars = FD_SETSIZE * 6 + 1;
329 int printed_out;
330#define SAFE_SPRINTF(...) \
331 do { \
332 printed_out = snprintf(pb, max_chars, __VA_ARGS__); \
333 if (printed_out <= 0) { \
334 D("... snprintf failed.\n"); \
335 return; \
336 } \
337 if (max_chars < (unsigned int)printed_out) { \
338 D("... snprintf out of space.\n"); \
339 return; \
340 } \
341 pb += printed_out; \
342 max_chars -= printed_out; \
343 } while(0)
344
345 for(i = 0; i < select_n; i++) {
346 fde = fd_table[i];
347 SAFE_SPRINTF("%d", i);
348 if(fde == 0) {
349 SAFE_SPRINTF("? ");
350 continue;
351 }
352 if(fcntl(i, F_GETFL, NULL) < 0) {
353 SAFE_SPRINTF("b");
354 }
355 SAFE_SPRINTF(" ");
356 }
357 D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
358}
359#endif
360
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800361static void fdevent_process()
362{
363 int i, n;
364 fdevent *fde;
365 unsigned events;
366 fd_set rfd, wfd, efd;
367
368 memcpy(&rfd, &read_fds, sizeof(fd_set));
369 memcpy(&wfd, &write_fds, sizeof(fd_set));
370 memcpy(&efd, &error_fds, sizeof(fd_set));
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200371
JP Abgrall408fa572011-03-16 15:57:42 -0700372 dump_all_fds("pre select()");
373
374 n = select(select_n, &rfd, &wfd, &efd, NULL);
375 int saved_errno = errno;
376 D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
377
378 dump_all_fds("post select()");
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200379
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800380 if(n < 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700381 switch(saved_errno) {
382 case EINTR: return;
383 case EBADF:
384 // Can't trust the FD sets after an error.
385 FD_ZERO(&wfd);
386 FD_ZERO(&efd);
387 FD_ZERO(&rfd);
388 break;
389 default:
390 D("Unexpected select() error=%d\n", saved_errno);
391 return;
392 }
393 }
394 if(n <= 0) {
395 // We fake a read, as the rest of the code assumes
396 // that errors will be detected at that point.
397 n = fdevent_fd_check(&rfd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800398 }
399
400 for(i = 0; (i < select_n) && (n > 0); i++) {
401 events = 0;
JP Abgrall408fa572011-03-16 15:57:42 -0700402 if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
403 if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
404 if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800405
406 if(events) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800407 fde = fd_table[i];
JP Abgrall408fa572011-03-16 15:57:42 -0700408 if(fde == 0)
409 FATAL("missing fde for fd %d\n", i);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410
411 fde->events |= events;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200412
JP Abgrall408fa572011-03-16 15:57:42 -0700413 D("got events fde->fd=%d events=%04x, state=%04x\n",
414 fde->fd, fde->events, fde->state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800415 if(fde->state & FDE_PENDING) continue;
416 fde->state |= FDE_PENDING;
417 fdevent_plist_enqueue(fde);
418 }
419 }
420}
421
422#endif
423
424static void fdevent_register(fdevent *fde)
425{
426 if(fde->fd < 0) {
427 FATAL("bogus negative fd (%d)\n", fde->fd);
428 }
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200429
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800430 if(fde->fd >= fd_table_max) {
431 int oldmax = fd_table_max;
432 if(fde->fd > 32000) {
433 FATAL("bogus huuuuge fd (%d)\n", fde->fd);
434 }
435 if(fd_table_max == 0) {
436 fdevent_init();
437 fd_table_max = 256;
438 }
439 while(fd_table_max <= fde->fd) {
440 fd_table_max *= 2;
441 }
Dan Albert630b9af2014-11-24 23:34:35 -0800442 fd_table = reinterpret_cast<fdevent**>(
443 realloc(fd_table, sizeof(fdevent*) * fd_table_max));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800444 if(fd_table == 0) {
445 FATAL("could not expand fd_table to %d entries\n", fd_table_max);
446 }
447 memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
448 }
449
450 fd_table[fde->fd] = fde;
451}
452
453static void fdevent_unregister(fdevent *fde)
454{
455 if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
456 FATAL("fd out of range (%d)\n", fde->fd);
457 }
458
459 if(fd_table[fde->fd] != fde) {
JP Abgrall408fa572011-03-16 15:57:42 -0700460 FATAL("fd_table out of sync [%d]\n", fde->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800461 }
462
463 fd_table[fde->fd] = 0;
464
465 if(!(fde->state & FDE_DONT_CLOSE)) {
466 dump_fde(fde, "close");
JP Abgrall408fa572011-03-16 15:57:42 -0700467 adb_close(fde->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800468 }
469}
470
471static void fdevent_plist_enqueue(fdevent *node)
472{
473 fdevent *list = &list_pending;
474
475 node->next = list;
476 node->prev = list->prev;
477 node->prev->next = node;
478 list->prev = node;
479}
480
481static void fdevent_plist_remove(fdevent *node)
482{
483 node->prev->next = node->next;
484 node->next->prev = node->prev;
485 node->next = 0;
486 node->prev = 0;
487}
488
489static fdevent *fdevent_plist_dequeue(void)
490{
491 fdevent *list = &list_pending;
492 fdevent *node = list->next;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200493
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800494 if(node == list) return 0;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200495
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800496 list->next = node->next;
497 list->next->prev = list;
498 node->next = 0;
499 node->prev = 0;
500
501 return node;
502}
503
JP Abgrall408fa572011-03-16 15:57:42 -0700504static void fdevent_call_fdfunc(fdevent* fde)
505{
506 unsigned events = fde->events;
507 fde->events = 0;
508 if(!(fde->state & FDE_PENDING)) return;
509 fde->state &= (~FDE_PENDING);
510 dump_fde(fde, "callback");
511 fde->func(fde->fd, events, fde->arg);
512}
513
Alex Vallée947cb3e2015-07-17 15:30:59 -0400514#if !ADB_HOST
Dan Albert630b9af2014-11-24 23:34:35 -0800515static void fdevent_subproc_event_func(int fd, unsigned ev,
516 void* /* userdata */)
JP Abgrall408fa572011-03-16 15:57:42 -0700517{
518
519 D("subproc handling on fd=%d ev=%04x\n", fd, ev);
520
521 // Hook oneself back into the fde's suitable for select() on read.
522 if((fd < 0) || (fd >= fd_table_max)) {
523 FATAL("fd %d out of range for fd_table \n", fd);
524 }
525 fdevent *fde = fd_table[fd];
526 fdevent_add(fde, FDE_READ);
527
528 if(ev & FDE_READ){
529 int subproc_fd;
530
Dan Albertcc731cc2015-02-24 21:26:58 -0800531 if(!ReadFdExactly(fd, &subproc_fd, sizeof(subproc_fd))) {
JP Abgrall408fa572011-03-16 15:57:42 -0700532 FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
533 }
534 if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
535 D("subproc_fd %d out of range 0, fd_table_max=%d\n",
536 subproc_fd, fd_table_max);
537 return;
538 }
539 fdevent *subproc_fde = fd_table[subproc_fd];
540 if(!subproc_fde) {
541 D("subproc_fd %d cleared from fd_table\n", subproc_fd);
542 return;
543 }
544 if(subproc_fde->fd != subproc_fd) {
545 // Already reallocated?
546 D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
547 return;
548 }
549
550 subproc_fde->force_eof = 1;
551
552 int rcount = 0;
JP Abgrallb40367e2011-03-29 12:36:22 -0700553 ioctl(subproc_fd, FIONREAD, &rcount);
JP Abgrall408fa572011-03-16 15:57:42 -0700554 D("subproc with fd=%d has rcount=%d err=%d\n",
555 subproc_fd, rcount, errno);
556
557 if(rcount) {
558 // If there is data left, it will show up in the select().
559 // This works because there is no other thread reading that
560 // data when in this fd_func().
561 return;
562 }
563
564 D("subproc_fde.state=%04x\n", subproc_fde->state);
565 subproc_fde->events |= FDE_READ;
566 if(subproc_fde->state & FDE_PENDING) {
567 return;
568 }
569 subproc_fde->state |= FDE_PENDING;
570 fdevent_call_fdfunc(subproc_fde);
571 }
572}
573
Alex Vallée947cb3e2015-07-17 15:30:59 -0400574void fdevent_subproc_setup()
575{
576 int s[2];
577
578 if(adb_socketpair(s)) {
579 FATAL("cannot create shell-exit socket-pair\n");
580 }
Spencer Low8d8126a2015-07-21 02:06:26 -0700581 D("socketpair: (%d,%d)\n", s[0], s[1]);
Alex Vallée947cb3e2015-07-17 15:30:59 -0400582
583 SHELL_EXIT_NOTIFY_FD = s[0];
584 fdevent *fde;
585 fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
586 if(!fde)
587 FATAL("cannot create fdevent for shell-exit handler\n");
588 fdevent_add(fde, FDE_READ);
589}
590#endif // !ADB_HOST
591
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800592fdevent *fdevent_create(int fd, fd_func func, void *arg)
593{
594 fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
595 if(fde == 0) return 0;
596 fdevent_install(fde, fd, func, arg);
597 fde->state |= FDE_CREATED;
598 return fde;
599}
600
601void fdevent_destroy(fdevent *fde)
602{
603 if(fde == 0) return;
604 if(!(fde->state & FDE_CREATED)) {
605 FATAL("fde %p not created by fdevent_create()\n", fde);
606 }
607 fdevent_remove(fde);
SungHyun Kwonabb80e02015-03-03 13:56:42 +0900608 free(fde);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800609}
610
JP Abgrall408fa572011-03-16 15:57:42 -0700611void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800612{
613 memset(fde, 0, sizeof(fdevent));
614 fde->state = FDE_ACTIVE;
615 fde->fd = fd;
JP Abgrall408fa572011-03-16 15:57:42 -0700616 fde->force_eof = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800617 fde->func = func;
618 fde->arg = arg;
619
Elliott Hughesadbf4422015-07-29 17:45:24 -0700620#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800621 fcntl(fd, F_SETFL, O_NONBLOCK);
622#endif
623 fdevent_register(fde);
624 dump_fde(fde, "connect");
625 fdevent_connect(fde);
626 fde->state |= FDE_ACTIVE;
627}
628
629void fdevent_remove(fdevent *fde)
630{
631 if(fde->state & FDE_PENDING) {
632 fdevent_plist_remove(fde);
633 }
634
635 if(fde->state & FDE_ACTIVE) {
636 fdevent_disconnect(fde);
JP Abgrall408fa572011-03-16 15:57:42 -0700637 dump_fde(fde, "disconnect");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800638 fdevent_unregister(fde);
639 }
640
641 fde->state = 0;
642 fde->events = 0;
643}
644
645
646void fdevent_set(fdevent *fde, unsigned events)
647{
648 events &= FDE_EVENTMASK;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200649
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800650 if((fde->state & FDE_EVENTMASK) == events) return;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200651
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800652 if(fde->state & FDE_ACTIVE) {
653 fdevent_update(fde, events);
654 dump_fde(fde, "update");
655 }
656
657 fde->state = (fde->state & FDE_STATEMASK) | events;
658
659 if(fde->state & FDE_PENDING) {
660 /* if we're pending, make sure
661 ** we don't signal an event that
662 ** is no longer wanted.
663 */
664 fde->events &= (~events);
665 if(fde->events == 0) {
666 fdevent_plist_remove(fde);
667 fde->state &= (~FDE_PENDING);
668 }
669 }
670}
671
672void fdevent_add(fdevent *fde, unsigned events)
673{
674 fdevent_set(
675 fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
676}
677
678void fdevent_del(fdevent *fde, unsigned events)
679{
680 fdevent_set(
681 fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
682}
683
684void fdevent_loop()
685{
686 fdevent *fde;
Alex Vallée947cb3e2015-07-17 15:30:59 -0400687#if !ADB_HOST
JP Abgrall408fa572011-03-16 15:57:42 -0700688 fdevent_subproc_setup();
Alex Vallée947cb3e2015-07-17 15:30:59 -0400689#endif // !ADB_HOST
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200690
Elliott Hughesaa245492015-08-03 10:38:08 -0700691 while (true) {
JP Abgrall408fa572011-03-16 15:57:42 -0700692 D("--- ---- waiting for events\n");
693
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800694 fdevent_process();
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200695
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800696 while((fde = fdevent_plist_dequeue())) {
JP Abgrall408fa572011-03-16 15:57:42 -0700697 fdevent_call_fdfunc(fde);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800698 }
699 }
700}