2 * Copyright (C) 2015 Regents of the University of California
3 * Copyright (C) 2017 SiFive
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation, version 2.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #ifndef _ASM_RISCV_SPINLOCK_H
16 #define _ASM_RISCV_SPINLOCK_H
18 #include <linux/kernel.h>
19 #include <asm/current.h>
20 #include <asm/fence.h>
23 * Simple spin lock operations. These provide no fairness guarantees.
26 /* FIXME: Replace this with a ticket lock, like MIPS. */
28 #define arch_spin_is_locked(x) (READ_ONCE((x)->lock) != 0)
30 static inline void arch_spin_unlock(arch_spinlock_t
*lock
)
32 smp_store_release(&lock
->lock
, 0);
35 static inline int arch_spin_trylock(arch_spinlock_t
*lock
)
39 __asm__
__volatile__ (
40 " amoswap.w %0, %2, %1\n"
42 : "=r" (busy
), "+A" (lock
->lock
)
49 static inline void arch_spin_lock(arch_spinlock_t
*lock
)
52 if (arch_spin_is_locked(lock
))
55 if (arch_spin_trylock(lock
))
60 /***********************************************************/
62 static inline void arch_read_lock(arch_rwlock_t
*lock
)
73 : "+A" (lock
->lock
), "=&r" (tmp
)
77 static inline void arch_write_lock(arch_rwlock_t
*lock
)
88 : "+A" (lock
->lock
), "=&r" (tmp
)
92 static inline int arch_read_trylock(arch_rwlock_t
*lock
)
102 RISCV_ACQUIRE_BARRIER
104 : "+A" (lock
->lock
), "=&r" (busy
)
110 static inline int arch_write_trylock(arch_rwlock_t
*lock
)
114 __asm__
__volatile__(
120 RISCV_ACQUIRE_BARRIER
122 : "+A" (lock
->lock
), "=&r" (busy
)
128 static inline void arch_read_unlock(arch_rwlock_t
*lock
)
130 __asm__
__volatile__(
131 RISCV_RELEASE_BARRIER
132 " amoadd.w x0, %1, %0\n"
138 static inline void arch_write_unlock(arch_rwlock_t
*lock
)
140 smp_store_release(&lock
->lock
, 0);
143 #endif /* _ASM_RISCV_SPINLOCK_H */