1c29fa5a6Sopenharmony_ci/*
2c29fa5a6Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License.
5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at
6c29fa5a6Sopenharmony_ci *
7c29fa5a6Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8c29fa5a6Sopenharmony_ci *
9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and
13c29fa5a6Sopenharmony_ci * limitations under the License.
14c29fa5a6Sopenharmony_ci */
15c29fa5a6Sopenharmony_ci
16c29fa5a6Sopenharmony_ci#include "epoll_manager.h"
17c29fa5a6Sopenharmony_ci
18c29fa5a6Sopenharmony_ci#include <unistd.h>
19c29fa5a6Sopenharmony_ci
20c29fa5a6Sopenharmony_ci#include "devicestatus_define.h"
21c29fa5a6Sopenharmony_ci
22c29fa5a6Sopenharmony_ci#undef LOG_TAG
23c29fa5a6Sopenharmony_ci#define LOG_TAG "EpollManager"
24c29fa5a6Sopenharmony_ci
25c29fa5a6Sopenharmony_cinamespace OHOS {
26c29fa5a6Sopenharmony_cinamespace Msdp {
27c29fa5a6Sopenharmony_cinamespace DeviceStatus {
28c29fa5a6Sopenharmony_cinamespace {
29c29fa5a6Sopenharmony_ciconstexpr int32_t MAX_N_EVENTS { 64 };
30c29fa5a6Sopenharmony_ci} // namespace
31c29fa5a6Sopenharmony_ci
32c29fa5a6Sopenharmony_ciEpollManager::~EpollManager()
33c29fa5a6Sopenharmony_ci{
34c29fa5a6Sopenharmony_ci    Close();
35c29fa5a6Sopenharmony_ci}
36c29fa5a6Sopenharmony_ci
37c29fa5a6Sopenharmony_ciint32_t EpollManager::Open()
38c29fa5a6Sopenharmony_ci{
39c29fa5a6Sopenharmony_ci    if (epollFd_ != -1) {
40c29fa5a6Sopenharmony_ci        return RET_OK;
41c29fa5a6Sopenharmony_ci    }
42c29fa5a6Sopenharmony_ci    epollFd_ = ::epoll_create1(EPOLL_CLOEXEC);
43c29fa5a6Sopenharmony_ci    if (epollFd_ == -1) {
44c29fa5a6Sopenharmony_ci        FI_HILOGE("epoll_create1 failed:%{public}s", ::strerror(errno));
45c29fa5a6Sopenharmony_ci        return RET_ERR;
46c29fa5a6Sopenharmony_ci    }
47c29fa5a6Sopenharmony_ci    return RET_OK;
48c29fa5a6Sopenharmony_ci}
49c29fa5a6Sopenharmony_ci
50c29fa5a6Sopenharmony_civoid EpollManager::Close()
51c29fa5a6Sopenharmony_ci{
52c29fa5a6Sopenharmony_ci    if (epollFd_ != -1) {
53c29fa5a6Sopenharmony_ci        if (::close(epollFd_) != 0) {
54c29fa5a6Sopenharmony_ci            FI_HILOGE("close(%{public}d) failed:%{public}s", epollFd_, ::strerror(errno));
55c29fa5a6Sopenharmony_ci        }
56c29fa5a6Sopenharmony_ci        epollFd_ = -1;
57c29fa5a6Sopenharmony_ci    }
58c29fa5a6Sopenharmony_ci}
59c29fa5a6Sopenharmony_ci
60c29fa5a6Sopenharmony_ciint32_t EpollManager::Add(IEpollEventSource &source)
61c29fa5a6Sopenharmony_ci{
62c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
63c29fa5a6Sopenharmony_ci    struct epoll_event ev {};
64c29fa5a6Sopenharmony_ci    ev.events = source.GetEvents();
65c29fa5a6Sopenharmony_ci    ev.data.ptr = &source;
66c29fa5a6Sopenharmony_ci
67c29fa5a6Sopenharmony_ci    int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_ADD, source.GetFd(), &ev);
68c29fa5a6Sopenharmony_ci    if (ret != 0) {
69c29fa5a6Sopenharmony_ci        FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
70c29fa5a6Sopenharmony_ci        return RET_ERR;
71c29fa5a6Sopenharmony_ci    }
72c29fa5a6Sopenharmony_ci    return RET_OK;
73c29fa5a6Sopenharmony_ci}
74c29fa5a6Sopenharmony_ci
75c29fa5a6Sopenharmony_civoid EpollManager::Remove(IEpollEventSource &source)
76c29fa5a6Sopenharmony_ci{
77c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
78c29fa5a6Sopenharmony_ci    int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_DEL, source.GetFd(), nullptr);
79c29fa5a6Sopenharmony_ci    if (ret != 0) {
80c29fa5a6Sopenharmony_ci        FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
81c29fa5a6Sopenharmony_ci    }
82c29fa5a6Sopenharmony_ci}
83c29fa5a6Sopenharmony_ci
84c29fa5a6Sopenharmony_ciint32_t EpollManager::Update(IEpollEventSource &source)
85c29fa5a6Sopenharmony_ci{
86c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
87c29fa5a6Sopenharmony_ci    struct epoll_event ev {};
88c29fa5a6Sopenharmony_ci    ev.events = source.GetEvents();
89c29fa5a6Sopenharmony_ci    ev.data.ptr = &source;
90c29fa5a6Sopenharmony_ci
91c29fa5a6Sopenharmony_ci    int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_MOD, source.GetFd(), &ev);
92c29fa5a6Sopenharmony_ci    if (ret != 0) {
93c29fa5a6Sopenharmony_ci        FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
94c29fa5a6Sopenharmony_ci        return RET_ERR;
95c29fa5a6Sopenharmony_ci    }
96c29fa5a6Sopenharmony_ci    return RET_OK;
97c29fa5a6Sopenharmony_ci}
98c29fa5a6Sopenharmony_ci
99c29fa5a6Sopenharmony_ciint32_t EpollManager::Wait(struct epoll_event *events, int32_t maxevents)
100c29fa5a6Sopenharmony_ci{
101c29fa5a6Sopenharmony_ci    return WaitTimeout(events, maxevents, -1);
102c29fa5a6Sopenharmony_ci}
103c29fa5a6Sopenharmony_ci
104c29fa5a6Sopenharmony_ciint32_t EpollManager::WaitTimeout(struct epoll_event *events, int32_t maxevents, int32_t timeout)
105c29fa5a6Sopenharmony_ci{
106c29fa5a6Sopenharmony_ci    int32_t ret = ::epoll_wait(epollFd_, events, maxevents, timeout);
107c29fa5a6Sopenharmony_ci    if (ret < 0) {
108c29fa5a6Sopenharmony_ci        FI_HILOGE("epoll_wait failed:%{public}s", ::strerror(errno));
109c29fa5a6Sopenharmony_ci    } else if (ret == 0) {
110c29fa5a6Sopenharmony_ci        FI_HILOGE("epoll_wait timeout");
111c29fa5a6Sopenharmony_ci    }
112c29fa5a6Sopenharmony_ci    return ret;
113c29fa5a6Sopenharmony_ci}
114c29fa5a6Sopenharmony_ci
115c29fa5a6Sopenharmony_civoid EpollManager::Dispatch(const struct epoll_event &ev)
116c29fa5a6Sopenharmony_ci{
117c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
118c29fa5a6Sopenharmony_ci    if ((ev.events & EPOLLIN) == EPOLLIN) {
119c29fa5a6Sopenharmony_ci        DispatchOne(ev);
120c29fa5a6Sopenharmony_ci    } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
121c29fa5a6Sopenharmony_ci        FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
122c29fa5a6Sopenharmony_ci    }
123c29fa5a6Sopenharmony_ci}
124c29fa5a6Sopenharmony_ci
125c29fa5a6Sopenharmony_civoid EpollManager::DispatchOne(const struct epoll_event &ev)
126c29fa5a6Sopenharmony_ci{
127c29fa5a6Sopenharmony_ci    struct epoll_event evs[MAX_N_EVENTS];
128c29fa5a6Sopenharmony_ci    int32_t cnt = WaitTimeout(evs, MAX_N_EVENTS, 0);
129c29fa5a6Sopenharmony_ci
130c29fa5a6Sopenharmony_ci    for (int32_t index = 0; index < cnt; ++index) {
131c29fa5a6Sopenharmony_ci        IEpollEventSource *source = reinterpret_cast<IEpollEventSource *>(evs[index].data.ptr);
132c29fa5a6Sopenharmony_ci        CHKPC(source);
133c29fa5a6Sopenharmony_ci        if ((evs[index].events & EPOLLIN) == EPOLLIN) {
134c29fa5a6Sopenharmony_ci            source->Dispatch(evs[index]);
135c29fa5a6Sopenharmony_ci        } else if ((evs[index].events & (EPOLLHUP | EPOLLERR)) != 0) {
136c29fa5a6Sopenharmony_ci            FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
137c29fa5a6Sopenharmony_ci        }
138c29fa5a6Sopenharmony_ci    }
139c29fa5a6Sopenharmony_ci}
140c29fa5a6Sopenharmony_ci} // namespace DeviceStatus
141c29fa5a6Sopenharmony_ci} // namespace Msdp
142c29fa5a6Sopenharmony_ci} // namespace OHOS