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 2017 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/thread.h> 27 28 /* avoiding synch.h */ 29 int rwlock_init(lwp_rwlock_t *, int, void *); 30 int rwlock_destroy(lwp_rwlock_t *); 31 int rw_rdlock(lwp_rwlock_t *); 32 int rw_wrlock(lwp_rwlock_t *); 33 int rw_unlock(lwp_rwlock_t *); 34 int rw_tryrdlock(lwp_rwlock_t *); 35 int rw_trywrlock(lwp_rwlock_t *); 36 int _rw_read_held(void *); 37 int _rw_write_held(void *); 38 39 /*ARGSUSED*/ 40 void 41 rw_init(krwlock_t *rwlp, char *name, krw_type_t type, void *arg) 42 { 43 (void) rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL); 44 rwlp->rw_owner = _KTHREAD_INVALID; 45 } 46 47 void 48 rw_destroy(krwlock_t *rwlp) 49 { 50 (void) rwlock_destroy(&rwlp->rw_lock); 51 rwlp->rw_owner = _KTHREAD_INVALID; 52 } 53 54 void 55 rw_enter(krwlock_t *rwlp, krw_t rw) 56 { 57 int rc; 58 59 if (rw == RW_READER) { 60 rc = rw_rdlock(&rwlp->rw_lock); 61 } else { 62 rc = rw_wrlock(&rwlp->rw_lock); 63 rwlp->rw_owner = _curthread(); 64 } 65 VERIFY(rc == 0); 66 } 67 68 void 69 rw_exit(krwlock_t *rwlp) 70 { 71 if (_rw_write_held(&rwlp->rw_lock)) { 72 ASSERT(rwlp->rw_owner == _curthread()); 73 rwlp->rw_owner = _KTHREAD_INVALID; 74 } else { 75 ASSERT(_rw_read_held(&rwlp->rw_lock)); 76 } 77 (void) rw_unlock(&rwlp->rw_lock); 78 } 79 80 int 81 rw_tryenter(krwlock_t *rwlp, krw_t rw) 82 { 83 int rv; 84 85 if (rw == RW_WRITER) { 86 rv = rw_trywrlock(&rwlp->rw_lock); 87 if (rv == 0) 88 rwlp->rw_owner = _curthread(); 89 } else 90 rv = rw_tryrdlock(&rwlp->rw_lock); 91 92 return ((rv == 0) ? 1 : 0); 93 } 94 95 /*ARGSUSED*/ 96 int 97 rw_tryupgrade(krwlock_t *rwlp) 98 { 99 100 return (0); 101 } 102 103 void 104 rw_downgrade(krwlock_t *rwlp) 105 { 106 ASSERT(rwlp->rw_owner == _curthread()); 107 rwlp->rw_owner = _KTHREAD_INVALID; 108 VERIFY(rw_unlock(&rwlp->rw_lock) == 0); 109 VERIFY(rw_rdlock(&rwlp->rw_lock) == 0); 110 } 111 112 int 113 rw_read_held(krwlock_t *rwlp) 114 { 115 return (_rw_read_held(rwlp)); 116 } 117 118 int 119 rw_write_held(krwlock_t *rwlp) 120 { 121 return (_rw_write_held(rwlp)); 122 } 123 124 int 125 rw_lock_held(krwlock_t *rwlp) 126 { 127 return (rw_read_held(rwlp) || rw_write_held(rwlp)); 128 } 129 130 /* 131 * Return the kthread_t * of the lock owner 132 */ 133 void * 134 rw_owner(krwlock_t *rwlp) 135 { 136 return (rwlp->rw_owner); 137 } 138