home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-m32r / spinlock.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  7.4 KB  |  313 lines

  1. #ifndef _ASM_M32R_SPINLOCK_H
  2. #define _ASM_M32R_SPINLOCK_H
  3.  
  4. /*
  5.  *  linux/include/asm-m32r/spinlock.h
  6.  *
  7.  *  M32R version:
  8.  *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
  9.  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  10.  */
  11.  
  12. #include <linux/compiler.h>
  13. #include <asm/atomic.h>
  14. #include <asm/page.h>
  15.  
  16. /*
  17.  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  18.  *
  19.  * (the type definitions are in asm/spinlock_types.h)
  20.  *
  21.  * Simple spin lock operations.  There are two variants, one clears IRQ's
  22.  * on the local processor, one does not.
  23.  *
  24.  * We make no fairness assumptions. They have a cost.
  25.  */
  26.  
  27. #define __raw_spin_is_locked(x)        (*(volatile int *)(&(x)->slock) <= 0)
  28. #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
  29. #define __raw_spin_unlock_wait(x) \
  30.         do { cpu_relax(); } while (__raw_spin_is_locked(x))
  31.  
  32. /**
  33.  * __raw_spin_trylock - Try spin lock and return a result
  34.  * @lock: Pointer to the lock variable
  35.  *
  36.  * __raw_spin_trylock() tries to get the lock and returns a result.
  37.  * On the m32r, the result value is 1 (= Success) or 0 (= Failure).
  38.  */
  39. static inline int __raw_spin_trylock(raw_spinlock_t *lock)
  40. {
  41.     int oldval;
  42.     unsigned long tmp1, tmp2;
  43.  
  44.     /*
  45.      * lock->slock :  =1 : unlock
  46.      *             : <=0 : lock
  47.      * {
  48.      *   oldval = lock->slock; <--+ need atomic operation
  49.      *   lock->slock = 0;      <--+
  50.      * }
  51.      */
  52.     __asm__ __volatile__ (
  53.         "# __raw_spin_trylock        \n\t"
  54.         "ldi    %1, #0;            \n\t"
  55.         "mvfc    %2, psw;        \n\t"
  56.         "clrpsw    #0x40 -> nop;        \n\t"
  57.         DCACHE_CLEAR("%0", "r6", "%3")
  58.         "lock    %0, @%3;        \n\t"
  59.         "unlock    %1, @%3;        \n\t"
  60.         "mvtc    %2, psw;        \n\t"
  61.         : "=&r" (oldval), "=&r" (tmp1), "=&r" (tmp2)
  62.         : "r" (&lock->slock)
  63.         : "memory"
  64. #ifdef CONFIG_CHIP_M32700_TS1
  65.         , "r6"
  66. #endif    /* CONFIG_CHIP_M32700_TS1 */
  67.     );
  68.  
  69.     return (oldval > 0);
  70. }
  71.  
  72. static inline void __raw_spin_lock(raw_spinlock_t *lock)
  73. {
  74.     unsigned long tmp0, tmp1;
  75.  
  76.     /*
  77.      * lock->slock :  =1 : unlock
  78.      *             : <=0 : lock
  79.      *
  80.      * for ( ; ; ) {
  81.      *   lock->slock -= 1;  <-- need atomic operation
  82.      *   if (lock->slock == 0) break;
  83.      *   for ( ; lock->slock <= 0 ; );
  84.      * }
  85.      */
  86.     __asm__ __volatile__ (
  87.         "# __raw_spin_lock        \n\t"
  88.         ".fillinsn            \n"
  89.         "1:                \n\t"
  90.         "mvfc    %1, psw;        \n\t"
  91.         "clrpsw    #0x40 -> nop;        \n\t"
  92.         DCACHE_CLEAR("%0", "r6", "%2")
  93.         "lock    %0, @%2;        \n\t"
  94.         "addi    %0, #-1;        \n\t"
  95.         "unlock    %0, @%2;        \n\t"
  96.         "mvtc    %1, psw;        \n\t"
  97.         "bltz    %0, 2f;            \n\t"
  98.         LOCK_SECTION_START(".balign 4 \n\t")
  99.         ".fillinsn            \n"
  100.         "2:                \n\t"
  101.         "ld    %0, @%2;        \n\t"
  102.         "bgtz    %0, 1b;            \n\t"
  103.         "bra    2b;            \n\t"
  104.         LOCK_SECTION_END
  105.         : "=&r" (tmp0), "=&r" (tmp1)
  106.         : "r" (&lock->slock)
  107.         : "memory"
  108. #ifdef CONFIG_CHIP_M32700_TS1
  109.         , "r6"
  110. #endif    /* CONFIG_CHIP_M32700_TS1 */
  111.     );
  112. }
  113.  
  114. static inline void __raw_spin_unlock(raw_spinlock_t *lock)
  115. {
  116.     mb();
  117.     lock->slock = 1;
  118. }
  119.  
  120. /*
  121.  * Read-write spinlocks, allowing multiple readers
  122.  * but only one writer.
  123.  *
  124.  * NOTE! it is quite common to have readers in interrupts
  125.  * but no interrupt writers. For those circumstances we
  126.  * can "mix" irq-safe locks - any writer needs to get a
  127.  * irq-safe write-lock, but readers can get non-irqsafe
  128.  * read-locks.
  129.  *
  130.  * On x86, we implement read-write locks as a 32-bit counter
  131.  * with the high bit (sign) being the "contended" bit.
  132.  *
  133.  * The inline assembly is non-obvious. Think about it.
  134.  *
  135.  * Changed to use the same technique as rw semaphores.  See
  136.  * semaphore.h for details.  -ben
  137.  */
  138.  
  139. /**
  140.  * read_can_lock - would read_trylock() succeed?
  141.  * @lock: the rwlock in question.
  142.  */
  143. #define __raw_read_can_lock(x) ((int)(x)->lock > 0)
  144.  
  145. /**
  146.  * write_can_lock - would write_trylock() succeed?
  147.  * @lock: the rwlock in question.
  148.  */
  149. #define __raw_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
  150.  
  151. static inline void __raw_read_lock(raw_rwlock_t *rw)
  152. {
  153.     unsigned long tmp0, tmp1;
  154.  
  155.     /*
  156.      * rw->lock :  >0 : unlock
  157.      *          : <=0 : lock
  158.      *
  159.      * for ( ; ; ) {
  160.      *   rw->lock -= 1;  <-- need atomic operation
  161.      *   if (rw->lock >= 0) break;
  162.      *   rw->lock += 1;  <-- need atomic operation
  163.      *   for ( ; rw->lock <= 0 ; );
  164.      * }
  165.      */
  166.     __asm__ __volatile__ (
  167.         "# read_lock            \n\t"
  168.         ".fillinsn            \n"
  169.         "1:                \n\t"
  170.         "mvfc    %1, psw;        \n\t"
  171.         "clrpsw    #0x40 -> nop;        \n\t"
  172.         DCACHE_CLEAR("%0", "r6", "%2")
  173.         "lock    %0, @%2;        \n\t"
  174.         "addi    %0, #-1;        \n\t"
  175.         "unlock    %0, @%2;        \n\t"
  176.         "mvtc    %1, psw;        \n\t"
  177.         "bltz    %0, 2f;            \n\t"
  178.         LOCK_SECTION_START(".balign 4 \n\t")
  179.         ".fillinsn            \n"
  180.         "2:                \n\t"
  181.         "clrpsw    #0x40 -> nop;        \n\t"
  182.         DCACHE_CLEAR("%0", "r6", "%2")
  183.         "lock    %0, @%2;        \n\t"
  184.         "addi    %0, #1;            \n\t"
  185.         "unlock    %0, @%2;        \n\t"
  186.         "mvtc    %1, psw;        \n\t"
  187.         ".fillinsn            \n"
  188.         "3:                \n\t"
  189.         "ld    %0, @%2;        \n\t"
  190.         "bgtz    %0, 1b;            \n\t"
  191.         "bra    3b;            \n\t"
  192.         LOCK_SECTION_END
  193.         : "=&r" (tmp0), "=&r" (tmp1)
  194.         : "r" (&rw->lock)
  195.         : "memory"
  196. #ifdef CONFIG_CHIP_M32700_TS1
  197.         , "r6"
  198. #endif    /* CONFIG_CHIP_M32700_TS1 */
  199.     );
  200. }
  201.  
  202. static inline void __raw_write_lock(raw_rwlock_t *rw)
  203. {
  204.     unsigned long tmp0, tmp1, tmp2;
  205.  
  206.     /*
  207.      * rw->lock :  =RW_LOCK_BIAS_STR : unlock
  208.      *          : !=RW_LOCK_BIAS_STR : lock
  209.      *
  210.      * for ( ; ; ) {
  211.      *   rw->lock -= RW_LOCK_BIAS_STR;  <-- need atomic operation
  212.      *   if (rw->lock == 0) break;
  213.      *   rw->lock += RW_LOCK_BIAS_STR;  <-- need atomic operation
  214.      *   for ( ; rw->lock != RW_LOCK_BIAS_STR ; ) ;
  215.      * }
  216.      */
  217.     __asm__ __volatile__ (
  218.         "# write_lock                    \n\t"
  219.         "seth    %1, #high(" RW_LOCK_BIAS_STR ");    \n\t"
  220.         "or3    %1, %1, #low(" RW_LOCK_BIAS_STR ");    \n\t"
  221.         ".fillinsn                    \n"
  222.         "1:                        \n\t"
  223.         "mvfc    %2, psw;                \n\t"
  224.         "clrpsw    #0x40 -> nop;                \n\t"
  225.         DCACHE_CLEAR("%0", "r7", "%3")
  226.         "lock    %0, @%3;                \n\t"
  227.         "sub    %0, %1;                    \n\t"
  228.         "unlock    %0, @%3;                \n\t"
  229.         "mvtc    %2, psw;                \n\t"
  230.         "bnez    %0, 2f;                    \n\t"
  231.         LOCK_SECTION_START(".balign 4 \n\t")
  232.         ".fillinsn                    \n"
  233.         "2:                        \n\t"
  234.         "clrpsw    #0x40 -> nop;                \n\t"
  235.         DCACHE_CLEAR("%0", "r7", "%3")
  236.         "lock    %0, @%3;                \n\t"
  237.         "add    %0, %1;                    \n\t"
  238.         "unlock    %0, @%3;                \n\t"
  239.         "mvtc    %2, psw;                \n\t"
  240.         ".fillinsn                    \n"
  241.         "3:                        \n\t"
  242.         "ld    %0, @%3;                \n\t"
  243.         "beq    %0, %1, 1b;                \n\t"
  244.         "bra    3b;                    \n\t"
  245.         LOCK_SECTION_END
  246.         : "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
  247.         : "r" (&rw->lock)
  248.         : "memory"
  249. #ifdef CONFIG_CHIP_M32700_TS1
  250.         , "r7"
  251. #endif    /* CONFIG_CHIP_M32700_TS1 */
  252.     );
  253. }
  254.  
  255. static inline void __raw_read_unlock(raw_rwlock_t *rw)
  256. {
  257.     unsigned long tmp0, tmp1;
  258.  
  259.     __asm__ __volatile__ (
  260.         "# read_unlock            \n\t"
  261.         "mvfc    %1, psw;        \n\t"
  262.         "clrpsw    #0x40 -> nop;        \n\t"
  263.         DCACHE_CLEAR("%0", "r6", "%2")
  264.         "lock    %0, @%2;        \n\t"
  265.         "addi    %0, #1;            \n\t"
  266.         "unlock    %0, @%2;        \n\t"
  267.         "mvtc    %1, psw;        \n\t"
  268.         : "=&r" (tmp0), "=&r" (tmp1)
  269.         : "r" (&rw->lock)
  270.         : "memory"
  271. #ifdef CONFIG_CHIP_M32700_TS1
  272.         , "r6"
  273. #endif    /* CONFIG_CHIP_M32700_TS1 */
  274.     );
  275. }
  276.  
  277. static inline void __raw_write_unlock(raw_rwlock_t *rw)
  278. {
  279.     unsigned long tmp0, tmp1, tmp2;
  280.  
  281.     __asm__ __volatile__ (
  282.         "# write_unlock                    \n\t"
  283.         "seth    %1, #high(" RW_LOCK_BIAS_STR ");    \n\t"
  284.         "or3    %1, %1, #low(" RW_LOCK_BIAS_STR ");    \n\t"
  285.         "mvfc    %2, psw;                \n\t"
  286.         "clrpsw    #0x40 -> nop;                \n\t"
  287.         DCACHE_CLEAR("%0", "r7", "%3")
  288.         "lock    %0, @%3;                \n\t"
  289.         "add    %0, %1;                    \n\t"
  290.         "unlock    %0, @%3;                \n\t"
  291.         "mvtc    %2, psw;                \n\t"
  292.         : "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
  293.         : "r" (&rw->lock)
  294.         : "memory"
  295. #ifdef CONFIG_CHIP_M32700_TS1
  296.         , "r7"
  297. #endif    /* CONFIG_CHIP_M32700_TS1 */
  298.     );
  299. }
  300.  
  301. #define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
  302.  
  303. static inline int __raw_write_trylock(raw_rwlock_t *lock)
  304. {
  305.     atomic_t *count = (atomic_t *)lock;
  306.     if (atomic_sub_and_test(RW_LOCK_BIAS, count))
  307.         return 1;
  308.     atomic_add(RW_LOCK_BIAS, count);
  309.     return 0;
  310. }
  311.  
  312. #endif    /* _ASM_M32R_SPINLOCK_H */
  313.