xref: /netbsd-src/external/mit/libuv/dist/src/unix/loop.c (revision 5f2f42719cd62ff11fd913b40b7ce19f07c4fd25)
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