blob: dc9e4fbed87c27a55a67c81de2ea8a5283f13ae1 [file] [log] [blame]
Dave Barach68b0fb02017-02-28 15:15:56 -05001/*
Florin Corasc5df8c72019-04-08 07:42:30 -07002 * Copyright (c) 2016-2019 Cisco and/or its affiliates.
Sirshak Das28aa5392019-02-05 01:33:33 -06003 * Copyright (c) 2019 Arm Limited
4 * Copyright (c) 2010-2017 Intel Corporation and/or its affiliates.
5 * Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org
6 * Inspired from DPDK rte_ring.h (SPSC only) (derived from freebsd bufring.h).
Dave Barach68b0fb02017-02-28 15:15:56 -05007 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at:
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
Florin Coras6792ec02017-03-13 03:49:51 -070020#include <svm/svm_fifo.h>
Florin Corasf22f4e52019-12-19 16:10:58 -080021#include <svm/fifo_segment.h>
Florin Corasf6359c82017-06-19 12:26:09 -040022#include <vppinfra/cpu.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050023
Florin Corasaf588822020-12-09 12:51:13 -080024#define F_INVALID_CPTR (svm_fifo_chunk_ptr_t) ~0ULL
25
26CLIB_MARCH_FN (svm_fifo_copy_to_chunk, void, svm_fifo_t *f,
27 svm_fifo_chunk_t *c, u32 tail_idx, const u8 *src, u32 len,
28 svm_fifo_chunk_ptr_t *last)
Florin Coras99ad2fc2019-04-18 21:25:49 -070029{
30 u32 n_chunk;
31
Florin Corasf22f4e52019-12-19 16:10:58 -080032 ASSERT (f_pos_geq (tail_idx, c->start_byte)
33 && f_pos_lt (tail_idx, c->start_byte + c->length));
Florin Coras99ad2fc2019-04-18 21:25:49 -070034
35 tail_idx -= c->start_byte;
36 n_chunk = c->length - tail_idx;
Florin Coras4375fa32019-04-19 15:56:00 -070037 if (n_chunk <= len)
Florin Coras99ad2fc2019-04-18 21:25:49 -070038 {
39 u32 to_copy = len;
40 clib_memcpy_fast (&c->data[tail_idx], src, n_chunk);
Florin Corasaf588822020-12-09 12:51:13 -080041 c = f_cptr (f, c->next);
Florin Coras99ad2fc2019-04-18 21:25:49 -070042 while ((to_copy -= n_chunk))
43 {
Florin Coras99ad2fc2019-04-18 21:25:49 -070044 n_chunk = clib_min (c->length, to_copy);
45 clib_memcpy_fast (&c->data[0], src + (len - to_copy), n_chunk);
Florin Corasaf588822020-12-09 12:51:13 -080046 c = c->length <= to_copy ? f_cptr (f, c->next) : c;
Florin Coras99ad2fc2019-04-18 21:25:49 -070047 }
Florin Coras4375fa32019-04-19 15:56:00 -070048 if (*last)
Florin Corasaf588822020-12-09 12:51:13 -080049 *last = f_csptr (f, c);
Florin Coras99ad2fc2019-04-18 21:25:49 -070050 }
51 else
52 {
53 clib_memcpy_fast (&c->data[tail_idx], src, len);
54 }
55}
56
Florin Corasaf588822020-12-09 12:51:13 -080057CLIB_MARCH_FN (svm_fifo_copy_from_chunk, void, svm_fifo_t *f,
58 svm_fifo_chunk_t *c, u32 head_idx, u8 *dst, u32 len,
59 svm_fifo_chunk_ptr_t *last)
Florin Coras99ad2fc2019-04-18 21:25:49 -070060{
61 u32 n_chunk;
62
Florin Corasf22f4e52019-12-19 16:10:58 -080063 ASSERT (f_pos_geq (head_idx, c->start_byte)
64 && f_pos_lt (head_idx, c->start_byte + c->length));
Florin Coras4375fa32019-04-19 15:56:00 -070065
Florin Coras99ad2fc2019-04-18 21:25:49 -070066 head_idx -= c->start_byte;
67 n_chunk = c->length - head_idx;
Florin Coras4375fa32019-04-19 15:56:00 -070068 if (n_chunk <= len)
Florin Coras99ad2fc2019-04-18 21:25:49 -070069 {
70 u32 to_copy = len;
71 clib_memcpy_fast (dst, &c->data[head_idx], n_chunk);
Florin Corasaf588822020-12-09 12:51:13 -080072 c = f_cptr (f, c->next);
Florin Coras99ad2fc2019-04-18 21:25:49 -070073 while ((to_copy -= n_chunk))
74 {
BenoƮt Gannedf601ae2020-10-20 14:31:55 +020075 CLIB_MEM_UNPOISON (c, sizeof (*c));
76 CLIB_MEM_UNPOISON (c->data, c->length);
Florin Coras99ad2fc2019-04-18 21:25:49 -070077 n_chunk = clib_min (c->length, to_copy);
78 clib_memcpy_fast (dst + (len - to_copy), &c->data[0], n_chunk);
Florin Corasaf588822020-12-09 12:51:13 -080079 c = c->length <= to_copy ? f_cptr (f, c->next) : c;
Florin Coras99ad2fc2019-04-18 21:25:49 -070080 }
Florin Coras4375fa32019-04-19 15:56:00 -070081 if (*last)
Florin Corasaf588822020-12-09 12:51:13 -080082 *last = f_csptr (f, c);
Florin Coras99ad2fc2019-04-18 21:25:49 -070083 }
84 else
85 {
86 clib_memcpy_fast (dst, &c->data[head_idx], len);
87 }
88}
89
90#ifndef CLIB_MARCH_VARIANT
91
92static inline void
Florin Corasaf588822020-12-09 12:51:13 -080093svm_fifo_copy_to_chunk (svm_fifo_t *f, svm_fifo_chunk_t *c, u32 tail_idx,
94 const u8 *src, u32 len, svm_fifo_chunk_ptr_t *last)
Florin Coras99ad2fc2019-04-18 21:25:49 -070095{
96 CLIB_MARCH_FN_SELECT (svm_fifo_copy_to_chunk) (f, c, tail_idx, src, len,
Florin Coras4375fa32019-04-19 15:56:00 -070097 last);
Florin Coras99ad2fc2019-04-18 21:25:49 -070098}
99
100static inline void
Florin Corasaf588822020-12-09 12:51:13 -0800101svm_fifo_copy_from_chunk (svm_fifo_t *f, svm_fifo_chunk_t *c, u32 head_idx,
102 u8 *dst, u32 len, svm_fifo_chunk_ptr_t *last)
Florin Coras99ad2fc2019-04-18 21:25:49 -0700103{
104 CLIB_MARCH_FN_SELECT (svm_fifo_copy_from_chunk) (f, c, head_idx, dst, len,
Florin Coras4375fa32019-04-19 15:56:00 -0700105 last);
Florin Coras99ad2fc2019-04-18 21:25:49 -0700106}
107
Florin Corasf03a59a2017-06-09 21:07:32 -0700108static inline u32
Florin Corasf22f4e52019-12-19 16:10:58 -0800109ooo_segment_end_pos (ooo_segment_t * s)
Florin Corasf03a59a2017-06-09 21:07:32 -0700110{
Florin Corasf22f4e52019-12-19 16:10:58 -0800111 return (s->start + s->length);
Florin Corasf03a59a2017-06-09 21:07:32 -0700112}
Dave Barach1f75cfd2017-04-14 16:46:44 -0400113
Florin Coras87b15ce2019-04-28 21:16:30 -0700114void
115svm_fifo_free_ooo_data (svm_fifo_t * f)
Dave Barach1f75cfd2017-04-14 16:46:44 -0400116{
Florin Coras87b15ce2019-04-28 21:16:30 -0700117 pool_free (f->ooo_segments);
118}
119
120static inline ooo_segment_t *
Florin Corasa7570b02019-05-02 12:52:19 -0700121ooo_segment_prev (svm_fifo_t * f, ooo_segment_t * s)
Florin Coras87b15ce2019-04-28 21:16:30 -0700122{
123 if (s->prev == OOO_SEGMENT_INVALID_INDEX)
124 return 0;
125 return pool_elt_at_index (f->ooo_segments, s->prev);
126}
127
128static inline ooo_segment_t *
129ooo_segment_next (svm_fifo_t * f, ooo_segment_t * s)
130{
131 if (s->next == OOO_SEGMENT_INVALID_INDEX)
132 return 0;
133 return pool_elt_at_index (f->ooo_segments, s->next);
134}
135
136static inline ooo_segment_t *
137ooo_segment_alloc (svm_fifo_t * f, u32 start, u32 length)
138{
139 ooo_segment_t *s;
140
141 pool_get (f->ooo_segments, s);
142
143 s->start = start;
144 s->length = length;
145 s->prev = s->next = OOO_SEGMENT_INVALID_INDEX;
146
Dave Barach1f75cfd2017-04-14 16:46:44 -0400147 return s;
148}
149
Florin Coras87b15ce2019-04-28 21:16:30 -0700150static inline void
151ooo_segment_free (svm_fifo_t * f, u32 index)
Florin Coras3eb50622017-07-13 01:24:57 -0400152{
Florin Coras87b15ce2019-04-28 21:16:30 -0700153 ooo_segment_t *cur, *prev = 0, *next = 0;
154 cur = pool_elt_at_index (f->ooo_segments, index);
Florin Coras3eb50622017-07-13 01:24:57 -0400155
Florin Coras87b15ce2019-04-28 21:16:30 -0700156 if (cur->next != OOO_SEGMENT_INVALID_INDEX)
Florin Coras3eb50622017-07-13 01:24:57 -0400157 {
Florin Coras87b15ce2019-04-28 21:16:30 -0700158 next = pool_elt_at_index (f->ooo_segments, cur->next);
159 next->prev = cur->prev;
Florin Coras3eb50622017-07-13 01:24:57 -0400160 }
Florin Coras87b15ce2019-04-28 21:16:30 -0700161
162 if (cur->prev != OOO_SEGMENT_INVALID_INDEX)
163 {
164 prev = pool_elt_at_index (f->ooo_segments, cur->prev);
165 prev->next = cur->next;
166 }
167 else
168 {
169 f->ooos_list_head = cur->next;
170 }
171
172 pool_put (f->ooo_segments, cur);
Florin Coras3eb50622017-07-13 01:24:57 -0400173}
174
Florin Coras87b15ce2019-04-28 21:16:30 -0700175/**
176 * Add segment to fifo's out-of-order segment list. Takes care of merging
177 * adjacent segments and removing overlapping ones.
178 */
179static void
180ooo_segment_add (svm_fifo_t * f, u32 offset, u32 head, u32 tail, u32 length)
Florin Coras3eb50622017-07-13 01:24:57 -0400181{
Florin Coras87b15ce2019-04-28 21:16:30 -0700182 ooo_segment_t *s, *new_s, *prev, *next, *it;
183 u32 new_index, s_end_pos, s_index;
184 u32 offset_pos, offset_end_pos;
Florin Coras3eb50622017-07-13 01:24:57 -0400185
Florin Corasf22f4e52019-12-19 16:10:58 -0800186 ASSERT (offset + length <= f_free_count (f, head, tail));
Florin Coras3eb50622017-07-13 01:24:57 -0400187
Florin Corasf22f4e52019-12-19 16:10:58 -0800188 offset_pos = tail + offset;
189 offset_end_pos = tail + offset + length;
Florin Coras3eb50622017-07-13 01:24:57 -0400190
Florin Coras87b15ce2019-04-28 21:16:30 -0700191 f->ooos_newest = OOO_SEGMENT_INVALID_INDEX;
Florin Coras3eb50622017-07-13 01:24:57 -0400192
Florin Coras87b15ce2019-04-28 21:16:30 -0700193 if (f->ooos_list_head == OOO_SEGMENT_INVALID_INDEX)
Florin Coras3eb50622017-07-13 01:24:57 -0400194 {
Florin Coras87b15ce2019-04-28 21:16:30 -0700195 s = ooo_segment_alloc (f, offset_pos, length);
196 f->ooos_list_head = s - f->ooo_segments;
197 f->ooos_newest = f->ooos_list_head;
198 return;
199 }
200
201 /* Find first segment that starts after new segment */
202 s = pool_elt_at_index (f->ooo_segments, f->ooos_list_head);
203 while (s->next != OOO_SEGMENT_INVALID_INDEX
Florin Corasf22f4e52019-12-19 16:10:58 -0800204 && f_pos_lt (s->start, offset_pos))
Florin Coras87b15ce2019-04-28 21:16:30 -0700205 s = pool_elt_at_index (f->ooo_segments, s->next);
206
207 /* If we have a previous and we overlap it, use it as starting point */
Florin Corasa7570b02019-05-02 12:52:19 -0700208 prev = ooo_segment_prev (f, s);
Florin Corasf22f4e52019-12-19 16:10:58 -0800209 if (prev && f_pos_leq (offset_pos, ooo_segment_end_pos (prev)))
Florin Coras87b15ce2019-04-28 21:16:30 -0700210 {
211 s = prev;
Florin Corasf22f4e52019-12-19 16:10:58 -0800212 s_end_pos = ooo_segment_end_pos (s);
Florin Coras87b15ce2019-04-28 21:16:30 -0700213
214 /* Since we have previous, offset start position cannot be smaller
215 * than prev->start. Check tail */
Florin Corasf22f4e52019-12-19 16:10:58 -0800216 ASSERT (f_pos_lt (s->start, offset_pos));
Florin Coras87b15ce2019-04-28 21:16:30 -0700217 goto check_tail;
218 }
219
220 s_index = s - f->ooo_segments;
Florin Corasf22f4e52019-12-19 16:10:58 -0800221 s_end_pos = ooo_segment_end_pos (s);
Florin Coras87b15ce2019-04-28 21:16:30 -0700222
223 /* No overlap, add before current segment */
Florin Corasf22f4e52019-12-19 16:10:58 -0800224 if (f_pos_lt (offset_end_pos, s->start))
Florin Coras87b15ce2019-04-28 21:16:30 -0700225 {
226 new_s = ooo_segment_alloc (f, offset_pos, length);
227 new_index = new_s - f->ooo_segments;
228
229 /* Pool might've moved, get segment again */
230 s = pool_elt_at_index (f->ooo_segments, s_index);
231 if (s->prev != OOO_SEGMENT_INVALID_INDEX)
Florin Coras3eb50622017-07-13 01:24:57 -0400232 {
Florin Coras87b15ce2019-04-28 21:16:30 -0700233 new_s->prev = s->prev;
234 prev = pool_elt_at_index (f->ooo_segments, new_s->prev);
235 prev->next = new_index;
Florin Coras3eb50622017-07-13 01:24:57 -0400236 }
Florin Coras87b15ce2019-04-28 21:16:30 -0700237 else
Florin Coras3eb50622017-07-13 01:24:57 -0400238 {
Florin Coras87b15ce2019-04-28 21:16:30 -0700239 /* New head */
240 f->ooos_list_head = new_index;
Florin Coras3eb50622017-07-13 01:24:57 -0400241 }
Florin Coras87b15ce2019-04-28 21:16:30 -0700242
243 new_s->next = s_index;
244 s->prev = new_index;
245 f->ooos_newest = new_index;
246 return;
247 }
248 /* No overlap, add after current segment */
Florin Corasf22f4e52019-12-19 16:10:58 -0800249 else if (f_pos_gt (offset_pos, s_end_pos))
Florin Coras87b15ce2019-04-28 21:16:30 -0700250 {
251 new_s = ooo_segment_alloc (f, offset_pos, length);
252 new_index = new_s - f->ooo_segments;
253
254 /* Pool might've moved, get segment again */
255 s = pool_elt_at_index (f->ooo_segments, s_index);
256
257 /* Needs to be last */
258 ASSERT (s->next == OOO_SEGMENT_INVALID_INDEX);
259
260 new_s->prev = s_index;
261 s->next = new_index;
262 f->ooos_newest = new_index;
263
264 return;
Florin Coras3eb50622017-07-13 01:24:57 -0400265 }
266
Florin Coras87b15ce2019-04-28 21:16:30 -0700267 /*
268 * Merge needed
269 */
Florin Coras3eb50622017-07-13 01:24:57 -0400270
Florin Coras87b15ce2019-04-28 21:16:30 -0700271 /* Merge at head */
Florin Corasf22f4e52019-12-19 16:10:58 -0800272 if (f_pos_lt (offset_pos, s->start))
Florin Coras87b15ce2019-04-28 21:16:30 -0700273 {
274 s->start = offset_pos;
Florin Corasf22f4e52019-12-19 16:10:58 -0800275 s->length = s_end_pos - s->start;
Florin Coras87b15ce2019-04-28 21:16:30 -0700276 f->ooos_newest = s - f->ooo_segments;
277 }
278
279check_tail:
280
281 /* Overlapping tail */
Florin Corasf22f4e52019-12-19 16:10:58 -0800282 if (f_pos_gt (offset_end_pos, s_end_pos))
Florin Coras87b15ce2019-04-28 21:16:30 -0700283 {
Florin Corasf22f4e52019-12-19 16:10:58 -0800284 s->length = offset_end_pos - s->start;
Florin Coras87b15ce2019-04-28 21:16:30 -0700285
286 /* Remove the completely overlapped segments in the tail */
287 it = ooo_segment_next (f, s);
Florin Corasf22f4e52019-12-19 16:10:58 -0800288 while (it && f_pos_leq (ooo_segment_end_pos (it), offset_end_pos))
Florin Coras87b15ce2019-04-28 21:16:30 -0700289 {
290 next = ooo_segment_next (f, it);
291 ooo_segment_free (f, it - f->ooo_segments);
292 it = next;
293 }
294
295 /* If partial overlap with last, merge */
Florin Corasf22f4e52019-12-19 16:10:58 -0800296 if (it && f_pos_leq (it->start, offset_end_pos))
Florin Coras87b15ce2019-04-28 21:16:30 -0700297 {
Florin Corasf22f4e52019-12-19 16:10:58 -0800298 s->length = ooo_segment_end_pos (it) - s->start;
Florin Coras87b15ce2019-04-28 21:16:30 -0700299 ooo_segment_free (f, it - f->ooo_segments);
300 }
301 f->ooos_newest = s - f->ooo_segments;
302 }
Florin Coras3eb50622017-07-13 01:24:57 -0400303}
304
Florin Coras87b15ce2019-04-28 21:16:30 -0700305/**
306 * Removes segments that can now be enqueued because the fifo's tail has
307 * advanced. Returns the number of bytes added to tail.
308 */
309static int
310ooo_segment_try_collect (svm_fifo_t * f, u32 n_bytes_enqueued, u32 * tail)
Dave Barach1f75cfd2017-04-14 16:46:44 -0400311{
Florin Coras87b15ce2019-04-28 21:16:30 -0700312 u32 s_index, bytes = 0;
313 ooo_segment_t *s;
314 i32 diff;
Dave Barach1f75cfd2017-04-14 16:46:44 -0400315
Florin Coras87b15ce2019-04-28 21:16:30 -0700316 s = pool_elt_at_index (f->ooo_segments, f->ooos_list_head);
Florin Corasf22f4e52019-12-19 16:10:58 -0800317 diff = *tail - s->start;
Florin Coras87b15ce2019-04-28 21:16:30 -0700318
319 ASSERT (diff != n_bytes_enqueued);
320
321 if (diff > n_bytes_enqueued)
322 return 0;
323
324 /* If last tail update overlaps one/multiple ooo segments, remove them */
325 while (0 <= diff && diff < n_bytes_enqueued)
Dave Barach1f75cfd2017-04-14 16:46:44 -0400326 {
Florin Coras87b15ce2019-04-28 21:16:30 -0700327 s_index = s - f->ooo_segments;
328
329 /* Segment end is beyond the tail. Advance tail and remove segment */
330 if (s->length > diff)
331 {
332 bytes = s->length - diff;
Florin Corasf22f4e52019-12-19 16:10:58 -0800333 *tail = *tail + bytes;
Florin Coras87b15ce2019-04-28 21:16:30 -0700334 ooo_segment_free (f, s_index);
335 break;
336 }
337
338 /* If we have next go on */
339 if (s->next != OOO_SEGMENT_INVALID_INDEX)
340 {
341 s = pool_elt_at_index (f->ooo_segments, s->next);
Florin Corasf22f4e52019-12-19 16:10:58 -0800342 diff = *tail - s->start;
Florin Coras87b15ce2019-04-28 21:16:30 -0700343 ooo_segment_free (f, s_index);
344 }
345 /* End of search */
346 else
347 {
348 ooo_segment_free (f, s_index);
349 break;
350 }
Dave Barach1f75cfd2017-04-14 16:46:44 -0400351 }
Florin Coras3eb50622017-07-13 01:24:57 -0400352
Florin Corasc547e912020-12-08 17:50:45 -0800353 ASSERT (bytes <= f->shr->size);
Florin Coras87b15ce2019-04-28 21:16:30 -0700354 return bytes;
Florin Corasb59a7052017-04-18 22:07:29 -0700355}
356
Florin Corasf22f4e52019-12-19 16:10:58 -0800357__clib_unused static ooo_segment_t *
Florin Corasa7570b02019-05-02 12:52:19 -0700358ooo_segment_last (svm_fifo_t * f)
359{
360 ooo_segment_t *s;
361
362 if (f->ooos_list_head == OOO_SEGMENT_INVALID_INDEX)
363 return 0;
364
365 s = svm_fifo_first_ooo_segment (f);
366 while (s->next != OOO_SEGMENT_INVALID_INDEX)
367 s = pool_elt_at_index (f->ooo_segments, s->next);
368 return s;
369}
370
Florin Coras0a846802019-04-09 18:29:14 -0700371void
372svm_fifo_init (svm_fifo_t * f, u32 size)
373{
Florin Corasf22f4e52019-12-19 16:10:58 -0800374 svm_fifo_chunk_t *c, *prev;
Florin Coras2de9c0f2020-02-02 19:30:39 +0000375 u32 min_alloc;
Florin Corasf22f4e52019-12-19 16:10:58 -0800376
Florin Corasc547e912020-12-08 17:50:45 -0800377 f->shr->size = size;
Florin Coras0a846802019-04-09 18:29:14 -0700378 f->ooos_list_head = OOO_SEGMENT_INVALID_INDEX;
Florin Coras0a846802019-04-09 18:29:14 -0700379 f->segment_index = SVM_FIFO_INVALID_INDEX;
380 f->refcnt = 1;
Florin Corasc547e912020-12-08 17:50:45 -0800381 f->shr->head = f->shr->tail = f->flags = 0;
382 f->shr->head_chunk = f->shr->tail_chunk = f->shr->start_chunk;
Florin Corasf22f4e52019-12-19 16:10:58 -0800383 f->ooo_deq = f->ooo_enq = 0;
Florin Coras0a846802019-04-09 18:29:14 -0700384
Florin Coras2de9c0f2020-02-02 19:30:39 +0000385 min_alloc = size > 32 << 10 ? size >> 3 : 4096;
386 min_alloc = clib_min (min_alloc, 64 << 10);
Florin Corasc547e912020-12-08 17:50:45 -0800387 f->shr->min_alloc = min_alloc;
Florin Coraseaacce42019-07-02 13:07:37 -0700388
Florin Corasf22f4e52019-12-19 16:10:58 -0800389 /*
390 * Initialize chunks
391 */
Florin Corasaf588822020-12-09 12:51:13 -0800392 prev = f_start_cptr (f);
393 prev->start_byte = 0;
Florin Coras91b36402020-11-17 15:56:38 -0800394 prev->enq_rb_index = prev->deq_rb_index = RBTREE_TNIL_INDEX;
Florin Corasaf588822020-12-09 12:51:13 -0800395 c = f_cptr (f, prev->next);
Florin Coraseaacce42019-07-02 13:07:37 -0700396
Florin Corasf22f4e52019-12-19 16:10:58 -0800397 while (c)
Florin Coraseaacce42019-07-02 13:07:37 -0700398 {
399 c->start_byte = prev->start_byte + prev->length;
Florin Coras91b36402020-11-17 15:56:38 -0800400 c->enq_rb_index = c->deq_rb_index = RBTREE_TNIL_INDEX;
Florin Corasb4624182020-12-11 13:58:12 -0800401 ASSERT (c->length >= 1 << FS_MIN_LOG2_CHUNK_SZ);
Florin Coraseaacce42019-07-02 13:07:37 -0700402 prev = c;
Florin Corasaf588822020-12-09 12:51:13 -0800403 c = f_cptr (f, c->next);
Florin Coraseaacce42019-07-02 13:07:37 -0700404 }
405}
406
Florin Corasf22f4e52019-12-19 16:10:58 -0800407void
408svm_fifo_init_ooo_lookup (svm_fifo_t * f, u8 ooo_type)
409{
410 if (ooo_type == 0)
411 {
412 ASSERT (!rb_tree_is_init (&f->ooo_enq_lookup));
413 rb_tree_init (&f->ooo_enq_lookup);
414 }
415 else
416 {
417 ASSERT (!rb_tree_is_init (&f->ooo_deq_lookup));
418 rb_tree_init (&f->ooo_deq_lookup);
419 }
420}
421
Florin Corasb095a3c2019-04-25 12:58:46 -0700422/**
423 * Creates a fifo in the current heap. Fails vs blow up the process
424 */
Dave Barach68b0fb02017-02-28 15:15:56 -0500425svm_fifo_t *
Florin Corasf22f4e52019-12-19 16:10:58 -0800426svm_fifo_alloc (u32 data_size_in_bytes)
Dave Barach68b0fb02017-02-28 15:15:56 -0500427{
Dave Barach818eb542017-08-02 13:56:13 -0400428 u32 rounded_data_size;
Florin Corascefd5d82019-05-05 13:19:57 -0700429 svm_fifo_chunk_t *c;
430 svm_fifo_t *f;
Dave Barach68b0fb02017-02-28 15:15:56 -0500431
Florin Corascefd5d82019-05-05 13:19:57 -0700432 f = clib_mem_alloc_aligned_or_null (sizeof (*f), CLIB_CACHE_LINE_BYTES);
Dave Barach68b0fb02017-02-28 15:15:56 -0500433 if (f == 0)
434 return 0;
435
Dave Barachb7b92992018-10-17 10:38:51 -0400436 clib_memset (f, 0, sizeof (*f));
Florin Corascefd5d82019-05-05 13:19:57 -0700437
438 /* always round fifo data size to the next highest power-of-two */
439 rounded_data_size = (1 << (max_log2 (data_size_in_bytes)));
440 c = clib_mem_alloc_aligned_or_null (sizeof (*c) + rounded_data_size,
441 CLIB_CACHE_LINE_BYTES);
442 if (!c)
443 {
444 clib_mem_free (f);
445 return 0;
446 }
447
Florin Corasf22f4e52019-12-19 16:10:58 -0800448 clib_memset (c, 0, sizeof (*c));
Florin Corascefd5d82019-05-05 13:19:57 -0700449 c->start_byte = 0;
450 c->length = data_size_in_bytes;
Florin Corasf22f4e52019-12-19 16:10:58 -0800451 c->enq_rb_index = RBTREE_TNIL_INDEX;
452 c->deq_rb_index = RBTREE_TNIL_INDEX;
Florin Corasaf588822020-12-09 12:51:13 -0800453 f->shr->start_chunk = f->shr->end_chunk = f_csptr (f, c);
Florin Corascefd5d82019-05-05 13:19:57 -0700454
Florin Coras0a846802019-04-09 18:29:14 -0700455 return f;
Dave Barach68b0fb02017-02-28 15:15:56 -0500456}
457
Florin Corasb095a3c2019-04-25 12:58:46 -0700458/**
459 * Creates a fifo chunk in the current heap
460 */
461svm_fifo_chunk_t *
462svm_fifo_chunk_alloc (u32 size)
463{
464 svm_fifo_chunk_t *c;
465 u32 rounded_size;
466
467 /* round chunk size to the next highest power-of-two */
468 rounded_size = (1 << (max_log2 (size)));
469 c = clib_mem_alloc_aligned_or_null (sizeof (*c) + rounded_size,
470 CLIB_CACHE_LINE_BYTES);
471 if (c == 0)
472 return 0;
473
474 clib_memset (c, 0, sizeof (*c));
475 c->length = rounded_size;
476 return c;
477}
478
Florin Corasf22f4e52019-12-19 16:10:58 -0800479/**
480 * Find chunk for given byte position
481 *
482 * @param f fifo
483 * @param pos normalized position in fifo
484 *
485 * @return chunk that includes given position or 0
486 */
487static svm_fifo_chunk_t *
488svm_fifo_find_chunk (svm_fifo_t * f, u32 pos)
Florin Coras4375fa32019-04-19 15:56:00 -0700489{
Florin Corasf22f4e52019-12-19 16:10:58 -0800490 svm_fifo_chunk_t *c;
491
Florin Corasaf588822020-12-09 12:51:13 -0800492 c = f_start_cptr (f);
Florin Corasf22f4e52019-12-19 16:10:58 -0800493 while (c && !f_chunk_includes_pos (c, pos))
Florin Corasaf588822020-12-09 12:51:13 -0800494 c = f_cptr (f, c->next);
Florin Corasf22f4e52019-12-19 16:10:58 -0800495
496 return c;
497}
498
499static svm_fifo_chunk_t *
500svm_fifo_find_next_chunk (svm_fifo_t * f, svm_fifo_chunk_t * start, u32 pos)
501{
502 svm_fifo_chunk_t *c;
503
504 ASSERT (start != 0);
505
506 c = start;
507 while (c && !f_chunk_includes_pos (c, pos))
Florin Corasaf588822020-12-09 12:51:13 -0800508 c = f_cptr (f, c->next);
Florin Corasf22f4e52019-12-19 16:10:58 -0800509
510 return c;
511}
512
513u32
514svm_fifo_max_read_chunk (svm_fifo_t * f)
515{
516 u32 head, tail, end_chunk;
517
518 f_load_head_tail_cons (f, &head, &tail);
Florin Corasaf588822020-12-09 12:51:13 -0800519 ASSERT (!f->shr->head_chunk || f_chunk_includes_pos (f_head_cptr (f), head));
Florin Corasf22f4e52019-12-19 16:10:58 -0800520
Florin Corasc547e912020-12-08 17:50:45 -0800521 if (!f->shr->head_chunk)
Florin Corasf22f4e52019-12-19 16:10:58 -0800522 {
Florin Corasaf588822020-12-09 12:51:13 -0800523 f->shr->head_chunk = f_csptr (f, svm_fifo_find_chunk (f, head));
Florin Corasc547e912020-12-08 17:50:45 -0800524 if (PREDICT_FALSE (!f->shr->head_chunk))
Florin Corasf22f4e52019-12-19 16:10:58 -0800525 return 0;
526 }
527
Florin Corasaf588822020-12-09 12:51:13 -0800528 end_chunk = f_chunk_end (f_head_cptr (f));
Florin Corasf22f4e52019-12-19 16:10:58 -0800529
530 return f_pos_lt (end_chunk, tail) ? end_chunk - head : tail - head;
531}
532
533u32
534svm_fifo_max_write_chunk (svm_fifo_t * f)
535{
Florin Corasaf588822020-12-09 12:51:13 -0800536 svm_fifo_chunk_t *tail_chunk;
Florin Corasf22f4e52019-12-19 16:10:58 -0800537 u32 head, tail;
538
539 f_load_head_tail_prod (f, &head, &tail);
Florin Corasaf588822020-12-09 12:51:13 -0800540 tail_chunk = f_tail_cptr (f);
Florin Corasf22f4e52019-12-19 16:10:58 -0800541
Florin Corasaf588822020-12-09 12:51:13 -0800542 ASSERT (!tail_chunk || f_chunk_includes_pos (tail_chunk, tail));
543
544 return tail_chunk ? f_chunk_end (tail_chunk) - tail : 0;
Florin Coras4375fa32019-04-19 15:56:00 -0700545}
546
Florin Corasb0208062019-12-12 12:09:29 -0800547static rb_node_t *
Florin Corasf22f4e52019-12-19 16:10:58 -0800548f_find_node_rbtree (rb_tree_t * rt, u32 pos)
Florin Corasb0208062019-12-12 12:09:29 -0800549{
550 rb_node_t *cur, *prev;
551
552 cur = rb_node (rt, rt->root);
553 if (PREDICT_FALSE (rb_node_is_tnil (rt, cur)))
554 return 0;
555
556 while (pos != cur->key)
557 {
558 prev = cur;
Florin Corasf22f4e52019-12-19 16:10:58 -0800559 if (f_pos_lt (pos, cur->key))
Florin Corasb0208062019-12-12 12:09:29 -0800560 {
561 cur = rb_node_left (rt, cur);
562 if (rb_node_is_tnil (rt, cur))
563 {
564 cur = rb_tree_predecessor (rt, prev);
565 break;
566 }
567 }
568 else
569 {
570 cur = rb_node_right (rt, cur);
571 if (rb_node_is_tnil (rt, cur))
572 {
573 cur = prev;
574 break;
575 }
576 }
577 }
578
579 if (rb_node_is_tnil (rt, cur))
580 return 0;
581
582 return cur;
583}
584
585static svm_fifo_chunk_t *
Florin Corasf22f4e52019-12-19 16:10:58 -0800586f_find_chunk_rbtree (rb_tree_t * rt, u32 pos)
Florin Corasb0208062019-12-12 12:09:29 -0800587{
588 svm_fifo_chunk_t *c;
589 rb_node_t *n;
590
Florin Corasf22f4e52019-12-19 16:10:58 -0800591 if (!rb_tree_is_init (rt))
592 return 0;
593
594 n = f_find_node_rbtree (rt, pos);
Florin Corasb0208062019-12-12 12:09:29 -0800595 if (!n)
596 return 0;
597 c = uword_to_pointer (n->opaque, svm_fifo_chunk_t *);
Florin Corasf22f4e52019-12-19 16:10:58 -0800598 if (f_chunk_includes_pos (c, pos))
Florin Corasb0208062019-12-12 12:09:29 -0800599 return c;
600
601 return 0;
602}
603
Florin Corasb0208062019-12-12 12:09:29 -0800604static void
Florin Corasf22f4e52019-12-19 16:10:58 -0800605f_update_ooo_enq (svm_fifo_t * f, u32 start_pos, u32 end_pos)
Florin Corasb0208062019-12-12 12:09:29 -0800606{
607 rb_tree_t *rt = &f->ooo_enq_lookup;
608 svm_fifo_chunk_t *c;
609 rb_node_t *cur;
610
Florin Corasf22f4e52019-12-19 16:10:58 -0800611 /* Use linear search if rbtree is not initialized */
612 if (PREDICT_FALSE (!rb_tree_is_init (rt)))
613 {
Florin Corasaf588822020-12-09 12:51:13 -0800614 f->ooo_enq = svm_fifo_find_next_chunk (f, f_tail_cptr (f), start_pos);
Florin Corasf22f4e52019-12-19 16:10:58 -0800615 return;
616 }
Florin Corasb0208062019-12-12 12:09:29 -0800617
618 if (rt->root == RBTREE_TNIL_INDEX)
619 {
Florin Corasaf588822020-12-09 12:51:13 -0800620 c = f_tail_cptr (f);
Florin Corasf22f4e52019-12-19 16:10:58 -0800621 ASSERT (c->enq_rb_index == RBTREE_TNIL_INDEX);
622 c->enq_rb_index = rb_tree_add_custom (rt, c->start_byte,
623 pointer_to_uword (c), f_pos_lt);
Florin Corasb0208062019-12-12 12:09:29 -0800624 }
625 else
626 {
Florin Corasf22f4e52019-12-19 16:10:58 -0800627 cur = f_find_node_rbtree (rt, start_pos);
Florin Corasb0208062019-12-12 12:09:29 -0800628 c = uword_to_pointer (cur->opaque, svm_fifo_chunk_t *);
Florin Corasf22f4e52019-12-19 16:10:58 -0800629 ASSERT (f_pos_leq (c->start_byte, start_pos));
Florin Coras4375fa32019-04-19 15:56:00 -0700630 }
631
Florin Corasf22f4e52019-12-19 16:10:58 -0800632 if (f_chunk_includes_pos (c, start_pos))
Florin Corasb0208062019-12-12 12:09:29 -0800633 f->ooo_enq = c;
634
Florin Corasf22f4e52019-12-19 16:10:58 -0800635 if (f_chunk_includes_pos (c, end_pos))
Florin Corasb0208062019-12-12 12:09:29 -0800636 return;
637
638 do
639 {
Florin Corasaf588822020-12-09 12:51:13 -0800640 c = f_cptr (f, c->next);
Florin Corasf22f4e52019-12-19 16:10:58 -0800641 if (!c || c->enq_rb_index != RBTREE_TNIL_INDEX)
Florin Corasb0208062019-12-12 12:09:29 -0800642 break;
643
Florin Corasf22f4e52019-12-19 16:10:58 -0800644 c->enq_rb_index = rb_tree_add_custom (rt, c->start_byte,
645 pointer_to_uword (c), f_pos_lt);
Florin Corasb0208062019-12-12 12:09:29 -0800646
Florin Corasf22f4e52019-12-19 16:10:58 -0800647 if (f_chunk_includes_pos (c, start_pos))
Florin Corasb0208062019-12-12 12:09:29 -0800648 f->ooo_enq = c;
Florin Corasb0208062019-12-12 12:09:29 -0800649 }
Florin Corasf22f4e52019-12-19 16:10:58 -0800650 while (!f_chunk_includes_pos (c, end_pos));
Florin Corasb0208062019-12-12 12:09:29 -0800651}
652
653static void
Florin Corasf22f4e52019-12-19 16:10:58 -0800654f_update_ooo_deq (svm_fifo_t * f, u32 start_pos, u32 end_pos)
Florin Corasb0208062019-12-12 12:09:29 -0800655{
656 rb_tree_t *rt = &f->ooo_deq_lookup;
657 rb_node_t *cur;
658 svm_fifo_chunk_t *c;
659
Florin Corasf22f4e52019-12-19 16:10:58 -0800660 /* Use linear search if rbtree is not initialized */
661 if (PREDICT_FALSE (!rb_tree_is_init (rt)))
662 {
663 f->ooo_deq = svm_fifo_find_chunk (f, start_pos);
664 return;
665 }
Florin Corasb0208062019-12-12 12:09:29 -0800666
667 if (rt->root == RBTREE_TNIL_INDEX)
668 {
Florin Corasaf588822020-12-09 12:51:13 -0800669 c = f_start_cptr (f);
Florin Corasf22f4e52019-12-19 16:10:58 -0800670 ASSERT (c->deq_rb_index == RBTREE_TNIL_INDEX);
671 c->deq_rb_index = rb_tree_add_custom (rt, c->start_byte,
672 pointer_to_uword (c), f_pos_lt);
Florin Corasb0208062019-12-12 12:09:29 -0800673 }
674 else
675 {
Florin Corasf22f4e52019-12-19 16:10:58 -0800676 cur = f_find_node_rbtree (rt, start_pos);
Florin Corasb0208062019-12-12 12:09:29 -0800677 c = uword_to_pointer (cur->opaque, svm_fifo_chunk_t *);
Florin Corasf22f4e52019-12-19 16:10:58 -0800678 ASSERT (f_pos_leq (c->start_byte, start_pos));
Florin Corasb0208062019-12-12 12:09:29 -0800679 }
680
Florin Corasf22f4e52019-12-19 16:10:58 -0800681 if (f_chunk_includes_pos (c, start_pos))
Florin Corasb0208062019-12-12 12:09:29 -0800682 f->ooo_deq = c;
683
Florin Corasf22f4e52019-12-19 16:10:58 -0800684 if (f_chunk_includes_pos (c, end_pos))
Florin Corasb0208062019-12-12 12:09:29 -0800685 return;
686
687 do
688 {
Florin Corasaf588822020-12-09 12:51:13 -0800689 c = f_cptr (f, c->next);
Florin Corasf22f4e52019-12-19 16:10:58 -0800690 if (!c || c->deq_rb_index != RBTREE_TNIL_INDEX)
Florin Corasb0208062019-12-12 12:09:29 -0800691 break;
692
Florin Corasf22f4e52019-12-19 16:10:58 -0800693 c->deq_rb_index = rb_tree_add_custom (rt, c->start_byte,
694 pointer_to_uword (c), f_pos_lt);
Florin Corasb0208062019-12-12 12:09:29 -0800695
Florin Corasf22f4e52019-12-19 16:10:58 -0800696 if (f_chunk_includes_pos (c, start_pos))
Florin Corasb0208062019-12-12 12:09:29 -0800697 f->ooo_deq = c;
Florin Corasb0208062019-12-12 12:09:29 -0800698 }
Florin Corasf22f4e52019-12-19 16:10:58 -0800699 while (!f_chunk_includes_pos (c, end_pos));
Florin Corasb0208062019-12-12 12:09:29 -0800700}
701
702static svm_fifo_chunk_t *
Florin Corasf22f4e52019-12-19 16:10:58 -0800703f_lookup_clear_enq_chunks (svm_fifo_t * f, svm_fifo_chunk_t * start,
704 u32 end_pos)
Florin Corasb0208062019-12-12 12:09:29 -0800705{
Florin Corasf22f4e52019-12-19 16:10:58 -0800706 rb_tree_t *rt = &f->ooo_enq_lookup;
Florin Corasb0208062019-12-12 12:09:29 -0800707 svm_fifo_chunk_t *c;
708 rb_node_t *n;
709
Florin Corasb0208062019-12-12 12:09:29 -0800710 c = start;
Florin Corasf22f4e52019-12-19 16:10:58 -0800711 while (c && !f_chunk_includes_pos (c, end_pos))
Florin Corasb0208062019-12-12 12:09:29 -0800712 {
Florin Corasf22f4e52019-12-19 16:10:58 -0800713 if (c->enq_rb_index != RBTREE_TNIL_INDEX)
Florin Corasb0208062019-12-12 12:09:29 -0800714 {
Florin Corasf22f4e52019-12-19 16:10:58 -0800715 n = rb_node (rt, c->enq_rb_index);
716 rb_tree_del_node (rt, n);
717 c->enq_rb_index = RBTREE_TNIL_INDEX;
Florin Corasb0208062019-12-12 12:09:29 -0800718 }
719
Florin Corasaf588822020-12-09 12:51:13 -0800720 c = f_cptr (f, c->next);
Florin Corasb0208062019-12-12 12:09:29 -0800721 }
Florin Corasf22f4e52019-12-19 16:10:58 -0800722
723 /* No ooo segments left, so make sure the current chunk
724 * is not tracked in the enq rbtree */
725 if (f->ooos_list_head == OOO_SEGMENT_INVALID_INDEX
726 && c && c->enq_rb_index != RBTREE_TNIL_INDEX)
727 {
728 n = rb_node (rt, c->enq_rb_index);
729 rb_tree_del_node (rt, n);
730 c->enq_rb_index = RBTREE_TNIL_INDEX;
731 }
Florin Corasb0208062019-12-12 12:09:29 -0800732
733 return c;
Florin Coras99ad2fc2019-04-18 21:25:49 -0700734}
735
Florin Corasf22f4e52019-12-19 16:10:58 -0800736static svm_fifo_chunk_t *
737f_lookup_clear_deq_chunks (svm_fifo_t * f, svm_fifo_chunk_t * start,
738 u32 end_pos)
Florin Corasa7570b02019-05-02 12:52:19 -0700739{
Florin Corasf22f4e52019-12-19 16:10:58 -0800740 rb_tree_t *rt = &f->ooo_deq_lookup;
741 svm_fifo_chunk_t *c;
742 rb_node_t *n;
Florin Corasa7570b02019-05-02 12:52:19 -0700743
Florin Corasf22f4e52019-12-19 16:10:58 -0800744 c = start;
745 while (c && !f_chunk_includes_pos (c, end_pos))
Florin Corasa7570b02019-05-02 12:52:19 -0700746 {
Florin Corasf22f4e52019-12-19 16:10:58 -0800747 if (c->deq_rb_index != RBTREE_TNIL_INDEX)
748 {
749 n = rb_node (rt, c->deq_rb_index);
750 rb_tree_del_node (rt, n);
751 c->deq_rb_index = RBTREE_TNIL_INDEX;
752 }
753
Florin Corasaf588822020-12-09 12:51:13 -0800754 c = f_cptr (f, c->next);
Florin Corasa7570b02019-05-02 12:52:19 -0700755 }
Florin Corasa7570b02019-05-02 12:52:19 -0700756
Florin Corasf22f4e52019-12-19 16:10:58 -0800757 return c;
Florin Corasa7570b02019-05-02 12:52:19 -0700758}
759
760void
Florin Corasb095a3c2019-04-25 12:58:46 -0700761svm_fifo_free_chunk_lookup (svm_fifo_t * f)
762{
Florin Corasb0208062019-12-12 12:09:29 -0800763 rb_tree_free_nodes (&f->ooo_enq_lookup);
764 rb_tree_free_nodes (&f->ooo_deq_lookup);
Florin Corasb095a3c2019-04-25 12:58:46 -0700765}
766
767void
Florin Coras6cf30ad2017-04-04 23:08:23 -0700768svm_fifo_free (svm_fifo_t * f)
769{
Dave Barach52851e62017-08-07 09:35:25 -0400770 ASSERT (f->refcnt > 0);
771
772 if (--f->refcnt == 0)
773 {
Florin Corasb095a3c2019-04-25 12:58:46 -0700774 /* ooo data is not allocated on segment heap */
775 svm_fifo_free_chunk_lookup (f);
Dave Barach52851e62017-08-07 09:35:25 -0400776 clib_mem_free (f);
777 }
Florin Coras6cf30ad2017-04-04 23:08:23 -0700778}
779
Florin Coras7fb0fe12018-04-09 09:24:52 -0700780void
Florin Coras87b15ce2019-04-28 21:16:30 -0700781svm_fifo_overwrite_head (svm_fifo_t * f, u8 * src, u32 len)
Florin Coras7fb0fe12018-04-09 09:24:52 -0700782{
Florin Coras0a846802019-04-09 18:29:14 -0700783 u32 n_chunk;
Sirshak Das28aa5392019-02-05 01:33:33 -0600784 u32 head, tail, head_idx;
Florin Coras0a846802019-04-09 18:29:14 -0700785 svm_fifo_chunk_t *c;
786
Florin Corasc547e912020-12-08 17:50:45 -0800787 ASSERT (len <= f->shr->size);
Sirshak Das28aa5392019-02-05 01:33:33 -0600788
789 f_load_head_tail_cons (f, &head, &tail);
Florin Corasf22f4e52019-12-19 16:10:58 -0800790
Florin Corasc547e912020-12-08 17:50:45 -0800791 if (!f->shr->head_chunk)
Florin Corasaf588822020-12-09 12:51:13 -0800792 f->shr->head_chunk = f_csptr (f, svm_fifo_find_chunk (f, head));
Florin Corasf22f4e52019-12-19 16:10:58 -0800793
Florin Corasaf588822020-12-09 12:51:13 -0800794 c = f_head_cptr (f);
Florin Coras29a59c32019-05-02 12:52:19 -0700795 head_idx = head - c->start_byte;
Florin Coras0a846802019-04-09 18:29:14 -0700796 n_chunk = c->length - head_idx;
797 if (len <= n_chunk)
Florin Coras87b15ce2019-04-28 21:16:30 -0700798 clib_memcpy_fast (&c->data[head_idx], src, len);
Florin Coras7fb0fe12018-04-09 09:24:52 -0700799 else
800 {
Florin Corasaf588822020-12-09 12:51:13 -0800801 ASSERT (len - n_chunk <= f_cptr (f, c->next)->length);
Florin Coras87b15ce2019-04-28 21:16:30 -0700802 clib_memcpy_fast (&c->data[head_idx], src, n_chunk);
Florin Corasaf588822020-12-09 12:51:13 -0800803 clib_memcpy_fast (&f_cptr (f, c->next)->data[0], src + n_chunk,
804 len - n_chunk);
Florin Coras7fb0fe12018-04-09 09:24:52 -0700805 }
806}
Dave Barach68b0fb02017-02-28 15:15:56 -0500807
Florin Corasf22f4e52019-12-19 16:10:58 -0800808static int
Florin Coras9e61d9a2020-02-05 21:13:18 +0000809f_try_chunk_alloc (svm_fifo_t * f, u32 head, u32 tail, u32 len)
Florin Corasf22f4e52019-12-19 16:10:58 -0800810{
Florin Coras9e61d9a2020-02-05 21:13:18 +0000811 svm_fifo_chunk_t *c, *cur, *prev;
Florin Corasf22f4e52019-12-19 16:10:58 -0800812 u32 alloc_size, free_alloced;
813
Florin Corasaf588822020-12-09 12:51:13 -0800814 prev = f_end_cptr (f);
815 free_alloced = f_chunk_end (prev) - tail;
Florin Corasf22f4e52019-12-19 16:10:58 -0800816
Florin Corasc547e912020-12-08 17:50:45 -0800817 alloc_size = clib_min (f->shr->min_alloc, f->shr->size - (tail - head));
Florin Corasf22f4e52019-12-19 16:10:58 -0800818 alloc_size = clib_max (alloc_size, len - free_alloced);
819
Florin Corasc547e912020-12-08 17:50:45 -0800820 c = fsh_alloc_chunk (f->fs_hdr, f->shr->slice_index, alloc_size);
Florin Corasf22f4e52019-12-19 16:10:58 -0800821 if (PREDICT_FALSE (!c))
822 return -1;
823
Florin Coras9e61d9a2020-02-05 21:13:18 +0000824 cur = c;
Florin Coras9e61d9a2020-02-05 21:13:18 +0000825
826 while (cur)
827 {
828 cur->start_byte = prev->start_byte + prev->length;
829 cur->enq_rb_index = RBTREE_TNIL_INDEX;
830 cur->deq_rb_index = RBTREE_TNIL_INDEX;
831
832 prev = cur;
Florin Corasaf588822020-12-09 12:51:13 -0800833 cur = f_cptr (f, cur->next);
Florin Coras9e61d9a2020-02-05 21:13:18 +0000834 }
835
Florin Corasaf588822020-12-09 12:51:13 -0800836 f_csptr_link (f, f->shr->end_chunk, c);
Florin Coras9e61d9a2020-02-05 21:13:18 +0000837 prev->next = 0;
Florin Corasaf588822020-12-09 12:51:13 -0800838 f->shr->end_chunk = f_csptr (f, prev);
Florin Coras9e61d9a2020-02-05 21:13:18 +0000839
Florin Corasc547e912020-12-08 17:50:45 -0800840 if (!f->shr->tail_chunk)
Florin Corasaf588822020-12-09 12:51:13 -0800841 f->shr->tail_chunk = f_csptr (f, c);
Florin Coras9e61d9a2020-02-05 21:13:18 +0000842
Florin Corasf22f4e52019-12-19 16:10:58 -0800843 return 0;
844}
845
Florin Coras99ad2fc2019-04-18 21:25:49 -0700846int
Florin Coras87b15ce2019-04-28 21:16:30 -0700847svm_fifo_enqueue (svm_fifo_t * f, u32 len, const u8 * src)
Dave Barach68b0fb02017-02-28 15:15:56 -0500848{
Florin Coras99ad2fc2019-04-18 21:25:49 -0700849 u32 tail, head, free_count;
Florin Corasf22f4e52019-12-19 16:10:58 -0800850 svm_fifo_chunk_t *old_tail_c;
851
852 f->ooos_newest = OOO_SEGMENT_INVALID_INDEX;
Florin Coras99ad2fc2019-04-18 21:25:49 -0700853
854 f_load_head_tail_prod (f, &head, &tail);
855
856 /* free space in fifo can only increase during enqueue: SPSC */
857 free_count = f_free_count (f, head, tail);
858
Florin Coras99ad2fc2019-04-18 21:25:49 -0700859 if (PREDICT_FALSE (free_count == 0))
Florin Coras87b15ce2019-04-28 21:16:30 -0700860 return SVM_FIFO_EFULL;
Florin Coras99ad2fc2019-04-18 21:25:49 -0700861
862 /* number of bytes we're going to copy */
863 len = clib_min (free_count, len);
Florin Corasf22f4e52019-12-19 16:10:58 -0800864
Florin Corasaf588822020-12-09 12:51:13 -0800865 if (f_pos_gt (tail + len, f_chunk_end (f_end_cptr (f))))
Florin Corasf22f4e52019-12-19 16:10:58 -0800866 {
Florin Coras9e61d9a2020-02-05 21:13:18 +0000867 if (PREDICT_FALSE (f_try_chunk_alloc (f, head, tail, len)))
Florin Corasf22f4e52019-12-19 16:10:58 -0800868 {
Florin Corasaf588822020-12-09 12:51:13 -0800869 len = f_chunk_end (f_end_cptr (f)) - tail;
Florin Corasf22f4e52019-12-19 16:10:58 -0800870 if (!len)
871 return SVM_FIFO_EGROW;
872 }
873 }
874
Florin Corasaf588822020-12-09 12:51:13 -0800875 old_tail_c = f_tail_cptr (f);
Florin Corasf22f4e52019-12-19 16:10:58 -0800876
Florin Corasaf588822020-12-09 12:51:13 -0800877 svm_fifo_copy_to_chunk (f, old_tail_c, tail, src, len, &f->shr->tail_chunk);
Florin Corasf22f4e52019-12-19 16:10:58 -0800878 tail = tail + len;
Florin Coras99ad2fc2019-04-18 21:25:49 -0700879
Florin Coras87b15ce2019-04-28 21:16:30 -0700880 svm_fifo_trace_add (f, head, len, 2);
Florin Coras99ad2fc2019-04-18 21:25:49 -0700881
882 /* collect out-of-order segments */
883 if (PREDICT_FALSE (f->ooos_list_head != OOO_SEGMENT_INVALID_INDEX))
Florin Coraseaacce42019-07-02 13:07:37 -0700884 {
885 len += ooo_segment_try_collect (f, len, &tail);
Florin Corasf22f4e52019-12-19 16:10:58 -0800886 /* Tail chunk might've changed even if nothing was collected */
Florin Corasaf588822020-12-09 12:51:13 -0800887 f->shr->tail_chunk =
888 f_csptr (f, f_lookup_clear_enq_chunks (f, old_tail_c, tail));
Florin Corasf22f4e52019-12-19 16:10:58 -0800889 f->ooo_enq = 0;
Florin Coraseaacce42019-07-02 13:07:37 -0700890 }
Florin Coras99ad2fc2019-04-18 21:25:49 -0700891
892 /* store-rel: producer owned index (paired with load-acq in consumer) */
Florin Corasc547e912020-12-08 17:50:45 -0800893 clib_atomic_store_rel_n (&f->shr->tail, tail);
Florin Coras99ad2fc2019-04-18 21:25:49 -0700894
895 return len;
896}
897
898/**
899 * Enqueue a future segment.
900 *
901 * Two choices: either copies the entire segment, or copies nothing
902 * Returns 0 of the entire segment was copied
903 * Returns -1 if none of the segment was copied due to lack of space
904 */
905int
906svm_fifo_enqueue_with_offset (svm_fifo_t * f, u32 offset, u32 len, u8 * src)
907{
Florin Corasf22f4e52019-12-19 16:10:58 -0800908 u32 tail, head, free_count, enq_pos;
Florin Corasaf588822020-12-09 12:51:13 -0800909 svm_fifo_chunk_ptr_t last = F_INVALID_CPTR;
Florin Coras99ad2fc2019-04-18 21:25:49 -0700910
911 f_load_head_tail_prod (f, &head, &tail);
912
913 /* free space in fifo can only increase during enqueue: SPSC */
914 free_count = f_free_count (f, head, tail);
Florin Corasf22f4e52019-12-19 16:10:58 -0800915 f->ooos_newest = OOO_SEGMENT_INVALID_INDEX;
Florin Coras99ad2fc2019-04-18 21:25:49 -0700916
917 /* will this request fit? */
918 if ((len + offset) > free_count)
Florin Coras87b15ce2019-04-28 21:16:30 -0700919 return SVM_FIFO_EFULL;
Florin Coras99ad2fc2019-04-18 21:25:49 -0700920
Florin Corasf22f4e52019-12-19 16:10:58 -0800921 enq_pos = tail + offset;
922
Florin Corasaf588822020-12-09 12:51:13 -0800923 if (f_pos_gt (enq_pos + len, f_chunk_end (f_end_cptr (f))))
Florin Corasf22f4e52019-12-19 16:10:58 -0800924 {
Florin Coras9e61d9a2020-02-05 21:13:18 +0000925 if (PREDICT_FALSE (f_try_chunk_alloc (f, head, tail, offset + len)))
Florin Corasf22f4e52019-12-19 16:10:58 -0800926 return SVM_FIFO_EGROW;
927 }
928
Florin Coras99ad2fc2019-04-18 21:25:49 -0700929 svm_fifo_trace_add (f, offset, len, 1);
Florin Coras99ad2fc2019-04-18 21:25:49 -0700930 ooo_segment_add (f, offset, head, tail, len);
Florin Coras4375fa32019-04-19 15:56:00 -0700931
Florin Corasf22f4e52019-12-19 16:10:58 -0800932 if (!f->ooo_enq || !f_chunk_includes_pos (f->ooo_enq, enq_pos))
933 f_update_ooo_enq (f, enq_pos, enq_pos + len);
Florin Coras4375fa32019-04-19 15:56:00 -0700934
Florin Corasaf588822020-12-09 12:51:13 -0800935 svm_fifo_copy_to_chunk (f, f->ooo_enq, enq_pos, src, len, &last);
936 if (last != F_INVALID_CPTR)
937 f->ooo_enq = f_cptr (f, last);
Florin Coras99ad2fc2019-04-18 21:25:49 -0700938
939 return 0;
940}
941
Florin Corasa7570b02019-05-02 12:52:19 -0700942/**
943 * Advance tail
944 */
945void
946svm_fifo_enqueue_nocopy (svm_fifo_t * f, u32 len)
947{
948 u32 tail;
949
950 ASSERT (len <= svm_fifo_max_enqueue_prod (f));
951 /* load-relaxed: producer owned index */
Florin Corasc547e912020-12-08 17:50:45 -0800952 tail = f->shr->tail;
Florin Corasf22f4e52019-12-19 16:10:58 -0800953 tail = tail + len;
Florin Coraseaacce42019-07-02 13:07:37 -0700954
Florin Corasf22f4e52019-12-19 16:10:58 -0800955 if (rb_tree_is_init (&f->ooo_enq_lookup))
956 {
Florin Corasc547e912020-12-08 17:50:45 -0800957 f->shr->tail_chunk =
Florin Corasaf588822020-12-09 12:51:13 -0800958 f_csptr (f, f_lookup_clear_enq_chunks (f, f_tail_cptr (f), tail));
Florin Corasf22f4e52019-12-19 16:10:58 -0800959 f->ooo_enq = 0;
960 }
961 else
962 {
Florin Corasc547e912020-12-08 17:50:45 -0800963 f->shr->tail_chunk =
Florin Corasaf588822020-12-09 12:51:13 -0800964 f_csptr (f, svm_fifo_find_next_chunk (f, f_tail_cptr (f), tail));
Florin Corasf22f4e52019-12-19 16:10:58 -0800965 }
Florin Coraseaacce42019-07-02 13:07:37 -0700966
Florin Corasa7570b02019-05-02 12:52:19 -0700967 /* store-rel: producer owned index (paired with load-acq in consumer) */
Florin Corasc547e912020-12-08 17:50:45 -0800968 clib_atomic_store_rel_n (&f->shr->tail, tail);
Florin Corasa7570b02019-05-02 12:52:19 -0700969}
970
Florin Corasc95cfa22020-11-24 08:41:17 -0800971int
972svm_fifo_enqueue_segments (svm_fifo_t * f, const svm_fifo_seg_t segs[],
973 u32 n_segs, u8 allow_partial)
974{
975 u32 tail, head, free_count, len = 0, i;
976 svm_fifo_chunk_t *old_tail_c;
977
978 f->ooos_newest = OOO_SEGMENT_INVALID_INDEX;
979
980 f_load_head_tail_prod (f, &head, &tail);
981
982 /* free space in fifo can only increase during enqueue: SPSC */
983 free_count = f_free_count (f, head, tail);
984
985 if (PREDICT_FALSE (free_count == 0))
986 return SVM_FIFO_EFULL;
987
988 for (i = 0; i < n_segs; i++)
989 len += segs[i].len;
990
Florin Corasaf588822020-12-09 12:51:13 -0800991 old_tail_c = f_tail_cptr (f);
Florin Corasc95cfa22020-11-24 08:41:17 -0800992
993 if (!allow_partial)
994 {
995 if (PREDICT_FALSE (free_count < len))
996 return SVM_FIFO_EFULL;
997
Florin Corasaf588822020-12-09 12:51:13 -0800998 if (f_pos_gt (tail + len, f_chunk_end (f_end_cptr (f))))
Florin Corasc95cfa22020-11-24 08:41:17 -0800999 {
1000 if (PREDICT_FALSE (f_try_chunk_alloc (f, head, tail, len)))
1001 return SVM_FIFO_EGROW;
1002 }
1003
1004 for (i = 0; i < n_segs; i++)
1005 {
Florin Corasaf588822020-12-09 12:51:13 -08001006 svm_fifo_copy_to_chunk (f, f_tail_cptr (f), tail, segs[i].data,
Florin Corasc547e912020-12-08 17:50:45 -08001007 segs[i].len, &f->shr->tail_chunk);
Florin Corasc95cfa22020-11-24 08:41:17 -08001008 tail += segs[i].len;
1009 }
1010 }
1011 else
1012 {
1013 len = clib_min (free_count, len);
1014
Florin Corasaf588822020-12-09 12:51:13 -08001015 if (f_pos_gt (tail + len, f_chunk_end (f_end_cptr (f))))
Florin Corasc95cfa22020-11-24 08:41:17 -08001016 {
1017 if (PREDICT_FALSE (f_try_chunk_alloc (f, head, tail, len)))
1018 {
Florin Corasaf588822020-12-09 12:51:13 -08001019 len = f_chunk_end (f_end_cptr (f)) - tail;
Florin Corasc95cfa22020-11-24 08:41:17 -08001020 if (!len)
1021 return SVM_FIFO_EGROW;
1022 }
1023 }
1024
1025 i = 0;
1026 while (len)
1027 {
1028 u32 to_copy = clib_min (segs[i].len, len);
Florin Corasaf588822020-12-09 12:51:13 -08001029 svm_fifo_copy_to_chunk (f, f_tail_cptr (f), tail, segs[i].data,
Florin Corasc547e912020-12-08 17:50:45 -08001030 to_copy, &f->shr->tail_chunk);
Florin Corasc95cfa22020-11-24 08:41:17 -08001031 len -= to_copy;
1032 tail += to_copy;
1033 i++;
1034 }
1035 }
1036
1037 /* collect out-of-order segments */
1038 if (PREDICT_FALSE (f->ooos_list_head != OOO_SEGMENT_INVALID_INDEX))
1039 {
1040 len += ooo_segment_try_collect (f, len, &tail);
1041 /* Tail chunk might've changed even if nothing was collected */
Florin Corasaf588822020-12-09 12:51:13 -08001042 f->shr->tail_chunk =
1043 f_csptr (f, f_lookup_clear_enq_chunks (f, old_tail_c, tail));
Florin Corasc95cfa22020-11-24 08:41:17 -08001044 f->ooo_enq = 0;
1045 }
1046
1047 /* store-rel: producer owned index (paired with load-acq in consumer) */
Florin Corasc547e912020-12-08 17:50:45 -08001048 clib_atomic_store_rel_n (&f->shr->tail, tail);
Florin Corasc95cfa22020-11-24 08:41:17 -08001049
1050 return len;
1051}
1052
Florin Corasf22f4e52019-12-19 16:10:58 -08001053always_inline svm_fifo_chunk_t *
1054f_unlink_chunks (svm_fifo_t * f, u32 end_pos, u8 maybe_ooo)
1055{
1056 svm_fifo_chunk_t *start, *prev = 0, *c;
1057 rb_tree_t *rt;
1058 rb_node_t *n;
1059
Florin Corasf22f4e52019-12-19 16:10:58 -08001060 if (maybe_ooo)
1061 rt = &f->ooo_deq_lookup;
1062
Florin Corasaf588822020-12-09 12:51:13 -08001063 c = f_start_cptr (f);
1064 ASSERT (!f_chunk_includes_pos (c, end_pos));
Florin Corasf22f4e52019-12-19 16:10:58 -08001065
1066 do
1067 {
1068 if (maybe_ooo && c->deq_rb_index != RBTREE_TNIL_INDEX)
1069 {
1070 n = rb_node (rt, c->deq_rb_index);
1071 ASSERT (n == f_find_node_rbtree (rt, c->start_byte));
1072 rb_tree_del_node (rt, n);
1073 c->deq_rb_index = RBTREE_TNIL_INDEX;
1074 }
1075 if (!c->next)
1076 break;
1077 prev = c;
Florin Corasaf588822020-12-09 12:51:13 -08001078 c = f_cptr (f, c->next);
Florin Corasf22f4e52019-12-19 16:10:58 -08001079 }
1080 while (!f_chunk_includes_pos (c, end_pos));
1081
1082 if (maybe_ooo)
1083 {
1084 if (f->ooo_deq && f_pos_lt (f->ooo_deq->start_byte, f_chunk_end (c)))
1085 f->ooo_deq = 0;
1086 }
1087 else
1088 {
1089 if (PREDICT_FALSE (f->ooo_deq != 0))
1090 f->ooo_deq = 0;
1091 }
1092
1093 /* Avoid unlinking the last chunk */
1094 if (!prev)
1095 return 0;
1096
1097 prev->next = 0;
Florin Corasaf588822020-12-09 12:51:13 -08001098 start = f_start_cptr (f);
1099 f->shr->start_chunk = f_csptr (f, c);
Florin Corasf22f4e52019-12-19 16:10:58 -08001100
1101 return start;
1102}
1103
Florin Coras99ad2fc2019-04-18 21:25:49 -07001104int
Florin Coras87b15ce2019-04-28 21:16:30 -07001105svm_fifo_dequeue (svm_fifo_t * f, u32 len, u8 * dst)
Florin Coras99ad2fc2019-04-18 21:25:49 -07001106{
1107 u32 tail, head, cursize;
Dave Barach68b0fb02017-02-28 15:15:56 -05001108
Sirshak Das28aa5392019-02-05 01:33:33 -06001109 f_load_head_tail_cons (f, &head, &tail);
1110
1111 /* current size of fifo can only increase during dequeue: SPSC */
1112 cursize = f_cursize (f, head, tail);
1113
Florin Coras3e350af2017-03-30 02:54:28 -07001114 if (PREDICT_FALSE (cursize == 0))
Florin Coras87b15ce2019-04-28 21:16:30 -07001115 return SVM_FIFO_EEMPTY;
Dave Barach68b0fb02017-02-28 15:15:56 -05001116
Florin Coras99ad2fc2019-04-18 21:25:49 -07001117 len = clib_min (cursize, len);
Dave Barach68b0fb02017-02-28 15:15:56 -05001118
Florin Corasc547e912020-12-08 17:50:45 -08001119 if (!f->shr->head_chunk)
Florin Corasaf588822020-12-09 12:51:13 -08001120 f->shr->head_chunk = f_csptr (f, svm_fifo_find_chunk (f, head));
Florin Corasf22f4e52019-12-19 16:10:58 -08001121
Florin Corasaf588822020-12-09 12:51:13 -08001122 svm_fifo_copy_from_chunk (f, f_head_cptr (f), head, dst, len,
Florin Corasc547e912020-12-08 17:50:45 -08001123 &f->shr->head_chunk);
Florin Corasf22f4e52019-12-19 16:10:58 -08001124 head = head + len;
1125
Florin Coras97d39e32020-09-04 08:57:27 -07001126 /* In order dequeues are not supported in combination with ooo peeking.
1127 * Use svm_fifo_dequeue_drop instead. */
1128 ASSERT (rb_tree_n_nodes (&f->ooo_deq_lookup) <= 1);
1129
Florin Corasaf588822020-12-09 12:51:13 -08001130 if (f_pos_geq (head, f_chunk_end (f_start_cptr (f))))
Florin Corasc547e912020-12-08 17:50:45 -08001131 fsh_collect_chunks (f->fs_hdr, f->shr->slice_index,
Florin Corasf22f4e52019-12-19 16:10:58 -08001132 f_unlink_chunks (f, head, 0));
Florin Coras2309e7a2019-04-18 18:58:10 -07001133
Sirshak Das28aa5392019-02-05 01:33:33 -06001134 /* store-rel: consumer owned index (paired with load-acq in producer) */
Florin Corasc547e912020-12-08 17:50:45 -08001135 clib_atomic_store_rel_n (&f->shr->head, head);
Dave Barach68b0fb02017-02-28 15:15:56 -05001136
Florin Coras0a846802019-04-09 18:29:14 -07001137 return len;
Dave Barach68b0fb02017-02-28 15:15:56 -05001138}
1139
Dave Barach68b0fb02017-02-28 15:15:56 -05001140int
Florin Coras4375fa32019-04-19 15:56:00 -07001141svm_fifo_peek (svm_fifo_t * f, u32 offset, u32 len, u8 * dst)
Florin Corasf6359c82017-06-19 12:26:09 -04001142{
Florin Coras4375fa32019-04-19 15:56:00 -07001143 u32 tail, head, cursize, head_idx;
Florin Corasaf588822020-12-09 12:51:13 -08001144 svm_fifo_chunk_ptr_t last = F_INVALID_CPTR;
Dave Barach68b0fb02017-02-28 15:15:56 -05001145
Sirshak Das28aa5392019-02-05 01:33:33 -06001146 f_load_head_tail_cons (f, &head, &tail);
1147
1148 /* current size of fifo can only increase during peek: SPSC */
1149 cursize = f_cursize (f, head, tail);
1150
Florin Coras4375fa32019-04-19 15:56:00 -07001151 if (PREDICT_FALSE (cursize < offset))
Florin Coras87b15ce2019-04-28 21:16:30 -07001152 return SVM_FIFO_EEMPTY;
Dave Barach68b0fb02017-02-28 15:15:56 -05001153
Florin Coras4375fa32019-04-19 15:56:00 -07001154 len = clib_min (cursize - offset, len);
Florin Corasf22f4e52019-12-19 16:10:58 -08001155 head_idx = head + offset;
Florin Corasb0208062019-12-12 12:09:29 -08001156
BenoƮt Gannedf601ae2020-10-20 14:31:55 +02001157 CLIB_MEM_UNPOISON (f->ooo_deq, sizeof (*f->ooo_deq));
Florin Corasf22f4e52019-12-19 16:10:58 -08001158 if (!f->ooo_deq || !f_chunk_includes_pos (f->ooo_deq, head_idx))
1159 f_update_ooo_deq (f, head_idx, head_idx + len);
Dave Barach68b0fb02017-02-28 15:15:56 -05001160
Florin Corasaf588822020-12-09 12:51:13 -08001161 svm_fifo_copy_from_chunk (f, f->ooo_deq, head_idx, dst, len, &last);
1162 if (last != F_INVALID_CPTR)
1163 f->ooo_deq = f_cptr (f, last);
Florin Coras0a846802019-04-09 18:29:14 -07001164 return len;
Dave Barach68b0fb02017-02-28 15:15:56 -05001165}
1166
1167int
Florin Coras87b15ce2019-04-28 21:16:30 -07001168svm_fifo_dequeue_drop (svm_fifo_t * f, u32 len)
Dave Barach68b0fb02017-02-28 15:15:56 -05001169{
Florin Coras87b15ce2019-04-28 21:16:30 -07001170 u32 total_drop_bytes, tail, head, cursize;
Dave Barach68b0fb02017-02-28 15:15:56 -05001171
Sirshak Das28aa5392019-02-05 01:33:33 -06001172 f_load_head_tail_cons (f, &head, &tail);
1173
Florin Coras87b15ce2019-04-28 21:16:30 -07001174 /* number of bytes available */
Sirshak Das28aa5392019-02-05 01:33:33 -06001175 cursize = f_cursize (f, head, tail);
Florin Coras3e350af2017-03-30 02:54:28 -07001176 if (PREDICT_FALSE (cursize == 0))
Florin Coras87b15ce2019-04-28 21:16:30 -07001177 return SVM_FIFO_EEMPTY;
Dave Barach68b0fb02017-02-28 15:15:56 -05001178
Sirshak Das28aa5392019-02-05 01:33:33 -06001179 /* number of bytes we're going to drop */
Florin Coras87b15ce2019-04-28 21:16:30 -07001180 total_drop_bytes = clib_min (cursize, len);
Dave Barach68b0fb02017-02-28 15:15:56 -05001181
Nathan Skrzypczakb4c67752019-06-20 09:58:37 +02001182 svm_fifo_trace_add (f, tail, total_drop_bytes, 3);
1183
Sirshak Das28aa5392019-02-05 01:33:33 -06001184 /* move head */
Florin Corasf22f4e52019-12-19 16:10:58 -08001185 head = head + total_drop_bytes;
Florin Coras3eb50622017-07-13 01:24:57 -04001186
Florin Corasaf588822020-12-09 12:51:13 -08001187 if (f_pos_geq (head, f_chunk_end (f_start_cptr (f))))
Florin Corasf22f4e52019-12-19 16:10:58 -08001188 {
Florin Corasc547e912020-12-08 17:50:45 -08001189 fsh_collect_chunks (f->fs_hdr, f->shr->slice_index,
Florin Corasf22f4e52019-12-19 16:10:58 -08001190 f_unlink_chunks (f, head, 1));
Florin Corasaf588822020-12-09 12:51:13 -08001191 f->shr->head_chunk = f_chunk_includes_pos (f_start_cptr (f), head) ?
Florin Corasc547e912020-12-08 17:50:45 -08001192 f->shr->start_chunk :
1193 0;
Florin Corasf22f4e52019-12-19 16:10:58 -08001194 }
Florin Coras0a6562c2019-08-05 09:39:47 -07001195
Sirshak Das28aa5392019-02-05 01:33:33 -06001196 /* store-rel: consumer owned index (paired with load-acq in producer) */
Florin Corasc547e912020-12-08 17:50:45 -08001197 clib_atomic_store_rel_n (&f->shr->head, head);
Dave Barach68b0fb02017-02-28 15:15:56 -05001198
1199 return total_drop_bytes;
1200}
1201
Florin Corasf22f4e52019-12-19 16:10:58 -08001202/**
1203 * Drop all data from fifo
1204 *
Florin Corasf22f4e52019-12-19 16:10:58 -08001205 */
Florin Coras25579b42018-06-06 17:55:02 -07001206void
1207svm_fifo_dequeue_drop_all (svm_fifo_t * f)
1208{
Florin Corasf22f4e52019-12-19 16:10:58 -08001209 u32 head, tail;
Florin Coraseaacce42019-07-02 13:07:37 -07001210
Florin Corasf22f4e52019-12-19 16:10:58 -08001211 f_load_head_tail_all_acq (f, &head, &tail);
Florin Coraseaacce42019-07-02 13:07:37 -07001212
Florin Corasaf588822020-12-09 12:51:13 -08001213 if (!f->shr->head_chunk || !f_chunk_includes_pos (f_head_cptr (f), head))
1214 f->shr->head_chunk = f_csptr (f, svm_fifo_find_chunk (f, head));
Florin Corasf22f4e52019-12-19 16:10:58 -08001215
Florin Corasaf588822020-12-09 12:51:13 -08001216 f->shr->head_chunk =
1217 f_csptr (f, f_lookup_clear_deq_chunks (f, f_head_cptr (f), tail));
Florin Corasf22f4e52019-12-19 16:10:58 -08001218
Florin Corasaf588822020-12-09 12:51:13 -08001219 if (f_pos_geq (tail, f_chunk_end (f_start_cptr (f))))
Florin Corasc547e912020-12-08 17:50:45 -08001220 fsh_collect_chunks (f->fs_hdr, f->shr->slice_index,
Florin Corasf22f4e52019-12-19 16:10:58 -08001221 f_unlink_chunks (f, tail, 0));
Florin Coras0a6562c2019-08-05 09:39:47 -07001222
Sirshak Das28aa5392019-02-05 01:33:33 -06001223 /* store-rel: consumer owned index (paired with load-acq in producer) */
Florin Corasc547e912020-12-08 17:50:45 -08001224 clib_atomic_store_rel_n (&f->shr->head, tail);
Florin Coras25579b42018-06-06 17:55:02 -07001225}
1226
Florin Coras2cba8532018-09-11 16:33:36 -07001227int
Florin Corasf22f4e52019-12-19 16:10:58 -08001228svm_fifo_fill_chunk_list (svm_fifo_t * f)
1229{
1230 u32 head, tail;
1231
1232 f_load_head_tail_prod (f, &head, &tail);
1233
Florin Corasaf588822020-12-09 12:51:13 -08001234 if (f_chunk_end (f_end_cptr (f)) - head >= f->shr->size)
Florin Corasf22f4e52019-12-19 16:10:58 -08001235 return 0;
1236
Florin Corasc547e912020-12-08 17:50:45 -08001237 if (f_try_chunk_alloc (f, head, tail, f->shr->size - (tail - head)))
Florin Corasf22f4e52019-12-19 16:10:58 -08001238 return SVM_FIFO_EGROW;
1239
1240 return 0;
1241}
1242
1243int
Florin Coras40a5da82020-12-18 09:19:18 -08001244svm_fifo_provision_chunks (svm_fifo_t *f, svm_fifo_seg_t *fs, u32 n_segs,
1245 u32 len)
1246{
1247 u32 head, tail, n_avail, head_pos, n_bytes, fs_index = 1, clen;
1248 svm_fifo_chunk_t *c;
1249
1250 f_load_head_tail_prod (f, &head, &tail);
1251
1252 if (f_free_count (f, head, tail) < len)
1253 return SVM_FIFO_EFULL;
1254
Florin Corasaf588822020-12-09 12:51:13 -08001255 n_avail = f_chunk_end (f_end_cptr (f)) - tail;
Florin Coras40a5da82020-12-18 09:19:18 -08001256
1257 if (n_avail < len && f_try_chunk_alloc (f, head, tail, len))
1258 return SVM_FIFO_EGROW;
1259
Florin Corasaf588822020-12-09 12:51:13 -08001260 c = f_tail_cptr (f);
Florin Coras40a5da82020-12-18 09:19:18 -08001261 head_pos = (tail - c->start_byte);
1262 fs[0].data = c->data + head_pos;
1263 fs[0].len = clib_min (c->length - head_pos, len);
1264 n_bytes = fs[0].len;
1265
1266 while (n_bytes < len && fs_index < n_segs)
1267 {
Florin Corasaf588822020-12-09 12:51:13 -08001268 c = f_cptr (f, c->next);
Florin Coras40a5da82020-12-18 09:19:18 -08001269 clen = clib_min (c->length, len - n_bytes);
1270 fs[fs_index].data = c->data;
1271 fs[fs_index].len = clen;
1272 n_bytes += clen;
1273 fs_index += 1;
1274 }
1275
1276 return fs_index;
1277}
1278
1279int
Florin Corasd1cc38d2020-10-11 11:05:04 -07001280svm_fifo_segments (svm_fifo_t * f, u32 offset, svm_fifo_seg_t * fs,
1281 u32 n_segs, u32 max_bytes)
Florin Coras2cba8532018-09-11 16:33:36 -07001282{
Florin Corasd1cc38d2020-10-11 11:05:04 -07001283 u32 cursize, to_read, head, tail, fs_index = 1;
1284 u32 n_bytes, head_pos, len, start;
Florin Corasd68faf82020-09-25 15:18:13 -07001285 svm_fifo_chunk_t *c;
Florin Coras2cba8532018-09-11 16:33:36 -07001286
Sirshak Das28aa5392019-02-05 01:33:33 -06001287 f_load_head_tail_cons (f, &head, &tail);
1288
1289 /* consumer function, cursize can only increase while we're working */
1290 cursize = f_cursize (f, head, tail);
1291
Florin Coras2cba8532018-09-11 16:33:36 -07001292 if (PREDICT_FALSE (cursize == 0))
Florin Coras87b15ce2019-04-28 21:16:30 -07001293 return SVM_FIFO_EEMPTY;
Florin Coras2cba8532018-09-11 16:33:36 -07001294
Florin Corasd1cc38d2020-10-11 11:05:04 -07001295 if (offset >= cursize)
1296 return SVM_FIFO_EEMPTY;
1297
1298 to_read = clib_min (cursize - offset, max_bytes);
1299 start = head + offset;
1300
Florin Corasc547e912020-12-08 17:50:45 -08001301 if (!f->shr->head_chunk)
Florin Corasaf588822020-12-09 12:51:13 -08001302 f->shr->head_chunk = f_csptr (f, svm_fifo_find_chunk (f, head));
Florin Coras2cba8532018-09-11 16:33:36 -07001303
Florin Corasaf588822020-12-09 12:51:13 -08001304 c = f_head_cptr (f);
Florin Corasd1cc38d2020-10-11 11:05:04 -07001305
1306 while (!f_chunk_includes_pos (c, start))
Florin Corasaf588822020-12-09 12:51:13 -08001307 c = f_cptr (f, c->next);
Florin Corasd1cc38d2020-10-11 11:05:04 -07001308
1309 head_pos = start - c->start_byte;
Florin Corasd68faf82020-09-25 15:18:13 -07001310 fs[0].data = c->data + head_pos;
Florin Corasdfd1caf2020-12-21 10:25:19 -08001311 fs[0].len = clib_min (c->length - head_pos, to_read);
Florin Corasd68faf82020-09-25 15:18:13 -07001312 n_bytes = fs[0].len;
Florin Corasd68faf82020-09-25 15:18:13 -07001313
1314 while (n_bytes < to_read && fs_index < n_segs)
Florin Coras2cba8532018-09-11 16:33:36 -07001315 {
Florin Corasaf588822020-12-09 12:51:13 -08001316 c = f_cptr (f, c->next);
Florin Corasd68faf82020-09-25 15:18:13 -07001317 len = clib_min (c->length, to_read - n_bytes);
1318 fs[fs_index].data = c->data;
1319 fs[fs_index].len = len;
1320 n_bytes += len;
Florin Corasd68faf82020-09-25 15:18:13 -07001321 fs_index += 1;
Florin Coras2cba8532018-09-11 16:33:36 -07001322 }
Florin Coras2cba8532018-09-11 16:33:36 -07001323
Florin Corasd68faf82020-09-25 15:18:13 -07001324 return n_bytes;
Sirshak Das28aa5392019-02-05 01:33:33 -06001325}
1326
Florin Coras87b15ce2019-04-28 21:16:30 -07001327/**
1328 * Clones fifo
1329 *
1330 * Assumptions:
1331 * - no prod and cons are accessing either dest or src fifo
1332 * - fifo is not multi chunk
1333 */
Sirshak Das28aa5392019-02-05 01:33:33 -06001334void
1335svm_fifo_clone (svm_fifo_t * df, svm_fifo_t * sf)
1336{
1337 u32 head, tail;
Florin Corasf22f4e52019-12-19 16:10:58 -08001338
1339 /* Support only single chunk clones for now */
1340 ASSERT (svm_fifo_n_chunks (sf) == 1);
1341
Florin Corasaf588822020-12-09 12:51:13 -08001342 clib_memcpy_fast (f_head_cptr (df)->data, f_head_cptr (sf)->data,
Florin Coras9a45bd82020-12-28 16:28:07 -08001343 f_head_cptr (sf)->length);
Sirshak Das28aa5392019-02-05 01:33:33 -06001344
1345 f_load_head_tail_all_acq (sf, &head, &tail);
Florin Corasc547e912020-12-08 17:50:45 -08001346 clib_atomic_store_rel_n (&df->shr->head, head);
1347 clib_atomic_store_rel_n (&df->shr->tail, tail);
Florin Coras2cba8532018-09-11 16:33:36 -07001348}
1349
Dave Barach1f75cfd2017-04-14 16:46:44 -04001350u32
Florin Coras87b15ce2019-04-28 21:16:30 -07001351svm_fifo_n_ooo_segments (svm_fifo_t * f)
Dave Barach1f75cfd2017-04-14 16:46:44 -04001352{
1353 return pool_elts (f->ooo_segments);
1354}
1355
1356ooo_segment_t *
1357svm_fifo_first_ooo_segment (svm_fifo_t * f)
1358{
1359 return pool_elt_at_index (f->ooo_segments, f->ooos_list_head);
1360}
1361
Florin Corasc28764f2017-04-26 00:08:42 -07001362/**
1363 * Set fifo pointers to requested offset
1364 */
1365void
Florin Coras4375fa32019-04-19 15:56:00 -07001366svm_fifo_init_pointers (svm_fifo_t * f, u32 head, u32 tail)
Florin Corasc28764f2017-04-26 00:08:42 -07001367{
Florin Corasf22f4e52019-12-19 16:10:58 -08001368 svm_fifo_chunk_t *c;
1369
Florin Corasc547e912020-12-08 17:50:45 -08001370 clib_atomic_store_rel_n (&f->shr->head, head);
1371 clib_atomic_store_rel_n (&f->shr->tail, tail);
Florin Corasf22f4e52019-12-19 16:10:58 -08001372
1373 c = svm_fifo_find_chunk (f, head);
1374 ASSERT (c != 0);
Florin Corasaf588822020-12-09 12:51:13 -08001375 f->ooo_deq = c;
1376 f->shr->head_chunk = f_csptr (f, c);
Florin Corasf22f4e52019-12-19 16:10:58 -08001377 c = svm_fifo_find_chunk (f, tail);
1378 ASSERT (c != 0);
Florin Corasaf588822020-12-09 12:51:13 -08001379 f->ooo_enq = c;
1380 f->shr->tail_chunk = f_csptr (f, c);
Florin Corasc28764f2017-04-26 00:08:42 -07001381}
1382
Florin Coras72b04282019-01-14 17:23:11 -08001383void
1384svm_fifo_add_subscriber (svm_fifo_t * f, u8 subscriber)
1385{
Florin Corasc547e912020-12-08 17:50:45 -08001386 if (f->shr->n_subscribers >= SVM_FIFO_MAX_EVT_SUBSCRIBERS)
Florin Coras72b04282019-01-14 17:23:11 -08001387 return;
Florin Corasc547e912020-12-08 17:50:45 -08001388 f->shr->subscribers[f->shr->n_subscribers++] = subscriber;
Florin Coras72b04282019-01-14 17:23:11 -08001389}
1390
1391void
1392svm_fifo_del_subscriber (svm_fifo_t * f, u8 subscriber)
1393{
1394 int i;
1395
Florin Corasc547e912020-12-08 17:50:45 -08001396 for (i = 0; i < f->shr->n_subscribers; i++)
Florin Coras72b04282019-01-14 17:23:11 -08001397 {
Florin Corasc547e912020-12-08 17:50:45 -08001398 if (f->shr->subscribers[i] != subscriber)
Florin Coras72b04282019-01-14 17:23:11 -08001399 continue;
Florin Corasc547e912020-12-08 17:50:45 -08001400 f->shr->subscribers[i] = f->shr->subscribers[f->shr->n_subscribers - 1];
1401 f->shr->n_subscribers--;
Florin Coras72b04282019-01-14 17:23:11 -08001402 break;
1403 }
1404}
1405
Florin Coraseaacce42019-07-02 13:07:37 -07001406u8
1407svm_fifo_is_sane (svm_fifo_t * f)
1408{
Florin Corasf22f4e52019-12-19 16:10:58 -08001409 svm_fifo_chunk_t *tmp;
Florin Coraseaacce42019-07-02 13:07:37 -07001410
Florin Corasc547e912020-12-08 17:50:45 -08001411 if (f->shr->head_chunk &&
Florin Corasaf588822020-12-09 12:51:13 -08001412 !f_chunk_includes_pos (f_head_cptr (f), f->shr->head))
Florin Corasf22f4e52019-12-19 16:10:58 -08001413 return 0;
Florin Corasc547e912020-12-08 17:50:45 -08001414 if (f->shr->tail_chunk &&
Florin Corasaf588822020-12-09 12:51:13 -08001415 !f_chunk_includes_pos (f_tail_cptr (f), f->shr->tail))
Florin Corasf22f4e52019-12-19 16:10:58 -08001416 return 0;
1417 if (f->ooo_deq)
1418 {
1419 if (rb_tree_is_init (&f->ooo_deq_lookup))
1420 {
Florin Corasc547e912020-12-08 17:50:45 -08001421 if (f_pos_lt (f->ooo_deq->start_byte,
Florin Corasaf588822020-12-09 12:51:13 -08001422 f_start_cptr (f)->start_byte) ||
1423 f_pos_gt (f->ooo_deq->start_byte, f_chunk_end (f_end_cptr (f))))
Florin Corasf22f4e52019-12-19 16:10:58 -08001424 return 0;
1425
1426 tmp = f_find_chunk_rbtree (&f->ooo_deq_lookup,
1427 f->ooo_deq->start_byte);
1428 }
1429 else
1430 tmp = svm_fifo_find_chunk (f, f->ooo_deq->start_byte);
1431 if (tmp != f->ooo_deq)
1432 return 0;
1433 }
1434 if (f->ooo_enq)
1435 {
1436 if (rb_tree_is_init (&f->ooo_enq_lookup))
1437 {
Florin Corasc547e912020-12-08 17:50:45 -08001438 if (f_pos_lt (f->ooo_enq->start_byte,
Florin Corasaf588822020-12-09 12:51:13 -08001439 f_start_cptr (f)->start_byte) ||
1440 f_pos_gt (f->ooo_enq->start_byte, f_chunk_end (f_end_cptr (f))))
Florin Corasf22f4e52019-12-19 16:10:58 -08001441 return 0;
1442
1443 tmp = f_find_chunk_rbtree (&f->ooo_enq_lookup,
1444 f->ooo_enq->start_byte);
1445 }
1446 else
1447 {
Florin Corasaf588822020-12-09 12:51:13 -08001448 tmp = svm_fifo_find_next_chunk (f, f_tail_cptr (f),
Florin Corasf22f4e52019-12-19 16:10:58 -08001449 f->ooo_enq->start_byte);
1450 }
1451 if (tmp != f->ooo_enq)
1452 return 0;
1453 }
1454
Florin Corasaf588822020-12-09 12:51:13 -08001455 if (f_start_cptr (f)->next)
Florin Coraseaacce42019-07-02 13:07:37 -07001456 {
1457 svm_fifo_chunk_t *c, *prev = 0, *tmp;
Florin Corasf22f4e52019-12-19 16:10:58 -08001458 u32 chunks_bytes = 0;
Florin Coraseaacce42019-07-02 13:07:37 -07001459
Florin Corasaf588822020-12-09 12:51:13 -08001460 c = f_start_cptr (f);
Florin Coraseaacce42019-07-02 13:07:37 -07001461 do
1462 {
1463 tmp = svm_fifo_find_chunk (f, c->start_byte);
1464 if (tmp != c)
1465 return 0;
1466 if (prev && (prev->start_byte + prev->length != c->start_byte))
1467 return 0;
Florin Corasb0208062019-12-12 12:09:29 -08001468
Florin Corasf22f4e52019-12-19 16:10:58 -08001469 if (c->enq_rb_index != RBTREE_TNIL_INDEX)
Florin Corasb0208062019-12-12 12:09:29 -08001470 {
Florin Corasf22f4e52019-12-19 16:10:58 -08001471 tmp = f_find_chunk_rbtree (&f->ooo_enq_lookup, c->start_byte);
Florin Corasb0208062019-12-12 12:09:29 -08001472 if (tmp)
1473 {
Florin Corasb0208062019-12-12 12:09:29 -08001474 if (tmp != c)
1475 return 0;
1476 }
Florin Corasf22f4e52019-12-19 16:10:58 -08001477 }
1478 if (c->deq_rb_index != RBTREE_TNIL_INDEX)
1479 {
1480 tmp = f_find_chunk_rbtree (&f->ooo_deq_lookup, c->start_byte);
Florin Corasb0208062019-12-12 12:09:29 -08001481 if (tmp)
1482 {
Florin Corasb0208062019-12-12 12:09:29 -08001483 if (tmp != c)
1484 return 0;
1485 }
Florin Corasb0208062019-12-12 12:09:29 -08001486 }
1487
Florin Corasf22f4e52019-12-19 16:10:58 -08001488 chunks_bytes += c->length;
Florin Coraseaacce42019-07-02 13:07:37 -07001489 prev = c;
Florin Corasaf588822020-12-09 12:51:13 -08001490 c = f_cptr (f, c->next);
Florin Coraseaacce42019-07-02 13:07:37 -07001491 }
Florin Corasf22f4e52019-12-19 16:10:58 -08001492 while (c);
Florin Coraseaacce42019-07-02 13:07:37 -07001493
Florin Corasc547e912020-12-08 17:50:45 -08001494 if (chunks_bytes < f->shr->tail - f->shr->head)
Florin Coraseaacce42019-07-02 13:07:37 -07001495 return 0;
1496 }
1497
1498 return 1;
1499}
1500
Florin Corasf22f4e52019-12-19 16:10:58 -08001501u32
1502svm_fifo_n_chunks (svm_fifo_t * f)
Ryujiro Shibuya8e20fe72019-10-16 06:30:02 +01001503{
Florin Corasf22f4e52019-12-19 16:10:58 -08001504 svm_fifo_chunk_t *c;
1505 int n_chunks = 0;
Ryujiro Shibuya8e20fe72019-10-16 06:30:02 +01001506
Florin Corasaf588822020-12-09 12:51:13 -08001507 c = f_start_cptr (f);
Florin Corasf22f4e52019-12-19 16:10:58 -08001508 while (c)
1509 {
1510 n_chunks++;
Florin Corasaf588822020-12-09 12:51:13 -08001511 c = f_cptr (f, c->next);
Ryujiro Shibuya8e20fe72019-10-16 06:30:02 +01001512 }
1513
Florin Corasf22f4e52019-12-19 16:10:58 -08001514 return n_chunks;
Ryujiro Shibuya8e20fe72019-10-16 06:30:02 +01001515}
1516
Florin Coras87b15ce2019-04-28 21:16:30 -07001517u8 *
1518format_ooo_segment (u8 * s, va_list * args)
1519{
Florin Corasf22f4e52019-12-19 16:10:58 -08001520 svm_fifo_t __clib_unused *f = va_arg (*args, svm_fifo_t *);
Florin Coras87b15ce2019-04-28 21:16:30 -07001521 ooo_segment_t *seg = va_arg (*args, ooo_segment_t *);
Florin Corasf22f4e52019-12-19 16:10:58 -08001522 s = format (s, "[%u, %u], len %u, next %d, prev %d", seg->start,
1523 seg->start + seg->length, seg->length, seg->next, seg->prev);
Florin Coras87b15ce2019-04-28 21:16:30 -07001524 return s;
1525}
1526
1527u8 *
1528svm_fifo_dump_trace (u8 * s, svm_fifo_t * f)
1529{
1530#if SVM_FIFO_TRACE
1531 svm_fifo_trace_elem_t *seg = 0;
1532 int i = 0;
1533
1534 if (f->trace)
1535 {
1536 vec_foreach (seg, f->trace)
1537 {
1538 s = format (s, "{%u, %u, %u}, ", seg->offset, seg->len, seg->action);
1539 i++;
1540 if (i % 5 == 0)
1541 s = format (s, "\n");
1542 }
1543 s = format (s, "\n");
1544 }
1545 return s;
1546#else
1547 return 0;
1548#endif
1549}
1550
1551u8 *
1552svm_fifo_replay (u8 * s, svm_fifo_t * f, u8 no_read, u8 verbose)
1553{
1554 int i, trace_len;
1555 u8 *data = 0;
1556 svm_fifo_trace_elem_t *trace;
1557 u32 offset;
Dave Barach11fb09e2020-08-06 12:10:09 -04001558 svm_fifo_t *placeholder_fifo;
Florin Coras87b15ce2019-04-28 21:16:30 -07001559
1560 if (!f)
1561 return s;
1562
1563#if SVM_FIFO_TRACE
1564 trace = f->trace;
1565 trace_len = vec_len (trace);
1566#else
1567 trace = 0;
1568 trace_len = 0;
1569#endif
1570
Florin Corasc547e912020-12-08 17:50:45 -08001571 placeholder_fifo = svm_fifo_alloc (f->shr->size);
1572 svm_fifo_init (f, f->shr->size);
Florin Corasaf588822020-12-09 12:51:13 -08001573 clib_memset (f_head_cptr (f)->data, 0xFF, f->shr->size);
Florin Corasc547e912020-12-08 17:50:45 -08001574 vec_validate (data, f->shr->size);
Florin Coras87b15ce2019-04-28 21:16:30 -07001575 for (i = 0; i < vec_len (data); i++)
1576 data[i] = i;
1577
1578 for (i = 0; i < trace_len; i++)
1579 {
1580 offset = trace[i].offset;
1581 if (trace[i].action == 1)
1582 {
1583 if (verbose)
1584 s = format (s, "adding [%u, %u]:", trace[i].offset,
Florin Corasf22f4e52019-12-19 16:10:58 -08001585 (trace[i].offset + trace[i].len));
Dave Barach11fb09e2020-08-06 12:10:09 -04001586 svm_fifo_enqueue_with_offset (placeholder_fifo, trace[i].offset,
Florin Coras87b15ce2019-04-28 21:16:30 -07001587 trace[i].len, &data[offset]);
1588 }
1589 else if (trace[i].action == 2)
1590 {
1591 if (verbose)
1592 s = format (s, "adding [%u, %u]:", 0, trace[i].len);
Dave Barach11fb09e2020-08-06 12:10:09 -04001593 svm_fifo_enqueue (placeholder_fifo, trace[i].len, &data[offset]);
Florin Coras87b15ce2019-04-28 21:16:30 -07001594 }
1595 else if (!no_read)
1596 {
1597 if (verbose)
1598 s = format (s, "read: %u", trace[i].len);
Dave Barach11fb09e2020-08-06 12:10:09 -04001599 svm_fifo_dequeue_drop (placeholder_fifo, trace[i].len);
Florin Coras87b15ce2019-04-28 21:16:30 -07001600 }
1601 if (verbose)
Dave Barach11fb09e2020-08-06 12:10:09 -04001602 s = format (s, "%U", format_svm_fifo, placeholder_fifo, 1);
Florin Coras87b15ce2019-04-28 21:16:30 -07001603 }
1604
Dave Barach11fb09e2020-08-06 12:10:09 -04001605 s = format (s, "result: %U", format_svm_fifo, placeholder_fifo, 1);
Florin Coras87b15ce2019-04-28 21:16:30 -07001606
1607 return s;
1608}
1609
1610u8 *
1611format_ooo_list (u8 * s, va_list * args)
1612{
1613 svm_fifo_t *f = va_arg (*args, svm_fifo_t *);
1614 u32 indent = va_arg (*args, u32);
1615 u32 ooo_segment_index = f->ooos_list_head;
1616 ooo_segment_t *seg;
1617
1618 while (ooo_segment_index != OOO_SEGMENT_INVALID_INDEX)
1619 {
1620 seg = pool_elt_at_index (f->ooo_segments, ooo_segment_index);
1621 s = format (s, "%U%U\n", format_white_space, indent, format_ooo_segment,
1622 f, seg);
1623 ooo_segment_index = seg->next;
1624 }
1625
1626 return s;
1627}
1628
1629u8 *
1630format_svm_fifo (u8 * s, va_list * args)
1631{
1632 svm_fifo_t *f = va_arg (*args, svm_fifo_t *);
1633 int verbose = va_arg (*args, int);
1634 u32 indent;
1635
1636 if (!s)
1637 return s;
1638
1639 indent = format_get_indent (s);
Florin Corasf22f4e52019-12-19 16:10:58 -08001640 s = format (s, "cursize %u nitems %u has_event %d min_alloc %u\n",
Florin Corasc547e912020-12-08 17:50:45 -08001641 svm_fifo_max_dequeue (f), f->shr->size, f->shr->has_event,
1642 f->shr->min_alloc);
Florin Coras87b15ce2019-04-28 21:16:30 -07001643 s = format (s, "%Uhead %u tail %u segment manager %u\n", format_white_space,
Florin Corasc547e912020-12-08 17:50:45 -08001644 indent, f->shr->head, f->shr->tail, f->segment_manager);
Florin Coras87b15ce2019-04-28 21:16:30 -07001645
1646 if (verbose > 1)
1647 s = format (s, "%Uvpp session %d thread %d app session %d thread %d\n",
Florin Corasc547e912020-12-08 17:50:45 -08001648 format_white_space, indent, f->shr->master_session_index,
1649 f->master_thread_index, f->shr->client_session_index,
Florin Coras87b15ce2019-04-28 21:16:30 -07001650 f->client_thread_index);
1651
1652 if (verbose)
1653 {
1654 s = format (s, "%Uooo pool %d active elts newest %u\n",
1655 format_white_space, indent, pool_elts (f->ooo_segments),
1656 f->ooos_newest);
1657 if (svm_fifo_has_ooo_data (f))
1658 s = format (s, " %U", format_ooo_list, f, indent, verbose);
1659 }
1660 return s;
1661}
1662
Florin Coras3aa7af32018-06-29 08:44:31 -07001663#endif
Dave Barach68b0fb02017-02-28 15:15:56 -05001664/*
1665 * fd.io coding-style-patch-verification: ON
1666 *
1667 * Local Variables:
1668 * eval: (c-set-style "gnu")
1669 * End:
1670 */