dec_and_lock.c 806 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. #ifdef CONFIG_SMP
  22. /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
  23. if (atomic_add_unless(atomic, -1, 1))
  24. return 0;
  25. #endif
  26. /* Otherwise do it the slow way */
  27. spin_lock(lock);
  28. if (atomic_dec_and_test(atomic))
  29. return 1;
  30. spin_unlock(lock);
  31. return 0;
  32. }
  33. EXPORT_SYMBOL(_atomic_dec_and_lock);