2 * Copyright (c) 2016-2019 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include <svm/fifo_segment.h>
19 * Fifo segment free space
21 * Queries the underlying memory manager, dlmalloc, for free space. Since this
22 * ends up walking the internal data structures, it should not be called
25 * @param fs fifo segment
26 * @return number of free bytes
29 fs_free_space (fifo_segment_t * fs)
31 struct dlmallinfo dlminfo;
33 dlminfo = mspace_mallinfo (fs->ssvm.sh->heap);
34 return dlminfo.fordblks;
38 fsh_free_bytes_sub (fifo_segment_header_t * fsh, int size)
40 clib_atomic_fetch_sub_rel (&fsh->n_free_bytes, size);
44 fsh_n_free_bytes (fifo_segment_header_t * fsh)
46 return clib_atomic_load_relax_n (&fsh->n_free_bytes);
49 static inline fifo_segment_slice_t *
50 fsh_slice_get (fifo_segment_header_t * fsh, u32 slice_index)
52 return &fsh->slices[slice_index];
56 fsh_active_fifos_update (fifo_segment_header_t * fsh, int inc)
58 clib_atomic_fetch_add_rel (&fsh->n_active_fifos, inc);
62 * Initialize fifo segment shared header
65 fifo_segment_init (fifo_segment_t * fs)
67 fifo_segment_header_t *fsh;
68 fifo_segment_slice_t *fss;
69 ssvm_shared_header_t *sh;
76 oldheap = ssvm_push_heap (sh);
79 * Manually align the fifo segment header to sizeof(uword) = 8 bytes.
80 * Long story made short: the "process-private" fifo segment
81 * is allocated from the main heap, not mmapped. dlmalloc
82 * only guarantees 4-byte alignment, and on aarch64
83 * the fsh can end up 4-byte but not 8-byte aligned.
84 * That eventually causes the atomic op in fifo_segment_update_free_bytes
87 fsh = clib_mem_alloc_aligned (sizeof (*fsh), sizeof (uword));
88 clib_memset (fsh, 0, sizeof (*fsh));
89 fs->h = sh->opaque[0] = fsh;
90 fs->n_slices = clib_max (fs->n_slices, 1);
92 fsh->ssvm_sh = fs->ssvm.sh;
93 fsh->n_slices = fs->n_slices;
94 max_fifo = clib_min ((fs_free_space (fs) - 4096) / 2,
95 FIFO_SEGMENT_MAX_FIFO_SIZE);
96 fsh->max_log2_chunk_size = max_log2 (max_fifo);
98 fsh->slices = clib_mem_alloc (sizeof (*fss) * fs->n_slices);
99 clib_memset (fsh->slices, 0, sizeof (*fss) * fs->n_slices);
100 max_chunk_sz = fsh->max_log2_chunk_size - FIFO_SEGMENT_MIN_LOG2_FIFO_SIZE;
102 for (i = 0; i < fs->n_slices; i++)
104 fss = fsh_slice_get (fsh, i);
105 vec_validate_init_empty (fss->free_chunks, max_chunk_sz, 0);
108 ssvm_pop_heap (oldheap);
110 fsh->n_free_bytes = fs_free_space (fs);
116 * Create a fifo segment and initialize as master
119 fifo_segment_create (fifo_segment_main_t * sm, fifo_segment_create_args_t * a)
125 /* Allocate a fresh segment */
126 pool_get_zero (sm->segments, fs);
128 baseva = a->segment_type == SSVM_SEGMENT_PRIVATE ? ~0ULL : sm->next_baseva;
129 fs->ssvm.ssvm_size = a->segment_size;
130 fs->ssvm.i_am_master = 1;
131 fs->ssvm.my_pid = getpid ();
132 fs->ssvm.name = format (0, "%s%c", a->segment_name, 0);
133 fs->ssvm.requested_va = baseva;
135 if ((rv = ssvm_master_init (&fs->ssvm, a->segment_type)))
137 pool_put (sm->segments, fs);
141 /* Note: requested_va updated due to seg base addr randomization */
142 sm->next_baseva = fs->ssvm.sh->ssvm_va + fs->ssvm.ssvm_size;
144 fifo_segment_init (fs);
145 vec_add1 (a->new_segment_indices, fs - sm->segments);
150 * Attach as slave to a fifo segment
153 fifo_segment_attach (fifo_segment_main_t * sm, fifo_segment_create_args_t * a)
158 pool_get_zero (sm->segments, fs);
160 fs->ssvm.ssvm_size = a->segment_size;
161 fs->ssvm.my_pid = getpid ();
162 fs->ssvm.name = format (0, "%s%c", a->segment_name, 0);
163 fs->ssvm.requested_va = sm->next_baseva;
164 if (a->segment_type == SSVM_SEGMENT_MEMFD)
165 fs->ssvm.fd = a->memfd_fd;
167 fs->ssvm.attach_timeout = sm->timeout_in_seconds;
169 if ((rv = ssvm_slave_init (&fs->ssvm, a->segment_type)))
171 _vec_len (fs) = vec_len (fs) - 1;
175 /* Fish the segment header */
176 fs->h = fs->ssvm.sh->opaque[0];
178 vec_add1 (a->new_segment_indices, fs - sm->segments);
183 fifo_segment_delete (fifo_segment_main_t * sm, fifo_segment_t * s)
185 ssvm_delete (&s->ssvm);
186 clib_memset (s, 0xfe, sizeof (*s));
187 pool_put (sm->segments, s);
191 fifo_segment_index (fifo_segment_main_t * sm, fifo_segment_t * s)
193 return s - sm->segments;
197 fifo_segment_get_segment (fifo_segment_main_t * sm, u32 segment_index)
199 return pool_elt_at_index (sm->segments, segment_index);
203 fifo_segment_info (fifo_segment_t * seg, char **address, size_t * size)
205 *address = (char *) seg->ssvm.sh->ssvm_va;
206 *size = seg->ssvm.ssvm_size;
210 fifo_segment_main_init (fifo_segment_main_t * sm, u64 baseva,
211 u32 timeout_in_seconds)
213 sm->next_baseva = baseva;
214 sm->timeout_in_seconds = timeout_in_seconds;
218 fs_freelist_for_size (u32 size)
220 return max_log2 (size) - FIFO_SEGMENT_MIN_LOG2_FIFO_SIZE;
224 fs_freelist_index_to_size (u32 fl_index)
226 return 1 << (fl_index + FIFO_SEGMENT_MIN_LOG2_FIFO_SIZE);
230 fs_chunk_size_is_valid (fifo_segment_header_t * fsh, u32 size)
233 * 4K minimum. It's not likely that anything good will happen
234 * with a smaller FIFO.
236 return size >= FIFO_SEGMENT_MIN_FIFO_SIZE
237 && size <= (1 << fsh->max_log2_chunk_size);
241 fs_try_alloc_fifo_freelist (fifo_segment_slice_t * fss,
242 u32 fl_index, u32 data_bytes)
248 c = fss->free_chunks[fl_index];
253 fss->free_fifos = f->next;
254 fss->free_chunks[fl_index] = c->next;
257 c->length = data_bytes;
258 memset (f, 0, sizeof (*f));
262 fss->n_fl_chunk_bytes -= fs_freelist_index_to_size (fl_index);
267 fs_try_alloc_fifo_freelist_multi_chunk (fifo_segment_header_t * fsh,
268 fifo_segment_slice_t * fss,
271 svm_fifo_chunk_t *c, *first = 0, *last = 0;
272 u32 fl_index, fl_size, n_alloc = 0;
278 void *oldheap = ssvm_push_heap (fsh->ssvm_sh);
279 f = clib_mem_alloc_aligned (sizeof (*f), CLIB_CACHE_LINE_BYTES);
280 ssvm_pop_heap (oldheap);
283 memset (f, 0, sizeof (*f));
284 fsh_free_bytes_sub (fsh, sizeof (*f));
288 fss->free_fifos = f->next;
291 fl_index = fs_freelist_for_size (data_bytes) - 1;
292 fl_size = fs_freelist_index_to_size (fl_index);
296 c = fss->free_chunks[fl_index];
299 fss->free_chunks[fl_index] = c->next;
305 c->length = clib_min (fl_size, data_bytes);
306 data_bytes -= c->length;
310 ASSERT (fl_index > 0);
312 fl_size = fl_size >> 1;
315 f->start_chunk = first;
318 fss->n_fl_chunk_bytes -= n_alloc;
323 fs_try_alloc_fifo_batch (fifo_segment_header_t * fsh,
324 fifo_segment_slice_t * fss,
325 u32 fl_index, u32 batch_size)
327 u32 size, hdrs, rounded_data_size;
334 rounded_data_size = fs_freelist_index_to_size (fl_index);
335 hdrs = sizeof (*f) + sizeof (*c);
336 size = (hdrs + rounded_data_size) * batch_size;
338 oldheap = ssvm_push_heap (fsh->ssvm_sh);
339 fmem = clib_mem_alloc_aligned_at_offset (size, CLIB_CACHE_LINE_BYTES,
340 0 /* align_offset */ ,
341 0 /* os_out_of_memory */ );
342 ssvm_pop_heap (oldheap);
348 /* Carve fifo + chunk space */
349 for (i = 0; i < batch_size; i++)
351 f = (svm_fifo_t *) fmem;
352 memset (f, 0, sizeof (*f));
353 f->next = fss->free_fifos;
355 c = (svm_fifo_chunk_t *) (fmem + sizeof (*f));
357 c->length = rounded_data_size;
358 c->next = fss->free_chunks[fl_index];
359 fss->free_chunks[fl_index] = c;
360 fmem += hdrs + rounded_data_size;
363 fss->n_fl_chunk_bytes += batch_size * rounded_data_size;
364 fsh_free_bytes_sub (fsh, size);
370 * Try to allocate new fifo
372 * Tries the following steps in order:
373 * - grab fifo and chunk from freelists
374 * - batch fifo and chunk allocation
375 * - single fifo allocation
376 * - grab multiple fifo chunks from freelists
379 fs_try_alloc_fifo (fifo_segment_header_t * fsh, fifo_segment_slice_t * fss,
382 u32 fifo_sz, fl_index;
386 fl_index = fs_freelist_for_size (data_bytes);
387 fifo_sz = sizeof (svm_fifo_t) + sizeof (svm_fifo_chunk_t);
388 fifo_sz += 1 << max_log2 (data_bytes);
390 if (fss->free_fifos && fss->free_chunks[fl_index])
392 f = fs_try_alloc_fifo_freelist (fss, fl_index, data_bytes);
396 n_free_bytes = fsh_n_free_bytes (fsh);
397 if (fifo_sz * FIFO_SEGMENT_ALLOC_BATCH_SIZE < n_free_bytes)
399 if (fs_try_alloc_fifo_batch (fsh, fss, fl_index,
400 FIFO_SEGMENT_ALLOC_BATCH_SIZE))
403 f = fs_try_alloc_fifo_freelist (fss, fl_index, data_bytes);
406 if (fifo_sz <= n_free_bytes)
408 void *oldheap = ssvm_push_heap (fsh->ssvm_sh);
409 f = svm_fifo_create (data_bytes);
410 ssvm_pop_heap (oldheap);
413 fsh_free_bytes_sub (fsh, fifo_sz);
417 if (data_bytes <= fss->n_fl_chunk_bytes)
418 f = fs_try_alloc_fifo_freelist_multi_chunk (fsh, fss, data_bytes);
426 * Allocate fifo in fifo segment
429 fifo_segment_alloc_fifo_w_slice (fifo_segment_t * fs, u32 slice_index,
430 u32 data_bytes, fifo_segment_ftype_t ftype)
432 fifo_segment_header_t *fsh = fs->h;
433 fifo_segment_slice_t *fss;
436 ASSERT (slice_index < fs->n_slices);
438 fss = fsh_slice_get (fsh, slice_index);
439 f = fs_try_alloc_fifo (fsh, fss, data_bytes);
443 f->slice_index = slice_index;
445 /* (re)initialize the fifo, as in svm_fifo_create */
446 svm_fifo_init (f, data_bytes);
448 /* Initialize chunks and rbtree for multi-chunk fifos */
449 if (f->start_chunk->next != f->start_chunk)
451 void *oldheap = ssvm_push_heap (fsh->ssvm_sh);
452 svm_fifo_init_chunks (f);
453 ssvm_pop_heap (oldheap);
456 /* If rx fifo type add to active fifos list. When cleaning up segment,
457 * we need a list of active sessions that should be disconnected. Since
458 * both rx and tx fifos keep pointers to the session, it's enough to track
460 if (ftype == FIFO_SEGMENT_RX_FIFO)
464 fss->fifos->prev = f;
465 f->next = fss->fifos;
468 f->flags |= SVM_FIFO_F_LL_TRACKED;
470 fsh_active_fifos_update (fsh, 1);
477 * Free fifo allocated in fifo segment
480 fifo_segment_free_fifo (fifo_segment_t * fs, svm_fifo_t * f)
482 fifo_segment_header_t *fsh = fs->h;
483 svm_fifo_chunk_t *cur, *next;
484 fifo_segment_slice_t *fss;
488 ASSERT (f->refcnt > 0);
493 fss = fsh_slice_get (fsh, f->slice_index);
495 /* Remove from active list. Only rx fifos are tracked */
496 if (f->flags & SVM_FIFO_F_LL_TRACKED)
499 f->prev->next = f->next;
501 fss->fifos = f->next;
503 f->next->prev = f->prev;
504 f->flags &= ~SVM_FIFO_F_LL_TRACKED;
507 /* Add to free list */
508 f->next = fss->free_fifos;
512 /* Free fifo chunks */
513 cur = f->start_chunk;
517 fl_index = fs_freelist_for_size (cur->length);
518 ASSERT (fl_index < vec_len (fss->free_chunks));
519 cur->next = fss->free_chunks[fl_index];
520 fss->free_chunks[fl_index] = cur;
521 fss->n_fl_chunk_bytes += fs_freelist_index_to_size (fl_index);
524 while (cur != f->start_chunk);
526 f->start_chunk = f->end_chunk = f->new_chunks = 0;
527 f->head_chunk = f->tail_chunk = f->ooo_enq = f->ooo_deq = 0;
529 oldheap = ssvm_push_heap (fsh->ssvm_sh);
530 svm_fifo_free_chunk_lookup (f);
531 ssvm_pop_heap (oldheap);
533 /* not allocated on segment heap */
534 svm_fifo_free_ooo_data (f);
538 f->master_session_index = ~0;
539 f->master_thread_index = ~0;
542 fsh_active_fifos_update (fsh, -1);
546 fifo_segment_prealloc_fifo_hdrs (fifo_segment_t * fs, u32 slice_index,
549 fifo_segment_header_t *fsh = fs->h;
550 fifo_segment_slice_t *fss;
557 fss = fsh_slice_get (fsh, slice_index);
558 size = (sizeof (*f)) * batch_size;
560 oldheap = ssvm_push_heap (fsh->ssvm_sh);
561 fmem = clib_mem_alloc_aligned_at_offset (size, CLIB_CACHE_LINE_BYTES,
562 0 /* align_offset */ ,
563 0 /* os_out_of_memory */ );
564 ssvm_pop_heap (oldheap);
570 /* Carve fifo + chunk space */
571 for (i = 0; i < batch_size; i++)
573 f = (svm_fifo_t *) fmem;
574 memset (f, 0, sizeof (*f));
575 f->next = fss->free_fifos;
580 fsh_free_bytes_sub (fsh, size);
586 fifo_segment_prealloc_fifo_chunks (fifo_segment_t * fs, u32 slice_index,
587 u32 chunk_size, u32 batch_size)
589 u32 size, rounded_data_size, fl_index;
590 fifo_segment_header_t *fsh = fs->h;
591 fifo_segment_slice_t *fss;
597 if (!fs_chunk_size_is_valid (fsh, chunk_size))
599 clib_warning ("chunk size out of range %d", chunk_size);
603 fl_index = fs_freelist_for_size (chunk_size);
604 rounded_data_size = fs_freelist_index_to_size (fl_index);
605 size = (sizeof (*c) + rounded_data_size) * batch_size;
607 oldheap = ssvm_push_heap (fsh->ssvm_sh);
608 cmem = clib_mem_alloc_aligned_at_offset (size, CLIB_CACHE_LINE_BYTES,
609 0 /* align_offset */ ,
610 0 /* os_out_of_memory */ );
611 ssvm_pop_heap (oldheap);
617 fss = fsh_slice_get (fsh, slice_index);
619 /* Carve fifo + chunk space */
620 for (i = 0; i < batch_size; i++)
622 c = (svm_fifo_chunk_t *) cmem;
624 c->length = rounded_data_size;
625 c->next = fss->free_chunks[fl_index];
626 fss->free_chunks[fl_index] = c;
627 cmem += sizeof (*c) + rounded_data_size;
630 fss->n_fl_chunk_bytes += batch_size * rounded_data_size;
631 fsh_free_bytes_sub (fsh, size);
637 * Pre-allocates fifo pairs in fifo segment
640 fifo_segment_preallocate_fifo_pairs (fifo_segment_t * fs,
641 u32 rx_fifo_size, u32 tx_fifo_size,
644 u32 rx_rounded_data_size, tx_rounded_data_size, pair_size, pairs_to_alloc;
645 fifo_segment_header_t *fsh = fs->h;
646 int rx_fl_index, tx_fl_index, i;
647 fifo_segment_slice_t *fss;
648 u32 hdrs, pairs_per_slice;
649 uword space_available;
651 /* Parameter check */
652 if (rx_fifo_size == 0 || tx_fifo_size == 0 || *n_fifo_pairs == 0)
655 if (!fs_chunk_size_is_valid (fsh, rx_fifo_size))
657 clib_warning ("rx fifo_size out of range %d", rx_fifo_size);
661 if (!fs_chunk_size_is_valid (fsh, tx_fifo_size))
663 clib_warning ("tx fifo_size out of range %d", tx_fifo_size);
667 rx_rounded_data_size = (1 << (max_log2 (rx_fifo_size)));
668 rx_fl_index = fs_freelist_for_size (rx_fifo_size);
669 tx_rounded_data_size = (1 << (max_log2 (tx_fifo_size)));
670 tx_fl_index = fs_freelist_for_size (tx_fifo_size);
672 hdrs = sizeof (svm_fifo_t) + sizeof (svm_fifo_chunk_t);
674 /* Calculate space requirements */
675 pair_size = 2 * hdrs + rx_rounded_data_size + tx_rounded_data_size;
676 space_available = fs_free_space (fs);
677 pairs_to_alloc = space_available / pair_size;
678 pairs_to_alloc = clib_min (pairs_to_alloc, *n_fifo_pairs);
679 pairs_per_slice = pairs_to_alloc / fs->n_slices;
681 if (!pairs_per_slice)
684 for (i = 0; i < fs->n_slices; i++)
686 fss = fsh_slice_get (fsh, i);
687 if (fs_try_alloc_fifo_batch (fsh, fss, rx_fl_index, pairs_to_alloc))
688 clib_warning ("rx prealloc failed: pairs %u", pairs_to_alloc);
689 if (fs_try_alloc_fifo_batch (fsh, fss, tx_fl_index, pairs_to_alloc))
690 clib_warning ("tx prealloc failed: pairs %u", pairs_to_alloc);
693 /* Account for the pairs allocated */
694 *n_fifo_pairs -= pairs_per_slice * fs->n_slices;
698 fifo_segment_grow_fifo (fifo_segment_t * fs, svm_fifo_t * f, u32 chunk_size)
700 fifo_segment_header_t *fsh = fs->h;
701 fifo_segment_slice_t *fss;
706 fl_index = fs_freelist_for_size (chunk_size);
707 fss = fsh_slice_get (fsh, f->slice_index);
709 oldheap = ssvm_push_heap (fsh->ssvm_sh);
711 c = fss->free_chunks[fl_index];
715 c = svm_fifo_chunk_alloc (chunk_size);
718 ssvm_pop_heap (oldheap);
721 fsh_free_bytes_sub (fsh, chunk_size + sizeof (*c));
725 fss->free_chunks[fl_index] = c->next;
727 fss->n_fl_chunk_bytes -= fs_freelist_index_to_size (fl_index);
730 svm_fifo_add_chunk (f, c);
732 ssvm_pop_heap (oldheap);
737 fifo_segment_collect_fifo_chunks (fifo_segment_t * fs, svm_fifo_t * f)
739 fifo_segment_header_t *fsh = fs->h;
740 svm_fifo_chunk_t *cur, *next;
741 fifo_segment_slice_t *fss;
745 oldheap = ssvm_push_heap (fsh->ssvm_sh);
746 cur = svm_fifo_collect_chunks (f);
748 fss = fsh_slice_get (fsh, f->slice_index);
753 fl_index = fs_freelist_for_size (cur->length);
754 cur->next = fss->free_chunks[fl_index];
755 fss->free_chunks[fl_index] = cur;
759 ssvm_pop_heap (oldheap);
765 * Get number of active fifos
768 fifo_segment_num_fifos (fifo_segment_t * fs)
770 return clib_atomic_load_relax_n (&fs->h->n_active_fifos);
774 fs_slice_num_free_fifos (fifo_segment_slice_t * fss)
792 fifo_segment_num_free_fifos (fifo_segment_t * fs)
794 fifo_segment_header_t *fsh = fs->h;
795 fifo_segment_slice_t *fss;
799 for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
801 fss = fsh_slice_get (fsh, slice_index);
802 count += fs_slice_num_free_fifos (fss);
808 fs_slice_num_free_chunks (fifo_segment_slice_t * fss, u32 size)
810 u32 count = 0, rounded_size, fl_index;
814 /* Count all free chunks? */
817 for (i = 0; i < vec_len (fss->free_chunks); i++)
819 c = fss->free_chunks[i];
832 rounded_size = (1 << (max_log2 (size)));
833 fl_index = fs_freelist_for_size (rounded_size);
835 if (fl_index >= vec_len (fss->free_chunks))
838 c = fss->free_chunks[fl_index];
851 fifo_segment_num_free_chunks (fifo_segment_t * fs, u32 size)
853 fifo_segment_header_t *fsh = fs->h;
854 fifo_segment_slice_t *fss;
858 for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
860 fss = fsh_slice_get (fsh, slice_index);
861 count += fs_slice_num_free_chunks (fss, size);
867 fifo_segment_update_free_bytes (fifo_segment_t * fs)
869 fifo_segment_header_t *fsh = fs->h;
870 clib_atomic_store_rel_n (&fsh->n_free_bytes, fs_free_space (fs));
874 fifo_segment_free_bytes (fifo_segment_t * fs)
876 return fsh_n_free_bytes (fs->h);
880 fifo_segment_fl_chunk_bytes (fifo_segment_t * fs)
882 fifo_segment_header_t *fsh = fs->h;
883 fifo_segment_slice_t *fss;
887 for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
889 fss = fsh_slice_get (fsh, slice_index);
890 n_bytes += fss->n_fl_chunk_bytes;
897 fifo_segment_has_fifos (fifo_segment_t * fs)
899 fifo_segment_header_t *fsh = fs->h;
900 fifo_segment_slice_t *fss;
903 for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
905 fss = fsh_slice_get (fsh, slice_index);
913 fifo_segment_get_slice_fifo_list (fifo_segment_t * fs, u32 slice_index)
915 fifo_segment_header_t *fsh = fs->h;
916 fifo_segment_slice_t *fss;
918 fss = fsh_slice_get (fsh, slice_index);
923 format_fifo_segment_type (u8 * s, va_list * args)
926 sp = va_arg (*args, fifo_segment_t *);
927 ssvm_segment_type_t st = ssvm_type (&sp->ssvm);
929 if (st == SSVM_SEGMENT_PRIVATE)
930 s = format (s, "%s", "private-heap");
931 else if (st == SSVM_SEGMENT_MEMFD)
932 s = format (s, "%s", "memfd");
933 else if (st == SSVM_SEGMENT_SHM)
934 s = format (s, "%s", "shm");
936 s = format (s, "%s", "unknown");
941 * Segment format function
944 format_fifo_segment (u8 * s, va_list * args)
946 u32 count, indent, active_fifos, free_fifos, fifo_hdr = 0;
947 fifo_segment_t *fs = va_arg (*args, fifo_segment_t *);
948 int verbose __attribute__ ((unused)) = va_arg (*args, int);
949 uword est_chunk_bytes, est_free_seg_bytes, free_chunks;
950 uword chunk_bytes = 0, free_seg_bytes, chunk_size;
951 fifo_segment_header_t *fsh;
952 fifo_segment_slice_t *fss;
959 indent = format_get_indent (s) + 2;
960 #if USE_DLMALLOC == 0
961 s = format (s, "%U segment heap: %U\n", format_white_space, indent,
962 format_mheap, fsh->ssvm_sh->heap, verbose);
963 s = format (s, "%U segment has %u active fifos\n",
964 format_white_space, indent, fifo_segment_num_fifos (fsh));
969 s = format (s, "%-15s%15s%15s%15s%15s%15s", "Name", "Type",
970 "HeapSize (M)", "ActiveFifos", "FreeFifos", "Address");
974 fifo_segment_info (fs, &address, &size);
975 active_fifos = fifo_segment_num_fifos (fs);
976 free_fifos = fifo_segment_num_free_fifos (fs);
978 s = format (s, "%-15v%15U%15llu%15u%15u%15llx", ssvm_name (&fs->ssvm),
979 format_fifo_segment_type, fs, size >> 20ULL, active_fifos,
980 free_fifos, address);
987 free_chunks = fifo_segment_num_free_chunks (fs, ~0);
989 s = format (s, "\n\n%UFree chunks by size:\n", format_white_space,
992 s = format (s, "\n");
994 for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
996 fss = fsh_slice_get (fsh, slice_index);
997 for (i = 0; i < vec_len (fss->free_chunks); i++)
999 c = fss->free_chunks[i];
1009 chunk_size = fs_freelist_index_to_size (i);
1010 s = format (s, "%U%-5u kB: %u\n", format_white_space, indent + 2,
1011 chunk_size >> 10, count);
1013 chunk_bytes += count * chunk_size;
1017 fifo_hdr = free_fifos * sizeof (svm_fifo_t);
1018 est_chunk_bytes = fifo_segment_fl_chunk_bytes (fs);
1019 est_free_seg_bytes = fifo_segment_free_bytes (fs);
1020 fifo_segment_update_free_bytes (fs);
1021 free_seg_bytes = fifo_segment_free_bytes (fs);
1023 s = format (s, "\n%Useg free bytes: %U (%lu) estimated: %U (%lu)\n",
1024 format_white_space, indent + 2, format_memory_size,
1025 free_seg_bytes, free_seg_bytes, format_memory_size,
1026 est_free_seg_bytes, est_free_seg_bytes);
1027 s = format (s, "%Uchunk free bytes: %U (%lu) estimated: %U (%lu)\n",
1028 format_white_space, indent + 2, format_memory_size, chunk_bytes,
1029 chunk_bytes, format_memory_size, est_chunk_bytes,
1031 s = format (s, "%Ufifo hdr free bytes: %U (%u)\n", format_white_space,
1032 indent + 2, format_memory_size, fifo_hdr, fifo_hdr);
1033 s = format (s, "\n");
1039 * fd.io coding-style-patch-verification: ON
1042 * eval: (c-set-style "gnu")