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