1/* $NetBSD: lock.c,v 1.4 2022/09/23 12:15:25 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 AND ISC 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/* 17 * Copyright (C) Red Hat 18 * 19 * Permission to use, copy, modify, and/or distribute this software for any 20 * purpose with or without fee is hereby granted, provided that the above 21 * copyright notice and this permission notice appear in all copies. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH 24 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 25 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 26 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 27 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 28 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 29 * PERFORMANCE OF THIS SOFTWARE. 30 */ 31 32#include "lock.h" 33 34#include <isc/task.h> 35#include <isc/util.h> 36 37/* 38 * Lock BIND dispatcher and allow only single task to run. 39 * 40 * @warning 41 * All calls to isc_task_beginexclusive() have to operate on the same task 42 * otherwise it would not be possible to distinguish recursive locking 43 * from real conflict on the dispatcher lock. 44 * For this reason this wrapper function always works with inst->task. 45 * As a result, this function have to be be called only from inst->task. 46 * 47 * Recursive locking is allowed. Auxiliary variable pointed to by "statep" 48 * stores information if last run_exclusive_enter() operation really locked 49 * something or if the lock was called recursively and was no-op. 50 * 51 * The pair (inst, state) used for run_exclusive_enter() has to be 52 * used for run_exclusive_exit(). 53 * 54 * @param[in] inst The instance with the only task which is allowed to 55 * run. 56 * @param[in,out] statep Lock state: ISC_R_SUCCESS or ISC_R_LOCKBUSY 57 */ 58void 59run_exclusive_enter(sample_instance_t *inst, isc_result_t *statep) { 60 REQUIRE(statep != NULL); 61 REQUIRE(*statep == ISC_R_IGNORE); 62 63 *statep = isc_task_beginexclusive(inst->task); 64 RUNTIME_CHECK(*statep == ISC_R_SUCCESS || *statep == ISC_R_LOCKBUSY); 65} 66 67/* 68 * Exit task-exclusive mode. 69 * 70 * @param[in] inst The instance used for previous run_exclusive_enter() call. 71 * @param[in] state Lock state as returned by run_exclusive_enter(). 72 */ 73void 74run_exclusive_exit(sample_instance_t *inst, isc_result_t state) { 75 if (state == ISC_R_SUCCESS) { 76 isc_task_endexclusive(inst->task); 77 } else { 78 /* Unlocking recursive lock or the lock was never locked. */ 79 INSIST(state == ISC_R_LOCKBUSY || state == ISC_R_IGNORE); 80 } 81 82 return; 83} 84