devpoll.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #include "precompiled.hpp"
4 #include "devpoll.hpp"
5 #if defined ZMQ_IOTHREAD_POLLER_USE_DEVPOLL
6 
7 #include <sys/devpoll.h>
8 #include <sys/time.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <sys/ioctl.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <limits.h>
15 #include <algorithm>
16 
17 #include "devpoll.hpp"
18 #include "err.hpp"
19 #include "config.hpp"
20 #include "i_poll_events.hpp"
21 
22 zmq::devpoll_t::devpoll_t (const zmq::thread_ctx_t &ctx_) :
23  worker_poller_base_t (ctx_)
24 {
25  devpoll_fd = open ("/dev/poll", O_RDWR);
26  errno_assert (devpoll_fd != -1);
27 }
28 
29 zmq::devpoll_t::~devpoll_t ()
30 {
31  // Wait till the worker thread exits.
32  stop_worker ();
33 
34  close (devpoll_fd);
35 }
36 
37 void zmq::devpoll_t::devpoll_ctl (fd_t fd_, short events_)
38 {
39  struct pollfd pfd = {fd_, events_, 0};
40  ssize_t rc = write (devpoll_fd, &pfd, sizeof pfd);
41  zmq_assert (rc == sizeof pfd);
42 }
43 
44 zmq::devpoll_t::handle_t zmq::devpoll_t::add_fd (fd_t fd_,
45  i_poll_events *reactor_)
46 {
47  check_thread ();
48  // If the file descriptor table is too small expand it.
49  fd_table_t::size_type sz = fd_table.size ();
50  if (sz <= (fd_table_t::size_type) fd_) {
51  fd_table.resize (fd_ + 1);
52  while (sz != (fd_table_t::size_type) (fd_ + 1)) {
53  fd_table[sz].valid = false;
54  ++sz;
55  }
56  }
57 
58  zmq_assert (!fd_table[fd_].valid);
59 
60  fd_table[fd_].events = 0;
61  fd_table[fd_].reactor = reactor_;
62  fd_table[fd_].valid = true;
63  fd_table[fd_].accepted = false;
64 
65  devpoll_ctl (fd_, 0);
66  pending_list.push_back (fd_);
67 
68  // Increase the load metric of the thread.
69  adjust_load (1);
70 
71  return fd_;
72 }
73 
74 void zmq::devpoll_t::rm_fd (handle_t handle_)
75 {
76  check_thread ();
77  zmq_assert (fd_table[handle_].valid);
78 
79  devpoll_ctl (handle_, POLLREMOVE);
80  fd_table[handle_].valid = false;
81 
82  // Decrease the load metric of the thread.
83  adjust_load (-1);
84 }
85 
86 void zmq::devpoll_t::set_pollin (handle_t handle_)
87 {
88  check_thread ();
89  devpoll_ctl (handle_, POLLREMOVE);
90  fd_table[handle_].events |= POLLIN;
91  devpoll_ctl (handle_, fd_table[handle_].events);
92 }
93 
94 void zmq::devpoll_t::reset_pollin (handle_t handle_)
95 {
96  check_thread ();
97  devpoll_ctl (handle_, POLLREMOVE);
98  fd_table[handle_].events &= ~((short) POLLIN);
99  devpoll_ctl (handle_, fd_table[handle_].events);
100 }
101 
102 void zmq::devpoll_t::set_pollout (handle_t handle_)
103 {
104  check_thread ();
105  devpoll_ctl (handle_, POLLREMOVE);
106  fd_table[handle_].events |= POLLOUT;
107  devpoll_ctl (handle_, fd_table[handle_].events);
108 }
109 
110 void zmq::devpoll_t::reset_pollout (handle_t handle_)
111 {
112  check_thread ();
113  devpoll_ctl (handle_, POLLREMOVE);
114  fd_table[handle_].events &= ~((short) POLLOUT);
115  devpoll_ctl (handle_, fd_table[handle_].events);
116 }
117 
118 void zmq::devpoll_t::stop ()
119 {
120  check_thread ();
121 }
122 
123 int zmq::devpoll_t::max_fds ()
124 {
125  return -1;
126 }
127 
128 void zmq::devpoll_t::loop ()
129 {
130  while (true) {
131  struct pollfd ev_buf[max_io_events];
132  struct dvpoll poll_req;
133 
134  for (pending_list_t::size_type i = 0; i < pending_list.size (); i++)
135  fd_table[pending_list[i]].accepted = true;
136  pending_list.clear ();
137 
138  // Execute any due timers.
139  int timeout = (int) execute_timers ();
140 
141  if (get_load () == 0) {
142  if (timeout == 0)
143  break;
144 
145  // TODO sleep for timeout
146  continue;
147  }
148 
149  // Wait for events.
150  // On Solaris, we can retrieve no more then (OPEN_MAX - 1) events.
151  poll_req.dp_fds = &ev_buf[0];
152 #if defined ZMQ_HAVE_SOLARIS
153  poll_req.dp_nfds = std::min ((int) max_io_events, OPEN_MAX - 1);
154 #else
155  poll_req.dp_nfds = max_io_events;
156 #endif
157  poll_req.dp_timeout = timeout ? timeout : -1;
158  int n = ioctl (devpoll_fd, DP_POLL, &poll_req);
159  if (n == -1 && errno == EINTR)
160  continue;
161  errno_assert (n != -1);
162 
163  for (int i = 0; i < n; i++) {
164  fd_entry_t *fd_ptr = &fd_table[ev_buf[i].fd];
165  if (!fd_ptr->valid || !fd_ptr->accepted)
166  continue;
167  if (ev_buf[i].revents & (POLLERR | POLLHUP))
168  fd_ptr->reactor->in_event ();
169  if (!fd_ptr->valid || !fd_ptr->accepted)
170  continue;
171  if (ev_buf[i].revents & POLLOUT)
172  fd_ptr->reactor->out_event ();
173  if (!fd_ptr->valid || !fd_ptr->accepted)
174  continue;
175  if (ev_buf[i].revents & POLLIN)
176  fd_ptr->reactor->in_event ();
177  }
178  }
179 }
180 
181 #endif
i_poll_events.hpp
EINTR
#define EINTR
Definition: errno.hpp:7
config.hpp
precompiled.hpp
zmq_assert
#define zmq_assert(x)
Definition: err.hpp:102
errno
int errno
errno_assert
#define errno_assert(x)
Definition: err.hpp:113
devpoll.hpp
timeout
GLbitfield GLuint64 timeout
Definition: glcorearb.h:3588
n
GLdouble n
Definition: glcorearb.h:4153
i
int i
Definition: gmock-matchers_test.cc:764
zmq::thread_ctx_t
Definition: ctx.hpp:37
err.hpp
fd_t
zmq_fd_t fd_t
Definition: libzmq/tests/testutil.hpp:98
zmq::max_io_events
@ max_io_events
Definition: config.hpp:32


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:50