Fix hangs with processes stuck sleeping on btalloc on i386.
[freebsd.git] / sys / cddl / contrib / opensolaris / uts / common / fs / zfs / sys / refcount.h
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
24  */
25
26 #ifndef _SYS_REFCOUNT_H
27 #define _SYS_REFCOUNT_H
28
29 #include <sys/cdefs.h>
30 #include <sys/types.h>
31 /* For FreeBSD refcount(9). */
32 #include_next <sys/refcount.h>
33 #include <sys/list.h>
34 #include <sys/zfs_context.h>
35
36 #ifdef  __cplusplus
37 extern "C" {
38 #endif
39
40 /*
41  * If the reference is held only by the calling function and not any
42  * particular object, use FTAG (which is a string) for the holder_tag.
43  * Otherwise, use the object that holds the reference.
44  */
45 #define FTAG ((char *)(uintptr_t)__func__)
46
47 #ifdef  ZFS_DEBUG
48 typedef struct reference {
49         list_node_t ref_link;
50         void *ref_holder;
51         uint64_t ref_number;
52         uint8_t *ref_removed;
53 } reference_t;
54
55 typedef struct refcount {
56         kmutex_t rc_mtx;
57         boolean_t rc_tracked;
58         list_t rc_list;
59         list_t rc_removed;
60         uint64_t rc_count;
61         uint64_t rc_removed_count;
62 } zfs_refcount_t;
63
64 /*
65  * Note: zfs_refcount_t must be initialized with
66  * refcount_create[_untracked]()
67  */
68
69 void zfs_refcount_create(zfs_refcount_t *);
70 void zfs_refcount_create_untracked(zfs_refcount_t *);
71 void zfs_refcount_create_tracked(zfs_refcount_t *);
72 void zfs_refcount_destroy(zfs_refcount_t *);
73 void zfs_refcount_destroy_many(zfs_refcount_t *, uint64_t);
74 int zfs_refcount_is_zero(zfs_refcount_t *);
75 int64_t zfs_refcount_count(zfs_refcount_t *);
76 int64_t zfs_refcount_add(zfs_refcount_t *, void *);
77 int64_t zfs_refcount_remove(zfs_refcount_t *, void *);
78 int64_t zfs_refcount_add_many(zfs_refcount_t *, uint64_t, void *);
79 int64_t zfs_refcount_remove_many(zfs_refcount_t *, uint64_t, void *);
80 void zfs_refcount_transfer(zfs_refcount_t *, zfs_refcount_t *);
81 void zfs_refcount_transfer_ownership(zfs_refcount_t *, void *, void *);
82 boolean_t zfs_refcount_held(zfs_refcount_t *, void *);
83 boolean_t zfs_refcount_not_held(zfs_refcount_t *, void *);
84
85 void zfs_refcount_init(void);
86 void zfs_refcount_fini(void);
87
88 #else   /* ZFS_DEBUG */
89
90 typedef struct refcount {
91         uint64_t rc_count;
92 } zfs_refcount_t;
93
94 #define zfs_refcount_create(rc) ((rc)->rc_count = 0)
95 #define zfs_refcount_create_untracked(rc) ((rc)->rc_count = 0)
96 #define zfs_refcount_create_tracked(rc) ((rc)->rc_count = 0)
97 #define zfs_refcount_destroy(rc) ((rc)->rc_count = 0)
98 #define zfs_refcount_destroy_many(rc, number) ((rc)->rc_count = 0)
99 #define zfs_refcount_is_zero(rc) ((rc)->rc_count == 0)
100 #define zfs_refcount_count(rc) ((rc)->rc_count)
101 #define zfs_refcount_add(rc, holder) atomic_inc_64_nv(&(rc)->rc_count)
102 #define zfs_refcount_remove(rc, holder) atomic_dec_64_nv(&(rc)->rc_count)
103 #define zfs_refcount_add_many(rc, number, holder) \
104         atomic_add_64_nv(&(rc)->rc_count, number)
105 #define zfs_refcount_remove_many(rc, number, holder) \
106         atomic_add_64_nv(&(rc)->rc_count, -number)
107 #define zfs_refcount_transfer(dst, src) { \
108         uint64_t __tmp = (src)->rc_count; \
109         atomic_add_64(&(src)->rc_count, -__tmp); \
110         atomic_add_64(&(dst)->rc_count, __tmp); \
111 }
112 #define zfs_refcount_transfer_ownership(rc, current_holder, new_holder) (void)0
113 #define zfs_refcount_held(rc, holder)           ((rc)->rc_count > 0)
114 #define zfs_refcount_not_held(rc, holder)               (B_TRUE)
115
116 #define zfs_refcount_init()
117 #define zfs_refcount_fini()
118
119 #endif  /* ZFS_DEBUG */
120
121 #ifdef  __cplusplus
122 }
123 #endif
124
125 #endif /* _SYS_REFCOUNT_H */