bitops.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. * bitops.c: atomic operations which got too long to be inlined all over
  3. * the place.
  4. *
  5. * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
  6. * Copyright 2000 Grant Grundler (grundler@cup.hp.com)
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/spinlock.h>
  10. #include <asm/system.h>
  11. #include <asm/atomic.h>
  12. #ifdef CONFIG_SMP
  13. raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
  14. [0 ... (ATOMIC_HASH_SIZE-1)] = __RAW_SPIN_LOCK_UNLOCKED
  15. };
  16. #endif
  17. #ifdef __LP64__
  18. unsigned long __xchg64(unsigned long x, unsigned long *ptr)
  19. {
  20. unsigned long temp, flags;
  21. _atomic_spin_lock_irqsave(ptr, flags);
  22. temp = *ptr;
  23. *ptr = x;
  24. _atomic_spin_unlock_irqrestore(ptr, flags);
  25. return temp;
  26. }
  27. #endif
  28. unsigned long __xchg32(int x, int *ptr)
  29. {
  30. unsigned long flags;
  31. long temp;
  32. _atomic_spin_lock_irqsave(ptr, flags);
  33. temp = (long) *ptr; /* XXX - sign extension wanted? */
  34. *ptr = x;
  35. _atomic_spin_unlock_irqrestore(ptr, flags);
  36. return (unsigned long)temp;
  37. }
  38. unsigned long __xchg8(char x, char *ptr)
  39. {
  40. unsigned long flags;
  41. long temp;
  42. _atomic_spin_lock_irqsave(ptr, flags);
  43. temp = (long) *ptr; /* XXX - sign extension wanted? */
  44. *ptr = x;
  45. _atomic_spin_unlock_irqrestore(ptr, flags);
  46. return (unsigned long)temp;
  47. }
  48. #ifdef __LP64__
  49. unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new)
  50. {
  51. unsigned long flags;
  52. unsigned long prev;
  53. _atomic_spin_lock_irqsave(ptr, flags);
  54. if ((prev = *ptr) == old)
  55. *ptr = new;
  56. _atomic_spin_unlock_irqrestore(ptr, flags);
  57. return prev;
  58. }
  59. #endif
  60. unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsigned int new)
  61. {
  62. unsigned long flags;
  63. unsigned int prev;
  64. _atomic_spin_lock_irqsave(ptr, flags);
  65. if ((prev = *ptr) == old)
  66. *ptr = new;
  67. _atomic_spin_unlock_irqrestore(ptr, flags);
  68. return (unsigned long)prev;
  69. }