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