The rte_wait_until_equal_xxx APIs abstract the functionality of 'polling for a memory location to become equal to a given value'.
Signed-off-by: Gavin Hu <gavin...@arm.com> Reviewed-by: Ruifeng Wang <ruifeng.w...@arm.com> Reviewed-by: Steve Capper <steve.cap...@arm.com> Reviewed-by: Ola Liljedahl <ola.liljed...@arm.com> Reviewed-by: Honnappa Nagarahalli <honnappa.nagaraha...@arm.com> --- .../common/include/arch/arm/rte_pause_64.h | 143 +++++++++++++++++++++ lib/librte_eal/common/include/generic/rte_pause.h | 20 +++ 2 files changed, 163 insertions(+) diff --git a/lib/librte_eal/common/include/arch/arm/rte_pause_64.h b/lib/librte_eal/common/include/arch/arm/rte_pause_64.h index 93895d3..0095da6 100644 --- a/lib/librte_eal/common/include/arch/arm/rte_pause_64.h +++ b/lib/librte_eal/common/include/arch/arm/rte_pause_64.h @@ -17,6 +17,149 @@ static inline void rte_pause(void) asm volatile("yield" ::: "memory"); } +#ifdef RTE_USE_WFE +#define rte_wait_until_equal_relaxed(addr, expected) do {\ + typeof(*addr) tmp; \ + if (__builtin_constant_p((expected))) \ + do { \ + if (sizeof(*(addr)) == 16)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldxrh %w0, %1\n" \ + "cmp %w0, %w2\n" \ + "bne 1b\n" \ + : "=&r"(tmp) \ + : "Q"(*addr), "i"(expected) \ + : "cc", "memory"); \ + else if (sizeof(*(addr)) == 32)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldxr %w0, %1\n" \ + "cmp %w0, %w2\n" \ + "bne 1b\n" \ + : "=&r"(tmp) \ + : "Q"(*addr), "i"(expected) \ + : "cc", "memory"); \ + else if (sizeof(*(addr)) == 64)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldxr %x0, %1\n" \ + "cmp %x0, %x2\n" \ + "bne 1b\n" \ + : "=&r" (tmp) \ + : "Q"(*addr), "i"(expected) \ + : "cc", "memory"); \ + } while (0); \ + else \ + do { \ + if (sizeof(*(addr)) == 16)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldxrh %w0, %1\n" \ + "cmp %w0, %w2\n" \ + "bne 1b\n" \ + : "=&r"(tmp) \ + : "Q"(*addr), "r"(expected) \ + : "cc", "memory"); \ + else if (sizeof(*(addr)) == 32)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldxr %w0, %1\n" \ + "cmp %w0, %w2\n" \ + "bne 1b\n" \ + : "=&r"(tmp) \ + : "Q"(*addr), "r"(expected) \ + : "cc", "memory"); \ + else if (sizeof(*(addr)) == 64)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldxr %x0, %1\n" \ + "cmp %x0, %x2\n" \ + "bne 1b\n" \ + : "=&r" (tmp) \ + : "Q"(*addr), "r"(expected) \ + : "cc", "memory"); \ + } while (0); \ +} while (0) + +#define rte_wait_until_equal_acquire(addr, expected) do {\ + typeof(*addr) tmp; \ + if (__builtin_constant_p((expected))) \ + do { \ + if (sizeof(*(addr)) == 16)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldaxrh %w0, %1\n" \ + "cmp %w0, %w2\n" \ + "bne 1b\n" \ + : "=&r"(tmp) \ + : "Q"(*addr), "i"(expected) \ + : "cc", "memory"); \ + else if (sizeof(*(addr)) == 32)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldaxr %w0, %1\n" \ + "cmp %w0, %w2\n" \ + "bne 1b\n" \ + : "=&r"(tmp) \ + : "Q"(*addr), "i"(expected) \ + : "cc", "memory"); \ + else if (sizeof(*(addr)) == 64)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldaxr %x0, %1\n" \ + "cmp %x0, %x2\n" \ + "bne 1b\n" \ + : "=&r" (tmp) \ + : "Q"(*addr), "i"(expected) \ + : "cc", "memory"); \ + } while (0); \ + else \ + do { \ + if (sizeof(*(addr)) == 16)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldaxrh %w0, %1\n" \ + "cmp %w0, %w2\n" \ + "bne 1b\n" \ + : "=&r"(tmp) \ + : "Q"(*addr), "r"(expected) \ + : "cc", "memory"); \ + else if (sizeof(*(addr)) == 32)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldaxr %w0, %1\n" \ + "cmp %w0, %w2\n" \ + "bne 1b\n" \ + : "=&r"(tmp) \ + : "Q"(*addr), "r"(expected) \ + : "cc", "memory"); \ + else if (sizeof(*(addr)) == 64)\ + asm volatile( \ + "sevl\n" \ + "1: wfe\n" \ + "ldaxr %x0, %1\n" \ + "cmp %x0, %x2\n" \ + "bne 1b\n" \ + : "=&r" (tmp) \ + : "Q"(*addr), "r"(expected) \ + : "cc", "memory"); \ + } while (0); \ +} while (0) + +#endif + #ifdef __cplusplus } #endif diff --git a/lib/librte_eal/common/include/generic/rte_pause.h b/lib/librte_eal/common/include/generic/rte_pause.h index 52bd4db..c115b61 100644 --- a/lib/librte_eal/common/include/generic/rte_pause.h +++ b/lib/librte_eal/common/include/generic/rte_pause.h @@ -20,4 +20,24 @@ */ static inline void rte_pause(void); +#if !defined(RTE_USE_WFE) +#define rte_wait_until_equal_relaxed(addr, expected) do {\ + rte_pause(); \ + } while (*(addr) != (expected)) + +#ifdef RTE_USE_C11_MEM_MODEL +#define rte_wait_until_equal_acquire(addr, expected) do {\ + rte_pause(); \ + } while (__atomic_load_n((addr), __ATOMIC_ACQUIRE) != (expected)) +#else +#define rte_wait_until_equal_acquire(addr, expected) do {\ + do {\ + rte_pause(); \ + } while (*(addr) != (expected)); \ + rte_smp_rmb(); \ + } while (0) +#endif +#endif + + #endif /* _RTE_PAUSE_H_ */ -- 2.7.4