3
* $Id: comm_kqueue.cc,v 1.12 2006/09/02 10:43:10 adrian Exp $
5
* DEBUG: section 5 Socket functions
7
* SQUID Web Proxy Cache http://www.squid-cache.org/
8
* ----------------------------------------------------------
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.
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.
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.
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.
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.
44
* XXX Currently not implemented / supported by this module XXX
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.
57
#include "comm_kqueue.h"
58
#include "CacheManager.h"
61
#include "SquidTime.h"
65
#include <sys/event.h>
70
/* jlemon goofed up and didn't add EV_SET until fbsd 4.3 */
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); \
79
(kevp)->udata = (f); \
83
static void kq_update_events(int, short, PF *);
86
static struct timespec zero_timespec;
88
static struct kevent *kqlst; /* kevent buffer */
89
static int kqmax; /* max structs to buffer */
90
static int kqoff; /* offset into the buffer */
91
static int max_poll_time = 1000;
94
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
95
/* Private functions */
98
kq_update_events(int fd, short filter, PF * handler)
111
cur_handler = fd_table[fd].read_handler;
115
cur_handler = fd_table[fd].write_handler;
119
/* XXX bad! -- adrian */
124
if ((cur_handler == NULL && handler != NULL)
125
|| (cur_handler != NULL && handler == NULL)) {
131
if (handler != NULL) {
132
kep_flags = (EV_ADD | EV_ONESHOT);
134
kep_flags = EV_DELETE;
137
EV_SET(kep, (uintptr_t) fd, filter, kep_flags, 0, 0, 0);
139
if (kqoff == kqmax) {
142
ret = kevent(kq, kqlst, kqoff, NULL, 0, &zero_timespec);
143
/* jdc -- someone needs to do error checking... */
146
perror("kq_update_events(): kevent()");
159
if (ke.flags & EV_ERROR) {
171
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
172
/* Public functions */
178
* This is a needed exported function which will be called to initialise
179
* the network loop code.
182
comm_select_init(void)
187
fatal("comm_select_init: Couldn't open kqueue fd!\n");
190
kqmax = getdtablesize();
192
kqlst = (struct kevent *)xmalloc(sizeof(*kqlst) * kqmax);
193
zero_timespec.tv_sec = 0;
194
zero_timespec.tv_nsec = 0;
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.
204
commSetSelect(int fd, unsigned int type, PF * handler,
205
void *client_data, time_t timeout)
207
fde *F = &fd_table[fd];
209
assert(F->flags.open);
211
if (type & COMM_SELECT_READ) {
212
kq_update_events(fd, EVFILT_READ, handler);
213
F->read_handler = handler;
214
F->read_data = client_data;
217
if (type & COMM_SELECT_WRITE) {
218
kq_update_events(fd, EVFILT_WRITE, handler);
219
F->write_handler = handler;
220
F->write_data = client_data;
224
F->timeout = squid_curtime + timeout;
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
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
244
comm_select(int msec)
248
static struct kevent ke[KE_LENGTH];
250
struct timespec poll_time;
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
258
if (msec > max_poll_time)
259
msec = max_poll_time;
261
poll_time.tv_sec = msec / 1000;
263
poll_time.tv_nsec = (msec % 1000) * 1000000;
266
num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, &poll_time);
267
statCounter.select_loops++;
273
if (ignoreErrno(errno))
286
return COMM_OK; /* No error.. */
288
for (i = 0; i < num; i++) {
289
int fd = (int) ke[i].ident;
291
fde *F = &fd_table[fd];
293
if (ke[i].flags & EV_ERROR) {
295
/* XXX error == bad! -- adrian */
299
switch (ke[i].filter) {
303
if ((hdl = F->read_handler) != NULL) {
304
F->read_handler = NULL;
305
hdl(fd, F->read_data);
312
if ((hdl = F->write_handler) != NULL) {
313
F->write_handler = NULL;
314
hdl(fd, F->write_data);
321
debug(5, 1) ("comm_select: kevent returned %d!\n", ke[i].filter);
330
comm_quick_poll_required(void)
336
commKQueueRegisterWithCacheManager(CacheManager & manager)
340
#endif /* USE_KQUEUE */