home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / mips / include / asm / cmpxchg.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  3.1 KB  |  125 lines

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (C) 2003, 06, 07 by Ralf Baechle (ralf@linux-mips.org)
  7.  */
  8. #ifndef __ASM_CMPXCHG_H
  9. #define __ASM_CMPXCHG_H
  10.  
  11. #include <linux/irqflags.h>
  12.  
  13. #define __HAVE_ARCH_CMPXCHG 1
  14.  
  15. #define __cmpxchg_asm(ld, st, m, old, new)                \
  16. ({                                    \
  17.     __typeof(*(m)) __ret;                        \
  18.                                     \
  19.     if (cpu_has_llsc && R10000_LLSC_WAR) {                \
  20.         __asm__ __volatile__(                    \
  21.         "    .set    push                \n"    \
  22.         "    .set    noat                \n"    \
  23.         "    .set    mips3                \n"    \
  24.         "1:    " ld "    %0, %2        # __cmpxchg_asm    \n"    \
  25.         "    bne    %0, %z3, 2f            \n"    \
  26.         "    .set    mips0                \n"    \
  27.         "    move    $1, %z4                \n"    \
  28.         "    .set    mips3                \n"    \
  29.         "    " st "    $1, %1                \n"    \
  30.         "    beqzl    $1, 1b                \n"    \
  31.         "2:                        \n"    \
  32.         "    .set    pop                \n"    \
  33.         : "=&r" (__ret), "=R" (*m)                \
  34.         : "R" (*m), "Jr" (old), "Jr" (new)            \
  35.         : "memory");                        \
  36.     } else if (cpu_has_llsc) {                    \
  37.         __asm__ __volatile__(                    \
  38.         "    .set    push                \n"    \
  39.         "    .set    noat                \n"    \
  40.         "    .set    mips3                \n"    \
  41.         "1:    " ld "    %0, %2        # __cmpxchg_asm    \n"    \
  42.         "    bne    %0, %z3, 2f            \n"    \
  43.         "    .set    mips0                \n"    \
  44.         "    move    $1, %z4                \n"    \
  45.         "    .set    mips3                \n"    \
  46.         "    " st "    $1, %1                \n"    \
  47.         "    beqz    $1, 3f                \n"    \
  48.         "2:                        \n"    \
  49.         "    .subsection 2                \n"    \
  50.         "3:    b    1b                \n"    \
  51.         "    .previous                \n"    \
  52.         "    .set    pop                \n"    \
  53.         : "=&r" (__ret), "=R" (*m)                \
  54.         : "R" (*m), "Jr" (old), "Jr" (new)            \
  55.         : "memory");                        \
  56.     } else {                            \
  57.         unsigned long __flags;                    \
  58.                                     \
  59.         raw_local_irq_save(__flags);                \
  60.         __ret = *m;                        \
  61.         if (__ret == old)                    \
  62.             *m = new;                    \
  63.         raw_local_irq_restore(__flags);                \
  64.     }                                \
  65.                                     \
  66.     __ret;                                \
  67. })
  68.  
  69. /*
  70.  * This function doesn't exist, so you'll get a linker error
  71.  * if something tries to do an invalid cmpxchg().
  72.  */
  73. extern void __cmpxchg_called_with_bad_pointer(void);
  74.  
  75. #define __cmpxchg(ptr, old, new, barrier)                \
  76. ({                                    \
  77.     __typeof__(ptr) __ptr = (ptr);                    \
  78.     __typeof__(*(ptr)) __old = (old);                \
  79.     __typeof__(*(ptr)) __new = (new);                \
  80.     __typeof__(*(ptr)) __res = 0;                    \
  81.                                     \
  82.     barrier;                            \
  83.                                     \
  84.     switch (sizeof(*(__ptr))) {                    \
  85.     case 4:                                \
  86.         __res = __cmpxchg_asm("ll", "sc", __ptr, __old, __new);    \
  87.         break;                            \
  88.     case 8:                                \
  89.         if (sizeof(long) == 8) {                \
  90.             __res = __cmpxchg_asm("lld", "scd", __ptr,    \
  91.                        __old, __new);        \
  92.             break;                        \
  93.         }                            \
  94.     default:                            \
  95.         __cmpxchg_called_with_bad_pointer();            \
  96.         break;                            \
  97.     }                                \
  98.                                     \
  99.     barrier;                            \
  100.                                     \
  101.     __res;                                \
  102. })
  103.  
  104. #define cmpxchg(ptr, old, new)        __cmpxchg(ptr, old, new, smp_llsc_mb())
  105. #define cmpxchg_local(ptr, old, new)    __cmpxchg(ptr, old, new, )
  106.  
  107. #define cmpxchg64(ptr, o, n)                        \
  108.   ({                                    \
  109.     BUILD_BUG_ON(sizeof(*(ptr)) != 8);                \
  110.     cmpxchg((ptr), (o), (n));                    \
  111.   })
  112.  
  113. #ifdef CONFIG_64BIT
  114. #define cmpxchg64_local(ptr, o, n)                    \
  115.   ({                                    \
  116.     BUILD_BUG_ON(sizeof(*(ptr)) != 8);                \
  117.     cmpxchg_local((ptr), (o), (n));                    \
  118.   })
  119. #else
  120. #include <asm-generic/cmpxchg-local.h>
  121. #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
  122. #endif
  123.  
  124. #endif /* __ASM_CMPXCHG_H */
  125.