rwlock.c revision 499b34cea04a46823d003d4c0520c8b03e8513cb
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews/*
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * Copyright (C) 1998-2001 Internet Software Consortium.
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews *
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * Permission to use, copy, modify, and distribute this software for any
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * purpose with or without fee is hereby granted, provided that the above
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * copyright notice and this permission notice appear in all copies.
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews *
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews */
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews/* $Id: rwlock.c,v 1.27 2001/01/09 21:56:26 bwelling Exp $ */
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#include <config.h>
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#include <stddef.h>
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#include <isc/magic.h>
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#include <isc/msgs.h>
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#include <isc/platform.h>
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#include <isc/rwlock.h>
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#include <isc/util.h>
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#define RWLOCK_MAGIC 0x52574C6BU /* RWLk. */
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#define VALID_RWLOCK(rwl) ISC_MAGIC_VALID(rwl, RWLOCK_MAGIC)
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#ifdef ISC_PLATFORM_USETHREADS
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#ifndef RWLOCK_DEFAULT_READ_QUOTA
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#define RWLOCK_DEFAULT_READ_QUOTA 4
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#endif
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#ifndef RWLOCK_DEFAULT_WRITE_QUOTA
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#define RWLOCK_DEFAULT_WRITE_QUOTA 4
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#endif
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#ifdef ISC_RWLOCK_TRACE
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#include <stdio.h> /* Required for fprintf/stderr. */
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#include <isc/thread.h> /* Requried for isc_thread_self(). */
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsstatic void
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsprint_lock(const char *operation, isc_rwlock_t *rwl, isc_rwlocktype_t type) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews fprintf(stderr,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_PRINTLOCK,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews "rwlock %p thread %lu %s(%s): %s, %u active, "
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews "%u granted, %u rwaiting, %u wwaiting\n"),
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl, isc_thread_self(), operation,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews (type == isc_rwlocktype_read ?
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_READ, "read") :
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_WRITE, "write")),
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews (rwl->type == isc_rwlocktype_read ?
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_READING, "reading") :
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_WRITING, "writing")),
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->active, rwl->granted, rwl->readers_waiting,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->writers_waiting);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews}
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#endif
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsisc_result_t
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsisc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews unsigned int write_quota)
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews{
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_result_t result;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews REQUIRE(rwl != NULL);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews /*
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * In case there's trouble initializing, we zero magic now. If all
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews * goes well, we'll set it to RWLOCK_MAGIC.
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews */
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->magic = 0;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->type = isc_rwlocktype_read;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->active = 0;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->granted = 0;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->readers_waiting = 0;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->writers_waiting = 0;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (read_quota == 0)
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews read_quota = RWLOCK_DEFAULT_READ_QUOTA;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->read_quota = read_quota;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (write_quota == 0)
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews write_quota = RWLOCK_DEFAULT_WRITE_QUOTA;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->write_quota = write_quota;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews result = isc_mutex_init(&rwl->lock);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (result != ISC_R_SUCCESS) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews "isc_mutex_init() %s: %s",
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_FAILED, "failed"),
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_result_totext(result));
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews return (ISC_R_UNEXPECTED);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews result = isc_condition_init(&rwl->readable);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (result != ISC_R_SUCCESS) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews "isc_condition_init(readable) %s: %s",
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_FAILED, "failed"),
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_result_totext(result));
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews return (ISC_R_UNEXPECTED);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews result = isc_condition_init(&rwl->writeable);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (result != ISC_R_SUCCESS) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews UNEXPECTED_ERROR(__FILE__, __LINE__,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews "isc_condition_init(writeable) %s: %s",
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_FAILED, "failed"),
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_result_totext(result));
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews return (ISC_R_UNEXPECTED);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->magic = RWLOCK_MAGIC;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews return (ISC_R_SUCCESS);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews}
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsisc_result_t
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsisc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_boolean_t skip = ISC_FALSE;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews isc_boolean_t done = ISC_FALSE;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews REQUIRE(VALID_RWLOCK(rwl));
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews LOCK(&rwl->lock);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#ifdef ISC_RWLOCK_TRACE
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_PRELOCK, "prelock"), rwl, type);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#endif
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (type == isc_rwlocktype_read) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (rwl->readers_waiting != 0)
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews skip = ISC_TRUE;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews while (!done) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (!skip &&
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ((rwl->active == 0 ||
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews (rwl->type == isc_rwlocktype_read &&
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews (rwl->writers_waiting == 0 ||
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->granted < rwl->read_quota)))))
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->type = isc_rwlocktype_read;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->active++;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->granted++;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews done = ISC_TRUE;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews } else {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews skip = ISC_FALSE;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->readers_waiting++;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews WAIT(&rwl->readable, &rwl->lock);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->readers_waiting--;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews } else {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (rwl->writers_waiting != 0)
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews skip = ISC_TRUE;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews while (!done) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (!skip && rwl->active == 0) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->type = isc_rwlocktype_write;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->active = 1;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->granted++;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews done = ISC_TRUE;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews } else {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews skip = ISC_FALSE;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->writers_waiting++;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews WAIT(&rwl->writeable, &rwl->lock);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->writers_waiting--;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#ifdef ISC_RWLOCK_TRACE
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_POSTLOCK, "postlock"), rwl, type);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#endif
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews UNLOCK(&rwl->lock);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews return (ISC_R_SUCCESS);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews}
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsisc_result_t
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsisc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews REQUIRE(VALID_RWLOCK(rwl));
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews LOCK(&rwl->lock);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews REQUIRE(rwl->type == type);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews UNUSED(type);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#ifdef ISC_RWLOCK_TRACE
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#endif
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews INSIST(rwl->active > 0);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->active--;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (rwl->active == 0) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (rwl->type == isc_rwlocktype_read) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->granted = 0;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (rwl->writers_waiting > 0) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->type = isc_rwlocktype_write;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews SIGNAL(&rwl->writeable);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews } else if (rwl->readers_waiting > 0) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews /* Does this case ever happen? */
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews BROADCAST(&rwl->readable);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews } else {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (rwl->readers_waiting > 0) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews if (rwl->writers_waiting > 0 &&
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->granted < rwl->write_quota) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews SIGNAL(&rwl->writeable);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews } else {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->granted = 0;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->type = isc_rwlocktype_read;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews BROADCAST(&rwl->readable);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews } else if (rwl->writers_waiting > 0) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->granted = 0;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews SIGNAL(&rwl->writeable);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews } else {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->granted = 0;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews }
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#ifdef ISC_RWLOCK_TRACE
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews ISC_MSG_POSTUNLOCK, "postunlock"),
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl, type);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#endif
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews UNLOCK(&rwl->lock);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews return (ISC_R_SUCCESS);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews}
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsvoid
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsisc_rwlock_destroy(isc_rwlock_t *rwl) {
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews REQUIRE(VALID_RWLOCK(rwl));
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews LOCK(&rwl->lock);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews REQUIRE(rwl->active == 0 &&
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->readers_waiting == 0 &&
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->writers_waiting == 0);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews UNLOCK(&rwl->lock);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews rwl->magic = 0;
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews (void)isc_condition_destroy(&rwl->readable);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews (void)isc_condition_destroy(&rwl->writeable);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews DESTROYLOCK(&rwl->lock);
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews}
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews#else /* ISC_PLATFORM_USETHREADS */
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsisc_result_t
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrewsisc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews unsigned int write_quota)
5c526acb82c882e41b655c31f5fa4425c87b671cMark Andrews{
REQUIRE(rwl != NULL);
UNUSED(read_quota);
UNUSED(write_quota);
rwl->type = isc_rwlocktype_read;
rwl->active = 0;
rwl->magic = RWLOCK_MAGIC;
return (ISC_R_SUCCESS);
}
isc_result_t
isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
REQUIRE(VALID_RWLOCK(rwl));
if (type == isc_rwlocktype_read) {
if (rwl->type != isc_rwlocktype_read && rwl->active != 0)
return (ISC_R_LOCKBUSY);
rwl->type = isc_rwlocktype_read;
rwl->active++;
} else {
if (rwl->active != 0)
return (ISC_R_LOCKBUSY);
rwl->type = isc_rwlocktype_write;
rwl->active = 1;
}
return (ISC_R_SUCCESS);
}
isc_result_t
isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
REQUIRE(VALID_RWLOCK(rwl));
REQUIRE(rwl->type == type);
INSIST(rwl->active > 0);
rwl->active--;
return (ISC_R_SUCCESS);
}
void
isc_rwlock_destroy(isc_rwlock_t *rwl) {
REQUIRE(rwl != NULL);
REQUIRE(rwl->active == 0);
rwl->magic = 0;
}
#endif /* ISC_PLATFORM_USETHREADS */