comparison src/event/modules/ngx_kqueue_module.c @ 0:4eff17414a43

nginx-0.0.1-2002-08-06-20:39:45 import The first code that uses "ngx_" prefix, the previous one used "gx_" prefix. At that point the code is not yet usable. The first draft ideas are dated back to 23.10.2001.
author Igor Sysoev <igor@sysoev.ru>
date Tue, 06 Aug 2002 16:39:45 +0000
parents
children 669801705ab1
comparison
equal deleted inserted replaced
-1:000000000000 0:4eff17414a43
1 /*
2 * Copyright (C) 2002 Igor Sysoev, http://sysoev.ru
3 */
4
5 /*
6 NEED ? : unify change_list and event_list:
7 event_list = change_list;
8 */
9
10 #include <ngx_config.h>
11 #include <ngx_types.h>
12 #include <ngx_log.h>
13 #include <ngx_connection.h>
14 #include <ngx_event.h>
15 #include <ngx_kqueue_module.h>
16
17 #if (USE_KQUEUE) && !(HAVE_KQUEUE)
18 #error "kqueue is not supported on this platform"
19 #endif
20
21 static void ngx_add_timer(ngx_event_t *ev, u_int timer);
22 static void ngx_inline ngx_del_timer(ngx_event_t *ev);
23
24
25 static int kq;
26 static struct kevent *change_list, *event_list;
27 static int nchanges, nevents;
28
29 static ngx_event_t timer_queue;
30
31 void ngx_kqueue_init(int max_connections, ngx_log_t *log)
32 {
33 int size = sizeof(struct kevent) * 512;
34
35 nchanges = 0;
36 nevents = 512;
37
38 if ((kq = kqueue()) == -1)
39 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
40 "ngx_kqueue_init: kqueue failed");
41
42 change_list = ngx_alloc(size, log);
43 event_list = ngx_alloc(size, log);
44
45 timer_queue.timer_prev = &timer_queue;
46 timer_queue.timer_next = &timer_queue;
47
48 #if !(USE_KQUEUE)
49 ngx_event_actions.add = ngx_kqueue_add_event;
50 ngx_event_actions.del = ngx_kqueue_del_event;
51 ngx_event_actions.process = ngx_kqueue_process_events;
52 #endif
53
54 }
55
56 int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags)
57 {
58 if (event == NGX_TIMER_EVENT) {
59 ngx_add_timer(ev, flags);
60 return 0;
61 }
62
63 return ngx_kqueue_set_event(ev, event, EV_ADD | flags);
64 }
65
66 int ngx_kqueue_del_event(ngx_event_t *ev, int event)
67 {
68 if (event == NGX_TIMER_EVENT) {
69 ngx_del_timer(ev);
70 return 0;
71 }
72
73 return ngx_kqueue_set_event(ev, event, EV_DELETE);
74 }
75
76 int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags)
77 {
78 struct timespec ts = { 0, 0 };
79 ngx_connection_t *cn = (ngx_connection_t *) ev->data;
80
81 ngx_log_debug(ev->log, "ngx_kqueue_set_event: %d: ft:%d f:%08x" _
82 cn->fd _ filter _ flags);
83
84 if (nchanges >= nevents) {
85 ngx_log_error(NGX_LOG_WARN, ev->log, 0,
86 "ngx_kqueue_set_event: change list is filled up");
87
88 if (kevent(kq, change_list, nchanges, NULL, 0, &ts) == -1) {
89 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
90 "ngx_kqueue_set_event: kevent failed");
91 return -1;
92 }
93 nchanges = 0;
94 }
95
96 change_list[nchanges].ident = cn->fd;
97 change_list[nchanges].filter = filter;
98 change_list[nchanges].flags = flags;
99 change_list[nchanges].fflags = 0;
100 change_list[nchanges].data = 0;
101 change_list[nchanges].udata = ev;
102 nchanges++;
103
104 return 0;
105 }
106
107 int ngx_kqueue_process_events(ngx_log_t *log)
108 {
109 int events, i;
110 u_int timer = 0, delta = 0;
111 ngx_event_t *ev, *nx;
112 struct timeval tv;
113 struct timespec ts, *tp = NULL;
114
115 if (timer_queue.timer_next != &timer_queue) {
116 timer = timer_queue.timer_next->timer_delta;
117 ts.tv_sec = timer / 1000;
118 ts.tv_nsec = (timer % 1000) * 1000000;
119 tp = &ts;
120 gettimeofday(&tv, NULL);
121 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000;
122 }
123
124 ngx_log_debug(log, "ngx_kqueue_process_events: timer: %d" _ timer);
125
126 if ((events = kevent(kq, change_list, nchanges, event_list, nevents, tp))
127 == -1) {
128 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
129 "ngx_kqueue_process_events: kevent failed");
130 return -1;
131 }
132
133 nchanges = 0;
134
135 if (timer) {
136 gettimeofday(&tv, NULL);
137 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
138
139 } else {
140 ngx_assert((events != 0), return -1, log,
141 "ngx_kqueue_process_events: "
142 "kevent returns no events without timeout");
143 }
144
145 ngx_log_debug(log, "ngx_kqueue_process_events: "
146 "timer: %d, delta: %d" _ timer _ delta);
147
148 if (timer) {
149 if (delta >= timer) {
150 for (ev = timer_queue.timer_next;
151 ev != &timer_queue && delta >= ev->timer_delta;
152 /* void */)
153 {
154 delta -= ev->timer_delta;
155 nx = ev->timer_next;
156 ngx_del_timer(ev);
157 if (ev->timer_handler(ev) == -1)
158 ev->close_handler(ev);
159 ev = nx;
160 }
161
162 } else {
163 timer_queue.timer_next->timer_delta -= delta;
164 }
165 }
166
167 for (i = 0; i < events; i++) {
168
169 ngx_log_debug(log, "ngx_kqueue_process_events: kevent: "
170 "%d: ft:%d f:%08x ff:%08x d:%d ud:%08x" _
171 event_list[i].ident _ event_list[i].filter _
172 event_list[i].flags _ event_list[i].fflags _
173 event_list[i].data _ event_list[i].udata);
174
175 if (event_list[i].flags & EV_ERROR) {
176 ngx_log_error(NGX_LOG_ALERT, log, event_list[i].data,
177 "ngx_kqueue_process_events: kevent error");
178 continue;
179 }
180
181 ev = (ngx_event_t *) event_list[i].udata;
182
183 switch (event_list[i].filter) {
184
185 case EVFILT_READ:
186 case EVFILT_WRITE:
187 ev->ready = 1;
188 ev->available = event_list[i].data;
189
190 if (event_list[i].flags & EV_EOF) {
191 ev->eof = 1;
192 ev->error = event_list[i].fflags;
193 }
194
195 if (ev->event_handler(ev) == -1)
196 ev->close_handler(ev);
197
198 break;
199
200 default:
201 ngx_assert(0, /* void */, log,
202 "ngx_kqueue_process_events: unknown filter %d" _
203 event_list[i].filter);
204 }
205 }
206
207 return 0;
208 }
209
210 static void ngx_add_timer(ngx_event_t *ev, u_int timer)
211 {
212 ngx_event_t *e;
213
214 for (e = timer_queue.timer_next;
215 e != &timer_queue && timer > e->timer_delta;
216 e = e->timer_next)
217 timer -= e->timer_delta;
218
219 ev->timer_delta = timer;
220
221 ev->timer_next = e;
222 ev->timer_prev = e->timer_prev;
223
224 e->timer_prev->timer_next = ev;
225 e->timer_prev = ev;
226 }
227
228 static void ngx_inline ngx_del_timer(ngx_event_t *ev)
229 {
230 if (ev->timer_prev)
231 ev->timer_prev->timer_next = ev->timer_next;
232
233 if (ev->timer_next) {
234 ev->timer_next->timer_prev = ev->timer_prev;
235 ev->timer_prev = NULL;
236 }
237
238 if (ev->timer_prev)
239 ev->timer_next = NULL;
240 }