Commit ecf7ace9a8450303a987aa8364e53860cd50e554

Authored by Thomas Hellstrom
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_ */
... ... @@ -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);