Boyan Karatotev 07ba153fda feat(locks): make spin_trylock with exclusives spin until it knows the state of the lock
spin_trylock() is meant to be a non-blocking equivalent of spin_lock().
When we have atomics this is easy - the `cas` will directly return the
state of the lock (held or not held). However, when using exclusives,
there's a third state - failed to hold the lock. This happens when the
store exclusive couldn't complete the write and bailed. The current
implementation will pigeonhole this state into a "not held" state which
loses this subtlety and can return with no one holding the lock.

This patch makes it so that the operation is retried until the core is
certain it either holds the lock or someone else does. This keeps the
nonblocking nature of the trylock call but may incur a delay until the
state of the lock settles.

Change-Id: I1a57de22557e13c22f6a6afdef4c28f679dbe7f2
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
2025-12-19 11:36:45 +00:00

40 lines
803 B
C

/*
* Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SPINLOCK_H
#define SPINLOCK_H
#ifndef __ASSEMBLER__
#include <stdbool.h>
#include <stdint.h>
typedef struct spinlock {
volatile uint32_t lock;
} spinlock_t;
typedef struct bitlock {
volatile uint8_t lock;
} bitlock_t;
void spin_lock(spinlock_t *lock);
void spin_unlock(spinlock_t *lock);
void bit_lock(bitlock_t *lock, uint8_t mask);
void bit_unlock(bitlock_t *lock, uint8_t mask);
/* non-blocking spin_lock(). Returns whether the lock was acquired. */
bool spin_trylock(spinlock_t *lock);
#else
/* Spin lock definitions for use in assembly */
#define SPINLOCK_ASM_ALIGN 2
#define SPINLOCK_ASM_SIZE 4
#endif /* __ASSEMBLER__ */
#endif /* SPINLOCK_H */