1 /* Copyright libuv project 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 "task.h" 24 #include <string.h> /* memset */ 25 26 #define UV_NS_TO_MS 1000000 27 28 29 static void timer_spin_cb(uv_timer_t* handle) { 30 uint64_t t; 31 32 (*(int*) handle->data)++; 33 t = uv_hrtime(); 34 /* Spin for 500 ms to spin loop time out of the delta check. */ 35 while (uv_hrtime() - t < 600 * UV_NS_TO_MS) { } 36 } 37 38 39 TEST_IMPL(metrics_idle_time) { 40 const uint64_t timeout = 1000; 41 uv_timer_t timer; 42 uint64_t idle_time; 43 int cntr; 44 45 cntr = 0; 46 timer.data = &cntr; 47 48 ASSERT_EQ(0, uv_loop_configure(uv_default_loop(), UV_METRICS_IDLE_TIME)); 49 ASSERT_EQ(0, uv_timer_init(uv_default_loop(), &timer)); 50 ASSERT_EQ(0, uv_timer_start(&timer, timer_spin_cb, timeout, 0)); 51 52 ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 53 ASSERT_GT(cntr, 0); 54 55 idle_time = uv_metrics_idle_time(uv_default_loop()); 56 57 /* Permissive check that the idle time matches within the timeout ±500 ms. */ 58 ASSERT((idle_time <= (timeout + 500) * UV_NS_TO_MS) && 59 (idle_time >= (timeout - 500) * UV_NS_TO_MS)); 60 61 MAKE_VALGRIND_HAPPY(); 62 return 0; 63 } 64 65 66 static void metrics_routine_cb(void* arg) { 67 const uint64_t timeout = 1000; 68 uv_loop_t loop; 69 uv_timer_t timer; 70 uint64_t idle_time; 71 int cntr; 72 73 cntr = 0; 74 timer.data = &cntr; 75 76 ASSERT_EQ(0, uv_loop_init(&loop)); 77 ASSERT_EQ(0, uv_loop_configure(&loop, UV_METRICS_IDLE_TIME)); 78 ASSERT_EQ(0, uv_timer_init(&loop, &timer)); 79 ASSERT_EQ(0, uv_timer_start(&timer, timer_spin_cb, timeout, 0)); 80 81 ASSERT_EQ(0, uv_run(&loop, UV_RUN_DEFAULT)); 82 ASSERT_GT(cntr, 0); 83 84 idle_time = uv_metrics_idle_time(&loop); 85 86 /* Only checking that idle time is greater than the lower bound since there 87 * may have been thread contention, causing the event loop to be delayed in 88 * the idle phase longer than expected. 89 */ 90 ASSERT_GE(idle_time, (timeout - 500) * UV_NS_TO_MS); 91 92 close_loop(&loop); 93 ASSERT_EQ(0, uv_loop_close(&loop)); 94 } 95 96 97 TEST_IMPL(metrics_idle_time_thread) { 98 uv_thread_t threads[5]; 99 int i; 100 101 for (i = 0; i < 5; i++) { 102 ASSERT_EQ(0, uv_thread_create(&threads[i], metrics_routine_cb, NULL)); 103 } 104 105 for (i = 0; i < 5; i++) { 106 uv_thread_join(&threads[i]); 107 } 108 109 return 0; 110 } 111 112 113 static void timer_noop_cb(uv_timer_t* handle) { 114 (*(int*) handle->data)++; 115 } 116 117 118 TEST_IMPL(metrics_idle_time_zero) { 119 uv_timer_t timer; 120 int cntr; 121 122 cntr = 0; 123 timer.data = &cntr; 124 ASSERT_EQ(0, uv_loop_configure(uv_default_loop(), UV_METRICS_IDLE_TIME)); 125 ASSERT_EQ(0, uv_timer_init(uv_default_loop(), &timer)); 126 ASSERT_EQ(0, uv_timer_start(&timer, timer_noop_cb, 0, 0)); 127 128 ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 129 130 ASSERT_GT(cntr, 0); 131 ASSERT_EQ(0, uv_metrics_idle_time(uv_default_loop())); 132 133 MAKE_VALGRIND_HAPPY(); 134 return 0; 135 } 136