DPDK  23.03.0
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
31 extern "C" {
32 #endif
33 
34 #include <rte_compat.h>
35 #include <rte_common.h>
36 #include <rte_pause.h>
37 
41 struct rte_pflock {
42  struct {
43  uint16_t in;
44  uint16_t out;
45  } rd, wr;
46 };
47 typedef 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
91 static 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
110 static inline void
111 rte_pflock_read_lock(rte_pflock_t *pf)
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
139 static inline void
140 rte_pflock_read_unlock(rte_pflock_t *pf)
141 {
142  __atomic_fetch_add(&pf->rd.out, RTE_PFLOCK_RINC, __ATOMIC_RELEASE);
143 }
144 
154 __rte_experimental
155 static inline void
156 rte_pflock_write_lock(rte_pflock_t *pf)
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
191 static inline void
192 rte_pflock_write_unlock(rte_pflock_t *pf)
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_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
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_always_inline void rte_wait_until_equal_16(volatile uint16_t *addr, uint16_t expected, int memorder)
Definition: rte_pause.h:85