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
26 * $Id: epoll.c 181 2006-12-18 02:56:07Z beu $
31 #include <sys/epoll.h>
35 static int ep
; /* epoll file descriptor */
36 static struct epoll_event
*pfd
;
40 #ifndef HAVE_EPOLL_CTL /* bah..glibc doesn't support epoll yet.. */
41 #include <sys/epoll.h>
42 #include <sys/syscall.h>
44 _syscall1(int, epoll_create
, int, maxfds
);
45 _syscall4(int, epoll_ctl
, int, epfd
, int, op
, int, fd
, struct epoll_event
*, events
);
46 _syscall4(int, epoll_wait
, int, epfd
, struct epoll_event
*, pevents
,
47 int, maxevents
, int, timeout
);
49 #endif /* HAVE_EPOLL_CTL */
55 * This is a needed exported function which will be called to initialise
56 * the network loop code.
61 pfd_size
= getdtablesize();
62 ep
= epoll_create(pfd_size
);
63 pfd
= MyMalloc(sizeof(struct epoll_event
) * pfd_size
);
66 fprintf(stderr
, "init_netio: Couldn't open epoll fd!\n");
67 exit(115); /* Whee! */
69 comm_note(ep
, "epoll file descriptor");
75 * This is a needed exported function which will be called to register
76 * and deregister interest in a pending IO state for a given FD.
79 comm_setselect(int fd
, fdlist_t list
, unsigned int type
, PF
* handler
,
80 void *client_data
, time_t timeout
)
82 struct epoll_event ep_event
;
83 fde_t
*F
= &fd_table
[fd
];
84 int old_flags
= F
->pflags
;
88 s_assert(F
->flags
.open
);
90 /* Update the list, even though we're not using it .. */
92 if(type
& COMM_SELECT_READ
)
97 F
->pflags
&= ~EPOLLIN
;
98 F
->read_handler
= handler
;
99 F
->read_data
= client_data
;
102 if(type
& COMM_SELECT_WRITE
)
105 F
->pflags
|= EPOLLOUT
;
107 F
->pflags
&= ~EPOLLOUT
;
108 F
->write_handler
= handler
;
109 F
->write_data
= client_data
;
113 F
->timeout
= CurrentTime
+ (timeout
/ 1000);
115 if(old_flags
== 0 && F
->pflags
== 0)
117 else if(F
->pflags
<= 0)
119 else if(old_flags
== 0 && F
->pflags
> 0)
121 else if(F
->pflags
!= old_flags
)
128 ep_event
.events
= F
->pflags
;
129 ep_event
.data
.ptr
= F
;
131 if(epoll_ctl(ep
, op
, fd
, &ep_event
) != 0)
133 libseven_log("comm_setselect(): epoll_ctl failed: %s", strerror(errno
));
143 * Called to do the new-style IO, courtesy of squid (like most of this
144 * new IO code). This routine handles the stuff we've hidden in
145 * comm_setselect and fd_table[] and calls callbacks for IO ready
150 comm_select(unsigned long delay
)
152 int num
, i
, flags
, old_flags
, op
;
153 struct epoll_event ep_event
;
156 num
= epoll_wait(ep
, pfd
, pfd_size
, delay
);
158 if(num
< 0 && !ignoreErrno(errno
))
165 for (i
= 0; i
< num
; i
++)
168 fde_t
*F
= pfd
[i
].data
.ptr
;
169 old_flags
= F
->pflags
;
170 if(pfd
[i
].events
& (EPOLLIN
| EPOLLHUP
| EPOLLERR
))
172 hdl
= F
->read_handler
;
174 F
->read_handler
= NULL
;
180 libseven_log("epoll.c: NULL read handler called");
185 if(F
->flags
.open
== 0)
187 if(pfd
[i
].events
& (EPOLLOUT
| EPOLLHUP
| EPOLLERR
))
189 hdl
= F
->write_handler
;
190 data
= F
->write_data
;
191 F
->write_handler
= NULL
;
192 F
->write_data
= NULL
;
198 libseven_log("epoll.c: NULL write handler called");
201 if(F
->flags
.open
== 0)
206 if(F
->read_handler
!= NULL
)
208 if(F
->write_handler
!= NULL
)
211 if(old_flags
!= flags
)
217 F
->pflags
= ep_event
.events
= flags
;
218 ep_event
.data
.ptr
= F
;
219 if(epoll_ctl(ep
, op
, F
->fd
, &ep_event
) != 0)
221 libseven_log("comm_setselect(): epoll_ctl failed: %s", strerror(errno
));