From 8b2ae8cc84d6dafdf3d4d5bf4b05b430e28acaa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Wed, 2 Feb 2022 10:50:27 +0100 Subject: [PATCH] Add network manager based timer API This commits adds API that allows to create arbitrary timers associated with the network manager handles. (cherry picked from commit 3c7b04d0150ae6d6192747d90d52247bd598bd9a) --- lib/isc/Makefile.am | 1 + lib/isc/include/isc/netmgr.h | 24 +++++++ lib/isc/netmgr/timer.c | 118 +++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 lib/isc/netmgr/timer.c diff --git a/lib/isc/Makefile.am b/lib/isc/Makefile.am index c6f800d5c6..3d37127fe9 100644 --- a/lib/isc/Makefile.am +++ b/lib/isc/Makefile.am @@ -109,6 +109,7 @@ libisc_la_SOURCES = \ netmgr/netmgr.c \ netmgr/tcp.c \ netmgr/tcpdns.c \ + netmgr/timer.c \ netmgr/tlsdns.c \ netmgr/udp.c \ netmgr/uv-compat.c \ diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index 671880137d..16eedb708f 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -700,3 +700,27 @@ isc__nm_force_tid(int tid); void isc_nmhandle_setwritetimeout(isc_nmhandle_t *handle, uint64_t write_timeout); + +/* + * Timer related functions + */ + +typedef struct isc_nm_timer isc_nm_timer_t; + +typedef void (*isc_nm_timer_cb)(void *, isc_result_t); + +void +isc_nm_timer_create(isc_nmhandle_t *, isc_nm_timer_cb, void *, + isc_nm_timer_t **); + +void +isc_nm_timer_attach(isc_nm_timer_t *, isc_nm_timer_t **); + +void +isc_nm_timer_detach(isc_nm_timer_t **); + +void +isc_nm_timer_start(isc_nm_timer_t *, uint64_t); + +void +isc_nm_timer_stop(isc_nm_timer_t *); diff --git a/lib/isc/netmgr/timer.c b/lib/isc/netmgr/timer.c new file mode 100644 index 0000000000..3016387b0f --- /dev/null +++ b/lib/isc/netmgr/timer.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include + +#include +#include + +#include "netmgr-int.h" + +struct isc_nm_timer { + isc_refcount_t references; + uv_timer_t timer; + isc_nmhandle_t *handle; + isc_nm_timer_cb cb; + void *cbarg; +}; + +void +isc_nm_timer_create(isc_nmhandle_t *handle, isc_nm_timer_cb cb, void *cbarg, + isc_nm_timer_t **timerp) { + isc__networker_t *worker = NULL; + isc_nmsocket_t *sock = NULL; + isc_nm_timer_t *timer = NULL; + int r; + + REQUIRE(isc__nm_in_netthread()); + REQUIRE(VALID_NMHANDLE(handle)); + REQUIRE(VALID_NMSOCK(handle->sock)); + + sock = handle->sock; + worker = &sock->mgr->workers[isc_nm_tid()]; + + timer = isc_mem_get(sock->mgr->mctx, sizeof(*timer)); + *timer = (isc_nm_timer_t){ .cb = cb, .cbarg = cbarg }; + isc_refcount_init(&timer->references, 1); + isc_nmhandle_attach(handle, &timer->handle); + + r = uv_timer_init(&worker->loop, &timer->timer); + UV_RUNTIME_CHECK(uv_timer_init, r); + + uv_handle_set_data((uv_handle_t *)&timer->timer, timer); + + *timerp = timer; +} + +void +isc_nm_timer_attach(isc_nm_timer_t *timer, isc_nm_timer_t **timerp) { + REQUIRE(timer != NULL); + REQUIRE(timerp != NULL && *timerp == NULL); + + isc_refcount_increment(&timer->references); + *timerp = timer; +} + +static void +timer_destroy(uv_handle_t *uvhandle) { + isc_nm_timer_t *timer = uv_handle_get_data(uvhandle); + isc_nmhandle_t *handle = timer->handle; + isc_mem_t *mctx = timer->handle->sock->mgr->mctx; + + isc_mem_put(mctx, timer, sizeof(*timer)); + + isc_nmhandle_detach(&handle); +} + +void +isc_nm_timer_detach(isc_nm_timer_t **timerp) { + isc_nm_timer_t *timer = NULL; + isc_nmhandle_t *handle = NULL; + + REQUIRE(timerp != NULL && *timerp != NULL); + + timer = *timerp; + *timerp = NULL; + + handle = timer->handle; + + REQUIRE(isc__nm_in_netthread()); + REQUIRE(VALID_NMHANDLE(handle)); + REQUIRE(VALID_NMSOCK(handle->sock)); + + if (isc_refcount_decrement(&timer->references) == 1) { + uv_timer_stop(&timer->timer); + uv_close((uv_handle_t *)&timer->timer, timer_destroy); + } +} + +static void +timer_cb(uv_timer_t *uvtimer) { + isc_nm_timer_t *timer = uv_handle_get_data((uv_handle_t *)uvtimer); + + REQUIRE(timer->cb != NULL); + + timer->cb(timer->cbarg, ISC_R_TIMEDOUT); +} + +void +isc_nm_timer_start(isc_nm_timer_t *timer, uint64_t timeout) { + int r = uv_timer_start(&timer->timer, timer_cb, timeout, 0); + UV_RUNTIME_CHECK(uv_timer_start, r); +} + +void +isc_nm_timer_stop(isc_nm_timer_t *timer) { + int r = uv_timer_stop(&timer->timer); + UV_RUNTIME_CHECK(uv_timer_stop, r); +}