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/tree.h" 24#include "uv_log.h" 25#include "internal.h" 26#include "heap-inl.h" 27#include <stdlib.h> 28#include <string.h> 29#include <unistd.h> 30 31int uv_loop_init(uv_loop_t* loop) { 32 uv__loop_internal_fields_t* lfields; 33 void* saved_data; 34 int err; 35 36 UV_LOGI("init:%{public}zu", (size_t)loop); 37 saved_data = loop->data; 38 memset(loop, 0, sizeof(*loop)); 39 loop->data = saved_data; 40 41 lfields = (uv__loop_internal_fields_t*) uv__calloc(1, sizeof(*lfields)); 42 if (lfields == NULL) 43 return UV_ENOMEM; 44 loop->internal_fields = lfields; 45 46 err = uv_mutex_init(&lfields->loop_metrics.lock); 47 if (err) 48 goto fail_metrics_mutex_init; 49 memset(&lfields->loop_metrics.metrics, 50 0, 51 sizeof(lfields->loop_metrics.metrics)); 52 53 heap_init((struct heap*) &loop->timer_heap); 54 uv__queue_init(&loop->wq); 55#ifdef USE_FFRT 56 uv__loop_internal_fields_t* lfields_qos = uv__get_internal_fields(loop); 57 uv__queue_init(&(lfields_qos->wq_sub[uv_qos_background])); 58 uv__queue_init(&(lfields_qos->wq_sub[uv_qos_utility])); 59 uv__queue_init(&(lfields_qos->wq_sub[uv_qos_default])); 60 uv__queue_init(&(lfields_qos->wq_sub[uv_qos_user_initiated])); 61#endif 62 63 uv__queue_init(&loop->idle_handles); 64 uv__queue_init(&loop->async_handles); 65 uv__queue_init(&loop->check_handles); 66 uv__queue_init(&loop->prepare_handles); 67 uv__queue_init(&loop->handle_queue); 68 69 loop->active_handles = 0; 70 loop->active_reqs.count = 0; 71 loop->nfds = 0; 72 loop->watchers = NULL; 73 loop->nwatchers = 0; 74 uv__queue_init(&loop->pending_queue); 75 uv__queue_init(&loop->watcher_queue); 76 77 loop->closing_handles = NULL; 78 uv__update_time(loop); 79 loop->async_io_watcher.fd = -1; 80 loop->async_wfd = -1; 81 loop->signal_pipefd[0] = -1; 82 loop->signal_pipefd[1] = -1; 83 loop->backend_fd = -1; 84 loop->emfile_fd = -1; 85 86 loop->timer_counter = 0; 87 loop->stop_flag = 0; 88 89 err = uv__platform_loop_init(loop); 90 if (err) 91 goto fail_platform_init; 92 93 uv__signal_global_once_init(); 94 err = uv__process_init(loop); 95 if (err) 96 goto fail_signal_init; 97 uv__queue_init(&loop->process_handles); 98 99 err = uv_rwlock_init(&loop->cloexec_lock); 100 if (err) 101 goto fail_rwlock_init; 102 103 err = uv_mutex_init(&loop->wq_mutex); 104 if (err) 105 goto fail_mutex_init; 106 107 err = uv_async_init(loop, &loop->wq_async, uv__work_done); 108 if (err) 109 goto fail_async_init; 110 111 uv__handle_unref(&loop->wq_async); 112 loop->wq_async.flags |= UV_HANDLE_INTERNAL; 113 114 loop->magic = UV_LOOP_MAGIC; 115 return 0; 116 117fail_async_init: 118 uv_mutex_destroy(&loop->wq_mutex); 119 120fail_mutex_init: 121 uv_rwlock_destroy(&loop->cloexec_lock); 122 123fail_rwlock_init: 124 uv__signal_loop_cleanup(loop); 125 126fail_signal_init: 127 uv__platform_loop_delete(loop); 128 129fail_platform_init: 130 uv_mutex_destroy(&lfields->loop_metrics.lock); 131 132fail_metrics_mutex_init: 133 uv__free(lfields); 134 loop->internal_fields = NULL; 135 136 uv__free(loop->watchers); 137 loop->nwatchers = 0; 138 return err; 139} 140 141 142int uv_loop_fork(uv_loop_t* loop) { 143 int err; 144 unsigned int i; 145 uv__io_t* w; 146 147 err = uv__io_fork(loop); 148 if (err) 149 return err; 150 151 err = uv__async_fork(loop); 152 if (err) 153 return err; 154 155 err = uv__signal_loop_fork(loop); 156 if (err) 157 return err; 158 159 /* Rearm all the watchers that aren't re-queued by the above. */ 160 for (i = 0; i < loop->nwatchers; i++) { 161 w = loop->watchers[i]; 162 if (w == NULL) 163 continue; 164 165 if (w->pevents != 0 && uv__queue_empty(&w->watcher_queue)) { 166 w->events = 0; /* Force re-registration in uv__io_poll. */ 167 uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue); 168 } 169 } 170 171 return 0; 172} 173 174 175void uv__loop_close(uv_loop_t* loop) { 176 uv__loop_internal_fields_t* lfields; 177 178 uv__signal_loop_cleanup(loop); 179 uv__platform_loop_delete(loop); 180 uv__async_stop(loop); 181 182 if (loop->emfile_fd != -1) { 183 uv__close(loop->emfile_fd); 184 loop->emfile_fd = -1; 185 } 186 187 if (loop->backend_fd != -1) { 188#ifdef USE_OHOS_DFX 189 fdsan_close_with_tag(loop->backend_fd, uv__get_addr_tag((void *)&loop->backend_fd)); 190#else 191 uv__close(loop->backend_fd); 192#endif 193 UV_LOGI("close:%{public}zu, backend_fd:%{public}d", (size_t)loop, loop->backend_fd); 194 loop->backend_fd = -1; 195 } 196 197 uv_mutex_lock(&loop->wq_mutex); 198#ifndef USE_FFRT 199 assert(uv__queue_empty(&loop->wq) && "thread pool work queue not empty!"); 200#endif 201 assert(!uv__has_active_reqs(loop)); 202 uv_mutex_unlock(&loop->wq_mutex); 203 uv_mutex_destroy(&loop->wq_mutex); 204 205 /* 206 * Note that all thread pool stuff is finished at this point and 207 * it is safe to just destroy rw lock 208 */ 209 uv_rwlock_destroy(&loop->cloexec_lock); 210 211#if 0 212 assert(uv__queue_empty(&loop->pending_queue)); 213 assert(uv__queue_empty(&loop->watcher_queue)); 214 assert(loop->nfds == 0); 215#endif 216 217 uv__free(loop->watchers); 218 loop->watchers = NULL; 219 loop->nwatchers = 0; 220 221 lfields = uv__get_internal_fields(loop); 222 uv_mutex_destroy(&lfields->loop_metrics.lock); 223 uv__free(lfields); 224 loop->internal_fields = NULL; 225 loop->magic = ~UV_LOOP_MAGIC; 226} 227 228 229int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { 230 uv__loop_internal_fields_t* lfields; 231 232 lfields = uv__get_internal_fields(loop); 233 if (option == UV_METRICS_IDLE_TIME) { 234 lfields->flags |= UV_METRICS_IDLE_TIME; 235 return 0; 236 } 237 238 if (option != UV_LOOP_BLOCK_SIGNAL) 239 return UV_ENOSYS; 240 241 if (va_arg(ap, int) != SIGPROF) 242 return UV_EINVAL; 243 244 loop->flags |= UV_LOOP_BLOCK_SIGPROF; 245 return 0; 246} 247