at v5.4 135 lines 2.5 kB view raw
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 */