ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/s_bsd_epoll.c
Revision: 3377
Committed: Thu Apr 24 16:15:51 2014 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 6028 byte(s)
Log Message:
- Create 8.2.x branch

File Contents

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

Properties

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