Logo Search packages:      
Sourcecode: linux version File versions  Download package

spinlock_64.h

/* spinlock.h: 64-bit Sparc spinlock support.
 *
 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
 */

#ifndef __SPARC64_SPINLOCK_H
#define __SPARC64_SPINLOCK_H

#include <linux/threads.h>    /* For NR_CPUS */

#ifndef __ASSEMBLY__

/* To get debugging spinlocks which detect and catch
 * deadlock situations, set CONFIG_DEBUG_SPINLOCK
 * and rebuild your kernel.
 */

/* All of these locking primitives are expected to work properly
 * even in an RMO memory model, which currently is what the kernel
 * runs in.
 *
 * There is another issue.  Because we play games to save cycles
 * in the non-contention case, we need to be extra careful about
 * branch targets into the "spinning" code.  They live in their
 * own section, but the newer V9 branches have a shorter range
 * than the traditional 32-bit sparc branch variants.  The rule
 * is that the branches that go into and out of the spinner sections
 * must be pre-V9 branches.
 */

#define __raw_spin_is_locked(lp)    ((lp)->lock != 0)

#define __raw_spin_unlock_wait(lp)  \
      do {  rmb();                  \
      } while((lp)->lock)

static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
      unsigned long tmp;

      __asm__ __volatile__(
"1:   ldstub            [%1], %0\n"
"     membar            #StoreLoad | #StoreStore\n"
"     brnz,pn           %0, 2f\n"
"      nop\n"
"     .subsection 2\n"
"2:   ldub        [%1], %0\n"
"     membar            #LoadLoad\n"
"     brnz,pt           %0, 2b\n"
"      nop\n"
"     ba,a,pt           %%xcc, 1b\n"
"     .previous"
      : "=&r" (tmp)
      : "r" (lock)
      : "memory");
}

static inline int __raw_spin_trylock(raw_spinlock_t *lock)
{
      unsigned long result;

      __asm__ __volatile__(
"     ldstub            [%1], %0\n"
"     membar            #StoreLoad | #StoreStore"
      : "=r" (result)
      : "r" (lock)
      : "memory");

      return (result == 0UL);
}

static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
      __asm__ __volatile__(
"     membar            #StoreStore | #LoadStore\n"
"     stb         %%g0, [%0]"
      : /* No outputs */
      : "r" (lock)
      : "memory");
}

static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
{
      unsigned long tmp1, tmp2;

      __asm__ __volatile__(
"1:   ldstub            [%2], %0\n"
"     membar            #StoreLoad | #StoreStore\n"
"     brnz,pn           %0, 2f\n"
"      nop\n"
"     .subsection 2\n"
"2:   rdpr        %%pil, %1\n"
"     wrpr        %3, %%pil\n"
"3:   ldub        [%2], %0\n"
"     membar            #LoadLoad\n"
"     brnz,pt           %0, 3b\n"
"      nop\n"
"     ba,pt       %%xcc, 1b\n"
"      wrpr       %1, %%pil\n"
"     .previous"
      : "=&r" (tmp1), "=&r" (tmp2)
      : "r"(lock), "r"(flags)
      : "memory");
}

/* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */

static void inline __read_lock(raw_rwlock_t *lock)
{
      unsigned long tmp1, tmp2;

      __asm__ __volatile__ (
"1:   ldsw        [%2], %0\n"
"     brlz,pn           %0, 2f\n"
"4:    add        %0, 1, %1\n"
"     cas         [%2], %0, %1\n"
"     cmp         %0, %1\n"
"     membar            #StoreLoad | #StoreStore\n"
"     bne,pn            %%icc, 1b\n"
"      nop\n"
"     .subsection 2\n"
"2:   ldsw        [%2], %0\n"
"     membar            #LoadLoad\n"
"     brlz,pt           %0, 2b\n"
"      nop\n"
"     ba,a,pt           %%xcc, 4b\n"
"     .previous"
      : "=&r" (tmp1), "=&r" (tmp2)
      : "r" (lock)
      : "memory");
}

