ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/s_bsd_poll.c
Revision: 34
Committed: Sun Oct 2 21:05:51 2005 UTC (18 years, 5 months ago) by lusky
Content type: text/x-csrc
File size: 4871 byte(s)
Log Message:
create 7.2 branch, we can move/rename it as needed.


File Contents

# Content
1 /*
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 * $Id$
24 */
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 Id Revision