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>
40 lines
803 B
C
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 */
|