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. 23fa9e4066Sahrens */ 24fa9e4066Sahrens 25fa9e4066Sahrens #ifndef _SYS_REFCOUNT_H 26fa9e4066Sahrens #define _SYS_REFCOUNT_H 27fa9e4066Sahrens 28fa9e4066Sahrens #include <sys/inttypes.h> 29fa9e4066Sahrens #include <sys/list.h> 30fa9e4066Sahrens #include <sys/zfs_context.h> 31fa9e4066Sahrens 32fa9e4066Sahrens #ifdef __cplusplus 33fa9e4066Sahrens extern "C" { 34fa9e4066Sahrens #endif 35fa9e4066Sahrens 36fa9e4066Sahrens /* 37fa9e4066Sahrens * If the reference is held only by the calling function and not any 38fa9e4066Sahrens * particular object, use FTAG (which is a string) for the holder_tag. 39fa9e4066Sahrens * Otherwise, use the object that holds the reference. 40fa9e4066Sahrens */ 41ea8dc4b6Seschrock #define FTAG ((char *)__func__) 42fa9e4066Sahrens 43*744947dcSTom Erickson #ifdef ZFS_DEBUG 44fa9e4066Sahrens typedef struct reference { 45fa9e4066Sahrens list_node_t ref_link; 46fa9e4066Sahrens void *ref_holder; 47fa9e4066Sahrens uint64_t ref_number; 48fa9e4066Sahrens uint8_t *ref_removed; 49fa9e4066Sahrens } reference_t; 50fa9e4066Sahrens 51fa9e4066Sahrens typedef struct refcount { 52fa9e4066Sahrens kmutex_t rc_mtx; 53fa9e4066Sahrens list_t rc_list; 54fa9e4066Sahrens list_t rc_removed; 55fa9e4066Sahrens int64_t rc_count; 56fa9e4066Sahrens int64_t rc_removed_count; 57fa9e4066Sahrens } refcount_t; 58fa9e4066Sahrens 5991ebeef5Sahrens /* Note: refcount_t must be initialized with refcount_create() */ 60fa9e4066Sahrens 61fa9e4066Sahrens void refcount_create(refcount_t *rc); 62fa9e4066Sahrens void refcount_destroy(refcount_t *rc); 63fa9e4066Sahrens void refcount_destroy_many(refcount_t *rc, uint64_t number); 64fa9e4066Sahrens int refcount_is_zero(refcount_t *rc); 65fa9e4066Sahrens int64_t refcount_count(refcount_t *rc); 66fa9e4066Sahrens int64_t refcount_add(refcount_t *rc, void *holder_tag); 67fa9e4066Sahrens int64_t refcount_remove(refcount_t *rc, void *holder_tag); 68fa9e4066Sahrens int64_t refcount_add_many(refcount_t *rc, uint64_t number, void *holder_tag); 69fa9e4066Sahrens int64_t refcount_remove_many(refcount_t *rc, uint64_t number, void *holder_tag); 70*744947dcSTom Erickson void refcount_transfer(refcount_t *dst, refcount_t *src); 71fa9e4066Sahrens 72fa9e4066Sahrens void refcount_init(void); 73fa9e4066Sahrens void refcount_fini(void); 74fa9e4066Sahrens 75*744947dcSTom Erickson #else /* ZFS_DEBUG */ 76fa9e4066Sahrens 77fa9e4066Sahrens typedef struct refcount { 78fa9e4066Sahrens uint64_t rc_count; 79fa9e4066Sahrens } refcount_t; 80fa9e4066Sahrens 81fa9e4066Sahrens #define refcount_create(rc) ((rc)->rc_count = 0) 82fa9e4066Sahrens #define refcount_destroy(rc) ((rc)->rc_count = 0) 83fa9e4066Sahrens #define refcount_destroy_many(rc, number) ((rc)->rc_count = 0) 84fa9e4066Sahrens #define refcount_is_zero(rc) ((rc)->rc_count == 0) 85fa9e4066Sahrens #define refcount_count(rc) ((rc)->rc_count) 86fa9e4066Sahrens #define refcount_add(rc, holder) atomic_add_64_nv(&(rc)->rc_count, 1) 87fa9e4066Sahrens #define refcount_remove(rc, holder) atomic_add_64_nv(&(rc)->rc_count, -1) 88fa9e4066Sahrens #define refcount_add_many(rc, number, holder) \ 89fa9e4066Sahrens atomic_add_64_nv(&(rc)->rc_count, number) 90fa9e4066Sahrens #define refcount_remove_many(rc, number, holder) \ 91fa9e4066Sahrens atomic_add_64_nv(&(rc)->rc_count, -number) 923f9d6ad7SLin Ling #define refcount_transfer(dst, src) { \ 933f9d6ad7SLin Ling uint64_t __tmp = (src)->rc_count; \ 943f9d6ad7SLin Ling atomic_add_64(&(src)->rc_count, -__tmp); \ 953f9d6ad7SLin Ling atomic_add_64(&(dst)->rc_count, __tmp); \ 963f9d6ad7SLin Ling } 97fa9e4066Sahrens 98fa9e4066Sahrens #define refcount_init() 99fa9e4066Sahrens #define refcount_fini() 100fa9e4066Sahrens 101*744947dcSTom Erickson #endif /* ZFS_DEBUG */ 102fa9e4066Sahrens 103fa9e4066Sahrens #ifdef __cplusplus 104fa9e4066Sahrens } 105fa9e4066Sahrens #endif 106fa9e4066Sahrens 107fa9e4066Sahrens #endif /* _SYS_REFCOUNT_H */ 108