/* * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2020. All rights reserved. * Description: NxLooper implement * Author: NxPlayer software group * Create: 2019-08-21 */ #define LOG_TAG "NP_SysLooper" #define LOG_NDEBUG 0 #include "NxLooper.h" #include #include #include #include "NxMediaDefine.h" namespace android { const int EPOLL_MAX_FD = 8; const int EPOLL_MAX_EVENTS = 16; const int ERROR_BUFFER_LEN = 256; NxLooper::NxLooper(int idx) : m_eFd(-1), m_epFd(-1), m_inited(false), m_instIdx(idx) { HLOGD("new NxLooper"); } NxLooper::~NxLooper() { HLOGD("delete NxLooper in"); close(m_eFd); m_eFd = -1; if (m_epFd >= 0) { close(m_epFd); } HLOGD("delete NxLooper out"); } void NxLooper::Init() { HLOGD("Init in"); if (m_inited) { HLOGD("already inited"); return; } m_eFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); if (m_eFd < 0) { char errbuf[ERROR_BUFFER_LEN] = {0}; HLOGE("create event fd failed! error: %s", strerror_r(errno, errbuf, sizeof(errbuf))); return; } m_epFd = epoll_create(EPOLL_MAX_FD); char errbuf[ERROR_BUFFER_LEN] = {0}; if (m_epFd < 0) { HLOGE("create epoll failed! error: %s", strerror_r(errno, errbuf, sizeof(errbuf))); return; } struct epoll_event eventItem = {}; eventItem.data.fd = m_eFd; eventItem.events = EPOLLIN; int ret = epoll_ctl(m_epFd, EPOLL_CTL_ADD, m_eFd, &eventItem); if (ret != 0) { HLOGE("call epoll_ctl, add eventfd failed! error: %s", strerror_r(errno, errbuf, sizeof(errbuf))); return; } m_inited = true; HLOGD("Init out"); } int NxLooper::Wait(int timeoutMs) const { struct epoll_event eventItems[EPOLL_MAX_EVENTS] = {}; /* wait event wake */ int eventCount = epoll_wait(m_epFd, eventItems, EPOLL_MAX_EVENTS, timeoutMs); for (int i = 0; i < eventCount && eventCount <= EPOLL_MAX_EVENTS; i++) { if (eventItems[i].data.fd == m_eFd) { if ((eventItems[i].events & EPOLLIN) != 0) { WakeDown(); } else { HLOGW("Ignoring unexpected epoll events on wake event fd."); } } } return 0; } void NxLooper::WakeUp() const { uint64_t inc = 1; long int ret; do { ret = static_cast(write(m_eFd, &inc, sizeof(uint64_t))); } while (ret == -1 && errno == EINTR); if (ret != sizeof(uint64_t)) { if (errno != EAGAIN) { char errbuf[ERROR_BUFFER_LEN] = {0}; HLOGE("write wake signal failed! m_eFd=%d error: %s", m_eFd, strerror_r(errno, errbuf, sizeof(errbuf))); } } } void NxLooper::WakeDown() const { uint64_t counter; long long ret; do { ret = static_cast(read(m_eFd, &counter, sizeof(uint64_t))); } while (ret == -1 && errno == EINTR); if (ret != sizeof(uint64_t)) { if (errno != EAGAIN) { char errbuf[ERROR_BUFFER_LEN] = {0}; HLOGE("read signal failed! m_eFd=%d error: %s", m_eFd, strerror_r(errno, errbuf, sizeof(errbuf))); } } } }