1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 3e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to 4e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the 5e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 6e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 7e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions: 8e66f31c5Sopenharmony_ci * 9e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 10e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software. 11e66f31c5Sopenharmony_ci * 12e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 17e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 18e66f31c5Sopenharmony_ci * IN THE SOFTWARE. 19e66f31c5Sopenharmony_ci */ 20e66f31c5Sopenharmony_ci 21e66f31c5Sopenharmony_ci#include "uv.h" 22e66f31c5Sopenharmony_ci#include "uv-common.h" 23e66f31c5Sopenharmony_ci#include "heap-inl.h" 24e66f31c5Sopenharmony_ci 25e66f31c5Sopenharmony_ci#include <assert.h> 26e66f31c5Sopenharmony_ci#include <limits.h> 27e66f31c5Sopenharmony_ci 28e66f31c5Sopenharmony_ci#ifdef ASYNC_STACKTRACE 29e66f31c5Sopenharmony_ci#include "dfx/async_stack/libuv_async_stack.h" 30e66f31c5Sopenharmony_ci#endif 31e66f31c5Sopenharmony_ci 32e66f31c5Sopenharmony_cistatic struct heap *timer_heap(const uv_loop_t* loop) { 33e66f31c5Sopenharmony_ci#ifdef _WIN32 34e66f31c5Sopenharmony_ci return (struct heap*) loop->timer_heap; 35e66f31c5Sopenharmony_ci#else 36e66f31c5Sopenharmony_ci return (struct heap*) &loop->timer_heap; 37e66f31c5Sopenharmony_ci#endif 38e66f31c5Sopenharmony_ci} 39e66f31c5Sopenharmony_ci 40e66f31c5Sopenharmony_ci 41e66f31c5Sopenharmony_cistatic int timer_less_than(const struct heap_node* ha, 42e66f31c5Sopenharmony_ci const struct heap_node* hb) { 43e66f31c5Sopenharmony_ci const uv_timer_t* a; 44e66f31c5Sopenharmony_ci const uv_timer_t* b; 45e66f31c5Sopenharmony_ci 46e66f31c5Sopenharmony_ci a = container_of(ha, uv_timer_t, heap_node); 47e66f31c5Sopenharmony_ci b = container_of(hb, uv_timer_t, heap_node); 48e66f31c5Sopenharmony_ci 49e66f31c5Sopenharmony_ci if (a->timeout < b->timeout) 50e66f31c5Sopenharmony_ci return 1; 51e66f31c5Sopenharmony_ci if (b->timeout < a->timeout) 52e66f31c5Sopenharmony_ci return 0; 53e66f31c5Sopenharmony_ci 54e66f31c5Sopenharmony_ci /* Compare start_id when both have the same timeout. start_id is 55e66f31c5Sopenharmony_ci * allocated with loop->timer_counter in uv_timer_start(). 56e66f31c5Sopenharmony_ci */ 57e66f31c5Sopenharmony_ci return a->start_id < b->start_id; 58e66f31c5Sopenharmony_ci} 59e66f31c5Sopenharmony_ci 60e66f31c5Sopenharmony_ci 61e66f31c5Sopenharmony_ciint uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) { 62e66f31c5Sopenharmony_ci uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER); 63e66f31c5Sopenharmony_ci handle->timer_cb = NULL; 64e66f31c5Sopenharmony_ci handle->timeout = 0; 65e66f31c5Sopenharmony_ci handle->repeat = 0; 66e66f31c5Sopenharmony_ci return 0; 67e66f31c5Sopenharmony_ci} 68e66f31c5Sopenharmony_ci 69e66f31c5Sopenharmony_ci 70e66f31c5Sopenharmony_ciint uv_timer_start(uv_timer_t* handle, 71e66f31c5Sopenharmony_ci uv_timer_cb cb, 72e66f31c5Sopenharmony_ci uint64_t timeout, 73e66f31c5Sopenharmony_ci uint64_t repeat) { 74e66f31c5Sopenharmony_ci uint64_t clamped_timeout; 75e66f31c5Sopenharmony_ci 76e66f31c5Sopenharmony_ci if (uv__is_closing(handle) || cb == NULL) 77e66f31c5Sopenharmony_ci return UV_EINVAL; 78e66f31c5Sopenharmony_ci 79e66f31c5Sopenharmony_ci if (uv__is_active(handle)) 80e66f31c5Sopenharmony_ci uv_timer_stop(handle); 81e66f31c5Sopenharmony_ci 82e66f31c5Sopenharmony_ci clamped_timeout = handle->loop->time + timeout; 83e66f31c5Sopenharmony_ci if (clamped_timeout < timeout) 84e66f31c5Sopenharmony_ci clamped_timeout = (uint64_t) -1; 85e66f31c5Sopenharmony_ci 86e66f31c5Sopenharmony_ci handle->timer_cb = cb; 87e66f31c5Sopenharmony_ci handle->timeout = clamped_timeout; 88e66f31c5Sopenharmony_ci handle->repeat = repeat; 89e66f31c5Sopenharmony_ci /* start_id is the second index to be compared in timer_less_than() */ 90e66f31c5Sopenharmony_ci handle->start_id = handle->loop->timer_counter++; 91e66f31c5Sopenharmony_ci 92e66f31c5Sopenharmony_ci#ifdef ASYNC_STACKTRACE 93e66f31c5Sopenharmony_ci handle->u.reserved[3] = (void*)LibuvCollectAsyncStack(); 94e66f31c5Sopenharmony_ci#endif 95e66f31c5Sopenharmony_ci 96e66f31c5Sopenharmony_ci heap_insert(timer_heap(handle->loop), 97e66f31c5Sopenharmony_ci (struct heap_node*) &handle->heap_node, 98e66f31c5Sopenharmony_ci timer_less_than); 99e66f31c5Sopenharmony_ci uv__handle_start(handle); 100e66f31c5Sopenharmony_ci#ifdef __linux__ 101e66f31c5Sopenharmony_ci if (uv_check_data_valid((struct uv_loop_data*)handle->loop->data) == 0) { 102e66f31c5Sopenharmony_ci uv_async_send(&handle->loop->wq_async); 103e66f31c5Sopenharmony_ci } 104e66f31c5Sopenharmony_ci#endif 105e66f31c5Sopenharmony_ci return 0; 106e66f31c5Sopenharmony_ci} 107e66f31c5Sopenharmony_ci 108e66f31c5Sopenharmony_ci 109e66f31c5Sopenharmony_ciint uv_timer_stop(uv_timer_t* handle) { 110e66f31c5Sopenharmony_ci if (!uv__is_active(handle)) 111e66f31c5Sopenharmony_ci return 0; 112e66f31c5Sopenharmony_ci 113e66f31c5Sopenharmony_ci heap_remove(timer_heap(handle->loop), 114e66f31c5Sopenharmony_ci (struct heap_node*) &handle->heap_node, 115e66f31c5Sopenharmony_ci timer_less_than); 116e66f31c5Sopenharmony_ci uv__handle_stop(handle); 117e66f31c5Sopenharmony_ci 118e66f31c5Sopenharmony_ci return 0; 119e66f31c5Sopenharmony_ci} 120e66f31c5Sopenharmony_ci 121e66f31c5Sopenharmony_ci 122e66f31c5Sopenharmony_ciint uv_timer_again(uv_timer_t* handle) { 123e66f31c5Sopenharmony_ci if (handle->timer_cb == NULL) 124e66f31c5Sopenharmony_ci return UV_EINVAL; 125e66f31c5Sopenharmony_ci 126e66f31c5Sopenharmony_ci if (handle->repeat) { 127e66f31c5Sopenharmony_ci uv_timer_stop(handle); 128e66f31c5Sopenharmony_ci uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat); 129e66f31c5Sopenharmony_ci } 130e66f31c5Sopenharmony_ci 131e66f31c5Sopenharmony_ci return 0; 132e66f31c5Sopenharmony_ci} 133e66f31c5Sopenharmony_ci 134e66f31c5Sopenharmony_ci 135e66f31c5Sopenharmony_civoid uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) { 136e66f31c5Sopenharmony_ci handle->repeat = repeat; 137e66f31c5Sopenharmony_ci} 138e66f31c5Sopenharmony_ci 139e66f31c5Sopenharmony_ci 140e66f31c5Sopenharmony_ciuint64_t uv_timer_get_repeat(const uv_timer_t* handle) { 141e66f31c5Sopenharmony_ci return handle->repeat; 142e66f31c5Sopenharmony_ci} 143e66f31c5Sopenharmony_ci 144e66f31c5Sopenharmony_ci 145e66f31c5Sopenharmony_ciuint64_t uv_timer_get_due_in(const uv_timer_t* handle) { 146e66f31c5Sopenharmony_ci if (handle->loop->time >= handle->timeout) 147e66f31c5Sopenharmony_ci return 0; 148e66f31c5Sopenharmony_ci 149e66f31c5Sopenharmony_ci return handle->timeout - handle->loop->time; 150e66f31c5Sopenharmony_ci} 151e66f31c5Sopenharmony_ci 152e66f31c5Sopenharmony_ci 153e66f31c5Sopenharmony_ciint uv__next_timeout(const uv_loop_t* loop) { 154e66f31c5Sopenharmony_ci const struct heap_node* heap_node; 155e66f31c5Sopenharmony_ci const uv_timer_t* handle; 156e66f31c5Sopenharmony_ci uint64_t diff; 157e66f31c5Sopenharmony_ci 158e66f31c5Sopenharmony_ci heap_node = heap_min(timer_heap(loop)); 159e66f31c5Sopenharmony_ci if (heap_node == NULL) 160e66f31c5Sopenharmony_ci return -1; /* block indefinitely */ 161e66f31c5Sopenharmony_ci 162e66f31c5Sopenharmony_ci handle = container_of(heap_node, uv_timer_t, heap_node); 163e66f31c5Sopenharmony_ci if (handle->timeout <= loop->time) 164e66f31c5Sopenharmony_ci return 0; 165e66f31c5Sopenharmony_ci 166e66f31c5Sopenharmony_ci diff = handle->timeout - loop->time; 167e66f31c5Sopenharmony_ci if (diff > INT_MAX) 168e66f31c5Sopenharmony_ci diff = INT_MAX; 169e66f31c5Sopenharmony_ci 170e66f31c5Sopenharmony_ci return (int) diff; 171e66f31c5Sopenharmony_ci} 172e66f31c5Sopenharmony_ci 173e66f31c5Sopenharmony_ci 174e66f31c5Sopenharmony_civoid uv__run_timers(uv_loop_t* loop) { 175e66f31c5Sopenharmony_ci struct heap_node* heap_node; 176e66f31c5Sopenharmony_ci uv_timer_t* handle; 177e66f31c5Sopenharmony_ci 178e66f31c5Sopenharmony_ci for (;;) { 179e66f31c5Sopenharmony_ci heap_node = heap_min(timer_heap(loop)); 180e66f31c5Sopenharmony_ci if (heap_node == NULL) 181e66f31c5Sopenharmony_ci break; 182e66f31c5Sopenharmony_ci 183e66f31c5Sopenharmony_ci handle = container_of(heap_node, uv_timer_t, heap_node); 184e66f31c5Sopenharmony_ci if (handle->timeout > loop->time) 185e66f31c5Sopenharmony_ci break; 186e66f31c5Sopenharmony_ci 187e66f31c5Sopenharmony_ci uv_timer_stop(handle); 188e66f31c5Sopenharmony_ci uv_timer_again(handle); 189e66f31c5Sopenharmony_ci#ifdef ASYNC_STACKTRACE 190e66f31c5Sopenharmony_ci LibuvSetStackId((uint64_t)handle->u.reserved[3]); 191e66f31c5Sopenharmony_ci#endif 192e66f31c5Sopenharmony_ci handle->timer_cb(handle); 193e66f31c5Sopenharmony_ci } 194e66f31c5Sopenharmony_ci} 195e66f31c5Sopenharmony_ci 196e66f31c5Sopenharmony_ci 197e66f31c5Sopenharmony_civoid uv__timer_close(uv_timer_t* handle) { 198e66f31c5Sopenharmony_ci uv_timer_stop(handle); 199e66f31c5Sopenharmony_ci} 200