opensbi/lib/sbi/riscv_locks.c
Daniel Schaefer f90c4c2e02 lib: sbi: Have spinlock checks return bool
spin_lock_check already returned bool in the source file but not in the
header. With some toolchains that causes an error, as it should.

Because it and related functions all essentially return a bool, we can
use this opportunity to change them.

Signed-off-by: Daniel Schaefer <git@danielschaefer.me>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
2021-05-14 17:05:20 +05:30

77 lines
1.6 KiB
C

/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
* Copyright (c) 2021 Christoph Müllner <cmuellner@linux.com>
*/
#include <sbi/riscv_barrier.h>
#include <sbi/riscv_locks.h>
static inline bool spin_lock_unlocked(spinlock_t lock)
{
return lock.owner == lock.next;
}
bool spin_lock_check(spinlock_t *lock)
{
RISCV_FENCE(r, rw);
return !spin_lock_unlocked(*lock);
}
bool spin_trylock(spinlock_t *lock)
{
unsigned long inc = 1u << TICKET_SHIFT;
unsigned long mask = 0xffffu << TICKET_SHIFT;
u32 l0, tmp1, tmp2;
__asm__ __volatile__(
/* Get the current lock counters. */
"1: lr.w.aq %0, %3\n"
" slli %2, %0, %6\n"
" and %2, %2, %5\n"
" and %1, %0, %5\n"
/* Is the lock free right now? */
" bne %1, %2, 2f\n"
" add %0, %0, %4\n"
/* Acquire the lock. */
" sc.w.rl %0, %0, %3\n"
" bnez %0, 1b\n"
"2:"
: "=&r"(l0), "=&r"(tmp1), "=&r"(tmp2), "+A"(*lock)
: "r"(inc), "r"(mask), "I"(TICKET_SHIFT)
: "memory");
return l0 == 0;
}
void spin_lock(spinlock_t *lock)
{
unsigned long inc = 1u << TICKET_SHIFT;
unsigned long mask = 0xffffu;
u32 l0, tmp1, tmp2;
__asm__ __volatile__(
/* Atomically increment the next ticket. */
" amoadd.w.aqrl %0, %4, %3\n"
/* Did we get the lock? */
" srli %1, %0, %6\n"
" and %1, %1, %5\n"
"1: and %2, %0, %5\n"
" beq %1, %2, 2f\n"
/* If not, then spin on the lock. */
" lw %0, %3\n"
RISCV_ACQUIRE_BARRIER
" j 1b\n"
"2:"
: "=&r"(l0), "=&r"(tmp1), "=&r"(tmp2), "+A"(*lock)
: "r"(inc), "r"(mask), "I"(TICKET_SHIFT)
: "memory");
}
void spin_unlock(spinlock_t *lock)
{
__smp_store_release(&lock->owner, lock->owner + 1);
}