1 #include "epoll_event_dispatcher.h" 2 3 #include <log/log.h> 4 #include <sys/epoll.h> 5 #include <sys/eventfd.h> 6 #include <sys/prctl.h> 7 8 #include <dvr/performance_client_api.h> 9 10 namespace android { 11 namespace dvr { 12 13 EpollEventDispatcher::EpollEventDispatcher() { 14 epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC)); 15 if (!epoll_fd_) { 16 ALOGE("Failed to create epoll fd: %s", strerror(errno)); 17 return; 18 } 19 20 event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); 21 if (!event_fd_) { 22 ALOGE("Failed to create event for epolling: %s", strerror(errno)); 23 return; 24 } 25 26 // Add watch for eventfd. This should only watch for EPOLLIN, which gets set 27 // when eventfd_write occurs. Use "this" as a unique sentinal value to 28 // identify events from the event fd. 29 epoll_event event = {.events = EPOLLIN, .data = {.ptr = this}}; 30 if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, event_fd_.Get(), &event) < 0) { 31 ALOGE("Failed to add eventfd to epoll set because: %s", strerror(errno)); 32 return; 33 } 34 35 thread_ = std::thread(&EpollEventDispatcher::EventThread, this); 36 } 37 38 EpollEventDispatcher::~EpollEventDispatcher() { Stop(); } 39 40 void EpollEventDispatcher::Stop() { 41 exit_thread_.store(true); 42 eventfd_write(event_fd_.Get(), 1); 43 } 44 45 pdx::Status<void> EpollEventDispatcher::AddEventHandler(int fd, int event_mask, 46 Handler handler) { 47 std::lock_guard<std::mutex> lock(lock_); 48 49 epoll_event event; 50 event.events = event_mask; 51 event.data.ptr = &(handlers_[fd] = handler); 52 53 ALOGD_IF( 54 TRACE, 55 "EpollEventDispatcher::AddEventHandler: fd=%d event_mask=0x%x handler=%p", 56 fd, event_mask, event.data.ptr); 57 58 if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd, &event) < 0) { 59 const int error = errno; 60 ALOGE("Failed to add fd to epoll set because: %s", strerror(error)); 61 return pdx::ErrorStatus(error); 62 } else { 63 return {}; 64 } 65 } 66 67 pdx::Status<void> EpollEventDispatcher::RemoveEventHandler(int fd) { 68 ALOGD_IF(TRACE, "EpollEventDispatcher::RemoveEventHandler: fd=%d", fd); 69 std::lock_guard<std::mutex> lock(lock_); 70 71 epoll_event dummy; // See BUGS in man 2 epoll_ctl. 72 if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, fd, &dummy) < 0) { 73 const int error = errno; 74 ALOGE("Failed to remove fd from epoll set because: %s", strerror(error)); 75 return pdx::ErrorStatus(error); 76 } 77 78 // If the fd was valid above, add it to the list of ids to remove. 79 removed_handlers_.push_back(fd); 80 81 // Wake up the event thread to clean up. 82 eventfd_write(event_fd_.Get(), 1); 83 84 return {}; 85 } 86 87 void EpollEventDispatcher::EventThread() { 88 prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrEvent"), 0, 0, 0); 89 90 const int error = dvrSetSchedulerClass(0, "graphics"); 91 LOG_ALWAYS_FATAL_IF( 92 error < 0, 93 "EpollEventDispatcher::EventThread: Failed to set scheduler class: %s", 94 strerror(-error)); 95 96 const size_t kMaxNumEvents = 128; 97 epoll_event events[kMaxNumEvents]; 98 99 while (!exit_thread_.load()) { 100 const int num_events = epoll_wait(epoll_fd_.Get(), events, kMaxNumEvents, -1); 101 if (num_events < 0 && errno != EINTR) 102 break; 103 104 ALOGD_IF(TRACE > 1, "EpollEventDispatcher::EventThread: num_events=%d", 105 num_events); 106 107 for (int i = 0; i < num_events; i++) { 108 ALOGD_IF( 109 TRACE > 1, 110 "EpollEventDispatcher::EventThread: event %d: handler=%p events=0x%x", 111 i, events[i].data.ptr, events[i].events); 112 113 if (events[i].data.ptr == this) { 114 // Clear pending event on event_fd_. Serialize the read with respect to 115 // writes from other threads. 116 std::lock_guard<std::mutex> lock(lock_); 117 eventfd_t value; 118 eventfd_read(event_fd_.Get(), &value); 119 } else { 120 auto handler = reinterpret_cast<Handler*>(events[i].data.ptr); 121 if (handler) 122 (*handler)(events[i].events); 123 } 124 } 125 126 // Remove any handlers that have been posted for removal. This is done here 127 // instead of in RemoveEventHandler() to prevent races between the dispatch 128 // thread and the code requesting the removal. Handlers are guaranteed to 129 // stay alive between exiting epoll_wait() and the dispatch loop above. 130 std::lock_guard<std::mutex> lock(lock_); 131 for (auto handler_fd : removed_handlers_) { 132 ALOGD_IF(TRACE, 133 "EpollEventDispatcher::EventThread: removing handler: fd=%d", 134 handler_fd); 135 handlers_.erase(handler_fd); 136 } 137 removed_handlers_.clear(); 138 } 139 } 140 141 } // namespace dvr 142 } // namespace android 143