199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2017 Cavium, Inc 399a2dd95SBruce Richardson * Copyright(c) 2019 Arm Limited 499a2dd95SBruce Richardson */ 599a2dd95SBruce Richardson 699a2dd95SBruce Richardson #ifndef _RTE_PAUSE_H_ 799a2dd95SBruce Richardson #define _RTE_PAUSE_H_ 899a2dd95SBruce Richardson 999a2dd95SBruce Richardson /** 1099a2dd95SBruce Richardson * @file 1199a2dd95SBruce Richardson * 1299a2dd95SBruce Richardson * CPU pause operation. 1399a2dd95SBruce Richardson */ 1499a2dd95SBruce Richardson 1599a2dd95SBruce Richardson #include <stdint.h> 1699a2dd95SBruce Richardson #include <assert.h> 171ec6a845STyler Retzlaff 1899a2dd95SBruce Richardson #include <rte_common.h> 1999a2dd95SBruce Richardson #include <rte_atomic.h> 201ec6a845STyler Retzlaff #include <rte_stdatomic.h> 2199a2dd95SBruce Richardson 22*719834a6SMattias Rönnblom #ifdef __cplusplus 23*719834a6SMattias Rönnblom extern "C" { 24*719834a6SMattias Rönnblom #endif 25*719834a6SMattias Rönnblom 2699a2dd95SBruce Richardson /** 2799a2dd95SBruce Richardson * Pause CPU execution for a short while 2899a2dd95SBruce Richardson * 2999a2dd95SBruce Richardson * This call is intended for tight loops which poll a shared resource or wait 3099a2dd95SBruce Richardson * for an event. A short pause within the loop may reduce the power consumption. 3199a2dd95SBruce Richardson */ 3299a2dd95SBruce Richardson static inline void rte_pause(void); 3399a2dd95SBruce Richardson 3499a2dd95SBruce Richardson /** 3599a2dd95SBruce Richardson * Wait for *addr to be updated with a 16-bit expected value, with a relaxed 3699a2dd95SBruce Richardson * memory ordering model meaning the loads around this API can be reordered. 3799a2dd95SBruce Richardson * 3899a2dd95SBruce Richardson * @param addr 3999a2dd95SBruce Richardson * A pointer to the memory location. 4099a2dd95SBruce Richardson * @param expected 4199a2dd95SBruce Richardson * A 16-bit expected value to be in the memory location. 4299a2dd95SBruce Richardson * @param memorder 4399a2dd95SBruce Richardson * Two different memory orders that can be specified: 441ec6a845STyler Retzlaff * rte_memory_order_acquire and rte_memory_order_relaxed. 4599a2dd95SBruce Richardson */ 4699a2dd95SBruce Richardson static __rte_always_inline void 4799a2dd95SBruce Richardson rte_wait_until_equal_16(volatile uint16_t *addr, uint16_t expected, 481ec6a845STyler Retzlaff rte_memory_order memorder); 4999a2dd95SBruce Richardson 5099a2dd95SBruce Richardson /** 5199a2dd95SBruce Richardson * Wait for *addr to be updated with a 32-bit expected value, with a relaxed 5299a2dd95SBruce Richardson * memory ordering model meaning the loads around this API can be reordered. 5399a2dd95SBruce Richardson * 5499a2dd95SBruce Richardson * @param addr 5599a2dd95SBruce Richardson * A pointer to the memory location. 5699a2dd95SBruce Richardson * @param expected 5799a2dd95SBruce Richardson * A 32-bit expected value to be in the memory location. 5899a2dd95SBruce Richardson * @param memorder 5999a2dd95SBruce Richardson * Two different memory orders that can be specified: 601ec6a845STyler Retzlaff * rte_memory_order_acquire and rte_memory_order_relaxed. 6199a2dd95SBruce Richardson */ 6299a2dd95SBruce Richardson static __rte_always_inline void 6399a2dd95SBruce Richardson rte_wait_until_equal_32(volatile uint32_t *addr, uint32_t expected, 641ec6a845STyler Retzlaff rte_memory_order memorder); 6599a2dd95SBruce Richardson 6699a2dd95SBruce Richardson /** 6799a2dd95SBruce Richardson * Wait for *addr to be updated with a 64-bit expected value, with a relaxed 6899a2dd95SBruce Richardson * memory ordering model meaning the loads around this API can be reordered. 6999a2dd95SBruce Richardson * 7099a2dd95SBruce Richardson * @param addr 7199a2dd95SBruce Richardson * A pointer to the memory location. 7299a2dd95SBruce Richardson * @param expected 7399a2dd95SBruce Richardson * A 64-bit expected value to be in the memory location. 7499a2dd95SBruce Richardson * @param memorder 7599a2dd95SBruce Richardson * Two different memory orders that can be specified: 761ec6a845STyler Retzlaff * rte_memory_order_acquire and rte_memory_order_relaxed. 7799a2dd95SBruce Richardson */ 7899a2dd95SBruce Richardson static __rte_always_inline void 7999a2dd95SBruce Richardson rte_wait_until_equal_64(volatile uint64_t *addr, uint64_t expected, 801ec6a845STyler Retzlaff rte_memory_order memorder); 8199a2dd95SBruce Richardson 8299a2dd95SBruce Richardson #ifndef RTE_WAIT_UNTIL_EQUAL_ARCH_DEFINED 8399a2dd95SBruce Richardson static __rte_always_inline void 8499a2dd95SBruce Richardson rte_wait_until_equal_16(volatile uint16_t *addr, uint16_t expected, 851ec6a845STyler Retzlaff rte_memory_order memorder) 8699a2dd95SBruce Richardson { 871ec6a845STyler Retzlaff assert(memorder == rte_memory_order_acquire || memorder == rte_memory_order_relaxed); 8899a2dd95SBruce Richardson 899290f8beSTyler Retzlaff while (rte_atomic_load_explicit((volatile __rte_atomic uint16_t *)addr, memorder) 909290f8beSTyler Retzlaff != expected) 9199a2dd95SBruce Richardson rte_pause(); 9299a2dd95SBruce Richardson } 9399a2dd95SBruce Richardson 9499a2dd95SBruce Richardson static __rte_always_inline void 9599a2dd95SBruce Richardson rte_wait_until_equal_32(volatile uint32_t *addr, uint32_t expected, 961ec6a845STyler Retzlaff rte_memory_order memorder) 9799a2dd95SBruce Richardson { 981ec6a845STyler Retzlaff assert(memorder == rte_memory_order_acquire || memorder == rte_memory_order_relaxed); 9999a2dd95SBruce Richardson 1009290f8beSTyler Retzlaff while (rte_atomic_load_explicit((volatile __rte_atomic uint32_t *)addr, memorder) 1019290f8beSTyler Retzlaff != expected) 10299a2dd95SBruce Richardson rte_pause(); 10399a2dd95SBruce Richardson } 10499a2dd95SBruce Richardson 10599a2dd95SBruce Richardson static __rte_always_inline void 10699a2dd95SBruce Richardson rte_wait_until_equal_64(volatile uint64_t *addr, uint64_t expected, 1071ec6a845STyler Retzlaff rte_memory_order memorder) 10899a2dd95SBruce Richardson { 1091ec6a845STyler Retzlaff assert(memorder == rte_memory_order_acquire || memorder == rte_memory_order_relaxed); 11099a2dd95SBruce Richardson 1119290f8beSTyler Retzlaff while (rte_atomic_load_explicit((volatile __rte_atomic uint64_t *)addr, memorder) 1129290f8beSTyler Retzlaff != expected) 11399a2dd95SBruce Richardson rte_pause(); 11499a2dd95SBruce Richardson } 115875f3509SFeifei Wang 116875f3509SFeifei Wang /* 117875f3509SFeifei Wang * Wait until *addr & mask makes the condition true. With a relaxed memory 118875f3509SFeifei Wang * ordering model, the loads around this helper can be reordered. 119875f3509SFeifei Wang * 120875f3509SFeifei Wang * @param addr 121875f3509SFeifei Wang * A pointer to the memory location. 122875f3509SFeifei Wang * @param mask 123875f3509SFeifei Wang * A mask of value bits in interest. 124875f3509SFeifei Wang * @param cond 125875f3509SFeifei Wang * A symbol representing the condition. 126875f3509SFeifei Wang * @param expected 127875f3509SFeifei Wang * An expected value to be in the memory location. 128875f3509SFeifei Wang * @param memorder 129875f3509SFeifei Wang * Two different memory orders that can be specified: 1301ec6a845STyler Retzlaff * rte_memory_order_acquire and rte_memory_order_relaxed. 131875f3509SFeifei Wang */ 132875f3509SFeifei Wang #define RTE_WAIT_UNTIL_MASKED(addr, mask, cond, expected, memorder) do { \ 133875f3509SFeifei Wang RTE_BUILD_BUG_ON(!__builtin_constant_p(memorder)); \ 1341ec6a845STyler Retzlaff RTE_BUILD_BUG_ON((memorder) != rte_memory_order_acquire && \ 1351ec6a845STyler Retzlaff (memorder) != rte_memory_order_relaxed); \ 136875f3509SFeifei Wang typeof(*(addr)) expected_value = (expected); \ 1371ec6a845STyler Retzlaff while (!((rte_atomic_load_explicit((addr), (memorder)) & (mask)) \ 1381ec6a845STyler Retzlaff cond expected_value)) \ 139875f3509SFeifei Wang rte_pause(); \ 140875f3509SFeifei Wang } while (0) 141875f3509SFeifei Wang #endif /* ! RTE_WAIT_UNTIL_EQUAL_ARCH_DEFINED */ 14299a2dd95SBruce Richardson 143*719834a6SMattias Rönnblom #ifdef __cplusplus 144*719834a6SMattias Rönnblom } 145*719834a6SMattias Rönnblom #endif 146*719834a6SMattias Rönnblom 14799a2dd95SBruce Richardson #endif /* _RTE_PAUSE_H_ */ 148