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
31414ff7d98ac8d7610a26206335954ad15f43f3acDavid 'Digit' Turner#include "fdevent.h"
32408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#include "transport.h"
33408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#include "sysdeps.h"
34408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
36408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall/* !!! Do not enable DEBUG for the adb that will run as the server:
37408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall** both stdout and stderr are used to communicate between the client
38408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall** and server. Any extra output will cause failures.
39408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall*/
40408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define DEBUG 0   /* non-0 will break adb server */
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
42408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall// This socket is used when a subproc shell service exists.
43408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall// It wakes up the fdevent_loop() and cause the correct handling
44408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall// of the shell's pseudo-tty master. I.e. force close it.
45408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallint SHELL_EXIT_NOTIFY_FD = -1;
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fatal(const char *fn, const char *fmt, ...)
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list ap;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(ap, fmt);
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "%s:", fn);
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    vfprintf(stderr, fmt, ap);
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_end(ap);
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    abort();
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FATAL(x...) fatal(__FUNCTION__, x)
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if DEBUG
60408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define D(...) \
61408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    do { \
62408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        adb_mutex_lock(&D_lock);               \
63408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        int save_errno = errno;                \
64408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        fprintf(stderr, "%s::%s():", __FILE__, __FUNCTION__);  \
65408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        errno = save_errno;                    \
66408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        fprintf(stderr, __VA_ARGS__);          \
67408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        adb_mutex_unlock(&D_lock);             \
68408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        errno = save_errno;                    \
69408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    } while(0)
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void dump_fde(fdevent *fde, const char *info)
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
72408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    adb_mutex_lock(&D_lock);
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state & FDE_READ ? 'R' : ' ',
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state & FDE_WRITE ? 'W' : ' ',
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state & FDE_ERROR ? 'E' : ' ',
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            info);
78408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    adb_mutex_unlock(&D_lock);
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
81408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define D(...) ((void)0)
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define dump_fde(fde, info) do { } while(0)
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_EVENTMASK  0x00ff
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_STATEMASK  0xff00
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_ACTIVE     0x0100
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_PENDING    0x0200
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_CREATED    0x0400
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_enqueue(fdevent *node);
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_remove(fdevent *node);
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent *fdevent_plist_dequeue(void);
95408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent list_pending = {
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .next = &list_pending,
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .prev = &list_pending,
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent **fd_table = 0;
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fd_table_max = 0;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef CRAPTASTIC
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//HAVE_EPOLL
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/epoll.h>
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int epoll_fd = -1;
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_init()
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* XXX: what's a good size for the passed in hint? */
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    epoll_fd = epoll_create(256);
116f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(epoll_fd < 0) {
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        perror("epoll_create() failed");
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(1);
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* mark for close-on-exec */
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_connect(fdevent *fde)
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event ev;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&ev, 0, sizeof(ev));
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.events = 0;
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.data.ptr = fde;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
134f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner#if 0
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        perror("epoll_ctl() failed\n");
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(1);
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_disconnect(fdevent *fde)
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event ev;
145f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&ev, 0, sizeof(ev));
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.events = 0;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.data.ptr = fde;
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* technically we only need to delete if we
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** were actively monitoring events, but let's
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** be aggressive and do it anyway, just in case
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** something's out of sync
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_update(fdevent *fde, unsigned events)
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event ev;
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int active;
162f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    active = (fde->state & FDE_EVENTMASK) != 0;
164f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&ev, 0, sizeof(ev));
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.events = 0;
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.data.ptr = fde;
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_READ) ev.events |= EPOLLIN;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_WRITE) ev.events |= EPOLLOUT;
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = (fde->state & FDE_STATEMASK) | events;
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(active) {
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* we're already active. if we're changing to *no*
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** events being monitored, we need to delete, otherwise
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** we need to just modify
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev.events) {
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                perror("epoll_ctl() failed\n");
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                perror("epoll_ctl() failed\n");
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* we're not active.  if we're watching events, we need
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** to add, otherwise we can just do nothing
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev.events) {
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                perror("epoll_ctl() failed\n");
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_process()
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event events[256];
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde;
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, n;
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    n = epoll_wait(epoll_fd, events, 256, -1);
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(n < 0) {
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(errno == EINTR) return;
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        perror("epoll_wait");
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(1);
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(i = 0; i < n; i++) {
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct epoll_event *ev = events + i;
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde = ev->data.ptr;
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev->events & EPOLLIN) {
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= FDE_READ;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev->events & EPOLLOUT) {
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= FDE_WRITE;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev->events & (EPOLLERR | EPOLLHUP)) {
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= FDE_ERROR;
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fde->events) {
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(fde->state & FDE_PENDING) continue;
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state |= FDE_PENDING;
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_plist_enqueue(fde);
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else /* USE_SELECT */
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_WINSOCK
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <winsock2.h>
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/select.h>
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set read_fds;
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set write_fds;
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set error_fds;
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int select_n = 0;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_init(void)
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_ZERO(&read_fds);
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_ZERO(&write_fds);
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_ZERO(&error_fds);
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_connect(fdevent *fde)
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->fd >= select_n) {
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        select_n = fde->fd + 1;
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_disconnect(fdevent *fde)
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, n;
270f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_CLR(fde->fd, &read_fds);
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_CLR(fde->fd, &write_fds);
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_CLR(fde->fd, &error_fds);
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(n = 0, i = 0; i < select_n; i++) {
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd_table[i] != 0) n = i;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    select_n = n + 1;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_update(fdevent *fde, unsigned events)
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_READ) {
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_SET(fde->fd, &read_fds);
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_CLR(fde->fd, &read_fds);
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_WRITE) {
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_SET(fde->fd, &write_fds);
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_CLR(fde->fd, &write_fds);
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_ERROR) {
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_SET(fde->fd, &error_fds);
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_CLR(fde->fd, &error_fds);
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
299408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde->state = (fde->state & FDE_STATEMASK) | events;
300408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
301408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
302408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall/* Looks at fd_table[] for bad FDs and sets bit in fds.
303408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall** Returns the number of bad FDs.
304408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall*/
305408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic int fdevent_fd_check(fd_set *fds)
306408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
307408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    int i, n = 0;
308408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent *fde;
309408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
310408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    for(i = 0; i < select_n; i++) {
311408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        fde = fd_table[i];
312408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(fde == 0) continue;
313408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(fcntl(i, F_GETFL, NULL) < 0) {
314408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            FD_SET(i, fds);
315408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            n++;
316408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            // fde->state |= FDE_DONT_CLOSE;
317408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
318408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }
319408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
320408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    return n;
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
323408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#if !DEBUG
324408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic inline void dump_all_fds(const char *extra_msg) {}
325408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#else
326408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void dump_all_fds(const char *extra_msg)
327408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
328408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallint i;
329408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent *fde;
330408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
331408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
332408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    size_t max_chars = FD_SETSIZE * 6 + 1;
333408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    int printed_out;
334408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define SAFE_SPRINTF(...)                                                    \
335408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    do {                                                                     \
336408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        printed_out = snprintf(pb, max_chars, __VA_ARGS__);                  \
337408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if (printed_out <= 0) {                                              \
338408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("... snprintf failed.\n");                                     \
339408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            return;                                                          \
340408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }                                                                    \
341408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if (max_chars < (unsigned int)printed_out) {                         \
342408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("... snprintf out of space.\n");                               \
343408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            return;                                                          \
344408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }                                                                    \
345408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        pb += printed_out;                                                   \
346408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        max_chars -= printed_out;                                            \
347408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    } while(0)
348408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
349408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    for(i = 0; i < select_n; i++) {
350408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        fde = fd_table[i];
351408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        SAFE_SPRINTF("%d", i);
352408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(fde == 0) {
353408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            SAFE_SPRINTF("? ");
354408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            continue;
355408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }
356408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(fcntl(i, F_GETFL, NULL) < 0) {
357408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            SAFE_SPRINTF("b");
358408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }
359408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        SAFE_SPRINTF(" ");
360408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
361408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
362408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
363408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#endif
364408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_process()
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, n;
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde;
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned events;
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd_set rfd, wfd, efd;
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(&rfd, &read_fds, sizeof(fd_set));
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(&wfd, &write_fds, sizeof(fd_set));
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(&efd, &error_fds, sizeof(fd_set));
375f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
376408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    dump_all_fds("pre select()");
377408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
378408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    n = select(select_n, &rfd, &wfd, &efd, NULL);
379408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    int saved_errno = errno;
380408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
381408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
382408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    dump_all_fds("post select()");
383f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(n < 0) {
385408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        switch(saved_errno) {
386408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        case EINTR: return;
387408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        case EBADF:
388408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            // Can't trust the FD sets after an error.
389408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            FD_ZERO(&wfd);
390408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            FD_ZERO(&efd);
391408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            FD_ZERO(&rfd);
392408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            break;
393408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        default:
394408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("Unexpected select() error=%d\n", saved_errno);
395408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            return;
396408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }
397408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
398408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(n <= 0) {
399408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        // We fake a read, as the rest of the code assumes
400408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        // that errors will be detected at that point.
401408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        n = fdevent_fd_check(&rfd);
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(i = 0; (i < select_n) && (n > 0); i++) {
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        events = 0;
406408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
407408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
408408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(events) {
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde = fd_table[i];
412408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            if(fde == 0)
413408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall              FATAL("missing fde for fd %d\n", i);
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= events;
416f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
417408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("got events fde->fd=%d events=%04x, state=%04x\n",
418408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall                fde->fd, fde->events, fde->state);
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(fde->state & FDE_PENDING) continue;
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state |= FDE_PENDING;
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_plist_enqueue(fde);
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_register(fdevent *fde)
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->fd < 0) {
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FATAL("bogus negative fd (%d)\n", fde->fd);
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
433f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->fd >= fd_table_max) {
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int oldmax = fd_table_max;
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fde->fd > 32000) {
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            FATAL("bogus huuuuge fd (%d)\n", fde->fd);
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd_table_max == 0) {
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_init();
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd_table_max = 256;
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while(fd_table_max <= fde->fd) {
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd_table_max *= 2;
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd_table == 0) {
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            FATAL("could not expand fd_table to %d entries\n", fd_table_max);
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd_table[fde->fd] = fde;
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_unregister(fdevent *fde)
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FATAL("fd out of range (%d)\n", fde->fd);
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd_table[fde->fd] != fde) {
463408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        FATAL("fd_table out of sync [%d]\n", fde->fd);
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd_table[fde->fd] = 0;
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!(fde->state & FDE_DONT_CLOSE)) {
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dump_fde(fde, "close");
470408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        adb_close(fde->fd);
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_enqueue(fdevent *node)
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *list = &list_pending;
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next = list;
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev = list->prev;
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev->next = node;
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list->prev = node;
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_remove(fdevent *node)
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev->next = node->next;
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next->prev = node->prev;
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next = 0;
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev = 0;
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent *fdevent_plist_dequeue(void)
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *list = &list_pending;
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *node = list->next;
496f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(node == list) return 0;
498f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list->next = node->next;
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list->next->prev = list;
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next = 0;
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev = 0;
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return node;
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
507408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void fdevent_call_fdfunc(fdevent* fde)
508408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
509408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    unsigned events = fde->events;
510408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde->events = 0;
511408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(!(fde->state & FDE_PENDING)) return;
512408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde->state &= (~FDE_PENDING);
513408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    dump_fde(fde, "callback");
514408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde->func(fde->fd, events, fde->arg);
515408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
516408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
517408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
518408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
519408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
520408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("subproc handling on fd=%d ev=%04x\n", fd, ev);
521408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
522408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    // Hook oneself back into the fde's suitable for select() on read.
523408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if((fd < 0) || (fd >= fd_table_max)) {
524408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        FATAL("fd %d out of range for fd_table \n", fd);
525408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
526408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent *fde = fd_table[fd];
527408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent_add(fde, FDE_READ);
528408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
529408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(ev & FDE_READ){
530408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      int subproc_fd;
531408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
532408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
533408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
534408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
535408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
536408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          D("subproc_fd %d out of range 0, fd_table_max=%d\n",
537408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            subproc_fd, fd_table_max);
538408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          return;
539408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
540408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      fdevent *subproc_fde = fd_table[subproc_fd];
541408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if(!subproc_fde) {
542408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          D("subproc_fd %d cleared from fd_table\n", subproc_fd);
543408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          return;
544408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
545408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if(subproc_fde->fd != subproc_fd) {
546408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          // Already reallocated?
547408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
548408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall          return;
549408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
550408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
551408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      subproc_fde->force_eof = 1;
552408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
553408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      int rcount = 0;
554b40367e7bc3f89c3875d50b29fa98c3a541e33a3JP Abgrall      ioctl(subproc_fd, FIONREAD, &rcount);
555408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      D("subproc with fd=%d  has rcount=%d err=%d\n",
556408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        subproc_fd, rcount, errno);
557408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
558408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if(rcount) {
559408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        // If there is data left, it will show up in the select().
560408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        // This works because there is no other thread reading that
561408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        // data when in this fd_func().
562408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        return;
563408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
564408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
565408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      D("subproc_fde.state=%04x\n", subproc_fde->state);
566408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      subproc_fde->events |= FDE_READ;
567408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      if(subproc_fde->state & FDE_PENDING) {
568408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        return;
569408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      }
570408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      subproc_fde->state |= FDE_PENDING;
571408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      fdevent_call_fdfunc(subproc_fde);
572408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
573408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
574408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfdevent *fdevent_create(int fd, fd_func func, void *arg)
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde == 0) return 0;
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_install(fde, fd, func, arg);
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state |= FDE_CREATED;
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return fde;
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_destroy(fdevent *fde)
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde == 0) return;
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!(fde->state & FDE_CREATED)) {
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FATAL("fde %p not created by fdevent_create()\n", fde);
589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_remove(fde);
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
593408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallvoid fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(fde, 0, sizeof(fdevent));
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = FDE_ACTIVE;
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->fd = fd;
598408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde->force_eof = 0;
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->func = func;
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->arg = arg;
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef HAVE_WINSOCK
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fcntl(fd, F_SETFL, O_NONBLOCK);
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_register(fde);
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dump_fde(fde, "connect");
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_connect(fde);
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state |= FDE_ACTIVE;
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_remove(fdevent *fde)
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_PENDING) {
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_plist_remove(fde);
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_ACTIVE) {
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_disconnect(fde);
619408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        dump_fde(fde, "disconnect");
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_unregister(fde);
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = 0;
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->events = 0;
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_set(fdevent *fde, unsigned events)
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    events &= FDE_EVENTMASK;
631f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((fde->state & FDE_EVENTMASK) == events) return;
633f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_ACTIVE) {
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_update(fde, events);
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dump_fde(fde, "update");
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = (fde->state & FDE_STATEMASK) | events;
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_PENDING) {
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* if we're pending, make sure
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** we don't signal an event that
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** is no longer wanted.
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde->events &= (~events);
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fde->events == 0) {
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_plist_remove(fde);
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state &= (~FDE_PENDING);
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_add(fdevent *fde, unsigned events)
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_set(
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_del(fdevent *fde, unsigned events)
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_set(
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
666408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallvoid fdevent_subproc_setup()
667408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
668408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    int s[2];
669408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
670408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(adb_socketpair(s)) {
671408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        FATAL("cannot create shell-exit socket-pair\n");
672408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
673408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    SHELL_EXIT_NOTIFY_FD = s[0];
674408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent *fde;
675408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
676408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(!fde)
677408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      FATAL("cannot create fdevent for shell-exit handler\n");
678408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent_add(fde, FDE_READ);
679408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
680408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_loop()
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde;
684408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    fdevent_subproc_setup();
685f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
687408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        D("--- ---- waiting for events\n");
688408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_process();
690f6330a2eeb78c0971f33feee7fd1ee06472a7dbaDavid 'Digit' Turner
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while((fde = fdevent_plist_dequeue())) {
692408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            fdevent_call_fdfunc(fde);
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
696