1 /*
2  * Copyright (c) 2015 Travis Geiselbrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <arch/spinlock.h>
9 
10 // super simple spin lock implementation
11 
riscv_spin_trylock(spin_lock_t * lock)12 int riscv_spin_trylock(spin_lock_t *lock) {
13     unsigned long val = arch_curr_cpu_num() + 1UL;
14     unsigned long old;
15 
16     __asm__ __volatile__(
17         "amoswap.w  %0, %2, %1\n"
18         "fence      r, rw\n"
19         : "=r"(old), "+A"(*lock)
20         : "r" (val)
21         : "memory"
22     );
23 
24     return !old;
25 }
26 
riscv_spin_lock(spin_lock_t * lock)27 void riscv_spin_lock(spin_lock_t *lock) {
28     unsigned long val = arch_curr_cpu_num() + 1UL;
29 
30     for (;;) {
31         if (*lock) {
32             continue;
33         }
34 
35         unsigned long old;
36         __asm__ __volatile__(
37             "amoswap.w  %0, %2, %1\n"
38             "fence      r, rw\n"
39             : "=r"(old), "+A"(*lock)
40             : "r" (val)
41             : "memory"
42         );
43 
44         if (!old) {
45             break;
46         }
47     }
48 }
49 
riscv_spin_unlock(spin_lock_t * lock)50 void riscv_spin_unlock(spin_lock_t *lock) {
51     __asm__ volatile("fence rw,w" ::: "memory");
52     *lock = 0;
53 }
54 
55