xref: /illumos-gate/usr/src/lib/libfakekernel/common/rwlock.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
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