]>
jfr.im git - irc/rqf/shadowircd.git/blob - libcharybdis/epoll.c
2 * charybdis: 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>
10 * Copyright (C) 2008 William Pitcock <nenolod@sacredspiral.co.uk>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 * $Id: epoll.c 3444 2007-05-09 00:32:08Z nenolod $
32 #include <sys/epoll.h>
34 #include "libcharybdis.h"
36 static int ep
; /* epoll file descriptor */
37 static struct epoll_event
*pfd
;
41 #ifndef HAVE_EPOLL_CTL /* bah..glibc doesn't support epoll yet.. */
42 #include <sys/epoll.h>
43 #include <sys/syscall.h>
45 _syscall1(int, epoll_create
, int, maxfds
);
46 _syscall4(int, epoll_ctl
, int, epfd
, int, op
, int, fd
, struct epoll_event
*, events
);
47 _syscall4(int, epoll_wait
, int, epfd
, struct epoll_event
*, pevents
,
48 int, maxevents
, int, timeout
);
50 #endif /* HAVE_EPOLL_CTL */
56 * This is a needed exported function which will be called to initialise
57 * the network loop code.
62 pfd_size
= getdtablesize();
63 ep
= epoll_create(pfd_size
);
64 pfd
= MyMalloc(sizeof(struct epoll_event
) * pfd_size
);
67 fprintf(stderr
, "init_netio: Couldn't open epoll fd!\n");
68 exit(115); /* Whee! */
70 comm_note(ep
, "epoll file descriptor");
76 * This is a needed exported function which will be called to register
77 * and deregister interest in a pending IO state for a given FD.
80 comm_setselect(int fd
, fdlist_t list
, unsigned int type
, PF
* handler
,
81 void *client_data
, time_t timeout
)
83 struct epoll_event ep_event
;
84 fde_t
*F
= comm_locate_fd(fd
);
85 int old_flags
= F
->pflags
;
89 s_assert(F
->flags
.open
);
91 /* Update the list, even though we're not using it .. */
93 if(type
& COMM_SELECT_READ
)
98 F
->pflags
&= ~EPOLLIN
;
99 F
->read_handler
= handler
;
100 F
->read_data
= client_data
;
103 if(type
& COMM_SELECT_WRITE
)
106 F
->pflags
|= EPOLLOUT
;
108 F
->pflags
&= ~EPOLLOUT
;
109 F
->write_handler
= handler
;
110 F
->write_data
= client_data
;
114 F
->timeout
= CurrentTime
+ (timeout
/ 1000);
116 if(old_flags
== 0 && F
->pflags
== 0)
118 else if(F
->pflags
<= 0)
120 else if(old_flags
== 0 && F
->pflags
> 0)
122 else if(F
->pflags
!= old_flags
)
129 ep_event
.events
= F
->pflags
;
130 ep_event
.data
.ptr
= F
;
132 if(epoll_ctl(ep
, op
, fd
, &ep_event
) != 0)
134 libcharybdis_log("comm_setselect(): epoll_ctl failed: %s", strerror(errno
));
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
149 comm_select(unsigned long delay
)
151 int num
, i
, flags
, old_flags
, op
;
152 struct epoll_event ep_event
;
155 num
= epoll_wait(ep
, pfd
, pfd_size
, delay
);
157 if(num
< 0 && !ignoreErrno(errno
))
164 for (i
= 0; i
< num
; i
++)
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
;
173 F
->read_handler
= NULL
;
179 libcharybdis_log("epoll.c: NULL read handler called");
183 if(F
->flags
.open
== 0)
185 if(pfd
[i
].events
& (EPOLLOUT
| EPOLLHUP
| EPOLLERR
))
187 hdl
= F
->write_handler
;
188 data
= F
->write_data
;
189 F
->write_handler
= NULL
;
190 F
->write_data
= NULL
;
196 libcharybdis_log("epoll.c: NULL write handler called");
199 if(F
->flags
.open
== 0 && F
->pflags
== 0)
201 else if (F
->flags
.open
== 0)
203 F
->pflags
= ep_event
.events
= flags
;
204 ep_event
.data
.ptr
= F
;
206 if(epoll_ctl(ep
, EPOLL_CTL_DEL
, F
->fd
, &ep_event
) != 0) {
207 /* XXX: we assume this is because close(2) has been called here. */
211 libcharybdis_log("comm_select(): epoll_ctl failed while trying to delete an FD marked as closed: %s", strerror(errno
));
218 if(F
->read_handler
!= NULL
)
223 if(F
->write_handler
!= NULL
)
228 if(old_flags
!= flags
)
235 F
->pflags
= ep_event
.events
= flags
;
236 ep_event
.data
.ptr
= F
;
238 if(epoll_ctl(ep
, op
, F
->fd
, &ep_event
) != 0)
239 libcharybdis_log("comm_select(): epoll_ctl failed: %s", strerror(errno
));