]>
Commit | Line | Data |
---|---|---|
7bdf406d TG |
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 | ||
33 | ||
34 | #ifdef __cplusplus | |
35 | extern "C" { | |
36 | #endif | |
37 | ||
38 | #include <sys/inttypes.h> | |
39 | #include <sys/zfs_context.h> | |
40 | #include <sys/refcount.h> | |
41 | ||
42 | /* | |
43 | * A reader-writer lock implementation that allows re-entrant reads, but | |
44 | * still gives writers priority on "new" reads. | |
45 | * | |
46 | * See rrwlock.c for more details about the implementation. | |
47 | * | |
48 | * Fields of the rrwlock_t structure: | |
49 | * - rr_lock: protects modification and reading of rrwlock_t fields | |
50 | * - rr_cv: cv for waking up readers or waiting writers | |
51 | * - rr_writer: thread id of the current writer | |
52 | * - rr_anon_rount: number of active anonymous readers | |
53 | * - rr_linked_rcount: total number of non-anonymous active readers | |
54 | * - rr_writer_wanted: a writer wants the lock | |
55 | */ | |
56 | typedef struct rrwlock { | |
57 | kmutex_t rr_lock; | |
58 | kcondvar_t rr_cv; | |
59 | kthread_t *rr_writer; | |
60 | refcount_t rr_anon_rcount; | |
61 | refcount_t rr_linked_rcount; | |
62 | boolean_t rr_writer_wanted; | |
63 | boolean_t rr_track_all; | |
64 | } rrwlock_t; | |
65 | ||
66 | /* | |
67 | * 'tag' is used in reference counting tracking. The | |
68 | * 'tag' must be the same in a rrw_enter() as in its | |
69 | * corresponding rrw_exit(). | |
70 | */ | |
71 | void rrw_init(rrwlock_t *rrl, boolean_t track_all); | |
72 | void rrw_destroy(rrwlock_t *rrl); | |
73 | void rrw_enter(rrwlock_t *rrl, krw_t rw, void *tag); | |
74 | void rrw_enter_read(rrwlock_t *rrl, void *tag); | |
75 | void rrw_enter_read_prio(rrwlock_t *rrl, void *tag); | |
76 | void rrw_enter_write(rrwlock_t *rrl); | |
77 | void rrw_exit(rrwlock_t *rrl, void *tag); | |
78 | boolean_t rrw_held(rrwlock_t *rrl, krw_t rw); | |
79 | void rrw_tsd_destroy(void *arg); | |
80 | ||
81 | #define RRW_READ_HELD(x) rrw_held(x, RW_READER) | |
82 | #define RRW_WRITE_HELD(x) rrw_held(x, RW_WRITER) | |
83 | #define RRW_LOCK_HELD(x) \ | |
84 | (rrw_held(x, RW_WRITER) || rrw_held(x, RW_READER)) | |
85 | ||
86 | /* | |
87 | * A reader-mostly lock implementation, tuning above reader-writer locks | |
88 | * for hightly parallel read acquisitions, pessimizing write acquisitions. | |
89 | * | |
90 | * This should be a prime number. See comment in rrwlock.c near | |
91 | * RRM_TD_LOCK() for details. | |
92 | */ | |
93 | #define RRM_NUM_LOCKS 17 | |
94 | typedef struct rrmlock { | |
95 | rrwlock_t locks[RRM_NUM_LOCKS]; | |
96 | } rrmlock_t; | |
97 | ||
98 | void rrm_init(rrmlock_t *rrl, boolean_t track_all); | |
99 | void rrm_destroy(rrmlock_t *rrl); | |
100 | void rrm_enter(rrmlock_t *rrl, krw_t rw, void *tag); | |
101 | void rrm_enter_read(rrmlock_t *rrl, void *tag); | |
102 | void rrm_enter_write(rrmlock_t *rrl); | |
103 | void rrm_exit(rrmlock_t *rrl, void *tag); | |
104 | boolean_t rrm_held(rrmlock_t *rrl, krw_t rw); | |
105 | ||
106 | #define RRM_READ_HELD(x) rrm_held(x, RW_READER) | |
107 | #define RRM_WRITE_HELD(x) rrm_held(x, RW_WRITER) | |
108 | #define RRM_LOCK_HELD(x) \ | |
109 | (rrm_held(x, RW_WRITER) || rrm_held(x, RW_READER)) | |
110 | ||
111 | #ifdef __cplusplus | |
112 | } | |
113 | #endif | |
114 | ||
115 | #endif /* _SYS_RR_RW_LOCK_H */ |