blob: 43e600cb3c8febeafaf3eeff6a23e883f5cb24a8 [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**
JP Abgrall0e7c4272011-02-23 18:44:39 -08005** 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**
JP Abgrall0e7c4272011-02-23 18:44:39 -08009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080010**
JP Abgrall0e7c4272011-02-23 18:44:39 -080011** 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
JP Abgrall408fa572011-03-16 15:57:42 -070018#include <sys/ioctl.h>
19
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080020#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <unistd.h>
24#include <errno.h>
25
26#include <fcntl.h>
27
28#include <stdarg.h>
29#include <stddef.h>
30
leozwangd3fc15f2014-07-29 12:50:02 -070031#include "adb_trace.h"
David 'Digit' Turner414ff7d2009-05-18 17:07:46 +020032#include "fdevent.h"
JP Abgrall408fa572011-03-16 15:57:42 -070033#include "transport.h"
34#include "sysdeps.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080035
leozwangd3fc15f2014-07-29 12:50:02 -070036#define TRACE_TAG TRACE_FDEVENT
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080037
JP Abgrall408fa572011-03-16 15:57:42 -070038/* !!! Do not enable DEBUG for the adb that will run as the server:
39** both stdout and stderr are used to communicate between the client
40** and server. Any extra output will cause failures.
41*/
42#define DEBUG 0 /* non-0 will break adb server */
43
44// This socket is used when a subproc shell service exists.
45// It wakes up the fdevent_loop() and cause the correct handling
46// of the shell's pseudo-tty master. I.e. force close it.
47int SHELL_EXIT_NOTIFY_FD = -1;
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);
JP Abgrall408fa572011-03-16 15:57:42 -070086static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080087
88static fdevent list_pending = {
89 .next = &list_pending,
90 .prev = &list_pending,
91};
92
93static fdevent **fd_table = 0;
94static int fd_table_max = 0;
95
Dan Albert45741ae2014-09-25 15:10:34 -070096#ifdef CRAPTASTIC
97//HAVE_EPOLL
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080098
99#include <sys/epoll.h>
100
101static int epoll_fd = -1;
102
103static void fdevent_init()
104{
Dan Albert45741ae2014-09-25 15:10:34 -0700105 /* XXX: what's a good size for the passed in hint? */
106 epoll_fd = epoll_create(256);
107
108 if(epoll_fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109 perror("epoll_create() failed");
110 exit(1);
111 }
Dan Albert45741ae2014-09-25 15:10:34 -0700112
113 /* mark for close-on-exec */
114 fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800115}
116
117static void fdevent_connect(fdevent *fde)
118{
Dan Albert45741ae2014-09-25 15:10:34 -0700119 struct epoll_event ev;
120
121 memset(&ev, 0, sizeof(ev));
122 ev.events = 0;
123 ev.data.ptr = fde;
124
125#if 0
126 if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
127 perror("epoll_ctl() failed\n");
128 exit(1);
129 }
130#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800131}
132
133static void fdevent_disconnect(fdevent *fde)
134{
135 struct epoll_event ev;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200136
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800137 memset(&ev, 0, sizeof(ev));
138 ev.events = 0;
139 ev.data.ptr = fde;
140
141 /* technically we only need to delete if we
142 ** were actively monitoring events, but let's
143 ** be aggressive and do it anyway, just in case
144 ** something's out of sync
145 */
146 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
147}
148
149static void fdevent_update(fdevent *fde, unsigned events)
150{
151 struct epoll_event ev;
152 int active;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200153
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800154 active = (fde->state & FDE_EVENTMASK) != 0;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200155
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800156 memset(&ev, 0, sizeof(ev));
157 ev.events = 0;
158 ev.data.ptr = fde;
159
160 if(events & FDE_READ) ev.events |= EPOLLIN;
161 if(events & FDE_WRITE) ev.events |= EPOLLOUT;
162 if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
163
164 fde->state = (fde->state & FDE_STATEMASK) | events;
165
166 if(active) {
167 /* we're already active. if we're changing to *no*
168 ** events being monitored, we need to delete, otherwise
169 ** we need to just modify
170 */
171 if(ev.events) {
172 if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
173 perror("epoll_ctl() failed\n");
174 exit(1);
175 }
176 } else {
177 if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
178 perror("epoll_ctl() failed\n");
179 exit(1);
180 }
181 }
182 } else {
183 /* we're not active. if we're watching events, we need
184 ** to add, otherwise we can just do nothing
185 */
186 if(ev.events) {
187 if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
188 perror("epoll_ctl() failed\n");
189 exit(1);
190 }
191 }
192 }
193}
194
195static void fdevent_process()
196{
197 struct epoll_event events[256];
198 fdevent *fde;
199 int i, n;
200
201 n = epoll_wait(epoll_fd, events, 256, -1);
202
203 if(n < 0) {
204 if(errno == EINTR) return;
205 perror("epoll_wait");
206 exit(1);
207 }
208
209 for(i = 0; i < n; i++) {
210 struct epoll_event *ev = events + i;
211 fde = ev->data.ptr;
212
213 if(ev->events & EPOLLIN) {
214 fde->events |= FDE_READ;
215 }
216 if(ev->events & EPOLLOUT) {
217 fde->events |= FDE_WRITE;
218 }
219 if(ev->events & (EPOLLERR | EPOLLHUP)) {
220 fde->events |= FDE_ERROR;
221 }
222 if(fde->events) {
223 if(fde->state & FDE_PENDING) continue;
224 fde->state |= FDE_PENDING;
225 fdevent_plist_enqueue(fde);
226 }
227 }
228}
229
230#else /* USE_SELECT */
231
232#ifdef HAVE_WINSOCK
233#include <winsock2.h>
234#else
235#include <sys/select.h>
236#endif
237
238static fd_set read_fds;
239static fd_set write_fds;
240static fd_set error_fds;
241
242static int select_n = 0;
243
244static void fdevent_init(void)
245{
246 FD_ZERO(&read_fds);
247 FD_ZERO(&write_fds);
248 FD_ZERO(&error_fds);
249}
250
251static void fdevent_connect(fdevent *fde)
252{
253 if(fde->fd >= select_n) {
254 select_n = fde->fd + 1;
255 }
256}
257
258static void fdevent_disconnect(fdevent *fde)
259{
260 int i, n;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200261
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262 FD_CLR(fde->fd, &read_fds);
263 FD_CLR(fde->fd, &write_fds);
264 FD_CLR(fde->fd, &error_fds);
265
266 for(n = 0, i = 0; i < select_n; i++) {
267 if(fd_table[i] != 0) n = i;
268 }
269 select_n = n + 1;
270}
271
272static void fdevent_update(fdevent *fde, unsigned events)
273{
274 if(events & FDE_READ) {
275 FD_SET(fde->fd, &read_fds);
276 } else {
277 FD_CLR(fde->fd, &read_fds);
278 }
279 if(events & FDE_WRITE) {
280 FD_SET(fde->fd, &write_fds);
281 } else {
282 FD_CLR(fde->fd, &write_fds);
283 }
284 if(events & FDE_ERROR) {
285 FD_SET(fde->fd, &error_fds);
286 } else {
287 FD_CLR(fde->fd, &error_fds);
288 }
289
JP Abgrall408fa572011-03-16 15:57:42 -0700290 fde->state = (fde->state & FDE_STATEMASK) | events;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800291}
292
JP Abgrall408fa572011-03-16 15:57:42 -0700293/* Looks at fd_table[] for bad FDs and sets bit in fds.
294** Returns the number of bad FDs.
295*/
296static int fdevent_fd_check(fd_set *fds)
297{
298 int i, n = 0;
299 fdevent *fde;
300
301 for(i = 0; i < select_n; i++) {
302 fde = fd_table[i];
303 if(fde == 0) continue;
304 if(fcntl(i, F_GETFL, NULL) < 0) {
305 FD_SET(i, fds);
306 n++;
307 // fde->state |= FDE_DONT_CLOSE;
308
309 }
310 }
311 return n;
312}
313
314#if !DEBUG
315static inline void dump_all_fds(const char *extra_msg) {}
316#else
317static void dump_all_fds(const char *extra_msg)
318{
319int i;
320 fdevent *fde;
321 // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
322 char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
323 size_t max_chars = FD_SETSIZE * 6 + 1;
324 int printed_out;
325#define SAFE_SPRINTF(...) \
326 do { \
327 printed_out = snprintf(pb, max_chars, __VA_ARGS__); \
328 if (printed_out <= 0) { \
329 D("... snprintf failed.\n"); \
330 return; \
331 } \
332 if (max_chars < (unsigned int)printed_out) { \
333 D("... snprintf out of space.\n"); \
334 return; \
335 } \
336 pb += printed_out; \
337 max_chars -= printed_out; \
338 } while(0)
339
340 for(i = 0; i < select_n; i++) {
341 fde = fd_table[i];
342 SAFE_SPRINTF("%d", i);
343 if(fde == 0) {
344 SAFE_SPRINTF("? ");
345 continue;
346 }
347 if(fcntl(i, F_GETFL, NULL) < 0) {
348 SAFE_SPRINTF("b");
349 }
350 SAFE_SPRINTF(" ");
351 }
352 D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
353}
354#endif
355
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800356static void fdevent_process()
357{
358 int i, n;
359 fdevent *fde;
360 unsigned events;
361 fd_set rfd, wfd, efd;
362
363 memcpy(&rfd, &read_fds, sizeof(fd_set));
364 memcpy(&wfd, &write_fds, sizeof(fd_set));
365 memcpy(&efd, &error_fds, sizeof(fd_set));
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200366
JP Abgrall408fa572011-03-16 15:57:42 -0700367 dump_all_fds("pre select()");
368
369 n = select(select_n, &rfd, &wfd, &efd, NULL);
370 int saved_errno = errno;
371 D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
372
373 dump_all_fds("post select()");
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200374
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800375 if(n < 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700376 switch(saved_errno) {
377 case EINTR: return;
378 case EBADF:
379 // Can't trust the FD sets after an error.
380 FD_ZERO(&wfd);
381 FD_ZERO(&efd);
382 FD_ZERO(&rfd);
383 break;
384 default:
385 D("Unexpected select() error=%d\n", saved_errno);
386 return;
387 }
388 }
389 if(n <= 0) {
390 // We fake a read, as the rest of the code assumes
391 // that errors will be detected at that point.
392 n = fdevent_fd_check(&rfd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800393 }
394
395 for(i = 0; (i < select_n) && (n > 0); i++) {
396 events = 0;
JP Abgrall408fa572011-03-16 15:57:42 -0700397 if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
398 if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
399 if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800400
401 if(events) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800402 fde = fd_table[i];
JP Abgrall408fa572011-03-16 15:57:42 -0700403 if(fde == 0)
404 FATAL("missing fde for fd %d\n", i);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800405
406 fde->events |= events;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200407
JP Abgrall408fa572011-03-16 15:57:42 -0700408 D("got events fde->fd=%d events=%04x, state=%04x\n",
409 fde->fd, fde->events, fde->state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 if(fde->state & FDE_PENDING) continue;
411 fde->state |= FDE_PENDING;
412 fdevent_plist_enqueue(fde);
413 }
414 }
415}
416
417#endif
418
419static void fdevent_register(fdevent *fde)
420{
421 if(fde->fd < 0) {
422 FATAL("bogus negative fd (%d)\n", fde->fd);
423 }
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200424
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425 if(fde->fd >= fd_table_max) {
426 int oldmax = fd_table_max;
427 if(fde->fd > 32000) {
428 FATAL("bogus huuuuge fd (%d)\n", fde->fd);
429 }
430 if(fd_table_max == 0) {
431 fdevent_init();
432 fd_table_max = 256;
433 }
434 while(fd_table_max <= fde->fd) {
435 fd_table_max *= 2;
436 }
437 fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
438 if(fd_table == 0) {
439 FATAL("could not expand fd_table to %d entries\n", fd_table_max);
440 }
441 memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
442 }
443
444 fd_table[fde->fd] = fde;
445}
446
447static void fdevent_unregister(fdevent *fde)
448{
449 if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
450 FATAL("fd out of range (%d)\n", fde->fd);
451 }
452
453 if(fd_table[fde->fd] != fde) {
JP Abgrall408fa572011-03-16 15:57:42 -0700454 FATAL("fd_table out of sync [%d]\n", fde->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800455 }
456
457 fd_table[fde->fd] = 0;
458
459 if(!(fde->state & FDE_DONT_CLOSE)) {
460 dump_fde(fde, "close");
JP Abgrall408fa572011-03-16 15:57:42 -0700461 adb_close(fde->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800462 }
463}
464
465static void fdevent_plist_enqueue(fdevent *node)
466{
467 fdevent *list = &list_pending;
468
469 node->next = list;
470 node->prev = list->prev;
471 node->prev->next = node;
472 list->prev = node;
473}
474
475static void fdevent_plist_remove(fdevent *node)
476{
477 node->prev->next = node->next;
478 node->next->prev = node->prev;
479 node->next = 0;
480 node->prev = 0;
481}
482
483static fdevent *fdevent_plist_dequeue(void)
484{
485 fdevent *list = &list_pending;
486 fdevent *node = list->next;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200487
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800488 if(node == list) return 0;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200489
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800490 list->next = node->next;
491 list->next->prev = list;
492 node->next = 0;
493 node->prev = 0;
494
495 return node;
496}
497
JP Abgrall408fa572011-03-16 15:57:42 -0700498static void fdevent_call_fdfunc(fdevent* fde)
499{
500 unsigned events = fde->events;
501 fde->events = 0;
502 if(!(fde->state & FDE_PENDING)) return;
503 fde->state &= (~FDE_PENDING);
504 dump_fde(fde, "callback");
505 fde->func(fde->fd, events, fde->arg);
506}
507
508static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
509{
510
511 D("subproc handling on fd=%d ev=%04x\n", fd, ev);
512
513 // Hook oneself back into the fde's suitable for select() on read.
514 if((fd < 0) || (fd >= fd_table_max)) {
515 FATAL("fd %d out of range for fd_table \n", fd);
516 }
517 fdevent *fde = fd_table[fd];
518 fdevent_add(fde, FDE_READ);
519
520 if(ev & FDE_READ){
521 int subproc_fd;
522
523 if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
524 FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
525 }
526 if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
527 D("subproc_fd %d out of range 0, fd_table_max=%d\n",
528 subproc_fd, fd_table_max);
529 return;
530 }
531 fdevent *subproc_fde = fd_table[subproc_fd];
532 if(!subproc_fde) {
533 D("subproc_fd %d cleared from fd_table\n", subproc_fd);
534 return;
535 }
536 if(subproc_fde->fd != subproc_fd) {
537 // Already reallocated?
538 D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
539 return;
540 }
541
542 subproc_fde->force_eof = 1;
543
544 int rcount = 0;
JP Abgrallb40367e2011-03-29 12:36:22 -0700545 ioctl(subproc_fd, FIONREAD, &rcount);
JP Abgrall408fa572011-03-16 15:57:42 -0700546 D("subproc with fd=%d has rcount=%d err=%d\n",
547 subproc_fd, rcount, errno);
548
549 if(rcount) {
550 // If there is data left, it will show up in the select().
551 // This works because there is no other thread reading that
552 // data when in this fd_func().
553 return;
554 }
555
556 D("subproc_fde.state=%04x\n", subproc_fde->state);
557 subproc_fde->events |= FDE_READ;
558 if(subproc_fde->state & FDE_PENDING) {
559 return;
560 }
561 subproc_fde->state |= FDE_PENDING;
562 fdevent_call_fdfunc(subproc_fde);
563 }
564}
565
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800566fdevent *fdevent_create(int fd, fd_func func, void *arg)
567{
568 fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
569 if(fde == 0) return 0;
570 fdevent_install(fde, fd, func, arg);
571 fde->state |= FDE_CREATED;
572 return fde;
573}
574
575void fdevent_destroy(fdevent *fde)
576{
577 if(fde == 0) return;
578 if(!(fde->state & FDE_CREATED)) {
579 FATAL("fde %p not created by fdevent_create()\n", fde);
580 }
581 fdevent_remove(fde);
582}
583
JP Abgrall408fa572011-03-16 15:57:42 -0700584void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800585{
586 memset(fde, 0, sizeof(fdevent));
587 fde->state = FDE_ACTIVE;
588 fde->fd = fd;
JP Abgrall408fa572011-03-16 15:57:42 -0700589 fde->force_eof = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800590 fde->func = func;
591 fde->arg = arg;
592
593#ifndef HAVE_WINSOCK
594 fcntl(fd, F_SETFL, O_NONBLOCK);
595#endif
596 fdevent_register(fde);
597 dump_fde(fde, "connect");
598 fdevent_connect(fde);
599 fde->state |= FDE_ACTIVE;
600}
601
602void fdevent_remove(fdevent *fde)
603{
604 if(fde->state & FDE_PENDING) {
605 fdevent_plist_remove(fde);
606 }
607
608 if(fde->state & FDE_ACTIVE) {
609 fdevent_disconnect(fde);
JP Abgrall408fa572011-03-16 15:57:42 -0700610 dump_fde(fde, "disconnect");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800611 fdevent_unregister(fde);
612 }
613
614 fde->state = 0;
615 fde->events = 0;
616}
617
618
619void fdevent_set(fdevent *fde, unsigned events)
620{
621 events &= FDE_EVENTMASK;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200622
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800623 if((fde->state & FDE_EVENTMASK) == events) return;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200624
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800625 if(fde->state & FDE_ACTIVE) {
626 fdevent_update(fde, events);
627 dump_fde(fde, "update");
628 }
629
630 fde->state = (fde->state & FDE_STATEMASK) | events;
631
632 if(fde->state & FDE_PENDING) {
633 /* if we're pending, make sure
634 ** we don't signal an event that
635 ** is no longer wanted.
636 */
637 fde->events &= (~events);
638 if(fde->events == 0) {
639 fdevent_plist_remove(fde);
640 fde->state &= (~FDE_PENDING);
641 }
642 }
643}
644
645void fdevent_add(fdevent *fde, unsigned events)
646{
647 fdevent_set(
648 fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
649}
650
651void fdevent_del(fdevent *fde, unsigned events)
652{
653 fdevent_set(
654 fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
655}
656
JP Abgrall408fa572011-03-16 15:57:42 -0700657void fdevent_subproc_setup()
658{
659 int s[2];
660
661 if(adb_socketpair(s)) {
662 FATAL("cannot create shell-exit socket-pair\n");
663 }
664 SHELL_EXIT_NOTIFY_FD = s[0];
665 fdevent *fde;
666 fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
667 if(!fde)
668 FATAL("cannot create fdevent for shell-exit handler\n");
669 fdevent_add(fde, FDE_READ);
670}
671
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800672void fdevent_loop()
673{
674 fdevent *fde;
JP Abgrall408fa572011-03-16 15:57:42 -0700675 fdevent_subproc_setup();
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200676
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800677 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -0700678 D("--- ---- waiting for events\n");
679
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800680 fdevent_process();
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200681
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800682 while((fde = fdevent_plist_dequeue())) {
JP Abgrall408fa572011-03-16 15:57:42 -0700683 fdevent_call_fdfunc(fde);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800684 }
685 }
686}