xref: /illumos-gate/usr/src/uts/common/fs/zfs/sys/refcount.h (revision 3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5)
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