linux/arch/riscv/include/asm/spinlock.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Copyright (C) 2015 Regents of the University of California
   4 * Copyright (C) 2017 SiFive
   5 */
   6
   7#ifndef _ASM_RISCV_SPINLOCK_H
   8#define _ASM_RISCV_SPINLOCK_H
   9
  10#include <linux/kernel.h>
  11#include <asm/current.h>
  12#include <asm/fence.h>
  13
  14/*
  15 * Simple spin lock operations.  These provide no fairness guarantees.
  16 */
  17
  18/* FIXME: Replace this with a ticket lock, like MIPS. */
  19
  20#define arch_spin_is_locked(x)  (READ_ONCE((x)->lock) != 0)
  21
  22static inline void arch_spin_unlock(arch_spinlock_t *lock)
  23{
  24        smp_store_release(&lock->lock, 0);
  25}
  26
  27static inline int arch_spin_trylock(arch_spinlock_t *lock)
  28{
  29        int tmp = 1, busy;
  30
  31        __asm__ __volatile__ (
  32                "       amoswap.w %0, %2, %1\n"
  33                RISCV_ACQUIRE_BARRIER
  34                : "=r" (busy), "+A" (lock->lock)
  35                : "r" (tmp)
  36                : "memory");
  37
  38        return !busy;
  39}
  40
  41static inline void arch_spin_lock(arch_spinlock_t *lock)
  42{
  43        while (1) {
  44                if (arch_spin_is_locked(lock))
  45                        continue;
  46
  47                if (arch_spin_trylock(lock))
  48                        break;
  49        }
  50}
  51
  52/***********************************************************/
  53
  54static inline void arch_read_lock(arch_rwlock_t *lock)
  55{
  56        int tmp;
  57
  58        __asm__ __volatile__(
  59                "1:     lr.w    %1, %0\n"
  60                "       bltz    %1, 1b\n"
  61                "       addi    %1, %1, 1\n"
  62                "       sc.w    %1, %1, %0\n"
  63                "       bnez    %1, 1b\n"
  64                RISCV_ACQUIRE_BARRIER
  65                : "+A" (lock->lock), "=&r" (tmp)
  66                :: "memory");
  67}
  68
  69static inline void arch_write_lock(arch_rwlock_t *lock)
  70{
  71        int tmp;
  72
  73        __asm__ __volatile__(
  74                "1:     lr.w    %1, %0\n"
  75                "       bnez    %1, 1b\n"
  76                "       li      %1, -1\n"
  77                "       sc.w    %1, %1, %0\n"
  78                "       bnez    %1, 1b\n"
  79                RISCV_ACQUIRE_BARRIER
  80                : "+A" (lock->lock), "=&r" (tmp)
  81                :: "memory");
  82}
  83
  84static inline int arch_read_trylock(arch_rwlock_t *lock)
  85{
  86        int busy;
  87
  88        __asm__ __volatile__(
  89                "1:     lr.w    %1, %0\n"
  90                "       bltz    %1, 1f\n"
  91                "       addi    %1, %1, 1\n"
  92                "       sc.w    %1, %1, %0\n"
  93                "       bnez    %1, 1b\n"
  94                RISCV_ACQUIRE_BARRIER
  95                "1:\n"
  96                : "+A" (lock->lock), "=&r" (busy)
  97                :: "memory");
  98
  99        return !busy;
 100}
 101
 102static inline int arch_write_trylock(arch_rwlock_t *lock)
 103{
 104        int busy;
 105
 106        __asm__ __volatile__(
 107                "1:     lr.w    %1, %0\n"
 108                "       bnez    %1, 1f\n"
 109                "       li      %1, -1\n"
 110                "       sc.w    %1, %1, %0\n"
 111                "       bnez    %1, 1b\n"
 112                RISCV_ACQUIRE_BARRIER
 113                "1:\n"
 114                : "+A" (lock->lock), "=&r" (busy)
 115                :: "memory");
 116
 117        return !busy;
 118}
 119
 120static inline void arch_read_unlock(arch_rwlock_t *lock)
 121{
 122        __asm__ __volatile__(
 123                RISCV_RELEASE_BARRIER
 124                "       amoadd.w x0, %1, %0\n"
 125                : "+A" (lock->lock)
 126                : "r" (-1)
 127                : "memory");
 128}
 129
 130static inline void arch_write_unlock(arch_rwlock_t *lock)
 131{
 132        smp_store_release(&lock->lock, 0);
 133}
 134
 135#endif /* _ASM_RISCV_SPINLOCK_H */
 136