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