1*b819cea2SGordon Ross /* 2*b819cea2SGordon Ross * This file and its contents are supplied under the terms of the 3*b819cea2SGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0. 4*b819cea2SGordon Ross * You may only use this file in accordance with the terms of version 5*b819cea2SGordon Ross * 1.0 of the CDDL. 6*b819cea2SGordon Ross * 7*b819cea2SGordon Ross * A full copy of the text of the CDDL should have accompanied this 8*b819cea2SGordon Ross * source. A copy of the CDDL is also available via the Internet at 9*b819cea2SGordon Ross * http://www.illumos.org/license/CDDL. 10*b819cea2SGordon Ross */ 11*b819cea2SGordon Ross 12*b819cea2SGordon Ross /* 13*b819cea2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 14*b819cea2SGordon Ross */ 15*b819cea2SGordon Ross 16*b819cea2SGordon Ross /* 17*b819cea2SGordon Ross * rwlock(9f) 18*b819cea2SGordon Ross */ 19*b819cea2SGordon Ross 20*b819cea2SGordon Ross /* This is the API we're emulating */ 21*b819cea2SGordon Ross #include <sys/rwlock.h> 22*b819cea2SGordon Ross 23*b819cea2SGordon Ross #include <sys/errno.h> 24*b819cea2SGordon Ross #include <sys/debug.h> 25*b819cea2SGordon Ross #include <sys/param.h> 26*b819cea2SGordon Ross #include <sys/synch32.h> 27*b819cea2SGordon Ross #include <sys/thread.h> 28*b819cea2SGordon Ross 29*b819cea2SGordon Ross /* avoiding synch.h */ 30*b819cea2SGordon Ross int rwlock_init(lwp_rwlock_t *, int, void *); 31*b819cea2SGordon Ross int rwlock_destroy(lwp_rwlock_t *); 32*b819cea2SGordon Ross int rw_rdlock(lwp_rwlock_t *); 33*b819cea2SGordon Ross int rw_wrlock(lwp_rwlock_t *); 34*b819cea2SGordon Ross int rw_unlock(lwp_rwlock_t *); 35*b819cea2SGordon Ross int rw_tryrdlock(lwp_rwlock_t *); 36*b819cea2SGordon Ross int rw_trywrlock(lwp_rwlock_t *); 37*b819cea2SGordon Ross int _rw_read_held(void *); 38*b819cea2SGordon Ross int _rw_write_held(void *); 39*b819cea2SGordon Ross 40*b819cea2SGordon Ross /*ARGSUSED*/ 41*b819cea2SGordon Ross void 42*b819cea2SGordon Ross rw_init(krwlock_t *rwlp, char *name, krw_type_t type, void *arg) 43*b819cea2SGordon Ross { 44*b819cea2SGordon Ross (void) rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 45*b819cea2SGordon Ross rwlp->rw_owner = _KTHREAD_INVALID; 46*b819cea2SGordon Ross } 47*b819cea2SGordon Ross 48*b819cea2SGordon Ross void 49*b819cea2SGordon Ross rw_destroy(krwlock_t *rwlp) 50*b819cea2SGordon Ross { 51*b819cea2SGordon Ross (void) rwlock_destroy(&rwlp->rw_lock); 52*b819cea2SGordon Ross rwlp->rw_owner = _KTHREAD_INVALID; 53*b819cea2SGordon Ross } 54*b819cea2SGordon Ross 55*b819cea2SGordon Ross void 56*b819cea2SGordon Ross rw_enter(krwlock_t *rwlp, krw_t rw) 57*b819cea2SGordon Ross { 58*b819cea2SGordon Ross int rc; 59*b819cea2SGordon Ross 60*b819cea2SGordon Ross if (rw == RW_READER) { 61*b819cea2SGordon Ross rc = rw_rdlock(&rwlp->rw_lock); 62*b819cea2SGordon Ross } else { 63*b819cea2SGordon Ross rc = rw_wrlock(&rwlp->rw_lock); 64*b819cea2SGordon Ross rwlp->rw_owner = _curthread(); 65*b819cea2SGordon Ross } 66*b819cea2SGordon Ross VERIFY(rc == 0); 67*b819cea2SGordon Ross } 68*b819cea2SGordon Ross 69*b819cea2SGordon Ross void 70*b819cea2SGordon Ross rw_exit(krwlock_t *rwlp) 71*b819cea2SGordon Ross { 72*b819cea2SGordon Ross if (_rw_write_held(&rwlp->rw_lock)) { 73*b819cea2SGordon Ross ASSERT(rwlp->rw_owner == _curthread()); 74*b819cea2SGordon Ross rwlp->rw_owner = _KTHREAD_INVALID; 75*b819cea2SGordon Ross } 76*b819cea2SGordon Ross (void) rw_unlock(&rwlp->rw_lock); 77*b819cea2SGordon Ross } 78*b819cea2SGordon Ross 79*b819cea2SGordon Ross int 80*b819cea2SGordon Ross rw_tryenter(krwlock_t *rwlp, krw_t rw) 81*b819cea2SGordon Ross { 82*b819cea2SGordon Ross int rv; 83*b819cea2SGordon Ross 84*b819cea2SGordon Ross if (rw == RW_WRITER) { 85*b819cea2SGordon Ross rv = rw_trywrlock(&rwlp->rw_lock); 86*b819cea2SGordon Ross if (rv == 0) 87*b819cea2SGordon Ross rwlp->rw_owner = _curthread(); 88*b819cea2SGordon Ross } else 89*b819cea2SGordon Ross rv = rw_tryrdlock(&rwlp->rw_lock); 90*b819cea2SGordon Ross 91*b819cea2SGordon Ross return ((rv == 0) ? 1 : 0); 92*b819cea2SGordon Ross } 93*b819cea2SGordon Ross 94*b819cea2SGordon Ross /*ARGSUSED*/ 95*b819cea2SGordon Ross int 96*b819cea2SGordon Ross rw_tryupgrade(krwlock_t *rwlp) 97*b819cea2SGordon Ross { 98*b819cea2SGordon Ross 99*b819cea2SGordon Ross return (0); 100*b819cea2SGordon Ross } 101*b819cea2SGordon Ross 102*b819cea2SGordon Ross void 103*b819cea2SGordon Ross rw_downgrade(krwlock_t *rwlp) 104*b819cea2SGordon Ross { 105*b819cea2SGordon Ross ASSERT(rwlp->rw_owner == _curthread()); 106*b819cea2SGordon Ross rwlp->rw_owner = _KTHREAD_INVALID; 107*b819cea2SGordon Ross VERIFY(rw_unlock(&rwlp->rw_lock) == 0); 108*b819cea2SGordon Ross VERIFY(rw_rdlock(&rwlp->rw_lock) == 0); 109*b819cea2SGordon Ross } 110*b819cea2SGordon Ross 111*b819cea2SGordon Ross int 112*b819cea2SGordon Ross rw_read_held(krwlock_t *rwlp) 113*b819cea2SGordon Ross { 114*b819cea2SGordon Ross return (_rw_read_held(rwlp)); 115*b819cea2SGordon Ross } 116*b819cea2SGordon Ross 117*b819cea2SGordon Ross int 118*b819cea2SGordon Ross rw_write_held(krwlock_t *rwlp) 119*b819cea2SGordon Ross { 120*b819cea2SGordon Ross return (_rw_write_held(rwlp)); 121*b819cea2SGordon Ross } 122*b819cea2SGordon Ross 123*b819cea2SGordon Ross int 124*b819cea2SGordon Ross rw_lock_held(krwlock_t *rwlp) 125*b819cea2SGordon Ross { 126*b819cea2SGordon Ross return (rw_read_held(rwlp) || rw_write_held(rwlp)); 127*b819cea2SGordon Ross } 128*b819cea2SGordon Ross 129*b819cea2SGordon Ross /* 130*b819cea2SGordon Ross * Return the kthread_t * of the lock owner 131*b819cea2SGordon Ross */ 132*b819cea2SGordon Ross void * 133*b819cea2SGordon Ross rw_owner(krwlock_t *rwlp) 134*b819cea2SGordon Ross { 135*b819cea2SGordon Ross return (rwlp->rw_owner); 136*b819cea2SGordon Ross } 137