fdevent.c revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
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**
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** you may not use this file except in compliance with the License.
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** You may obtain a copy of the License at
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 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
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdarg.h>
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stddef.h>
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/fdevent.h>
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define TRACE(x...) fprintf(stderr,x)
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DEBUG 0
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fatal(const char *fn, const char *fmt, ...)
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list ap;
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(ap, fmt);
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "%s:", fn);
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    vfprintf(stderr, fmt, ap);
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_end(ap);
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    abort();
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FATAL(x...) fatal(__FUNCTION__, x)
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if DEBUG
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void dump_fde(fdevent *fde, const char *info)
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state & FDE_READ ? 'R' : ' ',
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state & FDE_WRITE ? 'W' : ' ',
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state & FDE_ERROR ? 'E' : ' ',
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            info);
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define dump_fde(fde, info) do { } while(0)
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_EVENTMASK  0x00ff
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_STATEMASK  0xff00
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_ACTIVE     0x0100
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_PENDING    0x0200
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FDE_CREATED    0x0400
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_enqueue(fdevent *node);
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_remove(fdevent *node);
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent *fdevent_plist_dequeue(void);
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent list_pending = {
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .next = &list_pending,
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .prev = &list_pending,
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent **fd_table = 0;
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fd_table_max = 0;
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef CRAPTASTIC
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//HAVE_EPOLL
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/epoll.h>
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int epoll_fd = -1;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_init()
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* XXX: what's a good size for the passed in hint? */
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    epoll_fd = epoll_create(256);
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(epoll_fd < 0) {
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        perror("epoll_create() failed");
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(1);
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* mark for close-on-exec */
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_connect(fdevent *fde)
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event ev;
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&ev, 0, sizeof(ev));
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.events = 0;
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.data.ptr = fde;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        perror("epoll_ctl() failed\n");
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(1);
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_disconnect(fdevent *fde)
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event ev;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&ev, 0, sizeof(ev));
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.events = 0;
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.data.ptr = fde;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* technically we only need to delete if we
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** were actively monitoring events, but let's
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** be aggressive and do it anyway, just in case
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ** something's out of sync
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        */
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_update(fdevent *fde, unsigned events)
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event ev;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int active;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    active = (fde->state & FDE_EVENTMASK) != 0;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&ev, 0, sizeof(ev));
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.events = 0;
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ev.data.ptr = fde;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_READ) ev.events |= EPOLLIN;
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_WRITE) ev.events |= EPOLLOUT;
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = (fde->state & FDE_STATEMASK) | events;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(active) {
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* we're already active. if we're changing to *no*
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** events being monitored, we need to delete, otherwise
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** we need to just modify
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev.events) {
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                perror("epoll_ctl() failed\n");
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                perror("epoll_ctl() failed\n");
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* we're not active.  if we're watching events, we need
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** to add, otherwise we can just do nothing
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev.events) {
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                perror("epoll_ctl() failed\n");
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                exit(1);
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_process()
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct epoll_event events[256];
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, n;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    n = epoll_wait(epoll_fd, events, 256, -1);
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(n < 0) {
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(errno == EINTR) return;
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        perror("epoll_wait");
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(1);
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(i = 0; i < n; i++) {
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct epoll_event *ev = events + i;
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde = ev->data.ptr;
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev->events & EPOLLIN) {
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= FDE_READ;
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev->events & EPOLLOUT) {
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= FDE_WRITE;
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ev->events & (EPOLLERR | EPOLLHUP)) {
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= FDE_ERROR;
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fde->events) {
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(fde->state & FDE_PENDING) continue;
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state |= FDE_PENDING;
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_plist_enqueue(fde);
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else /* USE_SELECT */
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_WINSOCK
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <winsock2.h>
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/select.h>
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set read_fds;
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set write_fds;
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fd_set error_fds;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int select_n = 0;
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_init(void)
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_ZERO(&read_fds);
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_ZERO(&write_fds);
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_ZERO(&error_fds);
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_connect(fdevent *fde)
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->fd >= select_n) {
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        select_n = fde->fd + 1;
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_disconnect(fdevent *fde)
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, n;
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_CLR(fde->fd, &read_fds);
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_CLR(fde->fd, &write_fds);
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FD_CLR(fde->fd, &error_fds);
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(n = 0, i = 0; i < select_n; i++) {
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd_table[i] != 0) n = i;
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    select_n = n + 1;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_update(fdevent *fde, unsigned events)
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_READ) {
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_SET(fde->fd, &read_fds);
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_CLR(fde->fd, &read_fds);
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_WRITE) {
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_SET(fde->fd, &write_fds);
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_CLR(fde->fd, &write_fds);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(events & FDE_ERROR) {
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_SET(fde->fd, &error_fds);
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FD_CLR(fde->fd, &error_fds);
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = (fde->state & FDE_STATEMASK) | events;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_process()
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, n;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde;
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned events;
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd_set rfd, wfd, efd;
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(&rfd, &read_fds, sizeof(fd_set));
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(&wfd, &write_fds, sizeof(fd_set));
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(&efd, &error_fds, sizeof(fd_set));
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    n = select(select_n, &rfd, &wfd, &efd, 0);
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(n < 0) {
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(errno == EINTR) return;
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        perror("select");
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(i = 0; (i < select_n) && (n > 0); i++) {
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        events = 0;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(FD_ISSET(i, &rfd)) events |= FDE_READ;
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(FD_ISSET(i, &wfd)) events |= FDE_WRITE;
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(FD_ISSET(i, &efd)) events |= FDE_ERROR;
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(events) {
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            n--;
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde = fd_table[i];
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(fde == 0) FATAL("missing fde for fd %d\n", i);
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events |= events;
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(fde->state & FDE_PENDING) continue;
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state |= FDE_PENDING;
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_plist_enqueue(fde);
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_register(fdevent *fde)
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->fd < 0) {
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FATAL("bogus negative fd (%d)\n", fde->fd);
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->fd >= fd_table_max) {
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int oldmax = fd_table_max;
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fde->fd > 32000) {
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            FATAL("bogus huuuuge fd (%d)\n", fde->fd);
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd_table_max == 0) {
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_init();
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd_table_max = 256;
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while(fd_table_max <= fde->fd) {
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd_table_max *= 2;
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fd_table == 0) {
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            FATAL("could not expand fd_table to %d entries\n", fd_table_max);
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd_table[fde->fd] = fde;
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_unregister(fdevent *fde)
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FATAL("fd out of range (%d)\n", fde->fd);
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd_table[fde->fd] != fde) {
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FATAL("fd_table out of sync");
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd_table[fde->fd] = 0;
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!(fde->state & FDE_DONT_CLOSE)) {
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dump_fde(fde, "close");
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close(fde->fd);
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_enqueue(fdevent *node)
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *list = &list_pending;
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next = list;
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev = list->prev;
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev->next = node;
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list->prev = node;
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fdevent_plist_remove(fdevent *node)
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev->next = node->next;
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next->prev = node->prev;
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next = 0;
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev = 0;
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic fdevent *fdevent_plist_dequeue(void)
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *list = &list_pending;
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *node = list->next;
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(node == list) return 0;
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list->next = node->next;
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list->next->prev = list;
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->next = 0;
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    node->prev = 0;
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return node;
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfdevent *fdevent_create(int fd, fd_func func, void *arg)
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde == 0) return 0;
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_install(fde, fd, func, arg);
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state |= FDE_CREATED;
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return fde;
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_destroy(fdevent *fde)
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde == 0) return;
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!(fde->state & FDE_CREATED)) {
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FATAL("fde %p not created by fdevent_create()\n", fde);
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_remove(fde);
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(fde, 0, sizeof(fdevent));
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = FDE_ACTIVE;
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->fd = fd;
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->func = func;
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->arg = arg;
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef HAVE_WINSOCK
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fcntl(fd, F_SETFL, O_NONBLOCK);
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_register(fde);
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dump_fde(fde, "connect");
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_connect(fde);
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state |= FDE_ACTIVE;
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_remove(fdevent *fde)
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_PENDING) {
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_plist_remove(fde);
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_ACTIVE) {
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_disconnect(fde);
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dump_fde(fde, "disconnect");
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_unregister(fde);
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = 0;
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->events = 0;
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_set(fdevent *fde, unsigned events)
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    events &= FDE_EVENTMASK;
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((fde->state & FDE_EVENTMASK) == events) return;
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_ACTIVE) {
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_update(fde, events);
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dump_fde(fde, "update");
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fde->state = (fde->state & FDE_STATEMASK) | events;
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fde->state & FDE_PENDING) {
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* if we're pending, make sure
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** we don't signal an event that
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ** is no longer wanted.
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            */
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde->events &= (~events);
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(fde->events == 0) {
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fdevent_plist_remove(fde);
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state &= (~FDE_PENDING);
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_add(fdevent *fde, unsigned events)
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_set(
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_del(fdevent *fde, unsigned events)
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_set(
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fdevent_loop()
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent *fde;
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if DEBUG
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"--- ---- waiting for events\n");
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fdevent_process();
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while((fde = fdevent_plist_dequeue())) {
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            unsigned events = fde->events;
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->events = 0;
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->state &= (~FDE_PENDING);
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            dump_fde(fde, "callback");
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fde->func(fde->fd, events, fde->arg);
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
507