ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/s_bsd_sigio.c
Revision: 908
Committed: Sun Nov 4 23:21:51 2007 UTC (16 years, 5 months ago) by stu
Content type: text/x-csrc
File size: 7123 byte(s)
Log Message:
Completely redo the build system.  Now uses libtool and automake.  Suggest you clean out your tree and then do ./autogen.sh.

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * s_bsd_sigio.c: Linux Realtime SIGIO compatible network routines.
4 *
5 * Originally by Aaron Sethman <androsyn@ratbox.org>
6 * based upon: s_bsd_poll.c by Adrian Chadd <adrian@creative.net.au>
7 * Copyright (C) 2001-2002 Hybrid Development Team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 *
24 * $Id$
25 */
26
27 #ifndef _GNU_SOURCE
28 #define _GNU_SOURCE 1 /* Needed for F_SETSIG */
29 #endif
30
31 #include "stdinc.h"
32 #if USE_IOPOLL_MECHANISM == __IOPOLL_MECHANISM_RTSIGIO
33 #include <sys/poll.h>
34 #include "fdlist.h"
35 #include "hook.h"
36 #include "ircd.h"
37 #include "s_bsd.h"
38 #include "s_log.h"
39
40 #define SIGIO_SIGNAL SIGRTMIN
41
42 static pid_t my_pid;
43 static sigset_t our_sigset;
44 static struct pollfd *pollfds;
45 static int pollmax = -1; /* highest FD number */
46 static dlink_node *fdlim_hook, *setupfd_hook;
47
48 /*
49 * static void mask_our_signal(int s)
50 *
51 * Input: None
52 * Output: None
53 * Side Effects: Block our signal
54 */
55 static void
56 mask_our_signal()
57 {
58 sigemptyset(&our_sigset);
59 sigaddset(&our_sigset, SIGIO_SIGNAL);
60 sigaddset(&our_sigset, SIGIO);
61 sigprocmask(SIG_BLOCK, &our_sigset, NULL);
62 }
63
64 /*
65 * void setup_sigio_fd(int fd)
66 *
67 * Input: File descriptor
68 * Output: None
69 * Side Effect: Sets the FD up for SIGIO
70 */
71 static void *
72 setup_sigio_fd(va_list args)
73 {
74 int fd = va_arg(args, int);
75
76 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_ASYNC);
77 fcntl(fd, F_SETSIG, SIGIO_SIGNAL);
78 fcntl(fd, F_SETOWN, my_pid);
79
80 return pass_callback(setupfd_hook, fd);
81 }
82
83 /*
84 * changing_fdlimit
85 *
86 * Resize pollfds array if necessary.
87 */
88 static void *
89 changing_fdlimit(va_list args)
90 {
91 int old_fdlimit = hard_fdlimit;
92
93 pass_callback(fdlim_hook, va_arg(args, int));
94
95 if (hard_fdlimit != old_fdlimit)
96 pollfds = MyRealloc(pollfds, sizeof(struct pollfd) * hard_fdlimit);
97
98 return NULL;
99 }
100
101 /*
102 * void init_netio(void)
103 *
104 * Input: None
105 * Output: None
106 * Side Effects: This is a needed exported function which will
107 * be called to initialise the network loop code.
108 */
109 void
110 init_netio(void)
111 {
112 int fd;
113
114 pollfds = MyMalloc(sizeof(struct pollfd) * hard_fdlimit);
115
116 for (fd = 0; fd < hard_fdlimit; fd++)
117 pollfds[fd].fd = -1;
118
119 setupfd_hook = install_hook(setup_socket_cb, setup_sigio_fd);
120 fdlim_hook = install_hook(fdlimit_cb, changing_fdlimit);
121
122 my_pid = getpid();
123 mask_our_signal(SIGIO_SIGNAL);
124 }
125
126 /*
127 * find a spare slot in the fd list. We can optimise this out later!
128 * -- adrian
129 */
130 static inline int
131 poll_findslot(void)
132 {
133 int i;
134
135 for (i = 0; i < hard_fdlimit; i++)
136 {
137 if (pollfds[i].fd == -1)
138 {
139 /* MATCH!!#$*&$ */
140 return i;
141 }
142 }
143
144 assert(1 == 0);
145 /* NOTREACHED */
146 return -1;
147 }
148
149 /*
150 * comm_setselect
151 *
152 * This is a needed exported function which will be called to register
153 * and deregister interest in a pending IO state for a given FD.
154 */
155 void
156 comm_setselect(fde_t *F, unsigned int type, PF *handler,
157 void *client_data, time_t timeout)
158 {
159 int new_events;
160
161 if ((type & COMM_SELECT_READ))
162 {
163 F->read_handler = handler;
164 F->read_data = client_data;
165 }
166
167 if ((type & COMM_SELECT_WRITE))
168 {
169 F->write_handler = handler;
170 F->write_data = client_data;
171 }
172
173 new_events = (F->read_handler ? POLLRDNORM : 0) |
174 (F->write_handler ? POLLWRNORM : 0);
175
176 if (timeout != 0)
177 F->timeout = CurrentTime + (timeout / 1000);
178
179 if (new_events != F->evcache)
180 {
181 if (new_events == 0)
182 {
183 pollfds[F->comm_index].fd = -1;
184 pollfds[F->comm_index].revents = 0;
185
186 if (pollmax == F->comm_index)
187 while (pollmax >= 0 && pollfds[pollmax].fd == -1)
188 pollmax--;
189 }
190 else
191 {
192 if (F->evcache == 0)
193 {
194 F->comm_index = poll_findslot();
195 if (F->comm_index > pollmax)
196 pollmax = F->comm_index;
197
198 pollfds[F->comm_index].fd = F->fd;
199 }
200 pollfds[F->comm_index].events = new_events;
201 pollfds[F->comm_index].revents = 0;
202 }
203
204 F->evcache = new_events;
205 }
206 }
207
208 /*
209 * comm_select
210 *
211 * Called to do the new-style IO, courtesy of squid (like most of this
212 * new IO code). This routine handles the stuff we've hidden in
213 * comm_setselect and fd_table[] and calls callbacks for IO ready
214 * events.
215 */
216 void
217 comm_select(void)
218 {
219 static time_t last_rtsigqo_warning = 0;
220 struct timespec timeout;
221 struct siginfo si;
222 int i, revents, num;
223 fde_t *F;
224 PF *hdl;
225
226 timeout.tv_sec = 0;
227 timeout.tv_nsec = 1000000 * SELECT_DELAY;
228 i = sigtimedwait(&our_sigset, &si, &timeout);
229
230 set_time();
231
232 if (i != SIGIO)
233 {
234 if (i > 0)
235 {
236 F = lookup_fd(si.si_fd);
237 if (F == NULL || !F->flags.open)
238 return;
239
240 if (si.si_band & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
241 if ((hdl = F->read_handler) != NULL)
242 {
243 F->read_handler = NULL;
244 hdl(F, F->read_data);
245 if (!F->flags.open)
246 return;
247 }
248
249 if (si.si_band & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
250 if ((hdl = F->write_handler) != NULL)
251 {
252 F->write_handler = NULL;
253 hdl(F, F->write_data);
254 if (!F->flags.open)
255 return;
256 }
257
258 comm_setselect(F, 0, NULL, NULL, 0);
259 }
260
261 return;
262 }
263
264 /* RT signal queue overflowed.. */
265
266 if (CurrentTime - last_rtsigqo_warning >= 30)
267 {
268 ilog(L_WARN, "Kernel RT Signal queue overflowed. "
269 "Is /proc/sys/kernel/rtsig-max too small?");
270 last_rtsigqo_warning = CurrentTime;
271 }
272
273 signal(SIGIO_SIGNAL, SIG_IGN);
274 signal(SIGIO_SIGNAL, SIG_DFL);
275
276 /* ..try polling instead */
277
278 while ((num = poll(pollfds, pollmax + 1, 0)) < 0 && ignoreErrno(errno))
279 ;
280
281 /* update current time again, eww.. */
282 set_time();
283
284 for (i = 0; i <= pollmax && num > 0; i++)
285 {
286 if ((revents = pollfds[i].revents) == 0 || pollfds[i].fd == -1)
287 continue;
288 num--;
289
290 F = lookup_fd(pollfds[i].fd);
291 if (F == NULL || !F->flags.open)
292 continue;
293
294 if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
295 if ((hdl = F->read_handler) != NULL)
296 {
297 F->read_handler = NULL;
298 hdl(F, F->read_data);
299 if (!F->flags.open)
300 continue;
301 }
302
303 if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
304 if ((hdl = F->write_handler) != NULL)
305 {
306 F->write_handler = NULL;
307 hdl(F, F->write_data);
308 if (!F->flags.open)
309 continue;
310 }
311
312 comm_setselect(F, 0, NULL, NULL, 0);
313 }
314
315 mask_our_signal(SIGIO_SIGNAL);
316 }
317 #endif

Properties

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