xref: /illumos-gate/usr/src/uts/common/fs/zfs/sys/rrwlock.h (revision e914ace2)
1f18faf3fSek /*
2f18faf3fSek  * CDDL HEADER START
3f18faf3fSek  *
4f18faf3fSek  * The contents of this file are subject to the terms of the
5f18faf3fSek  * Common Development and Distribution License (the "License").
6f18faf3fSek  * You may not use this file except in compliance with the License.
7f18faf3fSek  *
8f18faf3fSek  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9f18faf3fSek  * or http://www.opensolaris.org/os/licensing.
10f18faf3fSek  * See the License for the specific language governing permissions
11f18faf3fSek  * and limitations under the License.
12f18faf3fSek  *
13f18faf3fSek  * When distributing Covered Code, include this CDDL HEADER in each
14f18faf3fSek  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15f18faf3fSek  * If applicable, add the following below this CDDL HEADER, with the
16f18faf3fSek  * fields enclosed by brackets "[]" replaced with your own identifying
17f18faf3fSek  * information: Portions Copyright [yyyy] [name of copyright owner]
18f18faf3fSek  *
19f18faf3fSek  * CDDL HEADER END
20f18faf3fSek  */
21f18faf3fSek /*
22f18faf3fSek  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23f18faf3fSek  * Use is subject to license terms.
24f18faf3fSek  */
254445fffbSMatthew Ahrens /*
264445fffbSMatthew Ahrens  * Copyright (c) 2012 by Delphix. All rights reserved.
274445fffbSMatthew Ahrens  */
28f18faf3fSek 
29f18faf3fSek #ifndef	_SYS_RR_RW_LOCK_H
30f18faf3fSek #define	_SYS_RR_RW_LOCK_H
31f18faf3fSek 
32f18faf3fSek #ifdef	__cplusplus
33f18faf3fSek extern "C" {
34f18faf3fSek #endif
35f18faf3fSek 
36f18faf3fSek #include <sys/inttypes.h>
37f18faf3fSek #include <sys/zfs_context.h>
38f18faf3fSek #include <sys/refcount.h>
39f18faf3fSek 
40f18faf3fSek /*
41f18faf3fSek  * A reader-writer lock implementation that allows re-entrant reads, but
42f18faf3fSek  * still gives writers priority on "new" reads.
43f18faf3fSek  *
44f18faf3fSek  * See rrwlock.c for more details about the implementation.
45f18faf3fSek  *
46f18faf3fSek  * Fields of the rrwlock_t structure:
47f18faf3fSek  * - rr_lock: protects modification and reading of rrwlock_t fields
48f18faf3fSek  * - rr_cv: cv for waking up readers or waiting writers
49f18faf3fSek  * - rr_writer: thread id of the current writer
50f18faf3fSek  * - rr_anon_rount: number of active anonymous readers
51f18faf3fSek  * - rr_linked_rcount: total number of non-anonymous active readers
52f18faf3fSek  * - rr_writer_wanted: a writer wants the lock
53f18faf3fSek  */
54f18faf3fSek typedef struct rrwlock {
55f18faf3fSek 	kmutex_t	rr_lock;
56f18faf3fSek 	kcondvar_t	rr_cv;
57f18faf3fSek 	kthread_t	*rr_writer;
58*e914ace2STim Schumacher 	zfs_refcount_t	rr_anon_rcount;
59*e914ace2STim Schumacher 	zfs_refcount_t	rr_linked_rcount;
60f18faf3fSek 	boolean_t	rr_writer_wanted;
613b2aab18SMatthew Ahrens 	boolean_t	rr_track_all;
62f18faf3fSek } rrwlock_t;
63f18faf3fSek 
64f18faf3fSek /*
65f18faf3fSek  * 'tag' is used in reference counting tracking.  The
66f18faf3fSek  * 'tag' must be the same in a rrw_enter() as in its
67f18faf3fSek  * corresponding rrw_exit().
68f18faf3fSek  */
693b2aab18SMatthew Ahrens void rrw_init(rrwlock_t *rrl, boolean_t track_all);
70f18faf3fSek void rrw_destroy(rrwlock_t *rrl);
71f18faf3fSek void rrw_enter(rrwlock_t *rrl, krw_t rw, void *tag);
723b2aab18SMatthew Ahrens void rrw_enter_read(rrwlock_t *rrl, void *tag);
731d3f896fSArne Jansen void rrw_enter_read_prio(rrwlock_t *rrl, void *tag);
743b2aab18SMatthew Ahrens void rrw_enter_write(rrwlock_t *rrl);
75f18faf3fSek void rrw_exit(rrwlock_t *rrl, void *tag);
76f18faf3fSek boolean_t rrw_held(rrwlock_t *rrl, krw_t rw);
774445fffbSMatthew Ahrens void rrw_tsd_destroy(void *arg);
78f18faf3fSek 
79f18faf3fSek #define	RRW_READ_HELD(x)	rrw_held(x, RW_READER)
80f18faf3fSek #define	RRW_WRITE_HELD(x)	rrw_held(x, RW_WRITER)
813b2aab18SMatthew Ahrens #define	RRW_LOCK_HELD(x) \
823b2aab18SMatthew Ahrens 	(rrw_held(x, RW_WRITER) || rrw_held(x, RW_READER))
83f18faf3fSek 
84c9030f6cSAlexander Motin /*
85c9030f6cSAlexander Motin  * A reader-mostly lock implementation, tuning above reader-writer locks
86c9030f6cSAlexander Motin  * for hightly parallel read acquisitions, pessimizing write acquisitions.
87c9030f6cSAlexander Motin  *
88c9030f6cSAlexander Motin  * This should be a prime number.  See comment in rrwlock.c near
89c9030f6cSAlexander Motin  * RRM_TD_LOCK() for details.
90c9030f6cSAlexander Motin  */
91c9030f6cSAlexander Motin #define	RRM_NUM_LOCKS		17
92c9030f6cSAlexander Motin typedef struct rrmlock {
93c9030f6cSAlexander Motin 	rrwlock_t	locks[RRM_NUM_LOCKS];
94c9030f6cSAlexander Motin } rrmlock_t;
95c9030f6cSAlexander Motin 
96c9030f6cSAlexander Motin void rrm_init(rrmlock_t *rrl, boolean_t track_all);
97c9030f6cSAlexander Motin void rrm_destroy(rrmlock_t *rrl);
98c9030f6cSAlexander Motin void rrm_enter(rrmlock_t *rrl, krw_t rw, void *tag);
99c9030f6cSAlexander Motin void rrm_enter_read(rrmlock_t *rrl, void *tag);
100c9030f6cSAlexander Motin void rrm_enter_write(rrmlock_t *rrl);
101c9030f6cSAlexander Motin void rrm_exit(rrmlock_t *rrl, void *tag);
102c9030f6cSAlexander Motin boolean_t rrm_held(rrmlock_t *rrl, krw_t rw);
103c9030f6cSAlexander Motin 
104c9030f6cSAlexander Motin #define	RRM_READ_HELD(x)	rrm_held(x, RW_READER)
105c9030f6cSAlexander Motin #define	RRM_WRITE_HELD(x)	rrm_held(x, RW_WRITER)
106c9030f6cSAlexander Motin #define	RRM_LOCK_HELD(x) \
107c9030f6cSAlexander Motin 	(rrm_held(x, RW_WRITER) || rrm_held(x, RW_READER))
108c9030f6cSAlexander Motin 
109f18faf3fSek #ifdef	__cplusplus
110f18faf3fSek }
111f18faf3fSek #endif
112f18faf3fSek 
113f18faf3fSek #endif	/* _SYS_RR_RW_LOCK_H */
114