linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / include / asm-m32r / semaphore.h
index 41e45d7..bf447c5 100644 (file)
@@ -9,9 +9,10 @@
  * SMP- and interrupt-safe semaphores..
  *
  * Copyright (C) 1996  Linus Torvalds
- * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  */
 
+#include <linux/config.h>
 #include <linux/wait.h>
 #include <linux/rwsem.h>
 #include <asm/assembler.h>
@@ -76,8 +77,27 @@ asmlinkage void __up(struct semaphore * sem);
  */
 static inline void down(struct semaphore * sem)
 {
+       unsigned long flags;
+       long count;
+
        might_sleep();
-       if (unlikely(atomic_dec_return(&sem->count) < 0))
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# down                         \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               M32R_LOCK" %0, @%1;             \n\t"
+               "addi   %0, #-1;                \n\t"
+               M32R_UNLOCK" %0, @%1;           \n\t"
+               : "=&r" (count)
+               : "r" (&sem->count)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       if (unlikely(count < 0))
                __down(sem);
 }
 
@@ -87,10 +107,28 @@ static inline void down(struct semaphore * sem)
  */
 static inline int down_interruptible(struct semaphore * sem)
 {
+       unsigned long flags;
+       long count;
        int result = 0;
 
        might_sleep();
-       if (unlikely(atomic_dec_return(&sem->count) < 0))
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# down_interruptible           \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               M32R_LOCK" %0, @%1;             \n\t"
+               "addi   %0, #-1;                \n\t"
+               M32R_UNLOCK" %0, @%1;           \n\t"
+               : "=&r" (count)
+               : "r" (&sem->count)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       if (unlikely(count < 0))
                result = __down_interruptible(sem);
 
        return result;
@@ -136,7 +174,26 @@ static inline int down_trylock(struct semaphore * sem)
  */
 static inline void up(struct semaphore * sem)
 {
-       if (unlikely(atomic_inc_return(&sem->count) <= 0))
+       unsigned long flags;
+       long count;
+
+       local_irq_save(flags);
+       __asm__ __volatile__ (
+               "# up                           \n\t"
+               DCACHE_CLEAR("%0", "r4", "%1")
+               M32R_LOCK" %0, @%1;             \n\t"
+               "addi   %0, #1;                 \n\t"
+               M32R_UNLOCK" %0, @%1;           \n\t"
+               : "=&r" (count)
+               : "r" (&sem->count)
+               : "memory"
+#ifdef CONFIG_CHIP_M32700_TS1
+               , "r4"
+#endif /* CONFIG_CHIP_M32700_TS1 */
+       );
+       local_irq_restore(flags);
+
+       if (unlikely(count <= 0))
                __up(sem);
 }