ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/s_bsd_poll.c
Revision: 32
Committed: Sun Oct 2 20:41:23 2005 UTC (18 years, 6 months ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/src/s_bsd_poll.c
File size: 4871 byte(s)
Log Message:
- svn:keywords

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * s_bsd_poll.c: POSIX poll() compatible network routines.
4     *
5     * Originally by Adrian Chadd <adrian@creative.net.au>
6     * Copyright (C) 2002 Hybrid Development Team
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21     * USA
22     *
23 knight 31 * $Id$
24 adx 30 */
25    
26     #include "stdinc.h"
27     #include <sys/poll.h>
28     #include "fdlist.h"
29     #include "hook.h"
30     #include "ircd.h"
31     #include "s_bsd.h"
32     #include "s_log.h"
33    
34     /* I hate linux -- adrian */
35     #ifndef POLLRDNORM
36     #define POLLRDNORM POLLIN
37     #endif
38     #ifndef POLLWRNORM
39     #define POLLWRNORM POLLOUT
40     #endif
41    
42     static struct pollfd *pollfds;
43     static int pollmax = -1; /* highest FD number */
44     static dlink_node *hookptr;
45    
46     /*
47     * changing_fdlimit
48     *
49     * Resize pollfds array if necessary.
50     */
51     static void *
52     changing_fdlimit(va_list args)
53     {
54     int old_fdlimit = hard_fdlimit;
55    
56     pass_callback(hookptr, va_arg(args, int));
57    
58     if (hard_fdlimit != old_fdlimit)
59     pollfds = MyRealloc(pollfds, sizeof(struct pollfd) * hard_fdlimit);
60    
61     return NULL;
62     }
63    
64     /*
65     * init_netio
66     *
67     * This is a needed exported function which will be called to initialise
68     * the network loop code.
69     */
70     void
71     init_netio(void)
72     {
73     int fd;
74    
75     pollfds = MyMalloc(sizeof(struct pollfd) * hard_fdlimit);
76    
77     for (fd = 0; fd < hard_fdlimit; fd++)
78     pollfds[fd].fd = -1;
79    
80     hookptr = install_hook(fdlimit_cb, changing_fdlimit);
81     }
82    
83     /*
84     * find a spare slot in the fd list. We can optimise this out later!
85     * -- adrian
86     */
87     static inline int
88     poll_findslot(void)
89     {
90     int i;
91    
92     for (i = 0; i < hard_fdlimit; i++)
93     if (pollfds[i].fd == -1)
94     {
95     /* MATCH!!#$*&$ */
96     return i;
97     }
98    
99     assert(1 == 0);
100     /* NOTREACHED */
101     return -1;
102     }
103    
104     /*
105     * comm_setselect
106     *
107     * This is a needed exported function which will be called to register
108     * and deregister interest in a pending IO state for a given FD.
109     */
110     void
111     comm_setselect(fde_t *F, unsigned int type, PF *handler,
112     void *client_data, time_t timeout)
113     {
114     int new_events;
115    
116     if ((type & COMM_SELECT_READ))
117     {
118     F->read_handler = handler;
119     F->read_data = client_data;
120     }
121    
122     if ((type & COMM_SELECT_WRITE))
123     {
124     F->write_handler = handler;
125     F->write_data = client_data;
126     }
127    
128     new_events = (F->read_handler ? POLLRDNORM : 0) |
129     (F->write_handler ? POLLWRNORM : 0);
130    
131     if (timeout != 0)
132     F->timeout = CurrentTime + (timeout / 1000);
133    
134     if (new_events != F->evcache)
135     {
136     if (new_events == 0)
137     {
138     pollfds[F->comm_index].fd = -1;
139     pollfds[F->comm_index].revents = 0;
140    
141     if (pollmax == F->comm_index)
142     while (pollmax >= 0 && pollfds[pollmax].fd == -1)
143     pollmax--;
144     }
145     else
146     {
147     if (F->evcache == 0)
148     {
149     F->comm_index = poll_findslot();
150     if (F->comm_index > pollmax)
151     pollmax = F->comm_index;
152    
153     pollfds[F->comm_index].fd = F->fd;
154     }
155     pollfds[F->comm_index].events = new_events;
156     pollfds[F->comm_index].revents = 0;
157     }
158    
159     F->evcache = new_events;
160     }
161     }
162    
163     /*
164     * comm_select
165     *
166     * Called to do the new-style IO, courtesy of of squid (like most of this
167     * new IO code). This routine handles the stuff we've hidden in
168     * comm_setselect and fd_table[] and calls callbacks for IO ready
169     * events.
170     */
171     void
172     comm_select(void)
173     {
174     int num, ci, revents;
175     PF *hdl;
176     fde_t *F;
177    
178     /* XXX kill that +1 later ! -- adrian */
179     num = poll(pollfds, pollmax + 1, SELECT_DELAY);
180    
181     set_time();
182    
183     if (num < 0)
184     {
185     #ifdef HAVE_USLEEP
186     usleep(50000); /* avoid 99% CPU in comm_select */
187     #endif
188     return;
189     }
190    
191     for (ci = 0; ci <= pollmax && num > 0; ci++)
192     {
193     if ((revents = pollfds[ci].revents) == 0 || pollfds[ci].fd == -1)
194     continue;
195     num--;
196    
197     F = lookup_fd(pollfds[ci].fd);
198     if (F == NULL || !F->flags.open)
199     continue;
200    
201     if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
202     if ((hdl = F->read_handler) != NULL)
203     {
204     F->read_handler = NULL;
205     hdl(F, F->read_data);
206     if (!F->flags.open)
207     continue;
208     }
209    
210     if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
211     if ((hdl = F->write_handler) != NULL)
212     {
213     F->write_handler = NULL;
214     hdl(F, F->write_data);
215     if (!F->flags.open)
216     continue;
217     }
218    
219     comm_setselect(F, 0, NULL, NULL, 0);
220     }
221     }

Properties

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