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