123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2023-05-18 GuEe-GUI first version
- */
- #include <rthw.h>
- #include <rtatomic.h>
- rt_atomic_t rt_hw_atomic_load(volatile rt_atomic_t *ptr)
- {
- rt_atomic_t ret;
- __asm__ volatile (
- " ldr %0, %1\n"
- " dmb ish"
- : "=r" (ret)
- : "Q" (*ptr)
- : "memory");
- return ret;
- }
- void rt_hw_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val)
- {
- __asm__ volatile (
- " str %1, %0\n"
- " dmb ish"
- : "=Q" (*ptr)
- : "r" (val)
- : "memory");
- }
- #define AARCH64_ATOMIC_OP_RETURN(op, ins, constraint) \
- rt_atomic_t rt_hw_atomic_##op(volatile rt_atomic_t *ptr, rt_atomic_t in_val) \
- { \
- rt_atomic_t tmp, val, result; \
- \
- __asm__ volatile ( \
- " prfm pstl1strm, %3\n" \
- "1: ldxr %0, %3\n" \
- " "#ins " %1, %0, %4\n" \
- " stlxr %w2, %1, %3\n" \
- " cbnz %w2, 1b\n" \
- " dmb ish" \
- : "=&r" (result), "=&r" (val), "=&r" (tmp), "+Q" (*ptr) \
- : __RT_STRINGIFY(constraint) "r" (in_val) \
- : "memory"); \
- \
- return result; \
- }
- AARCH64_ATOMIC_OP_RETURN(add, add, I)
- AARCH64_ATOMIC_OP_RETURN(sub, sub, J)
- AARCH64_ATOMIC_OP_RETURN(and, and, K)
- AARCH64_ATOMIC_OP_RETURN(or, orr, K)
- AARCH64_ATOMIC_OP_RETURN(xor, eor, K)
- rt_atomic_t rt_hw_atomic_exchange(volatile rt_atomic_t *ptr, rt_atomic_t val)
- {
- rt_atomic_t ret, tmp;
- __asm__ volatile (
- " prfm pstl1strm, %2\n"
- "1: ldxr %0, %2\n"
- " stlxr %w1, %3, %2\n"
- " cbnz %w1, 1b\n"
- " dmb ish"
- : "=&r" (ret), "=&r" (tmp), "+Q" (*ptr)
- : "r" (val)
- : "memory");
- return ret;
- }
- void rt_hw_atomic_flag_clear(volatile rt_atomic_t *ptr)
- {
- rt_hw_atomic_and(ptr, 0);
- }
- rt_atomic_t rt_hw_atomic_flag_test_and_set(volatile rt_atomic_t *ptr)
- {
- return rt_hw_atomic_or(ptr, 1);
- }
- rt_atomic_t rt_hw_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr, rt_atomic_t *old, rt_atomic_t new)
- {
- rt_atomic_t tmp, oldval;
- __asm__ volatile (
- " prfm pstl1strm, %2\n"
- "1: ldxr %0, %2\n"
- " eor %1, %0, %3\n"
- " cbnz %1, 2f\n"
- " stlxr %w1, %4, %2\n"
- " cbnz %w1, 1b\n"
- " dmb ish\n"
- "2:"
- : "=&r" (oldval), "=&r" (tmp), "+Q" (*ptr)
- : "Kr" (*old), "r" (new)
- : "memory");
- return oldval == *old;
- }
|