Mercurial
comparison third_party/libuv/src/uv-common.c @ 160:948de3f54cea
[ThirdParty] Added libuv
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Wed, 14 Jan 2026 19:39:52 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 159:05cf9467a1c3 | 160:948de3f54cea |
|---|---|
| 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 "uv.h" | |
| 23 #include "uv-common.h" | |
| 24 | |
| 25 #include <assert.h> | |
| 26 #include <errno.h> | |
| 27 #include <stdarg.h> | |
| 28 #include <stddef.h> /* NULL */ | |
| 29 #include <stdio.h> | |
| 30 #include <stdlib.h> /* malloc */ | |
| 31 #include <string.h> /* memset */ | |
| 32 | |
| 33 #if defined(_WIN32) | |
| 34 # include <malloc.h> /* malloc */ | |
| 35 #else | |
| 36 # include <net/if.h> /* if_nametoindex */ | |
| 37 # include <sys/un.h> /* AF_UNIX, sockaddr_un */ | |
| 38 #endif | |
| 39 | |
| 40 | |
| 41 typedef struct { | |
| 42 uv_malloc_func local_malloc; | |
| 43 uv_realloc_func local_realloc; | |
| 44 uv_calloc_func local_calloc; | |
| 45 uv_free_func local_free; | |
| 46 } uv__allocator_t; | |
| 47 | |
| 48 static uv__allocator_t uv__allocator = { | |
| 49 malloc, | |
| 50 realloc, | |
| 51 calloc, | |
| 52 free, | |
| 53 }; | |
| 54 | |
| 55 char* uv__strdup(const char* s) { | |
| 56 size_t len = strlen(s) + 1; | |
| 57 char* m = uv__malloc(len); | |
| 58 if (m == NULL) | |
| 59 return NULL; | |
| 60 return memcpy(m, s, len); | |
| 61 } | |
| 62 | |
| 63 char* uv__strndup(const char* s, size_t n) { | |
| 64 char* m; | |
| 65 size_t len = strlen(s); | |
| 66 if (n < len) | |
| 67 len = n; | |
| 68 m = uv__malloc(len + 1); | |
| 69 if (m == NULL) | |
| 70 return NULL; | |
| 71 m[len] = '\0'; | |
| 72 return memcpy(m, s, len); | |
| 73 } | |
| 74 | |
| 75 void* uv__malloc(size_t size) { | |
| 76 if (size > 0) | |
| 77 return uv__allocator.local_malloc(size); | |
| 78 return NULL; | |
| 79 } | |
| 80 | |
| 81 void uv__free(void* ptr) { | |
| 82 int saved_errno; | |
| 83 | |
| 84 /* Libuv expects that free() does not clobber errno. The system allocator | |
| 85 * honors that assumption but custom allocators may not be so careful. | |
| 86 */ | |
| 87 saved_errno = errno; | |
| 88 uv__allocator.local_free(ptr); | |
| 89 errno = saved_errno; | |
| 90 } | |
| 91 | |
| 92 void* uv__calloc(size_t count, size_t size) { | |
| 93 return uv__allocator.local_calloc(count, size); | |
| 94 } | |
| 95 | |
| 96 void* uv__realloc(void* ptr, size_t size) { | |
| 97 if (size > 0) | |
| 98 return uv__allocator.local_realloc(ptr, size); | |
| 99 uv__free(ptr); | |
| 100 return NULL; | |
| 101 } | |
| 102 | |
| 103 void* uv__reallocf(void* ptr, size_t size) { | |
| 104 void* newptr; | |
| 105 | |
| 106 newptr = uv__realloc(ptr, size); | |
| 107 if (newptr == NULL) | |
| 108 if (size > 0) | |
| 109 uv__free(ptr); | |
| 110 | |
| 111 return newptr; | |
| 112 } | |
| 113 | |
| 114 int uv_replace_allocator(uv_malloc_func malloc_func, | |
| 115 uv_realloc_func realloc_func, | |
| 116 uv_calloc_func calloc_func, | |
| 117 uv_free_func free_func) { | |
| 118 if (malloc_func == NULL || realloc_func == NULL || | |
| 119 calloc_func == NULL || free_func == NULL) { | |
| 120 return UV_EINVAL; | |
| 121 } | |
| 122 | |
| 123 uv__allocator.local_malloc = malloc_func; | |
| 124 uv__allocator.local_realloc = realloc_func; | |
| 125 uv__allocator.local_calloc = calloc_func; | |
| 126 uv__allocator.local_free = free_func; | |
| 127 | |
| 128 return 0; | |
| 129 } | |
| 130 | |
| 131 | |
| 132 void uv_os_free_passwd(uv_passwd_t* pwd) { | |
| 133 if (pwd == NULL) | |
| 134 return; | |
| 135 | |
| 136 /* On unix, the memory for name, shell, and homedir are allocated in a single | |
| 137 * uv__malloc() call. The base of the pointer is stored in pwd->username, so | |
| 138 * that is the field that needs to be freed. | |
| 139 */ | |
| 140 uv__free(pwd->username); | |
| 141 #ifdef _WIN32 | |
| 142 uv__free(pwd->homedir); | |
| 143 #endif | |
| 144 pwd->username = NULL; | |
| 145 pwd->shell = NULL; | |
| 146 pwd->homedir = NULL; | |
| 147 } | |
| 148 | |
| 149 | |
| 150 void uv_os_free_group(uv_group_t *grp) { | |
| 151 if (grp == NULL) | |
| 152 return; | |
| 153 | |
| 154 /* The memory for is allocated in a single uv__malloc() call. The base of the | |
| 155 * pointer is stored in grp->members, so that is the only field that needs to | |
| 156 * be freed. | |
| 157 */ | |
| 158 uv__free(grp->members); | |
| 159 grp->members = NULL; | |
| 160 grp->groupname = NULL; | |
| 161 } | |
| 162 | |
| 163 | |
| 164 #define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t); | |
| 165 | |
| 166 size_t uv_handle_size(uv_handle_type type) { | |
| 167 switch (type) { | |
| 168 UV_HANDLE_TYPE_MAP(XX) | |
| 169 default: | |
| 170 return -1; | |
| 171 } | |
| 172 } | |
| 173 | |
| 174 size_t uv_req_size(uv_req_type type) { | |
| 175 switch(type) { | |
| 176 UV_REQ_TYPE_MAP(XX) | |
| 177 default: | |
| 178 return -1; | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 #undef XX | |
| 183 | |
| 184 | |
| 185 size_t uv_loop_size(void) { | |
| 186 return sizeof(uv_loop_t); | |
| 187 } | |
| 188 | |
| 189 | |
| 190 uv_buf_t uv_buf_init(char* base, unsigned int len) { | |
| 191 uv_buf_t buf; | |
| 192 buf.base = base; | |
| 193 buf.len = len; | |
| 194 return buf; | |
| 195 } | |
| 196 | |
| 197 | |
| 198 static const char* uv__unknown_err_code(int err) { | |
| 199 char buf[32]; | |
| 200 char* copy; | |
| 201 | |
| 202 snprintf(buf, sizeof(buf), "Unknown system error %d", err); | |
| 203 copy = uv__strdup(buf); | |
| 204 | |
| 205 return copy != NULL ? copy : "Unknown system error"; | |
| 206 } | |
| 207 | |
| 208 #define UV_ERR_NAME_GEN_R(name, _) \ | |
| 209 case UV_## name: \ | |
| 210 uv__strscpy(buf, #name, buflen); break; | |
| 211 char* uv_err_name_r(int err, char* buf, size_t buflen) { | |
| 212 switch (err) { | |
| 213 UV_ERRNO_MAP(UV_ERR_NAME_GEN_R) | |
| 214 default: snprintf(buf, buflen, "Unknown system error %d", err); | |
| 215 } | |
| 216 return buf; | |
| 217 } | |
| 218 #undef UV_ERR_NAME_GEN_R | |
| 219 | |
| 220 | |
| 221 #define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name; | |
| 222 const char* uv_err_name(int err) { | |
| 223 switch (err) { | |
| 224 UV_ERRNO_MAP(UV_ERR_NAME_GEN) | |
| 225 } | |
| 226 return uv__unknown_err_code(err); | |
| 227 } | |
| 228 #undef UV_ERR_NAME_GEN | |
| 229 | |
| 230 | |
| 231 #define UV_STRERROR_GEN_R(name, msg) \ | |
| 232 case UV_ ## name: \ | |
| 233 snprintf(buf, buflen, "%s", msg); break; | |
| 234 char* uv_strerror_r(int err, char* buf, size_t buflen) { | |
| 235 switch (err) { | |
| 236 UV_ERRNO_MAP(UV_STRERROR_GEN_R) | |
| 237 default: snprintf(buf, buflen, "Unknown system error %d", err); | |
| 238 } | |
| 239 return buf; | |
| 240 } | |
| 241 #undef UV_STRERROR_GEN_R | |
| 242 | |
| 243 | |
| 244 #define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg; | |
| 245 const char* uv_strerror(int err) { | |
| 246 switch (err) { | |
| 247 UV_ERRNO_MAP(UV_STRERROR_GEN) | |
| 248 } | |
| 249 return uv__unknown_err_code(err); | |
| 250 } | |
| 251 #undef UV_STRERROR_GEN | |
| 252 | |
| 253 | |
| 254 int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) { | |
| 255 memset(addr, 0, sizeof(*addr)); | |
| 256 addr->sin_family = AF_INET; | |
| 257 addr->sin_port = htons(port); | |
| 258 #ifdef SIN6_LEN | |
| 259 addr->sin_len = sizeof(*addr); | |
| 260 #endif | |
| 261 return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr)); | |
| 262 } | |
| 263 | |
| 264 | |
| 265 int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) { | |
| 266 char address_part[40]; | |
| 267 size_t address_part_size; | |
| 268 const char* zone_index; | |
| 269 | |
| 270 memset(addr, 0, sizeof(*addr)); | |
| 271 addr->sin6_family = AF_INET6; | |
| 272 addr->sin6_port = htons(port); | |
| 273 #ifdef SIN6_LEN | |
| 274 addr->sin6_len = sizeof(*addr); | |
| 275 #endif | |
| 276 | |
| 277 zone_index = strchr(ip, '%'); | |
| 278 if (zone_index != NULL) { | |
| 279 address_part_size = zone_index - ip; | |
| 280 if (address_part_size >= sizeof(address_part)) | |
| 281 address_part_size = sizeof(address_part) - 1; | |
| 282 | |
| 283 memcpy(address_part, ip, address_part_size); | |
| 284 address_part[address_part_size] = '\0'; | |
| 285 ip = address_part; | |
| 286 | |
| 287 zone_index++; /* skip '%' */ | |
| 288 /* NOTE: unknown interface (id=0) is silently ignored */ | |
| 289 #ifdef _WIN32 | |
| 290 addr->sin6_scope_id = atoi(zone_index); | |
| 291 #else | |
| 292 addr->sin6_scope_id = if_nametoindex(zone_index); | |
| 293 #endif | |
| 294 } | |
| 295 | |
| 296 return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr); | |
| 297 } | |
| 298 | |
| 299 | |
| 300 int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) { | |
| 301 return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size); | |
| 302 } | |
| 303 | |
| 304 | |
| 305 int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) { | |
| 306 return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size); | |
| 307 } | |
| 308 | |
| 309 | |
| 310 int uv_ip_name(const struct sockaddr *src, char *dst, size_t size) { | |
| 311 switch (src->sa_family) { | |
| 312 case AF_INET: | |
| 313 return uv_inet_ntop(AF_INET, &((struct sockaddr_in *)src)->sin_addr, | |
| 314 dst, size); | |
| 315 case AF_INET6: | |
| 316 return uv_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)src)->sin6_addr, | |
| 317 dst, size); | |
| 318 default: | |
| 319 return UV_EAFNOSUPPORT; | |
| 320 } | |
| 321 } | |
| 322 | |
| 323 | |
| 324 int uv_tcp_bind(uv_tcp_t* handle, | |
| 325 const struct sockaddr* addr, | |
| 326 unsigned int flags) { | |
| 327 unsigned int addrlen; | |
| 328 | |
| 329 if (handle->type != UV_TCP) | |
| 330 return UV_EINVAL; | |
| 331 if (uv__is_closing(handle)) { | |
| 332 return UV_EINVAL; | |
| 333 } | |
| 334 if (addr->sa_family == AF_INET) | |
| 335 addrlen = sizeof(struct sockaddr_in); | |
| 336 else if (addr->sa_family == AF_INET6) | |
| 337 addrlen = sizeof(struct sockaddr_in6); | |
| 338 else | |
| 339 return UV_EINVAL; | |
| 340 | |
| 341 return uv__tcp_bind(handle, addr, addrlen, flags); | |
| 342 } | |
| 343 | |
| 344 | |
| 345 int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned flags) { | |
| 346 unsigned extra_flags; | |
| 347 int domain; | |
| 348 int rc; | |
| 349 | |
| 350 /* Use the lower 8 bits for the domain. */ | |
| 351 domain = flags & 0xFF; | |
| 352 if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) | |
| 353 return UV_EINVAL; | |
| 354 | |
| 355 /* Use the higher bits for extra flags. */ | |
| 356 extra_flags = flags & ~0xFF; | |
| 357 if (extra_flags & ~UV_UDP_RECVMMSG) | |
| 358 return UV_EINVAL; | |
| 359 | |
| 360 rc = uv__udp_init_ex(loop, handle, flags, domain); | |
| 361 | |
| 362 if (rc == 0) | |
| 363 if (extra_flags & UV_UDP_RECVMMSG) | |
| 364 handle->flags |= UV_HANDLE_UDP_RECVMMSG; | |
| 365 | |
| 366 return rc; | |
| 367 } | |
| 368 | |
| 369 | |
| 370 int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { | |
| 371 return uv_udp_init_ex(loop, handle, AF_UNSPEC); | |
| 372 } | |
| 373 | |
| 374 | |
| 375 int uv_udp_bind(uv_udp_t* handle, | |
| 376 const struct sockaddr* addr, | |
| 377 unsigned int flags) { | |
| 378 unsigned int addrlen; | |
| 379 | |
| 380 if (handle->type != UV_UDP) | |
| 381 return UV_EINVAL; | |
| 382 | |
| 383 if (addr->sa_family == AF_INET) | |
| 384 addrlen = sizeof(struct sockaddr_in); | |
| 385 else if (addr->sa_family == AF_INET6) | |
| 386 addrlen = sizeof(struct sockaddr_in6); | |
| 387 else | |
| 388 return UV_EINVAL; | |
| 389 | |
| 390 return uv__udp_bind(handle, addr, addrlen, flags); | |
| 391 } | |
| 392 | |
| 393 | |
| 394 int uv_tcp_connect(uv_connect_t* req, | |
| 395 uv_tcp_t* handle, | |
| 396 const struct sockaddr* addr, | |
| 397 uv_connect_cb cb) { | |
| 398 unsigned int addrlen; | |
| 399 | |
| 400 if (handle->type != UV_TCP) | |
| 401 return UV_EINVAL; | |
| 402 | |
| 403 if (addr->sa_family == AF_INET) | |
| 404 addrlen = sizeof(struct sockaddr_in); | |
| 405 else if (addr->sa_family == AF_INET6) | |
| 406 addrlen = sizeof(struct sockaddr_in6); | |
| 407 else | |
| 408 return UV_EINVAL; | |
| 409 | |
| 410 return uv__tcp_connect(req, handle, addr, addrlen, cb); | |
| 411 } | |
| 412 | |
| 413 | |
| 414 int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) { | |
| 415 unsigned int addrlen; | |
| 416 | |
| 417 if (handle->type != UV_UDP) | |
| 418 return UV_EINVAL; | |
| 419 | |
| 420 /* Disconnect the handle */ | |
| 421 if (addr == NULL) { | |
| 422 if (!(handle->flags & UV_HANDLE_UDP_CONNECTED)) | |
| 423 return UV_ENOTCONN; | |
| 424 | |
| 425 return uv__udp_disconnect(handle); | |
| 426 } | |
| 427 | |
| 428 if (addr->sa_family == AF_INET) | |
| 429 addrlen = sizeof(struct sockaddr_in); | |
| 430 else if (addr->sa_family == AF_INET6) | |
| 431 addrlen = sizeof(struct sockaddr_in6); | |
| 432 else | |
| 433 return UV_EINVAL; | |
| 434 | |
| 435 if (handle->flags & UV_HANDLE_UDP_CONNECTED) | |
| 436 return UV_EISCONN; | |
| 437 | |
| 438 return uv__udp_connect(handle, addr, addrlen); | |
| 439 } | |
| 440 | |
| 441 | |
| 442 int uv__udp_is_connected(uv_udp_t* handle) { | |
| 443 struct sockaddr_storage addr; | |
| 444 int addrlen; | |
| 445 if (handle->type != UV_UDP) | |
| 446 return 0; | |
| 447 | |
| 448 addrlen = sizeof(addr); | |
| 449 if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0) | |
| 450 return 0; | |
| 451 | |
| 452 return addrlen > 0; | |
| 453 } | |
| 454 | |
| 455 | |
| 456 int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) { | |
| 457 unsigned int addrlen; | |
| 458 | |
| 459 if (handle->type != UV_UDP) | |
| 460 return UV_EINVAL; | |
| 461 | |
| 462 if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED)) | |
| 463 return UV_EISCONN; | |
| 464 | |
| 465 if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED)) | |
| 466 return UV_EDESTADDRREQ; | |
| 467 | |
| 468 if (addr != NULL) { | |
| 469 if (addr->sa_family == AF_INET) | |
| 470 addrlen = sizeof(struct sockaddr_in); | |
| 471 else if (addr->sa_family == AF_INET6) | |
| 472 addrlen = sizeof(struct sockaddr_in6); | |
| 473 #if defined(AF_UNIX) && !defined(_WIN32) | |
| 474 else if (addr->sa_family == AF_UNIX) | |
| 475 addrlen = sizeof(struct sockaddr_un); | |
| 476 #endif | |
| 477 else | |
| 478 return UV_EINVAL; | |
| 479 } else { | |
| 480 addrlen = 0; | |
| 481 } | |
| 482 | |
| 483 return addrlen; | |
| 484 } | |
| 485 | |
| 486 | |
| 487 int uv_udp_send(uv_udp_send_t* req, | |
| 488 uv_udp_t* handle, | |
| 489 const uv_buf_t bufs[], | |
| 490 unsigned int nbufs, | |
| 491 const struct sockaddr* addr, | |
| 492 uv_udp_send_cb send_cb) { | |
| 493 int addrlen; | |
| 494 | |
| 495 addrlen = uv__udp_check_before_send(handle, addr); | |
| 496 if (addrlen < 0) | |
| 497 return addrlen; | |
| 498 | |
| 499 return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb); | |
| 500 } | |
| 501 | |
| 502 | |
| 503 int uv_udp_try_send(uv_udp_t* handle, | |
| 504 const uv_buf_t bufs[], | |
| 505 unsigned int nbufs, | |
| 506 const struct sockaddr* addr) { | |
| 507 int addrlen; | |
| 508 | |
| 509 addrlen = uv__udp_check_before_send(handle, addr); | |
| 510 if (addrlen < 0) | |
| 511 return addrlen; | |
| 512 | |
| 513 return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen); | |
| 514 } | |
| 515 | |
| 516 | |
| 517 int uv_udp_try_send2(uv_udp_t* handle, | |
| 518 unsigned int count, | |
| 519 uv_buf_t* bufs[/*count*/], | |
| 520 unsigned int nbufs[/*count*/], | |
| 521 struct sockaddr* addrs[/*count*/], | |
| 522 unsigned int flags) { | |
| 523 if (count < 1) | |
| 524 return UV_EINVAL; | |
| 525 | |
| 526 if (flags != 0) | |
| 527 return UV_EINVAL; | |
| 528 | |
| 529 if (handle->send_queue_count > 0) | |
| 530 return UV_EAGAIN; | |
| 531 | |
| 532 return uv__udp_try_send2(handle, count, bufs, nbufs, addrs); | |
| 533 } | |
| 534 | |
| 535 | |
| 536 int uv_udp_recv_start(uv_udp_t* handle, | |
| 537 uv_alloc_cb alloc_cb, | |
| 538 uv_udp_recv_cb recv_cb) { | |
| 539 if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL) | |
| 540 return UV_EINVAL; | |
| 541 else | |
| 542 return uv__udp_recv_start(handle, alloc_cb, recv_cb); | |
| 543 } | |
| 544 | |
| 545 | |
| 546 int uv_udp_recv_stop(uv_udp_t* handle) { | |
| 547 if (handle->type != UV_UDP) | |
| 548 return UV_EINVAL; | |
| 549 else | |
| 550 return uv__udp_recv_stop(handle); | |
| 551 } | |
| 552 | |
| 553 | |
| 554 void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) { | |
| 555 struct uv__queue queue; | |
| 556 struct uv__queue* q; | |
| 557 uv_handle_t* h; | |
| 558 | |
| 559 uv__queue_move(&loop->handle_queue, &queue); | |
| 560 while (!uv__queue_empty(&queue)) { | |
| 561 q = uv__queue_head(&queue); | |
| 562 h = uv__queue_data(q, uv_handle_t, handle_queue); | |
| 563 | |
| 564 uv__queue_remove(q); | |
| 565 uv__queue_insert_tail(&loop->handle_queue, q); | |
| 566 | |
| 567 if (h->flags & UV_HANDLE_INTERNAL) continue; | |
| 568 walk_cb(h, arg); | |
| 569 } | |
| 570 } | |
| 571 | |
| 572 | |
| 573 static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) { | |
| 574 const char* type; | |
| 575 struct uv__queue* q; | |
| 576 uv_handle_t* h; | |
| 577 | |
| 578 if (loop == NULL) | |
| 579 loop = uv_default_loop(); | |
| 580 | |
| 581 if (stream == NULL) | |
| 582 stream = stderr; | |
| 583 | |
| 584 uv__queue_foreach(q, &loop->handle_queue) { | |
| 585 h = uv__queue_data(q, uv_handle_t, handle_queue); | |
| 586 | |
| 587 if (only_active && !uv__is_active(h)) | |
| 588 continue; | |
| 589 | |
| 590 switch (h->type) { | |
| 591 #define X(uc, lc) case UV_##uc: type = #lc; break; | |
| 592 UV_HANDLE_TYPE_MAP(X) | |
| 593 #undef X | |
| 594 default: type = "<unknown>"; | |
| 595 } | |
| 596 | |
| 597 fprintf(stream, | |
| 598 "[%c%c%c] %-8s %p\n", | |
| 599 "R-"[!(h->flags & UV_HANDLE_REF)], | |
| 600 "A-"[!(h->flags & UV_HANDLE_ACTIVE)], | |
| 601 "I-"[!(h->flags & UV_HANDLE_INTERNAL)], | |
| 602 type, | |
| 603 (void*)h); | |
| 604 } | |
| 605 } | |
| 606 | |
| 607 | |
| 608 void uv_print_all_handles(uv_loop_t* loop, FILE* stream) { | |
| 609 uv__print_handles(loop, 0, stream); | |
| 610 } | |
| 611 | |
| 612 | |
| 613 void uv_print_active_handles(uv_loop_t* loop, FILE* stream) { | |
| 614 uv__print_handles(loop, 1, stream); | |
| 615 } | |
| 616 | |
| 617 | |
| 618 void uv_ref(uv_handle_t* handle) { | |
| 619 uv__handle_ref(handle); | |
| 620 } | |
| 621 | |
| 622 | |
| 623 void uv_unref(uv_handle_t* handle) { | |
| 624 uv__handle_unref(handle); | |
| 625 } | |
| 626 | |
| 627 | |
| 628 int uv_has_ref(const uv_handle_t* handle) { | |
| 629 return uv__has_ref(handle); | |
| 630 } | |
| 631 | |
| 632 | |
| 633 void uv_stop(uv_loop_t* loop) { | |
| 634 loop->stop_flag = 1; | |
| 635 } | |
| 636 | |
| 637 | |
| 638 uint64_t uv_now(const uv_loop_t* loop) { | |
| 639 return loop->time; | |
| 640 } | |
| 641 | |
| 642 | |
| 643 | |
| 644 size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) { | |
| 645 unsigned int i; | |
| 646 size_t bytes; | |
| 647 | |
| 648 bytes = 0; | |
| 649 for (i = 0; i < nbufs; i++) | |
| 650 bytes += (size_t) bufs[i].len; | |
| 651 | |
| 652 return bytes; | |
| 653 } | |
| 654 | |
| 655 int uv_recv_buffer_size(uv_handle_t* handle, int* value) { | |
| 656 return uv__socket_sockopt(handle, SO_RCVBUF, value); | |
| 657 } | |
| 658 | |
| 659 int uv_send_buffer_size(uv_handle_t* handle, int *value) { | |
| 660 return uv__socket_sockopt(handle, SO_SNDBUF, value); | |
| 661 } | |
| 662 | |
| 663 int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) { | |
| 664 size_t required_len; | |
| 665 | |
| 666 if (buffer == NULL || size == NULL || *size == 0) | |
| 667 return UV_EINVAL; | |
| 668 | |
| 669 if (!uv__is_active(handle)) { | |
| 670 *size = 0; | |
| 671 return UV_EINVAL; | |
| 672 } | |
| 673 | |
| 674 required_len = strlen(handle->path); | |
| 675 if (required_len >= *size) { | |
| 676 *size = required_len + 1; | |
| 677 return UV_ENOBUFS; | |
| 678 } | |
| 679 | |
| 680 memcpy(buffer, handle->path, required_len); | |
| 681 *size = required_len; | |
| 682 buffer[required_len] = '\0'; | |
| 683 | |
| 684 return 0; | |
| 685 } | |
| 686 | |
| 687 /* The windows implementation does not have the same structure layout as | |
| 688 * the unix implementation (nbufs is not directly inside req but is | |
| 689 * contained in a nested union/struct) so this function locates it. | |
| 690 */ | |
| 691 static unsigned int* uv__get_nbufs(uv_fs_t* req) { | |
| 692 #ifdef _WIN32 | |
| 693 return &req->fs.info.nbufs; | |
| 694 #else | |
| 695 return &req->nbufs; | |
| 696 #endif | |
| 697 } | |
| 698 | |
| 699 /* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows | |
| 700 * systems. So, the memory should be released using free(). On Windows, | |
| 701 * uv__malloc() is used, so use uv__free() to free memory. | |
| 702 */ | |
| 703 #ifdef _WIN32 | |
| 704 # define uv__fs_scandir_free uv__free | |
| 705 #else | |
| 706 # define uv__fs_scandir_free free | |
| 707 #endif | |
| 708 | |
| 709 void uv__fs_scandir_cleanup(uv_fs_t* req) { | |
| 710 uv__dirent_t** dents; | |
| 711 unsigned int* nbufs; | |
| 712 unsigned int i; | |
| 713 unsigned int n; | |
| 714 | |
| 715 if (req->result >= 0) { | |
| 716 dents = req->ptr; | |
| 717 nbufs = uv__get_nbufs(req); | |
| 718 | |
| 719 i = 0; | |
| 720 if (*nbufs > 0) | |
| 721 i = *nbufs - 1; | |
| 722 | |
| 723 n = (unsigned int) req->result; | |
| 724 for (; i < n; i++) | |
| 725 uv__fs_scandir_free(dents[i]); | |
| 726 } | |
| 727 | |
| 728 uv__fs_scandir_free(req->ptr); | |
| 729 req->ptr = NULL; | |
| 730 } | |
| 731 | |
| 732 | |
| 733 int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { | |
| 734 uv__dirent_t** dents; | |
| 735 uv__dirent_t* dent; | |
| 736 unsigned int* nbufs; | |
| 737 | |
| 738 /* Check to see if req passed */ | |
| 739 if (req->result < 0) | |
| 740 return req->result; | |
| 741 | |
| 742 /* Ptr will be null if req was canceled or no files found */ | |
| 743 if (!req->ptr) | |
| 744 return UV_EOF; | |
| 745 | |
| 746 nbufs = uv__get_nbufs(req); | |
| 747 assert(nbufs); | |
| 748 | |
| 749 dents = req->ptr; | |
| 750 | |
| 751 /* Free previous entity */ | |
| 752 if (*nbufs > 0) | |
| 753 uv__fs_scandir_free(dents[*nbufs - 1]); | |
| 754 | |
| 755 /* End was already reached */ | |
| 756 if (*nbufs == (unsigned int) req->result) { | |
| 757 uv__fs_scandir_free(dents); | |
| 758 req->ptr = NULL; | |
| 759 return UV_EOF; | |
| 760 } | |
| 761 | |
| 762 dent = dents[(*nbufs)++]; | |
| 763 | |
| 764 ent->name = dent->d_name; | |
| 765 ent->type = uv__fs_get_dirent_type(dent); | |
| 766 | |
| 767 return 0; | |
| 768 } | |
| 769 | |
| 770 uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) { | |
| 771 uv_dirent_type_t type; | |
| 772 | |
| 773 #ifdef HAVE_DIRENT_TYPES | |
| 774 switch (dent->d_type) { | |
| 775 case UV__DT_DIR: | |
| 776 type = UV_DIRENT_DIR; | |
| 777 break; | |
| 778 case UV__DT_FILE: | |
| 779 type = UV_DIRENT_FILE; | |
| 780 break; | |
| 781 case UV__DT_LINK: | |
| 782 type = UV_DIRENT_LINK; | |
| 783 break; | |
| 784 case UV__DT_FIFO: | |
| 785 type = UV_DIRENT_FIFO; | |
| 786 break; | |
| 787 case UV__DT_SOCKET: | |
| 788 type = UV_DIRENT_SOCKET; | |
| 789 break; | |
| 790 case UV__DT_CHAR: | |
| 791 type = UV_DIRENT_CHAR; | |
| 792 break; | |
| 793 case UV__DT_BLOCK: | |
| 794 type = UV_DIRENT_BLOCK; | |
| 795 break; | |
| 796 default: | |
| 797 type = UV_DIRENT_UNKNOWN; | |
| 798 } | |
| 799 #else | |
| 800 type = UV_DIRENT_UNKNOWN; | |
| 801 #endif | |
| 802 | |
| 803 return type; | |
| 804 } | |
| 805 | |
| 806 void uv__fs_readdir_cleanup(uv_fs_t* req) { | |
| 807 uv_dir_t* dir; | |
| 808 uv_dirent_t* dirents; | |
| 809 int i; | |
| 810 | |
| 811 if (req->ptr == NULL) | |
| 812 return; | |
| 813 | |
| 814 dir = req->ptr; | |
| 815 dirents = dir->dirents; | |
| 816 req->ptr = NULL; | |
| 817 | |
| 818 if (dirents == NULL) | |
| 819 return; | |
| 820 | |
| 821 for (i = 0; i < req->result; ++i) { | |
| 822 uv__free((char*) dirents[i].name); | |
| 823 dirents[i].name = NULL; | |
| 824 } | |
| 825 } | |
| 826 | |
| 827 | |
| 828 int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) { | |
| 829 va_list ap; | |
| 830 int err; | |
| 831 | |
| 832 va_start(ap, option); | |
| 833 /* Any platform-agnostic options should be handled here. */ | |
| 834 err = uv__loop_configure(loop, option, ap); | |
| 835 va_end(ap); | |
| 836 | |
| 837 return err; | |
| 838 } | |
| 839 | |
| 840 | |
| 841 static uv_loop_t default_loop_struct; | |
| 842 static uv_loop_t* default_loop_ptr; | |
| 843 | |
| 844 | |
| 845 uv_loop_t* uv_default_loop(void) { | |
| 846 if (default_loop_ptr != NULL) | |
| 847 return default_loop_ptr; | |
| 848 | |
| 849 if (uv_loop_init(&default_loop_struct)) | |
| 850 return NULL; | |
| 851 | |
| 852 default_loop_ptr = &default_loop_struct; | |
| 853 return default_loop_ptr; | |
| 854 } | |
| 855 | |
| 856 | |
| 857 uv_loop_t* uv_loop_new(void) { | |
| 858 uv_loop_t* loop; | |
| 859 | |
| 860 loop = uv__malloc(sizeof(*loop)); | |
| 861 if (loop == NULL) | |
| 862 return NULL; | |
| 863 | |
| 864 if (uv_loop_init(loop)) { | |
| 865 uv__free(loop); | |
| 866 return NULL; | |
| 867 } | |
| 868 | |
| 869 return loop; | |
| 870 } | |
| 871 | |
| 872 | |
| 873 int uv_loop_close(uv_loop_t* loop) { | |
| 874 struct uv__queue* q; | |
| 875 uv_handle_t* h; | |
| 876 #ifndef NDEBUG | |
| 877 void* saved_data; | |
| 878 #endif | |
| 879 | |
| 880 if (uv__has_active_reqs(loop)) | |
| 881 return UV_EBUSY; | |
| 882 | |
| 883 uv__queue_foreach(q, &loop->handle_queue) { | |
| 884 h = uv__queue_data(q, uv_handle_t, handle_queue); | |
| 885 if (!(h->flags & UV_HANDLE_INTERNAL)) | |
| 886 return UV_EBUSY; | |
| 887 } | |
| 888 | |
| 889 uv__loop_close(loop); | |
| 890 | |
| 891 #ifndef NDEBUG | |
| 892 saved_data = loop->data; | |
| 893 memset(loop, -1, sizeof(*loop)); | |
| 894 loop->data = saved_data; | |
| 895 #endif | |
| 896 if (loop == default_loop_ptr) | |
| 897 default_loop_ptr = NULL; | |
| 898 | |
| 899 return 0; | |
| 900 } | |
| 901 | |
| 902 | |
| 903 void uv_loop_delete(uv_loop_t* loop) { | |
| 904 uv_loop_t* default_loop; | |
| 905 int err; | |
| 906 | |
| 907 default_loop = default_loop_ptr; | |
| 908 | |
| 909 err = uv_loop_close(loop); | |
| 910 (void) err; /* Squelch compiler warnings. */ | |
| 911 assert(err == 0); | |
| 912 if (loop != default_loop) | |
| 913 uv__free(loop); | |
| 914 } | |
| 915 | |
| 916 | |
| 917 int uv_read_start(uv_stream_t* stream, | |
| 918 uv_alloc_cb alloc_cb, | |
| 919 uv_read_cb read_cb) { | |
| 920 if (stream == NULL || alloc_cb == NULL || read_cb == NULL) | |
| 921 return UV_EINVAL; | |
| 922 | |
| 923 if (stream->flags & UV_HANDLE_CLOSING) | |
| 924 return UV_EINVAL; | |
| 925 | |
| 926 if (stream->flags & UV_HANDLE_READING) | |
| 927 return UV_EALREADY; | |
| 928 | |
| 929 if (!(stream->flags & UV_HANDLE_READABLE)) | |
| 930 return UV_ENOTCONN; | |
| 931 | |
| 932 return uv__read_start(stream, alloc_cb, read_cb); | |
| 933 } | |
| 934 | |
| 935 | |
| 936 void uv_os_free_environ(uv_env_item_t* envitems, int count) { | |
| 937 int i; | |
| 938 | |
| 939 for (i = 0; i < count; i++) { | |
| 940 uv__free(envitems[i].name); | |
| 941 } | |
| 942 | |
| 943 uv__free(envitems); | |
| 944 } | |
| 945 | |
| 946 | |
| 947 void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { | |
| 948 #ifdef __linux__ | |
| 949 (void) &count; | |
| 950 uv__free(cpu_infos); | |
| 951 #else | |
| 952 int i; | |
| 953 | |
| 954 for (i = 0; i < count; i++) | |
| 955 uv__free(cpu_infos[i].model); | |
| 956 | |
| 957 uv__free(cpu_infos); | |
| 958 #endif /* __linux__ */ | |
| 959 } | |
| 960 | |
| 961 | |
| 962 /* Also covers __clang__ and __INTEL_COMPILER. Disabled on Windows because | |
| 963 * threads have already been forcibly terminated by the operating system | |
| 964 * by the time destructors run, ergo, it's not safe to try to clean them up. | |
| 965 */ | |
| 966 #if defined(__GNUC__) && !defined(_WIN32) | |
| 967 __attribute__((destructor)) | |
| 968 #endif | |
| 969 void uv_library_shutdown(void) { | |
| 970 static int was_shutdown; | |
| 971 | |
| 972 if (uv__exchange_int_relaxed(&was_shutdown, 1)) | |
| 973 return; | |
| 974 | |
| 975 uv__process_title_cleanup(); | |
| 976 uv__signal_cleanup(); | |
| 977 #ifdef __MVS__ | |
| 978 /* TODO(itodorov) - zos: revisit when Woz compiler is available. */ | |
| 979 uv__os390_cleanup(); | |
| 980 #else | |
| 981 uv__threadpool_cleanup(); | |
| 982 #endif | |
| 983 } | |
| 984 | |
| 985 | |
| 986 void uv__metrics_update_idle_time(uv_loop_t* loop) { | |
| 987 uv__loop_metrics_t* loop_metrics; | |
| 988 uint64_t entry_time; | |
| 989 uint64_t exit_time; | |
| 990 | |
| 991 if (!(uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME)) | |
| 992 return; | |
| 993 | |
| 994 loop_metrics = uv__get_loop_metrics(loop); | |
| 995 | |
| 996 /* The thread running uv__metrics_update_idle_time() is always the same | |
| 997 * thread that sets provider_entry_time. So it's unnecessary to lock before | |
| 998 * retrieving this value. | |
| 999 */ | |
| 1000 if (loop_metrics->provider_entry_time == 0) | |
| 1001 return; | |
| 1002 | |
| 1003 exit_time = uv_hrtime(); | |
| 1004 | |
| 1005 uv_mutex_lock(&loop_metrics->lock); | |
| 1006 entry_time = loop_metrics->provider_entry_time; | |
| 1007 loop_metrics->provider_entry_time = 0; | |
| 1008 loop_metrics->provider_idle_time += exit_time - entry_time; | |
| 1009 uv_mutex_unlock(&loop_metrics->lock); | |
| 1010 } | |
| 1011 | |
| 1012 | |
| 1013 void uv__metrics_set_provider_entry_time(uv_loop_t* loop) { | |
| 1014 uv__loop_metrics_t* loop_metrics; | |
| 1015 uint64_t now; | |
| 1016 | |
| 1017 if (!(uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME)) | |
| 1018 return; | |
| 1019 | |
| 1020 now = uv_hrtime(); | |
| 1021 loop_metrics = uv__get_loop_metrics(loop); | |
| 1022 uv_mutex_lock(&loop_metrics->lock); | |
| 1023 loop_metrics->provider_entry_time = now; | |
| 1024 uv_mutex_unlock(&loop_metrics->lock); | |
| 1025 } | |
| 1026 | |
| 1027 | |
| 1028 int uv_metrics_info(uv_loop_t* loop, uv_metrics_t* metrics) { | |
| 1029 memcpy(metrics, | |
| 1030 &uv__get_loop_metrics(loop)->metrics, | |
| 1031 sizeof(*metrics)); | |
| 1032 | |
| 1033 return 0; | |
| 1034 } | |
| 1035 | |
| 1036 | |
| 1037 uint64_t uv_metrics_idle_time(uv_loop_t* loop) { | |
| 1038 uv__loop_metrics_t* loop_metrics; | |
| 1039 uint64_t entry_time; | |
| 1040 uint64_t idle_time; | |
| 1041 | |
| 1042 loop_metrics = uv__get_loop_metrics(loop); | |
| 1043 uv_mutex_lock(&loop_metrics->lock); | |
| 1044 idle_time = loop_metrics->provider_idle_time; | |
| 1045 entry_time = loop_metrics->provider_entry_time; | |
| 1046 uv_mutex_unlock(&loop_metrics->lock); | |
| 1047 | |
| 1048 if (entry_time > 0) | |
| 1049 idle_time += uv_hrtime() - entry_time; | |
| 1050 return idle_time; | |
| 1051 } |