uv: Upgrade to v0.11.17
[platform/upstream/nodejs.git] / deps / uv / src / win / core.c
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21
22 #include <assert.h>
23 #include <errno.h>
24 #include <limits.h>
25 #include <malloc.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "uv.h"
31 #include "internal.h"
32 #include "handle-inl.h"
33 #include "req-inl.h"
34
35
36 /* The only event loop we support right now */
37 static uv_loop_t uv_default_loop_;
38
39 /* uv_once intialization guards */
40 static uv_once_t uv_init_guard_ = UV_ONCE_INIT;
41 static uv_once_t uv_default_loop_init_guard_ = UV_ONCE_INIT;
42
43
44 static void uv__crt_invalid_parameter_handler(const wchar_t* expression,
45     const wchar_t* function, const wchar_t * file, unsigned int line,
46     uintptr_t reserved) {
47   /* No-op. */
48 }
49
50
51 static void uv_init(void) {
52   /* Tell Windows that we will handle critical errors. */
53   SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
54                SEM_NOOPENFILEERRORBOX);
55
56   /* Tell the CRT to not exit the application when an invalid parameter is */
57   /* passed. The main issue is that invalid FDs will trigger this behavior. */
58 #if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800
59   _set_invalid_parameter_handler(uv__crt_invalid_parameter_handler);
60 #endif
61
62   /* Fetch winapi function pointers. This must be done first because other */
63   /* intialization code might need these function pointers to be loaded. */
64   uv_winapi_init();
65
66   /* Initialize winsock */
67   uv_winsock_init();
68
69   /* Initialize FS */
70   uv_fs_init();
71
72   /* Initialize signal stuff */
73   uv_signals_init();
74
75   /* Initialize console */
76   uv_console_init();
77
78   /* Initialize utilities */
79   uv__util_init();
80 }
81
82
83 static void uv_loop_init(uv_loop_t* loop) {
84   /* Create an I/O completion port */
85   loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
86   if (loop->iocp == NULL) {
87     uv_fatal_error(GetLastError(), "CreateIoCompletionPort");
88   }
89
90   /* To prevent uninitialized memory access, loop->time must be intialized */
91   /* to zero before calling uv_update_time for the first time. */
92   loop->time = 0;
93   loop->last_tick_count = 0;
94   uv_update_time(loop);
95
96   QUEUE_INIT(&loop->handle_queue);
97   QUEUE_INIT(&loop->active_reqs);
98   loop->active_handles = 0;
99
100   loop->pending_reqs_tail = NULL;
101
102   loop->endgame_handles = NULL;
103
104   RB_INIT(&loop->timers);
105
106   loop->check_handles = NULL;
107   loop->prepare_handles = NULL;
108   loop->idle_handles = NULL;
109
110   loop->next_prepare_handle = NULL;
111   loop->next_check_handle = NULL;
112   loop->next_idle_handle = NULL;
113
114   memset(&loop->poll_peer_sockets, 0, sizeof loop->poll_peer_sockets);
115
116   loop->active_tcp_streams = 0;
117   loop->active_udp_streams = 0;
118
119   loop->timer_counter = 0;
120   loop->stop_flag = 0;
121 }
122
123
124 static void uv_default_loop_init(void) {
125   /* Initialize libuv itself first */
126   uv__once_init();
127
128   /* Initialize the main loop */
129   uv_loop_init(&uv_default_loop_);
130 }
131
132
133 void uv__once_init(void) {
134   uv_once(&uv_init_guard_, uv_init);
135 }
136
137
138 uv_loop_t* uv_default_loop(void) {
139   uv_once(&uv_default_loop_init_guard_, uv_default_loop_init);
140   return &uv_default_loop_;
141 }
142
143
144 uv_loop_t* uv_loop_new(void) {
145   uv_loop_t* loop;
146
147   /* Initialize libuv itself first */
148   uv__once_init();
149
150   loop = (uv_loop_t*)malloc(sizeof(uv_loop_t));
151
152   if (!loop) {
153     uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
154   }
155
156   uv_loop_init(loop);
157   return loop;
158 }
159
160
161 void uv_loop_delete(uv_loop_t* loop) {
162   if (loop != &uv_default_loop_) {
163     int i;
164     for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) {
165       SOCKET sock = loop->poll_peer_sockets[i];
166       if (sock != 0 && sock != INVALID_SOCKET) {
167         closesocket(sock);
168       }
169     }
170
171     free(loop);
172   }
173 }
174
175
176 int uv_backend_fd(const uv_loop_t* loop) {
177   return -1;
178 }
179
180
181 int uv_backend_timeout(const uv_loop_t* loop) {
182   return 0;
183 }
184
185
186 static void uv_poll(uv_loop_t* loop, int block) {
187   DWORD bytes, timeout;
188   ULONG_PTR key;
189   OVERLAPPED* overlapped;
190   uv_req_t* req;
191
192   if (block) {
193     timeout = uv_get_poll_timeout(loop);
194   } else {
195     timeout = 0;
196   }
197
198   GetQueuedCompletionStatus(loop->iocp,
199                             &bytes,
200                             &key,
201                             &overlapped,
202                             timeout);
203
204   if (overlapped) {
205     /* Package was dequeued */
206     req = uv_overlapped_to_req(overlapped);
207     uv_insert_pending_req(loop, req);
208   } else if (GetLastError() != WAIT_TIMEOUT) {
209     /* Serious error */
210     uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
211   } else {
212     /* We're sure that at least `timeout` milliseconds have expired, but */
213     /* this may not be reflected yet in the GetTickCount() return value. */
214     /* Therefore we ensure it's taken into account here. */
215     uv__time_forward(loop, timeout);
216   }
217 }
218
219
220 static void uv_poll_ex(uv_loop_t* loop, int block) {
221   BOOL success;
222   DWORD timeout;
223   uv_req_t* req;
224   OVERLAPPED_ENTRY overlappeds[128];
225   ULONG count;
226   ULONG i;
227
228   if (block) {
229     timeout = uv_get_poll_timeout(loop);
230   } else {
231     timeout = 0;
232   }
233
234   success = pGetQueuedCompletionStatusEx(loop->iocp,
235                                          overlappeds,
236                                          ARRAY_SIZE(overlappeds),
237                                          &count,
238                                          timeout,
239                                          FALSE);
240
241   if (success) {
242     for (i = 0; i < count; i++) {
243       /* Package was dequeued */
244       req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);
245       uv_insert_pending_req(loop, req);
246     }
247   } else if (GetLastError() != WAIT_TIMEOUT) {
248     /* Serious error */
249     uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx");
250   } else if (timeout > 0) {
251     /* We're sure that at least `timeout` milliseconds have expired, but */
252     /* this may not be reflected yet in the GetTickCount() return value. */
253     /* Therefore we ensure it's taken into account here. */
254     uv__time_forward(loop, timeout);
255   }
256 }
257
258
259 static int uv__loop_alive(const uv_loop_t* loop) {
260   return loop->active_handles > 0 ||
261          !QUEUE_EMPTY(&loop->active_reqs) ||
262          loop->endgame_handles != NULL;
263 }
264
265
266 int uv_loop_alive(const uv_loop_t* loop) {
267     return uv__loop_alive(loop);
268 }
269
270
271 int uv_run(uv_loop_t *loop, uv_run_mode mode) {
272   int r;
273   void (*poll)(uv_loop_t* loop, int block);
274
275   if (pGetQueuedCompletionStatusEx)
276     poll = &uv_poll_ex;
277   else
278     poll = &uv_poll;
279
280   r = uv__loop_alive(loop);
281   if (!r)
282     uv_update_time(loop);
283
284   while (r != 0 && loop->stop_flag == 0) {
285     uv_update_time(loop);
286     uv_process_timers(loop);
287
288     uv_process_reqs(loop);
289     uv_idle_invoke(loop);
290     uv_prepare_invoke(loop);
291
292     (*poll)(loop, loop->idle_handles == NULL &&
293                   loop->pending_reqs_tail == NULL &&
294                   loop->endgame_handles == NULL &&
295                   !loop->stop_flag &&
296                   (loop->active_handles > 0 ||
297                    !QUEUE_EMPTY(&loop->active_reqs)) &&
298                   !(mode & UV_RUN_NOWAIT));
299
300     uv_check_invoke(loop);
301     uv_process_endgames(loop);
302
303     if (mode == UV_RUN_ONCE) {
304       /* UV_RUN_ONCE implies forward progess: at least one callback must have
305        * been invoked when it returns. uv__io_poll() can return without doing
306        * I/O (meaning: no callbacks) when its timeout expires - which means we
307        * have pending timers that satisfy the forward progress constraint.
308        *
309        * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
310        * the check.
311        */
312       uv_update_time(loop);
313       uv_process_timers(loop);
314     }
315
316     r = uv__loop_alive(loop);
317     if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))
318       break;
319   }
320
321   /* The if statement lets the compiler compile it to a conditional store.
322    * Avoids dirtying a cache line.
323    */
324   if (loop->stop_flag != 0)
325     loop->stop_flag = 0;
326
327   return r;
328 }