1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2006, Brian Swetland <swetland@frotz.net>
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
50e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** Licensed under the Apache License, Version 2.0 (the "License");
60e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** you may not use this file except in compliance with the License.
70e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** You may obtain a copy of the License at
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
90e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall**     http://www.apache.org/licenses/LICENSE-2.0
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
110e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** Unless required by applicable law or agreed to in writing, software
120e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** distributed under the License is distributed on an "AS IS" BASIS,
130e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
140e7c4274c687446dbe30a814278d7a6b99da8c4eJP Abgrall** See the License for the specific language governing permissions and
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** limitations under the License.
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
18408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#include <sys/ioctl.h>
19408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdarg.h>
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stddef.h>
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
31d3fc15f4841a8cbfd15fa9f051f2712266b5cd78leozwang#include "adb_trace.h"
32414ff7d98ac8d7610a26206335954ad15f43f3acDavid 'Digit' Turner#include "fdevent.h"
33408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#include "transport.h"
34408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#include "sysdeps.h"
35408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
36d3fc15f4841a8cbfd15fa9f051f2712266b5cd78leozwang#define TRACE_TAG  TRACE_FDEVENT
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall/* !!! Do not enable DEBUG for the adb that will run as the server:
39408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall** both stdout and stderr are used to communicate between the client
40408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall** and server. Any extra output will cause failures.
41408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall*/
42408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define DEBUG 0   /* non-0 will break adb server */
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall// This socket is used when a subproc shell service exists.
45408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall// It wakes up the fdevent_loop() and cause the correct handling
46408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall// of the shell's pseudo-tty master. I.e. force close it.
47408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallint SHELL_EXIT_NOTIFY_FD = -1;
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fatal(const char *fn, const char *fmt, ...)
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list ap;
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(ap, fmt);
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "%s:", fn);
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    vfprintf(stderr, fmt, ap);
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_end(ap);
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    abort();
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FATAL(x...) fatal(__FUNCTION__, x)
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if DEBUG
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void dump_fde(fdevent *fde, const char *info)
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
64408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    adb_mutex_lock(&D_lock);
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state & FDE_READ ? 'R' : ' ',
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state & FDE_WRITE ? 'W' : ' ',
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state & FDE_ERROR ? 'E' : ' ',
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            info);
70408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    adb_mutex_unlock(&D_lock);
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define dump_fde(fde, info) do { } while(0)
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_EVENTMASK  0x00ff
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_STATEMASK  0xff00
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_ACTIVE     0x0100
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_PENDING    0x0200
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_CREATED    0x0400
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_enqueue(fdevent *node);
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_remove(fdevent *node);
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent *fdevent_plist_dequeue(void);
86408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent list_pending = {
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .next = &list_pending,
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .prev = &list_pending,
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent **fd_table = 0;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fd_table_max = 0;
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef CRAPTASTIC
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//HAVE_EPOLL
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/epoll.h>
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int epoll_fd = -1;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_init()
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* XXX: what's a good size for the passed in hint? */
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    epoll_fd = epoll_create(256);
107f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(epoll_fd < 0) {
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        perror("epoll_create() failed");
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(1);
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* mark for close-on-exec */
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_connect(fdevent *fde)
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event ev;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&ev, 0, sizeof(ev));
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.events = 0;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.data.ptr = fde;
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
125f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner#if 0
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        perror("epoll_ctl() failed\n");
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(1);
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_disconnect(fdevent *fde)
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event ev;
136f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&ev, 0, sizeof(ev));
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.events = 0;
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.data.ptr = fde;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* technically we only need to delete if we
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** were actively monitoring events, but let's
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** be aggressive and do it anyway, just in case
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** something's out of sync
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_update(fdevent *fde, unsigned events)
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event ev;
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int active;
153f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    active = (fde->state & FDE_EVENTMASK) != 0;
155f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&ev, 0, sizeof(ev));
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.events = 0;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.data.ptr = fde;
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_READ) ev.events |= EPOLLIN;
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_WRITE) ev.events |= EPOLLOUT;
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = (fde->state & FDE_STATEMASK) | events;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(active) {
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* we're already active. if we're changing to *no*
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** events being monitored, we need to delete, otherwise
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** we need to just modify
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev.events) {
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                perror("epoll_ctl() failed\n");
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                perror("epoll_ctl() failed\n");
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* we're not active.  if we're watching events, we need
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** to add, otherwise we can just do nothing
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev.events) {
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                perror("epoll_ctl() failed\n");
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_process()
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event events[256];
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde;
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, n;
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    n = epoll_wait(epoll_fd, events, 256, -1);
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(n < 0) {
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(errno == EINTR) return;
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        perror("epoll_wait");
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(1);
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(i = 0; i < n; i++) {
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct epoll_event *ev = events + i;
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde = ev->data.ptr;
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev->events & EPOLLIN) {
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= FDE_READ;
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev->events & EPOLLOUT) {
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= FDE_WRITE;
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev->events & (EPOLLERR | EPOLLHUP)) {
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= FDE_ERROR;
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fde->events) {
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(fde->state & FDE_PENDING) continue;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state |= FDE_PENDING;
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_plist_enqueue(fde);
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else /* USE_SELECT */
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_WINSOCK
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <winsock2.h>
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/select.h>
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set read_fds;
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set write_fds;
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set error_fds;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int select_n = 0;
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_init(void)
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_ZERO(&read_fds);
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_ZERO(&write_fds);
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_ZERO(&error_fds);
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_connect(fdevent *fde)
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->fd >= select_n) {
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        select_n = fde->fd + 1;
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_disconnect(fdevent *fde)
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, n;
261f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_CLR(fde->fd, &read_fds);
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_CLR(fde->fd, &write_fds);
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_CLR(fde->fd, &error_fds);
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(n = 0, i = 0; i < select_n; i++) {
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd_table[i] != 0) n = i;
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    select_n = n + 1;
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_update(fdevent *fde, unsigned events)
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_READ) {
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_SET(fde->fd, &read_fds);
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_CLR(fde->fd, &read_fds);
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_WRITE) {
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_SET(fde->fd, &write_fds);
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_CLR(fde->fd, &write_fds);
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_ERROR) {
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_SET(fde->fd, &error_fds);
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_CLR(fde->fd, &error_fds);
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
290408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde->state = (fde->state & FDE_STATEMASK) | events;
291408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
292408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
293408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall/* Looks at fd_table[] for bad FDs and sets bit in fds.
294408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall** Returns the number of bad FDs.
295408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall*/
296408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic int fdevent_fd_check(fd_set *fds)
297408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
298408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    int i, n = 0;
299408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent *fde;
300408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
301408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    for(i = 0; i < select_n; i++) {
302408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        fde = fd_table[i];
303408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(fde == 0) continue;
304408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(fcntl(i, F_GETFL, NULL) < 0) {
305408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            FD_SET(i, fds);
306408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            n++;
307408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            // fde->state |= FDE_DONT_CLOSE;
308408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
309408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }
310408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
311408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    return n;
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
314408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#if !DEBUG
315408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic inline void dump_all_fds(const char *extra_msg) {}
316408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#else
317408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void dump_all_fds(const char *extra_msg)
318408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
319408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallint i;
320408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent *fde;
321408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
322408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
323408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    size_t max_chars = FD_SETSIZE * 6 + 1;
324408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    int printed_out;
325408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define SAFE_SPRINTF(...)                                                    \
326408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    do {                                                                     \
327408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        printed_out = snprintf(pb, max_chars, __VA_ARGS__);                  \
328408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if (printed_out <= 0) {                                              \
329408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("... snprintf failed.\n");                                     \
330408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            return;                                                          \
331408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }                                                                    \
332408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if (max_chars < (unsigned int)printed_out) {                         \
333408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("... snprintf out of space.\n");                               \
334408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            return;                                                          \
335408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }                                                                    \
336408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        pb += printed_out;                                                   \
337408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        max_chars -= printed_out;                                            \
338408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    } while(0)
339408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
340408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    for(i = 0; i < select_n; i++) {
341408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        fde = fd_table[i];
342408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        SAFE_SPRINTF("%d", i);
343408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(fde == 0) {
344408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            SAFE_SPRINTF("? ");
345408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            continue;
346408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }
347408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(fcntl(i, F_GETFL, NULL) < 0) {
348408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            SAFE_SPRINTF("b");
349408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }
350408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        SAFE_SPRINTF(" ");
351408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
352408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
353408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
354408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#endif
355408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_process()
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, n;
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde;
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned events;
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd_set rfd, wfd, efd;
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(&rfd, &read_fds, sizeof(fd_set));
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(&wfd, &write_fds, sizeof(fd_set));
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(&efd, &error_fds, sizeof(fd_set));
366f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
367408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    dump_all_fds("pre select()");
368408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
369408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    n = select(select_n, &rfd, &wfd, &efd, NULL);
370408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    int saved_errno = errno;
371408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
372408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
373408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    dump_all_fds("post select()");
374f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(n < 0) {
376408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        switch(saved_errno) {
377408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        case EINTR: return;
378408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        case EBADF:
379408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            // Can't trust the FD sets after an error.
380408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            FD_ZERO(&wfd);
381408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            FD_ZERO(&efd);
382408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            FD_ZERO(&rfd);
383408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            break;
384408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        default:
385408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("Unexpected select() error=%d\n", saved_errno);
386408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            return;
387408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }
388408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
389408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(n <= 0) {
390408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        // We fake a read, as the rest of the code assumes
391408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        // that errors will be detected at that point.
392408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        n = fdevent_fd_check(&rfd);
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(i = 0; (i < select_n) && (n > 0); i++) {
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        events = 0;
397408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
398408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
399408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(events) {
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde = fd_table[i];
403408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            if(fde == 0)
404408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall              FATAL("missing fde for fd %d\n", i);
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= events;
407f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
408408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("got events fde->fd=%d events=%04x, state=%04x\n",
409408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall                fde->fd, fde->events, fde->state);
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(fde->state & FDE_PENDING) continue;
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state |= FDE_PENDING;
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_plist_enqueue(fde);
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_register(fdevent *fde)
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->fd < 0) {
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FATAL("bogus negative fd (%d)\n", fde->fd);
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
424f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->fd >= fd_table_max) {
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int oldmax = fd_table_max;
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fde->fd > 32000) {
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            FATAL("bogus huuuuge fd (%d)\n", fde->fd);
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd_table_max == 0) {
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_init();
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd_table_max = 256;
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while(fd_table_max <= fde->fd) {
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd_table_max *= 2;
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd_table == 0) {
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            FATAL("could not expand fd_table to %d entries\n", fd_table_max);
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd_table[fde->fd] = fde;
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_unregister(fdevent *fde)
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FATAL("fd out of range (%d)\n", fde->fd);
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd_table[fde->fd] != fde) {
454408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        FATAL("fd_table out of sync [%d]\n", fde->fd);
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd_table[fde->fd] = 0;
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!(fde->state & FDE_DONT_CLOSE)) {
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dump_fde(fde, "close");
461408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        adb_close(fde->fd);
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_enqueue(fdevent *node)
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *list = &list_pending;
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next = list;
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev = list->prev;
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev->next = node;
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list->prev = node;
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_remove(fdevent *node)
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev->next = node->next;
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next->prev = node->prev;
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next = 0;
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev = 0;
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent *fdevent_plist_dequeue(void)
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *list = &list_pending;
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *node = list->next;
487f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(node == list) return 0;
489f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list->next = node->next;
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list->next->prev = list;
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next = 0;
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev = 0;
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return node;
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
498408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void fdevent_call_fdfunc(fdevent* fde)
499408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
500408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    unsigned events = fde->events;
501408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde->events = 0;
502408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(!(fde->state & FDE_PENDING)) return;
503408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde->state &= (~FDE_PENDING);
504408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    dump_fde(fde, "callback");
505408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde->func(fde->fd, events, fde->arg);
506408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
507408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
508408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
509408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
510408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
511408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("subproc handling on fd=%d ev=%04x\n", fd, ev);
512408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
513408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    // Hook oneself back into the fde's suitable for select() on read.
514408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if((fd < 0) || (fd >= fd_table_max)) {
515408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        FATAL("fd %d out of range for fd_table \n", fd);
516408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
517408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent *fde = fd_table[fd];
518408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent_add(fde, FDE_READ);
519408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
520408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(ev & FDE_READ){
521408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      int subproc_fd;
522408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
523408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
524408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
525408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
526408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
527408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          D("subproc_fd %d out of range 0, fd_table_max=%d\n",
528408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            subproc_fd, fd_table_max);
529408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          return;
530408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
531408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      fdevent *subproc_fde = fd_table[subproc_fd];
532408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if(!subproc_fde) {
533408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          D("subproc_fd %d cleared from fd_table\n", subproc_fd);
534408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          return;
535408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
536408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if(subproc_fde->fd != subproc_fd) {
537408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          // Already reallocated?
538408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
539408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          return;
540408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
541408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
542408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      subproc_fde->force_eof = 1;
543408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
544408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      int rcount = 0;
545b40367e7bc3f89c3875d50b29fa98c3a541e33a3JP Abgrall      ioctl(subproc_fd, FIONREAD, &rcount);
546408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      D("subproc with fd=%d  has rcount=%d err=%d\n",
547408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        subproc_fd, rcount, errno);
548408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
549408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if(rcount) {
550408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        // If there is data left, it will show up in the select().
551408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        // This works because there is no other thread reading that
552408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        // data when in this fd_func().
553408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        return;
554408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
555408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
556408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      D("subproc_fde.state=%04x\n", subproc_fde->state);
557408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      subproc_fde->events |= FDE_READ;
558408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if(subproc_fde->state & FDE_PENDING) {
559408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        return;
560408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
561408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      subproc_fde->state |= FDE_PENDING;
562408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      fdevent_call_fdfunc(subproc_fde);
563408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
564408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
565408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfdevent *fdevent_create(int fd, fd_func func, void *arg)
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde == 0) return 0;
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_install(fde, fd, func, arg);
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state |= FDE_CREATED;
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return fde;
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_destroy(fdevent *fde)
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde == 0) return;
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!(fde->state & FDE_CREATED)) {
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FATAL("fde %p not created by fdevent_create()\n", fde);
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_remove(fde);
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
584408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallvoid fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(fde, 0, sizeof(fdevent));
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = FDE_ACTIVE;
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->fd = fd;
589408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde->force_eof = 0;
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->func = func;
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->arg = arg;
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef HAVE_WINSOCK
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fcntl(fd, F_SETFL, O_NONBLOCK);
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_register(fde);
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dump_fde(fde, "connect");
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_connect(fde);
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state |= FDE_ACTIVE;
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_remove(fdevent *fde)
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_PENDING) {
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_plist_remove(fde);
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_ACTIVE) {
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_disconnect(fde);
610408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        dump_fde(fde, "disconnect");
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_unregister(fde);
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = 0;
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->events = 0;
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_set(fdevent *fde, unsigned events)
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    events &= FDE_EVENTMASK;
622f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((fde->state & FDE_EVENTMASK) == events) return;
624f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_ACTIVE) {
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_update(fde, events);
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dump_fde(fde, "update");
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = (fde->state & FDE_STATEMASK) | events;
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_PENDING) {
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* if we're pending, make sure
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** we don't signal an event that
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** is no longer wanted.
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde->events &= (~events);
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fde->events == 0) {
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_plist_remove(fde);
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state &= (~FDE_PENDING);
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_add(fdevent *fde, unsigned events)
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_set(
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_del(fdevent *fde, unsigned events)
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_set(
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
657408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallvoid fdevent_subproc_setup()
658408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
659408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    int s[2];
660408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
661408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(adb_socketpair(s)) {
662408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        FATAL("cannot create shell-exit socket-pair\n");
663408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
664408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    SHELL_EXIT_NOTIFY_FD = s[0];
665408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent *fde;
666408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
667408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(!fde)
668408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      FATAL("cannot create fdevent for shell-exit handler\n");
669408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent_add(fde, FDE_READ);
670408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
671408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_loop()
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde;
675408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent_subproc_setup();
676f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
678408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        D("--- ---- waiting for events\n");
679408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_process();
681f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while((fde = fdevent_plist_dequeue())) {
683408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            fdevent_call_fdfunc(fde);
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
687