Clean a bit - to be continued...
[seven-1.x.git] / libseven / epoll.c
blob889e95f25af20b96cc5289897a73a9644e753c94
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * epoll.c: Linux epoll compatible network routines.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2001 Adrian Chadd <adrian@creative.net.au>
8 * Copyright (C) 2002-2005 ircd-ratbox development team
9 * Copyright (C) 2002 Aaron Sethman <androsyn@ratbox.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 * USA
28 #include "config.h"
29 #include "stdinc.h"
30 #include <sys/epoll.h>
32 #include "libseven.h"
34 static int ep; /* epoll file descriptor */
35 static struct epoll_event *pfd;
36 static int pfd_size;
39 #ifndef HAVE_EPOLL_CTL /* bah..glibc doesn't support epoll yet.. */
40 #include <sys/epoll.h>
41 #include <sys/syscall.h>
43 _syscall1(int, epoll_create, int, maxfds);
44 _syscall4(int, epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, events);
45 _syscall4(int, epoll_wait, int, epfd, struct epoll_event *, pevents,
46 int, maxevents, int, timeout);
48 #endif /* HAVE_EPOLL_CTL */
52 * init_netio
54 * This is a needed exported function which will be called to initialise
55 * the network loop code.
57 void
58 init_netio(void)
60 pfd_size = getdtablesize();
61 ep = epoll_create(pfd_size);
62 pfd = MyMalloc(sizeof(struct epoll_event) * pfd_size);
63 if(ep < 0)
65 fprintf(stderr, "init_netio: Couldn't open epoll fd!\n");
66 exit(115); /* Whee! */
68 comm_note(ep, "epoll file descriptor");
72 * comm_setselect
74 * This is a needed exported function which will be called to register
75 * and deregister interest in a pending IO state for a given FD.
77 void
78 comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler,
79 void *client_data, time_t timeout)
81 struct epoll_event ep_event;
82 fde_t *F = &fd_table[fd];
83 int old_flags = F->pflags;
84 int op = -1;
86 s_assert(fd >= 0);
87 s_assert(F->flags.open);
89 /* Update the list, even though we're not using it .. */
90 F->list = list;
91 if(type & COMM_SELECT_READ)
93 if(handler != NULL)
94 F->pflags |= EPOLLIN;
95 else
96 F->pflags &= ~EPOLLIN;
97 F->read_handler = handler;
98 F->read_data = client_data;
101 if(type & COMM_SELECT_WRITE)
103 if(handler != NULL)
104 F->pflags |= EPOLLOUT;
105 else
106 F->pflags &= ~EPOLLOUT;
107 F->write_handler = handler;
108 F->write_data = client_data;
111 if(timeout)
112 F->timeout = CurrentTime + (timeout / 1000);
114 if(old_flags == 0 && F->pflags == 0)
115 return;
116 else if(F->pflags <= 0)
117 op = EPOLL_CTL_DEL;
118 else if(old_flags == 0 && F->pflags > 0)
119 op = EPOLL_CTL_ADD;
120 else if(F->pflags != old_flags)
121 op = EPOLL_CTL_MOD;
123 if(op == -1)
124 return;
127 ep_event.events = F->pflags;
128 ep_event.data.ptr = F;
130 if(epoll_ctl(ep, op, fd, &ep_event) != 0)
132 libseven_log("comm_setselect(): epoll_ctl failed: %s", strerror(errno));
133 abort();
140 * comm_select
142 * Called to do the new-style IO, courtesy of squid (like most of this
143 * new IO code). This routine handles the stuff we've hidden in
144 * comm_setselect and fd_table[] and calls callbacks for IO ready
145 * events.
149 comm_select(unsigned long delay)
151 int num, i, flags, old_flags, op;
152 struct epoll_event ep_event;
153 void *data;
155 num = epoll_wait(ep, pfd, pfd_size, delay);
156 set_time();
157 if(num < 0 && !ignoreErrno(errno))
159 return COMM_ERROR;
162 if(num == 0)
163 return COMM_OK;
164 for (i = 0; i < num; i++)
166 PF *hdl;
167 fde_t *F = pfd[i].data.ptr;
168 old_flags = F->pflags;
169 if(pfd[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR))
171 hdl = F->read_handler;
172 data = F->read_data;
173 F->read_handler = NULL;
174 F->read_data = NULL;
175 if(hdl) {
176 hdl(F->fd, data);
178 else
179 libseven_log("epoll.c: NULL read handler called");
184 if(F->flags.open == 0)
185 continue;
186 if(pfd[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR))
188 hdl = F->write_handler;
189 data = F->write_data;
190 F->write_handler = NULL;
191 F->write_data = NULL;
193 if(hdl) {
194 hdl(F->fd, data);
196 else
197 libseven_log("epoll.c: NULL write handler called");
200 if(F->flags.open == 0)
201 continue;
203 flags = 0;
205 if(F->read_handler != NULL)
206 flags |= EPOLLIN;
207 if(F->write_handler != NULL)
208 flags |= EPOLLOUT;
210 if(old_flags != flags)
212 if(flags == 0)
213 op = EPOLL_CTL_DEL;
214 else
215 op = EPOLL_CTL_MOD;
216 F->pflags = ep_event.events = flags;
217 ep_event.data.ptr = F;
218 if(epoll_ctl(ep, op, F->fd, &ep_event) != 0)
220 libseven_log("comm_setselect(): epoll_ctl failed: %s", strerror(errno));
225 return COMM_OK;