blob: ed12283848d38bf02e8aa888c8391fb89f4b8ad6 [file] [log] [blame]
Igor Sysoevf2e676a2003-11-16 21:49:42 +00001
2#include <ngx_config.h>
3#include <ngx_core.h>
4#include <ngx_event.h>
5
6
7#define NGX_MAX_PENDING_CONN 10
8
9
10static CRITICAL_SECTION connect_lock;
11static int nconnects;
12static ngx_connection_t pending_connects[NGX_MAX_PENDING_CONN];
13
14static HANDLE pending_connect_event;
15
16__declspec(thread) int nevents = 0;
Igor Sysoevd7fdb352003-11-17 16:15:03 +000017__declspec(thread) WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS + 1];
18__declspec(thread) ngx_connection_t *conn[WSA_MAXIMUM_WAIT_EVENTS + 1];
Igor Sysoevf2e676a2003-11-16 21:49:42 +000019
20
21
22int ngx_iocp_wait_connect(ngx_connection_t *c)
23{
24 for ( ;; ) {
25 EnterCriticalSection(&connect_lock);
26
27 if (nconnects < NGX_MAX_PENDING_CONN) {
28 pending_connects[--nconnects] = c;
29 LeaveCriticalSection(&connect_lock);
30
31 if (SetEvent(pending_connect_event) == 0) {
32 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
33 "SetEvent() failed");
34 return NGX_ERROR;
35
36 break;
37 }
38
39 LeaveCriticalSection(&connect_lock);
40 ngx_log_error(NGX_LOG_NOTICE, c->log, 0,
41 "max number of pending connect()s is %d",
42 NGX_MAX_PENDING_CONN);
43 msleep(100);
44 }
45
46 if (!started) {
47 if (ngx_iocp_new_thread(1) == NGX_ERROR) {
48 return NGX_ERROR;
49 }
50 started = 1;
51 }
52
53 return NGX_OK;
54}
55
56
57int ngx_iocp_new_thread(int main)
58{
59 u_int id;
60
61 if (main) {
62 pending_connect_event = CreateEvent(NULL, 0, 1, NULL);
63 if (pending_connect_event == INVALID_HANDLE_VALUE) {
64 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
65 "CreateThread() failed");
66 return NGX_ERROR;
67 }
68 }
69
70 if (CreateThread(NULL, 0, ngx_iocp_wait_events, main, 0, &id)
71 == INVALID_HANDLE_VALUE)
72 {
73 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
74 "CreateThread() failed");
75 return NGX_ERROR;
76 }
77
78 SetEvent(event) {
79 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
80 "SetEvent() failed");
81 return NGX_ERROR;
82 }
83
84 return NGX_OK;
85}
86
87
88int ngx_iocp_new_connect()
89{
90 EnterCriticalSection(&connect_lock);
91 c = pending_connects[--nconnects];
92 LeaveCriticalSection(&connect_lock);
93
94 conn[nevents] = c;
95
96 events[nevents] = WSACreateEvent();
97 if (events[nevents] == INVALID_HANDLE_VALUE) {
98 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
99 "WSACreateEvent() failed");
100 return NGX_ERROR;
101 }
102
103 if (WSAEventSelect(c->fd, events[nevents], FD_CONNECT) == -1)
104 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
105 "WSAEventSelect() failed");
106 return NGX_ERROR;
107 }
108
109 nevents++;
110
111 return NGX_OK;
112}
113
114
115void ngx_iocp_wait_events(int main)
116{
117 WSANETWORKEVENTS ne;
118
119 nevents = 1;
120 events[0] = pending_connect_event;
121 conn[0] = NULL;
122
123 for ( ;; ) {
Igor Sysoevd7fdb352003-11-17 16:15:03 +0000124 offset = (nevents == WSA_MAXIMUM_WAIT_EVENTS + 1) ? 1: 0;
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000125 timeout = (nevents == 1 && !first) ? 60000: INFINITE;
126
127 n = WSAWaitForMultipleEvents(nevents - offset, events[offset],
128 0, timeout, 0);
129 if (n == WAIT_FAILED) {
130 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
131 "WSAWaitForMultipleEvents() failed");
132 continue;
133 }
134
135 if (n == WAIT_TIMEOUT) {
Igor Sysoevd7fdb352003-11-17 16:15:03 +0000136 if (nevents == 2 && !main) {
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000137 ExitThread(0);
138 }
139
140 ngx_log_error(NGX_LOG_ALERT, log, 0,
141 "WSAWaitForMultipleEvents() "
142 "returned unexpected WAIT_TIMEOUT");
143 continue;
144 }
145
146 n -= WSA_WAIT_EVENT_0;
147
Igor Sysoevd7fdb352003-11-17 16:15:03 +0000148 if (events[n] == NULL) {
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000149
Igor Sysoevd7fdb352003-11-17 16:15:03 +0000150 /* the pending_connect_event */
Igor Sysoevf2e676a2003-11-16 21:49:42 +0000151
152 if (nevents == WSA_MAXIMUM_WAIT_EVENTS) {
153 ngx_iocp_new_thread(0);
154 } else {
155 ngx_iocp_new_connect();
156 }
157
158 continue;
159 }
160
161 if (WSAEnumNetworkEvents(c[n].fd, events[n], &ne) == -1) {
162 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
163 "WSAEnumNetworkEvents() failed");
164 continue;
165 }
166
167 if (ne.lNetworkEvents & FD_CONNECT) {
168 conn[n].write->ovlp.error = ne.iErrorCode[FD_CONNECT_BIT];
169
170 if (PostQueuedCompletionStatus(iocp, 0, NGX_IOCP_CONNECT,
171 &conn[n].write->ovlp) == 0)
172 {
173 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
174 "PostQueuedCompletionStatus() failed");
175 continue;
176 }
177
178 if (n < nevents) {
179 conn[n] = conn[nevents];
180 events[n] = events[nevents];
181 }
182
183 nevents--;
184 continue;
185 }
186
187 if (ne.lNetworkEvents & FD_ACCEPT) {
188
189 /* CHECK ERROR ??? */
190
191 ngx_event_post_acceptex(conn[n].listening, 1);
192 continue;
193 }
194
195 ngx_log_error(NGX_LOG_ALERT, c[n].log, 0,
196 "WSAWaitForMultipleEvents() "
197 "returned unexpected network event %lu",
198 ne.lNetworkEvents);
199 }
200}