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