The builtin functions __atomic_compare_exchange_* are missing when CONFIG_ATOMIC_OPERATIONS_C is set. Add them and verify they build/work as expected. Signed-off-by: Yuval Peress <peress@google.com>
52 lines
2.5 KiB
C
52 lines
2.5 KiB
C
/*
|
|
* Copyright (c) 2025 Google LLC
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* @brief C-based implementation of GCC __atomic built-ins.
|
|
*
|
|
* This file provides a fallback implementation for the C++ atomic functions
|
|
* required by the compiler on architectures that do not have native atomic
|
|
* instructions and are using the generic C implementation of atomics.
|
|
* All operations are made atomic by using a global interrupt lock.
|
|
*/
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <stdint.h>
|
|
|
|
/*
|
|
* Note on memory ordering:
|
|
* The `memorder` parameters are ignored because the irq_lock() provides
|
|
* a full memory barrier, which is equivalent to the strongest memory order,
|
|
* __ATOMIC_SEQ_CST. This is always safe.
|
|
*/
|
|
|
|
/* === compare_exchange ======================================================= */
|
|
|
|
#define DEFINE_ATOMIC_COMPARE_EXCHANGE(n, type) \
|
|
bool __atomic_compare_exchange_##n(volatile void *ptr, void *expected, type desired, \
|
|
bool weak, int success, int failure) \
|
|
{ \
|
|
bool ret = false; \
|
|
unsigned int key = irq_lock(); \
|
|
volatile type *p = ptr; \
|
|
type *e = expected; \
|
|
\
|
|
if (*p == *e) { \
|
|
*p = desired; \
|
|
ret = true; \
|
|
} else { \
|
|
*e = *p; \
|
|
ret = false; \
|
|
} \
|
|
irq_unlock(key); \
|
|
return ret; \
|
|
}
|
|
|
|
DEFINE_ATOMIC_COMPARE_EXCHANGE(1, uint8_t)
|
|
DEFINE_ATOMIC_COMPARE_EXCHANGE(2, uint16_t)
|
|
DEFINE_ATOMIC_COMPARE_EXCHANGE(4, uint32_t)
|