cmpxchg.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* MN10300 Atomic xchg/cmpxchg operations
  2. *
  3. * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public Licence
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the Licence, or (at your option) any later version.
  10. */
  11. #ifndef _ASM_CMPXCHG_H
  12. #define _ASM_CMPXCHG_H
  13. #include <asm/irqflags.h>
  14. #ifdef CONFIG_SMP
  15. #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
  16. static inline
  17. unsigned long __xchg(volatile unsigned long *m, unsigned long val)
  18. {
  19. unsigned long status;
  20. unsigned long oldval;
  21. asm volatile(
  22. "1: mov %4,(_AAR,%3) \n"
  23. " mov (_ADR,%3),%1 \n"
  24. " mov %5,(_ADR,%3) \n"
  25. " mov (_ADR,%3),%0 \n" /* flush */
  26. " mov (_ASR,%3),%0 \n"
  27. " or %0,%0 \n"
  28. " bne 1b \n"
  29. : "=&r"(status), "=&r"(oldval), "=m"(*m)
  30. : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m), "r"(val)
  31. : "memory", "cc");
  32. return oldval;
  33. }
  34. static inline unsigned long __cmpxchg(volatile unsigned long *m,
  35. unsigned long old, unsigned long new)
  36. {
  37. unsigned long status;
  38. unsigned long oldval;
  39. asm volatile(
  40. "1: mov %4,(_AAR,%3) \n"
  41. " mov (_ADR,%3),%1 \n"
  42. " cmp %5,%1 \n"
  43. " bne 2f \n"
  44. " mov %6,(_ADR,%3) \n"
  45. "2: mov (_ADR,%3),%0 \n" /* flush */
  46. " mov (_ASR,%3),%0 \n"
  47. " or %0,%0 \n"
  48. " bne 1b \n"
  49. : "=&r"(status), "=&r"(oldval), "=m"(*m)
  50. : "a"(ATOMIC_OPS_BASE_ADDR), "r"(m),
  51. "r"(old), "r"(new)
  52. : "memory", "cc");
  53. return oldval;
  54. }
  55. #else /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
  56. #error "No SMP atomic operation support!"
  57. #endif /* CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT */
  58. #else /* CONFIG_SMP */
  59. /*
  60. * Emulate xchg for non-SMP MN10300
  61. */
  62. struct __xchg_dummy { unsigned long a[100]; };
  63. #define __xg(x) ((struct __xchg_dummy *)(x))
  64. static inline
  65. unsigned long __xchg(volatile unsigned long *m, unsigned long val)
  66. {
  67. unsigned long oldval;
  68. unsigned long flags;
  69. flags = arch_local_cli_save();
  70. oldval = *m;
  71. *m = val;
  72. arch_local_irq_restore(flags);
  73. return oldval;
  74. }
  75. /*
  76. * Emulate cmpxchg for non-SMP MN10300
  77. */
  78. static inline unsigned long __cmpxchg(volatile unsigned long *m,
  79. unsigned long old, unsigned long new)
  80. {
  81. unsigned long oldval;
  82. unsigned long flags;
  83. flags = arch_local_cli_save();
  84. oldval = *m;
  85. if (oldval == old)
  86. *m = new;
  87. arch_local_irq_restore(flags);
  88. return oldval;
  89. }
  90. #endif /* CONFIG_SMP */
  91. #define xchg(ptr, v) \
  92. ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr), \
  93. (unsigned long)(v)))
  94. #define cmpxchg(ptr, o, n) \
  95. ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
  96. (unsigned long)(o), \
  97. (unsigned long)(n)))
  98. #endif /* _ASM_CMPXCHG_H */