2 fd_epoll.c -- I/O and event multiplexing using epoll
4 Copyright (C) 2003-2004 Guus Sliepen <guus@tinc-vpn.org>,
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 $Id: fd.c 1375 2004-03-22 12:30:39Z guus $
25 #include "support/avl.h"
26 #include "support/xalloc.h"
31 static avl_tree_t *fds;
33 volatile bool fd_running = false;
35 int fd_compare(struct fd *a, struct fd *b) {
36 return (a->fd - b->fd) ?: (a->mode - b->mode);
42 epollfd = epoll_create(32);
45 logger(LOG_ERR, "fd: could not open an epoll file descriptor: %s", strerror(errno));
49 fds = avl_tree_new((avl_compare_t)fd_compare, NULL);
62 bool fd_add(struct fd *fd) {
69 fd->event.events |= EPOLLIN;
72 fd->event.events |= EPOLLOUT;
75 fd->event.events |= EPOLLPRI | EPOLLERR | EPOLLHUP;
77 fd->event.data.ptr = fd;
79 if(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd->fd, &fd->event) == -1) {
80 logger(LOG_ERR, "fd: failed to add file descriptor: %s", strerror(errno));
87 bool fd_del(struct fd *fd) {
88 if(epoll_ctl(epollfd, EPOLL_CTL_DEL, fd->fd, &fd->event) == -1) {
89 logger(LOG_ERR, "fd: failed to delete file descriptor: %s", strerror(errno));
93 return avl_del(fds, fd);
96 bool fd_mod(struct fd *fd) {
100 fd->event.events |= EPOLLIN;
103 fd->event.events |= EPOLLOUT;
106 fd->event.events |= EPOLLPRI | EPOLLERR | EPOLLHUP;
108 if(epoll_ctl(epollfd, EPOLL_CTL_MOD, fd->fd, &fd->event) == -1) {
109 logger(LOG_ERR, "fd: failed to modify file descriptor: %s", strerror(errno));
119 struct epoll_event *events[10];
123 logger(LOG_INFO, "fd: running");
126 tv = event_timeout();
128 result = epoll_wait(epollfd, events, sizeof events / sizeof *events, tv.tv_sec >= 0 ? tv.tv_sec * 1000 + tv.tv_usec / 1000: -1);
131 if(errno != EINTR && errno != EAGAIN) {
132 logger(LOG_ERR, _("fd: error while waiting for input: %s"), strerror(errno));
143 fd = events[result].data.ptr;
145 if(events[result].events & EPOLLIN)
148 if(events[result].events & EPOLLOUT)
151 if(events[result].events & (EPOLLPRI | EPOLLERR | EPOLLHUP))
159 logger(LOG_INFO, "fd: stopping");