| /**@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/PollCont.h" | |
| #include "iocore/net/NetHandler.h" | |
| #include "P_UnixPollDescriptor.h" | |
| #include "P_Net.h" | |
| namespace | |
| { | |
| DbgCtl dbg_ctl_iocore_net_poll{"iocore_net_poll"}; | |
| DbgCtl dbg_ctl_v_iocore_net_poll{"v_iocore_net_poll"}; | |
| } // end anonymous namespace | |
| PollCont::PollCont(Ptr<ProxyMutex> &m, int pt) | |
| : Continuation(m.get()), net_handler(nullptr), nextPollDescriptor(nullptr), poll_timeout(pt) | |
| { | |
| pollDescriptor = new PollDescriptor(); | |
| SET_HANDLER(&PollCont::pollEvent); | |
| } | |
| PollCont::PollCont(Ptr<ProxyMutex> &m, NetHandler *nh, int pt) | |
| : Continuation(m.get()), net_handler(nh), nextPollDescriptor(nullptr), poll_timeout(pt) | |
| { | |
| pollDescriptor = new PollDescriptor(); | |
| SET_HANDLER(&PollCont::pollEvent); | |
| } | |
| PollCont::~PollCont() | |
| { | |
| delete pollDescriptor; | |
| if (nextPollDescriptor != nullptr) { | |
| delete nextPollDescriptor; | |
| } | |
| } | |
| // | |
| // PollCont continuation which does the epoll_wait | |
| // and stores the resultant events in ePoll_Triggered_Events | |
| // | |
| int | |
| PollCont::pollEvent(int, Event *) | |
| { | |
| this->do_poll(-1); | |
| return EVENT_CONT; | |
| } | |
| void | |
| PollCont::do_poll(ink_hrtime timeout) | |
| { | |
| if (likely(net_handler)) { | |
| /* checking to see whether there are connections on the ready_queue (either | |
| * read or write) that need processing [ebalsa] */ | |
| if (likely(!net_handler->read_ready_list.empty() || !net_handler->write_ready_list.empty() || | |
| !net_handler->read_enable_list.empty() || !net_handler->write_enable_list.empty())) { | |
| NetDbg(dbg_ctl_iocore_net_poll, "rrq: %d, wrq: %d, rel: %d, wel: %d", net_handler->read_ready_list.empty(), | |
| net_handler->write_ready_list.empty(), net_handler->read_enable_list.empty(), net_handler->write_enable_list.empty()); | |
| poll_timeout = 0; // poll immediately returns -- we have triggered stuff | |
| // to process right now | |
| } else if (timeout >= 0) { | |
| poll_timeout = ink_hrtime_to_msec(timeout); | |
| } else { | |
| poll_timeout = EThread::default_wait_interval_ms; | |
| } | |
| } | |
| // wait for fd's to trigger, or don't wait if timeout is 0 | |
| #if TS_USE_EPOLL | |
| pollDescriptor->result = | |
| epoll_wait(pollDescriptor->epoll_fd, pollDescriptor->ePoll_Triggered_Events, POLL_DESCRIPTOR_SIZE, poll_timeout); | |
| NetDbg(dbg_ctl_v_iocore_net_poll, "[PollCont::pollEvent] epoll_fd: %d, timeout: %d, results: %d", pollDescriptor->epoll_fd, | |
| poll_timeout, pollDescriptor->result); | |
| #elif TS_USE_KQUEUE | |
| struct timespec tv; | |
| tv.tv_sec = poll_timeout / 1000; | |
| tv.tv_nsec = 1000000 * (poll_timeout % 1000); | |
| pollDescriptor->result = | |
| kevent(pollDescriptor->kqueue_fd, nullptr, 0, pollDescriptor->kq_Triggered_Events, POLL_DESCRIPTOR_SIZE, &tv); | |
| NetDbg(dbg_ctl_v_iocore_net_poll, "[PollCont::pollEvent] kqueue_fd: %d, timeout: %d, results: %d", pollDescriptor->kqueue_fd, | |
| poll_timeout, pollDescriptor->result); | |
| #endif | |
| } |