26 #include "dbus-socket-set.h"
28 #include <dbus/dbus-internals.h>
29 #include <dbus/dbus-sysdeps.h>
32 # error This file is for Linux epoll(4)
37 #include <sys/epoll.h>
40 #ifndef DOXYGEN_SHOULD_SKIP_THIS
47 static inline DBusSocketSetEpoll *
48 socket_set_epoll_cast (DBusSocketSet *set)
50 _dbus_assert (set->cls == &_dbus_socket_set_epoll_class);
51 return (DBusSocketSetEpoll *) set;
56 socket_set_epoll_free (DBusSocketSet *set)
58 DBusSocketSetEpoll *
self = socket_set_epoll_cast (set);
70 _dbus_socket_set_epoll_new (
void)
72 DBusSocketSetEpoll *
self;
79 self->parent.cls = &_dbus_socket_set_epoll_class;
81 self->epfd = epoll_create1 (EPOLL_CLOEXEC);
90 self->epfd = epoll_create (42);
92 flags = fcntl (self->epfd, F_GETFD, 0);
95 fcntl (self->epfd, F_SETFD, flags | FD_CLOEXEC);
100 socket_set_epoll_free ((DBusSocketSet *)
self);
104 return (DBusSocketSet *)
self;
108 watch_flags_to_epoll_events (
unsigned int flags)
121 epoll_events_to_watch_flags (uint32_t events)
125 if (events & EPOLLIN)
127 if (events & EPOLLOUT)
129 if (events & EPOLLHUP)
131 if (events & EPOLLERR)
138 socket_set_epoll_add (DBusSocketSet *set,
143 DBusSocketSetEpoll *
self = socket_set_epoll_cast (set);
144 struct epoll_event event;
151 event.events = watch_flags_to_epoll_events (flags);
157 event.events = EPOLLET;
160 if (epoll_ctl (self->epfd, EPOLL_CTL_ADD, fd, &event) == 0)
178 _dbus_warn (
"fd %d added and then added again\n", fd);
182 _dbus_warn (
"Misc error when trying to watch fd %d: %s\n", fd,
191 socket_set_epoll_enable (DBusSocketSet *set,
195 DBusSocketSetEpoll *
self = socket_set_epoll_cast (set);
196 struct epoll_event event;
200 event.events = watch_flags_to_epoll_events (flags);
202 if (epoll_ctl (self->epfd, EPOLL_CTL_MOD, fd, &event) == 0)
216 _dbus_warn (
"fd %d enabled before it was added\n", fd);
220 _dbus_warn (
"Insufficient memory to change watch for fd %d\n", fd);
224 _dbus_warn (
"Misc error when trying to watch fd %d: %s\n", fd,
231 socket_set_epoll_disable (DBusSocketSet *set,
234 DBusSocketSetEpoll *
self = socket_set_epoll_cast (set);
235 struct epoll_event event;
255 event.events = EPOLLET;
257 if (epoll_ctl (self->epfd, EPOLL_CTL_MOD, fd, &event) == 0)
261 _dbus_warn (
"Error when trying to watch fd %d: %s\n", fd,
266 socket_set_epoll_remove (DBusSocketSet *set,
269 DBusSocketSetEpoll *
self = socket_set_epoll_cast (set);
273 struct epoll_event dummy = { 0 };
275 if (epoll_ctl (self->epfd, EPOLL_CTL_DEL, fd, &dummy) == 0)
279 _dbus_warn (
"Error when trying to remove fd %d: %s\n", fd, strerror (err));
285 #define N_STACK_DESCRIPTORS 64
288 socket_set_epoll_poll (DBusSocketSet *set,
289 DBusSocketEvent *revents,
293 DBusSocketSetEpoll *
self = socket_set_epoll_cast (set);
294 struct epoll_event events[N_STACK_DESCRIPTORS];
300 n_ready = epoll_wait (self->epfd, events,
307 for (i = 0; i < n_ready; i++)
309 revents[i].fd = events[i].data.fd;
310 revents[i].flags = epoll_events_to_watch_flags (events[i].events);
316 DBusSocketSetClass _dbus_socket_set_epoll_class = {
317 socket_set_epoll_free,
318 socket_set_epoll_add,
319 socket_set_epoll_remove,
320 socket_set_epoll_enable,
321 socket_set_epoll_disable,
322 socket_set_epoll_poll
325 #ifdef TEST_BEHAVIOUR_OF_EPOLLET
336 #include <sys/epoll.h>
343 struct epoll_event input;
344 struct epoll_event output;
345 int epfd = epoll_create1 (EPOLL_CLOEXEC);
349 input.events = EPOLLHUP | EPOLLET;
350 ret = epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &input);
351 printf (
"ctl ADD: %d\n", ret);
353 ret = epoll_wait (epfd, &output, 1, -1);
354 printf (
"wait for HUP, edge-triggered: %d\n", ret);
356 ret = epoll_wait (epfd, &output, 1, 1);
357 printf (
"wait for HUP again: %d\n", ret);
359 input.events = EPOLLHUP;
360 ret = epoll_ctl (epfd, EPOLL_CTL_MOD, fd, &input);
361 printf (
"ctl MOD: %d\n", ret);
363 ret = epoll_wait (epfd, &output, 1, -1);
364 printf (
"wait for HUP: %d\n", ret);
#define NULL
A null pointer, defined appropriately for C or C++.
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
As in POLLERR (can't watch for this, but can be present in current state passed to dbus_watch_handle(...
#define TRUE
Expands to "1".
As in POLLHUP (can't watch for it, but can be present in current state passed to dbus_watch_handle())...
#define FALSE
Expands to "0".