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