dec_and_lock.c 782 B

1234567891011121314151617181920212223242526272829303132333435
  1. #include <linux/module.h>
  2. #include <linux/spinlock.h>
  3. #include <asm/atomic.h>
  4. /*
  5. * This is an implementation of the notion of "decrement a
  6. * reference count, and return locked if it decremented to zero".
  7. *
  8. * NOTE NOTE NOTE! This is _not_ equivalent to
  9. *
  10. * if (atomic_dec_and_test(&atomic)) {
  11. * spin_lock(&lock);
  12. * return 1;
  13. * }
  14. * return 0;
  15. *
  16. * because the spin-lock and the decrement must be
  17. * "atomic".
  18. */
  19. int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
  20. {
  21. /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
  22. if (atomic_add_unless(atomic, -1, 1))
  23. return 0;
  24. /* Otherwise do it the slow way */
  25. spin_lock(lock);
  26. if (atomic_dec_and_test(atomic))
  27. return 1;
  28. spin_unlock(lock);
  29. return 0;
  30. }
  31. EXPORT_SYMBOL(_atomic_dec_and_lock);