/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* * rwlock(9f) */ /* This is the API we're emulating */ #include #include #include #include #include /* avoiding synch.h */ int rwlock_init(lwp_rwlock_t *, int, void *); int rwlock_destroy(lwp_rwlock_t *); int rw_rdlock(lwp_rwlock_t *); int rw_wrlock(lwp_rwlock_t *); int rw_unlock(lwp_rwlock_t *); int rw_tryrdlock(lwp_rwlock_t *); int rw_trywrlock(lwp_rwlock_t *); int _rw_read_held(void *); int _rw_write_held(void *); /*ARGSUSED*/ void rw_init(krwlock_t *rwlp, char *name, krw_type_t type, void *arg) { (void) rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); rwlp->rw_owner = _KTHREAD_INVALID; } void rw_destroy(krwlock_t *rwlp) { (void) rwlock_destroy(&rwlp->rw_lock); rwlp->rw_owner = _KTHREAD_INVALID; } void rw_enter(krwlock_t *rwlp, krw_t rw) { int rc; if (rw == RW_READER) { rc = rw_rdlock(&rwlp->rw_lock); } else { rc = rw_wrlock(&rwlp->rw_lock); rwlp->rw_owner = _curthread(); } VERIFY(rc == 0); } void rw_exit(krwlock_t *rwlp) { if (_rw_write_held(&rwlp->rw_lock)) { ASSERT(rwlp->rw_owner == _curthread()); rwlp->rw_owner = _KTHREAD_INVALID; } else { ASSERT(_rw_read_held(&rwlp->rw_lock)); } (void) rw_unlock(&rwlp->rw_lock); } int rw_tryenter(krwlock_t *rwlp, krw_t rw) { int rv; if (rw == RW_WRITER) { rv = rw_trywrlock(&rwlp->rw_lock); if (rv == 0) rwlp->rw_owner = _curthread(); } else rv = rw_tryrdlock(&rwlp->rw_lock); return ((rv == 0) ? 1 : 0); } /*ARGSUSED*/ int rw_tryupgrade(krwlock_t *rwlp) { return (0); } void rw_downgrade(krwlock_t *rwlp) { ASSERT(rwlp->rw_owner == _curthread()); rwlp->rw_owner = _KTHREAD_INVALID; VERIFY(rw_unlock(&rwlp->rw_lock) == 0); VERIFY(rw_rdlock(&rwlp->rw_lock) == 0); } int rw_read_held(krwlock_t *rwlp) { return (_rw_read_held(rwlp)); } int rw_write_held(krwlock_t *rwlp) { return (_rw_write_held(rwlp)); } int rw_lock_held(krwlock_t *rwlp) { return (rw_read_held(rwlp) || rw_write_held(rwlp)); } /* * Return the kthread_t * of the lock owner */ void * rw_owner(krwlock_t *rwlp) { return (rwlp->rw_owner); }