1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2e66f31c5Sopenharmony_ci * 3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the 6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions: 9e66f31c5Sopenharmony_ci * 10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software. 12e66f31c5Sopenharmony_ci * 13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19e66f31c5Sopenharmony_ci * IN THE SOFTWARE. 20e66f31c5Sopenharmony_ci */ 21e66f31c5Sopenharmony_ci 22e66f31c5Sopenharmony_ci#include <assert.h> 23e66f31c5Sopenharmony_ci#include <errno.h> 24e66f31c5Sopenharmony_ci#include <limits.h> 25e66f31c5Sopenharmony_ci#include <stdio.h> 26e66f31c5Sopenharmony_ci#include <stdlib.h> 27e66f31c5Sopenharmony_ci#include <string.h> 28e66f31c5Sopenharmony_ci#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) 29e66f31c5Sopenharmony_ci#include <crtdbg.h> 30e66f31c5Sopenharmony_ci#endif 31e66f31c5Sopenharmony_ci 32e66f31c5Sopenharmony_ci#include "uv.h" 33e66f31c5Sopenharmony_ci#include "internal.h" 34e66f31c5Sopenharmony_ci#include "queue.h" 35e66f31c5Sopenharmony_ci#include "handle-inl.h" 36e66f31c5Sopenharmony_ci#include "heap-inl.h" 37e66f31c5Sopenharmony_ci#include "req-inl.h" 38e66f31c5Sopenharmony_ci 39e66f31c5Sopenharmony_ci/* uv_once initialization guards */ 40e66f31c5Sopenharmony_cistatic uv_once_t uv_init_guard_ = UV_ONCE_INIT; 41e66f31c5Sopenharmony_ci 42e66f31c5Sopenharmony_ci 43e66f31c5Sopenharmony_ci#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)) 44e66f31c5Sopenharmony_ci/* Our crt debug report handler allows us to temporarily disable asserts 45e66f31c5Sopenharmony_ci * just for the current thread. 46e66f31c5Sopenharmony_ci */ 47e66f31c5Sopenharmony_ci 48e66f31c5Sopenharmony_ciUV_THREAD_LOCAL int uv__crt_assert_enabled = TRUE; 49e66f31c5Sopenharmony_ci 50e66f31c5Sopenharmony_cistatic int uv__crt_dbg_report_handler(int report_type, char *message, int *ret_val) { 51e66f31c5Sopenharmony_ci if (uv__crt_assert_enabled || report_type != _CRT_ASSERT) 52e66f31c5Sopenharmony_ci return FALSE; 53e66f31c5Sopenharmony_ci 54e66f31c5Sopenharmony_ci if (ret_val) { 55e66f31c5Sopenharmony_ci /* Set ret_val to 0 to continue with normal execution. 56e66f31c5Sopenharmony_ci * Set ret_val to 1 to trigger a breakpoint. 57e66f31c5Sopenharmony_ci */ 58e66f31c5Sopenharmony_ci 59e66f31c5Sopenharmony_ci if(IsDebuggerPresent()) 60e66f31c5Sopenharmony_ci *ret_val = 1; 61e66f31c5Sopenharmony_ci else 62e66f31c5Sopenharmony_ci *ret_val = 0; 63e66f31c5Sopenharmony_ci } 64e66f31c5Sopenharmony_ci 65e66f31c5Sopenharmony_ci /* Don't call _CrtDbgReport. */ 66e66f31c5Sopenharmony_ci return TRUE; 67e66f31c5Sopenharmony_ci} 68e66f31c5Sopenharmony_ci#else 69e66f31c5Sopenharmony_ciUV_THREAD_LOCAL int uv__crt_assert_enabled = FALSE; 70e66f31c5Sopenharmony_ci#endif 71e66f31c5Sopenharmony_ci 72e66f31c5Sopenharmony_ci 73e66f31c5Sopenharmony_ci#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800 74e66f31c5Sopenharmony_cistatic void uv__crt_invalid_parameter_handler(const wchar_t* expression, 75e66f31c5Sopenharmony_ci const wchar_t* function, const wchar_t * file, unsigned int line, 76e66f31c5Sopenharmony_ci uintptr_t reserved) { 77e66f31c5Sopenharmony_ci /* No-op. */ 78e66f31c5Sopenharmony_ci} 79e66f31c5Sopenharmony_ci#endif 80e66f31c5Sopenharmony_ci 81e66f31c5Sopenharmony_cistatic uv_loop_t** uv__loops; 82e66f31c5Sopenharmony_cistatic int uv__loops_size; 83e66f31c5Sopenharmony_cistatic int uv__loops_capacity; 84e66f31c5Sopenharmony_ci#define UV__LOOPS_CHUNK_SIZE 8 85e66f31c5Sopenharmony_cistatic uv_mutex_t uv__loops_lock; 86e66f31c5Sopenharmony_ci 87e66f31c5Sopenharmony_ci 88e66f31c5Sopenharmony_cistatic void uv__loops_init(void) { 89e66f31c5Sopenharmony_ci uv_mutex_init(&uv__loops_lock); 90e66f31c5Sopenharmony_ci} 91e66f31c5Sopenharmony_ci 92e66f31c5Sopenharmony_ci 93e66f31c5Sopenharmony_cistatic int uv__loops_add(uv_loop_t* loop) { 94e66f31c5Sopenharmony_ci uv_loop_t** new_loops; 95e66f31c5Sopenharmony_ci int new_capacity, i; 96e66f31c5Sopenharmony_ci 97e66f31c5Sopenharmony_ci uv_mutex_lock(&uv__loops_lock); 98e66f31c5Sopenharmony_ci 99e66f31c5Sopenharmony_ci if (uv__loops_size == uv__loops_capacity) { 100e66f31c5Sopenharmony_ci new_capacity = uv__loops_capacity + UV__LOOPS_CHUNK_SIZE; 101e66f31c5Sopenharmony_ci new_loops = uv__realloc(uv__loops, sizeof(uv_loop_t*) * new_capacity); 102e66f31c5Sopenharmony_ci if (!new_loops) 103e66f31c5Sopenharmony_ci goto failed_loops_realloc; 104e66f31c5Sopenharmony_ci uv__loops = new_loops; 105e66f31c5Sopenharmony_ci for (i = uv__loops_capacity; i < new_capacity; ++i) 106e66f31c5Sopenharmony_ci uv__loops[i] = NULL; 107e66f31c5Sopenharmony_ci uv__loops_capacity = new_capacity; 108e66f31c5Sopenharmony_ci } 109e66f31c5Sopenharmony_ci uv__loops[uv__loops_size] = loop; 110e66f31c5Sopenharmony_ci ++uv__loops_size; 111e66f31c5Sopenharmony_ci 112e66f31c5Sopenharmony_ci uv_mutex_unlock(&uv__loops_lock); 113e66f31c5Sopenharmony_ci return 0; 114e66f31c5Sopenharmony_ci 115e66f31c5Sopenharmony_cifailed_loops_realloc: 116e66f31c5Sopenharmony_ci uv_mutex_unlock(&uv__loops_lock); 117e66f31c5Sopenharmony_ci return ERROR_OUTOFMEMORY; 118e66f31c5Sopenharmony_ci} 119e66f31c5Sopenharmony_ci 120e66f31c5Sopenharmony_ci 121e66f31c5Sopenharmony_cistatic void uv__loops_remove(uv_loop_t* loop) { 122e66f31c5Sopenharmony_ci int loop_index; 123e66f31c5Sopenharmony_ci int smaller_capacity; 124e66f31c5Sopenharmony_ci uv_loop_t** new_loops; 125e66f31c5Sopenharmony_ci 126e66f31c5Sopenharmony_ci uv_mutex_lock(&uv__loops_lock); 127e66f31c5Sopenharmony_ci 128e66f31c5Sopenharmony_ci for (loop_index = 0; loop_index < uv__loops_size; ++loop_index) { 129e66f31c5Sopenharmony_ci if (uv__loops[loop_index] == loop) 130e66f31c5Sopenharmony_ci break; 131e66f31c5Sopenharmony_ci } 132e66f31c5Sopenharmony_ci /* If loop was not found, ignore */ 133e66f31c5Sopenharmony_ci if (loop_index == uv__loops_size) 134e66f31c5Sopenharmony_ci goto loop_removed; 135e66f31c5Sopenharmony_ci 136e66f31c5Sopenharmony_ci uv__loops[loop_index] = uv__loops[uv__loops_size - 1]; 137e66f31c5Sopenharmony_ci uv__loops[uv__loops_size - 1] = NULL; 138e66f31c5Sopenharmony_ci --uv__loops_size; 139e66f31c5Sopenharmony_ci 140e66f31c5Sopenharmony_ci if (uv__loops_size == 0) { 141e66f31c5Sopenharmony_ci uv__loops_capacity = 0; 142e66f31c5Sopenharmony_ci uv__free(uv__loops); 143e66f31c5Sopenharmony_ci uv__loops = NULL; 144e66f31c5Sopenharmony_ci goto loop_removed; 145e66f31c5Sopenharmony_ci } 146e66f31c5Sopenharmony_ci 147e66f31c5Sopenharmony_ci /* If we didn't grow to big skip downsizing */ 148e66f31c5Sopenharmony_ci if (uv__loops_capacity < 4 * UV__LOOPS_CHUNK_SIZE) 149e66f31c5Sopenharmony_ci goto loop_removed; 150e66f31c5Sopenharmony_ci 151e66f31c5Sopenharmony_ci /* Downsize only if more than half of buffer is free */ 152e66f31c5Sopenharmony_ci smaller_capacity = uv__loops_capacity / 2; 153e66f31c5Sopenharmony_ci if (uv__loops_size >= smaller_capacity) 154e66f31c5Sopenharmony_ci goto loop_removed; 155e66f31c5Sopenharmony_ci new_loops = uv__realloc(uv__loops, sizeof(uv_loop_t*) * smaller_capacity); 156e66f31c5Sopenharmony_ci if (!new_loops) 157e66f31c5Sopenharmony_ci goto loop_removed; 158e66f31c5Sopenharmony_ci uv__loops = new_loops; 159e66f31c5Sopenharmony_ci uv__loops_capacity = smaller_capacity; 160e66f31c5Sopenharmony_ci 161e66f31c5Sopenharmony_ciloop_removed: 162e66f31c5Sopenharmony_ci uv_mutex_unlock(&uv__loops_lock); 163e66f31c5Sopenharmony_ci} 164e66f31c5Sopenharmony_ci 165e66f31c5Sopenharmony_civoid uv__wake_all_loops(void) { 166e66f31c5Sopenharmony_ci int i; 167e66f31c5Sopenharmony_ci uv_loop_t* loop; 168e66f31c5Sopenharmony_ci 169e66f31c5Sopenharmony_ci uv_mutex_lock(&uv__loops_lock); 170e66f31c5Sopenharmony_ci for (i = 0; i < uv__loops_size; ++i) { 171e66f31c5Sopenharmony_ci loop = uv__loops[i]; 172e66f31c5Sopenharmony_ci assert(loop); 173e66f31c5Sopenharmony_ci if (loop->iocp != INVALID_HANDLE_VALUE) 174e66f31c5Sopenharmony_ci PostQueuedCompletionStatus(loop->iocp, 0, 0, NULL); 175e66f31c5Sopenharmony_ci } 176e66f31c5Sopenharmony_ci uv_mutex_unlock(&uv__loops_lock); 177e66f31c5Sopenharmony_ci} 178e66f31c5Sopenharmony_ci 179e66f31c5Sopenharmony_cistatic void uv__init(void) { 180e66f31c5Sopenharmony_ci /* Tell Windows that we will handle critical errors. */ 181e66f31c5Sopenharmony_ci SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | 182e66f31c5Sopenharmony_ci SEM_NOOPENFILEERRORBOX); 183e66f31c5Sopenharmony_ci 184e66f31c5Sopenharmony_ci /* Tell the CRT to not exit the application when an invalid parameter is 185e66f31c5Sopenharmony_ci * passed. The main issue is that invalid FDs will trigger this behavior. 186e66f31c5Sopenharmony_ci */ 187e66f31c5Sopenharmony_ci#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800 188e66f31c5Sopenharmony_ci _set_invalid_parameter_handler(uv__crt_invalid_parameter_handler); 189e66f31c5Sopenharmony_ci#endif 190e66f31c5Sopenharmony_ci 191e66f31c5Sopenharmony_ci /* We also need to setup our debug report handler because some CRT 192e66f31c5Sopenharmony_ci * functions (eg _get_osfhandle) raise an assert when called with invalid 193e66f31c5Sopenharmony_ci * FDs even though they return the proper error code in the release build. 194e66f31c5Sopenharmony_ci */ 195e66f31c5Sopenharmony_ci#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)) 196e66f31c5Sopenharmony_ci _CrtSetReportHook(uv__crt_dbg_report_handler); 197e66f31c5Sopenharmony_ci#endif 198e66f31c5Sopenharmony_ci 199e66f31c5Sopenharmony_ci /* Initialize tracking of all uv loops */ 200e66f31c5Sopenharmony_ci uv__loops_init(); 201e66f31c5Sopenharmony_ci 202e66f31c5Sopenharmony_ci /* Fetch winapi function pointers. This must be done first because other 203e66f31c5Sopenharmony_ci * initialization code might need these function pointers to be loaded. 204e66f31c5Sopenharmony_ci */ 205e66f31c5Sopenharmony_ci uv__winapi_init(); 206e66f31c5Sopenharmony_ci 207e66f31c5Sopenharmony_ci /* Initialize winsock */ 208e66f31c5Sopenharmony_ci uv__winsock_init(); 209e66f31c5Sopenharmony_ci 210e66f31c5Sopenharmony_ci /* Initialize FS */ 211e66f31c5Sopenharmony_ci uv__fs_init(); 212e66f31c5Sopenharmony_ci 213e66f31c5Sopenharmony_ci /* Initialize signal stuff */ 214e66f31c5Sopenharmony_ci uv__signals_init(); 215e66f31c5Sopenharmony_ci 216e66f31c5Sopenharmony_ci /* Initialize console */ 217e66f31c5Sopenharmony_ci uv__console_init(); 218e66f31c5Sopenharmony_ci 219e66f31c5Sopenharmony_ci /* Initialize utilities */ 220e66f31c5Sopenharmony_ci uv__util_init(); 221e66f31c5Sopenharmony_ci 222e66f31c5Sopenharmony_ci /* Initialize system wakeup detection */ 223e66f31c5Sopenharmony_ci uv__init_detect_system_wakeup(); 224e66f31c5Sopenharmony_ci} 225e66f31c5Sopenharmony_ci 226e66f31c5Sopenharmony_ci 227e66f31c5Sopenharmony_ciint uv_loop_init(uv_loop_t* loop) { 228e66f31c5Sopenharmony_ci uv__loop_internal_fields_t* lfields; 229e66f31c5Sopenharmony_ci struct heap* timer_heap; 230e66f31c5Sopenharmony_ci int err; 231e66f31c5Sopenharmony_ci 232e66f31c5Sopenharmony_ci /* Initialize libuv itself first */ 233e66f31c5Sopenharmony_ci uv__once_init(); 234e66f31c5Sopenharmony_ci 235e66f31c5Sopenharmony_ci /* Create an I/O completion port */ 236e66f31c5Sopenharmony_ci loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); 237e66f31c5Sopenharmony_ci if (loop->iocp == NULL) 238e66f31c5Sopenharmony_ci return uv_translate_sys_error(GetLastError()); 239e66f31c5Sopenharmony_ci 240e66f31c5Sopenharmony_ci lfields = (uv__loop_internal_fields_t*) uv__calloc(1, sizeof(*lfields)); 241e66f31c5Sopenharmony_ci if (lfields == NULL) 242e66f31c5Sopenharmony_ci return UV_ENOMEM; 243e66f31c5Sopenharmony_ci loop->internal_fields = lfields; 244e66f31c5Sopenharmony_ci 245e66f31c5Sopenharmony_ci err = uv_mutex_init(&lfields->loop_metrics.lock); 246e66f31c5Sopenharmony_ci if (err) 247e66f31c5Sopenharmony_ci goto fail_metrics_mutex_init; 248e66f31c5Sopenharmony_ci memset(&lfields->loop_metrics.metrics, 249e66f31c5Sopenharmony_ci 0, 250e66f31c5Sopenharmony_ci sizeof(lfields->loop_metrics.metrics)); 251e66f31c5Sopenharmony_ci 252e66f31c5Sopenharmony_ci /* To prevent uninitialized memory access, loop->time must be initialized 253e66f31c5Sopenharmony_ci * to zero before calling uv_update_time for the first time. 254e66f31c5Sopenharmony_ci */ 255e66f31c5Sopenharmony_ci loop->time = 0; 256e66f31c5Sopenharmony_ci uv_update_time(loop); 257e66f31c5Sopenharmony_ci 258e66f31c5Sopenharmony_ci uv__queue_init(&loop->wq); 259e66f31c5Sopenharmony_ci uv__queue_init(&loop->handle_queue); 260e66f31c5Sopenharmony_ci loop->active_reqs.count = 0; 261e66f31c5Sopenharmony_ci loop->active_handles = 0; 262e66f31c5Sopenharmony_ci 263e66f31c5Sopenharmony_ci loop->pending_reqs_tail = NULL; 264e66f31c5Sopenharmony_ci 265e66f31c5Sopenharmony_ci loop->endgame_handles = NULL; 266e66f31c5Sopenharmony_ci 267e66f31c5Sopenharmony_ci loop->timer_heap = timer_heap = uv__malloc(sizeof(*timer_heap)); 268e66f31c5Sopenharmony_ci if (timer_heap == NULL) { 269e66f31c5Sopenharmony_ci err = UV_ENOMEM; 270e66f31c5Sopenharmony_ci goto fail_timers_alloc; 271e66f31c5Sopenharmony_ci } 272e66f31c5Sopenharmony_ci 273e66f31c5Sopenharmony_ci heap_init(timer_heap); 274e66f31c5Sopenharmony_ci 275e66f31c5Sopenharmony_ci loop->check_handles = NULL; 276e66f31c5Sopenharmony_ci loop->prepare_handles = NULL; 277e66f31c5Sopenharmony_ci loop->idle_handles = NULL; 278e66f31c5Sopenharmony_ci 279e66f31c5Sopenharmony_ci loop->next_prepare_handle = NULL; 280e66f31c5Sopenharmony_ci loop->next_check_handle = NULL; 281e66f31c5Sopenharmony_ci loop->next_idle_handle = NULL; 282e66f31c5Sopenharmony_ci 283e66f31c5Sopenharmony_ci memset(&loop->poll_peer_sockets, 0, sizeof loop->poll_peer_sockets); 284e66f31c5Sopenharmony_ci 285e66f31c5Sopenharmony_ci loop->timer_counter = 0; 286e66f31c5Sopenharmony_ci loop->stop_flag = 0; 287e66f31c5Sopenharmony_ci 288e66f31c5Sopenharmony_ci err = uv_mutex_init(&loop->wq_mutex); 289e66f31c5Sopenharmony_ci if (err) 290e66f31c5Sopenharmony_ci goto fail_mutex_init; 291e66f31c5Sopenharmony_ci 292e66f31c5Sopenharmony_ci err = uv_async_init(loop, &loop->wq_async, uv__work_done); 293e66f31c5Sopenharmony_ci if (err) 294e66f31c5Sopenharmony_ci goto fail_async_init; 295e66f31c5Sopenharmony_ci 296e66f31c5Sopenharmony_ci uv__handle_unref(&loop->wq_async); 297e66f31c5Sopenharmony_ci loop->wq_async.flags |= UV_HANDLE_INTERNAL; 298e66f31c5Sopenharmony_ci 299e66f31c5Sopenharmony_ci err = uv__loops_add(loop); 300e66f31c5Sopenharmony_ci if (err) 301e66f31c5Sopenharmony_ci goto fail_async_init; 302e66f31c5Sopenharmony_ci 303e66f31c5Sopenharmony_ci loop->magic = UV_LOOP_MAGIC; 304e66f31c5Sopenharmony_ci return 0; 305e66f31c5Sopenharmony_ci 306e66f31c5Sopenharmony_cifail_async_init: 307e66f31c5Sopenharmony_ci uv_mutex_destroy(&loop->wq_mutex); 308e66f31c5Sopenharmony_ci 309e66f31c5Sopenharmony_cifail_mutex_init: 310e66f31c5Sopenharmony_ci uv__free(timer_heap); 311e66f31c5Sopenharmony_ci loop->timer_heap = NULL; 312e66f31c5Sopenharmony_ci 313e66f31c5Sopenharmony_cifail_timers_alloc: 314e66f31c5Sopenharmony_ci uv_mutex_destroy(&lfields->loop_metrics.lock); 315e66f31c5Sopenharmony_ci 316e66f31c5Sopenharmony_cifail_metrics_mutex_init: 317e66f31c5Sopenharmony_ci uv__free(lfields); 318e66f31c5Sopenharmony_ci loop->internal_fields = NULL; 319e66f31c5Sopenharmony_ci CloseHandle(loop->iocp); 320e66f31c5Sopenharmony_ci loop->iocp = INVALID_HANDLE_VALUE; 321e66f31c5Sopenharmony_ci 322e66f31c5Sopenharmony_ci return err; 323e66f31c5Sopenharmony_ci} 324e66f31c5Sopenharmony_ci 325e66f31c5Sopenharmony_ci 326e66f31c5Sopenharmony_civoid uv_update_time(uv_loop_t* loop) { 327e66f31c5Sopenharmony_ci uint64_t new_time = uv__hrtime(1000); 328e66f31c5Sopenharmony_ci assert(new_time >= loop->time); 329e66f31c5Sopenharmony_ci loop->time = new_time; 330e66f31c5Sopenharmony_ci} 331e66f31c5Sopenharmony_ci 332e66f31c5Sopenharmony_ci 333e66f31c5Sopenharmony_civoid uv__once_init(void) { 334e66f31c5Sopenharmony_ci uv_once(&uv_init_guard_, uv__init); 335e66f31c5Sopenharmony_ci} 336e66f31c5Sopenharmony_ci 337e66f31c5Sopenharmony_ci 338e66f31c5Sopenharmony_civoid uv__loop_close(uv_loop_t* loop) { 339e66f31c5Sopenharmony_ci uv__loop_internal_fields_t* lfields; 340e66f31c5Sopenharmony_ci size_t i; 341e66f31c5Sopenharmony_ci 342e66f31c5Sopenharmony_ci uv__loops_remove(loop); 343e66f31c5Sopenharmony_ci 344e66f31c5Sopenharmony_ci /* Close the async handle without needing an extra loop iteration. 345e66f31c5Sopenharmony_ci * We might have a pending message, but we're just going to destroy the IOCP 346e66f31c5Sopenharmony_ci * soon, so we can just discard it now without the usual risk of a getting 347e66f31c5Sopenharmony_ci * another notification from GetQueuedCompletionStatusEx after calling the 348e66f31c5Sopenharmony_ci * close_cb (which we also skip defining). We'll assert later that queue was 349e66f31c5Sopenharmony_ci * actually empty and all reqs handled. */ 350e66f31c5Sopenharmony_ci loop->wq_async.async_sent = 0; 351e66f31c5Sopenharmony_ci loop->wq_async.close_cb = NULL; 352e66f31c5Sopenharmony_ci uv__handle_closing(&loop->wq_async); 353e66f31c5Sopenharmony_ci uv__handle_close(&loop->wq_async); 354e66f31c5Sopenharmony_ci 355e66f31c5Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) { 356e66f31c5Sopenharmony_ci SOCKET sock = loop->poll_peer_sockets[i]; 357e66f31c5Sopenharmony_ci if (sock != 0 && sock != INVALID_SOCKET) 358e66f31c5Sopenharmony_ci closesocket(sock); 359e66f31c5Sopenharmony_ci } 360e66f31c5Sopenharmony_ci 361e66f31c5Sopenharmony_ci uv_mutex_lock(&loop->wq_mutex); 362e66f31c5Sopenharmony_ci assert(uv__queue_empty(&loop->wq) && "thread pool work queue not empty!"); 363e66f31c5Sopenharmony_ci assert(!uv__has_active_reqs(loop)); 364e66f31c5Sopenharmony_ci uv_mutex_unlock(&loop->wq_mutex); 365e66f31c5Sopenharmony_ci uv_mutex_destroy(&loop->wq_mutex); 366e66f31c5Sopenharmony_ci 367e66f31c5Sopenharmony_ci uv__free(loop->timer_heap); 368e66f31c5Sopenharmony_ci loop->timer_heap = NULL; 369e66f31c5Sopenharmony_ci 370e66f31c5Sopenharmony_ci lfields = uv__get_internal_fields(loop); 371e66f31c5Sopenharmony_ci uv_mutex_destroy(&lfields->loop_metrics.lock); 372e66f31c5Sopenharmony_ci uv__free(lfields); 373e66f31c5Sopenharmony_ci loop->internal_fields = NULL; 374e66f31c5Sopenharmony_ci 375e66f31c5Sopenharmony_ci CloseHandle(loop->iocp); 376e66f31c5Sopenharmony_ci loop->magic = ~UV_LOOP_MAGIC; 377e66f31c5Sopenharmony_ci} 378e66f31c5Sopenharmony_ci 379e66f31c5Sopenharmony_ci 380e66f31c5Sopenharmony_ciint uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { 381e66f31c5Sopenharmony_ci uv__loop_internal_fields_t* lfields; 382e66f31c5Sopenharmony_ci 383e66f31c5Sopenharmony_ci lfields = uv__get_internal_fields(loop); 384e66f31c5Sopenharmony_ci if (option == UV_METRICS_IDLE_TIME) { 385e66f31c5Sopenharmony_ci lfields->flags |= UV_METRICS_IDLE_TIME; 386e66f31c5Sopenharmony_ci return 0; 387e66f31c5Sopenharmony_ci } 388e66f31c5Sopenharmony_ci 389e66f31c5Sopenharmony_ci return UV_ENOSYS; 390e66f31c5Sopenharmony_ci} 391e66f31c5Sopenharmony_ci 392e66f31c5Sopenharmony_ci 393e66f31c5Sopenharmony_ciint uv_backend_fd(const uv_loop_t* loop) { 394e66f31c5Sopenharmony_ci return -1; 395e66f31c5Sopenharmony_ci} 396e66f31c5Sopenharmony_ci 397e66f31c5Sopenharmony_ci 398e66f31c5Sopenharmony_ciint uv_loop_fork(uv_loop_t* loop) { 399e66f31c5Sopenharmony_ci return UV_ENOSYS; 400e66f31c5Sopenharmony_ci} 401e66f31c5Sopenharmony_ci 402e66f31c5Sopenharmony_ci 403e66f31c5Sopenharmony_cistatic int uv__loop_alive(const uv_loop_t* loop) { 404e66f31c5Sopenharmony_ci return uv__has_active_handles(loop) || 405e66f31c5Sopenharmony_ci uv__has_active_reqs(loop) || 406e66f31c5Sopenharmony_ci loop->pending_reqs_tail != NULL || 407e66f31c5Sopenharmony_ci loop->endgame_handles != NULL; 408e66f31c5Sopenharmony_ci} 409e66f31c5Sopenharmony_ci 410e66f31c5Sopenharmony_ci 411e66f31c5Sopenharmony_ciint uv_loop_alive(const uv_loop_t* loop) { 412e66f31c5Sopenharmony_ci return uv__loop_alive(loop); 413e66f31c5Sopenharmony_ci} 414e66f31c5Sopenharmony_ci 415e66f31c5Sopenharmony_ci 416e66f31c5Sopenharmony_ciint uv_backend_timeout(const uv_loop_t* loop) { 417e66f31c5Sopenharmony_ci if (loop->stop_flag == 0 && 418e66f31c5Sopenharmony_ci /* uv__loop_alive(loop) && */ 419e66f31c5Sopenharmony_ci (uv__has_active_handles(loop) || uv__has_active_reqs(loop)) && 420e66f31c5Sopenharmony_ci loop->pending_reqs_tail == NULL && 421e66f31c5Sopenharmony_ci loop->idle_handles == NULL && 422e66f31c5Sopenharmony_ci loop->endgame_handles == NULL) 423e66f31c5Sopenharmony_ci return uv__next_timeout(loop); 424e66f31c5Sopenharmony_ci return 0; 425e66f31c5Sopenharmony_ci} 426e66f31c5Sopenharmony_ci 427e66f31c5Sopenharmony_ci 428e66f31c5Sopenharmony_cistatic void uv__poll_wine(uv_loop_t* loop, DWORD timeout) { 429e66f31c5Sopenharmony_ci uv__loop_internal_fields_t* lfields; 430e66f31c5Sopenharmony_ci DWORD bytes; 431e66f31c5Sopenharmony_ci ULONG_PTR key; 432e66f31c5Sopenharmony_ci OVERLAPPED* overlapped; 433e66f31c5Sopenharmony_ci uv_req_t* req; 434e66f31c5Sopenharmony_ci int repeat; 435e66f31c5Sopenharmony_ci uint64_t timeout_time; 436e66f31c5Sopenharmony_ci uint64_t user_timeout; 437e66f31c5Sopenharmony_ci int reset_timeout; 438e66f31c5Sopenharmony_ci 439e66f31c5Sopenharmony_ci lfields = uv__get_internal_fields(loop); 440e66f31c5Sopenharmony_ci timeout_time = loop->time + timeout; 441e66f31c5Sopenharmony_ci 442e66f31c5Sopenharmony_ci if (lfields->flags & UV_METRICS_IDLE_TIME) { 443e66f31c5Sopenharmony_ci reset_timeout = 1; 444e66f31c5Sopenharmony_ci user_timeout = timeout; 445e66f31c5Sopenharmony_ci timeout = 0; 446e66f31c5Sopenharmony_ci } else { 447e66f31c5Sopenharmony_ci reset_timeout = 0; 448e66f31c5Sopenharmony_ci } 449e66f31c5Sopenharmony_ci 450e66f31c5Sopenharmony_ci for (repeat = 0; ; repeat++) { 451e66f31c5Sopenharmony_ci /* Only need to set the provider_entry_time if timeout != 0. The function 452e66f31c5Sopenharmony_ci * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. 453e66f31c5Sopenharmony_ci */ 454e66f31c5Sopenharmony_ci if (timeout != 0) 455e66f31c5Sopenharmony_ci uv__metrics_set_provider_entry_time(loop); 456e66f31c5Sopenharmony_ci 457e66f31c5Sopenharmony_ci /* Store the current timeout in a location that's globally accessible so 458e66f31c5Sopenharmony_ci * other locations like uv__work_done() can determine whether the queue 459e66f31c5Sopenharmony_ci * of events in the callback were waiting when poll was called. 460e66f31c5Sopenharmony_ci */ 461e66f31c5Sopenharmony_ci lfields->current_timeout = timeout; 462e66f31c5Sopenharmony_ci 463e66f31c5Sopenharmony_ci GetQueuedCompletionStatus(loop->iocp, 464e66f31c5Sopenharmony_ci &bytes, 465e66f31c5Sopenharmony_ci &key, 466e66f31c5Sopenharmony_ci &overlapped, 467e66f31c5Sopenharmony_ci timeout); 468e66f31c5Sopenharmony_ci 469e66f31c5Sopenharmony_ci if (reset_timeout != 0) { 470e66f31c5Sopenharmony_ci if (overlapped && timeout == 0) 471e66f31c5Sopenharmony_ci uv__metrics_inc_events_waiting(loop, 1); 472e66f31c5Sopenharmony_ci timeout = user_timeout; 473e66f31c5Sopenharmony_ci reset_timeout = 0; 474e66f31c5Sopenharmony_ci } 475e66f31c5Sopenharmony_ci 476e66f31c5Sopenharmony_ci /* Placed here because on success the loop will break whether there is an 477e66f31c5Sopenharmony_ci * empty package or not, or if GetQueuedCompletionStatus returned early then 478e66f31c5Sopenharmony_ci * the timeout will be updated and the loop will run again. In either case 479e66f31c5Sopenharmony_ci * the idle time will need to be updated. 480e66f31c5Sopenharmony_ci */ 481e66f31c5Sopenharmony_ci uv__metrics_update_idle_time(loop); 482e66f31c5Sopenharmony_ci 483e66f31c5Sopenharmony_ci if (overlapped) { 484e66f31c5Sopenharmony_ci uv__metrics_inc_events(loop, 1); 485e66f31c5Sopenharmony_ci 486e66f31c5Sopenharmony_ci /* Package was dequeued */ 487e66f31c5Sopenharmony_ci req = uv__overlapped_to_req(overlapped); 488e66f31c5Sopenharmony_ci uv__insert_pending_req(loop, req); 489e66f31c5Sopenharmony_ci 490e66f31c5Sopenharmony_ci /* Some time might have passed waiting for I/O, 491e66f31c5Sopenharmony_ci * so update the loop time here. 492e66f31c5Sopenharmony_ci */ 493e66f31c5Sopenharmony_ci uv_update_time(loop); 494e66f31c5Sopenharmony_ci } else if (GetLastError() != WAIT_TIMEOUT) { 495e66f31c5Sopenharmony_ci /* Serious error */ 496e66f31c5Sopenharmony_ci uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus"); 497e66f31c5Sopenharmony_ci } else if (timeout > 0) { 498e66f31c5Sopenharmony_ci /* GetQueuedCompletionStatus can occasionally return a little early. 499e66f31c5Sopenharmony_ci * Make sure that the desired timeout target time is reached. 500e66f31c5Sopenharmony_ci */ 501e66f31c5Sopenharmony_ci uv_update_time(loop); 502e66f31c5Sopenharmony_ci if (timeout_time > loop->time) { 503e66f31c5Sopenharmony_ci timeout = (DWORD)(timeout_time - loop->time); 504e66f31c5Sopenharmony_ci /* The first call to GetQueuedCompletionStatus should return very 505e66f31c5Sopenharmony_ci * close to the target time and the second should reach it, but 506e66f31c5Sopenharmony_ci * this is not stated in the documentation. To make sure a busy 507e66f31c5Sopenharmony_ci * loop cannot happen, the timeout is increased exponentially 508e66f31c5Sopenharmony_ci * starting on the third round. 509e66f31c5Sopenharmony_ci */ 510e66f31c5Sopenharmony_ci timeout += repeat ? (1 << (repeat - 1)) : 0; 511e66f31c5Sopenharmony_ci continue; 512e66f31c5Sopenharmony_ci } 513e66f31c5Sopenharmony_ci } 514e66f31c5Sopenharmony_ci break; 515e66f31c5Sopenharmony_ci } 516e66f31c5Sopenharmony_ci} 517e66f31c5Sopenharmony_ci 518e66f31c5Sopenharmony_ci 519e66f31c5Sopenharmony_cistatic void uv__poll(uv_loop_t* loop, DWORD timeout) { 520e66f31c5Sopenharmony_ci uv__loop_internal_fields_t* lfields; 521e66f31c5Sopenharmony_ci BOOL success; 522e66f31c5Sopenharmony_ci uv_req_t* req; 523e66f31c5Sopenharmony_ci OVERLAPPED_ENTRY overlappeds[128]; 524e66f31c5Sopenharmony_ci ULONG count; 525e66f31c5Sopenharmony_ci ULONG i; 526e66f31c5Sopenharmony_ci int repeat; 527e66f31c5Sopenharmony_ci uint64_t timeout_time; 528e66f31c5Sopenharmony_ci uint64_t user_timeout; 529e66f31c5Sopenharmony_ci uint64_t actual_timeout; 530e66f31c5Sopenharmony_ci int reset_timeout; 531e66f31c5Sopenharmony_ci 532e66f31c5Sopenharmony_ci lfields = uv__get_internal_fields(loop); 533e66f31c5Sopenharmony_ci timeout_time = loop->time + timeout; 534e66f31c5Sopenharmony_ci 535e66f31c5Sopenharmony_ci if (lfields->flags & UV_METRICS_IDLE_TIME) { 536e66f31c5Sopenharmony_ci reset_timeout = 1; 537e66f31c5Sopenharmony_ci user_timeout = timeout; 538e66f31c5Sopenharmony_ci timeout = 0; 539e66f31c5Sopenharmony_ci } else { 540e66f31c5Sopenharmony_ci reset_timeout = 0; 541e66f31c5Sopenharmony_ci } 542e66f31c5Sopenharmony_ci 543e66f31c5Sopenharmony_ci for (repeat = 0; ; repeat++) { 544e66f31c5Sopenharmony_ci actual_timeout = timeout; 545e66f31c5Sopenharmony_ci 546e66f31c5Sopenharmony_ci /* Only need to set the provider_entry_time if timeout != 0. The function 547e66f31c5Sopenharmony_ci * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME. 548e66f31c5Sopenharmony_ci */ 549e66f31c5Sopenharmony_ci if (timeout != 0) 550e66f31c5Sopenharmony_ci uv__metrics_set_provider_entry_time(loop); 551e66f31c5Sopenharmony_ci 552e66f31c5Sopenharmony_ci /* Store the current timeout in a location that's globally accessible so 553e66f31c5Sopenharmony_ci * other locations like uv__work_done() can determine whether the queue 554e66f31c5Sopenharmony_ci * of events in the callback were waiting when poll was called. 555e66f31c5Sopenharmony_ci */ 556e66f31c5Sopenharmony_ci lfields->current_timeout = timeout; 557e66f31c5Sopenharmony_ci 558e66f31c5Sopenharmony_ci success = pGetQueuedCompletionStatusEx(loop->iocp, 559e66f31c5Sopenharmony_ci overlappeds, 560e66f31c5Sopenharmony_ci ARRAY_SIZE(overlappeds), 561e66f31c5Sopenharmony_ci &count, 562e66f31c5Sopenharmony_ci timeout, 563e66f31c5Sopenharmony_ci FALSE); 564e66f31c5Sopenharmony_ci 565e66f31c5Sopenharmony_ci if (reset_timeout != 0) { 566e66f31c5Sopenharmony_ci timeout = user_timeout; 567e66f31c5Sopenharmony_ci reset_timeout = 0; 568e66f31c5Sopenharmony_ci } 569e66f31c5Sopenharmony_ci 570e66f31c5Sopenharmony_ci /* Placed here because on success the loop will break whether there is an 571e66f31c5Sopenharmony_ci * empty package or not, or if pGetQueuedCompletionStatusEx returned early 572e66f31c5Sopenharmony_ci * then the timeout will be updated and the loop will run again. In either 573e66f31c5Sopenharmony_ci * case the idle time will need to be updated. 574e66f31c5Sopenharmony_ci */ 575e66f31c5Sopenharmony_ci uv__metrics_update_idle_time(loop); 576e66f31c5Sopenharmony_ci 577e66f31c5Sopenharmony_ci if (success) { 578e66f31c5Sopenharmony_ci for (i = 0; i < count; i++) { 579e66f31c5Sopenharmony_ci /* Package was dequeued, but see if it is not a empty package 580e66f31c5Sopenharmony_ci * meant only to wake us up. 581e66f31c5Sopenharmony_ci */ 582e66f31c5Sopenharmony_ci if (overlappeds[i].lpOverlapped) { 583e66f31c5Sopenharmony_ci uv__metrics_inc_events(loop, 1); 584e66f31c5Sopenharmony_ci if (actual_timeout == 0) 585e66f31c5Sopenharmony_ci uv__metrics_inc_events_waiting(loop, 1); 586e66f31c5Sopenharmony_ci 587e66f31c5Sopenharmony_ci req = uv__overlapped_to_req(overlappeds[i].lpOverlapped); 588e66f31c5Sopenharmony_ci uv__insert_pending_req(loop, req); 589e66f31c5Sopenharmony_ci } 590e66f31c5Sopenharmony_ci } 591e66f31c5Sopenharmony_ci 592e66f31c5Sopenharmony_ci /* Some time might have passed waiting for I/O, 593e66f31c5Sopenharmony_ci * so update the loop time here. 594e66f31c5Sopenharmony_ci */ 595e66f31c5Sopenharmony_ci uv_update_time(loop); 596e66f31c5Sopenharmony_ci } else if (GetLastError() != WAIT_TIMEOUT) { 597e66f31c5Sopenharmony_ci /* Serious error */ 598e66f31c5Sopenharmony_ci uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx"); 599e66f31c5Sopenharmony_ci } else if (timeout > 0) { 600e66f31c5Sopenharmony_ci /* GetQueuedCompletionStatus can occasionally return a little early. 601e66f31c5Sopenharmony_ci * Make sure that the desired timeout target time is reached. 602e66f31c5Sopenharmony_ci */ 603e66f31c5Sopenharmony_ci uv_update_time(loop); 604e66f31c5Sopenharmony_ci if (timeout_time > loop->time) { 605e66f31c5Sopenharmony_ci timeout = (DWORD)(timeout_time - loop->time); 606e66f31c5Sopenharmony_ci /* The first call to GetQueuedCompletionStatus should return very 607e66f31c5Sopenharmony_ci * close to the target time and the second should reach it, but 608e66f31c5Sopenharmony_ci * this is not stated in the documentation. To make sure a busy 609e66f31c5Sopenharmony_ci * loop cannot happen, the timeout is increased exponentially 610e66f31c5Sopenharmony_ci * starting on the third round. 611e66f31c5Sopenharmony_ci */ 612e66f31c5Sopenharmony_ci timeout += repeat ? (1 << (repeat - 1)) : 0; 613e66f31c5Sopenharmony_ci continue; 614e66f31c5Sopenharmony_ci } 615e66f31c5Sopenharmony_ci } 616e66f31c5Sopenharmony_ci break; 617e66f31c5Sopenharmony_ci } 618e66f31c5Sopenharmony_ci} 619e66f31c5Sopenharmony_ci 620e66f31c5Sopenharmony_ci 621e66f31c5Sopenharmony_ciint uv_run(uv_loop_t *loop, uv_run_mode mode) { 622e66f31c5Sopenharmony_ci DWORD timeout; 623e66f31c5Sopenharmony_ci int r; 624e66f31c5Sopenharmony_ci int can_sleep; 625e66f31c5Sopenharmony_ci 626e66f31c5Sopenharmony_ci r = uv__loop_alive(loop); 627e66f31c5Sopenharmony_ci if (!r) 628e66f31c5Sopenharmony_ci uv_update_time(loop); 629e66f31c5Sopenharmony_ci 630e66f31c5Sopenharmony_ci /* Maintain backwards compatibility by processing timers before entering the 631e66f31c5Sopenharmony_ci * while loop for UV_RUN_DEFAULT. Otherwise timers only need to be executed 632e66f31c5Sopenharmony_ci * once, which should be done after polling in order to maintain proper 633e66f31c5Sopenharmony_ci * execution order of the conceptual event loop. */ 634e66f31c5Sopenharmony_ci if (mode == UV_RUN_DEFAULT && r != 0 && loop->stop_flag == 0) { 635e66f31c5Sopenharmony_ci uv_update_time(loop); 636e66f31c5Sopenharmony_ci uv__run_timers(loop); 637e66f31c5Sopenharmony_ci } 638e66f31c5Sopenharmony_ci 639e66f31c5Sopenharmony_ci while (r != 0 && loop->stop_flag == 0) { 640e66f31c5Sopenharmony_ci can_sleep = loop->pending_reqs_tail == NULL && loop->idle_handles == NULL; 641e66f31c5Sopenharmony_ci 642e66f31c5Sopenharmony_ci uv__process_reqs(loop); 643e66f31c5Sopenharmony_ci uv__idle_invoke(loop); 644e66f31c5Sopenharmony_ci uv__prepare_invoke(loop); 645e66f31c5Sopenharmony_ci 646e66f31c5Sopenharmony_ci timeout = 0; 647e66f31c5Sopenharmony_ci if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT) 648e66f31c5Sopenharmony_ci timeout = uv_backend_timeout(loop); 649e66f31c5Sopenharmony_ci 650e66f31c5Sopenharmony_ci uv__metrics_inc_loop_count(loop); 651e66f31c5Sopenharmony_ci 652e66f31c5Sopenharmony_ci if (pGetQueuedCompletionStatusEx) 653e66f31c5Sopenharmony_ci uv__poll(loop, timeout); 654e66f31c5Sopenharmony_ci else 655e66f31c5Sopenharmony_ci uv__poll_wine(loop, timeout); 656e66f31c5Sopenharmony_ci 657e66f31c5Sopenharmony_ci /* Process immediate callbacks (e.g. write_cb) a small fixed number of 658e66f31c5Sopenharmony_ci * times to avoid loop starvation.*/ 659e66f31c5Sopenharmony_ci for (r = 0; r < 8 && loop->pending_reqs_tail != NULL; r++) 660e66f31c5Sopenharmony_ci uv__process_reqs(loop); 661e66f31c5Sopenharmony_ci 662e66f31c5Sopenharmony_ci /* Run one final update on the provider_idle_time in case uv__poll* 663e66f31c5Sopenharmony_ci * returned because the timeout expired, but no events were received. This 664e66f31c5Sopenharmony_ci * call will be ignored if the provider_entry_time was either never set (if 665e66f31c5Sopenharmony_ci * the timeout == 0) or was already updated b/c an event was received. 666e66f31c5Sopenharmony_ci */ 667e66f31c5Sopenharmony_ci uv__metrics_update_idle_time(loop); 668e66f31c5Sopenharmony_ci 669e66f31c5Sopenharmony_ci uv__check_invoke(loop); 670e66f31c5Sopenharmony_ci uv__process_endgames(loop); 671e66f31c5Sopenharmony_ci 672e66f31c5Sopenharmony_ci uv_update_time(loop); 673e66f31c5Sopenharmony_ci uv__run_timers(loop); 674e66f31c5Sopenharmony_ci 675e66f31c5Sopenharmony_ci r = uv__loop_alive(loop); 676e66f31c5Sopenharmony_ci if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) 677e66f31c5Sopenharmony_ci break; 678e66f31c5Sopenharmony_ci } 679e66f31c5Sopenharmony_ci 680e66f31c5Sopenharmony_ci /* The if statement lets the compiler compile it to a conditional store. 681e66f31c5Sopenharmony_ci * Avoids dirtying a cache line. 682e66f31c5Sopenharmony_ci */ 683e66f31c5Sopenharmony_ci if (loop->stop_flag != 0) 684e66f31c5Sopenharmony_ci loop->stop_flag = 0; 685e66f31c5Sopenharmony_ci 686e66f31c5Sopenharmony_ci return r; 687e66f31c5Sopenharmony_ci} 688e66f31c5Sopenharmony_ci 689e66f31c5Sopenharmony_ci 690e66f31c5Sopenharmony_ciint uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) { 691e66f31c5Sopenharmony_ci uv_os_fd_t fd_out; 692e66f31c5Sopenharmony_ci 693e66f31c5Sopenharmony_ci switch (handle->type) { 694e66f31c5Sopenharmony_ci case UV_TCP: 695e66f31c5Sopenharmony_ci fd_out = (uv_os_fd_t)((uv_tcp_t*) handle)->socket; 696e66f31c5Sopenharmony_ci break; 697e66f31c5Sopenharmony_ci 698e66f31c5Sopenharmony_ci case UV_NAMED_PIPE: 699e66f31c5Sopenharmony_ci fd_out = ((uv_pipe_t*) handle)->handle; 700e66f31c5Sopenharmony_ci break; 701e66f31c5Sopenharmony_ci 702e66f31c5Sopenharmony_ci case UV_TTY: 703e66f31c5Sopenharmony_ci fd_out = ((uv_tty_t*) handle)->handle; 704e66f31c5Sopenharmony_ci break; 705e66f31c5Sopenharmony_ci 706e66f31c5Sopenharmony_ci case UV_UDP: 707e66f31c5Sopenharmony_ci fd_out = (uv_os_fd_t)((uv_udp_t*) handle)->socket; 708e66f31c5Sopenharmony_ci break; 709e66f31c5Sopenharmony_ci 710e66f31c5Sopenharmony_ci case UV_POLL: 711e66f31c5Sopenharmony_ci fd_out = (uv_os_fd_t)((uv_poll_t*) handle)->socket; 712e66f31c5Sopenharmony_ci break; 713e66f31c5Sopenharmony_ci 714e66f31c5Sopenharmony_ci default: 715e66f31c5Sopenharmony_ci return UV_EINVAL; 716e66f31c5Sopenharmony_ci } 717e66f31c5Sopenharmony_ci 718e66f31c5Sopenharmony_ci if (uv_is_closing(handle) || fd_out == INVALID_HANDLE_VALUE) 719e66f31c5Sopenharmony_ci return UV_EBADF; 720e66f31c5Sopenharmony_ci 721e66f31c5Sopenharmony_ci *fd = fd_out; 722e66f31c5Sopenharmony_ci return 0; 723e66f31c5Sopenharmony_ci} 724e66f31c5Sopenharmony_ci 725e66f31c5Sopenharmony_ci 726e66f31c5Sopenharmony_ciint uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { 727e66f31c5Sopenharmony_ci int r; 728e66f31c5Sopenharmony_ci int len; 729e66f31c5Sopenharmony_ci SOCKET socket; 730e66f31c5Sopenharmony_ci 731e66f31c5Sopenharmony_ci if (handle == NULL || value == NULL) 732e66f31c5Sopenharmony_ci return UV_EINVAL; 733e66f31c5Sopenharmony_ci 734e66f31c5Sopenharmony_ci if (handle->type == UV_TCP) 735e66f31c5Sopenharmony_ci socket = ((uv_tcp_t*) handle)->socket; 736e66f31c5Sopenharmony_ci else if (handle->type == UV_UDP) 737e66f31c5Sopenharmony_ci socket = ((uv_udp_t*) handle)->socket; 738e66f31c5Sopenharmony_ci else 739e66f31c5Sopenharmony_ci return UV_ENOTSUP; 740e66f31c5Sopenharmony_ci 741e66f31c5Sopenharmony_ci len = sizeof(*value); 742e66f31c5Sopenharmony_ci 743e66f31c5Sopenharmony_ci if (*value == 0) 744e66f31c5Sopenharmony_ci r = getsockopt(socket, SOL_SOCKET, optname, (char*) value, &len); 745e66f31c5Sopenharmony_ci else 746e66f31c5Sopenharmony_ci r = setsockopt(socket, SOL_SOCKET, optname, (const char*) value, len); 747e66f31c5Sopenharmony_ci 748e66f31c5Sopenharmony_ci if (r == SOCKET_ERROR) 749e66f31c5Sopenharmony_ci return uv_translate_sys_error(WSAGetLastError()); 750e66f31c5Sopenharmony_ci 751e66f31c5Sopenharmony_ci return 0; 752e66f31c5Sopenharmony_ci} 753e66f31c5Sopenharmony_ci 754e66f31c5Sopenharmony_ciint uv_cpumask_size(void) { 755e66f31c5Sopenharmony_ci return (int)(sizeof(DWORD_PTR) * 8); 756e66f31c5Sopenharmony_ci} 757e66f31c5Sopenharmony_ci 758e66f31c5Sopenharmony_ciint uv__getsockpeername(const uv_handle_t* handle, 759e66f31c5Sopenharmony_ci uv__peersockfunc func, 760e66f31c5Sopenharmony_ci struct sockaddr* name, 761e66f31c5Sopenharmony_ci int* namelen, 762e66f31c5Sopenharmony_ci int delayed_error) { 763e66f31c5Sopenharmony_ci 764e66f31c5Sopenharmony_ci int result; 765e66f31c5Sopenharmony_ci uv_os_fd_t fd; 766e66f31c5Sopenharmony_ci 767e66f31c5Sopenharmony_ci result = uv_fileno(handle, &fd); 768e66f31c5Sopenharmony_ci if (result != 0) 769e66f31c5Sopenharmony_ci return result; 770e66f31c5Sopenharmony_ci 771e66f31c5Sopenharmony_ci if (delayed_error) 772e66f31c5Sopenharmony_ci return uv_translate_sys_error(delayed_error); 773e66f31c5Sopenharmony_ci 774e66f31c5Sopenharmony_ci result = func((SOCKET) fd, name, namelen); 775e66f31c5Sopenharmony_ci if (result != 0) 776e66f31c5Sopenharmony_ci return uv_translate_sys_error(WSAGetLastError()); 777e66f31c5Sopenharmony_ci 778e66f31c5Sopenharmony_ci return 0; 779e66f31c5Sopenharmony_ci} 780