Looper.cpp revision ed242de3f5b709e9e0925513ab976886a04358c0
1// 2// Copyright 2010 The Android Open Source Project 3// 4// A looper implementation based on epoll(). 5// 6#define LOG_TAG "Looper" 7 8//#define LOG_NDEBUG 0 9 10// Debugs poll and wake interactions. 11#define DEBUG_POLL_AND_WAKE 0 12 13// Debugs callback registration and invocation. 14#define DEBUG_CALLBACKS 0 15 16#include <cutils/log.h> 17#include <utils/Looper.h> 18#include <utils/Timers.h> 19 20#include <unistd.h> 21#include <fcntl.h> 22#include <sys/epoll.h> 23 24 25namespace android { 26 27static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; 28static bool gHaveTLS = false; 29static pthread_key_t gTLS = 0; 30 31// Hint for number of file descriptors to be associated with the epoll instance. 32static const int EPOLL_SIZE_HINT = 8; 33 34// Maximum number of file descriptors for which to retrieve poll events each iteration. 35static const int EPOLL_MAX_EVENTS = 16; 36 37Looper::Looper(bool allowNonCallbacks) : 38 mAllowNonCallbacks(allowNonCallbacks), 39 mResponseIndex(0) { 40 mEpollFd = epoll_create(EPOLL_SIZE_HINT); 41 LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); 42 43 int wakeFds[2]; 44 int result = pipe(wakeFds); 45 LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); 46 47 mWakeReadPipeFd = wakeFds[0]; 48 mWakeWritePipeFd = wakeFds[1]; 49 50 result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); 51 LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d", 52 errno); 53 54 result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); 55 LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", 56 errno); 57 58 struct epoll_event eventItem; 59 eventItem.events = EPOLLIN; 60 eventItem.data.fd = mWakeReadPipeFd; 61 result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); 62 LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", 63 errno); 64} 65 66Looper::~Looper() { 67 close(mWakeReadPipeFd); 68 close(mWakeWritePipeFd); 69 close(mEpollFd); 70} 71 72void Looper::threadDestructor(void *st) { 73 Looper* const self = static_cast<Looper*>(st); 74 if (self != NULL) { 75 self->decStrong((void*)threadDestructor); 76 } 77} 78 79void Looper::setForThread(const sp<Looper>& looper) { 80 sp<Looper> old = getForThread(); // also has side-effect of initializing TLS 81 82 if (looper != NULL) { 83 looper->incStrong((void*)threadDestructor); 84 } 85 86 pthread_setspecific(gTLS, looper.get()); 87 88 if (old != NULL) { 89 old->decStrong((void*)threadDestructor); 90 } 91} 92 93sp<Looper> Looper::getForThread() { 94 if (!gHaveTLS) { 95 pthread_mutex_lock(&gTLSMutex); 96 if (pthread_key_create(&gTLS, threadDestructor) != 0) { 97 pthread_mutex_unlock(&gTLSMutex); 98 return NULL; 99 } 100 gHaveTLS = true; 101 pthread_mutex_unlock(&gTLSMutex); 102 } 103 104 return (Looper*)pthread_getspecific(gTLS); 105} 106 107sp<Looper> Looper::prepare(int opts) { 108 bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS; 109 sp<Looper> looper = Looper::getForThread(); 110 if (looper == NULL) { 111 looper = new Looper(allowNonCallbacks); 112 Looper::setForThread(looper); 113 } 114 if (looper->getAllowNonCallbacks() != allowNonCallbacks) { 115 LOGW("Looper already prepared for this thread with a different value for the " 116 "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option."); 117 } 118 return looper; 119} 120 121bool Looper::getAllowNonCallbacks() const { 122 return mAllowNonCallbacks; 123} 124 125int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) { 126 int result = 0; 127 for (;;) { 128 while (mResponseIndex < mResponses.size()) { 129 const Response& response = mResponses.itemAt(mResponseIndex++); 130 if (! response.request.callback) { 131#if DEBUG_POLL_AND_WAKE 132 LOGD("%p ~ pollOnce - returning signalled identifier %d: " 133 "fd=%d, events=0x%x, data=%p", this, 134 response.request.ident, response.request.fd, 135 response.events, response.request.data); 136#endif 137 if (outFd != NULL) *outFd = response.request.fd; 138 if (outEvents != NULL) *outEvents = response.events; 139 if (outData != NULL) *outData = response.request.data; 140 return response.request.ident; 141 } 142 } 143 144 if (result != 0) { 145#if DEBUG_POLL_AND_WAKE 146 LOGD("%p ~ pollOnce - returning result %d", this, result); 147#endif 148 if (outFd != NULL) *outFd = 0; 149 if (outEvents != NULL) *outEvents = NULL; 150 if (outData != NULL) *outData = NULL; 151 return result; 152 } 153 154 result = pollInner(timeoutMillis); 155 } 156} 157 158int Looper::pollInner(int timeoutMillis) { 159#if DEBUG_POLL_AND_WAKE 160 LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis); 161#endif 162 struct epoll_event eventItems[EPOLL_MAX_EVENTS]; 163 int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); 164 if (eventCount < 0) { 165 if (errno == EINTR) { 166 return ALOOPER_POLL_WAKE; 167 } 168 169 LOGW("Poll failed with an unexpected error, errno=%d", errno); 170 return ALOOPER_POLL_ERROR; 171 } 172 173 if (eventCount == 0) { 174#if DEBUG_POLL_AND_WAKE 175 LOGD("%p ~ pollOnce - timeout", this); 176#endif 177 return ALOOPER_POLL_TIMEOUT; 178 } 179 180 int result = ALOOPER_POLL_WAKE; 181 mResponses.clear(); 182 mResponseIndex = 0; 183 184#if DEBUG_POLL_AND_WAKE 185 LOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount); 186#endif 187 bool acquiredLock = false; 188 for (int i = 0; i < eventCount; i++) { 189 int fd = eventItems[i].data.fd; 190 uint32_t epollEvents = eventItems[i].events; 191 if (fd == mWakeReadPipeFd) { 192 if (epollEvents & EPOLLIN) { 193#if DEBUG_POLL_AND_WAKE 194 LOGD("%p ~ pollOnce - awoken", this); 195#endif 196 char buffer[16]; 197 ssize_t nRead; 198 do { 199 nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer)); 200 } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer)); 201 } else { 202 LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents); 203 } 204 } else { 205 if (! acquiredLock) { 206 mLock.lock(); 207 acquiredLock = true; 208 } 209 210 ssize_t requestIndex = mRequests.indexOfKey(fd); 211 if (requestIndex >= 0) { 212 int events = 0; 213 if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT; 214 if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT; 215 if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR; 216 if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP; 217 218 Response response; 219 response.events = events; 220 response.request = mRequests.valueAt(requestIndex); 221 mResponses.push(response); 222 } else { 223 LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is " 224 "no longer registered.", epollEvents, fd); 225 } 226 } 227 } 228 if (acquiredLock) { 229 mLock.unlock(); 230 } 231 232 for (size_t i = 0; i < mResponses.size(); i++) { 233 const Response& response = mResponses.itemAt(i); 234 if (response.request.callback) { 235#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS 236 LOGD("%p ~ pollOnce - invoking callback: fd=%d, events=0x%x, data=%p", this, 237 response.request.fd, response.events, response.request.data); 238#endif 239 int callbackResult = response.request.callback( 240 response.request.fd, response.events, response.request.data); 241 if (callbackResult == 0) { 242 removeFd(response.request.fd); 243 } 244 245 result = ALOOPER_POLL_CALLBACK; 246 } 247 } 248 return result; 249} 250 251int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) { 252 if (timeoutMillis <= 0) { 253 int result; 254 do { 255 result = pollOnce(timeoutMillis, outFd, outEvents, outData); 256 } while (result == ALOOPER_POLL_CALLBACK); 257 return result; 258 } else { 259 nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC) 260 + milliseconds_to_nanoseconds(timeoutMillis); 261 262 for (;;) { 263 int result = pollOnce(timeoutMillis, outFd, outEvents, outData); 264 if (result != ALOOPER_POLL_CALLBACK) { 265 return result; 266 } 267 268 nsecs_t timeoutNanos = endTime - systemTime(SYSTEM_TIME_MONOTONIC); 269 if (timeoutNanos <= 0) { 270 return ALOOPER_POLL_TIMEOUT; 271 } 272 273 timeoutMillis = int(nanoseconds_to_milliseconds(timeoutNanos + 999999LL)); 274 } 275 } 276} 277 278void Looper::wake() { 279#if DEBUG_POLL_AND_WAKE 280 LOGD("%p ~ wake", this); 281#endif 282 283 ssize_t nWrite; 284 do { 285 nWrite = write(mWakeWritePipeFd, "W", 1); 286 } while (nWrite == -1 && errno == EINTR); 287 288 if (nWrite != 1) { 289 if (errno != EAGAIN) { 290 LOGW("Could not write wake signal, errno=%d", errno); 291 } 292 } 293} 294 295int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) { 296#if DEBUG_CALLBACKS 297 LOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident, 298 events, callback, data); 299#endif 300 301 int epollEvents = 0; 302 if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN; 303 if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT; 304 if (events & ALOOPER_EVENT_ERROR) epollEvents |= EPOLLERR; 305 if (events & ALOOPER_EVENT_HANGUP) epollEvents |= EPOLLHUP; 306 307 if (epollEvents == 0) { 308 LOGE("Invalid attempt to set a callback with no selected poll events."); 309 return -1; 310 } 311 312 if (! callback) { 313 if (! mAllowNonCallbacks) { 314 LOGE("Invalid attempt to set NULL callback but not allowed for this looper."); 315 return -1; 316 } 317 318 if (ident < 0) { 319 LOGE("Invalid attempt to set NULL callback with ident <= 0."); 320 return -1; 321 } 322 } 323 324 { // acquire lock 325 AutoMutex _l(mLock); 326 327 Request request; 328 request.fd = fd; 329 request.ident = ident; 330 request.callback = callback; 331 request.data = data; 332 333 struct epoll_event eventItem; 334 eventItem.events = epollEvents; 335 eventItem.data.fd = fd; 336 337 ssize_t requestIndex = mRequests.indexOfKey(fd); 338 if (requestIndex < 0) { 339 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem); 340 if (epollResult < 0) { 341 LOGE("Error adding epoll events for fd %d, errno=%d", fd, errno); 342 return -1; 343 } 344 mRequests.add(fd, request); 345 } else { 346 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem); 347 if (epollResult < 0) { 348 LOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno); 349 return -1; 350 } 351 mRequests.replaceValueAt(requestIndex, request); 352 } 353 } // release lock 354 return 1; 355} 356 357int Looper::removeFd(int fd) { 358#if DEBUG_CALLBACKS 359 LOGD("%p ~ removeFd - fd=%d", this, fd); 360#endif 361 362 { // acquire lock 363 AutoMutex _l(mLock); 364 ssize_t requestIndex = mRequests.indexOfKey(fd); 365 if (requestIndex < 0) { 366 return 0; 367 } 368 369 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL); 370 if (epollResult < 0) { 371 LOGE("Error removing epoll events for fd %d, errno=%d", fd, errno); 372 return -1; 373 } 374 375 mRequests.removeItemsAt(requestIndex); 376 } // request lock 377 return 1; 378} 379 380} // namespace android 381