comparison src/event/modules/ngx_epoll_module.c @ 245:e6c005b66b3a

nginx-0.0.1-2004-01-30-00:45:01 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 29 Jan 2004 21:45:01 +0000
parents
children 6753e8cdaa2c
comparison
equal deleted inserted replaced
244:187dc0a3197d 245:e6c005b66b3a
1
2 /*
3 * Copyright (C) 2002-2004 Igor Sysoev, http://sysoev.ru/en/
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
10
11
12 #if (TEST_BUILD_EPOLL)
13
14 /* epoll declarations */
15
16 #define EPOLLIN 0x001
17 #define EPOLLPRI 0x002
18 #define EPOLLOUT 0x004
19 #define EPOLLRDNORM 0x040
20 #define EPOLLRDBAND 0x080
21 #define EPOLLWRNORM 0x100
22 #define EPOLLWRBAND 0x200
23 #define EPOLLMSG 0x400
24 #define EPOLLERR 0x008
25 #define EPOLLHUP 0x010
26
27 #define EPOLL_CTL_ADD 1
28 #define EPOLL_CTL_DEL 2
29 #define EPOLL_CTL_MOD 3
30
31 typedef union epoll_data {
32 void *ptr;
33 int fd;
34 uint32_t u32;
35 uint64_t u64;
36 } epoll_data_t;
37
38 struct epoll_event {
39 uint32_t events;
40 epoll_data_t data;
41 };
42
43 int epoll_create(int size);
44 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
45 int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout);
46
47 int epoll_create(int size)
48 {
49 return -1;
50 }
51
52 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
53 {
54 return -1;
55 }
56
57 int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout)
58 {
59 return -1;
60 }
61
62 #endif
63
64
65 typedef struct {
66 u_int events;
67 } ngx_epoll_conf_t;
68
69
70 static int ngx_epoll_init(ngx_cycle_t *cycle);
71 static void ngx_epoll_done(ngx_cycle_t *cycle);
72 static int ngx_epoll_add_connection(ngx_connection_t *c);
73 static int ngx_epoll_del_connection(ngx_connection_t *c);
74 static int ngx_epoll_process_events(ngx_log_t *log);
75
76 static void *ngx_epoll_create_conf(ngx_cycle_t *cycle);
77 static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf);
78
79 static int ep = -1;
80 static struct epoll_event *event_list;
81 static u_int nevents;
82
83
84 static ngx_str_t epoll_name = ngx_string("epoll");
85
86 static ngx_command_t ngx_epoll_commands[] = {
87
88 {ngx_string("epoll_events"),
89 NGX_EVENT_CONF|NGX_CONF_TAKE1,
90 ngx_conf_set_num_slot,
91 0,
92 offsetof(ngx_epoll_conf_t, events),
93 NULL},
94
95 ngx_null_command
96 };
97
98
99 ngx_event_module_t ngx_epoll_module_ctx = {
100 &epoll_name,
101 ngx_epoll_create_conf, /* create configuration */
102 ngx_epoll_init_conf, /* init configuration */
103
104 {
105 NULL, /* add an event */
106 NULL, /* delete an event */
107 NULL, /* enable an event */
108 NULL, /* disable an event */
109 ngx_epoll_add_connection, /* add an connection */
110 ngx_epoll_del_connection, /* delete an connection */
111 ngx_epoll_process_events, /* process the events */
112 ngx_epoll_init, /* init the events */
113 ngx_epoll_done, /* done the events */
114 }
115
116 };
117
118 ngx_module_t ngx_epoll_module = {
119 NGX_MODULE,
120 &ngx_epoll_module_ctx, /* module context */
121 ngx_epoll_commands, /* module directives */
122 NGX_EVENT_MODULE, /* module type */
123 NULL, /* init module */
124 NULL /* init child */
125 };
126
127
128 static int ngx_epoll_init(ngx_cycle_t *cycle)
129 {
130 size_t n;
131 ngx_epoll_conf_t *epcf;
132
133 epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
134
135 if (ep == -1) {
136 ep = epoll_create(/* STUB: open_files / 2 */ 512);
137
138 if (ep == -1) {
139 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
140 "epoll_create() failed");
141 return NGX_ERROR;
142 }
143 }
144
145 if (nevents < epcf->events) {
146 if (event_list) {
147 ngx_free(event_list);
148 }
149
150 event_list = ngx_alloc(sizeof(struct epoll_event) * epcf->events,
151 cycle->log);
152 if (event_list == NULL) {
153 return NGX_ERROR;
154 }
155 }
156
157 nevents = epcf->events;
158
159 ngx_io = ngx_os_io;
160
161 ngx_event_actions = ngx_epoll_module_ctx.actions;
162
163 ngx_event_flags = NGX_USE_EDGE_EVENT;
164
165 return NGX_OK;
166 }
167
168
169 static void ngx_epoll_done(ngx_cycle_t *cycle)
170 {
171 if (close(ep) == -1) {
172 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
173 "epoll close() failed");
174 }
175
176 ep = -1;
177
178 ngx_free(event_list);
179
180 event_list = NULL;
181 nevents = 0;
182 }
183
184
185 static int ngx_epoll_add_connection(ngx_connection_t *c)
186 {
187 struct epoll_event ev;
188
189 ev.events = EPOLLIN|EPOLLOUT;
190 ev.data.ptr = (void *) ((uintptr_t) c | c->read->instance);
191
192 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
193 "epoll add connection: fd:%d ev:%04X", c->fd, ev.events);
194
195 if (epoll_ctl(ep, EPOLL_CTL_ADD, c->fd, &ev) == -1) {
196 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
197 "epoll_ctl(#%d) failed", c->fd);
198 return NGX_ERROR;
199 }
200
201 return NGX_OK;
202 }
203
204
205 static int ngx_epoll_del_connection(ngx_connection_t *c)
206 {
207 c->read->active = 0;
208 c->write->active = 0;
209
210 return NGX_OK;
211 }
212
213
214 int ngx_epoll_process_events(ngx_log_t *log)
215 {
216 int events;
217 ngx_int_t instance, i;
218 size_t n;
219 ngx_msec_t timer;
220 ngx_err_t err;
221 ngx_cycle_t **cycle;
222 struct timeval tv;
223 ngx_connection_t *c;
224 ngx_epoch_msec_t delta;
225
226
227 timer = ngx_event_find_timer();
228 ngx_old_elapsed_msec = ngx_elapsed_msec;
229
230 if (timer == 0) {
231 timer = (ngx_msec_t) -1;
232 }
233
234 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "epoll timer: %d", timer);
235
236 events = epoll_wait(ep, event_list, nevents, timer);
237
238 if (events == -1) {
239 err = ngx_errno;
240 } else {
241 err = 0;
242 }
243
244 ngx_gettimeofday(&tv);
245 ngx_time_update(tv.tv_sec);
246
247 delta = ngx_elapsed_msec;
248 ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec;
249
250 if ((int) timer != INFTIM) {
251 delta = ngx_elapsed_msec - delta;
252
253 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
254 "epoll timer: %d, delta: %d", timer, (int) delta);
255 } else {
256 if (events == 0) {
257 ngx_log_error(NGX_LOG_ALERT, log, 0,
258 "epoll_wait() returned no events without timeout");
259 return NGX_ERROR;
260 }
261 }
262
263 if (err) {
264 ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
265 log, err, "epoll_wait() failed");
266 return NGX_ERROR;
267 }
268
269 for (i = 0; i < events; i++) {
270 c = event_list[i].data.ptr;
271
272 instance = (uintptr_t) c & 1;
273 c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
274
275 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
276 "epoll: fd:%d ev:%04X d:" PTR_FMT,
277 c->fd, event_list[i].events, event_list[i].data);
278
279 if (c->read->instance != instance) {
280
281 /*
282 * it's a stale event from a file descriptor
283 * that was just closed in this iteration
284 */
285
286 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
287 "epoll: stale event " PTR_FMT, c);
288 continue;
289 }
290
291 if (event_list[i].events & EPOLLIN) {
292 if (!c->read->active) {
293 continue;
294 }
295
296 c->read->ready = 1;
297 c->read->event_handler(c->read);
298 }
299
300 if (event_list[i].events & EPOLLOUT) {
301 if (!c->write->active) {
302 continue;
303 }
304
305 c->write->ready = 1;
306 c->write->event_handler(c->write);
307 }
308
309 if (event_list[i].events & (EPOLLERR|EPOLLHUP|EPOLLMSG)) {
310 ngx_log_error(NGX_LOG_ERR, log, 0,
311 "epoll_wait() error on fd:%d ev:%d",
312 c->fd, event_list[i].events);
313 }
314 }
315
316 if (timer != (ngx_msec_t) -1 && delta) {
317 ngx_event_expire_timers((ngx_msec_t) delta);
318 }
319
320 return NGX_OK;
321 }
322
323
324 static void *ngx_epoll_create_conf(ngx_cycle_t *cycle)
325 {
326 ngx_epoll_conf_t *epcf;
327
328 ngx_test_null(epcf, ngx_palloc(cycle->pool, sizeof(ngx_epoll_conf_t)),
329 NGX_CONF_ERROR);
330
331 epcf->events = NGX_CONF_UNSET;
332
333 return epcf;
334 }
335
336
337 static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf)
338 {
339 ngx_epoll_conf_t *epcf = conf;
340
341 ngx_conf_init_unsigned_value(epcf->events, 512);
342
343 return NGX_CONF_OK;
344 }