fdevent.c revision 414ff7d98ac8d7610a26206335954ad15f43f3ac
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 29414ff7d98ac8d7610a26206335954ad15f43f3acDavid 'Digit' Turner#include "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