refcount.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _LINUX_REFCOUNT_H
  3. #define _LINUX_REFCOUNT_H
  4. #include <linux/atomic.h>
  5. #include <linux/mutex.h>
  6. #include <linux/spinlock.h>
  7. #include <linux/kernel.h>
  8. /**
  9. * struct refcount_t - variant of atomic_t specialized for reference counts
  10. * @refs: atomic_t counter field
  11. *
  12. * The counter saturates at UINT_MAX and will not move once
  13. * there. This avoids wrapping the counter and causing 'spurious'
  14. * use-after-free bugs.
  15. */
  16. typedef struct refcount_struct {
  17. atomic_t refs;
  18. } refcount_t;
  19. #define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), }
  20. /**
  21. * refcount_set - set a refcount's value
  22. * @r: the refcount
  23. * @n: value to which the refcount will be set
  24. */
  25. static inline void refcount_set(refcount_t *r, unsigned int n)
  26. {
  27. atomic_set(&r->refs, n);
  28. }
  29. /**
  30. * refcount_read - get a refcount's value
  31. * @r: the refcount
  32. *
  33. * Return: the refcount's value
  34. */
  35. static inline unsigned int refcount_read(const refcount_t *r)
  36. {
  37. return atomic_read(&r->refs);
  38. }
  39. #ifdef CONFIG_REFCOUNT_FULL
  40. extern __must_check bool refcount_add_not_zero(unsigned int i, refcount_t *r);
  41. extern void refcount_add(unsigned int i, refcount_t *r);
  42. extern __must_check bool refcount_inc_not_zero(refcount_t *r);
  43. extern void refcount_inc(refcount_t *r);
  44. extern __must_check bool refcount_sub_and_test(unsigned int i, refcount_t *r);
  45. extern __must_check bool refcount_dec_and_test(refcount_t *r);
  46. extern void refcount_dec(refcount_t *r);
  47. #else
  48. # ifdef CONFIG_ARCH_HAS_REFCOUNT
  49. # include <asm/refcount.h>
  50. # else
  51. static inline __must_check bool refcount_add_not_zero(unsigned int i, refcount_t *r)
  52. {
  53. return atomic_add_unless(&r->refs, i, 0);
  54. }
  55. static inline void refcount_add(unsigned int i, refcount_t *r)
  56. {
  57. atomic_add(i, &r->refs);
  58. }
  59. static inline __must_check bool refcount_inc_not_zero(refcount_t *r)
  60. {
  61. return atomic_add_unless(&r->refs, 1, 0);
  62. }
  63. static inline void refcount_inc(refcount_t *r)
  64. {
  65. atomic_inc(&r->refs);
  66. }
  67. static inline __must_check bool refcount_sub_and_test(unsigned int i, refcount_t *r)
  68. {
  69. return atomic_sub_and_test(i, &r->refs);
  70. }
  71. static inline __must_check bool refcount_dec_and_test(refcount_t *r)
  72. {
  73. return atomic_dec_and_test(&r->refs);
  74. }
  75. static inline void refcount_dec(refcount_t *r)
  76. {
  77. atomic_dec(&r->refs);
  78. }
  79. # endif /* !CONFIG_ARCH_HAS_REFCOUNT */
  80. #endif /* CONFIG_REFCOUNT_FULL */
  81. extern __must_check bool refcount_dec_if_one(refcount_t *r);
  82. extern __must_check bool refcount_dec_not_one(refcount_t *r);
  83. extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock);
  84. extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock);
  85. extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r,
  86. spinlock_t *lock,
  87. unsigned long *flags);
  88. #endif /* _LINUX_REFCOUNT_H */