]> git.ipfire.org Git - thirdparty/squid.git/blame - src/comm_kqueue.cc
Add in explicit typecast to silence gcc 4.x printf warnings under FreeBSD
[thirdparty/squid.git] / src / comm_kqueue.cc
CommitLineData
92b9f1fd 1
2/*
d9088c69 3 * $Id: comm_kqueue.cc,v 1.12 2006/09/02 10:43:10 adrian Exp $
92b9f1fd 4 *
5 * DEBUG: section 5 Socket functions
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
48 *
49 * So, its not entirely useful in a production setup since if a read
50 * is meant to be deferred it isn't (we're not even throwing the event
51 * away here). Eventually the rest of the code will be rewritten
52 * so deferred reads aren't required.
53 * -- adrian
54 */
55
56#include "squid.h"
62ee09ca 57#include "comm_kqueue.h"
58#include "CacheManager.h"
e6ccf245 59#include "Store.h"
f0d40406 60#include "fde.h"
a4452e04 61#include "SquidTime.h"
92b9f1fd 62
63#ifdef USE_KQUEUE
64
65#include <sys/event.h>
66
67
71b7abe0 68#define KE_LENGTH 128
92b9f1fd 69
70/* jlemon goofed up and didn't add EV_SET until fbsd 4.3 */
71
72#ifndef EV_SET
73#define EV_SET(kevp, a, b, c, d, e, f) do { \
74 (kevp)->ident = (a); \
75 (kevp)->filter = (b); \
76 (kevp)->flags = (c); \
77 (kevp)->fflags = (d); \
78 (kevp)->data = (e); \
79 (kevp)->udata = (f); \
80} while(0)
81#endif
82
83static void kq_update_events(int, short, PF *);
84static int kq;
62e76326 85
92b9f1fd 86static struct timespec zero_timespec;
87
71b7abe0 88static struct kevent *kqlst; /* kevent buffer */
89static int kqmax; /* max structs to buffer */
90static int kqoff; /* offset into the buffer */
50198132 91static int max_poll_time = 1000;
92b9f1fd 92
93
94/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
95/* Private functions */
96
97void
98kq_update_events(int fd, short filter, PF * handler)
99{
100 PF *cur_handler;
101 int kep_flags;
102
103#if 0
62e76326 104
92b9f1fd 105 int retval;
106#endif
107
108 switch (filter) {
62e76326 109
92b9f1fd 110 case EVFILT_READ:
71b7abe0 111 cur_handler = fd_table[fd].read_handler;
112 break;
62e76326 113
92b9f1fd 114 case EVFILT_WRITE:
71b7abe0 115 cur_handler = fd_table[fd].write_handler;
116 break;
62e76326 117
92b9f1fd 118 default:
71b7abe0 119 /* XXX bad! -- adrian */
120 return;
121 break;
92b9f1fd 122 }
123
124 if ((cur_handler == NULL && handler != NULL)
62e76326 125 || (cur_handler != NULL && handler == NULL)) {
126
71b7abe0 127 struct kevent *kep;
128
129 kep = kqlst + kqoff;
130
131 if (handler != NULL) {
132 kep_flags = (EV_ADD | EV_ONESHOT);
133 } else {
134 kep_flags = EV_DELETE;
135 }
136
137 EV_SET(kep, (uintptr_t) fd, filter, kep_flags, 0, 0, 0);
138
139 if (kqoff == kqmax) {
140 int ret;
141
142 ret = kevent(kq, kqlst, kqoff, NULL, 0, &zero_timespec);
143 /* jdc -- someone needs to do error checking... */
62e76326 144
71b7abe0 145 if (ret == -1) {
146 perror("kq_update_events(): kevent()");
147 return;
148 }
62e76326 149
71b7abe0 150 kqoff = 0;
151 } else {
152 kqoff++;
153 }
62e76326 154
92b9f1fd 155#if 0
71b7abe0 156 if (retval < 0) {
157 /* Error! */
62e76326 158
71b7abe0 159 if (ke.flags & EV_ERROR) {
160 errno = ke.data;
161 }
162 }
62e76326 163
92b9f1fd 164#endif
62e76326 165
92b9f1fd 166 }
167}
168
169
170
171/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
172/* Public functions */
173
174
175/*
176 * comm_select_init
177 *
178 * This is a needed exported function which will be called to initialise
179 * the network loop code.
180 */
181void
182comm_select_init(void)
183{
184 kq = kqueue();
62e76326 185
92b9f1fd 186 if (kq < 0) {
71b7abe0 187 fatal("comm_select_init: Couldn't open kqueue fd!\n");
92b9f1fd 188 }
62e76326 189
92b9f1fd 190 kqmax = getdtablesize();
62e76326 191
50198132 192 kqlst = (struct kevent *)xmalloc(sizeof(*kqlst) * kqmax);
92b9f1fd 193 zero_timespec.tv_sec = 0;
194 zero_timespec.tv_nsec = 0;
195}
196
197/*
198 * comm_setselect
199 *
200 * This is a needed exported function which will be called to register
201 * and deregister interest in a pending IO state for a given FD.
202 */
203void
204commSetSelect(int fd, unsigned int type, PF * handler,
62e76326 205 void *client_data, time_t timeout)
92b9f1fd 206{
207 fde *F = &fd_table[fd];
208 assert(fd >= 0);
209 assert(F->flags.open);
210
211 if (type & COMM_SELECT_READ) {
71b7abe0 212 kq_update_events(fd, EVFILT_READ, handler);
213 F->read_handler = handler;
214 F->read_data = client_data;
92b9f1fd 215 }
62e76326 216
92b9f1fd 217 if (type & COMM_SELECT_WRITE) {
71b7abe0 218 kq_update_events(fd, EVFILT_WRITE, handler);
219 F->write_handler = handler;
220 F->write_data = client_data;
92b9f1fd 221 }
62e76326 222
92b9f1fd 223 if (timeout)
71b7abe0 224 F->timeout = squid_curtime + timeout;
92b9f1fd 225
226}
227
228/*
229 * Check all connections for new connections and input data that is to be
230 * processed. Also check for connections with data queued and whether we can
231 * write it out.
232 */
233
234/*
235 * comm_select
236 *
237 * Called to do the new-style IO, courtesy of of squid (like most of this
238 * new IO code). This routine handles the stuff we've hidden in
239 * comm_setselect and fd_table[] and calls callbacks for IO ready
240 * events.
241 */
242
3d7e9d7c 243comm_err_t
92b9f1fd 244comm_select(int msec)
245{
246 int num, i;
62e76326 247
92b9f1fd 248 static struct kevent ke[KE_LENGTH];
62e76326 249
92b9f1fd 250 struct timespec poll_time;
251
3de50fcd 252 /*
253 * remember we are doing NANOseconds here, not micro/milli. God knows
254 * why jlemon used a timespec, but hey, he wrote the interface, not I
255 * -- Adrian
256 */
62e76326 257
50198132 258 if (msec > max_poll_time)
259 msec = max_poll_time;
62e76326 260
3de50fcd 261 poll_time.tv_sec = msec / 1000;
62e76326 262
3de50fcd 263 poll_time.tv_nsec = (msec % 1000) * 1000000;
62e76326 264
3de50fcd 265 for (;;) {
266 num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, &poll_time);
267 statCounter.select_loops++;
268 kqoff = 0;
62e76326 269
3de50fcd 270 if (num >= 0)
271 break;
62e76326 272
3de50fcd 273 if (ignoreErrno(errno))
274 break;
62e76326 275
71b7abe0 276 getCurrentTime();
62e76326 277
3de50fcd 278 return COMM_ERROR;
62e76326 279
3de50fcd 280 /* NOTREACHED */
281 }
282
283 getCurrentTime();
62e76326 284
3de50fcd 285 if (num == 0)
50198132 286 return COMM_OK; /* No error.. */
3de50fcd 287
288 for (i = 0; i < num; i++) {
289 int fd = (int) ke[i].ident;
290 PF *hdl = NULL;
291 fde *F = &fd_table[fd];
292
293 if (ke[i].flags & EV_ERROR) {
294 errno = ke[i].data;
295 /* XXX error == bad! -- adrian */
296 continue; /* XXX! */
297 }
62e76326 298
3de50fcd 299 switch (ke[i].filter) {
62e76326 300
301 case EVFILT_READ:
302
303 if ((hdl = F->read_handler) != NULL) {
304 F->read_handler = NULL;
305 hdl(fd, F->read_data);
306 }
307
308 break;
309
310 case EVFILT_WRITE:
311
312 if ((hdl = F->write_handler) != NULL) {
313 F->write_handler = NULL;
314 hdl(fd, F->write_data);
315 }
316
317 break;
318
319 default:
320 /* Bad! -- adrian */
321 debug(5, 1) ("comm_select: kevent returned %d!\n", ke[i].filter);
322 break;
71b7abe0 323 }
92b9f1fd 324 }
62e76326 325
3de50fcd 326 return COMM_OK;
92b9f1fd 327}
328
50198132 329void
330comm_quick_poll_required(void)
331{
332 max_poll_time = 100;
333}
334
d9088c69 335void
336commKQueueRegisterWithCacheManager(CacheManager & manager)
337{
338}
339
92b9f1fd 340#endif /* USE_KQUEUE */