blob: 44c155e732562f77b8b2a5d1834a3da5993a8b78 [file] [log] [blame]
Igor Sysoev73009772003-02-06 17:21:13 +00001
Igor Sysoeve4a25262003-06-06 14:59:20 +00002/*
3 * Copyright (C) 2002-2003 Igor Sysoev, http://sysoev.ru
4 */
5
6
Igor Sysoev73009772003-02-06 17:21:13 +00007#include <ngx_config.h>
Igor Sysoev73009772003-02-06 17:21:13 +00008#include <ngx_core.h>
Igor Sysoev73009772003-02-06 17:21:13 +00009#include <ngx_event.h>
Igor Sysoev73009772003-02-06 17:21:13 +000010
11
Igor Sysoeve4a25262003-06-06 14:59:20 +000012typedef struct {
13 int threads;
14} ngx_iocp_conf_t;
Igor Sysoev73009772003-02-06 17:21:13 +000015
16
Igor Sysoeve4a25262003-06-06 14:59:20 +000017static int ngx_iocp_init(ngx_log_t *log);
18static void ngx_iocp_done(ngx_log_t *log);
19static int ngx_iocp_add_event(ngx_event_t *ev, int event, u_int key);
20static int ngx_iocp_process_events(ngx_log_t *log);
21static void *ngx_iocp_create_conf(ngx_pool_t *pool);
22static char *ngx_iocp_init_conf(ngx_pool_t *pool, void *conf);
Igor Sysoev73009772003-02-06 17:21:13 +000023
24
Igor Sysoeve4a25262003-06-06 14:59:20 +000025static ngx_str_t iocp_name = ngx_string("iocp");
26
27static ngx_command_t ngx_iocp_commands[] = {
28
29 {ngx_string("iocp_threads"),
30 NGX_EVENT_CONF|NGX_CONF_TAKE1,
31 ngx_conf_set_num_slot,
32 0,
33 offsetof(ngx_iocp_conf_t, threads),
34 NULL},
35
36 ngx_null_command
37};
38
39
40ngx_event_module_t ngx_iocp_module_ctx = {
41 &iocp_name,
42 ngx_iocp_create_conf, /* create configuration */
43 ngx_iocp_init_conf, /* init configuration */
44
45 {
46 ngx_iocp_add_event, /* add an event */
47 NULL, /* delete an event */
48 NULL, /* enable an event */
49 NULL, /* disable an event */
50 NULL, /* add an connection */
51 NULL, /* delete an connection */
52 ngx_iocp_process_events, /* process the events */
53 ngx_iocp_init, /* init the events */
54 ngx_iocp_done /* done the events */
55 }
56
57};
58
59ngx_module_t ngx_iocp_module = {
60 NGX_MODULE,
61 &ngx_iocp_module_ctx, /* module context */
62 ngx_iocp_commands, /* module directives */
63 NGX_EVENT_MODULE, /* module type */
64 NULL /* init module */
65};
66
67
68static HANDLE iocp;
69
70
71static int ngx_iocp_init(ngx_log_t *log)
Igor Sysoev73009772003-02-06 17:21:13 +000072{
Igor Sysoeve4a25262003-06-06 14:59:20 +000073 ngx_iocp_conf_t *cf;
74
75 cf = ngx_event_get_conf(ngx_iocp_module);
76
77 iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, cf->threads);
Igor Sysoev73009772003-02-06 17:21:13 +000078
79 if (iocp == NULL) {
80 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
81 "CreateIoCompletionPort() failed");
82 return NGX_ERROR;
83 }
84
Igor Sysoeve4a25262003-06-06 14:59:20 +000085 if (ngx_event_timer_init(log) == NGX_ERROR) {
Igor Sysoev73009772003-02-06 17:21:13 +000086 return NGX_ERROR;
87 }
88
Igor Sysoeve4a25262003-06-06 14:59:20 +000089 ngx_event_actions = ngx_iocp_module_ctx.actions;
Igor Sysoev73009772003-02-06 17:21:13 +000090
91 ngx_event_flags = NGX_HAVE_AIO_EVENT|NGX_HAVE_IOCP_EVENT;
92
93 return NGX_OK;
94}
95
96
Igor Sysoeve4a25262003-06-06 14:59:20 +000097static void ngx_iocp_done(ngx_log_t *log)
98{
99 if (CloseHandle(iocp) == -1) {
100 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
101 "iocp CloseHandle() failed");
102 }
103
104 ngx_event_timer_done(log);
105}
106
107
108static int ngx_iocp_add_event(ngx_event_t *ev, int event, u_int key)
Igor Sysoev73009772003-02-06 17:21:13 +0000109{
110 ngx_connection_t *c;
111
112 c = (ngx_connection_t *) ev->data;
113
Igor Sysoeve4a25262003-06-06 14:59:20 +0000114 ngx_log_debug(ev->log, "iocp add: %d, %08x:%08x" _ c->fd _ key _ &ev->ovlp);
Igor Sysoev73009772003-02-06 17:21:13 +0000115
Igor Sysoeve4a25262003-06-06 14:59:20 +0000116 if (CreateIoCompletionPort((HANDLE) c->fd, iocp, key, 0) == NULL) {
Igor Sysoev73009772003-02-06 17:21:13 +0000117 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
118 "CreateIoCompletionPort() failed");
119 return NGX_ERROR;
120 }
121
122 return NGX_OK;
123}
124
125
Igor Sysoeve4a25262003-06-06 14:59:20 +0000126static int ngx_iocp_process_events(ngx_log_t *log)
Igor Sysoev73009772003-02-06 17:21:13 +0000127{
128 int rc;
Igor Sysoeve4a25262003-06-06 14:59:20 +0000129 u_int key;
Igor Sysoev73009772003-02-06 17:21:13 +0000130 size_t bytes;
131 ngx_err_t err;
132 ngx_msec_t timer, delta;
Igor Sysoeve4a25262003-06-06 14:59:20 +0000133 ngx_event_t *ev;
Igor Sysoev73009772003-02-06 17:21:13 +0000134 ngx_event_ovlp_t *ovlp;
135
Igor Sysoev73009772003-02-06 17:21:13 +0000136 timer = ngx_event_find_timer();
137
138 if (timer) {
139 delta = ngx_msec();
140
141 } else {
142 timer = INFINITE;
143 delta = 0;
144 }
145
146 ngx_log_debug(log, "iocp timer: %d" _ timer);
147
Igor Sysoeve4a25262003-06-06 14:59:20 +0000148 rc = GetQueuedCompletionStatus(iocp, &bytes, (LPDWORD) &key,
Igor Sysoev73009772003-02-06 17:21:13 +0000149 (LPOVERLAPPED *) &ovlp, timer);
Igor Sysoeve4a25262003-06-06 14:59:20 +0000150
151 ngx_log_debug(log, "iocp: %d, %d:%08x:%08x" _ rc _ bytes _ key _ ovlp);
152
Igor Sysoev73009772003-02-06 17:21:13 +0000153 if (rc == 0) {
Igor Sysoev73009772003-02-06 17:21:13 +0000154 err = ngx_errno;
155
156 if (ovlp == NULL) {
157 if (err != WAIT_TIMEOUT) {
158 ngx_log_error(NGX_LOG_ALERT, log, err,
159 "GetQueuedCompletionStatus() failed");
160
161 return NGX_ERROR;
162 }
163
164 } else {
165 ovlp->error = err;
166 }
167 }
168
169 if (timer != INFINITE) {
170 delta = ngx_msec() - delta;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000171 ngx_event_expire_timers(delta);
Igor Sysoev73009772003-02-06 17:21:13 +0000172 }
173
174 if (ovlp) {
175 ev = ovlp->event;
176
177ngx_log_debug(log, "iocp ev: %08x" _ ev);
178
Igor Sysoeve4a25262003-06-06 14:59:20 +0000179 switch (key) {
180 case NGX_IOCP_IO:
Igor Sysoev73009772003-02-06 17:21:13 +0000181 ev->ready = 1;
182 ev->available = bytes;
Igor Sysoeve4a25262003-06-06 14:59:20 +0000183 break;
184
185 case NGX_IOCP_ACCEPT:
186 break;
Igor Sysoev73009772003-02-06 17:21:13 +0000187 }
188
Igor Sysoeve4a25262003-06-06 14:59:20 +0000189ngx_log_debug(log, "iocp ev handler: %08x" _ ev->event_handler);
Igor Sysoev73009772003-02-06 17:21:13 +0000190
Igor Sysoev1c13c662003-05-20 15:37:55 +0000191 ev->event_handler(ev);
Igor Sysoev73009772003-02-06 17:21:13 +0000192 }
193
Igor Sysoev73009772003-02-06 17:21:13 +0000194 return NGX_OK;
195}
Igor Sysoeve4a25262003-06-06 14:59:20 +0000196
197
198static void *ngx_iocp_create_conf(ngx_pool_t *pool)
199{
200 ngx_iocp_conf_t *cf;
201
202 ngx_test_null(cf, ngx_palloc(pool, sizeof(ngx_iocp_conf_t)),
203 NGX_CONF_ERROR);
204
205 cf->threads = NGX_CONF_UNSET;
206
207 return cf;
208}
209
210
211static char *ngx_iocp_init_conf(ngx_pool_t *pool, void *conf)
212{
213 ngx_iocp_conf_t *cf = conf;
214
215 ngx_conf_init_value(cf->threads, 0);
216
217 return NGX_CONF_OK;
218}