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 /* 22*3f9d6ad7SLin 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 43fa9e4066Sahrens #if defined(DEBUG) || !defined(_KERNEL) 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); 70fa9e4066Sahrens 71fa9e4066Sahrens void refcount_init(void); 72fa9e4066Sahrens void refcount_fini(void); 73fa9e4066Sahrens 74fa9e4066Sahrens #else /* DEBUG */ 75fa9e4066Sahrens 76fa9e4066Sahrens typedef struct refcount { 77fa9e4066Sahrens uint64_t rc_count; 78fa9e4066Sahrens } refcount_t; 79fa9e4066Sahrens 80fa9e4066Sahrens #define refcount_create(rc) ((rc)->rc_count = 0) 81fa9e4066Sahrens #define refcount_destroy(rc) ((rc)->rc_count = 0) 82fa9e4066Sahrens #define refcount_destroy_many(rc, number) ((rc)->rc_count = 0) 83fa9e4066Sahrens #define refcount_is_zero(rc) ((rc)->rc_count == 0) 84fa9e4066Sahrens #define refcount_count(rc) ((rc)->rc_count) 85fa9e4066Sahrens #define refcount_add(rc, holder) atomic_add_64_nv(&(rc)->rc_count, 1) 86fa9e4066Sahrens #define refcount_remove(rc, holder) atomic_add_64_nv(&(rc)->rc_count, -1) 87fa9e4066Sahrens #define refcount_add_many(rc, number, holder) \ 88fa9e4066Sahrens atomic_add_64_nv(&(rc)->rc_count, number) 89fa9e4066Sahrens #define refcount_remove_many(rc, number, holder) \ 90fa9e4066Sahrens atomic_add_64_nv(&(rc)->rc_count, -number) 91*3f9d6ad7SLin Ling #define refcount_transfer(dst, src) { \ 92*3f9d6ad7SLin Ling uint64_t __tmp = (src)->rc_count; \ 93*3f9d6ad7SLin Ling atomic_add_64(&(src)->rc_count, -__tmp); \ 94*3f9d6ad7SLin Ling atomic_add_64(&(dst)->rc_count, __tmp); \ 95*3f9d6ad7SLin Ling } 96fa9e4066Sahrens 97fa9e4066Sahrens #define refcount_init() 98fa9e4066Sahrens #define refcount_fini() 99fa9e4066Sahrens 100fa9e4066Sahrens #endif /* DEBUG */ 101fa9e4066Sahrens 102fa9e4066Sahrens #ifdef __cplusplus 103fa9e4066Sahrens } 104fa9e4066Sahrens #endif 105fa9e4066Sahrens 106fa9e4066Sahrens #endif /* _SYS_REFCOUNT_H */ 107