Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | /* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2014, STMicroelectronics International N.V.
* Copyright (c) 2016, Linaro Limited
*/
#ifndef KERNEL_SPINLOCK_H
#define KERNEL_SPINLOCK_H
#define SPINLOCK_LOCK 1
#define SPINLOCK_UNLOCK 0
#ifndef ASM
#include <assert.h>
#include <compiler.h>
#include <stdbool.h>
#include <kernel/thread.h>
#ifdef CFG_TEE_CORE_DEBUG
void spinlock_count_incr(void);
void spinlock_count_decr(void);
bool have_spinlock(void);
static inline void assert_have_no_spinlock(void)
{
assert(!have_spinlock());
}
#else
static inline void spinlock_count_incr(void) { }
static inline void spinlock_count_decr(void) { }
static inline void assert_have_no_spinlock(void) { }
#endif
void __cpu_spin_lock(unsigned int *lock);
void __cpu_spin_unlock(unsigned int *lock);
/* returns 0 on locking success, non zero on failure */
unsigned int __cpu_spin_trylock(unsigned int *lock);
static inline void cpu_spin_lock_no_dldetect(unsigned int *lock)
{
assert(thread_foreign_intr_disabled());
__cpu_spin_lock(lock);
spinlock_count_incr();
}
#ifdef CFG_TEE_CORE_DEBUG
#define cpu_spin_lock(lock) \
cpu_spin_lock_dldetect(__func__, __LINE__, lock)
static inline void cpu_spin_lock_dldetect(const char *func, const int line,
unsigned int *lock)
{
unsigned int retries = 0;
unsigned int reminder = 0;
assert(thread_foreign_intr_disabled());
while (__cpu_spin_trylock(lock)) {
retries++;
if (!retries) {
/* wrapped, time to report */
trace_printf(func, line, TRACE_ERROR, true,
"possible spinlock deadlock reminder %u",
reminder);
if (reminder < UINT_MAX)
reminder++;
}
}
spinlock_count_incr();
}
#else
static inline void cpu_spin_lock(unsigned int *lock)
{
cpu_spin_lock_no_dldetect(lock);
}
#endif
static inline bool cpu_spin_trylock(unsigned int *lock)
{
unsigned int rc;
assert(thread_foreign_intr_disabled());
rc = __cpu_spin_trylock(lock);
if (!rc)
spinlock_count_incr();
return !rc;
}
static inline void cpu_spin_unlock(unsigned int *lock)
{
assert(thread_foreign_intr_disabled());
__cpu_spin_unlock(lock);
spinlock_count_decr();
}
static inline uint32_t cpu_spin_lock_xsave_no_dldetect(unsigned int *lock)
{
uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
cpu_spin_lock(lock);
return exceptions;
}
#ifdef CFG_TEE_CORE_DEBUG
#define cpu_spin_lock_xsave(lock) \
cpu_spin_lock_xsave_dldetect(__func__, __LINE__, lock)
static inline uint32_t cpu_spin_lock_xsave_dldetect(const char *func,
const int line,
unsigned int *lock)
{
uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
cpu_spin_lock_dldetect(func, line, lock);
return exceptions;
}
#else
static inline uint32_t cpu_spin_lock_xsave(unsigned int *lock)
{
return cpu_spin_lock_xsave_no_dldetect(lock);
}
#endif
static inline void cpu_spin_unlock_xrestore(unsigned int *lock,
uint32_t exceptions)
{
cpu_spin_unlock(lock);
thread_unmask_exceptions(exceptions);
}
#endif /* ASM */
#endif /* KERNEL_SPINLOCK_H */
|