]> jfr.im git - irc/evilnet/x3.git/blame - src/ioset-kevent.c
Fix typos and copy errors in chanserv help
[irc/evilnet/x3.git] / src / ioset-kevent.c
CommitLineData
1136f709 1/* ioset kqueue()/kevent() backend for srvx
2 * Copyright 2008 srvx Development Team
3 *
4 * This file is part of srvx.
5 *
6 * srvx is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
be2c97a5 8 * the Free Software Foundation; either version 3 of the License, or
1136f709 9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 */
20
21#include "ioset-impl.h"
22#include "common.h"
23#include "log.h"
24
25#ifdef HAVE_SYS_EVENT_H
26# include <sys/event.h>
27#endif
28
29#define MAX_EVENTS 16
30
31extern int clock_skew;
32static int kq_fd;
33
34static int
35ioset_kevent_init(void)
36{
37 kq_fd = kqueue();
38 return kq_fd >= 0;
39}
40
41static void
42ioset_kevent_add(struct io_fd *fd)
43{
44 struct kevent changes[2];
45 int nchanges = 0;
46 int res;
47
48 EV_SET(&changes[nchanges++], fd->fd, EVFILT_READ, EV_ADD, 0, 0, fd);
e9df2b7d 49 if (fd_wants_writes(fd)) {
50 EV_SET(&changes[nchanges++], fd->fd, EVFILT_WRITE, EV_ADD, 0, 0, fd);
51 }
1136f709 52 res = kevent(kq_fd, changes, nchanges, NULL, 0, NULL);
53 if (res < 0) {
54 log_module(MAIN_LOG, LOG_ERROR, "kevent() add failed: %s", strerror(errno));
55 }
56}
57
58static void
59ioset_kevent_remove(struct io_fd *fd, int closed)
60{
61 if (!closed) {
62 struct kevent changes[2];
63 int nchanges = 0;
64 int res;
65
66 EV_SET(&changes[nchanges++], fd->fd, EVFILT_READ, EV_DELETE, 0, 0, fd);
67 EV_SET(&changes[nchanges++], fd->fd, EVFILT_WRITE, EV_DELETE, 0, 0, fd);
68 res = kevent(kq_fd, changes, nchanges, NULL, 0, NULL);
69 if (res < 0) {
70 log_module(MAIN_LOG, LOG_ERROR, "kevent() remove failed: %s", strerror(errno));
71 }
72 }
73}
74
75static void
76ioset_kevent_update(struct io_fd *fd)
77{
e9df2b7d 78 struct kevent changes[2];
79 int nchanges = 0;
80 int res;
81
82 EV_SET(&changes[nchanges++], fd->fd, EVFILT_READ, EV_ADD, 0, 0, fd);
83 EV_SET(&changes[nchanges++], fd->fd, EVFILT_WRITE, fd_wants_writes(fd) ? EV_ADD : EV_DELETE, 0, 0, fd);
84 res = kevent(kq_fd, changes, nchanges, NULL, 0, NULL);
85 if (res < 0) {
86 log_module(MAIN_LOG, LOG_ERROR, "kevent() add failed: %s", strerror(errno));
87 }
1136f709 88}
89
90static void
91ioset_kevent_cleanup(void)
92{
93 close(kq_fd);
94}
95
96static int
97ioset_kevent_loop(struct timeval *timeout)
98{
99 struct kevent events[MAX_EVENTS];
100 struct timespec ts;
101 struct timespec *pts;
102 int is_write;
103 int is_read;
104 int res;
105 int ii;
106
107 /* Try to get events from the kernel. */
108 if (timeout) {
109 ts.tv_sec = timeout->tv_sec;
110 ts.tv_nsec = timeout->tv_usec * 1000;
111 pts = &ts;
112 } else {
113 pts = NULL;
114 }
115 res = kevent(kq_fd, NULL, 0, events, MAX_EVENTS, pts);
e9df2b7d 116 if ((res < 0) && (errno != EINTR)) {
1136f709 117 log_module(MAIN_LOG, LOG_ERROR, "kevent() poll failed: %s", strerror(errno));
118 return 1;
119 }
120 now = time(NULL) + clock_skew;
121
122 /* Process the events we got. */
123 for (ii = 0; ii < res; ++ii) {
124 is_write = events[ii].filter == EVFILT_WRITE;
125 is_read = events[ii].filter == EVFILT_READ;
126 ioset_events(events[ii].udata, is_read, is_write);
127 }
128
129 return 0;
130}
131
132struct io_engine io_engine_kevent = {
133 .name = "kevent",
134 .init = ioset_kevent_init,
135 .add = ioset_kevent_add,
136 .remove = ioset_kevent_remove,
137 .update = ioset_kevent_update,
138 .loop = ioset_kevent_loop,
139 .cleanup = ioset_kevent_cleanup,
140};