1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License. 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License. 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_TAG "selector" 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <assert.h> 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <pthread.h> 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/array.h> 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/selector.h> 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "loghack.h" 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct Selector { 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Array* selectableFds; 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bool looping; 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_set readFds; 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_set writeFds; 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_set exceptFds; 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int maxFd; 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int wakeupPipe[2]; 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SelectableFd* wakeupFd; 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bool inSelect; 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_t inSelectLock; 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Reads and ignores wake up data. */ 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void eatWakeupData(SelectableFd* wakeupFd) { 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project static char garbage[64]; 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (read(wakeupFd->fd, garbage, sizeof(garbage)) < 0) { 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (errno == EINTR) { 51fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block ALOGI("read() interrupted."); 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("This should never happen: %s", strerror(errno)); 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void setInSelect(Selector* selector, bool inSelect) { 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_lock(&selector->inSelectLock); 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selector->inSelect = inSelect; 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_unlock(&selector->inSelectLock); 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic bool isInSelect(Selector* selector) { 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_lock(&selector->inSelectLock); 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bool inSelect = selector->inSelect; 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_unlock(&selector->inSelectLock); 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return inSelect; 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid selectorWakeUp(Selector* selector) { 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!isInSelect(selector)) { 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // We only need to write wake-up data if we're blocked in select(). 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project static char garbage[1]; 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (write(selector->wakeupPipe[1], garbage, sizeof(garbage)) < 0) { 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (errno == EINTR) { 80fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block ALOGI("read() interrupted."); 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("This should never happen: %s", strerror(errno)); 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSelector* selectorCreate(void) { 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Selector* selector = calloc(1, sizeof(Selector)); 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (selector == NULL) { 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("malloc() error."); 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selector->selectableFds = arrayCreate(); 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Set up wake-up pipe. 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (pipe(selector->wakeupPipe) < 0) { 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("pipe() error: %s", strerror(errno)); 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 998d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Wakeup fd: %d", selector->wakeupPipe[0]); 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SelectableFd* wakeupFd = selectorAdd(selector, selector->wakeupPipe[0]); 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (wakeupFd == NULL) { 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("malloc() error."); 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project wakeupFd->onReadable = &eatWakeupData; 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pthread_mutex_init(&selector->inSelectLock, NULL); 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return selector; 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSelectableFd* selectorAdd(Selector* selector, int fd) { 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project assert(selector != NULL); 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SelectableFd* selectableFd = calloc(1, sizeof(SelectableFd)); 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (selectableFd != NULL) { 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selectableFd->selector = selector; 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selectableFd->fd = fd; 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project arrayAdd(selector->selectableFds, selectableFd); 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return selectableFd; 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Adds an fd to the given set if the callback is non-null. Returns true 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * if the fd was added. 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline bool maybeAdd(SelectableFd* selectableFd, 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project void (*callback)(SelectableFd*), fd_set* fdSet) { 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (callback != NULL) { 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_SET(selectableFd->fd, fdSet); 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return true; 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return false; 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Removes stale file descriptors and initializes file descriptor sets. 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void prepareForSelect(Selector* selector) { 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_set* exceptFds = &selector->exceptFds; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_set* readFds = &selector->readFds; 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd_set* writeFds = &selector->writeFds; 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_ZERO(exceptFds); 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_ZERO(readFds); 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_ZERO(writeFds); 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Array* selectableFds = selector->selectableFds; 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i = 0; 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selector->maxFd = 0; 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int size = arraySize(selectableFds); 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (i < size) { 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SelectableFd* selectableFd = arrayGet(selectableFds, i); 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (selectableFd->remove) { 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // This descriptor should be removed. 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project arrayRemove(selectableFds, i); 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project size--; 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (selectableFd->onRemove != NULL) { 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selectableFd->onRemove(selectableFd); 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(selectableFd); 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (selectableFd->beforeSelect != NULL) { 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selectableFd->beforeSelect(selectableFd); 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bool inSet = false; 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (maybeAdd(selectableFd, selectableFd->onExcept, exceptFds)) { 1728d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Selecting fd %d for writing...", selectableFd->fd); 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project inSet = true; 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (maybeAdd(selectableFd, selectableFd->onReadable, readFds)) { 1768d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Selecting fd %d for reading...", selectableFd->fd); 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project inSet = true; 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (maybeAdd(selectableFd, selectableFd->onWritable, writeFds)) { 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project inSet = true; 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (inSet) { 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // If the fd is in a set, check it against max. 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd = selectableFd->fd; 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd > selector->maxFd) { 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selector->maxFd = fd; 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Move to next descriptor. 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project i++; 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Invokes a callback if the callback is non-null and the fd is in the given 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * set. 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline void maybeInvoke(SelectableFd* selectableFd, 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project void (*callback)(SelectableFd*), fd_set* fdSet) { 2038d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block if (callback != NULL && !selectableFd->remove && 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FD_ISSET(selectableFd->fd, fdSet)) { 2058d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Selected fd %d.", selectableFd->fd); 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project callback(selectableFd); 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Notifies user if file descriptors are readable or writable, or if 212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * out-of-band data is present. 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fireEvents(Selector* selector) { 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project Array* selectableFds = selector->selectableFds; 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int size = arraySize(selectableFds); 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i; 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (i = 0; i < size; i++) { 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project SelectableFd* selectableFd = arrayGet(selectableFds, i); 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project maybeInvoke(selectableFd, selectableFd->onExcept, 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project &selector->exceptFds); 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project maybeInvoke(selectableFd, selectableFd->onReadable, 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project &selector->readFds); 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project maybeInvoke(selectableFd, selectableFd->onWritable, 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project &selector->writeFds); 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid selectorLoop(Selector* selector) { 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Make sure we're not already looping. 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (selector->looping) { 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("Already looping."); 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project selector->looping = true; 235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (true) { 237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project setInSelect(selector, true); 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project prepareForSelect(selector); 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 2418d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Entering select()."); 242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Select file descriptors. 244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result = select(selector->maxFd + 1, &selector->readFds, 245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project &selector->writeFds, &selector->exceptFds, NULL); 246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 2478d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("Exiting select()."); 248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project setInSelect(selector, false); 250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (result == -1) { 252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // Abort on everything except EINTR. 253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (errno == EINTR) { 254fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block ALOGI("select() interrupted."); 255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG_ALWAYS_FATAL("select() error: %s", 257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strerror(errno)); 258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (result > 0) { 260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fireEvents(selector); 261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 264