FD.io VPP  v19.08-27-gf4dcae4
Vector Packet Processing
fifo_segment.c
Go to the documentation of this file.
1 /*
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:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 
16 #include <svm/fifo_segment.h>
17 
18 /**
19  * Fifo segment free space
20  *
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
23  * indiscriminately.
24  *
25  * @param fs fifo segment
26  * @return number of free bytes
27  */
28 static u32
30 {
31  struct dlmallinfo dlminfo;
32 
33  dlminfo = mspace_mallinfo (fs->ssvm.sh->heap);
34  return dlminfo.fordblks;
35 }
36 
37 /**
38  * Initialize fifo segment shared header
39  */
40 int
42 {
45  void *oldheap;
46 
47  sh = fs->ssvm.sh;
48  oldheap = ssvm_push_heap (sh);
49 
50  fsh = clib_mem_alloc (sizeof (*fsh));
51  clib_memset (fsh, 0, sizeof (*fsh));
52  fs->h = sh->opaque[0] = fsh;
53 
54  ssvm_pop_heap (oldheap);
55 
56  fsh->n_free_bytes = fs_free_space (fs);
57  sh->ready = 1;
58  return (0);
59 }
60 
61 /**
62  * Create a fifo segment and initialize as master
63  */
64 int
66 {
67  fifo_segment_t *fs;
68  uword baseva;
69  int rv;
70 
71  /* Allocate a fresh segment */
72  pool_get_zero (sm->segments, fs);
73 
74  baseva = a->segment_type == SSVM_SEGMENT_PRIVATE ? ~0ULL : sm->next_baseva;
75  fs->ssvm.ssvm_size = a->segment_size;
76  fs->ssvm.i_am_master = 1;
77  fs->ssvm.my_pid = getpid ();
78  fs->ssvm.name = format (0, "%s%c", a->segment_name, 0);
79  fs->ssvm.requested_va = baseva;
80 
81  if ((rv = ssvm_master_init (&fs->ssvm, a->segment_type)))
82  {
83  pool_put (sm->segments, fs);
84  return (rv);
85  }
86 
87  /* Note: requested_va updated due to seg base addr randomization */
88  sm->next_baseva = fs->ssvm.sh->ssvm_va + fs->ssvm.ssvm_size;
89 
90  fifo_segment_init (fs);
91  vec_add1 (a->new_segment_indices, fs - sm->segments);
92  return (0);
93 }
94 
95 /**
96  * Attach as slave to a fifo segment
97  */
98 int
100 {
101  fifo_segment_t *s;
102  int rv;
103 
104  pool_get_zero (sm->segments, s);
105 
106  s->ssvm.ssvm_size = a->segment_size;
107  s->ssvm.my_pid = getpid ();
108  s->ssvm.name = format (0, "%s%c", a->segment_name, 0);
109  s->ssvm.requested_va = sm->next_baseva;
111  s->ssvm.fd = a->memfd_fd;
112  else
114 
115  if ((rv = ssvm_slave_init (&s->ssvm, a->segment_type)))
116  {
117  _vec_len (s) = vec_len (s) - 1;
118  return (rv);
119  }
120 
121  /* Fish the segment header */
122  s->h = s->ssvm.sh->opaque[0];
123 
124  vec_add1 (a->new_segment_indices, s - sm->segments);
125  return (0);
126 }
127 
128 void
130 {
131  ssvm_delete (&s->ssvm);
132  clib_memset (s, 0xfe, sizeof (*s));
133  pool_put (sm->segments, s);
134 }
135 
136 u32
138 {
139  return s - sm->segments;
140 }
141 
142 void *
144 {
145  return seg->ssvm.sh->heap;
146 }
147 
150 {
151  return pool_elt_at_index (sm->segments, segment_index);
152 }
153 
154 void
155 fifo_segment_info (fifo_segment_t * seg, char **address, size_t * size)
156 {
157  *address = (char *) seg->ssvm.sh->ssvm_va;
158  *size = seg->ssvm.ssvm_size;
159 }
160 
161 void
163  u32 timeout_in_seconds)
164 {
165  sm->next_baseva = baseva;
166  sm->timeout_in_seconds = timeout_in_seconds;
167 }
168 
169 static inline u32
171 {
172  return max_log2 (size) - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE);
173 }
174 
175 static inline u32
177 {
178  return 1 << (fl_index + max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE));
179 }
180 
181 static inline int
183 {
184  /*
185  * 4K minimum. It's not likely that anything good will happen
186  * with a smaller FIFO.
187  */
188  return size >= FIFO_SEGMENT_MIN_FIFO_SIZE
189  && size <= FIFO_SEGMENT_MAX_FIFO_SIZE;
190 }
191 
192 static svm_fifo_t *
193 fs_try_alloc_fifo_freelist (fifo_segment_t * fs, u32 fl_index, u32 data_bytes)
194 {
195  fifo_segment_header_t *fsh = fs->h;
197  svm_fifo_t *f;
198 
199  f = fsh->free_fifos;
200  c = fsh->free_chunks[fl_index];
201 
202  if (!f || !c)
203  return 0;
204 
205  fsh->free_fifos = f->next;
206  fsh->free_chunks[fl_index] = c->next;
207  c->next = c;
208  c->start_byte = 0;
209  c->length = data_bytes;
210  memset (f, 0, sizeof (*f));
211  f->start_chunk = c;
212  f->end_chunk = c;
213 
214  fsh->n_fl_chunk_bytes -= fs_freelist_index_to_size (fl_index);
215  return f;
216 }
217 
218 static svm_fifo_t *
220 {
221  svm_fifo_chunk_t *c, *first = 0, *last = 0;
222  fifo_segment_header_t *fsh = fs->h;
223  u32 fl_index, fl_size, n_alloc = 0;
224  svm_fifo_t *f;
225 
226  f = fsh->free_fifos;
227  if (!f)
228  {
229  void *oldheap = ssvm_push_heap (fs->ssvm.sh);
231  ssvm_pop_heap (oldheap);
232  if (!f)
233  return 0;
234  memset (f, 0, sizeof (*f));
235  }
236 
237  fl_index = fs_freelist_for_size (data_bytes) - 1;
238  vec_validate_init_empty (fsh->free_chunks, fl_index, 0);
239  fl_size = fs_freelist_index_to_size (fl_index);
240 
241  while (data_bytes)
242  {
243  c = fsh->free_chunks[fl_index];
244  if (c)
245  {
246  fsh->free_chunks[fl_index] = c->next;
247  if (!last)
248  last = c;
249  c->next = first;
250  first = c;
251  n_alloc += fl_size;
252  c->length = clib_min (fl_size, data_bytes);
253  data_bytes -= c->length;
254  }
255  else
256  {
257  ASSERT (fl_index > 0);
258  fl_index -= 1;
259  fl_size = fl_size >> 1;
260  }
261  }
262  f->start_chunk = first;
263  f->end_chunk = last;
264  last->next = first;
265  fsh->n_fl_chunk_bytes -= n_alloc;
266  return f;
267 }
268 
269 static int
270 fs_try_alloc_fifo_batch (fifo_segment_t * fs, u32 fl_index, u32 batch_size)
271 {
272  fifo_segment_header_t *fsh = fs->h;
273  u32 size, hdrs, rounded_data_size;
275  svm_fifo_t *f;
276  void *oldheap;
277  u8 *fmem;
278  int i;
279 
280  vec_validate_init_empty (fsh->free_chunks, fl_index, 0);
281  rounded_data_size = fs_freelist_index_to_size (fl_index);
282  hdrs = sizeof (*f) + sizeof (*c);
283  size = (hdrs + rounded_data_size) * batch_size;
284 
285  oldheap = ssvm_push_heap (fs->ssvm.sh);
287  0 /* align_offset */ ,
288  0 /* os_out_of_memory */ );
289  ssvm_pop_heap (oldheap);
290 
291  /* Out of space.. */
292  if (fmem == 0)
293  return -1;
294 
295  /* Carve fifo + chunk space */
296  for (i = 0; i < batch_size; i++)
297  {
298  f = (svm_fifo_t *) fmem;
299  memset (f, 0, sizeof (*f));
300  f->next = fsh->free_fifos;
301  fsh->free_fifos = f;
302  c = (svm_fifo_chunk_t *) (fmem + sizeof (*f));
303  c->start_byte = 0;
304  c->length = rounded_data_size;
305  c->next = fsh->free_chunks[fl_index];
306  fsh->free_chunks[fl_index] = c;
307  fmem += hdrs + rounded_data_size;
308  }
309 
310  fsh->n_fl_chunk_bytes += batch_size * rounded_data_size;
311  fsh->n_free_bytes -= size;
312 
313  return 0;
314 }
315 
316 /**
317  * Try to allocate new fifo
318  *
319  * Tries the following steps in order:
320  * - grab fifo and chunk from freelists
321  * - batch fifo and chunk allocation
322  * - single fifo allocation
323  * - grab multiple fifo chunks from freelists
324  */
325 static svm_fifo_t *
327 {
328  fifo_segment_header_t *fsh = fs->h;
329  u32 fifo_sz, fl_index;
330  svm_fifo_t *f = 0;
331 
332  fl_index = fs_freelist_for_size (data_bytes);
333  vec_validate_init_empty (fsh->free_chunks, fl_index, 0);
334  fifo_sz = sizeof (svm_fifo_t) + sizeof (svm_fifo_chunk_t);
335  fifo_sz += 1 << max_log2 (data_bytes);
336 
337  if (fsh->free_fifos && fsh->free_chunks[fl_index])
338  {
339  f = fs_try_alloc_fifo_freelist (fs, fl_index, data_bytes);
340  if (f)
341  goto done;
342  }
343  if (fifo_sz * FIFO_SEGMENT_ALLOC_BATCH_SIZE < fsh->n_free_bytes)
344  {
345  if (fs_try_alloc_fifo_batch (fs, fl_index,
347  goto done;
348 
349  f = fs_try_alloc_fifo_freelist (fs, fl_index, data_bytes);
350  goto done;
351  }
352  if (fifo_sz <= fsh->n_free_bytes)
353  {
354  void *oldheap = ssvm_push_heap (fs->ssvm.sh);
355  f = svm_fifo_create (data_bytes);
356  ssvm_pop_heap (oldheap);
357  if (f)
358  {
359  fsh->n_free_bytes -= fifo_sz;
360  goto done;
361  }
362  }
363  if (data_bytes <= fsh->n_fl_chunk_bytes)
364  f = fs_try_alloc_fifo_freelist_multi_chunk (fs, data_bytes);
365 
366 done:
367 
368  return f;
369 }
370 
371 /**
372  * Allocate fifo in fifo segment
373  */
374 svm_fifo_t *
376  fifo_segment_ftype_t ftype)
377 {
379  svm_fifo_t *f = 0;
380 
381  if (!fs_chunk_size_is_valid (data_bytes))
382  {
383  clib_warning ("fifo size out of range %d", data_bytes);
384  return 0;
385  }
386 
387  fsh = fs->h;
389 
390  f = fs_try_alloc_fifo (fs, data_bytes);
391  if (!f)
392  goto done;
393 
394  /* (re)initialize the fifo, as in svm_fifo_create */
395  svm_fifo_init (f, data_bytes);
396 
397  /* Initialize chunks and rbtree for multi-chunk fifos */
398  if (f->start_chunk->next != f->start_chunk)
399  {
400  void *oldheap = ssvm_push_heap (fs->ssvm.sh);
402  ssvm_pop_heap (oldheap);
403  }
404 
405  /* If rx fifo type add to active fifos list. When cleaning up segment,
406  * we need a list of active sessions that should be disconnected. Since
407  * both rx and tx fifos keep pointers to the session, it's enough to track
408  * only one. */
409  if (ftype == FIFO_SEGMENT_RX_FIFO)
410  {
411  if (fsh->fifos)
412  {
413  fsh->fifos->prev = f;
414  f->next = fsh->fifos;
415  }
416  fsh->fifos = f;
417  f->flags |= SVM_FIFO_F_LL_TRACKED;
418  }
419  fsh->n_active_fifos++;
420 
421 done:
423  return (f);
424 }
425 
426 /**
427  * Free fifo allocated in fifo segment
428  */
429 void
431 {
432  svm_fifo_chunk_t *cur, *next;
435  void *oldheap;
436  int fl_index;
437 
438  ASSERT (f->refcnt > 0);
439 
440  if (--f->refcnt > 0)
441  return;
442 
443  sh = fs->ssvm.sh;
444  fsh = fs->h;
445 
446  ssvm_lock_non_recursive (sh, 2);
447 
448  /* Remove from active list. Only rx fifos are tracked */
449  if (f->flags & SVM_FIFO_F_LL_TRACKED)
450  {
451  if (f->prev)
452  f->prev->next = f->next;
453  else
454  fsh->fifos = f->next;
455  if (f->next)
456  f->next->prev = f->prev;
457  f->flags &= ~SVM_FIFO_F_LL_TRACKED;
458  }
459 
460  /* Add to free list */
461  f->next = fsh->free_fifos;
462  f->prev = 0;
463  fsh->free_fifos = f;
464 
465  /* Free fifo chunks */
466  cur = f->start_chunk;
467  do
468  {
469  next = cur->next;
470  fl_index = fs_freelist_for_size (cur->length);
471  ASSERT (fl_index < vec_len (fsh->free_chunks));
472  cur->next = fsh->free_chunks[fl_index];
473  fsh->free_chunks[fl_index] = cur;
474  fsh->n_fl_chunk_bytes += fs_freelist_index_to_size (fl_index);
475  cur = next;
476  }
477  while (cur != f->start_chunk);
478 
479  f->start_chunk = f->end_chunk = f->new_chunks = 0;
480  f->head_chunk = f->tail_chunk = f->ooo_enq = f->ooo_deq = 0;
481 
482  oldheap = ssvm_push_heap (sh);
484  ssvm_pop_heap (oldheap);
485 
486  /* not allocated on segment heap */
488 
489  if (CLIB_DEBUG)
490  {
491  f->master_session_index = ~0;
492  f->master_thread_index = ~0;
493  }
494 
495  fsh->n_active_fifos--;
497 }
498 
499 int
501 {
502  fifo_segment_header_t *fsh = fs->h;
503  svm_fifo_t *f;
504  void *oldheap;
505  u32 size;
506  u8 *fmem;
507  int i;
508 
509  size = (sizeof (*f)) * batch_size;
510 
511  oldheap = ssvm_push_heap (fs->ssvm.sh);
513  0 /* align_offset */ ,
514  0 /* os_out_of_memory */ );
515  ssvm_pop_heap (oldheap);
516 
517  /* Out of space.. */
518  if (fmem == 0)
519  return -1;
520 
521  /* Carve fifo + chunk space */
522  for (i = 0; i < batch_size; i++)
523  {
524  f = (svm_fifo_t *) fmem;
525  memset (f, 0, sizeof (*f));
526  f->next = fsh->free_fifos;
527  fsh->free_fifos = f;
528  fmem += sizeof (*f);
529  }
530 
531  fsh->n_free_bytes -= size;
532 
533  return 0;
534 }
535 
536 int
538  u32 batch_size)
539 {
540  fifo_segment_header_t *fsh = fs->h;
541  u32 size, rounded_data_size, fl_index;
543  void *oldheap;
544  u8 *cmem;
545  int i;
546 
547  if (!fs_chunk_size_is_valid (chunk_size))
548  {
549  clib_warning ("chunk size out of range %d", chunk_size);
550  return -1;
551  }
552 
553  fl_index = fs_freelist_for_size (chunk_size);
554  vec_validate_init_empty (fsh->free_chunks, fl_index, 0);
555  rounded_data_size = fs_freelist_index_to_size (fl_index);
556  size = (sizeof (*c) + rounded_data_size) * batch_size;
557 
558  oldheap = ssvm_push_heap (fs->ssvm.sh);
560  0 /* align_offset */ ,
561  0 /* os_out_of_memory */ );
562  ssvm_pop_heap (oldheap);
563 
564  /* Out of space.. */
565  if (cmem == 0)
566  return -1;
567 
568  /* Carve fifo + chunk space */
569  for (i = 0; i < batch_size; i++)
570  {
571  c = (svm_fifo_chunk_t *) cmem;
572  c->start_byte = 0;
573  c->length = rounded_data_size;
574  c->next = fsh->free_chunks[fl_index];
575  fsh->free_chunks[fl_index] = c;
576  cmem += sizeof (*c) + rounded_data_size;
577  }
578 
579  fsh->n_fl_chunk_bytes += batch_size * rounded_data_size;
580  fsh->n_free_bytes -= size;
581 
582  return 0;
583 }
584 
585 /**
586  * Pre-allocates fifo pairs in fifo segment
587  */
588 void
590  u32 rx_fifo_size, u32 tx_fifo_size,
591  u32 * n_fifo_pairs)
592 {
593  u32 rx_rounded_data_size, tx_rounded_data_size, pair_size, pairs_to_alloc;
594  int rx_fl_index, tx_fl_index;
595  uword space_available;
596  u32 hdrs;
597 
598  /* Parameter check */
599  if (rx_fifo_size == 0 || tx_fifo_size == 0 || *n_fifo_pairs == 0)
600  return;
601 
602  if (!fs_chunk_size_is_valid (rx_fifo_size))
603  {
604  clib_warning ("rx fifo_size out of range %d", rx_fifo_size);
605  return;
606  }
607 
608  if (!fs_chunk_size_is_valid (tx_fifo_size))
609  {
610  clib_warning ("tx fifo_size out of range %d", tx_fifo_size);
611  return;
612  }
613 
614  rx_rounded_data_size = (1 << (max_log2 (rx_fifo_size)));
615  rx_fl_index = fs_freelist_for_size (rx_fifo_size);
616  tx_rounded_data_size = (1 << (max_log2 (tx_fifo_size)));
617  tx_fl_index = fs_freelist_for_size (tx_fifo_size);
618 
619  hdrs = sizeof (svm_fifo_t) + sizeof (svm_fifo_chunk_t);
620 
621  /* Calculate space requirements */
622  pair_size = 2 * hdrs + rx_rounded_data_size + tx_rounded_data_size;
623  space_available = fs_free_space (fs);
624  pairs_to_alloc = space_available / pair_size;
625  pairs_to_alloc = clib_min (pairs_to_alloc, *n_fifo_pairs);
626 
627  if (!pairs_to_alloc)
628  return;
629 
630  if (fs_try_alloc_fifo_batch (fs, rx_fl_index, pairs_to_alloc))
631  clib_warning ("rx prealloc failed: pairs %u", pairs_to_alloc);
632  if (fs_try_alloc_fifo_batch (fs, tx_fl_index, pairs_to_alloc))
633  clib_warning ("tx prealloc failed: pairs %u", pairs_to_alloc);
634 
635  /* Account for the pairs allocated */
636  *n_fifo_pairs -= pairs_to_alloc;
637 }
638 
639 int
641 {
644  void *oldheap;
645  int fl_index;
646 
647  if (!fs_chunk_size_is_valid (chunk_size))
648  {
649  clib_warning ("chunk size out of range %d", chunk_size);
650  return -1;
651  }
652 
653  fl_index = fs_freelist_for_size (chunk_size);
654 
655  sh = fs->ssvm.sh;
656  ssvm_lock_non_recursive (sh, 1);
657 
658  vec_validate_init_empty (fs->h->free_chunks, fl_index, 0);
659  c = fs->h->free_chunks[fl_index];
660 
661  oldheap = ssvm_push_heap (sh);
662 
663  if (!c)
664  {
665  c = svm_fifo_chunk_alloc (chunk_size);
666  if (!c)
667  {
668  ssvm_pop_heap (oldheap);
670  return -1;
671  }
672  }
673  else
674  {
675  fs->h->free_chunks[fl_index] = c->next;
676  c->next = 0;
677  fs->h->n_fl_chunk_bytes -= fs_freelist_index_to_size (fl_index);
678  }
679 
680  svm_fifo_add_chunk (f, c);
681 
682  ssvm_pop_heap (oldheap);
684  return 0;
685 }
686 
687 int
689 {
690  svm_fifo_chunk_t *cur, *next;
692  void *oldheap;
693  int fl_index;
694 
695  sh = fs->ssvm.sh;
696  ssvm_lock_non_recursive (sh, 1);
697 
698  oldheap = ssvm_push_heap (sh);
699  cur = svm_fifo_collect_chunks (f);
700 
701  while (cur)
702  {
703  next = cur->next;
704  fl_index = fs_freelist_for_size (cur->length);
705  cur->next = fs->h->free_chunks[fl_index];
706  fs->h->free_chunks[fl_index] = cur;
707  cur = next;
708  }
709 
710  ssvm_pop_heap (oldheap);
712 
713  return 0;
714 }
715 
716 /**
717  * Get number of active fifos
718  */
719 u32
721 {
722  return fs->h->n_active_fifos;
723 }
724 
725 u32
727 {
728  fifo_segment_header_t *fsh = fs->h;
729  svm_fifo_t *f;
730  u32 count = 0;
731 
732  f = fsh->free_fifos;
733  if (f == 0)
734  return 0;
735 
736  while (f)
737  {
738  f = f->next;
739  count++;
740  }
741  return count;
742 }
743 
744 u32
746 {
747  u32 count = 0, rounded_size, fl_index;
750  int i;
751 
752  fsh = fs->h;
753 
754  /* Count all free chunks? */
755  if (size == ~0)
756  {
757  for (i = 0; i < vec_len (fsh->free_chunks); i++)
758  {
759  c = fsh->free_chunks[i];
760  if (c == 0)
761  continue;
762 
763  while (c)
764  {
765  c = c->next;
766  count++;
767  }
768  }
769  return count;
770  }
771 
772  rounded_size = (1 << (max_log2 (size)));
773  fl_index = fs_freelist_for_size (rounded_size);
774 
775  if (fl_index >= vec_len (fsh->free_chunks))
776  return 0;
777 
778  c = fsh->free_chunks[fl_index];
779  if (c == 0)
780  return 0;
781 
782  while (c)
783  {
784  c = c->next;
785  count++;
786  }
787  return count;
788 }
789 
790 void
792 {
793  fs->h->n_free_bytes = fs_free_space (fs);
794 }
795 
796 u32
798 {
799  return fs->h->n_free_bytes;
800 }
801 
802 u32
804 {
805  return fs->h->n_fl_chunk_bytes;
806 }
807 
808 u8
810 {
811  return fs->h->fifos != 0;
812 }
813 
814 svm_fifo_t *
816 {
817  return fs->h->fifos;
818 }
819 
820 u8 *
821 format_fifo_segment_type (u8 * s, va_list * args)
822 {
823  fifo_segment_t *sp;
824  sp = va_arg (*args, fifo_segment_t *);
825  ssvm_segment_type_t st = ssvm_type (&sp->ssvm);
826 
827  if (st == SSVM_SEGMENT_PRIVATE)
828  s = format (s, "%s", "private-heap");
829  else if (st == SSVM_SEGMENT_MEMFD)
830  s = format (s, "%s", "memfd");
831  else if (st == SSVM_SEGMENT_SHM)
832  s = format (s, "%s", "shm");
833  else
834  s = format (s, "%s", "unknown");
835  return s;
836 }
837 
838 /**
839  * Segment format function
840  */
841 u8 *
842 format_fifo_segment (u8 * s, va_list * args)
843 {
844  fifo_segment_t *fs = va_arg (*args, fifo_segment_t *);
845  int verbose __attribute__ ((unused)) = va_arg (*args, int);
848  u32 count, indent;
849  u32 active_fifos;
850  u32 free_fifos;
851  char *address;
852  size_t size;
853  int i;
854 
855  indent = format_get_indent (s) + 2;
856 #if USE_DLMALLOC == 0
857  s = format (s, "%U segment heap: %U\n", format_white_space, indent,
858  format_mheap, svm_fifo_segment_heap (fs), verbose);
859  s = format (s, "%U segment has %u active fifos\n",
861 #endif
862 
863  if (fs == 0)
864  {
865  s = format (s, "%-15s%15s%15s%15s%15s%15s", "Name", "Type",
866  "HeapSize (M)", "ActiveFifos", "FreeFifos", "Address");
867  return s;
868  }
869 
870  fsh = fs->h;
871  fifo_segment_info (fs, &address, &size);
872  active_fifos = fifo_segment_num_fifos (fs);
873  free_fifos = fifo_segment_num_free_fifos (fs);
874 
875  s = format (s, "%-15v%15U%15llu%15u%15u%15llx", ssvm_name (&fs->ssvm),
876  format_fifo_segment_type, fs, size >> 20ULL, active_fifos,
877  free_fifos, address);
878 
879  if (!verbose)
880  return s;
881 
882  s = format (s, "\n");
883  for (i = 0; i < vec_len (fsh->free_chunks); i++)
884  {
885  c = fsh->free_chunks[i];
886  if (c == 0)
887  continue;
888  count = 0;
889  while (c)
890  {
891  c = c->next;
892  count++;
893  }
894 
895  s = format (s, "%U%-5u Kb: %u free", format_white_space, indent + 2,
896  1 << (i + max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE) - 10),
897  count);
898  }
899  s = format (s, "%Ufree bytes %U", format_white_space, indent + 2,
901 
902  return s;
903 }
904 
905 /*
906  * fd.io coding-style-patch-verification: ON
907  *
908  * Local Variables:
909  * eval: (c-set-style "gnu")
910  * End:
911  */
u32 length
length of chunk in bytes
Definition: svm_fifo.h:61
void fifo_segment_info(fifo_segment_t *seg, char **address, size_t *size)
Definition: fifo_segment.c:155
u64 ssvm_size
Definition: ssvm.h:85
typedef address
Definition: ip_types.api:83
fifo_segment_header_t * h
fifo segment data
Definition: fifo_segment.h:53
#define clib_min(x, y)
Definition: clib.h:295
svm_fifo_chunk_t * svm_fifo_collect_chunks(svm_fifo_t *f)
Removes chunks that are after fifo end byte.
Definition: svm_fifo.c:634
static u32 fs_free_space(fifo_segment_t *fs)
Fifo segment free space.
Definition: fifo_segment.c:29
uword requested_va
Definition: ssvm.h:88
i32 next
Definition: heap.h:78
static void * clib_mem_alloc_aligned_at_offset(uword size, uword align, uword align_offset, int os_out_of_memory_on_failure)
Definition: mem.h:102
a
Definition: bitmap.h:538
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:239
void svm_fifo_free_chunk_lookup(svm_fifo_t *f)
Cleanup fifo chunk lookup rb tree.
Definition: svm_fifo.c:766
volatile u32 ready
Definition: ssvm.h:77
unsigned long u64
Definition: types.h:89
void fifo_segment_delete(fifo_segment_main_t *sm, fifo_segment_t *s)
Definition: fifo_segment.c:129
u32 n_active_fifos
Number of active fifos.
Definition: fifo_segment.h:44
void * opaque[SSVM_N_OPAQUE]
Definition: ssvm.h:74
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
void svm_fifo_init(svm_fifo_t *f, u32 size)
Initialize fifo.
Definition: svm_fifo.c:392
int i
static u32 format_get_indent(u8 *s)
Definition: format.h:72
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
ssvm_shared_header_t * sh
Definition: ssvm.h:84
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static svm_fifo_t * fs_try_alloc_fifo_freelist(fifo_segment_t *fs, u32 fl_index, u32 data_bytes)
Definition: fifo_segment.c:193
DLMALLOC_EXPORT struct dlmallinfo mspace_mallinfo(mspace msp)
static u32 fs_freelist_index_to_size(u32 fl_index)
Definition: fifo_segment.c:176
u32 n_free_bytes
Bytes usable for new allocs.
Definition: fifo_segment.h:46
unsigned char u8
Definition: types.h:56
u32 fifo_segment_num_free_fifos(fifo_segment_t *fs)
Definition: fifo_segment.c:726
void ssvm_delete(ssvm_private_t *ssvm)
Definition: ssvm.c:432
struct _svm_fifo svm_fifo_t
void svm_fifo_init_chunks(svm_fifo_t *f)
Initialize fifo chunks and rbtree.
Definition: svm_fifo.c:408
u32 fifo_segment_num_free_chunks(fifo_segment_t *fs, u32 size)
Find number of free chunks of given size.
Definition: fifo_segment.c:745
fifo_segment_t * fifo_segment_get_segment(fifo_segment_main_t *sm, u32 segment_index)
Definition: fifo_segment.c:149
u32 n_fl_chunk_bytes
Chunk bytes on freelist.
Definition: fifo_segment.h:47
u32 fifo_segment_free_bytes(fifo_segment_t *fs)
Fifo segment estimate of number of free bytes.
Definition: fifo_segment.c:797
u8 * ssvm_name(const ssvm_private_t *ssvm)
Definition: ssvm.c:444
int fifo_segment_prealloc_fifo_hdrs(fifo_segment_t *fs, u32 batch_size)
Try to preallocate fifo headers.
Definition: fifo_segment.c:500
enum ssvm_segment_type_ ssvm_segment_type_t
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
svm_fifo_chunk_t * svm_fifo_chunk_alloc(u32 size)
Creates a fifo chunk in the current heap.
Definition: svm_fifo.c:471
static u32 fs_freelist_for_size(u32 size)
Definition: fifo_segment.c:170
u8 * format_memory_size(u8 *s, va_list *va)
Definition: std-formats.c:209
void svm_fifo_free_ooo_data(svm_fifo_t *f)
Cleanup fifo ooo data.
Definition: svm_fifo.c:132
static void * ssvm_push_heap(ssvm_shared_header_t *sh)
Definition: ssvm.h:143
unsigned int u32
Definition: types.h:88
int attach_timeout
shm segments attach timeout (sec)
Definition: ssvm.h:94
u64 next_baseva
Where to put the next one.
Definition: fifo_segment.h:59
int ssvm_master_init(ssvm_private_t *ssvm, ssvm_segment_type_t type)
Definition: ssvm.c:420
static void ssvm_pop_heap(void *oldheap)
Definition: ssvm.h:151
char * segment_name
segment name
Definition: fifo_segment.h:68
static heap_elt_t * first(heap_header_t *h)
Definition: heap.c:59
int fifo_segment_attach(fifo_segment_main_t *sm, fifo_segment_create_args_t *a)
Attach as slave to a fifo segment.
Definition: fifo_segment.c:99
void fifo_segment_preallocate_fifo_pairs(fifo_segment_t *fs, u32 rx_fifo_size, u32 tx_fifo_size, u32 *n_fifo_pairs)
Pre-allocates fifo pairs in fifo segment.
Definition: fifo_segment.c:589
u8 * format_mheap(u8 *s, va_list *va)
Definition: mem_dlmalloc.c:354
svm_fifo_chunk_t ** free_chunks
Freelists by chunk size.
Definition: fifo_segment.h:43
u8 * format_fifo_segment_type(u8 *s, va_list *args)
Definition: fifo_segment.c:821
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
uword size
struct svm_fifo_chunk_ * next
pointer to next chunk in linked-lists
Definition: svm_fifo.h:62
u8 * format_fifo_segment(u8 *s, va_list *args)
Segment format function.
Definition: fifo_segment.c:842
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
u32 fifo_segment_fl_chunk_bytes(fifo_segment_t *fs)
Number of bytes on chunk free lists.
Definition: fifo_segment.c:803
int fifo_segment_grow_fifo(fifo_segment_t *fs, svm_fifo_t *f, u32 chunk_size)
Grow fifo size by adding an additional chunk of memory.
Definition: fifo_segment.c:640
static int fs_chunk_size_is_valid(u32 size)
Definition: fifo_segment.c:182
svm_fifo_t * free_fifos
Freelists by fifo size.
Definition: fifo_segment.h:42
svm_fifo_t * fifo_segment_get_fifo_list(fifo_segment_t *fs)
Definition: fifo_segment.c:815
static int fs_try_alloc_fifo_batch(fifo_segment_t *fs, u32 fl_index, u32 batch_size)
Definition: fifo_segment.c:270
int fifo_segment_prealloc_fifo_chunks(fifo_segment_t *fs, u32 chunk_size, u32 batch_size)
Try to preallocate fifo chunks on segment.
Definition: fifo_segment.c:537
int fifo_segment_create(fifo_segment_main_t *sm, fifo_segment_create_args_t *a)
Create a fifo segment and initialize as master.
Definition: fifo_segment.c:65
#define FIFO_SEGMENT_MIN_FIFO_SIZE
Definition: fifo_segment.h:29
u32 segment_size
size of the segment
Definition: fifo_segment.h:66
ssvm_private_t ssvm
ssvm segment data
Definition: fifo_segment.h:52
svmdb_client_t * c
void fifo_segment_main_init(fifo_segment_main_t *sm, u64 baseva, u32 timeout_in_seconds)
Definition: fifo_segment.c:162
#define clib_warning(format, args...)
Definition: error.h:59
void svm_fifo_add_chunk(svm_fifo_t *f, svm_fifo_chunk_t *c)
Grow fifo size by adding chunk to chunk list.
Definition: svm_fifo.c:579
int ssvm_slave_init(ssvm_private_t *ssvm, ssvm_segment_type_t type)
Definition: ssvm.c:426
u32 my_pid
Definition: ssvm.h:86
u32 start_byte
chunk start byte
Definition: svm_fifo.h:60
int memfd_fd
fd for memfd segments
Definition: fifo_segment.h:67
int fd
memfd segments
Definition: ssvm.h:93
u32 fifo_segment_index(fifo_segment_main_t *sm, fifo_segment_t *s)
Definition: fifo_segment.c:137
#define ASSERT(truth)
void * svm_fifo_segment_heap(fifo_segment_t *seg)
Definition: fifo_segment.c:143
void fifo_segment_free_fifo(fifo_segment_t *fs, svm_fifo_t *f)
Free fifo allocated in fifo segment.
Definition: fifo_segment.c:430
static svm_fifo_t * fs_try_alloc_fifo(fifo_segment_t *fs, u32 data_bytes)
Try to allocate new fifo.
Definition: fifo_segment.c:326
fifo_segment_t * segments
pool of fifo segments
Definition: fifo_segment.h:58
fifo_segment_ftype_t
Definition: fifo_segment.h:21
#define FIFO_SEGMENT_MAX_FIFO_SIZE
Definition: fifo_segment.h:30
size_t count
Definition: vapi.c:47
svm_fifo_t * fifo_segment_alloc_fifo(fifo_segment_t *fs, u32 data_bytes, fifo_segment_ftype_t ftype)
Allocate fifo in fifo segment.
Definition: fifo_segment.c:375
static void * clib_mem_alloc(uword size)
Definition: mem.h:153
u8 * name
Definition: ssvm.h:87
ssvm_segment_type_t segment_type
type of segment requested
Definition: fifo_segment.h:65
svm_fifo_t * fifos
Linked list of active RX fifos.
Definition: fifo_segment.h:41
u32 fifo_segment_num_fifos(fifo_segment_t *fs)
Get number of active fifos.
Definition: fifo_segment.c:720
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static uword max_log2(uword x)
Definition: clib.h:191
u64 uword
Definition: types.h:112
void fifo_segment_update_free_bytes(fifo_segment_t *fs)
Update fifo segment free bytes estimate.
Definition: fifo_segment.c:791
u8 fifo_segment_has_fifos(fifo_segment_t *fs)
Definition: fifo_segment.c:809
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:161
int fifo_segment_collect_fifo_chunks(fifo_segment_t *fs, svm_fifo_t *f)
Collect unused chunks for fifo.
Definition: fifo_segment.c:688
#define FIFO_SEGMENT_ALLOC_BATCH_SIZE
Definition: fifo_segment.h:31
static void ssvm_unlock_non_recursive(ssvm_shared_header_t *h)
Definition: ssvm.h:136
u32 timeout_in_seconds
Time to wait during attach.
Definition: fifo_segment.h:60
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:486
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
int fifo_segment_init(fifo_segment_t *fs)
Initialize fifo segment shared header.
Definition: fifo_segment.c:41
int i_am_master
Definition: ssvm.h:89
static void ssvm_lock_non_recursive(ssvm_shared_header_t *h, u32 tag)
Definition: ssvm.h:116
u32 * new_segment_indices
return vec of new seg indices
Definition: fifo_segment.h:69
static svm_fifo_t * fs_try_alloc_fifo_freelist_multi_chunk(fifo_segment_t *fs, u32 data_bytes)
Definition: fifo_segment.c:219
ssvm_segment_type_t ssvm_type(const ssvm_private_t *ssvm)
Definition: ssvm.c:438
svm_fifo_t * svm_fifo_create(u32 data_size_in_bytes)
Creates a fifo in the current heap.
Definition: svm_fifo.c:436