a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt/*
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt */
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt#include <config.h>
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt#include <isc/task.h>
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt#include <isc/util.h>
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt#include "lock.h"
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt/*
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * Lock BIND dispatcher and allow only single task to run.
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt *
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * @warning
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * All calls to isc_task_beginexclusive() have to operate on the same task
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * otherwise it would not be possible to distinguish recursive locking
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * from real conflict on the dispatcher lock.
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * For this reason this wrapper function always works with inst->task.
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * As a result, this function have to be be called only from inst->task.
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt *
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * Recursive locking is allowed. Auxiliary variable pointed to by "statep"
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * stores information if last run_exclusive_enter() operation really locked
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * something or if the lock was called recursively and was no-op.
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt *
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * The pair (inst, state) used for run_exclusive_enter() has to be
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * used for run_exclusive_exit().
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt *
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * @param[in] inst The instance with the only task which is allowed to run.
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * @param[in,out] statep Lock state: ISC_R_SUCCESS or ISC_R_LOCKBUSY
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt */
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Huntvoid
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Huntrun_exclusive_enter(sample_instance_t *inst, isc_result_t *statep) {
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt REQUIRE(statep != NULL);
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt REQUIRE(*statep == ISC_R_IGNORE);
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt *statep = isc_task_beginexclusive(inst->task);
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt RUNTIME_CHECK(*statep == ISC_R_SUCCESS || *statep == ISC_R_LOCKBUSY);
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt}
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt/*
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * Exit task-exclusive mode.
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt *
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * @param[in] inst The instance used for previous run_exclusive_enter() call.
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt * @param[in] state Lock state as returned by run_exclusive_enter().
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt */
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Huntvoid
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Huntrun_exclusive_exit(sample_instance_t *inst, isc_result_t state) {
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt if (state == ISC_R_SUCCESS)
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt isc_task_endexclusive(inst->task);
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt else
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt /* Unlocking recursive lock or the lock was never locked. */
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt INSIST(state == ISC_R_LOCKBUSY || state == ISC_R_IGNORE);
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt return;
a00f9e2f50675bd43cc6a9fe2669709162a2ccb4Evan Hunt}