28#include "dbus-pollable-set.h"
30#include <dbus/dbus-internals.h>
31#include <dbus/dbus-sysdeps.h>
34# error This file is for Linux epoll(4)
42#ifndef DOXYGEN_SHOULD_SKIP_THIS
45 DBusPollableSet parent;
47} DBusPollableSetEpoll;
49static inline DBusPollableSetEpoll *
50socket_set_epoll_cast (DBusPollableSet *set)
52 _dbus_assert (set->cls == &_dbus_pollable_set_epoll_class);
53 return (DBusPollableSetEpoll *) set;
58socket_set_epoll_free (DBusPollableSet *set)
60 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
72_dbus_pollable_set_epoll_new (
void)
74 DBusPollableSetEpoll *self;
76 self =
dbus_new0 (DBusPollableSetEpoll, 1);
81 self->parent.cls = &_dbus_pollable_set_epoll_class;
83 self->epfd = epoll_create1 (EPOLL_CLOEXEC);
92 self->epfd = epoll_create (42);
94 flags = fcntl (self->epfd, F_GETFD, 0);
97 fcntl (self->epfd, F_SETFD, flags | FD_CLOEXEC);
100 if (self->epfd == -1)
102 socket_set_epoll_free ((DBusPollableSet *) self);
106 return (DBusPollableSet *) self;
110watch_flags_to_epoll_events (
unsigned int flags)
123epoll_events_to_watch_flags (uint32_t events)
127 if (events & EPOLLIN)
129 if (events & EPOLLOUT)
131 if (events & EPOLLHUP)
133 if (events & EPOLLERR)
140socket_set_epoll_add (DBusPollableSet *set,
145 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
146 struct epoll_event event;
154 event.events = watch_flags_to_epoll_events (flags);
160 event.events = EPOLLET;
163 if (epoll_ctl (self->epfd, EPOLL_CTL_ADD, fd, &event) == 0)
181 _dbus_warn (
"fd %d added and then added again", fd);
185 _dbus_warn (
"Misc error when trying to watch fd %d: %s", fd,
194socket_set_epoll_enable (DBusPollableSet *set,
198 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
199 struct epoll_event event;
204 event.events = watch_flags_to_epoll_events (flags);
206 if (epoll_ctl (self->epfd, EPOLL_CTL_MOD, fd, &event) == 0)
220 _dbus_warn (
"fd %d enabled before it was added", fd);
224 _dbus_warn (
"Insufficient memory to change watch for fd %d", fd);
228 _dbus_warn (
"Misc error when trying to watch fd %d: %s", fd,
235socket_set_epoll_disable (DBusPollableSet *set,
238 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
239 struct epoll_event event;
260 event.events = EPOLLET;
262 if (epoll_ctl (self->epfd, EPOLL_CTL_MOD, fd, &event) == 0)
266 _dbus_warn (
"Error when trying to watch fd %d: %s", fd,
271socket_set_epoll_remove (DBusPollableSet *set,
274 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
278 struct epoll_event dummy;
281 if (epoll_ctl (self->epfd, EPOLL_CTL_DEL, fd, &dummy) == 0)
285 _dbus_warn (
"Error when trying to remove fd %d: %s", fd, strerror (err));
291#define N_STACK_DESCRIPTORS 64
294socket_set_epoll_poll (DBusPollableSet *set,
295 DBusPollableEvent *revents,
299 DBusPollableSetEpoll *self = socket_set_epoll_cast (set);
300 struct epoll_event events[N_STACK_DESCRIPTORS];
306 n_ready = epoll_wait (self->epfd, events,
313 for (i = 0; i < n_ready; i++)
315 revents[i].fd = events[i].data.fd;
316 revents[i].flags = epoll_events_to_watch_flags (events[i].events);
322DBusPollableSetClass _dbus_pollable_set_epoll_class = {
323 socket_set_epoll_free,
324 socket_set_epoll_add,
325 socket_set_epoll_remove,
326 socket_set_epoll_enable,
327 socket_set_epoll_disable,
328 socket_set_epoll_poll
331#ifdef TEST_BEHAVIOUR_OF_EPOLLET
342#include <sys/epoll.h>
349 struct epoll_event input;
350 struct epoll_event output;
351 int epfd = epoll_create1 (EPOLL_CLOEXEC);
357 input.events = EPOLLHUP | EPOLLET;
358 ret = epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &input);
359 printf (
"ctl ADD: %d\n", ret);
361 ret = epoll_wait (epfd, &output, 1, -1);
362 printf (
"wait for HUP, edge-triggered: %d\n", ret);
364 ret = epoll_wait (epfd, &output, 1, 1);
365 printf (
"wait for HUP again: %d\n", ret);
367 input.events = EPOLLHUP;
368 ret = epoll_ctl (epfd, EPOLL_CTL_MOD, fd, &input);
369 printf (
"ctl MOD: %d\n", ret);
371 ret = epoll_wait (epfd, &output, 1, -1);
372 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().