DPDK  20.08.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 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 #include <rte_common.h>
26 #include <rte_lcore.h>
27 #include <rte_pause.h>
28 
32 typedef union {
33  uint32_t tickets;
34  struct {
35  uint16_t current;
36  uint16_t next;
37  } s;
39 
43 #define RTE_TICKETLOCK_INITIALIZER { 0 }
44 
51 __rte_experimental
52 static inline void
54 {
55  __atomic_store_n(&tl->tickets, 0, __ATOMIC_RELAXED);
56 }
57 
64 __rte_experimental
65 static inline void
67 {
68  uint16_t me = __atomic_fetch_add(&tl->s.next, 1, __ATOMIC_RELAXED);
69  rte_wait_until_equal_16(&tl->s.current, me, __ATOMIC_ACQUIRE);
70 }
71 
78 __rte_experimental
79 static inline void
81 {
82  uint16_t i = __atomic_load_n(&tl->s.current, __ATOMIC_RELAXED);
83  __atomic_store_n(&tl->s.current, i + 1, __ATOMIC_RELEASE);
84 }
85 
94 __rte_experimental
95 static inline int
97 {
98  rte_ticketlock_t old, new;
99  old.tickets = __atomic_load_n(&tl->tickets, __ATOMIC_RELAXED);
100  new.tickets = old.tickets;
101  new.s.next++;
102  if (old.s.next == old.s.current) {
103  if (__atomic_compare_exchange_n(&tl->tickets, &old.tickets,
104  new.tickets, 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
105  return 1;
106  }
107 
108  return 0;
109 }
110 
119 __rte_experimental
120 static inline int
122 {
123  rte_ticketlock_t tic;
124  tic.tickets = __atomic_load_n(&tl->tickets, __ATOMIC_ACQUIRE);
125  return (tic.s.current != tic.s.next);
126 }
127 
131 #define TICKET_LOCK_INVALID_ID -1
132 
133 typedef struct {
134  rte_ticketlock_t tl;
135  int user;
136  unsigned int count;
137 } rte_ticketlock_recursive_t;
138 
142 #define RTE_TICKETLOCK_RECURSIVE_INITIALIZER {RTE_TICKETLOCK_INITIALIZER, \
143  TICKET_LOCK_INVALID_ID, 0}
144 
151 __rte_experimental
152 static inline void
153 rte_ticketlock_recursive_init(rte_ticketlock_recursive_t *tlr)
154 {
155  rte_ticketlock_init(&tlr->tl);
156  __atomic_store_n(&tlr->user, TICKET_LOCK_INVALID_ID, __ATOMIC_RELAXED);
157  tlr->count = 0;
158 }
159 
166 __rte_experimental
167 static inline void
168 rte_ticketlock_recursive_lock(rte_ticketlock_recursive_t *tlr)
169 {
170  int id = rte_gettid();
171 
172  if (__atomic_load_n(&tlr->user, __ATOMIC_RELAXED) != id) {
173  rte_ticketlock_lock(&tlr->tl);
174  __atomic_store_n(&tlr->user, id, __ATOMIC_RELAXED);
175  }
176  tlr->count++;
177 }
178 
185 __rte_experimental
186 static inline void
187 rte_ticketlock_recursive_unlock(rte_ticketlock_recursive_t *tlr)
188 {
189  if (--(tlr->count) == 0) {
190  __atomic_store_n(&tlr->user, TICKET_LOCK_INVALID_ID,
191  __ATOMIC_RELAXED);
192  rte_ticketlock_unlock(&tlr->tl);
193  }
194 }
195 
204 __rte_experimental
205 static inline int
206 rte_ticketlock_recursive_trylock(rte_ticketlock_recursive_t *tlr)
207 {
208  int id = rte_gettid();
209 
210  if (__atomic_load_n(&tlr->user, __ATOMIC_RELAXED) != id) {
211  if (rte_ticketlock_trylock(&tlr->tl) == 0)
212  return 0;
213  __atomic_store_n(&tlr->user, id, __ATOMIC_RELAXED);
214  }
215  tlr->count++;
216  return 1;
217 }
218 
219 #ifdef __cplusplus
220 }
221 #endif
222 
223 #endif /* _RTE_TICKETLOCK_H_ */
#define TICKET_LOCK_INVALID_ID
static __rte_experimental void rte_ticketlock_recursive_unlock(rte_ticketlock_recursive_t *tlr)
static __rte_experimental void rte_ticketlock_lock(rte_ticketlock_t *tl)
static __rte_experimental void rte_ticketlock_unlock(rte_ticketlock_t *tl)
static __rte_experimental void rte_ticketlock_recursive_init(rte_ticketlock_recursive_t *tlr)
static __rte_experimental void rte_ticketlock_init(rte_ticketlock_t *tl)
static __rte_experimental int rte_ticketlock_recursive_trylock(rte_ticketlock_recursive_t *tlr)
static __rte_experimental int rte_ticketlock_trylock(rte_ticketlock_t *tl)
static __rte_experimental __rte_always_inline void rte_wait_until_equal_16(volatile uint16_t *addr, uint16_t expected, int memorder)
Definition: rte_pause.h:98
static __rte_experimental int rte_ticketlock_is_locked(rte_ticketlock_t *tl)
static __rte_experimental void rte_ticketlock_recursive_lock(rte_ticketlock_recursive_t *tlr)
static int rte_gettid(void)
Definition: rte_eal.h:478