10e552da7Schristos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
20e552da7Schristos *
30e552da7Schristos * Permission is hereby granted, free of charge, to any person obtaining a copy
40e552da7Schristos * of this software and associated documentation files (the "Software"), to
50e552da7Schristos * deal in the Software without restriction, including without limitation the
60e552da7Schristos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
70e552da7Schristos * sell copies of the Software, and to permit persons to whom the Software is
80e552da7Schristos * furnished to do so, subject to the following conditions:
90e552da7Schristos *
100e552da7Schristos * The above copyright notice and this permission notice shall be included in
110e552da7Schristos * all copies or substantial portions of the Software.
120e552da7Schristos *
130e552da7Schristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
140e552da7Schristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
150e552da7Schristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
160e552da7Schristos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
170e552da7Schristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
180e552da7Schristos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
190e552da7Schristos * IN THE SOFTWARE.
200e552da7Schristos */
210e552da7Schristos
220e552da7Schristos #include "uv.h"
230e552da7Schristos #include "uv/tree.h"
240e552da7Schristos #include "internal.h"
250e552da7Schristos #include "heap-inl.h"
260e552da7Schristos #include <stdlib.h>
270e552da7Schristos #include <string.h>
280e552da7Schristos #include <unistd.h>
290e552da7Schristos
uv_loop_init(uv_loop_t * loop)300e552da7Schristos int uv_loop_init(uv_loop_t* loop) {
31*5f2f4271Schristos uv__loop_internal_fields_t* lfields;
320e552da7Schristos void* saved_data;
330e552da7Schristos int err;
340e552da7Schristos
350e552da7Schristos
360e552da7Schristos saved_data = loop->data;
370e552da7Schristos memset(loop, 0, sizeof(*loop));
380e552da7Schristos loop->data = saved_data;
390e552da7Schristos
40*5f2f4271Schristos lfields = (uv__loop_internal_fields_t*) uv__calloc(1, sizeof(*lfields));
41*5f2f4271Schristos if (lfields == NULL)
42*5f2f4271Schristos return UV_ENOMEM;
43*5f2f4271Schristos loop->internal_fields = lfields;
44*5f2f4271Schristos
45*5f2f4271Schristos err = uv_mutex_init(&lfields->loop_metrics.lock);
46*5f2f4271Schristos if (err)
47*5f2f4271Schristos goto fail_metrics_mutex_init;
48*5f2f4271Schristos
490e552da7Schristos heap_init((struct heap*) &loop->timer_heap);
500e552da7Schristos QUEUE_INIT(&loop->wq);
510e552da7Schristos QUEUE_INIT(&loop->idle_handles);
520e552da7Schristos QUEUE_INIT(&loop->async_handles);
530e552da7Schristos QUEUE_INIT(&loop->check_handles);
540e552da7Schristos QUEUE_INIT(&loop->prepare_handles);
550e552da7Schristos QUEUE_INIT(&loop->handle_queue);
560e552da7Schristos
570e552da7Schristos loop->active_handles = 0;
580e552da7Schristos loop->active_reqs.count = 0;
590e552da7Schristos loop->nfds = 0;
600e552da7Schristos loop->watchers = NULL;
610e552da7Schristos loop->nwatchers = 0;
620e552da7Schristos QUEUE_INIT(&loop->pending_queue);
630e552da7Schristos QUEUE_INIT(&loop->watcher_queue);
640e552da7Schristos
650e552da7Schristos loop->closing_handles = NULL;
660e552da7Schristos uv__update_time(loop);
670e552da7Schristos loop->async_io_watcher.fd = -1;
680e552da7Schristos loop->async_wfd = -1;
690e552da7Schristos loop->signal_pipefd[0] = -1;
700e552da7Schristos loop->signal_pipefd[1] = -1;
710e552da7Schristos loop->backend_fd = -1;
720e552da7Schristos loop->emfile_fd = -1;
730e552da7Schristos
740e552da7Schristos loop->timer_counter = 0;
750e552da7Schristos loop->stop_flag = 0;
760e552da7Schristos
770e552da7Schristos err = uv__platform_loop_init(loop);
780e552da7Schristos if (err)
79*5f2f4271Schristos goto fail_platform_init;
800e552da7Schristos
810e552da7Schristos uv__signal_global_once_init();
820e552da7Schristos err = uv_signal_init(loop, &loop->child_watcher);
830e552da7Schristos if (err)
840e552da7Schristos goto fail_signal_init;
850e552da7Schristos
860e552da7Schristos uv__handle_unref(&loop->child_watcher);
870e552da7Schristos loop->child_watcher.flags |= UV_HANDLE_INTERNAL;
880e552da7Schristos QUEUE_INIT(&loop->process_handles);
890e552da7Schristos
900e552da7Schristos err = uv_rwlock_init(&loop->cloexec_lock);
910e552da7Schristos if (err)
920e552da7Schristos goto fail_rwlock_init;
930e552da7Schristos
940e552da7Schristos err = uv_mutex_init(&loop->wq_mutex);
950e552da7Schristos if (err)
960e552da7Schristos goto fail_mutex_init;
970e552da7Schristos
980e552da7Schristos err = uv_async_init(loop, &loop->wq_async, uv__work_done);
990e552da7Schristos if (err)
1000e552da7Schristos goto fail_async_init;
1010e552da7Schristos
1020e552da7Schristos uv__handle_unref(&loop->wq_async);
1030e552da7Schristos loop->wq_async.flags |= UV_HANDLE_INTERNAL;
1040e552da7Schristos
1050e552da7Schristos return 0;
1060e552da7Schristos
1070e552da7Schristos fail_async_init:
1080e552da7Schristos uv_mutex_destroy(&loop->wq_mutex);
1090e552da7Schristos
1100e552da7Schristos fail_mutex_init:
1110e552da7Schristos uv_rwlock_destroy(&loop->cloexec_lock);
1120e552da7Schristos
1130e552da7Schristos fail_rwlock_init:
1140e552da7Schristos uv__signal_loop_cleanup(loop);
1150e552da7Schristos
1160e552da7Schristos fail_signal_init:
1170e552da7Schristos uv__platform_loop_delete(loop);
1180e552da7Schristos
119*5f2f4271Schristos fail_platform_init:
120*5f2f4271Schristos uv_mutex_destroy(&lfields->loop_metrics.lock);
121*5f2f4271Schristos
122*5f2f4271Schristos fail_metrics_mutex_init:
123*5f2f4271Schristos uv__free(lfields);
124*5f2f4271Schristos loop->internal_fields = NULL;
125*5f2f4271Schristos
1260e552da7Schristos uv__free(loop->watchers);
1270e552da7Schristos loop->nwatchers = 0;
1280e552da7Schristos return err;
1290e552da7Schristos }
1300e552da7Schristos
1310e552da7Schristos
uv_loop_fork(uv_loop_t * loop)1320e552da7Schristos int uv_loop_fork(uv_loop_t* loop) {
1330e552da7Schristos int err;
1340e552da7Schristos unsigned int i;
1350e552da7Schristos uv__io_t* w;
1360e552da7Schristos
1370e552da7Schristos err = uv__io_fork(loop);
1380e552da7Schristos if (err)
1390e552da7Schristos return err;
1400e552da7Schristos
1410e552da7Schristos err = uv__async_fork(loop);
1420e552da7Schristos if (err)
1430e552da7Schristos return err;
1440e552da7Schristos
1450e552da7Schristos err = uv__signal_loop_fork(loop);
1460e552da7Schristos if (err)
1470e552da7Schristos return err;
1480e552da7Schristos
1490e552da7Schristos /* Rearm all the watchers that aren't re-queued by the above. */
1500e552da7Schristos for (i = 0; i < loop->nwatchers; i++) {
1510e552da7Schristos w = loop->watchers[i];
1520e552da7Schristos if (w == NULL)
1530e552da7Schristos continue;
1540e552da7Schristos
1550e552da7Schristos if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) {
1560e552da7Schristos w->events = 0; /* Force re-registration in uv__io_poll. */
1570e552da7Schristos QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
1580e552da7Schristos }
1590e552da7Schristos }
1600e552da7Schristos
1610e552da7Schristos return 0;
1620e552da7Schristos }
1630e552da7Schristos
1640e552da7Schristos
uv__loop_close(uv_loop_t * loop)1650e552da7Schristos void uv__loop_close(uv_loop_t* loop) {
166*5f2f4271Schristos uv__loop_internal_fields_t* lfields;
167*5f2f4271Schristos
1680e552da7Schristos uv__signal_loop_cleanup(loop);
1690e552da7Schristos uv__platform_loop_delete(loop);
1700e552da7Schristos uv__async_stop(loop);
1710e552da7Schristos
1720e552da7Schristos if (loop->emfile_fd != -1) {
1730e552da7Schristos uv__close(loop->emfile_fd);
1740e552da7Schristos loop->emfile_fd = -1;
1750e552da7Schristos }
1760e552da7Schristos
1770e552da7Schristos if (loop->backend_fd != -1) {
1780e552da7Schristos uv__close(loop->backend_fd);
1790e552da7Schristos loop->backend_fd = -1;
1800e552da7Schristos }
1810e552da7Schristos
1820e552da7Schristos uv_mutex_lock(&loop->wq_mutex);
1830e552da7Schristos assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!");
1840e552da7Schristos assert(!uv__has_active_reqs(loop));
1850e552da7Schristos uv_mutex_unlock(&loop->wq_mutex);
1860e552da7Schristos uv_mutex_destroy(&loop->wq_mutex);
1870e552da7Schristos
1880e552da7Schristos /*
1890e552da7Schristos * Note that all thread pool stuff is finished at this point and
1900e552da7Schristos * it is safe to just destroy rw lock
1910e552da7Schristos */
1920e552da7Schristos uv_rwlock_destroy(&loop->cloexec_lock);
1930e552da7Schristos
1940e552da7Schristos #if 0
1950e552da7Schristos assert(QUEUE_EMPTY(&loop->pending_queue));
1960e552da7Schristos assert(QUEUE_EMPTY(&loop->watcher_queue));
1970e552da7Schristos assert(loop->nfds == 0);
1980e552da7Schristos #endif
1990e552da7Schristos
2000e552da7Schristos uv__free(loop->watchers);
2010e552da7Schristos loop->watchers = NULL;
2020e552da7Schristos loop->nwatchers = 0;
203*5f2f4271Schristos
204*5f2f4271Schristos lfields = uv__get_internal_fields(loop);
205*5f2f4271Schristos uv_mutex_destroy(&lfields->loop_metrics.lock);
206*5f2f4271Schristos uv__free(lfields);
207*5f2f4271Schristos loop->internal_fields = NULL;
2080e552da7Schristos }
2090e552da7Schristos
2100e552da7Schristos
uv__loop_configure(uv_loop_t * loop,uv_loop_option option,va_list ap)2110e552da7Schristos int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
212*5f2f4271Schristos uv__loop_internal_fields_t* lfields;
213*5f2f4271Schristos
214*5f2f4271Schristos lfields = uv__get_internal_fields(loop);
215*5f2f4271Schristos if (option == UV_METRICS_IDLE_TIME) {
216*5f2f4271Schristos lfields->flags |= UV_METRICS_IDLE_TIME;
217*5f2f4271Schristos return 0;
218*5f2f4271Schristos }
219*5f2f4271Schristos
2200e552da7Schristos if (option != UV_LOOP_BLOCK_SIGNAL)
2210e552da7Schristos return UV_ENOSYS;
2220e552da7Schristos
2230e552da7Schristos if (va_arg(ap, int) != SIGPROF)
2240e552da7Schristos return UV_EINVAL;
2250e552da7Schristos
2260e552da7Schristos loop->flags |= UV_LOOP_BLOCK_SIGPROF;
2270e552da7Schristos return 0;
2280e552da7Schristos }
229