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