]>
jfr.im git - solanum.git/blob - libratbox/src/kqueue.c
faeacd3d532411a8b60cb5d611df3bd842e5d548
2 * ircd-ratbox: A slightly useful ircd.
3 * kqueue.c: FreeBSD kqueue compatible network routines.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2001 Adrian Chadd <adrian@creative.net.au>
8 * Copyright (C) 2002-2005 ircd-ratbox development team
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
25 * $Id: kqueue.c 25038 2008-01-23 16:03:08Z androsyn $
28 #include <libratbox_config.h>
29 #include <ratbox_lib.h>
30 #include <commio-int.h>
31 #include <event-int.h>
33 #if defined(HAVE_SYS_EVENT_H) && (HAVE_KEVENT)
35 #include <sys/event.h>
39 /* jlemon goofed up and didn't add EV_SET until fbsd 4.3 */
42 #define EV_SET(kevp, a, b, c, d, e, f) do { \
43 (kevp)->ident = (a); \
44 (kevp)->filter = (b); \
45 (kevp)->flags = (c); \
46 (kevp)->fflags = (d); \
48 (kevp)->udata = (f); \
53 #define KQUEUE_SCHED_EVENT
57 static void kq_update_events(rb_fde_t
*, short, PF
*);
59 static struct timespec zero_timespec
;
61 static struct kevent
*kqlst
; /* kevent buffer */
62 static int kqmax
; /* max structs to buffer */
63 static int kqoff
; /* offset into the buffer */
67 rb_setup_fd_kqueue(rb_fde_t
* F
)
73 kq_update_events(rb_fde_t
* F
, short filter
, PF
* handler
)
81 cur_handler
= F
->read_handler
;
84 cur_handler
= F
->write_handler
;
87 /* XXX bad! -- adrian */
92 if((cur_handler
== NULL
&& handler
!= NULL
) || (cur_handler
!= NULL
&& handler
== NULL
))
100 if(filter
== EVFILT_WRITE
)
101 kep_flags
= (EV_ADD
| EV_ONESHOT
);
107 kep_flags
= EV_DELETE
;
110 EV_SET(kep
, (uintptr_t) F
->fd
, filter
, kep_flags
, 0, 0, (void *) F
);
116 ret
= kevent(kq
, kqlst
, kqoff
, NULL
, 0, &zero_timespec
);
117 /* jdc -- someone needs to do error checking... */
120 rb_lib_log("kq_update_events(): kevent(): %s", strerror(errno
));
130 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
131 /* Public functions */
137 * This is a needed exported function which will be called to initialise
138 * the network loop code.
141 rb_init_netio_kqueue(void)
148 kqmax
= getdtablesize();
149 kqlst
= rb_malloc(sizeof(struct kevent
) * kqmax
);
150 rb_open(kq
, RB_FD_UNKNOWN
, "kqueue fd");
151 zero_timespec
.tv_sec
= 0;
152 zero_timespec
.tv_nsec
= 0;
160 * This is a needed exported function which will be called to register
161 * and deregister interest in a pending IO state for a given FD.
164 rb_setselect_kqueue(rb_fde_t
* F
, unsigned int type
, PF
* handler
, void *client_data
)
166 lrb_assert(IsFDOpen(F
));
168 if(type
& RB_SELECT_READ
)
170 kq_update_events(F
, EVFILT_READ
, handler
);
171 F
->read_handler
= handler
;
172 F
->read_data
= client_data
;
174 if(type
& RB_SELECT_WRITE
)
176 kq_update_events(F
, EVFILT_WRITE
, handler
);
177 F
->write_handler
= handler
;
178 F
->write_data
= client_data
;
183 * Check all connections for new connections and input data that is to be
184 * processed. Also check for connections with data queued and whether we can
191 * Called to do the new-style IO, courtesy of squid (like most of this
192 * new IO code). This routine handles the stuff we've hidden in
193 * rb_setselect and fd_table[] and calls callbacks for IO ready
198 rb_select_kqueue(long delay
)
201 static struct kevent ke
[KE_LENGTH
];
202 struct timespec poll_time
;
212 poll_time
.tv_sec
= delay
/ 1000;
213 poll_time
.tv_nsec
= (delay
% 1000) * 1000000;
218 num
= kevent(kq
, kqlst
, kqoff
, ke
, KE_LENGTH
, pt
);
224 if(rb_ignore_errno(errno
))
237 return RB_OK
; /* No error.. */
239 for (i
= 0; i
< num
; i
++)
243 if(ke
[i
].flags
& EV_ERROR
)
246 /* XXX error == bad! -- adrian */
250 switch (ke
[i
].filter
)
255 if((hdl
= F
->read_handler
) != NULL
)
257 F
->read_handler
= NULL
;
258 hdl(F
, F
->read_data
);
265 if((hdl
= F
->write_handler
) != NULL
)
267 F
->write_handler
= NULL
;
268 hdl(F
, F
->write_data
);
271 #if defined(EVFILT_TIMER)
273 rb_run_event(ke
[i
].udata
);
283 static int can_do_event
= 0;
285 rb_kqueue_supports_event(void)
291 if(can_do_event
== 1)
293 if(can_do_event
== -1)
301 EV_SET(&kv
, (uintptr_t) 0x0, EVFILT_TIMER
, EV_ADD
| EV_ONESHOT
, 0, 1, 0);
302 if(kevent(xkq
, &kv
, 1, NULL
, 0, NULL
) < 0)
314 rb_kqueue_sched_event(struct ev_entry
*event
, int when
)
320 if(event
->frequency
== 0)
321 kep_flags
|= EV_ONESHOT
;
322 EV_SET(&kev
, (uintptr_t) event
, EVFILT_TIMER
, kep_flags
, 0, when
* 1000, event
);
323 if(kevent(kq
, &kev
, 1, NULL
, 0, NULL
) < 0)
329 rb_kqueue_unsched_event(struct ev_entry
*event
)
332 EV_SET(&kev
, (uintptr_t) event
, EVFILT_TIMER
, EV_DELETE
, 0, 0, event
);
333 kevent(kq
, &kev
, 1, NULL
, 0, NULL
);
337 rb_kqueue_init_event(void)
342 #else /* kqueue not supported */
344 rb_init_netio_kqueue(void)
351 rb_setselect_kqueue(rb_fde_t
* F
, unsigned int type
, PF
* handler
, void *client_data
)
358 rb_select_kqueue(long delay
)
365 rb_setup_fd_kqueue(rb_fde_t
* F
)
373 #if !defined(HAVE_KEVENT) || !defined(KQUEUE_SCHED_EVENT)
375 rb_kqueue_init_event(void)
381 rb_kqueue_sched_event(struct ev_entry
*event
, int when
)
388 rb_kqueue_unsched_event(struct ev_entry
*event
)
394 rb_kqueue_supports_event(void)
399 #endif /* !HAVE_KEVENT || !KQUEUE_SCHED_EVENT */