ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/s_bsd_sigio.c
Revision: 1309
Committed: Sun Mar 25 11:24:18 2012 UTC (12 years ago) by michael
Content type: text/x-csrc
File size: 7138 byte(s)
Log Message:
- renaming files:

  ircd_parser.y -> conf_parser.y
  ircd_lexer.l  -> conf_lexer.l
  s_conf.c      -> conf.c
  s_conf.h      -> conf.h
  s_log.c       -> log.c
  s_log.h       -> log.h

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 "list.h"
35 #include "fdlist.h"
36 #include "hook.h"
37 #include "ircd.h"
38 #include "s_bsd.h"
39 #include "log.h"
40
41 #define SIGIO_SIGNAL SIGRTMIN
42
43 static pid_t my_pid;
44 static sigset_t our_sigset;
45 static struct pollfd *pollfds;
46 static int pollmax = -1; /* highest FD number */
47 static dlink_node *fdlim_hook, *setupfd_hook;
48
49 /*
50 * static void mask_our_signal(int s)
51 *
52 * Input: None
53 * Output: None
54 * Side Effects: Block our signal
55 */
56 static void
57 mask_our_signal()
58 {
59 sigemptyset(&our_sigset);
60 sigaddset(&our_sigset, SIGIO_SIGNAL);
61 sigaddset(&our_sigset, SIGIO);
62 sigprocmask(SIG_BLOCK, &our_sigset, NULL);
63 }
64
65 /*
66 * void setup_sigio_fd(int fd)
67 *
68 * Input: File descriptor
69 * Output: None
70 * Side Effect: Sets the FD up for SIGIO
71 */
72 static void *
73 setup_sigio_fd(va_list args)
74 {
75 int fd = va_arg(args, int);
76
77 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_ASYNC);
78 fcntl(fd, F_SETSIG, SIGIO_SIGNAL);
79 fcntl(fd, F_SETOWN, my_pid);
80
81 return pass_callback(setupfd_hook, fd);
82 }
83
84 /*
85 * changing_fdlimit
86 *
87 * Resize pollfds array if necessary.
88 */
89 static void *
90 changing_fdlimit(va_list args)
91 {
92 int old_fdlimit = hard_fdlimit;
93
94 pass_callback(fdlim_hook, va_arg(args, int));
95
96 if (hard_fdlimit != old_fdlimit)
97 pollfds = MyRealloc(pollfds, sizeof(struct pollfd) * hard_fdlimit);
98
99 return NULL;
100 }
101
102 /*
103 * void init_netio(void)
104 *
105 * Input: None
106 * Output: None
107 * Side Effects: This is a needed exported function which will
108 * be called to initialise the network loop code.
109 */
110 void
111 init_netio(void)
112 {
113 int fd;
114
115 pollfds = MyMalloc(sizeof(struct pollfd) * hard_fdlimit);
116
117 for (fd = 0; fd < hard_fdlimit; fd++)
118 pollfds[fd].fd = -1;
119
120 setupfd_hook = install_hook(setup_socket_cb, setup_sigio_fd);
121 fdlim_hook = install_hook(fdlimit_cb, changing_fdlimit);
122
123 my_pid = getpid();
124 mask_our_signal(SIGIO_SIGNAL);
125 }
126
127 /*
128 * find a spare slot in the fd list. We can optimise this out later!
129 * -- adrian
130 */
131 static inline int
132 poll_findslot(void)
133 {
134 int i;
135
136 for (i = 0; i < hard_fdlimit; i++)
137 {
138 if (pollfds[i].fd == -1)
139 {
140 /* MATCH!!#$*&$ */
141 return i;
142 }
143 }
144
145 assert(1 == 0);
146 /* NOTREACHED */
147 return -1;
148 }
149
150 /*
151 * comm_setselect
152 *
153 * This is a needed exported function which will be called to register
154 * and deregister interest in a pending IO state for a given FD.
155 */
156 void
157 comm_setselect(fde_t *F, unsigned int type, PF *handler,
158 void *client_data, time_t timeout)
159 {
160 int new_events;
161
162 if ((type & COMM_SELECT_READ))
163 {
164 F->read_handler = handler;
165 F->read_data = client_data;
166 }
167
168 if ((type & COMM_SELECT_WRITE))
169 {
170 F->write_handler = handler;
171 F->write_data = client_data;
172 }
173
174 new_events = (F->read_handler ? POLLRDNORM : 0) |
175 (F->write_handler ? POLLWRNORM : 0);
176
177 if (timeout != 0)
178 F->timeout = CurrentTime + (timeout / 1000);
179
180 if (new_events != F->evcache)
181 {
182 if (new_events == 0)
183 {
184 pollfds[F->comm_index].fd = -1;
185 pollfds[F->comm_index].revents = 0;
186
187 if (pollmax == F->comm_index)
188 while (pollmax >= 0 && pollfds[pollmax].fd == -1)
189 pollmax--;
190 }
191 else
192 {
193 if (F->evcache == 0)
194 {
195 F->comm_index = poll_findslot();
196 if (F->comm_index > pollmax)
197 pollmax = F->comm_index;
198
199 pollfds[F->comm_index].fd = F->fd;
200 }
201 pollfds[F->comm_index].events = new_events;
202 pollfds[F->comm_index].revents = 0;
203 }
204
205 F->evcache = new_events;
206 }
207 }
208
209 /*
210 * comm_select
211 *
212 * Called to do the new-style IO, courtesy of squid (like most of this
213 * new IO code). This routine handles the stuff we've hidden in
214 * comm_setselect and fd_table[] and calls callbacks for IO ready
215 * events.
216 */
217 void
218 comm_select(void)
219 {
220 static time_t last_rtsigqo_warning = 0;
221 struct timespec timeout;
222 struct siginfo si;
223 int i, revents, num;
224 fde_t *F;
225 PF *hdl;
226
227 timeout.tv_sec = 0;
228 timeout.tv_nsec = 1000000 * SELECT_DELAY;
229 i = sigtimedwait(&our_sigset, &si, &timeout);
230
231 set_time();
232
233 if (i != SIGIO)
234 {
235 if (i > 0)
236 {
237 F = lookup_fd(si.si_fd);
238 if (F == NULL || !F->flags.open)
239 return;
240
241 if (si.si_band & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
242 if ((hdl = F->read_handler) != NULL)
243 {
244 F->read_handler = NULL;
245 hdl(F, F->read_data);
246 if (!F->flags.open)
247 return;
248 }
249
250 if (si.si_band & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
251 if ((hdl = F->write_handler) != NULL)
252 {
253 F->write_handler = NULL;
254 hdl(F, F->write_data);
255 if (!F->flags.open)
256 return;
257 }
258
259 comm_setselect(F, 0, NULL, NULL, 0);
260 }
261
262 return;
263 }
264
265 /* RT signal queue overflowed.. */
266
267 if (CurrentTime - last_rtsigqo_warning >= 30)
268 {
269 ilog(LOG_TYPE_IRCD, "Kernel RT Signal queue overflowed. "
270 "Is /proc/sys/kernel/rtsig-max too small?");
271 last_rtsigqo_warning = CurrentTime;
272 }
273
274 signal(SIGIO_SIGNAL, SIG_IGN);
275 signal(SIGIO_SIGNAL, SIG_DFL);
276
277 /* ..try polling instead */
278
279 while ((num = poll(pollfds, pollmax + 1, 0)) < 0 && ignoreErrno(errno))
280 ;
281
282 /* update current time again, eww.. */
283 set_time();
284
285 for (i = 0; i <= pollmax && num > 0; i++)
286 {
287 if ((revents = pollfds[i].revents) == 0 || pollfds[i].fd == -1)
288 continue;
289 num--;
290
291 F = lookup_fd(pollfds[i].fd);
292 if (F == NULL || !F->flags.open)
293 continue;
294
295 if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
296 if ((hdl = F->read_handler) != NULL)
297 {
298 F->read_handler = NULL;
299 hdl(F, F->read_data);
300 if (!F->flags.open)
301 continue;
302 }
303
304 if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
305 if ((hdl = F->write_handler) != NULL)
306 {
307 F->write_handler = NULL;
308 hdl(F, F->write_data);
309 if (!F->flags.open)
310 continue;
311 }
312
313 comm_setselect(F, 0, NULL, NULL, 0);
314 }
315
316 mask_our_signal(SIGIO_SIGNAL);
317 }
318 #endif

Properties

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