Line data Source code
1 : /*
2 : Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3 :
4 : This file is part of libzmq, the ZeroMQ core engine in C++.
5 :
6 : libzmq is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU Lesser General Public License (LGPL) as published
8 : by the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : As a special exception, the Contributors give you permission to link
12 : this library with independent modules to produce an executable,
13 : regardless of the license terms of these independent modules, and to
14 : copy and distribute the resulting executable under terms of your choice,
15 : provided that you also meet, for each linked independent module, the
16 : terms and conditions of the license of that module. An independent
17 : module is a module which is not derived from or based on this library.
18 : If you modify this library, you must extend this exception to your
19 : version of the library.
20 :
21 : libzmq is distributed in the hope that it will be useful, but WITHOUT
22 : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 : License for more details.
25 :
26 : You should have received a copy of the GNU Lesser General Public License
27 : along with this program. If not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : #include "precompiled.hpp"
31 : #include "epoll.hpp"
32 : #if defined ZMQ_USE_EPOLL
33 :
34 : #include <sys/epoll.h>
35 : #include <stdlib.h>
36 : #include <string.h>
37 : #include <unistd.h>
38 : #include <algorithm>
39 : #include <new>
40 :
41 : #include "macros.hpp"
42 : #include "epoll.hpp"
43 : #include "err.hpp"
44 : #include "config.hpp"
45 : #include "i_poll_events.hpp"
46 :
47 1026 : zmq::epoll_t::epoll_t (const zmq::ctx_t &ctx_) :
48 : ctx(ctx_),
49 2052 : stopping (false)
50 : {
51 1026 : epoll_fd = epoll_create (1);
52 1026 : errno_assert (epoll_fd != -1);
53 1026 : }
54 :
55 4104 : zmq::epoll_t::~epoll_t ()
56 : {
57 : // Wait till the worker thread exits.
58 1026 : worker.stop ();
59 :
60 1026 : close (epoll_fd);
61 5130 : for (retired_t::iterator it = retired.begin (); it != retired.end (); ++it) {
62 0 : LIBZMQ_DELETE(*it);
63 : }
64 2052 : }
65 :
66 23116 : zmq::epoll_t::handle_t zmq::epoll_t::add_fd (fd_t fd_, i_poll_events *events_)
67 : {
68 23116 : poll_entry_t *pe = new (std::nothrow) poll_entry_t;
69 23115 : alloc_assert (pe);
70 :
71 : // The memset is not actually needed. It's here to prevent debugging
72 : // tools to complain about using uninitialised memory.
73 : memset (pe, 0, sizeof (poll_entry_t));
74 :
75 23115 : pe->fd = fd_;
76 23115 : pe->ev.events = 0;
77 23115 : pe->ev.data.ptr = pe;
78 23115 : pe->events = events_;
79 :
80 23115 : int rc = epoll_ctl (epoll_fd, EPOLL_CTL_ADD, fd_, &pe->ev);
81 23116 : errno_assert (rc != -1);
82 :
83 : // Increase the load metric of the thread.
84 23116 : adjust_load (1);
85 :
86 23116 : return pe;
87 : }
88 :
89 23112 : void zmq::epoll_t::rm_fd (handle_t handle_)
90 : {
91 23112 : poll_entry_t *pe = (poll_entry_t*) handle_;
92 23112 : int rc = epoll_ctl (epoll_fd, EPOLL_CTL_DEL, pe->fd, &pe->ev);
93 23112 : errno_assert (rc != -1);
94 23112 : pe->fd = retired_fd;
95 23112 : retired.push_back (pe);
96 :
97 : // Decrease the load metric of the thread.
98 23110 : adjust_load (-1);
99 23116 : }
100 :
101 19489 : void zmq::epoll_t::set_pollin (handle_t handle_)
102 : {
103 19489 : poll_entry_t *pe = (poll_entry_t*) handle_;
104 19489 : pe->ev.events |= EPOLLIN;
105 19489 : int rc = epoll_ctl (epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
106 19490 : errno_assert (rc != -1);
107 19490 : }
108 :
109 239 : void zmq::epoll_t::reset_pollin (handle_t handle_)
110 : {
111 239 : poll_entry_t *pe = (poll_entry_t*) handle_;
112 239 : pe->ev.events &= ~((short) EPOLLIN);
113 239 : int rc = epoll_ctl (epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
114 239 : errno_assert (rc != -1);
115 239 : }
116 :
117 22998 : void zmq::epoll_t::set_pollout (handle_t handle_)
118 : {
119 22998 : poll_entry_t *pe = (poll_entry_t*) handle_;
120 22998 : pe->ev.events |= EPOLLOUT;
121 22998 : int rc = epoll_ctl (epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
122 22997 : errno_assert (rc != -1);
123 22997 : }
124 :
125 17954 : void zmq::epoll_t::reset_pollout (handle_t handle_)
126 : {
127 17954 : poll_entry_t *pe = (poll_entry_t*) handle_;
128 17954 : pe->ev.events &= ~((short) EPOLLOUT);
129 17954 : int rc = epoll_ctl (epoll_fd, EPOLL_CTL_MOD, pe->fd, &pe->ev);
130 17956 : errno_assert (rc != -1);
131 17956 : }
132 :
133 1026 : void zmq::epoll_t::start ()
134 : {
135 1026 : ctx.start_thread (worker, worker_routine, this);
136 1026 : }
137 :
138 1026 : void zmq::epoll_t::stop ()
139 : {
140 1026 : stopping = true;
141 1026 : }
142 :
143 858 : int zmq::epoll_t::max_fds ()
144 : {
145 858 : return -1;
146 : }
147 :
148 1026 : void zmq::epoll_t::loop ()
149 : {
150 : epoll_event ev_buf [max_io_events];
151 :
152 36066 : while (!stopping) {
153 :
154 : // Execute any due timers.
155 34014 : int timeout = (int) execute_timers ();
156 :
157 : // Wait for events.
158 : int n = epoll_wait (epoll_fd, &ev_buf [0], max_io_events,
159 34018 : timeout ? timeout : -1);
160 34010 : if (n == -1) {
161 0 : errno_assert (errno == EINTR);
162 : continue;
163 : }
164 :
165 68374 : for (int i = 0; i < n; i ++) {
166 68370 : poll_entry_t *pe = ((poll_entry_t*) ev_buf [i].data.ptr);
167 :
168 68370 : if (pe->fd == retired_fd)
169 : continue;
170 67338 : if (ev_buf [i].events & (EPOLLERR | EPOLLHUP))
171 733 : pe->events->in_event ();
172 67340 : if (pe->fd == retired_fd)
173 : continue;
174 66692 : if (ev_buf [i].events & EPOLLOUT)
175 23788 : pe->events->out_event ();
176 66696 : if (pe->fd == retired_fd)
177 : continue;
178 63512 : if (ev_buf [i].events & EPOLLIN)
179 43680 : pe->events->in_event ();
180 : }
181 :
182 : // Destroy retired event sources.
183 239415 : for (retired_t::iterator it = retired.begin (); it != retired.end (); ++it) {
184 23115 : LIBZMQ_DELETE(*it);
185 : }
186 34014 : retired.clear ();
187 : }
188 1026 : }
189 :
190 1026 : void zmq::epoll_t::worker_routine (void *arg_)
191 : {
192 1026 : ((epoll_t*) arg_)->loop ();
193 1026 : }
194 :
195 : #endif
|