Commit ecf7ace9a8450303a987aa8364e53860cd50e554
Committed by
Dave Airlie
1 parent
d6ea88865d
kref: Add a kref_sub function
Makes it possible to optimize batched multiple unrefs. Initial user will be drivers/gpu/ttm which accumulates unrefs to be processed outside of atomic code. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Showing 2 changed files with 32 additions and 0 deletions Side-by-side Diff
include/linux/kref.h
... | ... | @@ -24,6 +24,8 @@ |
24 | 24 | void kref_init(struct kref *kref); |
25 | 25 | void kref_get(struct kref *kref); |
26 | 26 | int kref_put(struct kref *kref, void (*release) (struct kref *kref)); |
27 | +int kref_sub(struct kref *kref, unsigned int count, | |
28 | + void (*release) (struct kref *kref)); | |
27 | 29 | |
28 | 30 | #endif /* _KREF_H_ */ |
lib/kref.c
... | ... | @@ -62,7 +62,37 @@ |
62 | 62 | return 0; |
63 | 63 | } |
64 | 64 | |
65 | + | |
66 | +/** | |
67 | + * kref_sub - subtract a number of refcounts for object. | |
68 | + * @kref: object. | |
69 | + * @count: Number of recounts to subtract. | |
70 | + * @release: pointer to the function that will clean up the object when the | |
71 | + * last reference to the object is released. | |
72 | + * This pointer is required, and it is not acceptable to pass kfree | |
73 | + * in as this function. | |
74 | + * | |
75 | + * Subtract @count from the refcount, and if 0, call release(). | |
76 | + * Return 1 if the object was removed, otherwise return 0. Beware, if this | |
77 | + * function returns 0, you still can not count on the kref from remaining in | |
78 | + * memory. Only use the return value if you want to see if the kref is now | |
79 | + * gone, not present. | |
80 | + */ | |
81 | +int kref_sub(struct kref *kref, unsigned int count, | |
82 | + void (*release)(struct kref *kref)) | |
83 | +{ | |
84 | + WARN_ON(release == NULL); | |
85 | + WARN_ON(release == (void (*)(struct kref *))kfree); | |
86 | + | |
87 | + if (atomic_sub_and_test((int) count, &kref->refcount)) { | |
88 | + release(kref); | |
89 | + return 1; | |
90 | + } | |
91 | + return 0; | |
92 | +} | |
93 | + | |
65 | 94 | EXPORT_SYMBOL(kref_init); |
66 | 95 | EXPORT_SYMBOL(kref_get); |
67 | 96 | EXPORT_SYMBOL(kref_put); |
97 | +EXPORT_SYMBOL(kref_sub); |