DPDK  26.07.0
rte_spinlock.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4 
5 #ifndef _RTE_SPINLOCK_H_
6 #define _RTE_SPINLOCK_H_
7 
24 #include <rte_lcore.h>
25 #ifdef RTE_FORCE_INTRINSICS
26 #include <rte_common.h>
27 #endif
28 #include <rte_debug.h>
29 #include <rte_lock_annotations.h>
30 #include <rte_pause.h>
31 #include <rte_stdatomic.h>
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
40 typedef struct __rte_capability("spinlock") {
41  volatile RTE_ATOMIC(int) locked;
43 
47 #define RTE_SPINLOCK_INITIALIZER { 0 }
48 
55 static inline void
57 {
58  sl->locked = 0;
59 }
60 
67 static inline void
69  __rte_acquire_capability(sl);
70 
71 #ifdef RTE_FORCE_INTRINSICS
72 static inline void
74  __rte_no_thread_safety_analysis
75 {
76  int exp = 0;
77 
78  while (!rte_atomic_compare_exchange_strong_explicit(&sl->locked, &exp, 1,
79  rte_memory_order_acquire, rte_memory_order_relaxed)) {
80  rte_wait_until_equal_32((volatile uint32_t *)(uintptr_t)&sl->locked,
81  0, rte_memory_order_relaxed);
82  exp = 0;
83  }
84 }
85 #endif
86 
93 static inline void
95  __rte_release_capability(sl);
96 
97 #ifdef RTE_FORCE_INTRINSICS
98 static inline void
100  __rte_no_thread_safety_analysis
101 {
102  rte_atomic_store_explicit(&sl->locked, 0, rte_memory_order_release);
103 }
104 #endif
105 
115 static inline int
117  __rte_try_acquire_capability(true, sl);
118 
119 #ifdef RTE_FORCE_INTRINSICS
120 static inline int
122  __rte_no_thread_safety_analysis
123 {
124  int exp = 0;
125  return rte_atomic_compare_exchange_strong_explicit(&sl->locked, &exp, 1,
126  rte_memory_order_acquire, rte_memory_order_relaxed);
127 }
128 #endif
129 
138 static inline int rte_spinlock_is_locked (rte_spinlock_t *sl)
139 {
140  return rte_atomic_load_explicit(&sl->locked, rte_memory_order_acquire);
141 }
142 
149 static inline int rte_tm_supported(void);
150 
164 static inline void
166  __rte_acquire_capability(sl);
167 
175 static inline void
177  __rte_release_capability(sl);
178 
196 static inline int
198  __rte_try_acquire_capability(true, sl);
199 
203 typedef struct {
205  RTE_ATOMIC(int) owner;
206  int count;
208 
212 #define RTE_SPINLOCK_RECURSIVE_INITIALIZER {RTE_SPINLOCK_INITIALIZER, -1, 0}
213 
221 {
222  rte_spinlock_init(&slr->sl);
223  rte_atomic_store_explicit(&slr->owner, -1, rte_memory_order_relaxed);
224  slr->count = 0;
225 }
226 
234  __rte_no_thread_safety_analysis
235 {
236  int id = rte_gettid();
237 
238  if (rte_atomic_load_explicit(&slr->owner, rte_memory_order_relaxed) != id) {
239  rte_spinlock_lock(&slr->sl);
240  rte_atomic_store_explicit(&slr->owner, id, rte_memory_order_relaxed);
241  }
242  slr->count++;
243 }
251  __rte_no_thread_safety_analysis
252 {
253  RTE_ASSERT(rte_atomic_load_explicit(&slr->owner, rte_memory_order_relaxed) == rte_gettid());
254  RTE_ASSERT(slr->count > 0);
255  if (--(slr->count) == 0) {
256  rte_atomic_store_explicit(&slr->owner, -1, rte_memory_order_relaxed);
257  rte_spinlock_unlock(&slr->sl);
258  }
259 }
260 
271  __rte_no_thread_safety_analysis
272 {
273  int id = rte_gettid();
274 
275  if (rte_atomic_load_explicit(&slr->owner, rte_memory_order_relaxed) != id) {
276  if (rte_spinlock_trylock(&slr->sl) == 0)
277  return 0;
278  rte_atomic_store_explicit(&slr->owner, id, rte_memory_order_relaxed);
279  }
280  slr->count++;
281  return 1;
282 }
283 
284 
298 static inline void rte_spinlock_recursive_lock_tm(
300 
308 static inline void rte_spinlock_recursive_unlock_tm(
310 
328 static inline int rte_spinlock_recursive_trylock_tm(
330 
331 #ifdef __cplusplus
332 }
333 #endif
334 
335 #endif /* _RTE_SPINLOCK_H_ */
static __rte_warn_unused_result int rte_spinlock_trylock_tm(rte_spinlock_t *sl) sl)
static void rte_spinlock_recursive_lock_tm(rte_spinlock_recursive_t *slr)
static void rte_spinlock_lock(rte_spinlock_t *sl)
static __rte_always_inline void rte_wait_until_equal_32(volatile uint32_t *addr, uint32_t expected, rte_memory_order memorder)
Definition: rte_pause.h:95
static void rte_spinlock_recursive_unlock(rte_spinlock_recursive_t *slr) __rte_no_thread_safety_analysis
Definition: rte_spinlock.h:250
static __rte_warn_unused_result int rte_spinlock_recursive_trylock_tm(rte_spinlock_recursive_t *slr)
static void rte_spinlock_recursive_init(rte_spinlock_recursive_t *slr)
Definition: rte_spinlock.h:220
static void rte_spinlock_unlock(rte_spinlock_t *sl)
static void rte_spinlock_unlock_tm(rte_spinlock_t *sl)
static __rte_warn_unused_result int rte_spinlock_recursive_trylock(rte_spinlock_recursive_t *slr) __rte_no_thread_safety_analysis
Definition: rte_spinlock.h:270
static void rte_spinlock_init(rte_spinlock_t *sl)
Definition: rte_spinlock.h:56
static int rte_tm_supported(void)
static __rte_warn_unused_result int rte_spinlock_trylock(rte_spinlock_t *sl) sl)
static void rte_spinlock_recursive_unlock_tm(rte_spinlock_recursive_t *slr)
static int rte_spinlock_is_locked(rte_spinlock_t *sl)
Definition: rte_spinlock.h:138
static void rte_spinlock_recursive_lock(rte_spinlock_recursive_t *slr) __rte_no_thread_safety_analysis
Definition: rte_spinlock.h:233
static void rte_spinlock_lock_tm(rte_spinlock_t *sl)
static int rte_gettid(void)
Definition: rte_eal.h:439
#define __rte_warn_unused_result
Definition: rte_common.h:481