DPDK 25.03.0-rc0
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#include <rte_common.h>
21#include <rte_lcore.h>
22#include <rte_pause.h>
23#include <rte_stdatomic.h>
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
32typedef 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
51static inline void
53{
54 rte_atomic_store_explicit(&tl->tickets, 0, rte_memory_order_relaxed);
55}
56
63static 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
77static 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
92static 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
117static inline int
119{
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
130typedef struct {
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
148static inline void
149rte_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
162static inline void
163rte_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
180static inline void
181rte_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
198static inline int
199rte_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 int rte_gettid(void)
Definition: rte_eal.h:438
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:84
#define TICKET_LOCK_INVALID_ID
static void rte_ticketlock_recursive_init(rte_ticketlock_recursive_t *tlr)
static void rte_ticketlock_init(rte_ticketlock_t *tl)
static void rte_ticketlock_unlock(rte_ticketlock_t *tl)
static void rte_ticketlock_recursive_lock(rte_ticketlock_recursive_t *tlr)
static void rte_ticketlock_lock(rte_ticketlock_t *tl)
static void rte_ticketlock_recursive_unlock(rte_ticketlock_recursive_t *tlr)
static int rte_ticketlock_is_locked(rte_ticketlock_t *tl)
static int rte_ticketlock_recursive_trylock(rte_ticketlock_recursive_t *tlr)
static int rte_ticketlock_trylock(rte_ticketlock_t *tl)