xref: /third_party/libuv/src/win/req-inl.h (revision e66f31c5)
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#ifndef UV_WIN_REQ_INL_H_
23#define UV_WIN_REQ_INL_H_
24
25#include <assert.h>
26
27#include "uv.h"
28#include "internal.h"
29
30
31#define SET_REQ_STATUS(req, status)                                     \
32   (req)->u.io.overlapped.Internal = (ULONG_PTR) (status)
33
34#define SET_REQ_ERROR(req, error)                                       \
35  SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error)))
36
37/* Note: used open-coded in UV_REQ_INIT() because of a circular dependency
38 * between src/uv-common.h and src/win/internal.h.
39 */
40#define SET_REQ_SUCCESS(req)                                            \
41  SET_REQ_STATUS((req), STATUS_SUCCESS)
42
43#define GET_REQ_STATUS(req)                                             \
44  ((NTSTATUS) (req)->u.io.overlapped.Internal)
45
46#define REQ_SUCCESS(req)                                                \
47  (NT_SUCCESS(GET_REQ_STATUS((req))))
48
49#define GET_REQ_ERROR(req)                                              \
50  (pRtlNtStatusToDosError(GET_REQ_STATUS((req))))
51
52#define GET_REQ_SOCK_ERROR(req)                                         \
53  (uv__ntstatus_to_winsock_error(GET_REQ_STATUS((req))))
54
55
56#define REGISTER_HANDLE_REQ(loop, handle, req)                          \
57  do {                                                                  \
58    INCREASE_ACTIVE_COUNT((loop), (handle));                            \
59    uv__req_register((loop), (req));                                    \
60  } while (0)
61
62#define UNREGISTER_HANDLE_REQ(loop, handle, req)                        \
63  do {                                                                  \
64    DECREASE_ACTIVE_COUNT((loop), (handle));                            \
65    uv__req_unregister((loop), (req));                                  \
66  } while (0)
67
68
69#define UV_SUCCEEDED_WITHOUT_IOCP(result)                               \
70  ((result) && (handle->flags & UV_HANDLE_SYNC_BYPASS_IOCP))
71
72#define UV_SUCCEEDED_WITH_IOCP(result)                                  \
73  ((result) || (GetLastError() == ERROR_IO_PENDING))
74
75
76#define POST_COMPLETION_FOR_REQ(loop, req)                              \
77  if (!PostQueuedCompletionStatus((loop)->iocp,                         \
78                                  0,                                    \
79                                  0,                                    \
80                                  &((req)->u.io.overlapped))) {         \
81    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");       \
82  }
83
84
85INLINE static uv_req_t* uv__overlapped_to_req(OVERLAPPED* overlapped) {
86  return CONTAINING_RECORD(overlapped, uv_req_t, u.io.overlapped);
87}
88
89
90INLINE static void uv__insert_pending_req(uv_loop_t* loop, uv_req_t* req) {
91  req->next_req = NULL;
92  if (loop->pending_reqs_tail) {
93#ifdef _DEBUG
94    /* Ensure the request is not already in the queue, or the queue
95     * will get corrupted.
96     */
97    uv_req_t* current = loop->pending_reqs_tail;
98    do {
99      assert(req != current);
100      current = current->next_req;
101    } while(current != loop->pending_reqs_tail);
102#endif
103
104    req->next_req = loop->pending_reqs_tail->next_req;
105    loop->pending_reqs_tail->next_req = req;
106    loop->pending_reqs_tail = req;
107  } else {
108    req->next_req = req;
109    loop->pending_reqs_tail = req;
110  }
111}
112
113
114#define DELEGATE_STREAM_REQ(loop, req, method, handle_at)                     \
115  do {                                                                        \
116    switch (((uv_handle_t*) (req)->handle_at)->type) {                        \
117      case UV_TCP:                                                            \
118        uv__process_tcp_##method##_req(loop,                                  \
119                                      (uv_tcp_t*) ((req)->handle_at),         \
120                                      req);                                   \
121        break;                                                                \
122                                                                              \
123      case UV_NAMED_PIPE:                                                     \
124        uv__process_pipe_##method##_req(loop,                                 \
125                                       (uv_pipe_t*) ((req)->handle_at),       \
126                                       req);                                  \
127        break;                                                                \
128                                                                              \
129      case UV_TTY:                                                            \
130        uv__process_tty_##method##_req(loop,                                  \
131                                      (uv_tty_t*) ((req)->handle_at),         \
132                                      req);                                   \
133        break;                                                                \
134                                                                              \
135      default:                                                                \
136        assert(0);                                                            \
137    }                                                                         \
138  } while (0)
139
140
141INLINE static void uv__process_reqs(uv_loop_t* loop) {
142  uv_req_t* req;
143  uv_req_t* first;
144  uv_req_t* next;
145
146  if (loop->pending_reqs_tail == NULL)
147    return;
148
149  first = loop->pending_reqs_tail->next_req;
150  next = first;
151  loop->pending_reqs_tail = NULL;
152
153  while (next != NULL) {
154    req = next;
155    next = req->next_req != first ? req->next_req : NULL;
156
157    switch (req->type) {
158      case UV_READ:
159        DELEGATE_STREAM_REQ(loop, req, read, data);
160        break;
161
162      case UV_WRITE:
163        DELEGATE_STREAM_REQ(loop, (uv_write_t*) req, write, handle);
164        break;
165
166      case UV_ACCEPT:
167        DELEGATE_STREAM_REQ(loop, req, accept, data);
168        break;
169
170      case UV_CONNECT:
171        DELEGATE_STREAM_REQ(loop, (uv_connect_t*) req, connect, handle);
172        break;
173
174      case UV_SHUTDOWN:
175        DELEGATE_STREAM_REQ(loop, (uv_shutdown_t*) req, shutdown, handle);
176        break;
177
178      case UV_UDP_RECV:
179        uv__process_udp_recv_req(loop, (uv_udp_t*) req->data, req);
180        break;
181
182      case UV_UDP_SEND:
183        uv__process_udp_send_req(loop,
184                                 ((uv_udp_send_t*) req)->handle,
185                                 (uv_udp_send_t*) req);
186        break;
187
188      case UV_WAKEUP:
189        uv__process_async_wakeup_req(loop, (uv_async_t*) req->data, req);
190        break;
191
192      case UV_SIGNAL_REQ:
193        uv__process_signal_req(loop, (uv_signal_t*) req->data, req);
194        break;
195
196      case UV_POLL_REQ:
197        uv__process_poll_req(loop, (uv_poll_t*) req->data, req);
198        break;
199
200      case UV_PROCESS_EXIT:
201        uv__process_proc_exit(loop, (uv_process_t*) req->data);
202        break;
203
204      case UV_FS_EVENT_REQ:
205        uv__process_fs_event_req(loop, req, (uv_fs_event_t*) req->data);
206        break;
207
208      default:
209        assert(0);
210    }
211  }
212}
213
214#endif /* UV_WIN_REQ_INL_H_ */
215