1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6ea8dc4b6Seschrock * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 223f9d6ad7SLin Ling * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 2328e4da25SMatthew Ahrens * Copyright (c) 2012 by Delphix. All rights reserved. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 26fa9e4066Sahrens #ifndef _SYS_REFCOUNT_H 27fa9e4066Sahrens #define _SYS_REFCOUNT_H 28fa9e4066Sahrens 29fa9e4066Sahrens #include <sys/inttypes.h> 30fa9e4066Sahrens #include <sys/list.h> 31fa9e4066Sahrens #include <sys/zfs_context.h> 32fa9e4066Sahrens 33fa9e4066Sahrens #ifdef __cplusplus 34fa9e4066Sahrens extern "C" { 35fa9e4066Sahrens #endif 36fa9e4066Sahrens 37fa9e4066Sahrens /* 38fa9e4066Sahrens * If the reference is held only by the calling function and not any 39fa9e4066Sahrens * particular object, use FTAG (which is a string) for the holder_tag. 40fa9e4066Sahrens * Otherwise, use the object that holds the reference. 41fa9e4066Sahrens */ 42ea8dc4b6Seschrock #define FTAG ((char *)__func__) 43fa9e4066Sahrens 44744947dcSTom Erickson #ifdef ZFS_DEBUG 45fa9e4066Sahrens typedef struct reference { 46fa9e4066Sahrens list_node_t ref_link; 47fa9e4066Sahrens void *ref_holder; 48fa9e4066Sahrens uint64_t ref_number; 49fa9e4066Sahrens uint8_t *ref_removed; 50fa9e4066Sahrens } reference_t; 51fa9e4066Sahrens 52fa9e4066Sahrens typedef struct refcount { 53fa9e4066Sahrens kmutex_t rc_mtx; 543b2aab18SMatthew Ahrens boolean_t rc_tracked; 55fa9e4066Sahrens list_t rc_list; 56fa9e4066Sahrens list_t rc_removed; 5728e4da25SMatthew Ahrens uint64_t rc_count; 5828e4da25SMatthew Ahrens uint64_t rc_removed_count; 59fa9e4066Sahrens } refcount_t; 60fa9e4066Sahrens 613b2aab18SMatthew Ahrens /* Note: refcount_t must be initialized with refcount_create[_untracked]() */ 62fa9e4066Sahrens 63fa9e4066Sahrens void refcount_create(refcount_t *rc); 643b2aab18SMatthew Ahrens void refcount_create_untracked(refcount_t *rc); 65fa9e4066Sahrens void refcount_destroy(refcount_t *rc); 66fa9e4066Sahrens void refcount_destroy_many(refcount_t *rc, uint64_t number); 67fa9e4066Sahrens int refcount_is_zero(refcount_t *rc); 68fa9e4066Sahrens int64_t refcount_count(refcount_t *rc); 69fa9e4066Sahrens int64_t refcount_add(refcount_t *rc, void *holder_tag); 70fa9e4066Sahrens int64_t refcount_remove(refcount_t *rc, void *holder_tag); 71fa9e4066Sahrens int64_t refcount_add_many(refcount_t *rc, uint64_t number, void *holder_tag); 72fa9e4066Sahrens int64_t refcount_remove_many(refcount_t *rc, uint64_t number, void *holder_tag); 73744947dcSTom Erickson void refcount_transfer(refcount_t *dst, refcount_t *src); 74fa9e4066Sahrens 75fa9e4066Sahrens void refcount_init(void); 76fa9e4066Sahrens void refcount_fini(void); 77fa9e4066Sahrens 78744947dcSTom Erickson #else /* ZFS_DEBUG */ 79fa9e4066Sahrens 80fa9e4066Sahrens typedef struct refcount { 81fa9e4066Sahrens uint64_t rc_count; 82fa9e4066Sahrens } refcount_t; 83fa9e4066Sahrens 84fa9e4066Sahrens #define refcount_create(rc) ((rc)->rc_count = 0) 853b2aab18SMatthew Ahrens #define refcount_create_untracked(rc) ((rc)->rc_count = 0) 86fa9e4066Sahrens #define refcount_destroy(rc) ((rc)->rc_count = 0) 87fa9e4066Sahrens #define refcount_destroy_many(rc, number) ((rc)->rc_count = 0) 88fa9e4066Sahrens #define refcount_is_zero(rc) ((rc)->rc_count == 0) 89fa9e4066Sahrens #define refcount_count(rc) ((rc)->rc_count) 90*1a5e258fSJosef 'Jeff' Sipek #define refcount_add(rc, holder) atomic_inc_64_nv(&(rc)->rc_count) 91*1a5e258fSJosef 'Jeff' Sipek #define refcount_remove(rc, holder) atomic_dec_64_nv(&(rc)->rc_count) 92fa9e4066Sahrens #define refcount_add_many(rc, number, holder) \ 93fa9e4066Sahrens atomic_add_64_nv(&(rc)->rc_count, number) 94fa9e4066Sahrens #define refcount_remove_many(rc, number, holder) \ 95fa9e4066Sahrens atomic_add_64_nv(&(rc)->rc_count, -number) 963f9d6ad7SLin Ling #define refcount_transfer(dst, src) { \ 973f9d6ad7SLin Ling uint64_t __tmp = (src)->rc_count; \ 983f9d6ad7SLin Ling atomic_add_64(&(src)->rc_count, -__tmp); \ 993f9d6ad7SLin Ling atomic_add_64(&(dst)->rc_count, __tmp); \ 1003f9d6ad7SLin Ling } 101fa9e4066Sahrens 102fa9e4066Sahrens #define refcount_init() 103fa9e4066Sahrens #define refcount_fini() 104fa9e4066Sahrens 105744947dcSTom Erickson #endif /* ZFS_DEBUG */ 106fa9e4066Sahrens 107fa9e4066Sahrens #ifdef __cplusplus 108fa9e4066Sahrens } 109fa9e4066Sahrens #endif 110fa9e4066Sahrens 111fa9e4066Sahrens #endif /* _SYS_REFCOUNT_H */ 112