DPDK  24.03.0
rte_ticketlock.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019 Arm Limited
3  */
4 
5 #ifndef _RTE_TICKETLOCK_H_
6 #define _RTE_TICKETLOCK_H_
7 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 #include <rte_common.h>
25 #include <rte_lcore.h>
26 #include <rte_pause.h>
27 #include <rte_stdatomic.h>
28 
32 typedef union {
33  RTE_ATOMIC(uint32_t) tickets;
34  struct {
35  RTE_ATOMIC(uint16_t) current;
36  RTE_ATOMIC(uint16_t) next;
37  } s;
39 
43 #define RTE_TICKETLOCK_INITIALIZER { 0 }
44 
51 static inline void
53 {
54  rte_atomic_store_explicit(&tl->tickets, 0, rte_memory_order_relaxed);
55 }
56 
63 static inline void
65 {
66  uint16_t me = rte_atomic_fetch_add_explicit(&tl->s.next, 1, rte_memory_order_relaxed);
67  rte_wait_until_equal_16((uint16_t *)(uintptr_t)&tl->s.current, me,
68  rte_memory_order_acquire);
69 }
70 
77 static inline void
79 {
80  uint16_t i = rte_atomic_load_explicit(&tl->s.current, rte_memory_order_relaxed);
81  rte_atomic_store_explicit(&tl->s.current, i + 1, rte_memory_order_release);
82 }
83 
92 static inline int
94 {
95  rte_ticketlock_t oldl, newl;
96  oldl.tickets = rte_atomic_load_explicit(&tl->tickets, rte_memory_order_relaxed);
97  newl.tickets = oldl.tickets;
98  newl.s.next++;
99  if (oldl.s.next == oldl.s.current) {
100  if (rte_atomic_compare_exchange_strong_explicit(&tl->tickets,
101  (uint32_t *)(uintptr_t)&oldl.tickets, newl.tickets,
102  rte_memory_order_acquire, rte_memory_order_relaxed))
103  return 1;
104  }
105 
106  return 0;
107 }
108 
117 static inline int
119 {
120  rte_ticketlock_t tic;
121  tic.tickets = rte_atomic_load_explicit(&tl->tickets, rte_memory_order_acquire);
122  return (tic.s.current != tic.s.next);
123 }
124 
128 #define TICKET_LOCK_INVALID_ID -1
129 
130 typedef struct {
131  rte_ticketlock_t tl;
132  RTE_ATOMIC(int) user;
133  unsigned int count;
134 } rte_ticketlock_recursive_t;
135 
139 #define RTE_TICKETLOCK_RECURSIVE_INITIALIZER {RTE_TICKETLOCK_INITIALIZER, \
140  TICKET_LOCK_INVALID_ID, 0}
141 
148 static inline void
149 rte_ticketlock_recursive_init(rte_ticketlock_recursive_t *tlr)
150 {
151  rte_ticketlock_init(&tlr->tl);
152  rte_atomic_store_explicit(&tlr->user, TICKET_LOCK_INVALID_ID, rte_memory_order_relaxed);
153  tlr->count = 0;
154 }
155 
162 static inline void
163 rte_ticketlock_recursive_lock(rte_ticketlock_recursive_t *tlr)
164 {
165  int id = rte_gettid();
166 
167  if (rte_atomic_load_explicit(&tlr->user, rte_memory_order_relaxed) != id) {
168  rte_ticketlock_lock(&tlr->tl);
169  rte_atomic_store_explicit(&tlr->user, id, rte_memory_order_relaxed);
170  }
171  tlr->count++;
172 }
173 
180 static inline void
181 rte_ticketlock_recursive_unlock(rte_ticketlock_recursive_t *tlr)
182 {
183  if (--(tlr->count) == 0) {
184  rte_atomic_store_explicit(&tlr->user, TICKET_LOCK_INVALID_ID,
185  rte_memory_order_relaxed);
186  rte_ticketlock_unlock(&tlr->tl);
187  }
188 }
189 
198 static inline int
199 rte_ticketlock_recursive_trylock(rte_ticketlock_recursive_t *tlr)
200 {
201  int id = rte_gettid();
202 
203  if (rte_atomic_load_explicit(&tlr->user, rte_memory_order_relaxed) != id) {
204  if (rte_ticketlock_trylock(&tlr->tl) == 0)
205  return 0;
206  rte_atomic_store_explicit(&tlr->user, id, rte_memory_order_relaxed);
207  }
208  tlr->count++;
209  return 1;
210 }
211 
212 #ifdef __cplusplus
213 }
214 #endif
215 
216 #endif /* _RTE_TICKETLOCK_H_ */
static void rte_ticketlock_lock(rte_ticketlock_t *tl)
#define TICKET_LOCK_INVALID_ID
static __rte_always_inline void rte_wait_until_equal_16(volatile uint16_t *addr, uint16_t expected, rte_memory_order memorder)
Definition: rte_pause.h:80
static void rte_ticketlock_recursive_unlock(rte_ticketlock_recursive_t *tlr)
static int rte_ticketlock_is_locked(rte_ticketlock_t *tl)
static void rte_ticketlock_init(rte_ticketlock_t *tl)
static int rte_ticketlock_recursive_trylock(rte_ticketlock_recursive_t *tlr)
static void rte_ticketlock_recursive_init(rte_ticketlock_recursive_t *tlr)
static void rte_ticketlock_unlock(rte_ticketlock_t *tl)
static int rte_ticketlock_trylock(rte_ticketlock_t *tl)
static void rte_ticketlock_recursive_lock(rte_ticketlock_recursive_t *tlr)
static int rte_gettid(void)
Definition: rte_eal.h:438