Annotation of embedaddon/lighttpd/src/fdevent_freebsd_kqueue.c, revision 1.1.1.1
1.1 misho 1: #include "fdevent.h"
2: #include "buffer.h"
3: #include "log.h"
4:
5: #include <sys/types.h>
6:
7: #include <unistd.h>
8: #include <stdlib.h>
9: #include <stdio.h>
10: #include <string.h>
11: #include <errno.h>
12: #include <signal.h>
13: #include <fcntl.h>
14:
15: #ifdef USE_FREEBSD_KQUEUE
16: # include <sys/event.h>
17: # include <sys/time.h>
18:
19: static void fdevent_freebsd_kqueue_free(fdevents *ev) {
20: close(ev->kq_fd);
21: free(ev->kq_results);
22: }
23:
24: static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) {
25: int ret, n = 0;
26: struct kevent kev[2];
27: struct timespec ts;
28: int oevents;
29:
30: if (fde_ndx < 0) return -1;
31:
32: oevents = ev->fdarray[fd]->events;
33:
34: if (oevents & FDEVENT_IN) {
35: EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
36: n++;
37: }
38: if (oevents & FDEVENT_OUT) {
39: EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
40: n++;
41: }
42:
43: if (0 == n) return -1;
44:
45: ts.tv_sec = 0;
46: ts.tv_nsec = 0;
47:
48: ret = kevent(ev->kq_fd,
49: &kev, n,
50: NULL, 0,
51: &ts);
52:
53: if (ret == -1) {
54: log_error_write(ev->srv, __FILE__, __LINE__, "SS",
55: "kqueue event delete failed: ", strerror(errno));
56:
57: return -1;
58: }
59:
60: return -1;
61: }
62:
63: static int fdevent_freebsd_kqueue_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
64: int ret, n = 0;
65: struct kevent kev[2];
66: struct timespec ts;
67: int oevents = ev->fdarray[fd]->events;
68: int addevents = events & ~oevents;
69: int delevents = ~events & oevents;
70:
71: UNUSED(fde_ndx);
72:
73: if (events == oevents) return fd;
74:
75: if (addevents & FDEVENT_IN) {
76: EV_SET(&kev[n], fd, EVFILT_READ, EV_ADD|EV_CLEAR, 0, 0, NULL);
77: n++;
78: } else if (delevents & FDEVENT_IN) {
79: EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
80: n++;
81: }
82: if (addevents & FDEVENT_OUT) {
83: EV_SET(&kev[n], fd, EVFILT_WRITE, EV_ADD|EV_CLEAR, 0, 0, NULL);
84: n++;
85: } else if (delevents & FDEVENT_OUT) {
86: EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
87: n++;
88: }
89:
90: if (0 == n) return fd;
91:
92: ts.tv_sec = 0;
93: ts.tv_nsec = 0;
94:
95: ret = kevent(ev->kq_fd,
96: kev, n,
97: NULL, 0,
98: &ts);
99:
100: if (ret == -1) {
101: log_error_write(ev->srv, __FILE__, __LINE__, "SS",
102: "kqueue event set failed: ", strerror(errno));
103:
104: return -1;
105: }
106:
107: return fd;
108: }
109:
110: static int fdevent_freebsd_kqueue_poll(fdevents *ev, int timeout_ms) {
111: int ret;
112: struct timespec ts;
113:
114: ts.tv_sec = timeout_ms / 1000;
115: ts.tv_nsec = (timeout_ms % 1000) * 1000000;
116:
117: ret = kevent(ev->kq_fd,
118: NULL, 0,
119: ev->kq_results, ev->maxfds,
120: &ts);
121:
122: if (ret == -1) {
123: switch(errno) {
124: case EINTR:
125: /* we got interrupted, perhaps just a SIGCHLD of a CGI script */
126: return 0;
127: default:
128: log_error_write(ev->srv, __FILE__, __LINE__, "SS",
129: "kqueue failed polling: ", strerror(errno));
130: break;
131: }
132: }
133:
134: return ret;
135: }
136:
137: static int fdevent_freebsd_kqueue_event_get_revent(fdevents *ev, size_t ndx) {
138: int events = 0, e;
139:
140: e = ev->kq_results[ndx].filter;
141:
142: if (e == EVFILT_READ) {
143: events |= FDEVENT_IN;
144: } else if (e == EVFILT_WRITE) {
145: events |= FDEVENT_OUT;
146: }
147:
148: e = ev->kq_results[ndx].flags;
149:
150: if (e & EV_EOF) {
151: events |= FDEVENT_HUP;
152: }
153:
154: if (e & EV_ERROR) {
155: events |= FDEVENT_ERR;
156: }
157:
158: return events;
159: }
160:
161: static int fdevent_freebsd_kqueue_event_get_fd(fdevents *ev, size_t ndx) {
162: return ev->kq_results[ndx].ident;
163: }
164:
165: static int fdevent_freebsd_kqueue_event_next_fdndx(fdevents *ev, int ndx) {
166: UNUSED(ev);
167:
168: return (ndx < 0) ? 0 : ndx + 1;
169: }
170:
171: static int fdevent_freebsd_kqueue_reset(fdevents *ev) {
172: if (-1 == (ev->kq_fd = kqueue())) {
173: log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
174: "kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
175:
176: return -1;
177: }
178:
179: return 0;
180: }
181:
182:
183: int fdevent_freebsd_kqueue_init(fdevents *ev) {
184: ev->type = FDEVENT_HANDLER_FREEBSD_KQUEUE;
185: #define SET(x) \
186: ev->x = fdevent_freebsd_kqueue_##x;
187:
188: SET(free);
189: SET(poll);
190: SET(reset);
191:
192: SET(event_del);
193: SET(event_set);
194:
195: SET(event_next_fdndx);
196: SET(event_get_fd);
197: SET(event_get_revent);
198:
199: ev->kq_fd = -1;
200:
201: ev->kq_results = calloc(ev->maxfds, sizeof(*ev->kq_results));
202:
203: /* check that kqueue works */
204:
205: if (-1 == (ev->kq_fd = kqueue())) {
206: log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
207: "kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
208:
209: return -1;
210: }
211:
212: close(ev->kq_fd);
213: ev->kq_fd = -1;
214:
215: return 0;
216: }
217: #else
218: int fdevent_freebsd_kqueue_init(fdevents *ev) {
219: UNUSED(ev);
220:
221: log_error_write(ev->srv, __FILE__, __LINE__, "S",
222: "kqueue not available, try to set server.event-handler = \"poll\" or \"select\"");
223:
224: return -1;
225: }
226: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>