ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/s_bsd_epoll.c
Revision: 34
Committed: Sun Oct 2 21:05:51 2005 UTC (18 years, 5 months ago) by lusky
Content type: text/x-csrc
File size: 5835 byte(s)
Log Message:
create 7.2 branch, we can move/rename it as needed.


File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * s_bsd_epoll.c: Linux epoll() compatible network routines.
4 *
5 * Copyright (C) 2002-2005 Hybrid Development Team
6 * Based also on work of Adrian Chadd, Aaron Sethman and others.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 *
23 * $Id$
24 */
25
26 #include "stdinc.h"
27 #include "fdlist.h"
28 #include "ircd.h"
29 #include "memory.h"
30 #include "s_bsd.h"
31 #include "s_log.h"
32 #include <sys/epoll.h>
33 #include <sys/syscall.h>
34
35 static fde_t efd;
36
37 /* Thanks to ircu for the following ifdefs. */
38
39 /* The GNU C library may have a valid header but stub implementations
40 * of the epoll system calls. If so, provide our own. */
41 #if defined(__stub_epoll_create) || defined(__stub___epoll_create) || defined(EPOLL_NEED_BODY)
42
43 /* Oh, did we mention that some glibc releases do not even define the
44 * syscall numbers? */
45 #if !defined(__NR_epoll_create)
46 #if defined(__ia64__)
47 #define __NR_epoll_create 1243
48 #define __NR_epoll_ctl 1244
49 #define __NR_epoll_wait 1245
50 #elif defined(__x86_64__)
51 #define __NR_epoll_create 214
52 #define __NR_epoll_ctl 233
53 #define __NR_epoll_wait 232
54 #elif defined(__sparc64__) || defined(__sparc__)
55 #define __NR_epoll_create 193
56 #define __NR_epoll_ctl 194
57 #define __NR_epoll_wait 195
58 #elif defined(__s390__) || defined(__m68k__)
59 #define __NR_epoll_create 249
60 #define __NR_epoll_ctl 250
61 #define __NR_epoll_wait 251
62 #elif defined(__ppc64__) || defined(__ppc__)
63 #define __NR_epoll_create 236
64 #define __NR_epoll_ctl 237
65 #define __NR_epoll_wait 238
66 #elif defined(__parisc__) || defined(__arm26__) || defined(__arm__)
67 #define __NR_epoll_create 224
68 #define __NR_epoll_ctl 225
69 #define __NR_epoll_wait 226
70 #elif defined(__alpha__)
71 #define __NR_epoll_create 407
72 #define __NR_epoll_ctl 408
73 #define __NR_epoll_wait 409
74 #elif defined(__sh64__)
75 #define __NR_epoll_create 282
76 #define __NR_epoll_ctl 283
77 #define __NR_epoll_wait 284
78 #elif defined(__i386__) || defined(__sh__) || defined(__m32r__) || defined(__h8300__) || defined(__frv__)
79 #define __NR_epoll_create 254
80 #define __NR_epoll_ctl 255
81 #define __NR_epoll_wait 256
82 #else /* cpu types */
83 #error No system call numbers defined for epoll family.
84 #endif /* cpu types */
85 #endif /* !defined(__NR_epoll_create) */
86
87 _syscall1(int, epoll_create, int, size)
88 _syscall4(int, epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, event)
89 _syscall4(int, epoll_wait, int, epfd, struct epoll_event *, pevents, int, maxevents, int, timeout)
90
91 #endif /* epoll_create defined as stub */
92
93 /*
94 * init_netio
95 *
96 * This is a needed exported function which will be called to initialise
97 * the network loop code.
98 */
99 void
100 init_netio(void)
101 {
102 int fd;
103
104 if ((fd = epoll_create(hard_fdlimit)) < 0)
105 {
106 ilog(L_CRIT, "init_netio: Couldn't open epoll fd - %d: %s",
107 errno, strerror(errno));
108 exit(115); /* Whee! */
109 }
110
111 fd_open(&efd, fd, 0, "epoll file descriptor");
112 }
113
114 /*
115 * comm_setselect
116 *
117 * This is a needed exported function which will be called to register
118 * and deregister interest in a pending IO state for a given FD.
119 */
120 void
121 comm_setselect(fde_t *F, unsigned int type, PF *handler,
122 void *client_data, time_t timeout)
123 {
124 int new_events, op;
125 struct epoll_event ep_event;
126
127 if ((type & COMM_SELECT_READ))
128 {
129 F->read_handler = handler;
130 F->read_data = client_data;
131 }
132
133 if ((type & COMM_SELECT_WRITE))
134 {
135 F->write_handler = handler;
136 F->write_data = client_data;
137 }
138
139 new_events = (F->read_handler ? EPOLLIN : 0) |
140 (F->write_handler ? EPOLLOUT : 0);
141
142 if (timeout != 0)
143 F->timeout = CurrentTime + (timeout / 1000);
144
145 if (new_events != F->evcache)
146 {
147 if (new_events == 0)
148 op = EPOLL_CTL_DEL;
149 else if (F->evcache == 0)
150 op = EPOLL_CTL_ADD;
151 else
152 op = EPOLL_CTL_MOD;
153
154 ep_event.events = F->evcache = new_events;
155 ep_event.data.fd = F->fd;
156
157 if (epoll_ctl(efd.fd, op, F->fd, &ep_event) != 0)
158 {
159 ilog(L_CRIT, "comm_setselect: epoll_ctl() failed: %s", strerror(errno));
160 abort();
161 }
162 }
163 }
164
165 /*
166 * comm_select()
167 *
168 * Called to do the new-style IO, courtesy of of squid (like most of this
169 * new IO code). This routine handles the stuff we've hidden in
170 * comm_setselect and fd_table[] and calls callbacks for IO ready
171 * events.
172 */
173 void
174 comm_select(void)
175 {
176 struct epoll_event ep_fdlist[128];
177 int num, i;
178 PF *hdl;
179 fde_t *F;
180
181 num = epoll_wait(efd.fd, ep_fdlist, 128, SELECT_DELAY);
182
183 set_time();
184
185 if (num < 0)
186 {
187 #ifdef HAVE_USLEEP
188 usleep(50000); /* avoid 99% CPU in comm_select */
189 #endif
190 return;
191 }
192
193 for (i = 0; i < num; i++)
194 {
195 F = lookup_fd(ep_fdlist[i].data.fd);
196 if (F == NULL || !F->flags.open)
197 continue;
198
199 if ((ep_fdlist[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR)))
200 if ((hdl = F->read_handler) != NULL)
201 {
202 F->read_handler = NULL;
203 hdl(F, F->read_data);
204 if (!F->flags.open)
205 continue;
206 }
207
208 if ((ep_fdlist[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR)))
209 if ((hdl = F->write_handler) != NULL)
210 {
211 F->write_handler = NULL;
212 hdl(F, F->write_data);
213 if (!F->flags.open)
214 continue;
215 }
216
217 comm_setselect(F, 0, NULL, NULL, 0);
218 }
219 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision