26#include "dbus-pollable-set.h"
28#include <dbus/dbus-internals.h>
29#include <dbus/dbus-sysdeps.h>
32# error This file is for Linux epoll(4)
40#ifndef DOXYGEN_SHOULD_SKIP_THIS
43 DBusPollableSet parent;
45} DBusPollableSetEpoll;
47static inline DBusPollableSetEpoll *
48socket_set_epoll_cast (DBusPollableSet *set)
50 _dbus_assert (set->cls == &_dbus_pollable_set_epoll_class);
51 return (DBusPollableSetEpoll *) set;
56socket_set_epoll_free (DBusPollableSet *set)
58 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
70_dbus_pollable_set_epoll_new (
void)
72 DBusPollableSetEpoll *self;
74 self =
dbus_new0 (DBusPollableSetEpoll, 1);
79 self->parent.cls = &_dbus_pollable_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 ((DBusPollableSet *) self);
104 return (DBusPollableSet *) self;
108watch_flags_to_epoll_events (
unsigned int flags)
121epoll_events_to_watch_flags (uint32_t events)
125 if (events & EPOLLIN)
127 if (events & EPOLLOUT)
129 if (events & EPOLLHUP)
131 if (events & EPOLLERR)
138socket_set_epoll_add (DBusPollableSet *set,
143 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
144 struct epoll_event event;
152 event.events = watch_flags_to_epoll_events (flags);
158 event.events = EPOLLET;
161 if (epoll_ctl (self->epfd, EPOLL_CTL_ADD, fd, &event) == 0)
179 _dbus_warn (
"fd %d added and then added again", fd);
183 _dbus_warn (
"Misc error when trying to watch fd %d: %s", fd,
192socket_set_epoll_enable (DBusPollableSet *set,
196 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
197 struct epoll_event event;
202 event.events = watch_flags_to_epoll_events (flags);
204 if (epoll_ctl (self->epfd, EPOLL_CTL_MOD, fd, &event) == 0)
218 _dbus_warn (
"fd %d enabled before it was added", fd);
222 _dbus_warn (
"Insufficient memory to change watch for fd %d", fd);
226 _dbus_warn (
"Misc error when trying to watch fd %d: %s", fd,
233socket_set_epoll_disable (DBusPollableSet *set,
236 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
237 struct epoll_event event;
258 event.events = EPOLLET;
260 if (epoll_ctl (self->epfd, EPOLL_CTL_MOD, fd, &event) == 0)
264 _dbus_warn (
"Error when trying to watch fd %d: %s", fd,
269socket_set_epoll_remove (DBusPollableSet *set,
272 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
276 struct epoll_event dummy;
279 if (epoll_ctl (self->epfd, EPOLL_CTL_DEL, fd, &dummy) == 0)
283 _dbus_warn (
"Error when trying to remove fd %d: %s", fd, strerror (err));
289#define N_STACK_DESCRIPTORS 64
292socket_set_epoll_poll (DBusPollableSet *set,
293 DBusPollableEvent *revents,
297 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
298 struct epoll_event events[N_STACK_DESCRIPTORS];
304 n_ready = epoll_wait (self->epfd, events,
311 for (i = 0; i < n_ready; i++)
313 revents[i].fd = events[i].data.fd;
314 revents[i].flags = epoll_events_to_watch_flags (events[i].events);
320DBusPollableSetClass _dbus_pollable_set_epoll_class = {
321 socket_set_epoll_free,
322 socket_set_epoll_add,
323 socket_set_epoll_remove,
324 socket_set_epoll_enable,
325 socket_set_epoll_disable,
326 socket_set_epoll_poll
329#ifdef TEST_BEHAVIOUR_OF_EPOLLET
340#include <sys/epoll.h>
347 struct epoll_event input;
348 struct epoll_event output;
349 int epfd = epoll_create1 (EPOLL_CLOEXEC);
355 input.events = EPOLLHUP | EPOLLET;
356 ret = epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &input);
357 printf (
"ctl ADD: %d\n", ret);
359 ret = epoll_wait (epfd, &output, 1, -1);
360 printf (
"wait for HUP, edge-triggered: %d\n", ret);
362 ret = epoll_wait (epfd, &output, 1, 1);
363 printf (
"wait for HUP again: %d\n", ret);
365 input.events = EPOLLHUP;
366 ret = epoll_ctl (epfd, EPOLL_CTL_MOD, fd, &input);
367 printf (
"ctl MOD: %d\n", ret);
369 ret = epoll_wait (epfd, &output, 1, -1);
370 printf (
"wait for HUP: %d\n", ret);
@ DBUS_WATCH_READABLE
As in POLLIN.
@ DBUS_WATCH_WRITABLE
As in POLLOUT.
@ DBUS_WATCH_HANGUP
As in POLLHUP (can't watch for it, but can be present in current state passed to dbus_watch_handle())...
@ DBUS_WATCH_ERROR
As in POLLERR (can't watch for this, but can be present in current state passed to dbus_watch_handle(...
#define _dbus_assert(condition)
Aborts with an error message if the condition is 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().
#define _DBUS_ZERO(object)
Sets all bits in an object to zero.
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
#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.