DPDK 22.11.4
rte_rwlock.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
3 */
4
5#ifndef _RTE_RWLOCK_H_
6#define _RTE_RWLOCK_H_
7
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29#include <errno.h>
30
32#include <rte_common.h>
33#include <rte_pause.h>
34
52#define RTE_RWLOCK_WAIT 0x1 /* Writer is waiting */
53#define RTE_RWLOCK_WRITE 0x2 /* Writer has the lock */
54#define RTE_RWLOCK_MASK (RTE_RWLOCK_WAIT | RTE_RWLOCK_WRITE)
55 /* Writer is waiting or has lock */
56#define RTE_RWLOCK_READ 0x4 /* Reader increment */
57
58typedef struct {
59 int32_t cnt;
60} rte_rwlock_t;
61
65#define RTE_RWLOCK_INITIALIZER { 0 }
66
73static inline void
74rte_rwlock_init(rte_rwlock_t *rwl)
75{
76 rwl->cnt = 0;
77}
78
89static inline void
90rte_rwlock_read_lock(rte_rwlock_t *rwl)
91{
92 int32_t x;
93
94 while (1) {
95 /* Wait while writer is present or pending */
96 while (__atomic_load_n(&rwl->cnt, __ATOMIC_RELAXED)
97 & RTE_RWLOCK_MASK)
98 rte_pause();
99
100 /* Try to get read lock */
101 x = __atomic_add_fetch(&rwl->cnt, RTE_RWLOCK_READ,
102 __ATOMIC_ACQUIRE);
103
104 /* If no writer, then acquire was successful */
105 if (likely(!(x & RTE_RWLOCK_MASK)))
106 return;
107
108 /* Lost race with writer, backout the change. */
109 __atomic_fetch_sub(&rwl->cnt, RTE_RWLOCK_READ,
110 __ATOMIC_RELAXED);
111 }
112}
113
124static inline int
125rte_rwlock_read_trylock(rte_rwlock_t *rwl)
126{
127 int32_t x;
128
129 x = __atomic_load_n(&rwl->cnt, __ATOMIC_RELAXED);
130
131 /* fail if write lock is held or writer is pending */
132 if (x & RTE_RWLOCK_MASK)
133 return -EBUSY;
134
135 /* Try to get read lock */
136 x = __atomic_add_fetch(&rwl->cnt, RTE_RWLOCK_READ,
137 __ATOMIC_ACQUIRE);
138
139 /* Back out if writer raced in */
140 if (unlikely(x & RTE_RWLOCK_MASK)) {
141 __atomic_fetch_sub(&rwl->cnt, RTE_RWLOCK_READ,
142 __ATOMIC_RELEASE);
143
144 return -EBUSY;
145 }
146 return 0;
147}
148
155static inline void
156rte_rwlock_read_unlock(rte_rwlock_t *rwl)
157{
158 __atomic_fetch_sub(&rwl->cnt, RTE_RWLOCK_READ, __ATOMIC_RELEASE);
159}
160
171static inline int
172rte_rwlock_write_trylock(rte_rwlock_t *rwl)
173{
174 int32_t x;
175
176 x = __atomic_load_n(&rwl->cnt, __ATOMIC_RELAXED);
177 if (x < RTE_RWLOCK_WRITE &&
178 __atomic_compare_exchange_n(&rwl->cnt, &x, x + RTE_RWLOCK_WRITE,
179 1, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
180 return 0;
181 else
182 return -EBUSY;
183}
184
191static inline void
192rte_rwlock_write_lock(rte_rwlock_t *rwl)
193{
194 int32_t x;
195
196 while (1) {
197 x = __atomic_load_n(&rwl->cnt, __ATOMIC_RELAXED);
198
199 /* No readers or writers? */
200 if (likely(x < RTE_RWLOCK_WRITE)) {
201 /* Turn off RTE_RWLOCK_WAIT, turn on RTE_RWLOCK_WRITE */
202 if (__atomic_compare_exchange_n(&rwl->cnt, &x, RTE_RWLOCK_WRITE, 1,
203 __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
204 return;
205 }
206
207 /* Turn on writer wait bit */
208 if (!(x & RTE_RWLOCK_WAIT))
209 __atomic_fetch_or(&rwl->cnt, RTE_RWLOCK_WAIT, __ATOMIC_RELAXED);
210
211 /* Wait until no readers before trying again */
212 while (__atomic_load_n(&rwl->cnt, __ATOMIC_RELAXED) > RTE_RWLOCK_WAIT)
213 rte_pause();
214
215 }
216}
217
224static inline void
225rte_rwlock_write_unlock(rte_rwlock_t *rwl)
226{
227 __atomic_fetch_sub(&rwl->cnt, RTE_RWLOCK_WRITE, __ATOMIC_RELEASE);
228}
229
243static inline void
244rte_rwlock_read_lock_tm(rte_rwlock_t *rwl);
245
252static inline void
253rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl);
254
268static inline void
269rte_rwlock_write_lock_tm(rte_rwlock_t *rwl);
270
277static inline void
278rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl);
279
280#ifdef __cplusplus
281}
282#endif
283
284#endif /* _RTE_RWLOCK_H_ */
#define likely(x)
#define unlikely(x)
static void rte_pause(void)
static void rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl)
static void rte_rwlock_write_unlock(rte_rwlock_t *rwl)
Definition: rte_rwlock.h:225
static void rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl)
static int rte_rwlock_write_trylock(rte_rwlock_t *rwl)
Definition: rte_rwlock.h:172
static void rte_rwlock_write_lock(rte_rwlock_t *rwl)
Definition: rte_rwlock.h:192
#define RTE_RWLOCK_WAIT
Definition: rte_rwlock.h:52
static void rte_rwlock_read_lock_tm(rte_rwlock_t *rwl)
static void rte_rwlock_read_lock(rte_rwlock_t *rwl)
Definition: rte_rwlock.h:90
static void rte_rwlock_init(rte_rwlock_t *rwl)
Definition: rte_rwlock.h:74
static void rte_rwlock_write_lock_tm(rte_rwlock_t *rwl)
static int rte_rwlock_read_trylock(rte_rwlock_t *rwl)
Definition: rte_rwlock.h:125
static void rte_rwlock_read_unlock(rte_rwlock_t *rwl)
Definition: rte_rwlock.h:156