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
30 #include <sys/epoll.h>
34 static int ep
; /* epoll file descriptor */
35 static struct epoll_event
*pfd
;
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 */
54 * This is a needed exported function which will be called to initialise
55 * the network loop code.
60 pfd_size
= getdtablesize();
61 ep
= epoll_create(pfd_size
);
62 pfd
= MyMalloc(sizeof(struct epoll_event
) * pfd_size
);
65 fprintf(stderr
, "init_netio: Couldn't open epoll fd!\n");
66 exit(115); /* Whee! */
68 comm_note(ep
, "epoll file descriptor");
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.
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
;
87 s_assert(F
->flags
.open
);
89 /* Update the list, even though we're not using it .. */
91 if(type
& COMM_SELECT_READ
)
96 F
->pflags
&= ~EPOLLIN
;
97 F
->read_handler
= handler
;
98 F
->read_data
= client_data
;
101 if(type
& COMM_SELECT_WRITE
)
104 F
->pflags
|= EPOLLOUT
;
106 F
->pflags
&= ~EPOLLOUT
;
107 F
->write_handler
= handler
;
108 F
->write_data
= client_data
;
112 F
->timeout
= CurrentTime
+ (timeout
/ 1000);
114 if(old_flags
== 0 && F
->pflags
== 0)
116 else if(F
->pflags
<= 0)
118 else if(old_flags
== 0 && F
->pflags
> 0)
120 else if(F
->pflags
!= old_flags
)
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
));
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 libseven_log("epoll.c: NULL read handler called");
184 if(F
->flags
.open
== 0)
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
;
197 libseven_log("epoll.c: NULL write handler called");
200 if(F
->flags
.open
== 0)
205 if(F
->read_handler
!= NULL
)
207 if(F
->write_handler
!= NULL
)
210 if(old_flags
!= flags
)
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
));