DPDK 22.11.5
rte_pflock.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2021 Microsoft Corp.
3 * All rights reserved.
4 *
5 * Derived from Concurrency Kit
6 * Copyright 2011-2015 Samy Al Bahra.
7 */
8
9#ifndef _RTE_PFLOCK_H_
10#define _RTE_PFLOCK_H_
11
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34#include <rte_compat.h>
35#include <rte_common.h>
36#include <rte_pause.h>
37
41struct rte_pflock {
42 struct {
43 uint16_t in;
44 uint16_t out;
45 } rd, wr;
46};
47typedef struct rte_pflock rte_pflock_t;
48
49/*
50 * Allocation of bits to reader
51 *
52 * 15 4 3 2 1 0
53 * +-------------------+---+-+-+
54 * | rin: reads issued |x|x| | |
55 * +-------------------+---+-+-+
56 * ^ ^
57 * | |
58 * PRES: writer present ----/ |
59 * PHID: writer phase id -----/
60 *
61 * 15 4 3 2 1 0
62 * +------------------+------+
63 * |rout:read complete|unused|
64 * +------------------+------+
65 *
66 * The maximum number of readers is 4095
67 */
68
69/* Constants used to map the bits in reader counter */
70#define RTE_PFLOCK_WBITS 0x3 /* Writer bits in reader. */
71#define RTE_PFLOCK_PRES 0x2 /* Writer present bit. */
72#define RTE_PFLOCK_PHID 0x1 /* Phase ID bit. */
73#define RTE_PFLOCK_LSB 0xFFF0 /* reader bits. */
74#define RTE_PFLOCK_RINC 0x10 /* Reader increment. */
75
79#define RTE_PFLOCK_INITIALIZER { }
80
90__rte_experimental
91static inline void
93{
94 pf->rd.in = 0;
95 pf->rd.out = 0;
96 pf->wr.in = 0;
97 pf->wr.out = 0;
98}
99
109__rte_experimental
110static inline void
112{
113 uint16_t w;
114
115 /*
116 * If no writer is present, then the operation has completed
117 * successfully.
118 */
119 w = __atomic_fetch_add(&pf->rd.in, RTE_PFLOCK_RINC, __ATOMIC_ACQUIRE)
120 & RTE_PFLOCK_WBITS;
121 if (w == 0)
122 return;
123
124 /* Wait for current write phase to complete. */
125 RTE_WAIT_UNTIL_MASKED(&pf->rd.in, RTE_PFLOCK_WBITS, !=, w,
126 __ATOMIC_ACQUIRE);
127}
128
138__rte_experimental
139static inline void
141{
142 __atomic_fetch_add(&pf->rd.out, RTE_PFLOCK_RINC, __ATOMIC_RELEASE);
143}
144
154__rte_experimental
155static inline void
157{
158 uint16_t ticket, w;
159
160 /* Acquire ownership of write-phase.
161 * This is same as rte_ticketlock_lock().
162 */
163 ticket = __atomic_fetch_add(&pf->wr.in, 1, __ATOMIC_RELAXED);
164 rte_wait_until_equal_16(&pf->wr.out, ticket, __ATOMIC_ACQUIRE);
165
166 /*
167 * Acquire ticket on read-side in order to allow them
168 * to flush. Indicates to any incoming reader that a
169 * write-phase is pending.
170 *
171 * The load of rd.out in wait loop could be executed
172 * speculatively.
173 */
174 w = RTE_PFLOCK_PRES | (ticket & RTE_PFLOCK_PHID);
175 ticket = __atomic_fetch_add(&pf->rd.in, w, __ATOMIC_RELAXED);
176
177 /* Wait for any pending readers to flush. */
178 rte_wait_until_equal_16(&pf->rd.out, ticket, __ATOMIC_ACQUIRE);
179}
180
190__rte_experimental
191static inline void
193{
194 /* Migrate from write phase to read phase. */
195 __atomic_fetch_and(&pf->rd.in, RTE_PFLOCK_LSB, __ATOMIC_RELEASE);
196
197 /* Allow other writers to continue. */
198 __atomic_fetch_add(&pf->wr.out, 1, __ATOMIC_RELEASE);
199}
200
201#ifdef __cplusplus
202}
203#endif
204
205#endif /* RTE_PFLOCK_H */
static __rte_always_inline void rte_wait_until_equal_16(volatile uint16_t *addr, uint16_t expected, int memorder)
Definition: rte_pause.h:85
static __rte_experimental void rte_pflock_read_lock(rte_pflock_t *pf)
Definition: rte_pflock.h:111
static __rte_experimental void rte_pflock_write_unlock(rte_pflock_t *pf)
Definition: rte_pflock.h:192
static __rte_experimental void rte_pflock_write_lock(rte_pflock_t *pf)
Definition: rte_pflock.h:156
static __rte_experimental void rte_pflock_init(struct rte_pflock *pf)
Definition: rte_pflock.h:92
static __rte_experimental void rte_pflock_read_unlock(rte_pflock_t *pf)
Definition: rte_pflock.h:140