]> git.ipfire.org Git - thirdparty/squid.git/blame - src/comm_kqueue.cc
Bug #2175: Update valgrind support for valgrind-3.3.0
[thirdparty/squid.git] / src / comm_kqueue.cc
CommitLineData
92b9f1fd 1
2/*
768d3d2f 3 * $Id: comm_kqueue.cc,v 1.17 2007/07/19 13:33:18 hno Exp $
92b9f1fd 4 *
507d0a78 5 * DEBUG: section 5 Socket Functions
92b9f1fd 6 *
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
9 *
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 *
33 */
34
35/*
36 * This code was originally written by Benno Rice and hacked on quite
37 * a bit by Adrian. Adrian then took it to the hybrid-ircd project to use
38 * in their new IO subsystem. After a year of modifications and some
39 * rather interesting changes (event aggregation) its back in squid.
40 * Thanks to the ircd-hybrid guys.
41 */
42
43/*
44 * XXX Currently not implemented / supported by this module XXX
45 *
46 * - delay pools
47 * - deferred reads
0a080ce3 48 * - flags.read_pending
92b9f1fd 49 *
50 * So, its not entirely useful in a production setup since if a read
51 * is meant to be deferred it isn't (we're not even throwing the event
52 * away here). Eventually the rest of the code will be rewritten
53 * so deferred reads aren't required.
54 * -- adrian
55 */
56
57#include "squid.h"
62ee09ca 58#include "comm_kqueue.h"
59#include "CacheManager.h"
e6ccf245 60#include "Store.h"
f0d40406 61#include "fde.h"
a4452e04 62#include "SquidTime.h"
92b9f1fd 63
64#ifdef USE_KQUEUE
65
66#include <sys/event.h>
67
68
71b7abe0 69#define KE_LENGTH 128
92b9f1fd 70
71/* jlemon goofed up and didn't add EV_SET until fbsd 4.3 */
72
73#ifndef EV_SET
74#define EV_SET(kevp, a, b, c, d, e, f) do { \
75 (kevp)->ident = (a); \
76 (kevp)->filter = (b); \
77 (kevp)->flags = (c); \
78 (kevp)->fflags = (d); \
79 (kevp)->data = (e); \
80 (kevp)->udata = (f); \
81} while(0)
82#endif
83
84static void kq_update_events(int, short, PF *);
85static int kq;
62e76326 86
92b9f1fd 87static struct timespec zero_timespec;
88
71b7abe0 89static struct kevent *kqlst; /* kevent buffer */
90static int kqmax; /* max structs to buffer */
91static int kqoff; /* offset into the buffer */
50198132 92static int max_poll_time = 1000;
92b9f1fd 93
94
95/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
96/* Private functions */
97
98void
99kq_update_events(int fd, short filter, PF * handler)
100{
101 PF *cur_handler;
102 int kep_flags;
103
92b9f1fd 104 switch (filter) {
62e76326 105
92b9f1fd 106 case EVFILT_READ:
71b7abe0 107 cur_handler = fd_table[fd].read_handler;
108 break;
62e76326 109
92b9f1fd 110 case EVFILT_WRITE:
71b7abe0 111 cur_handler = fd_table[fd].write_handler;
112 break;
62e76326 113
92b9f1fd 114 default:
71b7abe0 115 /* XXX bad! -- adrian */
116 return;
117 break;
92b9f1fd 118 }
119
120 if ((cur_handler == NULL && handler != NULL)
62e76326 121 || (cur_handler != NULL && handler == NULL)) {
122
71b7abe0 123 struct kevent *kep;
124
125 kep = kqlst + kqoff;
126
127 if (handler != NULL) {
128 kep_flags = (EV_ADD | EV_ONESHOT);
129 } else {
130 kep_flags = EV_DELETE;
131 }
132
133 EV_SET(kep, (uintptr_t) fd, filter, kep_flags, 0, 0, 0);
134
09729b90 135 /* Check if we've used the last one. If we have then submit them all */
136 if (kqoff == kqmax - 1) {
71b7abe0 137 int ret;
138
09729b90 139 ret = kevent(kq, kqlst, kqmax, NULL, 0, &zero_timespec);
71b7abe0 140 /* jdc -- someone needs to do error checking... */
62e76326 141
71b7abe0 142 if (ret == -1) {
143 perror("kq_update_events(): kevent()");
144 return;
145 }
62e76326 146
71b7abe0 147 kqoff = 0;
148 } else {
149 kqoff++;
150 }
92b9f1fd 151 }
152}
153
154
155
156/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
157/* Public functions */
158
159
160/*
161 * comm_select_init
162 *
163 * This is a needed exported function which will be called to initialise
164 * the network loop code.
165 */
166void
167comm_select_init(void)
168{
169 kq = kqueue();
62e76326 170
92b9f1fd 171 if (kq < 0) {
71b7abe0 172 fatal("comm_select_init: Couldn't open kqueue fd!\n");
92b9f1fd 173 }
62e76326 174
92b9f1fd 175 kqmax = getdtablesize();
62e76326 176
50198132 177 kqlst = (struct kevent *)xmalloc(sizeof(*kqlst) * kqmax);
92b9f1fd 178 zero_timespec.tv_sec = 0;
179 zero_timespec.tv_nsec = 0;
180}
181
182/*
183 * comm_setselect
184 *
185 * This is a needed exported function which will be called to register
186 * and deregister interest in a pending IO state for a given FD.
187 */
188void
189commSetSelect(int fd, unsigned int type, PF * handler,
62e76326 190 void *client_data, time_t timeout)
92b9f1fd 191{
192 fde *F = &fd_table[fd];
193 assert(fd >= 0);
194 assert(F->flags.open);
195
196 if (type & COMM_SELECT_READ) {
71b7abe0 197 kq_update_events(fd, EVFILT_READ, handler);
198 F->read_handler = handler;
199 F->read_data = client_data;
92b9f1fd 200 }
62e76326 201
92b9f1fd 202 if (type & COMM_SELECT_WRITE) {
71b7abe0 203 kq_update_events(fd, EVFILT_WRITE, handler);
204 F->write_handler = handler;
205 F->write_data = client_data;
92b9f1fd 206 }
62e76326 207
92b9f1fd 208 if (timeout)
71b7abe0 209 F->timeout = squid_curtime + timeout;
92b9f1fd 210
211}
212
213/*
214 * Check all connections for new connections and input data that is to be
215 * processed. Also check for connections with data queued and whether we can
216 * write it out.
217 */
218
219/*
220 * comm_select
221 *
222 * Called to do the new-style IO, courtesy of of squid (like most of this
223 * new IO code). This routine handles the stuff we've hidden in
224 * comm_setselect and fd_table[] and calls callbacks for IO ready
225 * events.
226 */
227
3d7e9d7c 228comm_err_t
92b9f1fd 229comm_select(int msec)
230{
231 int num, i;
62e76326 232
92b9f1fd 233 static struct kevent ke[KE_LENGTH];
62e76326 234
92b9f1fd 235 struct timespec poll_time;
236
50198132 237 if (msec > max_poll_time)
238 msec = max_poll_time;
62e76326 239
3de50fcd 240 poll_time.tv_sec = msec / 1000;
62e76326 241
3de50fcd 242 poll_time.tv_nsec = (msec % 1000) * 1000000;
62e76326 243
3de50fcd 244 for (;;) {
245 num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, &poll_time);
246 statCounter.select_loops++;
247 kqoff = 0;
62e76326 248
3de50fcd 249 if (num >= 0)
250 break;
62e76326 251
3de50fcd 252 if (ignoreErrno(errno))
253 break;
62e76326 254
71b7abe0 255 getCurrentTime();
62e76326 256
3de50fcd 257 return COMM_ERROR;
62e76326 258
3de50fcd 259 /* NOTREACHED */
260 }
261
262 getCurrentTime();
62e76326 263
3de50fcd 264 if (num == 0)
50198132 265 return COMM_OK; /* No error.. */
3de50fcd 266
267 for (i = 0; i < num; i++) {
268 int fd = (int) ke[i].ident;
269 PF *hdl = NULL;
270 fde *F = &fd_table[fd];
271
272 if (ke[i].flags & EV_ERROR) {
273 errno = ke[i].data;
274 /* XXX error == bad! -- adrian */
275 continue; /* XXX! */
276 }
62e76326 277
3de50fcd 278 switch (ke[i].filter) {
62e76326 279
280 case EVFILT_READ:
281
282 if ((hdl = F->read_handler) != NULL) {
283 F->read_handler = NULL;
0a080ce3 284 F->flags.read_pending = 0;
62e76326 285 hdl(fd, F->read_data);
286 }
287
288 break;
289
290 case EVFILT_WRITE:
291
292 if ((hdl = F->write_handler) != NULL) {
293 F->write_handler = NULL;
294 hdl(fd, F->write_data);
295 }
296
297 break;
298
299 default:
300 /* Bad! -- adrian */
bf8fe701 301 debugs(5, 1, "comm_select: kevent returned " << ke[i].filter << "!");
62e76326 302 break;
71b7abe0 303 }
92b9f1fd 304 }
62e76326 305
3de50fcd 306 return COMM_OK;
92b9f1fd 307}
308
50198132 309void
310comm_quick_poll_required(void)
311{
768d3d2f 312 max_poll_time = 10;
50198132 313}
314
d9088c69 315void
316commKQueueRegisterWithCacheManager(CacheManager & manager)
317{
318}
319
92b9f1fd 320#endif /* USE_KQUEUE */