DPDK  21.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 static inline void
53 {
54  __atomic_store_n(&tl->tickets, 0, __ATOMIC_RELAXED);
55 }
56 
63 static inline void
65 {
66  uint16_t me = __atomic_fetch_add(&tl->s.next, 1, __ATOMIC_RELAXED);
67  rte_wait_until_equal_16(&tl->s.current, me, __ATOMIC_ACQUIRE);
68 }
69 
76 static inline void
78 {
79  uint16_t i = __atomic_load_n(&tl->s.current, __ATOMIC_RELAXED);
80  __atomic_store_n(&tl->s.current, i + 1, __ATOMIC_RELEASE);
81 }
82 
91 static inline int
93 {
94  rte_ticketlock_t old, new;
95  old.tickets = __atomic_load_n(&tl->tickets, __ATOMIC_RELAXED);
96  new.tickets = old.tickets;
97  new.s.next++;
98  if (old.s.next == old.s.current) {
99  if (__atomic_compare_exchange_n(&tl->tickets, &old.tickets,
100  new.tickets, 0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
101  return 1;
102  }
103 
104  return 0;
105 }
106 
115 static inline int
117 {
118  rte_ticketlock_t tic;
119  tic.tickets = __atomic_load_n(&tl->tickets, __ATOMIC_ACQUIRE);
120  return (tic.s.current != tic.s.next);
121 }
122 
126 #define TICKET_LOCK_INVALID_ID -1
127 
128 typedef struct {
129  rte_ticketlock_t tl;
130  int user;
131  unsigned int count;
132 } rte_ticketlock_recursive_t;
133 
137 #define RTE_TICKETLOCK_RECURSIVE_INITIALIZER {RTE_TICKETLOCK_INITIALIZER, \
138  TICKET_LOCK_INVALID_ID, 0}
139 
146 static inline void
147 rte_ticketlock_recursive_init(rte_ticketlock_recursive_t *tlr)
148 {
149  rte_ticketlock_init(&tlr->tl);
150  __atomic_store_n(&tlr->user, TICKET_LOCK_INVALID_ID, __ATOMIC_RELAXED);
151  tlr->count = 0;
152 }
153 
160 static inline void
161 rte_ticketlock_recursive_lock(rte_ticketlock_recursive_t *tlr)
162 {
163  int id = rte_gettid();
164 
165  if (__atomic_load_n(&tlr->user, __ATOMIC_RELAXED) != id) {
166  rte_ticketlock_lock(&tlr->tl);
167  __atomic_store_n(&tlr->user, id, __ATOMIC_RELAXED);
168  }
169  tlr->count++;
170 }
171 
178 static inline void
179 rte_ticketlock_recursive_unlock(rte_ticketlock_recursive_t *tlr)
180 {
181  if (--(tlr->count) == 0) {
182  __atomic_store_n(&tlr->user, TICKET_LOCK_INVALID_ID,
183  __ATOMIC_RELAXED);
184  rte_ticketlock_unlock(&tlr->tl);
185  }
186 }
187 
196 static inline int
197 rte_ticketlock_recursive_trylock(rte_ticketlock_recursive_t *tlr)
198 {
199  int id = rte_gettid();
200 
201  if (__atomic_load_n(&tlr->user, __ATOMIC_RELAXED) != id) {
202  if (rte_ticketlock_trylock(&tlr->tl) == 0)
203  return 0;
204  __atomic_store_n(&tlr->user, id, __ATOMIC_RELAXED);
205  }
206  tlr->count++;
207  return 1;
208 }
209 
210 #ifdef __cplusplus
211 }
212 #endif
213 
214 #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:86
static int rte_gettid(void)
Definition: rte_eal.h:471