ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/s_bsd_sigio.c
Revision: 1592
Committed: Sat Oct 27 21:02:32 2012 UTC (12 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 7138 byte(s)
Log Message:
- Second time's the charm? Moving svnroot/ircd-hybrid-8 to
  svnroot/ircd-hybrid/trunk

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 stu 908 #if USE_IOPOLL_MECHANISM == __IOPOLL_MECHANISM_RTSIGIO
33 adx 30 #include <sys/poll.h>
34 michael 1021 #include "list.h"
35 adx 30 #include "fdlist.h"
36     #include "hook.h"
37     #include "ircd.h"
38     #include "s_bsd.h"
39 michael 1309 #include "log.h"
40 adx 30
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 michael 1247 ilog(LOG_TYPE_IRCD, "Kernel RT Signal queue overflowed. "
270     "Is /proc/sys/kernel/rtsig-max too small?");
271 adx 30 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 stu 908 #endif

Properties

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