1 /* $NetBSD: timer.c,v 1.3 2025/01/26 16:25:43 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #include <isc/netmgr.h> 17 #include <isc/util.h> 18 #include <isc/uv.h> 19 20 #include "netmgr-int.h" 21 22 struct isc_nm_timer { 23 isc_refcount_t references; 24 uv_timer_t timer; 25 isc_nmhandle_t *handle; 26 isc_nm_timer_cb cb; 27 void *cbarg; 28 }; 29 30 void 31 isc_nm_timer_create(isc_nmhandle_t *handle, isc_nm_timer_cb cb, void *cbarg, 32 isc_nm_timer_t **timerp) { 33 isc__networker_t *worker = NULL; 34 isc_nmsocket_t *sock = NULL; 35 isc_nm_timer_t *timer = NULL; 36 int r; 37 38 REQUIRE(VALID_NMHANDLE(handle)); 39 REQUIRE(VALID_NMSOCK(handle->sock)); 40 41 sock = handle->sock; 42 worker = sock->worker; 43 44 /* TODO: per-loop object cache */ 45 timer = isc_mem_get(worker->mctx, sizeof(*timer)); 46 *timer = (isc_nm_timer_t){ .cb = cb, .cbarg = cbarg }; 47 isc_refcount_init(&timer->references, 1); 48 isc_nmhandle_attach(handle, &timer->handle); 49 50 r = uv_timer_init(&worker->loop->loop, &timer->timer); 51 UV_RUNTIME_CHECK(uv_timer_init, r); 52 uv_handle_set_data((uv_handle_t *)&timer->timer, timer); 53 54 *timerp = timer; 55 } 56 57 void 58 isc_nm_timer_attach(isc_nm_timer_t *timer, isc_nm_timer_t **timerp) { 59 REQUIRE(timer != NULL); 60 REQUIRE(timerp != NULL && *timerp == NULL); 61 62 isc_refcount_increment(&timer->references); 63 *timerp = timer; 64 } 65 66 static void 67 timer_destroy(uv_handle_t *uvhandle) { 68 isc_nm_timer_t *timer = uv_handle_get_data(uvhandle); 69 isc_nmhandle_t *handle = timer->handle; 70 isc_mem_t *mctx = timer->handle->sock->worker->mctx; 71 72 isc_mem_put(mctx, timer, sizeof(*timer)); 73 74 isc_nmhandle_detach(&handle); 75 } 76 77 void 78 isc_nm_timer_detach(isc_nm_timer_t **timerp) { 79 isc_nm_timer_t *timer = NULL; 80 isc_nmhandle_t *handle = NULL; 81 82 REQUIRE(timerp != NULL && *timerp != NULL); 83 84 timer = *timerp; 85 *timerp = NULL; 86 87 handle = timer->handle; 88 89 REQUIRE(VALID_NMHANDLE(handle)); 90 REQUIRE(VALID_NMSOCK(handle->sock)); 91 92 if (isc_refcount_decrement(&timer->references) == 1) { 93 int r = uv_timer_stop(&timer->timer); 94 UV_RUNTIME_CHECK(uv_timer_stop, r); 95 uv_close((uv_handle_t *)&timer->timer, timer_destroy); 96 } 97 } 98 99 static void 100 timer_cb(uv_timer_t *uvtimer) { 101 isc_nm_timer_t *timer = uv_handle_get_data((uv_handle_t *)uvtimer); 102 103 REQUIRE(timer->cb != NULL); 104 105 timer->cb(timer->cbarg, ISC_R_TIMEDOUT); 106 } 107 108 void 109 isc_nm_timer_start(isc_nm_timer_t *timer, uint64_t timeout) { 110 int r = uv_timer_start(&timer->timer, timer_cb, timeout, 0); 111 UV_RUNTIME_CHECK(uv_timer_start, r); 112 } 113 114 void 115 isc_nm_timer_stop(isc_nm_timer_t *timer) { 116 int r = uv_timer_stop(&timer->timer); 117 UV_RUNTIME_CHECK(uv_timer_stop, r); 118 } 119