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