b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * This file and its contents are supplied under the terms of the
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * You may only use this file in accordance with the terms of version
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * 1.0 of the CDDL.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * A full copy of the text of the CDDL should have accompanied this
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * source. A copy of the CDDL is also available via the Internet at
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * http://www.illumos.org/license/CDDL.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * rwlock(9f)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/* This is the API we're emulating */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/rwlock.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/errno.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/debug.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/param.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/synch32.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/thread.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/* avoiding synch.h */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint rwlock_init(lwp_rwlock_t *, int, void *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint rwlock_destroy(lwp_rwlock_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint rw_rdlock(lwp_rwlock_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint rw_wrlock(lwp_rwlock_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint rw_unlock(lwp_rwlock_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint rw_tryrdlock(lwp_rwlock_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint rw_trywrlock(lwp_rwlock_t *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint _rw_read_held(void *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint _rw_write_held(void *);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*ARGSUSED*/
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_init(krwlock_t *rwlp, char *name, krw_type_t type, void *arg)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rwlp->rw_owner = _KTHREAD_INVALID;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_destroy(krwlock_t *rwlp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) rwlock_destroy(&rwlp->rw_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rwlp->rw_owner = _KTHREAD_INVALID;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_enter(krwlock_t *rwlp, krw_t rw)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int rc;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (rw == RW_READER) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rc = rw_rdlock(&rwlp->rw_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross } else {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rc = rw_wrlock(&rwlp->rw_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rwlp->rw_owner = _curthread();
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross VERIFY(rc == 0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_exit(krwlock_t *rwlp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (_rw_write_held(&rwlp->rw_lock)) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross ASSERT(rwlp->rw_owner == _curthread());
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rwlp->rw_owner = _KTHREAD_INVALID;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) rw_unlock(&rwlp->rw_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_tryenter(krwlock_t *rwlp, krw_t rw)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int rv;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (rw == RW_WRITER) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rv = rw_trywrlock(&rwlp->rw_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (rv == 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rwlp->rw_owner = _curthread();
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross } else
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rv = rw_tryrdlock(&rwlp->rw_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return ((rv == 0) ? 1 : 0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*ARGSUSED*/
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_tryupgrade(krwlock_t *rwlp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_downgrade(krwlock_t *rwlp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross ASSERT(rwlp->rw_owner == _curthread());
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rwlp->rw_owner = _KTHREAD_INVALID;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_read_held(krwlock_t *rwlp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (_rw_read_held(rwlp));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_write_held(krwlock_t *rwlp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (_rw_write_held(rwlp));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_lock_held(krwlock_t *rwlp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (rw_read_held(rwlp) || rw_write_held(rwlp));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Return the kthread_t * of the lock owner
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossrw_owner(krwlock_t *rwlp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (rwlp->rw_owner);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}