blob: 18f858b4b6896c22fe7cdc346880fb5ba3968669 [file] [log] [blame]
Jeff Brown4fe6c3e2010-09-13 23:17:30 -07001//
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>
Jeff Brown05dc66a2011-03-02 14:41:58 -080022#include <limits.h>
Jeff Brown4fe6c3e2010-09-13 23:17:30 -070023
24
25namespace android {
26
Jeff Brown05dc66a2011-03-02 14:41:58 -080027// --- WeakMessageHandler ---
28
29WeakMessageHandler::WeakMessageHandler(const wp<MessageHandler>& handler) :
30 mHandler(handler) {
31}
32
33void WeakMessageHandler::handleMessage(const Message& message) {
34 sp<MessageHandler> handler = mHandler.promote();
35 if (handler != NULL) {
36 handler->handleMessage(message);
37 }
38}
39
40
41// --- Looper ---
42
Jeff Brown415d8c32010-10-05 15:35:37 -070043#ifdef LOOPER_USES_EPOLL
Jeff Brown4fe6c3e2010-09-13 23:17:30 -070044// Hint for number of file descriptors to be associated with the epoll instance.
45static const int EPOLL_SIZE_HINT = 8;
46
47// Maximum number of file descriptors for which to retrieve poll events each iteration.
48static const int EPOLL_MAX_EVENTS = 16;
Jeff Brown415d8c32010-10-05 15:35:37 -070049#endif
Jeff Brown4fe6c3e2010-09-13 23:17:30 -070050
Jeff Brown134b4ae2010-09-21 15:11:18 -070051static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
52static pthread_key_t gTLSKey = 0;
53
Jeff Brown4fe6c3e2010-09-13 23:17:30 -070054Looper::Looper(bool allowNonCallbacks) :
Jeff Brown05dc66a2011-03-02 14:41:58 -080055 mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
56 mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -070057 int wakeFds[2];
58 int result = pipe(wakeFds);
59 LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
60
61 mWakeReadPipeFd = wakeFds[0];
62 mWakeWritePipeFd = wakeFds[1];
63
64 result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
65 LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
66 errno);
67
68 result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
69 LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
70 errno);
71
Jeff Brown415d8c32010-10-05 15:35:37 -070072#ifdef LOOPER_USES_EPOLL
73 // Allocate the epoll instance and register the wake pipe.
74 mEpollFd = epoll_create(EPOLL_SIZE_HINT);
75 LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
76
Jeff Brown4fe6c3e2010-09-13 23:17:30 -070077 struct epoll_event eventItem;
Jeff Brown134b4ae2010-09-21 15:11:18 -070078 memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
Jeff Brown4fe6c3e2010-09-13 23:17:30 -070079 eventItem.events = EPOLLIN;
80 eventItem.data.fd = mWakeReadPipeFd;
81 result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
82 LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
83 errno);
Jeff Brown415d8c32010-10-05 15:35:37 -070084#else
85 // Add the wake pipe to the head of the request list with a null callback.
86 struct pollfd requestedFd;
87 requestedFd.fd = mWakeReadPipeFd;
88 requestedFd.events = POLLIN;
89 mRequestedFds.push(requestedFd);
90
91 Request request;
92 request.fd = mWakeReadPipeFd;
93 request.callback = NULL;
94 request.ident = 0;
95 request.data = NULL;
96 mRequests.push(request);
97
98 mPolling = false;
99 mWaiters = 0;
100#endif
101
102#ifdef LOOPER_STATISTICS
103 mPendingWakeTime = -1;
104 mPendingWakeCount = 0;
105 mSampledWakeCycles = 0;
106 mSampledWakeCountSum = 0;
107 mSampledWakeLatencySum = 0;
108
109 mSampledPolls = 0;
110 mSampledZeroPollCount = 0;
111 mSampledZeroPollLatencySum = 0;
112 mSampledTimeoutPollCount = 0;
113 mSampledTimeoutPollLatencySum = 0;
114#endif
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700115}
116
117Looper::~Looper() {
118 close(mWakeReadPipeFd);
119 close(mWakeWritePipeFd);
Jeff Brown415d8c32010-10-05 15:35:37 -0700120#ifdef LOOPER_USES_EPOLL
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700121 close(mEpollFd);
Jeff Brown415d8c32010-10-05 15:35:37 -0700122#endif
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700123}
124
Jeff Brown134b4ae2010-09-21 15:11:18 -0700125void Looper::initTLSKey() {
126 int result = pthread_key_create(& gTLSKey, threadDestructor);
127 LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
128}
129
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700130void Looper::threadDestructor(void *st) {
131 Looper* const self = static_cast<Looper*>(st);
132 if (self != NULL) {
133 self->decStrong((void*)threadDestructor);
134 }
135}
136
137void Looper::setForThread(const sp<Looper>& looper) {
138 sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
139
140 if (looper != NULL) {
141 looper->incStrong((void*)threadDestructor);
142 }
143
Jeff Brown134b4ae2010-09-21 15:11:18 -0700144 pthread_setspecific(gTLSKey, looper.get());
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700145
146 if (old != NULL) {
147 old->decStrong((void*)threadDestructor);
148 }
149}
150
151sp<Looper> Looper::getForThread() {
Jeff Brown134b4ae2010-09-21 15:11:18 -0700152 int result = pthread_once(& gTLSOnce, initTLSKey);
153 LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700154
Jeff Brown134b4ae2010-09-21 15:11:18 -0700155 return (Looper*)pthread_getspecific(gTLSKey);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700156}
157
158sp<Looper> Looper::prepare(int opts) {
159 bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS;
160 sp<Looper> looper = Looper::getForThread();
161 if (looper == NULL) {
162 looper = new Looper(allowNonCallbacks);
163 Looper::setForThread(looper);
164 }
165 if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
166 LOGW("Looper already prepared for this thread with a different value for the "
167 "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
168 }
169 return looper;
170}
171
172bool Looper::getAllowNonCallbacks() const {
173 return mAllowNonCallbacks;
174}
175
176int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
177 int result = 0;
178 for (;;) {
179 while (mResponseIndex < mResponses.size()) {
180 const Response& response = mResponses.itemAt(mResponseIndex++);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800181 ALooper_callbackFunc callback = response.request.callback;
182 if (!callback) {
183 int ident = response.request.ident;
184 int fd = response.request.fd;
185 int events = response.events;
186 void* data = response.request.data;
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700187#if DEBUG_POLL_AND_WAKE
188 LOGD("%p ~ pollOnce - returning signalled identifier %d: "
Jeff Brown05dc66a2011-03-02 14:41:58 -0800189 "fd=%d, events=0x%x, data=%p",
190 this, ident, fd, events, data);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700191#endif
Jeff Brown05dc66a2011-03-02 14:41:58 -0800192 if (outFd != NULL) *outFd = fd;
193 if (outEvents != NULL) *outEvents = events;
194 if (outData != NULL) *outData = data;
195 return ident;
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700196 }
197 }
198
199 if (result != 0) {
200#if DEBUG_POLL_AND_WAKE
201 LOGD("%p ~ pollOnce - returning result %d", this, result);
202#endif
203 if (outFd != NULL) *outFd = 0;
204 if (outEvents != NULL) *outEvents = NULL;
205 if (outData != NULL) *outData = NULL;
206 return result;
207 }
208
209 result = pollInner(timeoutMillis);
210 }
211}
212
213int Looper::pollInner(int timeoutMillis) {
214#if DEBUG_POLL_AND_WAKE
215 LOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
216#endif
Jeff Brown415d8c32010-10-05 15:35:37 -0700217
Jeff Brown05dc66a2011-03-02 14:41:58 -0800218 // Adjust the timeout based on when the next message is due.
219 if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
220 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
221 if (mNextMessageUptime <= now) {
222 timeoutMillis = 0;
223 } else {
224 uint64_t delay = (mNextMessageUptime - now + 999999LL) / 1000000LL;
225 if (delay < INT_MAX
226 && (timeoutMillis < 0 || int(delay) < timeoutMillis)) {
227 timeoutMillis = int(delay);
228 }
229 }
230#if DEBUG_POLL_AND_WAKE
231 LOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
232 this, mNextMessageUptime - now, timeoutMillis);
233#endif
234 }
235
236 // Poll.
Jeff Brown415d8c32010-10-05 15:35:37 -0700237 int result = ALOOPER_POLL_WAKE;
238 mResponses.clear();
239 mResponseIndex = 0;
240
241#ifdef LOOPER_STATISTICS
242 nsecs_t pollStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
243#endif
244
245#ifdef LOOPER_USES_EPOLL
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700246 struct epoll_event eventItems[EPOLL_MAX_EVENTS];
247 int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
Jeff Brown415d8c32010-10-05 15:35:37 -0700248#else
249 // Wait for wakeAndLock() waiters to run then set mPolling to true.
250 mLock.lock();
251 while (mWaiters != 0) {
252 mResume.wait(mLock);
253 }
254 mPolling = true;
255 mLock.unlock();
256
257 size_t requestedCount = mRequestedFds.size();
258 int eventCount = poll(mRequestedFds.editArray(), requestedCount, timeoutMillis);
259#endif
260
Jeff Brown05dc66a2011-03-02 14:41:58 -0800261 // Acquire lock.
262 mLock.lock();
263
264 // Check for poll error.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700265 if (eventCount < 0) {
Jeff Brown7dae0e42010-09-16 17:04:52 -0700266 if (errno == EINTR) {
Jeff Brown415d8c32010-10-05 15:35:37 -0700267 goto Done;
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700268 }
Jeff Brown7dae0e42010-09-16 17:04:52 -0700269 LOGW("Poll failed with an unexpected error, errno=%d", errno);
Jeff Brown415d8c32010-10-05 15:35:37 -0700270 result = ALOOPER_POLL_ERROR;
271 goto Done;
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700272 }
273
Jeff Brown05dc66a2011-03-02 14:41:58 -0800274 // Check for poll timeout.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700275 if (eventCount == 0) {
276#if DEBUG_POLL_AND_WAKE
277 LOGD("%p ~ pollOnce - timeout", this);
278#endif
Jeff Brown415d8c32010-10-05 15:35:37 -0700279 result = ALOOPER_POLL_TIMEOUT;
280 goto Done;
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700281 }
282
Jeff Brown05dc66a2011-03-02 14:41:58 -0800283 // Handle all events.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700284#if DEBUG_POLL_AND_WAKE
285 LOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
286#endif
Jeff Brown415d8c32010-10-05 15:35:37 -0700287
288#ifdef LOOPER_USES_EPOLL
Jeff Brown96049872010-09-17 17:01:23 -0700289 for (int i = 0; i < eventCount; i++) {
290 int fd = eventItems[i].data.fd;
291 uint32_t epollEvents = eventItems[i].events;
292 if (fd == mWakeReadPipeFd) {
293 if (epollEvents & EPOLLIN) {
Jeff Brown415d8c32010-10-05 15:35:37 -0700294 awoken();
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700295 } else {
Jeff Brown96049872010-09-17 17:01:23 -0700296 LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
297 }
298 } else {
Jeff Brown96049872010-09-17 17:01:23 -0700299 ssize_t requestIndex = mRequests.indexOfKey(fd);
300 if (requestIndex >= 0) {
301 int events = 0;
302 if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
303 if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
304 if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
305 if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
Jeff Brown415d8c32010-10-05 15:35:37 -0700306 pushResponse(events, mRequests.valueAt(requestIndex));
Jeff Brown96049872010-09-17 17:01:23 -0700307 } else {
308 LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
309 "no longer registered.", epollEvents, fd);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700310 }
311 }
312 }
Jeff Brown415d8c32010-10-05 15:35:37 -0700313Done: ;
314#else
315 for (size_t i = 0; i < requestedCount; i++) {
316 const struct pollfd& requestedFd = mRequestedFds.itemAt(i);
317
318 short pollEvents = requestedFd.revents;
319 if (pollEvents) {
320 if (requestedFd.fd == mWakeReadPipeFd) {
321 if (pollEvents & POLLIN) {
322 awoken();
323 } else {
324 LOGW("Ignoring unexpected poll events 0x%x on wake read pipe.", pollEvents);
325 }
326 } else {
327 int events = 0;
328 if (pollEvents & POLLIN) events |= ALOOPER_EVENT_INPUT;
329 if (pollEvents & POLLOUT) events |= ALOOPER_EVENT_OUTPUT;
330 if (pollEvents & POLLERR) events |= ALOOPER_EVENT_ERROR;
331 if (pollEvents & POLLHUP) events |= ALOOPER_EVENT_HANGUP;
332 if (pollEvents & POLLNVAL) events |= ALOOPER_EVENT_INVALID;
333 pushResponse(events, mRequests.itemAt(i));
334 }
335 if (--eventCount == 0) {
336 break;
337 }
338 }
339 }
Jeff Brown415d8c32010-10-05 15:35:37 -0700340Done:
341 // Set mPolling to false and wake up the wakeAndLock() waiters.
Jeff Brown415d8c32010-10-05 15:35:37 -0700342 mPolling = false;
343 if (mWaiters != 0) {
344 mAwake.broadcast();
345 }
Jeff Brown415d8c32010-10-05 15:35:37 -0700346#endif
347
348#ifdef LOOPER_STATISTICS
349 nsecs_t pollEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
350 mSampledPolls += 1;
351 if (timeoutMillis == 0) {
352 mSampledZeroPollCount += 1;
353 mSampledZeroPollLatencySum += pollEndTime - pollStartTime;
354 } else if (timeoutMillis > 0 && result == ALOOPER_POLL_TIMEOUT) {
355 mSampledTimeoutPollCount += 1;
356 mSampledTimeoutPollLatencySum += pollEndTime - pollStartTime
357 - milliseconds_to_nanoseconds(timeoutMillis);
358 }
359 if (mSampledPolls == SAMPLED_POLLS_TO_AGGREGATE) {
360 LOGD("%p ~ poll latency statistics: %0.3fms zero timeout, %0.3fms non-zero timeout", this,
361 0.000001f * float(mSampledZeroPollLatencySum) / mSampledZeroPollCount,
362 0.000001f * float(mSampledTimeoutPollLatencySum) / mSampledTimeoutPollCount);
363 mSampledPolls = 0;
364 mSampledZeroPollCount = 0;
365 mSampledZeroPollLatencySum = 0;
366 mSampledTimeoutPollCount = 0;
367 mSampledTimeoutPollLatencySum = 0;
368 }
369#endif
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700370
Jeff Brown05dc66a2011-03-02 14:41:58 -0800371 // Invoke pending message callbacks.
372 mNextMessageUptime = LLONG_MAX;
373 while (mMessageEnvelopes.size() != 0) {
374 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
375 const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
376 if (messageEnvelope.uptime <= now) {
377 // Remove the envelope from the list.
378 // We keep a strong reference to the handler until the call to handleMessage
379 // finishes. Then we drop it so that the handler can be deleted *before*
380 // we reacquire our lock.
381 { // obtain handler
382 sp<MessageHandler> handler = messageEnvelope.handler;
383 Message message = messageEnvelope.message;
384 mMessageEnvelopes.removeAt(0);
385 mSendingMessage = true;
386 mLock.unlock();
387
388#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
389 LOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
390 this, handler.get(), message.what);
391#endif
392 handler->handleMessage(message);
393 } // release handler
394
395 mLock.lock();
396 mSendingMessage = false;
397 result = ALOOPER_POLL_CALLBACK;
398 } else {
399 // The last message left at the head of the queue determines the next wakeup time.
400 mNextMessageUptime = messageEnvelope.uptime;
401 break;
402 }
403 }
404
405 // Release lock.
406 mLock.unlock();
407
408 // Invoke all response callbacks.
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700409 for (size_t i = 0; i < mResponses.size(); i++) {
410 const Response& response = mResponses.itemAt(i);
Jeff Brown05dc66a2011-03-02 14:41:58 -0800411 ALooper_callbackFunc callback = response.request.callback;
412 if (callback) {
413 int fd = response.request.fd;
414 int events = response.events;
415 void* data = response.request.data;
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700416#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
Jeff Brown05dc66a2011-03-02 14:41:58 -0800417 LOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
418 this, callback, fd, events, data);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700419#endif
Jeff Brown05dc66a2011-03-02 14:41:58 -0800420 int callbackResult = callback(fd, events, data);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700421 if (callbackResult == 0) {
Jeff Brown05dc66a2011-03-02 14:41:58 -0800422 removeFd(fd);
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700423 }
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700424 result = ALOOPER_POLL_CALLBACK;
425 }
426 }
427 return result;
428}
429
430int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
431 if (timeoutMillis <= 0) {
432 int result;
433 do {
434 result = pollOnce(timeoutMillis, outFd, outEvents, outData);
435 } while (result == ALOOPER_POLL_CALLBACK);
436 return result;
437 } else {
438 nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
439 + milliseconds_to_nanoseconds(timeoutMillis);
440
441 for (;;) {
442 int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
443 if (result != ALOOPER_POLL_CALLBACK) {
444 return result;
445 }
446
447 nsecs_t timeoutNanos = endTime - systemTime(SYSTEM_TIME_MONOTONIC);
448 if (timeoutNanos <= 0) {
449 return ALOOPER_POLL_TIMEOUT;
450 }
451
452 timeoutMillis = int(nanoseconds_to_milliseconds(timeoutNanos + 999999LL));
453 }
454 }
455}
456
457void Looper::wake() {
458#if DEBUG_POLL_AND_WAKE
459 LOGD("%p ~ wake", this);
460#endif
461
Jeff Brown415d8c32010-10-05 15:35:37 -0700462#ifdef LOOPER_STATISTICS
463 // FIXME: Possible race with awoken() but this code is for testing only and is rarely enabled.
464 if (mPendingWakeCount++ == 0) {
465 mPendingWakeTime = systemTime(SYSTEM_TIME_MONOTONIC);
466 }
467#endif
468
Jeff Brown7dae0e42010-09-16 17:04:52 -0700469 ssize_t nWrite;
470 do {
471 nWrite = write(mWakeWritePipeFd, "W", 1);
472 } while (nWrite == -1 && errno == EINTR);
473
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700474 if (nWrite != 1) {
475 if (errno != EAGAIN) {
476 LOGW("Could not write wake signal, errno=%d", errno);
477 }
478 }
479}
480
Jeff Brown415d8c32010-10-05 15:35:37 -0700481void Looper::awoken() {
482#if DEBUG_POLL_AND_WAKE
483 LOGD("%p ~ awoken", this);
484#endif
485
486#ifdef LOOPER_STATISTICS
487 if (mPendingWakeCount == 0) {
488 LOGD("%p ~ awoken: spurious!", this);
489 } else {
490 mSampledWakeCycles += 1;
491 mSampledWakeCountSum += mPendingWakeCount;
492 mSampledWakeLatencySum += systemTime(SYSTEM_TIME_MONOTONIC) - mPendingWakeTime;
493 mPendingWakeCount = 0;
494 mPendingWakeTime = -1;
495 if (mSampledWakeCycles == SAMPLED_WAKE_CYCLES_TO_AGGREGATE) {
496 LOGD("%p ~ wake statistics: %0.3fms wake latency, %0.3f wakes per cycle", this,
497 0.000001f * float(mSampledWakeLatencySum) / mSampledWakeCycles,
498 float(mSampledWakeCountSum) / mSampledWakeCycles);
499 mSampledWakeCycles = 0;
500 mSampledWakeCountSum = 0;
501 mSampledWakeLatencySum = 0;
502 }
503 }
504#endif
505
506 char buffer[16];
507 ssize_t nRead;
508 do {
509 nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
510 } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
511}
512
513void Looper::pushResponse(int events, const Request& request) {
514 Response response;
515 response.events = events;
516 response.request = request;
517 mResponses.push(response);
518}
519
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700520int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) {
521#if DEBUG_CALLBACKS
522 LOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
523 events, callback, data);
524#endif
525
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700526 if (! callback) {
527 if (! mAllowNonCallbacks) {
528 LOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
529 return -1;
530 }
531
532 if (ident < 0) {
533 LOGE("Invalid attempt to set NULL callback with ident <= 0.");
534 return -1;
535 }
536 }
537
Jeff Brown415d8c32010-10-05 15:35:37 -0700538#ifdef LOOPER_USES_EPOLL
539 int epollEvents = 0;
540 if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
541 if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
542
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700543 { // acquire lock
544 AutoMutex _l(mLock);
545
546 Request request;
547 request.fd = fd;
548 request.ident = ident;
549 request.callback = callback;
550 request.data = data;
551
552 struct epoll_event eventItem;
Jeff Brown134b4ae2010-09-21 15:11:18 -0700553 memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700554 eventItem.events = epollEvents;
555 eventItem.data.fd = fd;
556
557 ssize_t requestIndex = mRequests.indexOfKey(fd);
558 if (requestIndex < 0) {
559 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
560 if (epollResult < 0) {
561 LOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
562 return -1;
563 }
564 mRequests.add(fd, request);
565 } else {
566 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
567 if (epollResult < 0) {
568 LOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
569 return -1;
570 }
571 mRequests.replaceValueAt(requestIndex, request);
572 }
573 } // release lock
Jeff Brown415d8c32010-10-05 15:35:37 -0700574#else
575 int pollEvents = 0;
576 if (events & ALOOPER_EVENT_INPUT) pollEvents |= POLLIN;
577 if (events & ALOOPER_EVENT_OUTPUT) pollEvents |= POLLOUT;
578
579 wakeAndLock(); // acquire lock
580
581 struct pollfd requestedFd;
582 requestedFd.fd = fd;
583 requestedFd.events = pollEvents;
584
585 Request request;
586 request.fd = fd;
587 request.ident = ident;
588 request.callback = callback;
589 request.data = data;
590 ssize_t index = getRequestIndexLocked(fd);
591 if (index < 0) {
592 mRequestedFds.push(requestedFd);
593 mRequests.push(request);
594 } else {
595 mRequestedFds.replaceAt(requestedFd, size_t(index));
596 mRequests.replaceAt(request, size_t(index));
597 }
598
599 mLock.unlock(); // release lock
600#endif
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700601 return 1;
602}
603
604int Looper::removeFd(int fd) {
605#if DEBUG_CALLBACKS
606 LOGD("%p ~ removeFd - fd=%d", this, fd);
607#endif
608
Jeff Brown415d8c32010-10-05 15:35:37 -0700609#ifdef LOOPER_USES_EPOLL
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700610 { // acquire lock
611 AutoMutex _l(mLock);
612 ssize_t requestIndex = mRequests.indexOfKey(fd);
613 if (requestIndex < 0) {
614 return 0;
615 }
616
617 int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
618 if (epollResult < 0) {
619 LOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
620 return -1;
621 }
622
623 mRequests.removeItemsAt(requestIndex);
Jeff Brown415d8c32010-10-05 15:35:37 -0700624 } // release lock
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700625 return 1;
Jeff Brown415d8c32010-10-05 15:35:37 -0700626#else
627 wakeAndLock(); // acquire lock
628
629 ssize_t index = getRequestIndexLocked(fd);
630 if (index >= 0) {
631 mRequestedFds.removeAt(size_t(index));
632 mRequests.removeAt(size_t(index));
633 }
634
635 mLock.unlock(); // release lock
636 return index >= 0;
637#endif
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700638}
639
Jeff Brown415d8c32010-10-05 15:35:37 -0700640#ifndef LOOPER_USES_EPOLL
641ssize_t Looper::getRequestIndexLocked(int fd) {
642 size_t requestCount = mRequestedFds.size();
643
644 for (size_t i = 0; i < requestCount; i++) {
645 if (mRequestedFds.itemAt(i).fd == fd) {
646 return i;
647 }
648 }
649
650 return -1;
651}
652
653void Looper::wakeAndLock() {
654 mLock.lock();
655
656 mWaiters += 1;
657 while (mPolling) {
658 wake();
659 mAwake.wait(mLock);
660 }
661
662 mWaiters -= 1;
663 if (mWaiters == 0) {
664 mResume.signal();
665 }
666}
667#endif
668
Jeff Brown05dc66a2011-03-02 14:41:58 -0800669void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
670 sendMessageAtTime(LLONG_MIN, handler, message);
671}
672
673void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
674 const Message& message) {
675 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
676 sendMessageAtTime(now + uptimeDelay, handler, message);
677}
678
679void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
680 const Message& message) {
681#if DEBUG_CALLBACKS
682 LOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",
683 this, uptime, handler.get(), message.what);
684#endif
685
686 size_t i = 0;
687 { // acquire lock
688 AutoMutex _l(mLock);
689
690 size_t messageCount = mMessageEnvelopes.size();
691 while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
692 i += 1;
693 }
694
695 MessageEnvelope messageEnvelope(uptime, handler, message);
696 mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
697
698 // Optimization: If the Looper is currently sending a message, then we can skip
699 // the call to wake() because the next thing the Looper will do after processing
700 // messages is to decide when the next wakeup time should be. In fact, it does
701 // not even matter whether this code is running on the Looper thread.
702 if (mSendingMessage) {
703 return;
704 }
705 } // release lock
706
707 // Wake the poll loop only when we enqueue a new message at the head.
708 if (i == 0) {
709 wake();
710 }
711}
712
713void Looper::removeMessages(const sp<MessageHandler>& handler) {
714#if DEBUG_CALLBACKS
715 LOGD("%p ~ removeMessages - handler=%p", this, handler.get());
716#endif
717
718 { // acquire lock
719 AutoMutex _l(mLock);
720
721 for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
722 const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
723 if (messageEnvelope.handler == handler) {
724 mMessageEnvelopes.removeAt(i);
725 }
726 }
727 } // release lock
728}
729
730void Looper::removeMessages(const sp<MessageHandler>& handler, int what) {
731#if DEBUG_CALLBACKS
732 LOGD("%p ~ removeMessages - handler=%p, what=%d", this, handler.get(), what);
733#endif
734
735 { // acquire lock
736 AutoMutex _l(mLock);
737
738 for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
739 const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
740 if (messageEnvelope.handler == handler
741 && messageEnvelope.message.what == what) {
742 mMessageEnvelopes.removeAt(i);
743 }
744 }
745 } // release lock
746}
747
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700748} // namespace android