ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/s_bsd_sigio.c
Revision: 31
Committed: Sun Oct 2 20:34:05 2005 UTC (19 years, 10 months ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/src/s_bsd_sigio.c
File size: 7061 byte(s)
Log Message:
- Fix svn:keywords

File Contents

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

Properties

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