diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2012-11-06 06:31:49 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-11-20 01:15:02 -0500 |
commit | 4b20db3de8dab005b07c74161cb041db8c5ff3a7 (patch) | |
tree | 894e7d485b2e5d2b1ae0652b55dcd0f3f249fe8b /include | |
parent | d7144556195ab04a148e722a93103da5438bdf78 (diff) |
kref: Implement kref_get_unless_zero v3
This function is intended to simplify locking around refcounting for
objects that can be looked up from a lookup structure, and which are
removed from that lookup structure in the object destructor.
Operations on such objects require at least a read lock around
lookup + kref_get, and a write lock around kref_put + remove from lookup
structure. Furthermore, RCU implementations become extremely tricky.
With a lookup followed by a kref_get_unless_zero *with return value check*
locking in the kref_put path can be deferred to the actual removal from
the lookup structure and RCU lookups become trivial.
v2: Formatting fixes.
v3: Invert the return value.
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/kref.h | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/include/linux/kref.h b/include/linux/kref.h index 65af6887872f..4972e6e9ca93 100644 --- a/include/linux/kref.h +++ b/include/linux/kref.h | |||
@@ -111,4 +111,25 @@ static inline int kref_put_mutex(struct kref *kref, | |||
111 | } | 111 | } |
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
114 | |||
115 | /** | ||
116 | * kref_get_unless_zero - Increment refcount for object unless it is zero. | ||
117 | * @kref: object. | ||
118 | * | ||
119 | * Return non-zero if the increment succeeded. Otherwise return 0. | ||
120 | * | ||
121 | * This function is intended to simplify locking around refcounting for | ||
122 | * objects that can be looked up from a lookup structure, and which are | ||
123 | * removed from that lookup structure in the object destructor. | ||
124 | * Operations on such objects require at least a read lock around | ||
125 | * lookup + kref_get, and a write lock around kref_put + remove from lookup | ||
126 | * structure. Furthermore, RCU implementations become extremely tricky. | ||
127 | * With a lookup followed by a kref_get_unless_zero *with return value check* | ||
128 | * locking in the kref_put path can be deferred to the actual removal from | ||
129 | * the lookup structure and RCU lookups become trivial. | ||
130 | */ | ||
131 | static inline int __must_check kref_get_unless_zero(struct kref *kref) | ||
132 | { | ||
133 | return atomic_add_unless(&kref->refcount, 1, 0); | ||
134 | } | ||
114 | #endif /* _KREF_H_ */ | 135 | #endif /* _KREF_H_ */ |