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