kref.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /*
  2. * kref.c - library routines for handling generic reference counted objects
  3. *
  4. * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
  5. * Copyright (C) 2004 IBM Corp.
  6. *
  7. * based on lib/kobject.c which was:
  8. * Copyright (C) 2002-2003 Patrick Mochel <mochel@osdl.org>
  9. *
  10. * This file is released under the GPLv2.
  11. *
  12. */
  13. #include <linux/kref.h>
  14. #include <linux/module.h>
  15. #include <linux/slab.h>
  16. /**
  17. * kref_init - initialize object.
  18. * @kref: object in question.
  19. */
  20. void kref_init(struct kref *kref)
  21. {
  22. atomic_set(&kref->refcount, 1);
  23. smp_mb();
  24. }
  25. /**
  26. * kref_get - increment refcount for object.
  27. * @kref: object.
  28. */
  29. void kref_get(struct kref *kref)
  30. {
  31. WARN_ON(!atomic_read(&kref->refcount));
  32. atomic_inc(&kref->refcount);
  33. smp_mb__after_atomic_inc();
  34. }
  35. /**
  36. * kref_test_and_get - increment refcount for object only if refcount is not
  37. * zero.
  38. * @kref: object.
  39. *
  40. * Return non-zero if the refcount was incremented, 0 otherwise
  41. */
  42. int kref_test_and_get(struct kref *kref)
  43. {
  44. return atomic_inc_not_zero(&kref->refcount);
  45. }
  46. /**
  47. * kref_put - decrement refcount for object.
  48. * @kref: object.
  49. * @release: pointer to the function that will clean up the object when the
  50. * last reference to the object is released.
  51. * This pointer is required, and it is not acceptable to pass kfree
  52. * in as this function.
  53. *
  54. * Decrement the refcount, and if 0, call release().
  55. * Return 1 if the object was removed, otherwise return 0. Beware, if this
  56. * function returns 0, you still can not count on the kref from remaining in
  57. * memory. Only use the return value if you want to see if the kref is now
  58. * gone, not present.
  59. */
  60. int kref_put(struct kref *kref, void (*release)(struct kref *kref))
  61. {
  62. WARN_ON(release == NULL);
  63. WARN_ON(release == (void (*)(struct kref *))kfree);
  64. if (atomic_dec_and_test(&kref->refcount)) {
  65. release(kref);
  66. return 1;
  67. }
  68. return 0;
  69. }
  70. EXPORT_SYMBOL(kref_init);
  71. EXPORT_SYMBOL(kref_get);
  72. EXPORT_SYMBOL(kref_put);