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