Looper.cpp revision 8d15c74d50fd01d6e63970aadd261a9d3bed27e7
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 237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownnamespace android { 257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 268d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL 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; 328d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 34d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownstatic pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT; 35d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownstatic pthread_key_t gTLSKey = 0; 36d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown 377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff BrownLooper::Looper(bool allowNonCallbacks) : 387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mAllowNonCallbacks(allowNonCallbacks), 397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mResponseIndex(0) { 407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int wakeFds[2]; 417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int result = pipe(wakeFds); 427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); 437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mWakeReadPipeFd = wakeFds[0]; 457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mWakeWritePipeFd = wakeFds[1]; 467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); 487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d", 497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown errno); 507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); 527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", 537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown errno); 547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 558d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL 568d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown // Allocate the epoll instance and register the wake pipe. 578d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mEpollFd = epoll_create(EPOLL_SIZE_HINT); 588d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); 598d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown struct epoll_event eventItem; 61d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union 627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown eventItem.events = EPOLLIN; 637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown eventItem.data.fd = mWakeReadPipeFd; 647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); 657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", 667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown errno); 678d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#else 688d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown // Add the wake pipe to the head of the request list with a null callback. 698d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown struct pollfd requestedFd; 708d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown requestedFd.fd = mWakeReadPipeFd; 718d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown requestedFd.events = POLLIN; 728d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mRequestedFds.push(requestedFd); 738d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 748d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown Request request; 758d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown request.fd = mWakeReadPipeFd; 768d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown request.callback = NULL; 778d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown request.ident = 0; 788d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown request.data = NULL; 798d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mRequests.push(request); 808d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 818d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mPolling = false; 828d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mWaiters = 0; 838d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 848d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 858d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_STATISTICS 868d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mPendingWakeTime = -1; 878d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mPendingWakeCount = 0; 888d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledWakeCycles = 0; 898d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledWakeCountSum = 0; 908d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledWakeLatencySum = 0; 918d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 928d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledPolls = 0; 938d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledZeroPollCount = 0; 948d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledZeroPollLatencySum = 0; 958d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledTimeoutPollCount = 0; 968d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledTimeoutPollLatencySum = 0; 978d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 987901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 997901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1007901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff BrownLooper::~Looper() { 1017901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown close(mWakeReadPipeFd); 1027901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown close(mWakeWritePipeFd); 1038d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL 1047901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown close(mEpollFd); 1058d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 1067901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1077901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 108d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brownvoid Looper::initTLSKey() { 109d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown int result = pthread_key_create(& gTLSKey, threadDestructor); 110d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key."); 111d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown} 112d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown 1137901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::threadDestructor(void *st) { 1147901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown Looper* const self = static_cast<Looper*>(st); 1157901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (self != NULL) { 1167901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown self->decStrong((void*)threadDestructor); 1177901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1187901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1197901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1207901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::setForThread(const sp<Looper>& looper) { 1217901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown sp<Looper> old = getForThread(); // also has side-effect of initializing TLS 1227901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1237901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (looper != NULL) { 1247901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown looper->incStrong((void*)threadDestructor); 1257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1267901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 127d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown pthread_setspecific(gTLSKey, looper.get()); 1287901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (old != NULL) { 1307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown old->decStrong((void*)threadDestructor); 1317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownsp<Looper> Looper::getForThread() { 135d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown int result = pthread_once(& gTLSOnce, initTLSKey); 136d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed"); 1377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 138d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown return (Looper*)pthread_getspecific(gTLSKey); 1397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownsp<Looper> Looper::prepare(int opts) { 1427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS; 1437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown sp<Looper> looper = Looper::getForThread(); 1447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (looper == NULL) { 1457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown looper = new Looper(allowNonCallbacks); 1467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown Looper::setForThread(looper); 1477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (looper->getAllowNonCallbacks() != allowNonCallbacks) { 1497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGW("Looper already prepared for this thread with a different value for the " 1507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option."); 1517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return looper; 1537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownbool Looper::getAllowNonCallbacks() const { 1567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return mAllowNonCallbacks; 1577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) { 1607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int result = 0; 1617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown for (;;) { 1627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown while (mResponseIndex < mResponses.size()) { 1637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown const Response& response = mResponses.itemAt(mResponseIndex++); 1647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (! response.request.callback) { 1657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 1667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - returning signalled identifier %d: " 1677901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown "fd=%d, events=0x%x, data=%p", this, 1687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown response.request.ident, response.request.fd, 1697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown response.events, response.request.data); 1707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 1717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outFd != NULL) *outFd = response.request.fd; 1727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outEvents != NULL) *outEvents = response.events; 1737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outData != NULL) *outData = response.request.data; 1747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return response.request.ident; 1757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (result != 0) { 1797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 1807901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - returning result %d", this, result); 1817901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 1827901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outFd != NULL) *outFd = 0; 1837901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outEvents != NULL) *outEvents = NULL; 1847901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (outData != NULL) *outData = NULL; 1857901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return result; 1867901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1877901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1887901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = pollInner(timeoutMillis); 1897901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 1907901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 1917901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 1927901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollInner(int timeoutMillis) { 1937901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 1947901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis); 1957901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 1968d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 1978d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown int result = ALOOPER_POLL_WAKE; 1988d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mResponses.clear(); 1998d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mResponseIndex = 0; 2008d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 2018d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_STATISTICS 2028d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown nsecs_t pollStartTime = systemTime(SYSTEM_TIME_MONOTONIC); 2038d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 2048d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 2058d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL 2067901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown struct epoll_event eventItems[EPOLL_MAX_EVENTS]; 2077901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); 2088d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown bool acquiredLock = false; 2098d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#else 2108d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown // Wait for wakeAndLock() waiters to run then set mPolling to true. 2118d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mLock.lock(); 2128d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown while (mWaiters != 0) { 2138d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mResume.wait(mLock); 2148d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 2158d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mPolling = true; 2168d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mLock.unlock(); 2178d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 2188d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown size_t requestedCount = mRequestedFds.size(); 2198d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown int eventCount = poll(mRequestedFds.editArray(), requestedCount, timeoutMillis); 2208d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 2218d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 2227901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (eventCount < 0) { 223171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown if (errno == EINTR) { 2248d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown goto Done; 2257901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 226171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown 227171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown LOGW("Poll failed with an unexpected error, errno=%d", errno); 2288d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown result = ALOOPER_POLL_ERROR; 2298d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown goto Done; 2307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (eventCount == 0) { 2337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 2347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - timeout", this); 2357901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 2368d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown result = ALOOPER_POLL_TIMEOUT; 2378d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown goto Done; 2387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 2407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 2417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount); 2427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 2438d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 2448d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL 2459da1810050d8825e51dabdd0262173432d49c16cJeff Brown for (int i = 0; i < eventCount; i++) { 2469da1810050d8825e51dabdd0262173432d49c16cJeff Brown int fd = eventItems[i].data.fd; 2479da1810050d8825e51dabdd0262173432d49c16cJeff Brown uint32_t epollEvents = eventItems[i].events; 2489da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (fd == mWakeReadPipeFd) { 2499da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (epollEvents & EPOLLIN) { 2508d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown awoken(); 2517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } else { 2529da1810050d8825e51dabdd0262173432d49c16cJeff Brown LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents); 2539da1810050d8825e51dabdd0262173432d49c16cJeff Brown } 2549da1810050d8825e51dabdd0262173432d49c16cJeff Brown } else { 2559da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (! acquiredLock) { 2569da1810050d8825e51dabdd0262173432d49c16cJeff Brown mLock.lock(); 2579da1810050d8825e51dabdd0262173432d49c16cJeff Brown acquiredLock = true; 2589da1810050d8825e51dabdd0262173432d49c16cJeff Brown } 2599da1810050d8825e51dabdd0262173432d49c16cJeff Brown 2609da1810050d8825e51dabdd0262173432d49c16cJeff Brown ssize_t requestIndex = mRequests.indexOfKey(fd); 2619da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (requestIndex >= 0) { 2629da1810050d8825e51dabdd0262173432d49c16cJeff Brown int events = 0; 2639da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT; 2649da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT; 2659da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR; 2669da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP; 2678d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown pushResponse(events, mRequests.valueAt(requestIndex)); 2689da1810050d8825e51dabdd0262173432d49c16cJeff Brown } else { 2699da1810050d8825e51dabdd0262173432d49c16cJeff Brown LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is " 2709da1810050d8825e51dabdd0262173432d49c16cJeff Brown "no longer registered.", epollEvents, fd); 2717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 2749da1810050d8825e51dabdd0262173432d49c16cJeff Brown if (acquiredLock) { 2759da1810050d8825e51dabdd0262173432d49c16cJeff Brown mLock.unlock(); 2769da1810050d8825e51dabdd0262173432d49c16cJeff Brown } 2778d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff BrownDone: ; 2788d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#else 2798d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown for (size_t i = 0; i < requestedCount; i++) { 2808d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown const struct pollfd& requestedFd = mRequestedFds.itemAt(i); 2818d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 2828d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown short pollEvents = requestedFd.revents; 2838d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (pollEvents) { 2848d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (requestedFd.fd == mWakeReadPipeFd) { 2858d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (pollEvents & POLLIN) { 2868d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown awoken(); 2878d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } else { 2888d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown LOGW("Ignoring unexpected poll events 0x%x on wake read pipe.", pollEvents); 2898d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 2908d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } else { 2918d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown int events = 0; 2928d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (pollEvents & POLLIN) events |= ALOOPER_EVENT_INPUT; 2938d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (pollEvents & POLLOUT) events |= ALOOPER_EVENT_OUTPUT; 2948d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (pollEvents & POLLERR) events |= ALOOPER_EVENT_ERROR; 2958d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (pollEvents & POLLHUP) events |= ALOOPER_EVENT_HANGUP; 2968d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (pollEvents & POLLNVAL) events |= ALOOPER_EVENT_INVALID; 2978d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown pushResponse(events, mRequests.itemAt(i)); 2988d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 2998d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (--eventCount == 0) { 3008d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown break; 3018d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 3028d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 3038d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 3048d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 3058d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff BrownDone: 3068d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown // Set mPolling to false and wake up the wakeAndLock() waiters. 3078d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mLock.lock(); 3088d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mPolling = false; 3098d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (mWaiters != 0) { 3108d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mAwake.broadcast(); 3118d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 3128d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mLock.unlock(); 3138d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 3148d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 3158d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_STATISTICS 3168d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown nsecs_t pollEndTime = systemTime(SYSTEM_TIME_MONOTONIC); 3178d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledPolls += 1; 3188d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (timeoutMillis == 0) { 3198d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledZeroPollCount += 1; 3208d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledZeroPollLatencySum += pollEndTime - pollStartTime; 3218d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } else if (timeoutMillis > 0 && result == ALOOPER_POLL_TIMEOUT) { 3228d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledTimeoutPollCount += 1; 3238d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledTimeoutPollLatencySum += pollEndTime - pollStartTime 3248d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown - milliseconds_to_nanoseconds(timeoutMillis); 3258d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 3268d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (mSampledPolls == SAMPLED_POLLS_TO_AGGREGATE) { 3278d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown LOGD("%p ~ poll latency statistics: %0.3fms zero timeout, %0.3fms non-zero timeout", this, 3288d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 0.000001f * float(mSampledZeroPollLatencySum) / mSampledZeroPollCount, 3298d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 0.000001f * float(mSampledTimeoutPollLatencySum) / mSampledTimeoutPollCount); 3308d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledPolls = 0; 3318d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledZeroPollCount = 0; 3328d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledZeroPollLatencySum = 0; 3338d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledTimeoutPollCount = 0; 3348d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledTimeoutPollLatencySum = 0; 3358d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 3368d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 3377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown for (size_t i = 0; i < mResponses.size(); i++) { 3397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown const Response& response = mResponses.itemAt(i); 3407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (response.request.callback) { 3417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS 3427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ pollOnce - invoking callback: fd=%d, events=0x%x, data=%p", this, 3437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown response.request.fd, response.events, response.request.data); 3447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 3457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int callbackResult = response.request.callback( 3467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown response.request.fd, response.events, response.request.data); 3477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (callbackResult == 0) { 3487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown removeFd(response.request.fd); 3497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = ALOOPER_POLL_CALLBACK; 3527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return result; 3557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 3567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) { 3587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (timeoutMillis <= 0) { 3597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int result; 3607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown do { 3617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown result = pollOnce(timeoutMillis, outFd, outEvents, outData); 3627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } while (result == ALOOPER_POLL_CALLBACK); 3637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return result; 3647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } else { 3657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC) 3667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown + milliseconds_to_nanoseconds(timeoutMillis); 3677901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3687901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown for (;;) { 3697901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int result = pollOnce(timeoutMillis, outFd, outEvents, outData); 3707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (result != ALOOPER_POLL_CALLBACK) { 3717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return result; 3727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown nsecs_t timeoutNanos = endTime - systemTime(SYSTEM_TIME_MONOTONIC); 3757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (timeoutNanos <= 0) { 3767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return ALOOPER_POLL_TIMEOUT; 3777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown timeoutMillis = int(nanoseconds_to_milliseconds(timeoutNanos + 999999LL)); 3807901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3817901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 3827901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 3837901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3847901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownvoid Looper::wake() { 3857901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_POLL_AND_WAKE 3867901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ wake", this); 3877901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 3887901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 3898d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_STATISTICS 3908d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown // FIXME: Possible race with awoken() but this code is for testing only and is rarely enabled. 3918d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (mPendingWakeCount++ == 0) { 3928d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mPendingWakeTime = systemTime(SYSTEM_TIME_MONOTONIC); 3938d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 3948d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 3958d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 396171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown ssize_t nWrite; 397171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown do { 398171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown nWrite = write(mWakeWritePipeFd, "W", 1); 399171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown } while (nWrite == -1 && errno == EINTR); 400171bf9e69792f4796e27334c8a97dbd8576ad78aJeff Brown 4017901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (nWrite != 1) { 4027901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (errno != EAGAIN) { 4037901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGW("Could not write wake signal, errno=%d", errno); 4047901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 4057901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 4067901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 4077901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 4088d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brownvoid Looper::awoken() { 4098d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#if DEBUG_POLL_AND_WAKE 4108d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown LOGD("%p ~ awoken", this); 4118d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 4128d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 4138d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_STATISTICS 4148d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (mPendingWakeCount == 0) { 4158d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown LOGD("%p ~ awoken: spurious!", this); 4168d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } else { 4178d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledWakeCycles += 1; 4188d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledWakeCountSum += mPendingWakeCount; 4198d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledWakeLatencySum += systemTime(SYSTEM_TIME_MONOTONIC) - mPendingWakeTime; 4208d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mPendingWakeCount = 0; 4218d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mPendingWakeTime = -1; 4228d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (mSampledWakeCycles == SAMPLED_WAKE_CYCLES_TO_AGGREGATE) { 4238d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown LOGD("%p ~ wake statistics: %0.3fms wake latency, %0.3f wakes per cycle", this, 4248d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 0.000001f * float(mSampledWakeLatencySum) / mSampledWakeCycles, 4258d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown float(mSampledWakeCountSum) / mSampledWakeCycles); 4268d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledWakeCycles = 0; 4278d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledWakeCountSum = 0; 4288d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mSampledWakeLatencySum = 0; 4298d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 4308d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 4318d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 4328d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 4338d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown char buffer[16]; 4348d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown ssize_t nRead; 4358d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown do { 4368d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer)); 4378d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer)); 4388d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown} 4398d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 4408d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brownvoid Looper::pushResponse(int events, const Request& request) { 4418d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown Response response; 4428d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown response.events = events; 4438d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown response.request = request; 4448d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mResponses.push(response); 4458d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown} 4468d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 4477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) { 4487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_CALLBACKS 4497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident, 4507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown events, callback, data); 4517901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 4527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 4537901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (! callback) { 4547901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (! mAllowNonCallbacks) { 4557901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Invalid attempt to set NULL callback but not allowed for this looper."); 4567901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 4577901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 4587901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 4597901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (ident < 0) { 4607901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Invalid attempt to set NULL callback with ident <= 0."); 4617901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 4627901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 4637901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 4647901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 4658d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL 4668d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown int epollEvents = 0; 4678d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN; 4688d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT; 4698d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 4707901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown { // acquire lock 4717901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown AutoMutex _l(mLock); 4727901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 4737901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown Request request; 4747901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown request.fd = fd; 4757901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown request.ident = ident; 4767901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown request.callback = callback; 4777901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown request.data = data; 4787901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 4797901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown struct epoll_event eventItem; 480d18051870e8e2a5f55237a2c11fde75f46082639Jeff Brown memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union 4817901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown eventItem.events = epollEvents; 4827901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown eventItem.data.fd = fd; 4837901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 4847901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown ssize_t requestIndex = mRequests.indexOfKey(fd); 4857901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (requestIndex < 0) { 4867901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem); 4877901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (epollResult < 0) { 4887901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Error adding epoll events for fd %d, errno=%d", fd, errno); 4897901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 4907901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 4917901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mRequests.add(fd, request); 4927901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } else { 4937901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem); 4947901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (epollResult < 0) { 4957901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno); 4967901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 4977901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 4987901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mRequests.replaceValueAt(requestIndex, request); 4997901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 5007901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } // release lock 5018d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#else 5028d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown int pollEvents = 0; 5038d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (events & ALOOPER_EVENT_INPUT) pollEvents |= POLLIN; 5048d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (events & ALOOPER_EVENT_OUTPUT) pollEvents |= POLLOUT; 5058d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5068d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown wakeAndLock(); // acquire lock 5078d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5088d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown struct pollfd requestedFd; 5098d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown requestedFd.fd = fd; 5108d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown requestedFd.events = pollEvents; 5118d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5128d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown Request request; 5138d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown request.fd = fd; 5148d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown request.ident = ident; 5158d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown request.callback = callback; 5168d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown request.data = data; 5178d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown ssize_t index = getRequestIndexLocked(fd); 5188d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (index < 0) { 5198d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mRequestedFds.push(requestedFd); 5208d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mRequests.push(request); 5218d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } else { 5228d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mRequestedFds.replaceAt(requestedFd, size_t(index)); 5238d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mRequests.replaceAt(request, size_t(index)); 5248d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 5258d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5268d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mLock.unlock(); // release lock 5278d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 5287901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return 1; 5297901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 5307901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 5317901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brownint Looper::removeFd(int fd) { 5327901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#if DEBUG_CALLBACKS 5337901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGD("%p ~ removeFd - fd=%d", this, fd); 5347901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown#endif 5357901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 5368d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifdef LOOPER_USES_EPOLL 5377901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown { // acquire lock 5387901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown AutoMutex _l(mLock); 5397901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown ssize_t requestIndex = mRequests.indexOfKey(fd); 5407901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (requestIndex < 0) { 5417901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return 0; 5427901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 5437901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 5447901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL); 5457901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown if (epollResult < 0) { 5467901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown LOGE("Error removing epoll events for fd %d, errno=%d", fd, errno); 5477901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return -1; 5487901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown } 5497901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 5507901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown mRequests.removeItemsAt(requestIndex); 5518d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } // release lock 5527901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown return 1; 5538d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#else 5548d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown wakeAndLock(); // acquire lock 5558d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5568d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown ssize_t index = getRequestIndexLocked(fd); 5578d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (index >= 0) { 5588d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mRequestedFds.removeAt(size_t(index)); 5598d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mRequests.removeAt(size_t(index)); 5608d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 5618d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5628d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mLock.unlock(); // release lock 5638d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown return index >= 0; 5648d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 5657901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} 5667901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown 5678d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#ifndef LOOPER_USES_EPOLL 5688d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brownssize_t Looper::getRequestIndexLocked(int fd) { 5698d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown size_t requestCount = mRequestedFds.size(); 5708d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5718d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown for (size_t i = 0; i < requestCount; i++) { 5728d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (mRequestedFds.itemAt(i).fd == fd) { 5738d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown return i; 5748d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 5758d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 5768d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5778d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown return -1; 5788d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown} 5798d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5808d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brownvoid Looper::wakeAndLock() { 5818d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mLock.lock(); 5828d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5838d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mWaiters += 1; 5848d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown while (mPolling) { 5858d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown wake(); 5868d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mAwake.wait(mLock); 5878d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 5888d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5898d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mWaiters -= 1; 5908d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown if (mWaiters == 0) { 5918d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown mResume.signal(); 5928d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown } 5938d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown} 5948d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown#endif 5958d15c74d50fd01d6e63970aadd261a9d3bed27e7Jeff Brown 5967901eb25c60b1df00050d6c3772505d8dcfcdab9Jeff Brown} // namespace android 597