Looper.cpp revision d18051870e8e2a5f55237a2c11fde75f46082639
17901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// 27901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// Copyright 2010 The Android Open Source Project 37901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// 47901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// A looper implementation based on epoll(). 57901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// 67901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#define LOG_TAG "Looper" 77901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 87901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown//#define LOG_NDEBUG 0 97901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 107901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// Debugs poll and wake interactions. 117901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#define DEBUG_POLL_AND_WAKE 0 127901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 137901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// Debugs callback registration and invocation. 147901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#define DEBUG_CALLBACKS 0 157901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 167901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <cutils/log.h> 177901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <utils/Looper.h> 187901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <utils/Timers.h> 197901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 207901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <unistd.h> 217901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <fcntl.h> 227901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#include <sys/epoll.h> 237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownnamespace android { 267901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 277901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// Hint for number of file descriptors to be associated with the epoll instance. 287901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownstatic const int EPOLL_SIZE_HINT = 8; 297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown// Maximum number of file descriptors for which to retrieve poll events each iteration. 317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownstatic const int EPOLL_MAX_EVENTS = 16; 327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 33d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownstatic pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT; 34d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownstatic pthread_key_t gTLSKey = 0; 35d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown 367901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff BrownLooper::Looper(bool allowNonCallbacks) : 377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mAllowNonCallbacks(allowNonCallbacks), 387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mResponseIndex(0) { 397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mEpollFd = epoll_create(EPOLL_SIZE_HINT); 407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); 417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int wakeFds[2]; 437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int result = pipe(wakeFds); 447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); 457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mWakeReadPipeFd = wakeFds[0]; 477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mWakeWritePipeFd = wakeFds[1]; 487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); 507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d", 517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown errno); 527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); 547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", 557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown errno); 567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown struct epoll_event eventItem; 58d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union 597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown eventItem.events = EPOLLIN; 607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown eventItem.data.fd = mWakeReadPipeFd; 617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); 627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", 637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown errno); 647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff BrownLooper::~Looper() { 677901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown close(mWakeReadPipeFd); 687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown close(mWakeWritePipeFd); 697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown close(mEpollFd); 707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 72d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownvoid Looper::initTLSKey() { 73d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown int result = pthread_key_create(& gTLSKey, threadDestructor); 74d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key."); 75d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown} 76d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown 777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::threadDestructor(void *st) { 787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown Looper* const self = static_cast<Looper*>(st); 797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (self != NULL) { 807901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown self->decStrong((void*)threadDestructor); 817901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 827901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 837901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 847901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::setForThread(const sp<Looper>& looper) { 857901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown sp<Looper> old = getForThread(); // also has side-effect of initializing TLS 867901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 877901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (looper != NULL) { 887901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown looper->incStrong((void*)threadDestructor); 897901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 907901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 91d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown pthread_setspecific(gTLSKey, looper.get()); 927901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 937901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (old != NULL) { 947901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown old->decStrong((void*)threadDestructor); 957901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 967901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 977901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 987901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownsp<Looper> Looper::getForThread() { 99d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown int result = pthread_once(& gTLSOnce, initTLSKey); 100d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed"); 1017901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 102d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown return (Looper*)pthread_getspecific(gTLSKey); 1037901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1047901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1057901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownsp<Looper> Looper::prepare(int opts) { 1067901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS; 1077901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown sp<Looper> looper = Looper::getForThread(); 1087901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (looper == NULL) { 1097901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown looper = new Looper(allowNonCallbacks); 1107901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown Looper::setForThread(looper); 1117901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1127901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (looper->getAllowNonCallbacks() != allowNonCallbacks) { 1137901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGW("Looper already prepared for this thread with a different value for the " 1147901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option."); 1157901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1167901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return looper; 1177901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1187901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1197901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownbool Looper::getAllowNonCallbacks() const { 1207901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return mAllowNonCallbacks; 1217901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1227901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) { 1247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int result = 0; 1257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown for (;;) { 1267901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown while (mResponseIndex < mResponses.size()) { 1277901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown const Response& response = mResponses.itemAt(mResponseIndex++); 1287901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (! response.request.callback) { 1297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 1307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - returning signalled identifier %d: " 1317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown "fd=%d, events=0x%x, data=%p", this, 1327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown response.request.ident, response.request.fd, 1337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown response.events, response.request.data); 1347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 1357901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outFd != NULL) *outFd = response.request.fd; 1367901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outEvents != NULL) *outEvents = response.events; 1377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outData != NULL) *outData = response.request.data; 1387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return response.request.ident; 1397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (result != 0) { 1437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 1447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - returning result %d", this, result); 1457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 1467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outFd != NULL) *outFd = 0; 1477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outEvents != NULL) *outEvents = NULL; 1487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outData != NULL) *outData = NULL; 1497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return result; 1507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = pollInner(timeoutMillis); 1537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollInner(int timeoutMillis) { 1577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 1587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis); 1597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 1607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown struct epoll_event eventItems[EPOLL_MAX_EVENTS]; 1617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); 1627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (eventCount < 0) { 163171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown if (errno == EINTR) { 164171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown return ALOOPER_POLL_WAKE; 1657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 166171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown 167171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown LOGW("Poll failed with an unexpected error, errno=%d", errno); 1687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return ALOOPER_POLL_ERROR; 1697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (eventCount == 0) { 1727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 1737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - timeout", this); 1747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 1757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return ALOOPER_POLL_TIMEOUT; 1767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int result = ALOOPER_POLL_WAKE; 1797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mResponses.clear(); 1807901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mResponseIndex = 0; 1817901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1827901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 1837901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount); 1847901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 1859da1810050d8825e51dabdd0262173432d49c16cJeff Brown bool acquiredLock = false; 1869da1810050d8825e51dabdd0262173432d49c16cJeff Brown for (int i = 0; i < eventCount; i++) { 1879da1810050d8825e51dabdd0262173432d49c16cJeff Brown int fd = eventItems[i].data.fd; 1889da1810050d8825e51dabdd0262173432d49c16cJeff Brown uint32_t epollEvents = eventItems[i].events; 1899da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (fd == mWakeReadPipeFd) { 1909da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (epollEvents & EPOLLIN) { 1917901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 1929da1810050d8825e51dabdd0262173432d49c16cJeff Brown LOGD("%p ~ pollOnce - awoken", this); 1937901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 1949da1810050d8825e51dabdd0262173432d49c16cJeff Brown char buffer[16]; 1959da1810050d8825e51dabdd0262173432d49c16cJeff Brown ssize_t nRead; 1969da1810050d8825e51dabdd0262173432d49c16cJeff Brown do { 1979da1810050d8825e51dabdd0262173432d49c16cJeff Brown nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer)); 1989da1810050d8825e51dabdd0262173432d49c16cJeff Brown } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer)); 1997901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } else { 2009da1810050d8825e51dabdd0262173432d49c16cJeff Brown LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents); 2019da1810050d8825e51dabdd0262173432d49c16cJeff Brown } 2029da1810050d8825e51dabdd0262173432d49c16cJeff Brown } else { 2039da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (! acquiredLock) { 2049da1810050d8825e51dabdd0262173432d49c16cJeff Brown mLock.lock(); 2059da1810050d8825e51dabdd0262173432d49c16cJeff Brown acquiredLock = true; 2069da1810050d8825e51dabdd0262173432d49c16cJeff Brown } 2079da1810050d8825e51dabdd0262173432d49c16cJeff Brown 2089da1810050d8825e51dabdd0262173432d49c16cJeff Brown ssize_t requestIndex = mRequests.indexOfKey(fd); 2099da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (requestIndex >= 0) { 2109da1810050d8825e51dabdd0262173432d49c16cJeff Brown int events = 0; 2119da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT; 2129da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT; 2139da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR; 2149da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP; 2159da1810050d8825e51dabdd0262173432d49c16cJeff Brown 2169da1810050d8825e51dabdd0262173432d49c16cJeff Brown Response response; 2179da1810050d8825e51dabdd0262173432d49c16cJeff Brown response.events = events; 2189da1810050d8825e51dabdd0262173432d49c16cJeff Brown response.request = mRequests.valueAt(requestIndex); 2199da1810050d8825e51dabdd0262173432d49c16cJeff Brown mResponses.push(response); 2209da1810050d8825e51dabdd0262173432d49c16cJeff Brown } else { 2219da1810050d8825e51dabdd0262173432d49c16cJeff Brown LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is " 2229da1810050d8825e51dabdd0262173432d49c16cJeff Brown "no longer registered.", epollEvents, fd); 2237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2269da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (acquiredLock) { 2279da1810050d8825e51dabdd0262173432d49c16cJeff Brown mLock.unlock(); 2289da1810050d8825e51dabdd0262173432d49c16cJeff Brown } 2297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown for (size_t i = 0; i < mResponses.size(); i++) { 2317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown const Response& response = mResponses.itemAt(i); 2327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (response.request.callback) { 2337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS 2347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - invoking callback: fd=%d, events=0x%x, data=%p", this, 2357901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown response.request.fd, response.events, response.request.data); 2367901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 2377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int callbackResult = response.request.callback( 2387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown response.request.fd, response.events, response.request.data); 2397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (callbackResult == 0) { 2407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown removeFd(response.request.fd); 2417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = ALOOPER_POLL_CALLBACK; 2447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return result; 2477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 2487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) { 2507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (timeoutMillis <= 0) { 2517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int result; 2527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown do { 2537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = pollOnce(timeoutMillis, outFd, outEvents, outData); 2547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } while (result == ALOOPER_POLL_CALLBACK); 2557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return result; 2567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } else { 2577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC) 2587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown + milliseconds_to_nanoseconds(timeoutMillis); 2597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown for (;;) { 2617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int result = pollOnce(timeoutMillis, outFd, outEvents, outData); 2627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (result != ALOOPER_POLL_CALLBACK) { 2637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return result; 2647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown nsecs_t timeoutNanos = endTime - systemTime(SYSTEM_TIME_MONOTONIC); 2677901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (timeoutNanos <= 0) { 2687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return ALOOPER_POLL_TIMEOUT; 2697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown timeoutMillis = int(nanoseconds_to_milliseconds(timeoutNanos + 999999LL)); 2727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 2757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::wake() { 2777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 2787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ wake", this); 2797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 2807901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 281171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown ssize_t nWrite; 282171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown do { 283171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown nWrite = write(mWakeWritePipeFd, "W", 1); 284171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown } while (nWrite == -1 && errno == EINTR); 285171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown 2867901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (nWrite != 1) { 2877901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (errno != EAGAIN) { 2887901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGW("Could not write wake signal, errno=%d", errno); 2897901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2907901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2917901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 2927901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2937901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) { 2947901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_CALLBACKS 2957901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident, 2967901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown events, callback, data); 2977901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 2987901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2997901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int epollEvents = 0; 3007901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN; 3017901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT; 3027901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (events & ALOOPER_EVENT_ERROR) epollEvents |= EPOLLERR; 3037901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (events & ALOOPER_EVENT_HANGUP) epollEvents |= EPOLLHUP; 3047901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3057901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (epollEvents == 0) { 3067901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Invalid attempt to set a callback with no selected poll events."); 3077901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 3087901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3097901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3107901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (! callback) { 3117901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (! mAllowNonCallbacks) { 3127901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Invalid attempt to set NULL callback but not allowed for this looper."); 3137901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 3147901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3157901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3167901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (ident < 0) { 3177901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Invalid attempt to set NULL callback with ident <= 0."); 3187901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 3197901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3207901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3217901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3227901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown { // acquire lock 3237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown AutoMutex _l(mLock); 3247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown Request request; 3267901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown request.fd = fd; 3277901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown request.ident = ident; 3287901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown request.callback = callback; 3297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown request.data = data; 3307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown struct epoll_event eventItem; 332d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union 3337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown eventItem.events = epollEvents; 3347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown eventItem.data.fd = fd; 3357901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3367901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown ssize_t requestIndex = mRequests.indexOfKey(fd); 3377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (requestIndex < 0) { 3387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem); 3397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (epollResult < 0) { 3407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Error adding epoll events for fd %d, errno=%d", fd, errno); 3417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 3427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mRequests.add(fd, request); 3447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } else { 3457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem); 3467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (epollResult < 0) { 3477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno); 3487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 3497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mRequests.replaceValueAt(requestIndex, request); 3517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } // release lock 3537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return 1; 3547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 3557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::removeFd(int fd) { 3577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_CALLBACKS 3587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ removeFd - fd=%d", this, fd); 3597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 3607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown { // acquire lock 3627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown AutoMutex _l(mLock); 3637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown ssize_t requestIndex = mRequests.indexOfKey(fd); 3647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (requestIndex < 0) { 3657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return 0; 3667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3677901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL); 3697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (epollResult < 0) { 3707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Error removing epoll events for fd %d, errno=%d", fd, errno); 3717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 3727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mRequests.removeItemsAt(requestIndex); 3757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } // request lock 3767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return 1; 3777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 3787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} // namespace android 380