linux/arch/csky/include/asm/spinlock.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2
   3#ifndef __ASM_CSKY_SPINLOCK_H
   4#define __ASM_CSKY_SPINLOCK_H
   5
   6#include <linux/spinlock_types.h>
   7#include <asm/barrier.h>
   8
   9#ifdef CONFIG_QUEUED_RWLOCKS
  10
  11/*
  12 * Ticket-based spin-locking.
  13 */
  14static inline void arch_spin_lock(arch_spinlock_t *lock)
  15{
  16        arch_spinlock_t lockval;
  17        u32 ticket_next = 1 << TICKET_NEXT;
  18        u32 *p = &lock->lock;
  19        u32 tmp;
  20
  21        asm volatile (
  22                "1:     ldex.w          %0, (%2) \n"
  23                "       mov             %1, %0   \n"
  24                "       add             %0, %3   \n"
  25                "       stex.w          %0, (%2) \n"
  26                "       bez             %0, 1b   \n"
  27                : "=&r" (tmp), "=&r" (lockval)
  28                : "r"(p), "r"(ticket_next)
  29                : "cc");
  30
  31        while (lockval.tickets.next != lockval.tickets.owner)
  32                lockval.tickets.owner = READ_ONCE(lock->tickets.owner);
  33
  34        smp_mb();
  35}
  36
  37static inline int arch_spin_trylock(arch_spinlock_t *lock)
  38{
  39        u32 tmp, contended, res;
  40        u32 ticket_next = 1 << TICKET_NEXT;
  41        u32 *p = &lock->lock;
  42
  43        do {
  44                asm volatile (
  45                "       ldex.w          %0, (%3)   \n"
  46                "       movi            %2, 1      \n"
  47                "       rotli           %1, %0, 16 \n"
  48                "       cmpne           %1, %0     \n"
  49                "       bt              1f         \n"
  50                "       movi            %2, 0      \n"
  51                "       add             %0, %0, %4 \n"
  52                "       stex.w          %0, (%3)   \n"
  53                "1:                                \n"
  54                : "=&r" (res), "=&r" (tmp), "=&r" (contended)
  55                : "r"(p), "r"(ticket_next)
  56                : "cc");
  57        } while (!res);
  58
  59        if (!contended)
  60                smp_mb();
  61
  62        return !contended;
  63}
  64
  65static inline void arch_spin_unlock(arch_spinlock_t *lock)
  66{
  67        smp_mb();
  68        WRITE_ONCE(lock->tickets.owner, lock->tickets.owner + 1);
  69}
  70
  71static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
  72{
  73        return lock.tickets.owner == lock.tickets.next;
  74}
  75
  76static inline int arch_spin_is_locked(arch_spinlock_t *lock)
  77{
  78        return !arch_spin_value_unlocked(READ_ONCE(*lock));
  79}
  80
  81static inline int arch_spin_is_contended(arch_spinlock_t *lock)
  82{
  83        struct __raw_tickets tickets = READ_ONCE(lock->tickets);
  84
  85        return (tickets.next - tickets.owner) > 1;
  86}
  87#define arch_spin_is_contended  arch_spin_is_contended
  88
  89#include <asm/qrwlock.h>
  90
  91/* See include/linux/spinlock.h */
  92#define smp_mb__after_spinlock()        smp_mb()
  93
  94#else /* CONFIG_QUEUED_RWLOCKS */
  95
  96/*
  97 * Test-and-set spin-locking.
  98 */
  99static inline void arch_spin_lock(arch_spinlock_t *lock)
 100{
 101        u32 *p = &lock->lock;
 102        u32 tmp;
 103
 104        asm volatile (
 105                "1:     ldex.w          %0, (%1) \n"
 106                "       bnez            %0, 1b   \n"
 107                "       movi            %0, 1    \n"
 108                "       stex.w          %0, (%1) \n"
 109                "       bez             %0, 1b   \n"
 110                : "=&r" (tmp)
 111                : "r"(p)
 112                : "cc");
 113        smp_mb();
 114}
 115
 116static inline void arch_spin_unlock(arch_spinlock_t *lock)
 117{
 118        smp_mb();
 119        WRITE_ONCE(lock->lock, 0);
 120}
 121
 122static inline int arch_spin_trylock(arch_spinlock_t *lock)
 123{
 124        u32 *p = &lock->lock;
 125        u32 tmp;
 126
 127        asm volatile (
 128                "1:     ldex.w          %0, (%1) \n"
 129                "       bnez            %0, 2f   \n"
 130                "       movi            %0, 1    \n"
 131                "       stex.w          %0, (%1) \n"
 132                "       bez             %0, 1b   \n"
 133                "       movi            %0, 0    \n"
 134                "2:                              \n"
 135                : "=&r" (tmp)
 136                : "r"(p)
 137                : "cc");
 138
 139        if (!tmp)
 140                smp_mb();
 141
 142        return !tmp;
 143}
 144
 145#define arch_spin_is_locked(x)  (READ_ONCE((x)->lock) != 0)
 146
 147/*
 148 * read lock/unlock/trylock
 149 */
 150static inline void arch_read_lock(arch_rwlock_t *lock)
 151{
 152        u32 *p = &lock->lock;
 153        u32 tmp;
 154
 155        asm volatile (
 156                "1:     ldex.w          %0, (%1) \n"
 157                "       blz             %0, 1b   \n"
 158                "       addi            %0, 1    \n"
 159                "       stex.w          %0, (%1) \n"
 160                "       bez             %0, 1b   \n"
 161                : "=&r" (tmp)
 162                : "r"(p)
 163                : "cc");
 164        smp_mb();
 165}
 166
 167static inline void arch_read_unlock(arch_rwlock_t *lock)
 168{
 169        u32 *p = &lock->lock;
 170        u32 tmp;
 171
 172        smp_mb();
 173        asm volatile (
 174                "1:     ldex.w          %0, (%1) \n"
 175                "       subi            %0, 1    \n"
 176                "       stex.w          %0, (%1) \n"
 177                "       bez             %0, 1b   \n"
 178                : "=&r" (tmp)
 179                : "r"(p)
 180                : "cc");
 181}
 182
 183static inline int arch_read_trylock(arch_rwlock_t *lock)
 184{
 185        u32 *p = &lock->lock;
 186        u32 tmp;
 187
 188        asm volatile (
 189                "1:     ldex.w          %0, (%1) \n"
 190                "       blz             %0, 2f   \n"
 191                "       addi            %0, 1    \n"
 192                "       stex.w          %0, (%1) \n"
 193                "       bez             %0, 1b   \n"
 194                "       movi            %0, 0    \n"
 195                "2:                              \n"
 196                : "=&r" (tmp)
 197                : "r"(p)
 198                : "cc");
 199
 200        if (!tmp)
 201                smp_mb();
 202
 203        return !tmp;
 204}
 205
 206/*
 207 * write lock/unlock/trylock
 208 */
 209static inline void arch_write_lock(arch_rwlock_t *lock)
 210{
 211        u32 *p = &lock->lock;
 212        u32 tmp;
 213
 214        asm volatile (
 215                "1:     ldex.w          %0, (%1) \n"
 216                "       bnez            %0, 1b   \n"
 217                "       subi            %0, 1    \n"
 218                "       stex.w          %0, (%1) \n"
 219                "       bez             %0, 1b   \n"
 220                : "=&r" (tmp)
 221                : "r"(p)
 222                : "cc");
 223        smp_mb();
 224}
 225
 226static inline void arch_write_unlock(arch_rwlock_t *lock)
 227{
 228        smp_mb();
 229        WRITE_ONCE(lock->lock, 0);
 230}
 231
 232static inline int arch_write_trylock(arch_rwlock_t *lock)
 233{
 234        u32 *p = &lock->lock;
 235        u32 tmp;
 236
 237        asm volatile (
 238                "1:     ldex.w          %0, (%1) \n"
 239                "       bnez            %0, 2f   \n"
 240                "       subi            %0, 1    \n"
 241                "       stex.w          %0, (%1) \n"
 242                "       bez             %0, 1b   \n"
 243                "       movi            %0, 0    \n"
 244                "2:                              \n"
 245                : "=&r" (tmp)
 246                : "r"(p)
 247                : "cc");
 248
 249        if (!tmp)
 250                smp_mb();
 251
 252        return !tmp;
 253}
 254
 255#endif /* CONFIG_QUEUED_RWLOCKS */
 256#endif /* __ASM_CSKY_SPINLOCK_H */
 257