blob: 7197e386dbdbbc0751fff5ddcbb984fe143c566a [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 Coras17672aa2020-12-29 16:55:32 -080024#define F_INVALID_CPTR (fs_sptr_t) ~0ULL
Florin Corasaf588822020-12-09 12:51:13 -080025
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,
Florin Coras17672aa2020-12-29 16:55:32 -080028 fs_sptr_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,
Florin Coras17672aa2020-12-29 16:55:32 -080059 fs_sptr_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,
Florin Coras17672aa2020-12-29 16:55:32 -080094 const u8 *src, u32 len, fs_sptr_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,
Florin Coras17672aa2020-12-29 16:55:32 -0800102 u8 *dst, u32 len, fs_sptr_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 Coras17672aa2020-12-29 16:55:32 -0800909 fs_sptr_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 {
Florin Coras95bbbe42022-01-18 14:11:11 -08001013 u32 n_left = clib_min (free_count, len);
Florin Corasc95cfa22020-11-24 08:41:17 -08001014
Florin Coras95bbbe42022-01-18 14:11:11 -08001015 if (f_pos_gt (tail + n_left, f_chunk_end (f_end_cptr (f))))
Florin Corasc95cfa22020-11-24 08:41:17 -08001016 {
Florin Coras95bbbe42022-01-18 14:11:11 -08001017 if (PREDICT_FALSE (f_try_chunk_alloc (f, head, tail, n_left)))
Florin Corasc95cfa22020-11-24 08:41:17 -08001018 {
Florin Coras95bbbe42022-01-18 14:11:11 -08001019 n_left = f_chunk_end (f_end_cptr (f)) - tail;
1020 if (!n_left)
Florin Corasc95cfa22020-11-24 08:41:17 -08001021 return SVM_FIFO_EGROW;
1022 }
1023 }
1024
Florin Coras95bbbe42022-01-18 14:11:11 -08001025 len = n_left;
Florin Corasc95cfa22020-11-24 08:41:17 -08001026 i = 0;
Florin Coras95bbbe42022-01-18 14:11:11 -08001027 while (n_left)
Florin Corasc95cfa22020-11-24 08:41:17 -08001028 {
Florin Coras95bbbe42022-01-18 14:11:11 -08001029 u32 to_copy = clib_min (segs[i].len, n_left);
Florin Corasaf588822020-12-09 12:51:13 -08001030 svm_fifo_copy_to_chunk (f, f_tail_cptr (f), tail, segs[i].data,
Florin Corasc547e912020-12-08 17:50:45 -08001031 to_copy, &f->shr->tail_chunk);
Florin Coras95bbbe42022-01-18 14:11:11 -08001032 n_left -= to_copy;
Florin Corasc95cfa22020-11-24 08:41:17 -08001033 tail += to_copy;
1034 i++;
1035 }
1036 }
1037
1038 /* collect out-of-order segments */
1039 if (PREDICT_FALSE (f->ooos_list_head != OOO_SEGMENT_INVALID_INDEX))
1040 {
1041 len += ooo_segment_try_collect (f, len, &tail);
1042 /* Tail chunk might've changed even if nothing was collected */
Florin Corasaf588822020-12-09 12:51:13 -08001043 f->shr->tail_chunk =
1044 f_csptr (f, f_lookup_clear_enq_chunks (f, old_tail_c, tail));
Florin Corasc95cfa22020-11-24 08:41:17 -08001045 f->ooo_enq = 0;
1046 }
1047
1048 /* store-rel: producer owned index (paired with load-acq in consumer) */
Florin Corasc547e912020-12-08 17:50:45 -08001049 clib_atomic_store_rel_n (&f->shr->tail, tail);
Florin Corasc95cfa22020-11-24 08:41:17 -08001050
1051 return len;
1052}
1053
Florin Corasf22f4e52019-12-19 16:10:58 -08001054always_inline svm_fifo_chunk_t *
1055f_unlink_chunks (svm_fifo_t * f, u32 end_pos, u8 maybe_ooo)
1056{
1057 svm_fifo_chunk_t *start, *prev = 0, *c;
1058 rb_tree_t *rt;
1059 rb_node_t *n;
1060
Florin Corasf22f4e52019-12-19 16:10:58 -08001061 if (maybe_ooo)
1062 rt = &f->ooo_deq_lookup;
1063
Florin Corasaf588822020-12-09 12:51:13 -08001064 c = f_start_cptr (f);
1065 ASSERT (!f_chunk_includes_pos (c, end_pos));
Florin Corasf22f4e52019-12-19 16:10:58 -08001066
1067 do
1068 {
1069 if (maybe_ooo && c->deq_rb_index != RBTREE_TNIL_INDEX)
1070 {
1071 n = rb_node (rt, c->deq_rb_index);
1072 ASSERT (n == f_find_node_rbtree (rt, c->start_byte));
1073 rb_tree_del_node (rt, n);
1074 c->deq_rb_index = RBTREE_TNIL_INDEX;
1075 }
1076 if (!c->next)
1077 break;
1078 prev = c;
Florin Corasaf588822020-12-09 12:51:13 -08001079 c = f_cptr (f, c->next);
Florin Corasf22f4e52019-12-19 16:10:58 -08001080 }
1081 while (!f_chunk_includes_pos (c, end_pos));
1082
1083 if (maybe_ooo)
1084 {
1085 if (f->ooo_deq && f_pos_lt (f->ooo_deq->start_byte, f_chunk_end (c)))
1086 f->ooo_deq = 0;
1087 }
1088 else
1089 {
1090 if (PREDICT_FALSE (f->ooo_deq != 0))
1091 f->ooo_deq = 0;
1092 }
1093
1094 /* Avoid unlinking the last chunk */
1095 if (!prev)
1096 return 0;
1097
1098 prev->next = 0;
Florin Corasaf588822020-12-09 12:51:13 -08001099 start = f_start_cptr (f);
1100 f->shr->start_chunk = f_csptr (f, c);
Florin Corasf22f4e52019-12-19 16:10:58 -08001101
1102 return start;
1103}
1104
Florin Coras99ad2fc2019-04-18 21:25:49 -07001105int
Florin Coras87b15ce2019-04-28 21:16:30 -07001106svm_fifo_dequeue (svm_fifo_t * f, u32 len, u8 * dst)
Florin Coras99ad2fc2019-04-18 21:25:49 -07001107{
1108 u32 tail, head, cursize;
Dave Barach68b0fb02017-02-28 15:15:56 -05001109
Sirshak Das28aa5392019-02-05 01:33:33 -06001110 f_load_head_tail_cons (f, &head, &tail);
1111
1112 /* current size of fifo can only increase during dequeue: SPSC */
1113 cursize = f_cursize (f, head, tail);
1114
Florin Coras3e350af2017-03-30 02:54:28 -07001115 if (PREDICT_FALSE (cursize == 0))
Florin Coras87b15ce2019-04-28 21:16:30 -07001116 return SVM_FIFO_EEMPTY;
Dave Barach68b0fb02017-02-28 15:15:56 -05001117
Florin Coras99ad2fc2019-04-18 21:25:49 -07001118 len = clib_min (cursize, len);
Dave Barach68b0fb02017-02-28 15:15:56 -05001119
Florin Corasc547e912020-12-08 17:50:45 -08001120 if (!f->shr->head_chunk)
Florin Corasaf588822020-12-09 12:51:13 -08001121 f->shr->head_chunk = f_csptr (f, svm_fifo_find_chunk (f, head));
Florin Corasf22f4e52019-12-19 16:10:58 -08001122
Florin Corasaf588822020-12-09 12:51:13 -08001123 svm_fifo_copy_from_chunk (f, f_head_cptr (f), head, dst, len,
Florin Corasc547e912020-12-08 17:50:45 -08001124 &f->shr->head_chunk);
Florin Corasf22f4e52019-12-19 16:10:58 -08001125 head = head + len;
1126
Florin Coras97d39e32020-09-04 08:57:27 -07001127 /* In order dequeues are not supported in combination with ooo peeking.
1128 * Use svm_fifo_dequeue_drop instead. */
1129 ASSERT (rb_tree_n_nodes (&f->ooo_deq_lookup) <= 1);
1130
Florin Corasaf588822020-12-09 12:51:13 -08001131 if (f_pos_geq (head, f_chunk_end (f_start_cptr (f))))
Florin Corasc547e912020-12-08 17:50:45 -08001132 fsh_collect_chunks (f->fs_hdr, f->shr->slice_index,
Florin Corasf22f4e52019-12-19 16:10:58 -08001133 f_unlink_chunks (f, head, 0));
Florin Coras2309e7a2019-04-18 18:58:10 -07001134
Sirshak Das28aa5392019-02-05 01:33:33 -06001135 /* store-rel: consumer owned index (paired with load-acq in producer) */
Florin Corasc547e912020-12-08 17:50:45 -08001136 clib_atomic_store_rel_n (&f->shr->head, head);
Dave Barach68b0fb02017-02-28 15:15:56 -05001137
Florin Coras0a846802019-04-09 18:29:14 -07001138 return len;
Dave Barach68b0fb02017-02-28 15:15:56 -05001139}
1140
Dave Barach68b0fb02017-02-28 15:15:56 -05001141int
Florin Coras4375fa32019-04-19 15:56:00 -07001142svm_fifo_peek (svm_fifo_t * f, u32 offset, u32 len, u8 * dst)
Florin Corasf6359c82017-06-19 12:26:09 -04001143{
Florin Coras4375fa32019-04-19 15:56:00 -07001144 u32 tail, head, cursize, head_idx;
Florin Coras17672aa2020-12-29 16:55:32 -08001145 fs_sptr_t last = F_INVALID_CPTR;
Dave Barach68b0fb02017-02-28 15:15:56 -05001146
Sirshak Das28aa5392019-02-05 01:33:33 -06001147 f_load_head_tail_cons (f, &head, &tail);
1148
1149 /* current size of fifo can only increase during peek: SPSC */
1150 cursize = f_cursize (f, head, tail);
1151
Florin Coras4375fa32019-04-19 15:56:00 -07001152 if (PREDICT_FALSE (cursize < offset))
Florin Coras87b15ce2019-04-28 21:16:30 -07001153 return SVM_FIFO_EEMPTY;
Dave Barach68b0fb02017-02-28 15:15:56 -05001154
Florin Coras4375fa32019-04-19 15:56:00 -07001155 len = clib_min (cursize - offset, len);
Florin Corasf22f4e52019-12-19 16:10:58 -08001156 head_idx = head + offset;
Florin Corasb0208062019-12-12 12:09:29 -08001157
BenoƮt Gannedf601ae2020-10-20 14:31:55 +02001158 CLIB_MEM_UNPOISON (f->ooo_deq, sizeof (*f->ooo_deq));
Florin Corasf22f4e52019-12-19 16:10:58 -08001159 if (!f->ooo_deq || !f_chunk_includes_pos (f->ooo_deq, head_idx))
1160 f_update_ooo_deq (f, head_idx, head_idx + len);
Dave Barach68b0fb02017-02-28 15:15:56 -05001161
Florin Corasaf588822020-12-09 12:51:13 -08001162 svm_fifo_copy_from_chunk (f, f->ooo_deq, head_idx, dst, len, &last);
1163 if (last != F_INVALID_CPTR)
1164 f->ooo_deq = f_cptr (f, last);
Florin Coras0a846802019-04-09 18:29:14 -07001165 return len;
Dave Barach68b0fb02017-02-28 15:15:56 -05001166}
1167
1168int
Florin Coras87b15ce2019-04-28 21:16:30 -07001169svm_fifo_dequeue_drop (svm_fifo_t * f, u32 len)
Dave Barach68b0fb02017-02-28 15:15:56 -05001170{
Florin Coras87b15ce2019-04-28 21:16:30 -07001171 u32 total_drop_bytes, tail, head, cursize;
Dave Barach68b0fb02017-02-28 15:15:56 -05001172
Sirshak Das28aa5392019-02-05 01:33:33 -06001173 f_load_head_tail_cons (f, &head, &tail);
1174
Florin Coras87b15ce2019-04-28 21:16:30 -07001175 /* number of bytes available */
Sirshak Das28aa5392019-02-05 01:33:33 -06001176 cursize = f_cursize (f, head, tail);
Florin Coras3e350af2017-03-30 02:54:28 -07001177 if (PREDICT_FALSE (cursize == 0))
Florin Coras87b15ce2019-04-28 21:16:30 -07001178 return SVM_FIFO_EEMPTY;
Dave Barach68b0fb02017-02-28 15:15:56 -05001179
Sirshak Das28aa5392019-02-05 01:33:33 -06001180 /* number of bytes we're going to drop */
Florin Coras87b15ce2019-04-28 21:16:30 -07001181 total_drop_bytes = clib_min (cursize, len);
Dave Barach68b0fb02017-02-28 15:15:56 -05001182
Nathan Skrzypczakb4c67752019-06-20 09:58:37 +02001183 svm_fifo_trace_add (f, tail, total_drop_bytes, 3);
1184
Sirshak Das28aa5392019-02-05 01:33:33 -06001185 /* move head */
Florin Corasf22f4e52019-12-19 16:10:58 -08001186 head = head + total_drop_bytes;
Florin Coras3eb50622017-07-13 01:24:57 -04001187
Florin Corasaf588822020-12-09 12:51:13 -08001188 if (f_pos_geq (head, f_chunk_end (f_start_cptr (f))))
Florin Corasf22f4e52019-12-19 16:10:58 -08001189 {
Florin Corasc547e912020-12-08 17:50:45 -08001190 fsh_collect_chunks (f->fs_hdr, f->shr->slice_index,
Florin Corasf22f4e52019-12-19 16:10:58 -08001191 f_unlink_chunks (f, head, 1));
Florin Corasaf588822020-12-09 12:51:13 -08001192 f->shr->head_chunk = f_chunk_includes_pos (f_start_cptr (f), head) ?
Florin Corasc547e912020-12-08 17:50:45 -08001193 f->shr->start_chunk :
1194 0;
Florin Corasf22f4e52019-12-19 16:10:58 -08001195 }
Florin Coras0a6562c2019-08-05 09:39:47 -07001196
Sirshak Das28aa5392019-02-05 01:33:33 -06001197 /* store-rel: consumer owned index (paired with load-acq in producer) */
Florin Corasc547e912020-12-08 17:50:45 -08001198 clib_atomic_store_rel_n (&f->shr->head, head);
Dave Barach68b0fb02017-02-28 15:15:56 -05001199
1200 return total_drop_bytes;
1201}
1202
Florin Corasf22f4e52019-12-19 16:10:58 -08001203/**
1204 * Drop all data from fifo
1205 *
Florin Corasf22f4e52019-12-19 16:10:58 -08001206 */
Florin Coras25579b42018-06-06 17:55:02 -07001207void
1208svm_fifo_dequeue_drop_all (svm_fifo_t * f)
1209{
Florin Corasf22f4e52019-12-19 16:10:58 -08001210 u32 head, tail;
Florin Coraseaacce42019-07-02 13:07:37 -07001211
Florin Corasf22f4e52019-12-19 16:10:58 -08001212 f_load_head_tail_all_acq (f, &head, &tail);
Florin Coraseaacce42019-07-02 13:07:37 -07001213
Florin Corasaf588822020-12-09 12:51:13 -08001214 if (!f->shr->head_chunk || !f_chunk_includes_pos (f_head_cptr (f), head))
1215 f->shr->head_chunk = f_csptr (f, svm_fifo_find_chunk (f, head));
Florin Corasf22f4e52019-12-19 16:10:58 -08001216
Florin Corasaf588822020-12-09 12:51:13 -08001217 f->shr->head_chunk =
1218 f_csptr (f, f_lookup_clear_deq_chunks (f, f_head_cptr (f), tail));
Florin Corasf22f4e52019-12-19 16:10:58 -08001219
Florin Corasaf588822020-12-09 12:51:13 -08001220 if (f_pos_geq (tail, f_chunk_end (f_start_cptr (f))))
Florin Corasc547e912020-12-08 17:50:45 -08001221 fsh_collect_chunks (f->fs_hdr, f->shr->slice_index,
Florin Corasf22f4e52019-12-19 16:10:58 -08001222 f_unlink_chunks (f, tail, 0));
Florin Coras0a6562c2019-08-05 09:39:47 -07001223
Sirshak Das28aa5392019-02-05 01:33:33 -06001224 /* store-rel: consumer owned index (paired with load-acq in producer) */
Florin Corasc547e912020-12-08 17:50:45 -08001225 clib_atomic_store_rel_n (&f->shr->head, tail);
Florin Coras25579b42018-06-06 17:55:02 -07001226}
1227
Florin Coras2cba8532018-09-11 16:33:36 -07001228int
Florin Corasf22f4e52019-12-19 16:10:58 -08001229svm_fifo_fill_chunk_list (svm_fifo_t * f)
1230{
1231 u32 head, tail;
1232
1233 f_load_head_tail_prod (f, &head, &tail);
1234
Florin Corasaf588822020-12-09 12:51:13 -08001235 if (f_chunk_end (f_end_cptr (f)) - head >= f->shr->size)
Florin Corasf22f4e52019-12-19 16:10:58 -08001236 return 0;
1237
Florin Corasc547e912020-12-08 17:50:45 -08001238 if (f_try_chunk_alloc (f, head, tail, f->shr->size - (tail - head)))
Florin Corasf22f4e52019-12-19 16:10:58 -08001239 return SVM_FIFO_EGROW;
1240
1241 return 0;
1242}
1243
1244int
Florin Coras40a5da82020-12-18 09:19:18 -08001245svm_fifo_provision_chunks (svm_fifo_t *f, svm_fifo_seg_t *fs, u32 n_segs,
1246 u32 len)
1247{
1248 u32 head, tail, n_avail, head_pos, n_bytes, fs_index = 1, clen;
1249 svm_fifo_chunk_t *c;
1250
1251 f_load_head_tail_prod (f, &head, &tail);
1252
1253 if (f_free_count (f, head, tail) < len)
1254 return SVM_FIFO_EFULL;
1255
Florin Corasaf588822020-12-09 12:51:13 -08001256 n_avail = f_chunk_end (f_end_cptr (f)) - tail;
Florin Coras40a5da82020-12-18 09:19:18 -08001257
1258 if (n_avail < len && f_try_chunk_alloc (f, head, tail, len))
1259 return SVM_FIFO_EGROW;
1260
Florin Corase3c6a542021-05-19 19:28:40 -07001261 if (!fs || !n_segs)
1262 return 0;
1263
Florin Corasaf588822020-12-09 12:51:13 -08001264 c = f_tail_cptr (f);
Florin Coras40a5da82020-12-18 09:19:18 -08001265 head_pos = (tail - c->start_byte);
1266 fs[0].data = c->data + head_pos;
1267 fs[0].len = clib_min (c->length - head_pos, len);
1268 n_bytes = fs[0].len;
1269
1270 while (n_bytes < len && fs_index < n_segs)
1271 {
Florin Corasaf588822020-12-09 12:51:13 -08001272 c = f_cptr (f, c->next);
Florin Coras40a5da82020-12-18 09:19:18 -08001273 clen = clib_min (c->length, len - n_bytes);
1274 fs[fs_index].data = c->data;
1275 fs[fs_index].len = clen;
1276 n_bytes += clen;
1277 fs_index += 1;
1278 }
1279
1280 return fs_index;
1281}
1282
1283int
Florin Corasd1cc38d2020-10-11 11:05:04 -07001284svm_fifo_segments (svm_fifo_t * f, u32 offset, svm_fifo_seg_t * fs,
1285 u32 n_segs, u32 max_bytes)
Florin Coras2cba8532018-09-11 16:33:36 -07001286{
Florin Corasd1cc38d2020-10-11 11:05:04 -07001287 u32 cursize, to_read, head, tail, fs_index = 1;
1288 u32 n_bytes, head_pos, len, start;
Florin Corasd68faf82020-09-25 15:18:13 -07001289 svm_fifo_chunk_t *c;
Florin Coras2cba8532018-09-11 16:33:36 -07001290
Sirshak Das28aa5392019-02-05 01:33:33 -06001291 f_load_head_tail_cons (f, &head, &tail);
1292
1293 /* consumer function, cursize can only increase while we're working */
1294 cursize = f_cursize (f, head, tail);
1295
Florin Coras2cba8532018-09-11 16:33:36 -07001296 if (PREDICT_FALSE (cursize == 0))
Florin Coras87b15ce2019-04-28 21:16:30 -07001297 return SVM_FIFO_EEMPTY;
Florin Coras2cba8532018-09-11 16:33:36 -07001298
Florin Corasd1cc38d2020-10-11 11:05:04 -07001299 if (offset >= cursize)
1300 return SVM_FIFO_EEMPTY;
1301
1302 to_read = clib_min (cursize - offset, max_bytes);
1303 start = head + offset;
1304
Florin Corasc547e912020-12-08 17:50:45 -08001305 if (!f->shr->head_chunk)
Florin Corasaf588822020-12-09 12:51:13 -08001306 f->shr->head_chunk = f_csptr (f, svm_fifo_find_chunk (f, head));
Florin Coras2cba8532018-09-11 16:33:36 -07001307
Florin Corasaf588822020-12-09 12:51:13 -08001308 c = f_head_cptr (f);
Florin Corasd1cc38d2020-10-11 11:05:04 -07001309
1310 while (!f_chunk_includes_pos (c, start))
Florin Corasaf588822020-12-09 12:51:13 -08001311 c = f_cptr (f, c->next);
Florin Corasd1cc38d2020-10-11 11:05:04 -07001312
1313 head_pos = start - c->start_byte;
Florin Corasd68faf82020-09-25 15:18:13 -07001314 fs[0].data = c->data + head_pos;
Florin Corasdfd1caf2020-12-21 10:25:19 -08001315 fs[0].len = clib_min (c->length - head_pos, to_read);
Florin Corasd68faf82020-09-25 15:18:13 -07001316 n_bytes = fs[0].len;
Florin Corasd68faf82020-09-25 15:18:13 -07001317
1318 while (n_bytes < to_read && fs_index < n_segs)
Florin Coras2cba8532018-09-11 16:33:36 -07001319 {
Florin Corasaf588822020-12-09 12:51:13 -08001320 c = f_cptr (f, c->next);
Florin Corasd68faf82020-09-25 15:18:13 -07001321 len = clib_min (c->length, to_read - n_bytes);
1322 fs[fs_index].data = c->data;
1323 fs[fs_index].len = len;
1324 n_bytes += len;
Florin Corasd68faf82020-09-25 15:18:13 -07001325 fs_index += 1;
Florin Coras2cba8532018-09-11 16:33:36 -07001326 }
Florin Coras2cba8532018-09-11 16:33:36 -07001327
Florin Corasd68faf82020-09-25 15:18:13 -07001328 return n_bytes;
Sirshak Das28aa5392019-02-05 01:33:33 -06001329}
1330
Florin Coras87b15ce2019-04-28 21:16:30 -07001331/**
1332 * Clones fifo
1333 *
1334 * Assumptions:
1335 * - no prod and cons are accessing either dest or src fifo
1336 * - fifo is not multi chunk
1337 */
Sirshak Das28aa5392019-02-05 01:33:33 -06001338void
1339svm_fifo_clone (svm_fifo_t * df, svm_fifo_t * sf)
1340{
1341 u32 head, tail;
Florin Corasf22f4e52019-12-19 16:10:58 -08001342
1343 /* Support only single chunk clones for now */
1344 ASSERT (svm_fifo_n_chunks (sf) == 1);
1345
Florin Corasaf588822020-12-09 12:51:13 -08001346 clib_memcpy_fast (f_head_cptr (df)->data, f_head_cptr (sf)->data,
Florin Coras9a45bd82020-12-28 16:28:07 -08001347 f_head_cptr (sf)->length);
Sirshak Das28aa5392019-02-05 01:33:33 -06001348
1349 f_load_head_tail_all_acq (sf, &head, &tail);
Florin Corasc547e912020-12-08 17:50:45 -08001350 clib_atomic_store_rel_n (&df->shr->head, head);
1351 clib_atomic_store_rel_n (&df->shr->tail, tail);
Florin Coras2cba8532018-09-11 16:33:36 -07001352}
1353
Dave Barach1f75cfd2017-04-14 16:46:44 -04001354u32
Florin Coras87b15ce2019-04-28 21:16:30 -07001355svm_fifo_n_ooo_segments (svm_fifo_t * f)
Dave Barach1f75cfd2017-04-14 16:46:44 -04001356{
1357 return pool_elts (f->ooo_segments);
1358}
1359
1360ooo_segment_t *
1361svm_fifo_first_ooo_segment (svm_fifo_t * f)
1362{
1363 return pool_elt_at_index (f->ooo_segments, f->ooos_list_head);
1364}
1365
Florin Corasc28764f2017-04-26 00:08:42 -07001366/**
1367 * Set fifo pointers to requested offset
1368 */
1369void
Florin Coras4375fa32019-04-19 15:56:00 -07001370svm_fifo_init_pointers (svm_fifo_t * f, u32 head, u32 tail)
Florin Corasc28764f2017-04-26 00:08:42 -07001371{
Florin Corasf22f4e52019-12-19 16:10:58 -08001372 svm_fifo_chunk_t *c;
1373
Florin Corasc547e912020-12-08 17:50:45 -08001374 clib_atomic_store_rel_n (&f->shr->head, head);
1375 clib_atomic_store_rel_n (&f->shr->tail, tail);
Florin Corasf22f4e52019-12-19 16:10:58 -08001376
1377 c = svm_fifo_find_chunk (f, head);
1378 ASSERT (c != 0);
Florin Corasaf588822020-12-09 12:51:13 -08001379 f->ooo_deq = c;
1380 f->shr->head_chunk = f_csptr (f, c);
Florin Corasf22f4e52019-12-19 16:10:58 -08001381 c = svm_fifo_find_chunk (f, tail);
1382 ASSERT (c != 0);
Florin Corasaf588822020-12-09 12:51:13 -08001383 f->ooo_enq = c;
1384 f->shr->tail_chunk = f_csptr (f, c);
Florin Corasc28764f2017-04-26 00:08:42 -07001385}
1386
Florin Coras72b04282019-01-14 17:23:11 -08001387void
1388svm_fifo_add_subscriber (svm_fifo_t * f, u8 subscriber)
1389{
Florin Corasc547e912020-12-08 17:50:45 -08001390 if (f->shr->n_subscribers >= SVM_FIFO_MAX_EVT_SUBSCRIBERS)
Florin Coras72b04282019-01-14 17:23:11 -08001391 return;
Florin Corasc547e912020-12-08 17:50:45 -08001392 f->shr->subscribers[f->shr->n_subscribers++] = subscriber;
Florin Coras72b04282019-01-14 17:23:11 -08001393}
1394
1395void
1396svm_fifo_del_subscriber (svm_fifo_t * f, u8 subscriber)
1397{
1398 int i;
1399
Florin Corasc547e912020-12-08 17:50:45 -08001400 for (i = 0; i < f->shr->n_subscribers; i++)
Florin Coras72b04282019-01-14 17:23:11 -08001401 {
Florin Corasc547e912020-12-08 17:50:45 -08001402 if (f->shr->subscribers[i] != subscriber)
Florin Coras72b04282019-01-14 17:23:11 -08001403 continue;
Florin Corasc547e912020-12-08 17:50:45 -08001404 f->shr->subscribers[i] = f->shr->subscribers[f->shr->n_subscribers - 1];
1405 f->shr->n_subscribers--;
Florin Coras72b04282019-01-14 17:23:11 -08001406 break;
1407 }
1408}
1409
Florin Coraseaacce42019-07-02 13:07:37 -07001410u8
1411svm_fifo_is_sane (svm_fifo_t * f)
1412{
Florin Corasf22f4e52019-12-19 16:10:58 -08001413 svm_fifo_chunk_t *tmp;
Florin Coraseaacce42019-07-02 13:07:37 -07001414
Florin Corasc547e912020-12-08 17:50:45 -08001415 if (f->shr->head_chunk &&
Florin Corasaf588822020-12-09 12:51:13 -08001416 !f_chunk_includes_pos (f_head_cptr (f), f->shr->head))
Florin Corasf22f4e52019-12-19 16:10:58 -08001417 return 0;
Florin Corasc547e912020-12-08 17:50:45 -08001418 if (f->shr->tail_chunk &&
Florin Corasaf588822020-12-09 12:51:13 -08001419 !f_chunk_includes_pos (f_tail_cptr (f), f->shr->tail))
Florin Corasf22f4e52019-12-19 16:10:58 -08001420 return 0;
1421 if (f->ooo_deq)
1422 {
1423 if (rb_tree_is_init (&f->ooo_deq_lookup))
1424 {
Florin Corasc547e912020-12-08 17:50:45 -08001425 if (f_pos_lt (f->ooo_deq->start_byte,
Florin Corasaf588822020-12-09 12:51:13 -08001426 f_start_cptr (f)->start_byte) ||
1427 f_pos_gt (f->ooo_deq->start_byte, f_chunk_end (f_end_cptr (f))))
Florin Corasf22f4e52019-12-19 16:10:58 -08001428 return 0;
1429
1430 tmp = f_find_chunk_rbtree (&f->ooo_deq_lookup,
1431 f->ooo_deq->start_byte);
1432 }
1433 else
1434 tmp = svm_fifo_find_chunk (f, f->ooo_deq->start_byte);
1435 if (tmp != f->ooo_deq)
1436 return 0;
1437 }
1438 if (f->ooo_enq)
1439 {
1440 if (rb_tree_is_init (&f->ooo_enq_lookup))
1441 {
Florin Corasc547e912020-12-08 17:50:45 -08001442 if (f_pos_lt (f->ooo_enq->start_byte,
Florin Corasaf588822020-12-09 12:51:13 -08001443 f_start_cptr (f)->start_byte) ||
1444 f_pos_gt (f->ooo_enq->start_byte, f_chunk_end (f_end_cptr (f))))
Florin Corasf22f4e52019-12-19 16:10:58 -08001445 return 0;
1446
1447 tmp = f_find_chunk_rbtree (&f->ooo_enq_lookup,
1448 f->ooo_enq->start_byte);
1449 }
1450 else
1451 {
Florin Corasaf588822020-12-09 12:51:13 -08001452 tmp = svm_fifo_find_next_chunk (f, f_tail_cptr (f),
Florin Corasf22f4e52019-12-19 16:10:58 -08001453 f->ooo_enq->start_byte);
1454 }
1455 if (tmp != f->ooo_enq)
1456 return 0;
1457 }
1458
Florin Corasaf588822020-12-09 12:51:13 -08001459 if (f_start_cptr (f)->next)
Florin Coraseaacce42019-07-02 13:07:37 -07001460 {
1461 svm_fifo_chunk_t *c, *prev = 0, *tmp;
Florin Corasf22f4e52019-12-19 16:10:58 -08001462 u32 chunks_bytes = 0;
Florin Coraseaacce42019-07-02 13:07:37 -07001463
Florin Corasaf588822020-12-09 12:51:13 -08001464 c = f_start_cptr (f);
Florin Coraseaacce42019-07-02 13:07:37 -07001465 do
1466 {
1467 tmp = svm_fifo_find_chunk (f, c->start_byte);
1468 if (tmp != c)
1469 return 0;
1470 if (prev && (prev->start_byte + prev->length != c->start_byte))
1471 return 0;
Florin Corasb0208062019-12-12 12:09:29 -08001472
Florin Corasf22f4e52019-12-19 16:10:58 -08001473 if (c->enq_rb_index != RBTREE_TNIL_INDEX)
Florin Corasb0208062019-12-12 12:09:29 -08001474 {
Florin Corasf22f4e52019-12-19 16:10:58 -08001475 tmp = f_find_chunk_rbtree (&f->ooo_enq_lookup, c->start_byte);
Florin Corasb0208062019-12-12 12:09:29 -08001476 if (tmp)
1477 {
Florin Corasb0208062019-12-12 12:09:29 -08001478 if (tmp != c)
1479 return 0;
1480 }
Florin Corasf22f4e52019-12-19 16:10:58 -08001481 }
1482 if (c->deq_rb_index != RBTREE_TNIL_INDEX)
1483 {
1484 tmp = f_find_chunk_rbtree (&f->ooo_deq_lookup, c->start_byte);
Florin Corasb0208062019-12-12 12:09:29 -08001485 if (tmp)
1486 {
Florin Corasb0208062019-12-12 12:09:29 -08001487 if (tmp != c)
1488 return 0;
1489 }
Florin Corasb0208062019-12-12 12:09:29 -08001490 }
1491
Florin Corasf22f4e52019-12-19 16:10:58 -08001492 chunks_bytes += c->length;
Florin Coraseaacce42019-07-02 13:07:37 -07001493 prev = c;
Florin Corasaf588822020-12-09 12:51:13 -08001494 c = f_cptr (f, c->next);
Florin Coraseaacce42019-07-02 13:07:37 -07001495 }
Florin Corasf22f4e52019-12-19 16:10:58 -08001496 while (c);
Florin Coraseaacce42019-07-02 13:07:37 -07001497
Florin Corasc547e912020-12-08 17:50:45 -08001498 if (chunks_bytes < f->shr->tail - f->shr->head)
Florin Coraseaacce42019-07-02 13:07:37 -07001499 return 0;
1500 }
1501
1502 return 1;
1503}
1504
Florin Corasf22f4e52019-12-19 16:10:58 -08001505u32
1506svm_fifo_n_chunks (svm_fifo_t * f)
Ryujiro Shibuya8e20fe72019-10-16 06:30:02 +01001507{
Florin Corasf22f4e52019-12-19 16:10:58 -08001508 svm_fifo_chunk_t *c;
1509 int n_chunks = 0;
Ryujiro Shibuya8e20fe72019-10-16 06:30:02 +01001510
Florin Corasaf588822020-12-09 12:51:13 -08001511 c = f_start_cptr (f);
Florin Corasf22f4e52019-12-19 16:10:58 -08001512 while (c)
1513 {
1514 n_chunks++;
Florin Corasaf588822020-12-09 12:51:13 -08001515 c = f_cptr (f, c->next);
Ryujiro Shibuya8e20fe72019-10-16 06:30:02 +01001516 }
1517
Florin Corasf22f4e52019-12-19 16:10:58 -08001518 return n_chunks;
Ryujiro Shibuya8e20fe72019-10-16 06:30:02 +01001519}
1520
Florin Coras87b15ce2019-04-28 21:16:30 -07001521u8 *
1522format_ooo_segment (u8 * s, va_list * args)
1523{
Florin Corasf22f4e52019-12-19 16:10:58 -08001524 svm_fifo_t __clib_unused *f = va_arg (*args, svm_fifo_t *);
Florin Coras87b15ce2019-04-28 21:16:30 -07001525 ooo_segment_t *seg = va_arg (*args, ooo_segment_t *);
Florin Corasf22f4e52019-12-19 16:10:58 -08001526 s = format (s, "[%u, %u], len %u, next %d, prev %d", seg->start,
1527 seg->start + seg->length, seg->length, seg->next, seg->prev);
Florin Coras87b15ce2019-04-28 21:16:30 -07001528 return s;
1529}
1530
1531u8 *
1532svm_fifo_dump_trace (u8 * s, svm_fifo_t * f)
1533{
1534#if SVM_FIFO_TRACE
1535 svm_fifo_trace_elem_t *seg = 0;
1536 int i = 0;
1537
1538 if (f->trace)
1539 {
1540 vec_foreach (seg, f->trace)
1541 {
1542 s = format (s, "{%u, %u, %u}, ", seg->offset, seg->len, seg->action);
1543 i++;
1544 if (i % 5 == 0)
1545 s = format (s, "\n");
1546 }
1547 s = format (s, "\n");
1548 }
1549 return s;
1550#else
1551 return 0;
1552#endif
1553}
1554
1555u8 *
1556svm_fifo_replay (u8 * s, svm_fifo_t * f, u8 no_read, u8 verbose)
1557{
1558 int i, trace_len;
1559 u8 *data = 0;
1560 svm_fifo_trace_elem_t *trace;
1561 u32 offset;
Dave Barach11fb09e2020-08-06 12:10:09 -04001562 svm_fifo_t *placeholder_fifo;
Florin Coras87b15ce2019-04-28 21:16:30 -07001563
1564 if (!f)
1565 return s;
1566
1567#if SVM_FIFO_TRACE
1568 trace = f->trace;
1569 trace_len = vec_len (trace);
1570#else
1571 trace = 0;
1572 trace_len = 0;
1573#endif
1574
Florin Corasc547e912020-12-08 17:50:45 -08001575 placeholder_fifo = svm_fifo_alloc (f->shr->size);
1576 svm_fifo_init (f, f->shr->size);
Florin Corasaf588822020-12-09 12:51:13 -08001577 clib_memset (f_head_cptr (f)->data, 0xFF, f->shr->size);
Florin Corasc547e912020-12-08 17:50:45 -08001578 vec_validate (data, f->shr->size);
Florin Coras87b15ce2019-04-28 21:16:30 -07001579 for (i = 0; i < vec_len (data); i++)
1580 data[i] = i;
1581
1582 for (i = 0; i < trace_len; i++)
1583 {
1584 offset = trace[i].offset;
1585 if (trace[i].action == 1)
1586 {
1587 if (verbose)
1588 s = format (s, "adding [%u, %u]:", trace[i].offset,
Florin Corasf22f4e52019-12-19 16:10:58 -08001589 (trace[i].offset + trace[i].len));
Dave Barach11fb09e2020-08-06 12:10:09 -04001590 svm_fifo_enqueue_with_offset (placeholder_fifo, trace[i].offset,
Florin Coras87b15ce2019-04-28 21:16:30 -07001591 trace[i].len, &data[offset]);
1592 }
1593 else if (trace[i].action == 2)
1594 {
1595 if (verbose)
1596 s = format (s, "adding [%u, %u]:", 0, trace[i].len);
Dave Barach11fb09e2020-08-06 12:10:09 -04001597 svm_fifo_enqueue (placeholder_fifo, trace[i].len, &data[offset]);
Florin Coras87b15ce2019-04-28 21:16:30 -07001598 }
1599 else if (!no_read)
1600 {
1601 if (verbose)
1602 s = format (s, "read: %u", trace[i].len);
Dave Barach11fb09e2020-08-06 12:10:09 -04001603 svm_fifo_dequeue_drop (placeholder_fifo, trace[i].len);
Florin Coras87b15ce2019-04-28 21:16:30 -07001604 }
1605 if (verbose)
Dave Barach11fb09e2020-08-06 12:10:09 -04001606 s = format (s, "%U", format_svm_fifo, placeholder_fifo, 1);
Florin Coras87b15ce2019-04-28 21:16:30 -07001607 }
1608
Dave Barach11fb09e2020-08-06 12:10:09 -04001609 s = format (s, "result: %U", format_svm_fifo, placeholder_fifo, 1);
Florin Coras87b15ce2019-04-28 21:16:30 -07001610
1611 return s;
1612}
1613
1614u8 *
1615format_ooo_list (u8 * s, va_list * args)
1616{
1617 svm_fifo_t *f = va_arg (*args, svm_fifo_t *);
1618 u32 indent = va_arg (*args, u32);
1619 u32 ooo_segment_index = f->ooos_list_head;
1620 ooo_segment_t *seg;
1621
1622 while (ooo_segment_index != OOO_SEGMENT_INVALID_INDEX)
1623 {
1624 seg = pool_elt_at_index (f->ooo_segments, ooo_segment_index);
1625 s = format (s, "%U%U\n", format_white_space, indent, format_ooo_segment,
1626 f, seg);
1627 ooo_segment_index = seg->next;
1628 }
1629
1630 return s;
1631}
1632
1633u8 *
1634format_svm_fifo (u8 * s, va_list * args)
1635{
1636 svm_fifo_t *f = va_arg (*args, svm_fifo_t *);
1637 int verbose = va_arg (*args, int);
1638 u32 indent;
1639
1640 if (!s)
1641 return s;
1642
1643 indent = format_get_indent (s);
Florin Corasf22f4e52019-12-19 16:10:58 -08001644 s = format (s, "cursize %u nitems %u has_event %d min_alloc %u\n",
Florin Corasc547e912020-12-08 17:50:45 -08001645 svm_fifo_max_dequeue (f), f->shr->size, f->shr->has_event,
1646 f->shr->min_alloc);
Florin Coras87b15ce2019-04-28 21:16:30 -07001647 s = format (s, "%Uhead %u tail %u segment manager %u\n", format_white_space,
Florin Corasc547e912020-12-08 17:50:45 -08001648 indent, f->shr->head, f->shr->tail, f->segment_manager);
Florin Coras87b15ce2019-04-28 21:16:30 -07001649
1650 if (verbose > 1)
1651 s = format (s, "%Uvpp session %d thread %d app session %d thread %d\n",
Florin Corasc547e912020-12-08 17:50:45 -08001652 format_white_space, indent, f->shr->master_session_index,
1653 f->master_thread_index, f->shr->client_session_index,
Florin Coras87b15ce2019-04-28 21:16:30 -07001654 f->client_thread_index);
1655
1656 if (verbose)
1657 {
1658 s = format (s, "%Uooo pool %d active elts newest %u\n",
1659 format_white_space, indent, pool_elts (f->ooo_segments),
1660 f->ooos_newest);
1661 if (svm_fifo_has_ooo_data (f))
1662 s = format (s, " %U", format_ooo_list, f, indent, verbose);
1663 }
1664 return s;
1665}
1666
Florin Coras3aa7af32018-06-29 08:44:31 -07001667#endif
Dave Barach68b0fb02017-02-28 15:15:56 -05001668/*
1669 * fd.io coding-style-patch-verification: ON
1670 *
1671 * Local Variables:
1672 * eval: (c-set-style "gnu")
1673 * End:
1674 */