diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-12-16 21:02:15 (GMT) |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-12-16 21:02:15 (GMT) |
commit | d8c58fabd75021cdd99abcd96513cb088d41092b (patch) | |
tree | f6554ecfb27c0d50f5ae6acae3a7077282813cab /lib | |
parent | 9c04f015ebc2cc2cca5a4a576deb82a311578edc (diff) | |
parent | b08ebe7e776e5be0271ed1e1bbb384e1f29dd117 (diff) | |
download | linux-d8c58fabd75021cdd99abcd96513cb088d41092b.tar.xz |
Merge remote branch 'airlied/drm-core-next' into drm-intel-next
Diffstat (limited to 'lib')
-rw-r--r-- | lib/kref.c | 30 |
1 files changed, 30 insertions, 0 deletions
@@ -62,6 +62,36 @@ int kref_put(struct kref *kref, void (*release)(struct kref *kref)) return 0; } + +/** + * kref_sub - subtract a number of refcounts for object. + * @kref: object. + * @count: Number of recounts to subtract. + * @release: pointer to the function that will clean up the object when the + * last reference to the object is released. + * This pointer is required, and it is not acceptable to pass kfree + * in as this function. + * + * Subtract @count from the refcount, and if 0, call release(). + * Return 1 if the object was removed, otherwise return 0. Beware, if this + * function returns 0, you still can not count on the kref from remaining in + * memory. Only use the return value if you want to see if the kref is now + * gone, not present. + */ +int kref_sub(struct kref *kref, unsigned int count, + void (*release)(struct kref *kref)) +{ + WARN_ON(release == NULL); + WARN_ON(release == (void (*)(struct kref *))kfree); + + if (atomic_sub_and_test((int) count, &kref->refcount)) { + release(kref); + return 1; + } + return 0; +} + EXPORT_SYMBOL(kref_init); EXPORT_SYMBOL(kref_get); EXPORT_SYMBOL(kref_put); +EXPORT_SYMBOL(kref_sub); |