static int inline __read_trylock(raw_rwlock_t *lock)
{
      int tmp1, tmp2;

      __asm__ __volatile__ (
"1:   ldsw        [%2], %0\n"
"     brlz,a,pn   %0, 2f\n"
"      mov        0, %0\n"
"     add         %0, 1, %1\n"
"     cas         [%2], %0, %1\n"
"     cmp         %0, %1\n"
"     membar            #StoreLoad | #StoreStore\n"
"     bne,pn            %%icc, 1b\n"
"      mov        1, %0\n"
"2:"
      : "=&r" (tmp1), "=&r" (tmp2)
      : "r" (lock)
      : "memory");

      return tmp1;
}

static void inline __read_unlock(raw_rwlock_t *lock)
{
      unsigned long tmp1, tmp2;

      __asm__ __volatile__(
"     membar      #StoreLoad | #LoadLoad\n"
"1:   lduw  [%2], %0\n"
"     sub   %0, 1, %1\n"
"     cas   [%2], %0, %1\n"
"     cmp   %0, %1\n"
"     bne,pn      %%xcc, 1b\n"
"      nop"
      : "=&r" (tmp1), "=&r" (tmp2)
      : "r" (lock)
      : "memory");
}

static void inline __write_lock(raw_rwlock_t *lock)
{
      unsigned long mask, tmp1, tmp2;

      mask = 0x80000000UL;

      __asm__ __volatile__(
"1:   lduw        [%2], %0\n"
"     brnz,pn           %0, 2f\n"
"4:    or         %0, %3, %1\n"
"     cas         [%2], %0, %1\n"
"     cmp         %0, %1\n"
"     membar            #StoreLoad | #StoreStore\n"
"     bne,pn            %%icc, 1b\n"
"      nop\n"
"     .subsection 2\n"
"2:   lduw        [%2], %0\n"
"     membar            #LoadLoad\n"
"     brnz,pt           %0, 2b\n"
"      nop\n"
"     ba,a,pt           %%xcc, 4b\n"
"     .previous"
      : "=&r" (tmp1), "=&r" (tmp2)
      : "r" (lock), "r" (mask)
      : "memory");
}

static void inline __write_unlock(raw_rwlock_t *lock)
{
      __asm__ __volatile__(
"     membar            #LoadStore | #StoreStore\n"
"     stw         %%g0, [%0]"
      : /* no outputs */
      : "r" (lock)
      : "memory");
}

static int inline __write_trylock(raw_rwlock_t *lock)
{
      unsigned long mask, tmp1, tmp2, result;

      mask = 0x80000000UL;

      __asm__ __volatile__(
"     mov         0, %2\n"
"1:   lduw        [%3], %0\n"
"     brnz,pn           %0, 2f\n"
"      or         %0, %4, %1\n"
"     cas         [%3], %0, %1\n"
"     cmp         %0, %1\n"
"     membar            #StoreLoad | #StoreStore\n"
"     bne,pn            %%icc, 1b\n"
"      nop\n"
"     mov         1, %2\n"
"2:"
      : "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
      : "r" (lock), "r" (mask)
      : "memory");

      return result;
}

#define __raw_read_lock(p)    __read_lock(p)
#define __raw_read_trylock(p) __read_trylock(p)
#define __raw_read_unlock(p)  __read_unlock(p)
#define __raw_write_lock(p)   __write_lock(p)
#define __raw_write_unlock(p) __write_unlock(p)
#define __raw_write_trylock(p)      __write_trylock(p)

#define __raw_read_can_lock(rw)           (!((rw)->lock & 0x80000000UL))
#define __raw_write_can_lock(rw)    (!(rw)->lock)

#define _raw_spin_relax(lock) cpu_relax()
#define _raw_read_relax(lock) cpu_relax()
#define _raw_write_relax(lock)      cpu_relax()

#endif /* !(__ASSEMBLY__) */

#endif /* !(__SPARC64_SPINLOCK_H) */

Generated by  Doxygen 1.6.0   Back to index