1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
5 #ifndef _RTE_SPINLOCK_H_
6 #define _RTE_SPINLOCK_H_
13 * This file defines an API for read-write locks, which are implemented
14 * in an architecture-specific way. This kind of lock simply waits in
15 * a loop repeatedly checking until the lock becomes available.
17 * All locks must be initialised before use, and only initialised once.
21 #include <rte_lcore.h>
22 #ifdef RTE_FORCE_INTRINSICS
23 #include <rte_common.h>
25 #include <rte_pause.h>
28 * The rte_spinlock_t type.
31 volatile int locked; /**< lock status 0 = unlocked, 1 = locked */
35 * A static spinlock initializer.
37 #define RTE_SPINLOCK_INITIALIZER { 0 }
40 * Initialize the spinlock to an unlocked state.
43 * A pointer to the spinlock.
46 rte_spinlock_init(rte_spinlock_t *sl)
55 * A pointer to the spinlock.
58 rte_spinlock_lock(rte_spinlock_t *sl);
60 #ifdef RTE_FORCE_INTRINSICS
62 rte_spinlock_lock(rte_spinlock_t *sl)
64 while (__sync_lock_test_and_set(&sl->locked, 1))
71 * Release the spinlock.
74 * A pointer to the spinlock.
77 rte_spinlock_unlock (rte_spinlock_t *sl);
79 #ifdef RTE_FORCE_INTRINSICS
81 rte_spinlock_unlock (rte_spinlock_t *sl)
83 __sync_lock_release(&sl->locked);
88 * Try to take the lock.
91 * A pointer to the spinlock.
93 * 1 if the lock is successfully taken; 0 otherwise.
96 rte_spinlock_trylock (rte_spinlock_t *sl);
98 #ifdef RTE_FORCE_INTRINSICS
100 rte_spinlock_trylock (rte_spinlock_t *sl)
102 return __sync_lock_test_and_set(&sl->locked,1) == 0;
107 * Test if the lock is taken.
110 * A pointer to the spinlock.
112 * 1 if the lock is currently taken; 0 otherwise.
114 static inline int rte_spinlock_is_locked (rte_spinlock_t *sl)
120 * Test if hardware transactional memory (lock elision) is supported
123 * 1 if the hardware transactional memory is supported; 0 otherwise.
125 static inline int rte_tm_supported(void);
128 * Try to execute critical section in a hardware memory transaction,
129 * if it fails or not available take the spinlock.
131 * NOTE: An attempt to perform a HW I/O operation inside a hardware memory
132 * transaction always aborts the transaction since the CPU is not able to
133 * roll-back should the transaction fail. Therefore, hardware transactional
134 * locks are not advised to be used around rte_eth_rx_burst() and
135 * rte_eth_tx_burst() calls.
138 * A pointer to the spinlock.
141 rte_spinlock_lock_tm(rte_spinlock_t *sl);
144 * Commit hardware memory transaction or release the spinlock if
145 * the spinlock is used as a fall-back
148 * A pointer to the spinlock.
151 rte_spinlock_unlock_tm(rte_spinlock_t *sl);
154 * Try to execute critical section in a hardware memory transaction,
155 * if it fails or not available try to take the lock.
157 * NOTE: An attempt to perform a HW I/O operation inside a hardware memory
158 * transaction always aborts the transaction since the CPU is not able to
159 * roll-back should the transaction fail. Therefore, hardware transactional
160 * locks are not advised to be used around rte_eth_rx_burst() and
161 * rte_eth_tx_burst() calls.
164 * A pointer to the spinlock.
166 * 1 if the hardware memory transaction is successfully started
167 * or lock is successfully taken; 0 otherwise.
170 rte_spinlock_trylock_tm(rte_spinlock_t *sl);
173 * The rte_spinlock_recursive_t type.
176 rte_spinlock_t sl; /**< the actual spinlock */
177 volatile int user; /**< core id using lock, -1 for unused */
178 volatile int count; /**< count of time this lock has been called */
179 } rte_spinlock_recursive_t;
182 * A static recursive spinlock initializer.
184 #define RTE_SPINLOCK_RECURSIVE_INITIALIZER {RTE_SPINLOCK_INITIALIZER, -1, 0}
187 * Initialize the recursive spinlock to an unlocked state.
190 * A pointer to the recursive spinlock.
192 static inline void rte_spinlock_recursive_init(rte_spinlock_recursive_t *slr)
194 rte_spinlock_init(&slr->sl);
200 * Take the recursive spinlock.
203 * A pointer to the recursive spinlock.
205 static inline void rte_spinlock_recursive_lock(rte_spinlock_recursive_t *slr)
207 int id = rte_gettid();
209 if (slr->user != id) {
210 rte_spinlock_lock(&slr->sl);
216 * Release the recursive spinlock.
219 * A pointer to the recursive spinlock.
221 static inline void rte_spinlock_recursive_unlock(rte_spinlock_recursive_t *slr)
223 if (--(slr->count) == 0) {
225 rte_spinlock_unlock(&slr->sl);
231 * Try to take the recursive lock.
234 * A pointer to the recursive spinlock.
236 * 1 if the lock is successfully taken; 0 otherwise.
238 static inline int rte_spinlock_recursive_trylock(rte_spinlock_recursive_t *slr)
240 int id = rte_gettid();
242 if (slr->user != id) {
243 if (rte_spinlock_trylock(&slr->sl) == 0)
253 * Try to execute critical section in a hardware memory transaction,
254 * if it fails or not available take the recursive spinlocks
256 * NOTE: An attempt to perform a HW I/O operation inside a hardware memory
257 * transaction always aborts the transaction since the CPU is not able to
258 * roll-back should the transaction fail. Therefore, hardware transactional
259 * locks are not advised to be used around rte_eth_rx_burst() and
260 * rte_eth_tx_burst() calls.
263 * A pointer to the recursive spinlock.
265 static inline void rte_spinlock_recursive_lock_tm(
266 rte_spinlock_recursive_t *slr);
269 * Commit hardware memory transaction or release the recursive spinlock
270 * if the recursive spinlock is used as a fall-back
273 * A pointer to the recursive spinlock.
275 static inline void rte_spinlock_recursive_unlock_tm(
276 rte_spinlock_recursive_t *slr);
279 * Try to execute critical section in a hardware memory transaction,
280 * if it fails or not available try to take the recursive lock
282 * NOTE: An attempt to perform a HW I/O operation inside a hardware memory
283 * transaction always aborts the transaction since the CPU is not able to
284 * roll-back should the transaction fail. Therefore, hardware transactional
285 * locks are not advised to be used around rte_eth_rx_burst() and
286 * rte_eth_tx_burst() calls.
289 * A pointer to the recursive spinlock.
291 * 1 if the hardware memory transaction is successfully started
292 * or lock is successfully taken; 0 otherwise.
294 static inline int rte_spinlock_recursive_trylock_tm(
295 rte_spinlock_recursive_t *slr);
297 #endif /* _RTE_SPINLOCK_H_ */