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