DPDK  23.07.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 
31 typedef union {
32  uint32_t tickets;
33  struct {
34  uint16_t current;
35  uint16_t next;
36  } s;
38 
42 #define RTE_TICKETLOCK_INITIALIZER { 0 }
43 
50 static inline void
52 {
53  __atomic_store_n(&tl->tickets, 0, __ATOMIC_RELAXED);
54 }
55 
62 static inline void
64 {
65  uint16_t me = __atomic_fetch_add(&tl->s.next, 1, __ATOMIC_RELAXED);
66  rte_wait_until_equal_16(&tl->s.current, me, __ATOMIC_ACQUIRE);
67 }
68 
75 static inline void
77 {
78  uint16_t i = __atomic_load_n(&tl->s.current, __ATOMIC_RELAXED);
79  __atomic_store_n(&tl->s.current, i + 1, __ATOMIC_RELEASE);
80 }
81 
90 static inline int
92 {
93  rte_ticketlock_t oldl, newl;
94  oldl.tickets = __atomic_load_n(&tl->tickets, __ATOMIC_RELAXED);
95  newl.tickets = oldl.tickets;
96  newl.s.next++;
97  if (oldl.s.next == oldl.s.current) {
98  if (__atomic_compare_exchange_n(&tl->tickets, &oldl.tickets,
99  newl.tickets, 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
100  return 1;
101  }
102 
103  return 0;
104 }
105 
114 static inline int
116 {
117  rte_ticketlock_t tic;
118  tic.tickets = __atomic_load_n(&tl->tickets, __ATOMIC_ACQUIRE);
119  return (tic.s.current != tic.s.next);
120 }
121 
125 #define TICKET_LOCK_INVALID_ID -1
126 
127 typedef struct {
128  rte_ticketlock_t tl;
129  int user;
130  unsigned int count;
131 } rte_ticketlock_recursive_t;
132 
136 #define RTE_TICKETLOCK_RECURSIVE_INITIALIZER {RTE_TICKETLOCK_INITIALIZER, \
137  TICKET_LOCK_INVALID_ID, 0}
138 
145 static inline void
146 rte_ticketlock_recursive_init(rte_ticketlock_recursive_t *tlr)
147 {
148  rte_ticketlock_init(&tlr->tl);
149  __atomic_store_n(&tlr->user, TICKET_LOCK_INVALID_ID, __ATOMIC_RELAXED);
150  tlr->count = 0;
151 }
152 
159 static inline void
160 rte_ticketlock_recursive_lock(rte_ticketlock_recursive_t *tlr)
161 {
162  int id = rte_gettid();
163 
164  if (__atomic_load_n(&tlr->user, __ATOMIC_RELAXED) != id) {
165  rte_ticketlock_lock(&tlr->tl);
166  __atomic_store_n(&tlr->user, id, __ATOMIC_RELAXED);
167  }
168  tlr->count++;
169 }
170 
177 static inline void
178 rte_ticketlock_recursive_unlock(rte_ticketlock_recursive_t *tlr)
179 {
180  if (--(tlr->count) == 0) {
181  __atomic_store_n(&tlr->user, TICKET_LOCK_INVALID_ID,
182  __ATOMIC_RELAXED);
183  rte_ticketlock_unlock(&tlr->tl);
184  }
185 }
186 
195 static inline int
196 rte_ticketlock_recursive_trylock(rte_ticketlock_recursive_t *tlr)
197 {
198  int id = rte_gettid();
199 
200  if (__atomic_load_n(&tlr->user, __ATOMIC_RELAXED) != id) {
201  if (rte_ticketlock_trylock(&tlr->tl) == 0)
202  return 0;
203  __atomic_store_n(&tlr->user, id, __ATOMIC_RELAXED);
204  }
205  tlr->count++;
206  return 1;
207 }
208 
209 #ifdef __cplusplus
210 }
211 #endif
212 
213 #endif /* _RTE_TICKETLOCK_H_ */
static void rte_ticketlock_lock(rte_ticketlock_t *tl)
#define TICKET_LOCK_INVALID_ID
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 __rte_always_inline void rte_wait_until_equal_16(volatile uint16_t *addr, uint16_t expected, int memorder)
Definition: rte_pause.h:84
static int rte_gettid(void)
Definition: rte_eal.h:445