1 /* IOEngine_epoll.c - IOMultiplexer
2 * Copyright (C) 2014 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #define _IOHandler_internals
18 #include "IOInternal.h"
19 #include "IOHandler.h"
21 #include "IOSockets.h"
24 #ifdef HAVE_SYS_EPOLL_H
25 #include <sys/epoll.h>
34 static int engine_epoll_init() {
35 epoll_fd = epoll_create(IOHANDLER_MAX_SOCKETS);
41 static void engine_epoll_add(struct _IOSocket *iosock) {
42 //add Socket FD to the epoll queue
43 struct epoll_event evt;
46 evt.events = EPOLLHUP | (iosocket_wants_reads(iosock) ? EPOLLIN : 0) | (iosocket_wants_writes(iosock) ? EPOLLOUT : 0);
47 evt.data.ptr = iosock;
48 res = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, iosock->fd, &evt);
50 iolog_trigger(IOLOG_ERROR, "could not add _IOSocket %d to epoll queue. (returned: %d)", iosock->fd, res);
53 static void engine_epoll_remove(struct _IOSocket *iosock) {
54 struct epoll_event evt;
55 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, iosock->fd, &evt);
58 static void engine_epoll_update(struct _IOSocket *iosock) {
59 struct epoll_event evt;
62 evt.events = EPOLLHUP | (iosocket_wants_reads(iosock) ? EPOLLIN : 0) | (iosocket_wants_writes(iosock) ? EPOLLOUT : 0);
63 evt.data.ptr = iosock;
64 res = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, iosock->fd, &evt);
66 iolog_trigger(IOLOG_ERROR, "could not update _IOSocket %d in epoll queue. (returned: %d)", iosock->fd, res);
69 static void engine_epoll_loop(struct timeval *timeout) {
70 struct epoll_event evts[MAX_EVENTS];
77 gettimeofday(&now, NULL);
78 if(iotimer_sorted_descriptors && timeval_is_bigger(now, iotimer_sorted_descriptors->timeout))
81 //get timeout (timer or given timeout)
82 if(iotimer_sorted_descriptors) {
83 msec = (iotimer_sorted_descriptors->timeout.tv_sec - now.tv_sec) * 1000;
84 msec += (iotimer_sorted_descriptors->timeout.tv_usec - now.tv_usec) / 1000;
87 msec2 = (timeout->tv_sec * 1000 + timeout->tv_usec / 1000);
88 if(!iotimer_sorted_descriptors || msec2 < msec)
90 } else if(!iotimer_sorted_descriptors)
94 epoll_result = epoll_wait(epoll_fd, evts, MAX_EVENTS, msec);
96 if (epoll_result < 0) {
98 iolog_trigger(IOLOG_FATAL, "epoll_wait() failed with errno %d: %s", errno, strerror(errno));
103 for(i = 0; i < epoll_result; i++) {
104 events = evts[i].events;
105 iosocket_events_callback(evts[i].data.ptr, (events & (EPOLLIN | EPOLLHUP)), (events & EPOLLOUT));
110 gettimeofday(&now, NULL);
111 if(iotimer_sorted_descriptors && timeval_is_bigger(now, iotimer_sorted_descriptors->timeout))
115 static void engine_epoll_cleanup() {
119 struct IOEngine engine_epoll = {
121 .init = engine_epoll_init,
122 .add = engine_epoll_add,
123 .remove = engine_epoll_remove,
124 .update = engine_epoll_update,
125 .loop = engine_epoll_loop,
126 .cleanup = engine_epoll_cleanup,
131 struct IOEngine engine_epoll = {