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)14int 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)29void 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)52void riscv_spin_unlock(spin_lock_t *lock) { 53 __asm__ volatile("fence rw,w" ::: "memory"); 54 *lock = 0; 55 } 56 57