xref: /netbsd-src/external/mpl/bind/dist/lib/isc/netmgr/timer.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
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