| /** @file | |
| A brief file description | |
| @section license License | |
| Licensed to the Apache Software Foundation (ASF) under one | |
| or more contributor license agreements. See the NOTICE file | |
| distributed with this work for additional information | |
| regarding copyright ownership. The ASF licenses this file | |
| to you under the Apache License, Version 2.0 (the | |
| "License"); you may not use this file except in compliance | |
| with the License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| See the License for the specific language governing permissions and | |
| limitations under the License. | |
| */ | |
| #include "iocore/net/EventIO.h" | |
| #include "tscore/ink_assert.h" | |
| #include "P_UnixPollDescriptor.h" | |
| int | |
| EventIO::start_common(EventLoop l, int afd, int e) | |
| { | |
| if (!this->syscall) { | |
| return 0; | |
| } | |
| fd = afd; | |
| event_loop = l; | |
| #if TS_USE_EPOLL | |
| struct epoll_event ev; | |
| memset(&ev, 0, sizeof(ev)); | |
| ev.events = e | EPOLLEXCLUSIVE; | |
| ev.data.ptr = this; | |
| #ifndef USE_EDGE_TRIGGER | |
| events = e; | |
| #endif | |
| return epoll_ctl(event_loop->epoll_fd, EPOLL_CTL_ADD, fd, &ev); | |
| #endif | |
| #if TS_USE_KQUEUE | |
| events = e; | |
| struct kevent ev[2]; | |
| int n = 0; | |
| if (e & EVENTIO_READ) { | |
| EV_SET(&ev[n++], fd, EVFILT_READ, EV_ADD | INK_EV_EDGE_TRIGGER, 0, 0, this); | |
| } | |
| if (e & EVENTIO_WRITE) { | |
| EV_SET(&ev[n++], fd, EVFILT_WRITE, EV_ADD | INK_EV_EDGE_TRIGGER, 0, 0, this); | |
| } | |
| return kevent(l->kqueue_fd, &ev[0], n, nullptr, 0, nullptr); | |
| #endif | |
| } | |
| int | |
| EventIO::modify(int e) | |
| { | |
| if (!this->syscall) { | |
| return 0; | |
| } | |
| ink_assert(event_loop); | |
| #if TS_USE_EPOLL && !defined(USE_EDGE_TRIGGER) | |
| struct epoll_event ev; | |
| memset(&ev, 0, sizeof(ev)); | |
| int new_events = events, old_events = events; | |
| if (e < 0) | |
| new_events &= ~(-e); | |
| else | |
| new_events |= e; | |
| events = new_events; | |
| ev.events = new_events; | |
| ev.data.ptr = this; | |
| if (!new_events) | |
| return epoll_ctl(event_loop->epoll_fd, EPOLL_CTL_DEL, fd, &ev); | |
| else if (!old_events) | |
| return epoll_ctl(event_loop->epoll_fd, EPOLL_CTL_ADD, fd, &ev); | |
| else | |
| return epoll_ctl(event_loop->epoll_fd, EPOLL_CTL_MOD, fd, &ev); | |
| #endif | |
| #if TS_USE_KQUEUE && !defined(USE_EDGE_TRIGGER) | |
| int n = 0; | |
| struct kevent ev[2]; | |
| int ee = events; | |
| if (e < 0) { | |
| ee &= ~(-e); | |
| if ((-e) & EVENTIO_READ) | |
| EV_SET(&ev[n++], fd, EVFILT_READ, EV_DELETE, 0, 0, this); | |
| if ((-e) & EVENTIO_WRITE) | |
| EV_SET(&ev[n++], fd, EVFILT_WRITE, EV_DELETE, 0, 0, this); | |
| } else { | |
| ee |= e; | |
| if (e & EVENTIO_READ) | |
| EV_SET(&ev[n++], fd, EVFILT_READ, EV_ADD | INK_EV_EDGE_TRIGGER, 0, 0, this); | |
| if (e & EVENTIO_WRITE) | |
| EV_SET(&ev[n++], fd, EVFILT_WRITE, EV_ADD | INK_EV_EDGE_TRIGGER, 0, 0, this); | |
| } | |
| events = ee; | |
| if (n) | |
| return kevent(event_loop->kqueue_fd, &ev[0], n, nullptr, 0, nullptr); | |
| else | |
| return 0; | |
| #endif | |
| (void)e; // ATS_UNUSED | |
| return 0; | |
| } | |
| int | |
| EventIO::refresh(int e) | |
| { | |
| if (!this->syscall) { | |
| return 0; | |
| } | |
| ink_assert(event_loop); | |
| #if TS_USE_KQUEUE && defined(USE_EDGE_TRIGGER) | |
| e = e & events; | |
| struct kevent ev[2]; | |
| int n = 0; | |
| if (e & EVENTIO_READ) { | |
| EV_SET(&ev[n++], fd, EVFILT_READ, EV_ADD | INK_EV_EDGE_TRIGGER, 0, 0, this); | |
| } | |
| if (e & EVENTIO_WRITE) { | |
| EV_SET(&ev[n++], fd, EVFILT_WRITE, EV_ADD | INK_EV_EDGE_TRIGGER, 0, 0, this); | |
| } | |
| if (n) { | |
| return kevent(event_loop->kqueue_fd, &ev[0], n, nullptr, 0, nullptr); | |
| } else { | |
| return 0; | |
| } | |
| #endif | |
| (void)e; // ATS_UNUSED | |
| return 0; | |
| } | |
| int | |
| EventIO::stop() | |
| { | |
| if (!this->syscall) { | |
| return 0; | |
| } | |
| if (event_loop) { | |
| int retval = 0; | |
| #if TS_USE_EPOLL | |
| struct epoll_event ev; | |
| memset(&ev, 0, sizeof(struct epoll_event)); | |
| ev.events = EPOLLIN | EPOLLOUT | EPOLLET; | |
| retval = epoll_ctl(event_loop->epoll_fd, EPOLL_CTL_DEL, fd, &ev); | |
| #endif | |
| event_loop = nullptr; | |
| return retval; | |
| } | |
| return 0; | |
| } |