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 #include <stdint.h>
11 
12 // super simple spin lock implementation
13 
riscv_spin_trylock(spin_lock_t * lock)14 int riscv_spin_trylock(spin_lock_t *lock) {
15     // use a full 32/64 type since amoswap overwrites the entire register
16     unsigned long old;
17 
18     __asm__ __volatile__(
19         "amoswap.w  %0, %2, %1\n"
20         "fence      r, rw\n"
21         : "=r"(old), "+A"(*lock)
22         : "r" (1u)
23         : "memory"
24     );
25 
26     return !old;
27 }
28 
riscv_spin_lock(spin_lock_t * lock)29 void riscv_spin_lock(spin_lock_t *lock) {
30     for (;;) {
31         if (*lock) {
32             // TODO: use a yield instruction here?
33             continue;
34         }
35 
36         // use a full 32/64 type since amoswap overwrites the entire register
37         unsigned long old;
38         __asm__ __volatile__(
39             "amoswap.w  %0, %2, %1\n"
40             "fence      r, rw\n"
41             : "=r"(old), "+A"(*lock)
42             : "r" (1u)
43             : "memory"
44         );
45 
46         if (!old) {
47             break;
48         }
49     }
50 }
51 
riscv_spin_unlock(spin_lock_t * lock)52 void riscv_spin_unlock(spin_lock_t *lock) {
53     __asm__ volatile("fence rw,w" ::: "memory");
54     *lock = 0;
55 }
56 
57