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 }