linux/arch/sparc/include/asm/spinlock_64.h
<<
>>
Prefs
   1/* spinlock.h: 64-bit Sparc spinlock support.
   2 *
   3 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
   4 */
   5
   6#ifndef __SPARC64_SPINLOCK_H
   7#define __SPARC64_SPINLOCK_H
   8
   9#ifndef __ASSEMBLY__
  10
  11/* To get debugging spinlocks which detect and catch
  12 * deadlock situations, set CONFIG_DEBUG_SPINLOCK
  13 * and rebuild your kernel.
  14 */
  15
  16/* Because we play games to save cycles in the non-contention case, we
  17 * need to be extra careful about branch targets into the "spinning"
  18 * code.  They live in their own section, but the newer V9 branches
  19 * have a shorter range than the traditional 32-bit sparc branch
  20 * variants.  The rule is that the branches that go into and out of
  21 * the spinner sections must be pre-V9 branches.
  22 */
  23
  24#define __raw_spin_is_locked(lp)        ((lp)->lock != 0)
  25
  26#define __raw_spin_unlock_wait(lp)      \
  27        do {    rmb();                  \
  28        } while((lp)->lock)
  29
  30static inline void __raw_spin_lock(raw_spinlock_t *lock)
  31{
  32        unsigned long tmp;
  33
  34        __asm__ __volatile__(
  35"1:     ldstub          [%1], %0\n"
  36"       brnz,pn         %0, 2f\n"
  37"        nop\n"
  38"       .subsection     2\n"
  39"2:     ldub            [%1], %0\n"
  40"       brnz,pt         %0, 2b\n"
  41"        nop\n"
  42"       ba,a,pt         %%xcc, 1b\n"
  43"       .previous"
  44        : "=&r" (tmp)
  45        : "r" (lock)
  46        : "memory");
  47}
  48
  49static inline int __raw_spin_trylock(raw_spinlock_t *lock)
  50{
  51        unsigned long result;
  52
  53        __asm__ __volatile__(
  54"       ldstub          [%1], %0\n"
  55        : "=r" (result)
  56        : "r" (lock)
  57        : "memory");
  58
  59        return (result == 0UL);
  60}
  61
  62static inline void __raw_spin_unlock(raw_spinlock_t *lock)
  63{
  64        __asm__ __volatile__(
  65"       stb             %%g0, [%0]"
  66        : /* No outputs */
  67        : "r" (lock)
  68        : "memory");
  69}
  70
  71static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
  72{
  73        unsigned long tmp1, tmp2;
  74
  75        __asm__ __volatile__(
  76"1:     ldstub          [%2], %0\n"
  77"       brnz,pn         %0, 2f\n"
  78"        nop\n"
  79"       .subsection     2\n"
  80"2:     rdpr            %%pil, %1\n"
  81"       wrpr            %3, %%pil\n"
  82"3:     ldub            [%2], %0\n"
  83"       brnz,pt         %0, 3b\n"
  84"        nop\n"
  85"       ba,pt           %%xcc, 1b\n"
  86"        wrpr           %1, %%pil\n"
  87"       .previous"
  88        : "=&r" (tmp1), "=&r" (tmp2)
  89        : "r"(lock), "r"(flags)
  90        : "memory");
  91}
  92
  93/* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
  94
  95static void inline arch_read_lock(raw_rwlock_t *lock)
  96{
  97        unsigned long tmp1, tmp2;
  98
  99        __asm__ __volatile__ (
 100"1:     ldsw            [%2], %0\n"
 101"       brlz,pn         %0, 2f\n"
 102"4:      add            %0, 1, %1\n"
 103"       cas             [%2], %0, %1\n"
 104"       cmp             %0, %1\n"
 105"       bne,pn          %%icc, 1b\n"
 106"        nop\n"
 107"       .subsection     2\n"
 108"2:     ldsw            [%2], %0\n"
 109"       brlz,pt         %0, 2b\n"
 110"        nop\n"
 111"       ba,a,pt         %%xcc, 4b\n"
 112"       .previous"
 113        : "=&r" (tmp1), "=&r" (tmp2)
 114        : "r" (lock)
 115        : "memory");
 116}
 117
 118static int inline arch_read_trylock(raw_rwlock_t *lock)
 119{
 120        int tmp1, tmp2;
 121
 122        __asm__ __volatile__ (
 123"1:     ldsw            [%2], %0\n"
 124"       brlz,a,pn       %0, 2f\n"
 125"        mov            0, %0\n"
 126"       add             %0, 1, %1\n"
 127"       cas             [%2], %0, %1\n"
 128"       cmp             %0, %1\n"
 129"       bne,pn          %%icc, 1b\n"
 130"        mov            1, %0\n"
 131"2:"
 132        : "=&r" (tmp1), "=&r" (tmp2)
 133        : "r" (lock)
 134        : "memory");
 135
 136        return tmp1;
 137}
 138
 139static void inline arch_read_unlock(raw_rwlock_t *lock)
 140{
 141        unsigned long tmp1, tmp2;
 142
 143        __asm__ __volatile__(
 144"1:     lduw    [%2], %0\n"
 145"       sub     %0, 1, %1\n"
 146"       cas     [%2], %0, %1\n"
 147"       cmp     %0, %1\n"
 148"       bne,pn  %%xcc, 1b\n"
 149"        nop"
 150        : "=&r" (tmp1), "=&r" (tmp2)
 151        : "r" (lock)
 152        : "memory");
 153}
 154
 155static void inline arch_write_lock(raw_rwlock_t *lock)
 156{
 157        unsigned long mask, tmp1, tmp2;
 158
 159        mask = 0x80000000UL;
 160
 161        __asm__ __volatile__(
 162"1:     lduw            [%2], %0\n"
 163"       brnz,pn         %0, 2f\n"
 164"4:      or             %0, %3, %1\n"
 165"       cas             [%2], %0, %1\n"
 166"       cmp             %0, %1\n"
 167"       bne,pn          %%icc, 1b\n"
 168"        nop\n"
 169"       .subsection     2\n"
 170"2:     lduw            [%2], %0\n"
 171"       brnz,pt         %0, 2b\n"
 172"        nop\n"
 173"       ba,a,pt         %%xcc, 4b\n"
 174"       .previous"
 175        : "=&r" (tmp1), "=&r" (tmp2)
 176        : "r" (lock), "r" (mask)
 177        : "memory");
 178}
 179
 180static void inline arch_write_unlock(raw_rwlock_t *lock)
 181{
 182        __asm__ __volatile__(
 183"       stw             %%g0, [%0]"
 184        : /* no outputs */
 185        : "r" (lock)
 186        : "memory");
 187}
 188
 189static int inline arch_write_trylock(raw_rwlock_t *lock)
 190{
 191        unsigned long mask, tmp1, tmp2, result;
 192
 193        mask = 0x80000000UL;
 194
 195        __asm__ __volatile__(
 196"       mov             0, %2\n"
 197"1:     lduw            [%3], %0\n"
 198"       brnz,pn         %0, 2f\n"
 199"        or             %0, %4, %1\n"
 200"       cas             [%3], %0, %1\n"
 201"       cmp             %0, %1\n"
 202"       bne,pn          %%icc, 1b\n"
 203"        nop\n"
 204"       mov             1, %2\n"
 205"2:"
 206        : "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
 207        : "r" (lock), "r" (mask)
 208        : "memory");
 209
 210        return result;
 211}
 212
 213#define __raw_read_lock(p)      arch_read_lock(p)
 214#define __raw_read_lock_flags(p, f) arch_read_lock(p)
 215#define __raw_read_trylock(p)   arch_read_trylock(p)
 216#define __raw_read_unlock(p)    arch_read_unlock(p)
 217#define __raw_write_lock(p)     arch_write_lock(p)
 218#define __raw_write_lock_flags(p, f) arch_write_lock(p)
 219#define __raw_write_unlock(p)   arch_write_unlock(p)
 220#define __raw_write_trylock(p)  arch_write_trylock(p)
 221
 222#define __raw_read_can_lock(rw)         (!((rw)->lock & 0x80000000UL))
 223#define __raw_write_can_lock(rw)        (!(rw)->lock)
 224
 225#define _raw_spin_relax(lock)   cpu_relax()
 226#define _raw_read_relax(lock)   cpu_relax()
 227#define _raw_write_relax(lock)  cpu_relax()
 228
 229#endif /* !(__ASSEMBLY__) */
 230
 231#endif /* !(__SPARC64_SPINLOCK_H) */
 232