• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <sys/epoll.h>
17 #include <unistd.h>
18 #include "utils_log.h"
19 #include "common_event_sys_errors.h"
20 #include "io_event_epoll.h"
21 
22 namespace OHOS {
23 namespace Utils {
IOEventEpoll()24 IOEventEpoll::IOEventEpoll()
25     : epollFd_(epoll_create1(EPOLL_CLOEXEC)), maxEvents_(EPOLL_MAX_EVENTS_INIT) {}
26 
~IOEventEpoll()27 IOEventEpoll::~IOEventEpoll()
28 {
29     CleanUp();
30 }
31 
SetUp()32 ErrCode IOEventEpoll::SetUp()
33 {
34     if (epollFd_ < 0) {
35         epollFd_ = epoll_create1(EPOLL_CLOEXEC);
36         if (epollFd_ < 0) {
37             return EVENT_SYS_ERR_BADF;
38         }
39     }
40     return EVENT_SYS_ERR_OK;
41 }
42 
CleanUp()43 void IOEventEpoll::CleanUp()
44 {
45     if (epollFd_ != IO_EVENT_INVALID_FD) {
46         if (close(epollFd_) != 0) {
47             UTILS_LOGW("%{public}s: Failed, cannot close fd: %{public}s.", __FUNCTION__, strerror(errno));
48         }
49         epollFd_ = IO_EVENT_INVALID_FD;
50     }
51 }
52 
OperateEpoll(int op,int fd,EPEventId epollEvents)53 bool IOEventEpoll::OperateEpoll(int op, int fd, EPEventId epollEvents)
54 {
55     struct epoll_event event;
56     bzero(&event, sizeof(event));
57     event.events = epollEvents;
58     event.data.fd = fd;
59 
60     if (epoll_ctl(epollFd_, op, fd, &event) != 0) {
61         UTILS_LOGE("%{public}s: Operate on epoll failed, %{public}s. epoll_fd: %{public}d , operation: %{public}d, \
62                    target fd: %{public}d", __FUNCTION__, strerror(errno), epollFd_, op, fd);
63         return false;
64     }
65 
66     switch (op) {
67         case EPOLL_CTL_ADD:
68             interestFds_.insert(fd);
69             break;
70         case EPOLL_CTL_DEL:
71             interestFds_.erase(fd);
72             break;
73         default:
74             break;
75     }
76     return true;
77 }
78 
ModifyEvents(int fd,REventId events)79 ErrCode IOEventEpoll::ModifyEvents(int fd, REventId events)
80 {
81     if (fd == -1) {
82         UTILS_LOGE("%{public}s: Failed, bad fd.", __FUNCTION__);
83         return EVENT_SYS_ERR_BADF;
84     }
85 
86     int op = EPOLL_CTL_ADD;
87     if (interestFds_.find(fd) != interestFds_.end()) {
88         if (events == Events::EVENT_NONE) {
89             op = EPOLL_CTL_DEL;
90         } else {
91             op = EPOLL_CTL_MOD;
92         }
93     }
94 
95     if (!OperateEpoll(op, fd, Reactor2Epoll(events))) {
96         UTILS_LOGE("%{public}s: Modify events failed.", __FUNCTION__);
97         return EVENT_SYS_ERR_FAILED;
98     }
99     return EVENT_SYS_ERR_OK;
100 }
101 
Polling(int timeout,std::vector<std::pair<int,REventId>> & res)102 ErrCode IOEventEpoll::Polling(int timeout /* ms */, std::vector<std::pair<int, REventId>>& res)
103 {
104     struct epoll_event epollEvents[maxEvents_];
105     int nfds = epoll_wait(epollFd_, &epollEvents[0], maxEvents_, timeout);
106     if (nfds == 0) {
107         return EVENT_SYS_ERR_NOEVENT;
108     }
109     if (nfds == -1) {
110         UTILS_LOGE("%{public}s: epoll_wait() failed, %{public}s", __FUNCTION__, strerror(errno));
111         return EVENT_SYS_ERR_FAILED;
112     }
113     for (int idx = 0; idx < nfds; ++idx) {
114         res.emplace_back(std::make_pair(epollEvents[idx].data.fd, Epoll2Reactor(epollEvents[idx].events)));
115     }
116 
117     if (nfds == maxEvents_) {
118         maxEvents_ *= EXPANSION_COEFF;
119     }
120     return EVENT_SYS_ERR_OK;
121 }
122 
Epoll2Reactor(EPEventId epollEvents)123 REventId IOEventEpoll::Epoll2Reactor(EPEventId epollEvents)
124 {
125     REventId res = Events::EVENT_NONE;
126     if ((epollEvents & EPOLLHUP) && !(epollEvents & EPOLLIN)) {
127         res |= Events::EVENT_CLOSE;
128     }
129 
130     if (epollEvents & EPOLLERR) {
131         res |= Events::EVENT_ERROR;
132     }
133 
134     if (epollEvents & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) {
135         res |= Events::EVENT_READ;
136     }
137 
138     if (epollEvents & EPOLLOUT) {
139         res |= Events::EVENT_WRITE;
140     }
141 
142     return res;
143 }
144 
Reactor2Epoll(REventId reactorEvent)145 EPEventId IOEventEpoll::Reactor2Epoll(REventId reactorEvent)
146 {
147     EPEventId res = 0u;
148 
149     if (reactorEvent & Events::EVENT_READ) {
150         res |= EPOLLIN | EPOLLPRI;
151     }
152 
153     if (reactorEvent & Events::EVENT_WRITE) {
154         res |= EPOLLOUT;
155     }
156 
157     if (reactorEvent & Events::EVENT_ERROR) {
158         res |= EPOLLERR;
159     }
160 
161     return res;
162 }
163 
164 } // namespace Utils
165 } // namespace OHOS
166