From eb4c130ccf05799fe7c20a4737f21dd63c0dbed5 Mon Sep 17 00:00:00 2001 From: koron393 Date: Tue, 7 May 2019 02:49:25 +0900 Subject: shinano-common: libshim_camera: Update GraphicBuffer sources to Pie * Copy from Pie framework sources. Change-Id: I903eb0c3c80a752d4a8da44dec47e348c7dd23fc Signed-off-by: Nikhil Punathil --- libshims/utils/Looper.cpp | 249 +++++++++++++++++++++++++++++------------- libshims/utils/VectorImpl.cpp | 46 +++----- 2 files changed, 194 insertions(+), 101 deletions(-) (limited to 'libshims/utils') diff --git a/libshims/utils/Looper.cpp b/libshims/utils/Looper.cpp index 4bab6d5..6c57b2e 100644 --- a/libshims/utils/Looper.cpp +++ b/libshims/utils/Looper.cpp @@ -13,14 +13,8 @@ // Debugs callback registration and invocation. #define DEBUG_CALLBACKS 0 -#include #include -#include - -#include -#include -#include - +#include namespace android { @@ -68,41 +62,22 @@ static pthread_key_t gTLSKey = 0; Looper::Looper(bool allowNonCallbacks) : mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false), - mResponseIndex(0), mNextMessageUptime(LLONG_MAX) { - int wakeFds[2]; - int result = pipe(wakeFds); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); - - mWakeReadPipeFd = wakeFds[0]; - mWakeWritePipeFd = wakeFds[1]; - - result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d", - errno); - - result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", - errno); - - mPolling = false; - - // Allocate the epoll instance and register the wake pipe. - mEpollFd = epoll_create(EPOLL_SIZE_HINT); - LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); - - struct epoll_event eventItem; - memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union - eventItem.events = EPOLLIN; - eventItem.data.fd = mWakeReadPipeFd; - result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", - errno); + mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false), + mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) { + mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); + LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd: %s", + strerror(errno)); + + AutoMutex _l(mLock); + rebuildEpollLocked(); } Looper::~Looper() { - close(mWakeReadPipeFd); - close(mWakeWritePipeFd); - close(mEpollFd); + close(mWakeEventFd); + mWakeEventFd = -1; + if (mEpollFd >= 0) { + close(mEpollFd); + } } void Looper::initTLSKey() { @@ -156,6 +131,50 @@ bool Looper::getAllowNonCallbacks() const { return mAllowNonCallbacks; } +void Looper::rebuildEpollLocked() { + // Close old epoll instance if we have one. + if (mEpollFd >= 0) { +#if DEBUG_CALLBACKS + ALOGD("%p ~ rebuildEpollLocked - rebuilding epoll set", this); +#endif + close(mEpollFd); + } + + // Allocate the new epoll instance and register the wake pipe. + mEpollFd = epoll_create(EPOLL_SIZE_HINT); + LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno)); + + struct epoll_event eventItem; + memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union + eventItem.events = EPOLLIN; + eventItem.data.fd = mWakeEventFd; + int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem); + LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance: %s", + strerror(errno)); + + for (size_t i = 0; i < mRequests.size(); i++) { + const Request& request = mRequests.valueAt(i); + struct epoll_event eventItem; + request.initEventItem(&eventItem); + + int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem); + if (epollResult < 0) { + ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s", + request.fd, strerror(errno)); + } + } +} + +void Looper::scheduleEpollRebuildLocked() { + if (!mEpollRebuildRequired) { +#if DEBUG_CALLBACKS + ALOGD("%p ~ scheduleEpollRebuildLocked - scheduling epoll set rebuild", this); +#endif + mEpollRebuildRequired = true; + wake(); + } +} + int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) { int result = 0; for (;;) { @@ -206,7 +225,7 @@ int Looper::pollInner(int timeoutMillis) { timeoutMillis = messageTimeoutMillis; } #if DEBUG_POLL_AND_WAKE - ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d", + ALOGD("%p ~ pollOnce - next message in %" PRId64 "ns, adjusted timeout: timeoutMillis=%d", this, mNextMessageUptime - now, timeoutMillis); #endif } @@ -228,12 +247,19 @@ int Looper::pollInner(int timeoutMillis) { // Acquire lock. mLock.lock(); + // Rebuild epoll set if needed. + if (mEpollRebuildRequired) { + mEpollRebuildRequired = false; + rebuildEpollLocked(); + goto Done; + } + // Check for poll error. if (eventCount < 0) { if (errno == EINTR) { goto Done; } - ALOGW("Poll failed with an unexpected error, errno=%d", errno); + ALOGW("Poll failed with an unexpected error: %s", strerror(errno)); result = POLL_ERROR; goto Done; } @@ -255,11 +281,11 @@ int Looper::pollInner(int timeoutMillis) { for (int i = 0; i < eventCount; i++) { int fd = eventItems[i].data.fd; uint32_t epollEvents = eventItems[i].events; - if (fd == mWakeReadPipeFd) { + if (fd == mWakeEventFd) { if (epollEvents & EPOLLIN) { awoken(); } else { - ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents); + ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents); } } else { ssize_t requestIndex = mRequests.indexOfKey(fd); @@ -326,10 +352,14 @@ Done: ; ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p", this, response.request.callback.get(), fd, events, data); #endif + // Invoke the callback. Note that the file descriptor may be closed by + // the callback (and potentially even reused) before the function returns so + // we need to be a little careful when removing the file descriptor afterwards. int callbackResult = response.request.callback->handleEvent(fd, events, data); if (callbackResult == 0) { - removeFd(fd); + removeFd(fd, response.request.seq); } + // Clear the callback reference in the response structure promptly because we // will not clear the response vector itself until the next poll. response.request.callback.clear(); @@ -370,14 +400,12 @@ void Looper::wake() { ALOGD("%p ~ wake", this); #endif - ssize_t nWrite; - do { - nWrite = write(mWakeWritePipeFd, "W", 1); - } while (nWrite == -1 && errno == EINTR); - - if (nWrite != 1) { + uint64_t inc = 1; + ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t))); + if (nWrite != sizeof(uint64_t)) { if (errno != EAGAIN) { - ALOGW("Could not write wake signal, errno=%d", errno); + LOG_ALWAYS_FATAL("Could not write wake signal to fd %d: %s", + mWakeEventFd, strerror(errno)); } } } @@ -387,11 +415,8 @@ void Looper::awoken() { ALOGD("%p ~ awoken", this); #endif - char buffer[16]; - ssize_t nRead; - do { - nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer)); - } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer)); + uint64_t counter; + TEMP_FAILURE_RETRY(read(mWakeEventFd, &counter, sizeof(uint64_t))); } void Looper::pushResponse(int events, const Request& request) { @@ -425,37 +450,62 @@ int Looper::addFd(int fd, int ident, int events, const sp& callb ident = POLL_CALLBACK; } - int epollEvents = 0; - if (events & EVENT_INPUT) epollEvents |= EPOLLIN; - if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT; - { // acquire lock AutoMutex _l(mLock); Request request; request.fd = fd; request.ident = ident; + request.events = events; + request.seq = mNextRequestSeq++; request.callback = callback; request.data = data; + if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1 struct epoll_event eventItem; - memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union - eventItem.events = epollEvents; - eventItem.data.fd = fd; + request.initEventItem(&eventItem); ssize_t requestIndex = mRequests.indexOfKey(fd); if (requestIndex < 0) { int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem); if (epollResult < 0) { - ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno); + ALOGE("Error adding epoll events for fd %d: %s", fd, strerror(errno)); return -1; } mRequests.add(fd, request); } else { int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem); if (epollResult < 0) { - ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno); - return -1; + if (errno == ENOENT) { + // Tolerate ENOENT because it means that an older file descriptor was + // closed before its callback was unregistered and meanwhile a new + // file descriptor with the same number has been created and is now + // being registered for the first time. This error may occur naturally + // when a callback has the side-effect of closing the file descriptor + // before returning and unregistering itself. Callback sequence number + // checks further ensure that the race is benign. + // + // Unfortunately due to kernel limitations we need to rebuild the epoll + // set from scratch because it may contain an old file handle that we are + // now unable to remove since its file descriptor is no longer valid. + // No such problem would have occurred if we were using the poll system + // call instead, but that approach carries others disadvantages. +#if DEBUG_CALLBACKS + ALOGD("%p ~ addFd - EPOLL_CTL_MOD failed due to file descriptor " + "being recycled, falling back on EPOLL_CTL_ADD: %s", + this, strerror(errno)); +#endif + epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem); + if (epollResult < 0) { + ALOGE("Error modifying or adding epoll events for fd %d: %s", + fd, strerror(errno)); + return -1; + } + scheduleEpollRebuildLocked(); + } else { + ALOGE("Error modifying epoll events for fd %d: %s", fd, strerror(errno)); + return -1; + } } mRequests.replaceValueAt(requestIndex, request); } @@ -464,8 +514,12 @@ int Looper::addFd(int fd, int ident, int events, const sp& callb } int Looper::removeFd(int fd) { + return removeFd(fd, -1); +} + +int Looper::removeFd(int fd, int seq) { #if DEBUG_CALLBACKS - ALOGD("%p ~ removeFd - fd=%d", this, fd); + ALOGD("%p ~ removeFd - fd=%d, seq=%d", this, fd, seq); #endif { // acquire lock @@ -475,13 +529,48 @@ int Looper::removeFd(int fd) { return 0; } - int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL); - if (epollResult < 0) { - ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno); - return -1; + // Check the sequence number if one was given. + if (seq != -1 && mRequests.valueAt(requestIndex).seq != seq) { +#if DEBUG_CALLBACKS + ALOGD("%p ~ removeFd - sequence number mismatch, oldSeq=%d", + this, mRequests.valueAt(requestIndex).seq); +#endif + return 0; } + // Always remove the FD from the request map even if an error occurs while + // updating the epoll set so that we avoid accidentally leaking callbacks. mRequests.removeItemsAt(requestIndex); + + int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL); + if (epollResult < 0) { + if (seq != -1 && (errno == EBADF || errno == ENOENT)) { + // Tolerate EBADF or ENOENT when the sequence number is known because it + // means that the file descriptor was closed before its callback was + // unregistered. This error may occur naturally when a callback has the + // side-effect of closing the file descriptor before returning and + // unregistering itself. + // + // Unfortunately due to kernel limitations we need to rebuild the epoll + // set from scratch because it may contain an old file handle that we are + // now unable to remove since its file descriptor is no longer valid. + // No such problem would have occurred if we were using the poll system + // call instead, but that approach carries others disadvantages. +#if DEBUG_CALLBACKS + ALOGD("%p ~ removeFd - EPOLL_CTL_DEL failed due to file descriptor " + "being closed: %s", this, strerror(errno)); +#endif + scheduleEpollRebuildLocked(); + } else { + // Some other error occurred. This is really weird because it means + // our list of callbacks got out of sync with the epoll set somehow. + // We defensively rebuild the epoll set to avoid getting spurious + // notifications with nowhere to go. + ALOGE("Error removing epoll events for fd %d: %s", fd, strerror(errno)); + scheduleEpollRebuildLocked(); + return -1; + } + } } // release lock return 1; } @@ -500,7 +589,7 @@ void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp& h void Looper::sendMessageAtTime(nsecs_t uptime, const sp& handler, const Message& message) { #if DEBUG_CALLBACKS - ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d", + ALOGD("%p ~ sendMessageAtTime - uptime=%" PRId64 ", handler=%p, what=%d", this, uptime, handler.get(), message.what); #endif @@ -570,4 +659,18 @@ bool Looper::isPolling() const { return mPolling; } -} // namespace android \ No newline at end of file +void Looper::Request::initEventItem(struct epoll_event* eventItem) const { + int epollEvents = 0; + if (events & EVENT_INPUT) epollEvents |= EPOLLIN; + if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT; + + memset(eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union + eventItem->events = epollEvents; + eventItem->data.fd = fd; +} + +MessageHandler::~MessageHandler() { } + +LooperCallback::~LooperCallback() { } + +} // namespace android diff --git a/libshims/utils/VectorImpl.cpp b/libshims/utils/VectorImpl.cpp index 936cd37..ef3277f 100644 --- a/libshims/utils/VectorImpl.cpp +++ b/libshims/utils/VectorImpl.cpp @@ -16,16 +16,17 @@ #define LOG_TAG "Vector" -#include -#include +#include + #include +#include +#include #include + #include -#include -#include -#include +#include "SharedBuffer.h" /*****************************************************************************/ @@ -62,7 +63,7 @@ VectorImpl::~VectorImpl() "[%p] subclasses of VectorImpl must call finish_vector()" " in their destructor. Leaking %d bytes.", this, (int)(mCount*mItemSize)); - // We can't call _do_destroy() here because the vtable is already gone. + // We can't call _do_destroy() here because the vtable is already gone. } VectorImpl& VectorImpl::operator = (const VectorImpl& rhs) @@ -198,13 +199,16 @@ status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state) _do_copy(temp, item, 1); ssize_t j = i-1; - void* next = reinterpret_cast(array) + mItemSize*(i); + void* next = reinterpret_cast(array) + mItemSize*(i); do { _do_destroy(next, 1); _do_copy(next, curr, 1); next = curr; --j; - curr = reinterpret_cast(array) + mItemSize*(j); + curr = NULL; + if (j >= 0) { + curr = reinterpret_cast(array) + mItemSize*(j); + } } while (j>=0 && (cmp(curr, temp, state) > 0)); _do_destroy(next, 1); @@ -212,7 +216,7 @@ status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state) } i++; } - + if (temp) { _do_destroy(temp, 1); free(temp); @@ -368,7 +372,7 @@ void VectorImpl::release_storage() if (sb->release(SharedBuffer::eKeepStorage) == 1) { _do_destroy(mStorage, mCount); SharedBuffer::dealloc(sb); - } + } } } @@ -552,15 +556,6 @@ void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) con do_move_backward(dest, from, num); } -void VectorImpl::reservedVectorImpl1() { } -void VectorImpl::reservedVectorImpl2() { } -void VectorImpl::reservedVectorImpl3() { } -void VectorImpl::reservedVectorImpl4() { } -void VectorImpl::reservedVectorImpl5() { } -void VectorImpl::reservedVectorImpl6() { } -void VectorImpl::reservedVectorImpl7() { } -void VectorImpl::reservedVectorImpl8() { } - /*****************************************************************************/ SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags) @@ -596,6 +591,10 @@ size_t SortedVectorImpl::orderOf(const void* item) const ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const { + if (order) *order = 0; + if (isEmpty()) { + return NAME_NOT_FOUND; + } // binary search ssize_t err = NAME_NOT_FOUND; ssize_t l = 0; @@ -676,15 +675,6 @@ ssize_t SortedVectorImpl::remove(const void* item) return i; } -void SortedVectorImpl::reservedSortedVectorImpl1() { }; -void SortedVectorImpl::reservedSortedVectorImpl2() { }; -void SortedVectorImpl::reservedSortedVectorImpl3() { }; -void SortedVectorImpl::reservedSortedVectorImpl4() { }; -void SortedVectorImpl::reservedSortedVectorImpl5() { }; -void SortedVectorImpl::reservedSortedVectorImpl6() { }; -void SortedVectorImpl::reservedSortedVectorImpl7() { }; -void SortedVectorImpl::reservedSortedVectorImpl8() { }; - /*****************************************************************************/ }; // namespace android -- cgit v1.2.3