linux/arch/sh/include/asm/spinlock.h
<<
>>
Prefs
   1/*
   2 * include/asm-sh/spinlock.h
   3 *
   4 * Copyright (C) 2002, 2003 Paul Mundt
   5 * Copyright (C) 2006, 2007 Akio Idehara
   6 *
   7 * This file is subject to the terms and conditions of the GNU General Public
   8 * License.  See the file "COPYING" in the main directory of this archive
   9 * for more details.
  10 */
  11#ifndef __ASM_SH_SPINLOCK_H
  12#define __ASM_SH_SPINLOCK_H
  13
  14/*
  15 * The only locking implemented here uses SH-4A opcodes. For others,
  16 * split this out as per atomic-*.h.
  17 */
  18#ifndef CONFIG_CPU_SH4A
  19#error "Need movli.l/movco.l for spinlocks"
  20#endif
  21
  22/*
  23 * Your basic SMP spinlocks, allowing only a single CPU anywhere
  24 */
  25
  26#define arch_spin_is_locked(x)          ((x)->lock <= 0)
  27#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
  28#define arch_spin_unlock_wait(x) \
  29        do { while (arch_spin_is_locked(x)) cpu_relax(); } while (0)
  30
  31/*
  32 * Simple spin lock operations.  There are two variants, one clears IRQ's
  33 * on the local processor, one does not.
  34 *
  35 * We make no fairness assumptions.  They have a cost.
  36 */
  37static inline void arch_spin_lock(arch_spinlock_t *lock)
  38{
  39        unsigned long tmp;
  40        unsigned long oldval;
  41
  42        __asm__ __volatile__ (
  43                "1:                                             \n\t"
  44                "movli.l        @%2, %0 ! arch_spin_lock        \n\t"
  45                "mov            %0, %1                          \n\t"
  46                "mov            #0, %0                          \n\t"
  47                "movco.l        %0, @%2                         \n\t"
  48                "bf             1b                              \n\t"
  49                "cmp/pl         %1                              \n\t"
  50                "bf             1b                              \n\t"
  51                : "=&z" (tmp), "=&r" (oldval)
  52                : "r" (&lock->lock)
  53                : "t", "memory"
  54        );
  55}
  56
  57static inline void arch_spin_unlock(arch_spinlock_t *lock)
  58{
  59        unsigned long tmp;
  60
  61        __asm__ __volatile__ (
  62                "mov            #1, %0 ! arch_spin_unlock       \n\t"
  63                "mov.l          %0, @%1                         \n\t"
  64                : "=&z" (tmp)
  65                : "r" (&lock->lock)
  66                : "t", "memory"
  67        );
  68}
  69
  70static inline int arch_spin_trylock(arch_spinlock_t *lock)
  71{
  72        unsigned long tmp, oldval;
  73
  74        __asm__ __volatile__ (
  75                "1:                                             \n\t"
  76                "movli.l        @%2, %0 ! arch_spin_trylock     \n\t"
  77                "mov            %0, %1                          \n\t"
  78                "mov            #0, %0                          \n\t"
  79                "movco.l        %0, @%2                         \n\t"
  80                "bf             1b                              \n\t"
  81                "synco                                          \n\t"
  82                : "=&z" (tmp), "=&r" (oldval)
  83                : "r" (&lock->lock)
  84                : "t", "memory"
  85        );
  86
  87        return oldval;
  88}
  89
  90/*
  91 * Read-write spinlocks, allowing multiple readers but only one writer.
  92 *
  93 * NOTE! it is quite common to have readers in interrupts but no interrupt
  94 * writers. For those circumstances we can "mix" irq-safe locks - any writer
  95 * needs to get a irq-safe write-lock, but readers can get non-irqsafe
  96 * read-locks.
  97 */
  98
  99/**
 100 * read_can_lock - would read_trylock() succeed?
 101 * @lock: the rwlock in question.
 102 */
 103#define arch_read_can_lock(x)   ((x)->lock > 0)
 104
 105/**
 106 * write_can_lock - would write_trylock() succeed?
 107 * @lock: the rwlock in question.
 108 */
 109#define arch_write_can_lock(x)  ((x)->lock == RW_LOCK_BIAS)
 110
 111static inline void arch_read_lock(arch_rwlock_t *rw)
 112{
 113        unsigned long tmp;
 114
 115        __asm__ __volatile__ (
 116                "1:                                             \n\t"
 117                "movli.l        @%1, %0 ! arch_read_lock        \n\t"
 118                "cmp/pl         %0                              \n\t"
 119                "bf             1b                              \n\t"
 120                "add            #-1, %0                         \n\t"
 121                "movco.l        %0, @%1                         \n\t"
 122                "bf             1b                              \n\t"
 123                : "=&z" (tmp)
 124                : "r" (&rw->lock)
 125                : "t", "memory"
 126        );
 127}
 128
 129static inline void arch_read_unlock(arch_rwlock_t *rw)
 130{
 131        unsigned long tmp;
 132
 133        __asm__ __volatile__ (
 134                "1:                                             \n\t"
 135                "movli.l        @%1, %0 ! arch_read_unlock      \n\t"
 136                "add            #1, %0                          \n\t"
 137                "movco.l        %0, @%1                         \n\t"
 138                "bf             1b                              \n\t"
 139                : "=&z" (tmp)
 140                : "r" (&rw->lock)
 141                : "t", "memory"
 142        );
 143}
 144
 145static inline void arch_write_lock(arch_rwlock_t *rw)
 146{
 147        unsigned long tmp;
 148
 149        __asm__ __volatile__ (
 150                "1:                                             \n\t"
 151                "movli.l        @%1, %0 ! arch_write_lock       \n\t"
 152                "cmp/hs         %2, %0                          \n\t"
 153                "bf             1b                              \n\t"
 154                "sub            %2, %0                          \n\t"
 155                "movco.l        %0, @%1                         \n\t"
 156                "bf             1b                              \n\t"
 157                : "=&z" (tmp)
 158                : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
 159                : "t", "memory"
 160        );
 161}
 162
 163static inline void arch_write_unlock(arch_rwlock_t *rw)
 164{
 165        __asm__ __volatile__ (
 166                "mov.l          %1, @%0 ! arch_write_unlock     \n\t"
 167                :
 168                : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
 169                : "t", "memory"
 170        );
 171}
 172
 173static inline int arch_read_trylock(arch_rwlock_t *rw)
 174{
 175        unsigned long tmp, oldval;
 176
 177        __asm__ __volatile__ (
 178                "1:                                             \n\t"
 179                "movli.l        @%2, %0 ! arch_read_trylock     \n\t"
 180                "mov            %0, %1                          \n\t"
 181                "cmp/pl         %0                              \n\t"
 182                "bf             2f                              \n\t"
 183                "add            #-1, %0                         \n\t"
 184                "movco.l        %0, @%2                         \n\t"
 185                "bf             1b                              \n\t"
 186                "2:                                             \n\t"
 187                "synco                                          \n\t"
 188                : "=&z" (tmp), "=&r" (oldval)
 189                : "r" (&rw->lock)
 190                : "t", "memory"
 191        );
 192
 193        return (oldval > 0);
 194}
 195
 196static inline int arch_write_trylock(arch_rwlock_t *rw)
 197{
 198        unsigned long tmp, oldval;
 199
 200        __asm__ __volatile__ (
 201                "1:                                             \n\t"
 202                "movli.l        @%2, %0 ! arch_write_trylock    \n\t"
 203                "mov            %0, %1                          \n\t"
 204                "cmp/hs         %3, %0                          \n\t"
 205                "bf             2f                              \n\t"
 206                "sub            %3, %0                          \n\t"
 207                "2:                                             \n\t"
 208                "movco.l        %0, @%2                         \n\t"
 209                "bf             1b                              \n\t"
 210                "synco                                          \n\t"
 211                : "=&z" (tmp), "=&r" (oldval)
 212                : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
 213                : "t", "memory"
 214        );
 215
 216        return (oldval > (RW_LOCK_BIAS - 1));
 217}
 218
 219#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
 220#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
 221
 222#define arch_spin_relax(lock)   cpu_relax()
 223#define arch_read_relax(lock)   cpu_relax()
 224#define arch_write_relax(lock)  cpu_relax()
 225
 226#endif /* __ASM_SH_SPINLOCK_H */
 227
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.