FD.io VPP  v21.01.1
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 static inline fifo_segment_slice_t *
20 {
21  return &fsh->slices[slice_index];
22 }
23 
25 #define _(sym,str) str,
27 #undef _
28 };
29 
30 /**
31  * Fifo segment free space
32  *
33  * Queries the underlying memory manager, dlmalloc, for free space. Since this
34  * ends up walking the internal data structures, it should not be called
35  * indiscriminately.
36  *
37  * @param fs fifo segment
38  * @return number of free bytes
39  */
40 static uword
42 {
44 }
45 
46 static inline void
48 {
50 }
51 
52 static inline uword
54 {
56  return n_free > fsh->n_reserved_bytes ? n_free - fsh->n_reserved_bytes : 0;
57 }
58 
59 static inline void
61 {
63 }
64 
65 static inline void
67 {
69 }
70 
71 static inline void
73 {
75 }
76 
77 static inline uword
79 {
81  return n_cached;
82 }
83 
84 static inline void
86 {
88 }
89 
90 static inline u32
92 {
94 }
95 
96 static inline uword
98 {
100  uword total_vm = 0;
101  int i;
102 
103  for (i = 0; i < fsh->n_slices; i++)
104  {
105  fss = fsh_slice_get (fsh, i);
106  total_vm += clib_atomic_load_relax_n (&fss->virtual_mem);
107  }
108  return total_vm;
109 }
110 
111 void
113  int n_bytes)
114 {
115  fifo_segment_slice_t *fss = fsh_slice_get (fsh, slice_index);
116  fss->virtual_mem += n_bytes;
117 }
118 
119 static void
121 {
122  uword thresh;
123 
124  if (fsh->flags & FIFO_SEGMENT_F_MEM_LIMIT)
125  return;
126 
127  thresh = clib_max (0.01 * fsh->ssvm_sh->ssvm_size,
128  2 * fsh->n_reserved_bytes);
129  if (fsh->n_free_bytes > thresh)
130  return;
131 
133  fsh_update_free_bytes (fsh);
134 }
135 
136 static inline int
138 {
139  return (fl_index < vec_len (fss->free_chunks));
140 }
141 
142 static void
145 {
147  c->next = fss->free_chunks[fl_index];
148  fss->free_chunks[fl_index] = c;
150 }
151 
152 static void
154  svm_fifo_chunk_t * head,
155  svm_fifo_chunk_t * tail)
156 {
158  tail->next = fss->free_chunks[fl_index];
159  fss->free_chunks[fl_index] = head;
161 }
162 
163 static svm_fifo_chunk_t *
165 {
167 
168  ASSERT (fss_chunk_fl_index_is_valid (fss, fl_index));
169 
171 
172  if (!fss->free_chunks[fl_index])
173  {
175  return 0;
176  }
177 
178  c = fss->free_chunks[fl_index];
179  fss->free_chunks[fl_index] = c->next;
180 
182 
183  return c;
184 }
185 
186 static inline void
188 {
189  if (fss->fifos)
190  {
191  fss->fifos->prev = f;
192  f->next = fss->fifos;
193  }
194  fss->fifos = f;
195 }
196 
197 static inline void
199 {
200  if (f->flags & SVM_FIFO_F_LL_TRACKED)
201  {
202  if (f->prev)
203  f->prev->next = f->next;
204  else
205  fss->fifos = f->next;
206  if (f->next)
207  f->next->prev = f->prev;
208  }
209 }
210 
211 static inline uword
213 {
215 }
216 
217 static inline void
219 {
221 }
222 
223 static inline void
225 {
227 }
228 
229 /**
230  * Initialize fifo segment shared header
231  */
232 int
234 {
238  u32 max_chunk_sz;
239  uword max_fifo;
240  void *oldheap;
241  int i;
242 
243  sh = fs->ssvm.sh;
244  oldheap = ssvm_push_heap (sh);
245 
246  /*
247  * Manually align the fifo segment header to sizeof(uword) = 8 bytes.
248  * Long story made short: the "process-private" fifo segment
249  * is allocated from the main heap, not mmapped. dlmalloc
250  * only guarantees 4-byte alignment, and on aarch64
251  * the fsh can end up 4-byte but not 8-byte aligned.
252  * That eventually causes the atomic op in fifo_segment_update_free_bytes
253  * to backfire.
254  */
255  fsh = clib_mem_alloc_aligned (sizeof (*fsh), sizeof (uword));
256  clib_memset (fsh, 0, sizeof (*fsh));
257  fs->h = sh->opaque[0] = fsh;
258  fs->n_slices = clib_max (fs->n_slices, 1);
259 
260  fsh->ssvm_sh = fs->ssvm.sh;
261  fsh->n_slices = fs->n_slices;
262  max_fifo = clib_min ((fsh_free_space (fsh) - 4096) / 2,
264  fsh->max_log2_chunk_size = max_log2 (max_fifo);
265 
266  fsh->slices = clib_mem_alloc (sizeof (*fss) * fs->n_slices);
267  clib_memset (fsh->slices, 0, sizeof (*fss) * fs->n_slices);
269 
270  for (i = 0; i < fs->n_slices; i++)
271  {
272  fss = fsh_slice_get (fsh, i);
273  vec_validate_init_empty (fss->free_chunks, max_chunk_sz, 0);
274  vec_validate_init_empty (fss->num_chunks, max_chunk_sz, 0);
276  }
277 
278  ssvm_pop_heap (oldheap);
279 
280  fsh->n_free_bytes = fsh_free_space (fsh);
281  fsh->n_cached_bytes = 0;
282  fsh->n_reserved_bytes = clib_min (0.01 * fsh->n_free_bytes, 256 << 10);
283  sh->ready = 1;
284  return (0);
285 }
286 
287 /**
288  * Create a fifo segment and initialize as master
289  */
290 int
292 {
293  fifo_segment_t *fs;
294  uword baseva;
295  int rv;
296 
297  /* Allocate a fresh segment */
298  pool_get_zero (sm->segments, fs);
299 
300  baseva = a->segment_type == SSVM_SEGMENT_PRIVATE ? ~0ULL : sm->next_baseva;
301  fs->ssvm.ssvm_size = a->segment_size;
302  fs->ssvm.is_server = 1;
303  fs->ssvm.my_pid = getpid ();
304  fs->ssvm.name = format (0, "%s%c", a->segment_name, 0);
305  fs->ssvm.requested_va = baseva;
306 
307  if ((rv = ssvm_server_init (&fs->ssvm, a->segment_type)))
308  {
309  pool_put (sm->segments, fs);
310  return (rv);
311  }
312 
313  /* Note: requested_va updated due to seg base addr randomization */
314  sm->next_baseva = fs->ssvm.sh->ssvm_va + fs->ssvm.ssvm_size;
315 
316  fifo_segment_init (fs);
317  vec_add1 (a->new_segment_indices, fs - sm->segments);
318  return (0);
319 }
320 
321 /**
322  * Attach as slave to a fifo segment
323  */
324 int
326 {
327  fifo_segment_t *fs;
328  int rv;
329 
330  pool_get_zero (sm->segments, fs);
331 
332  fs->ssvm.ssvm_size = a->segment_size;
333  fs->ssvm.my_pid = getpid ();
334  fs->ssvm.name = format (0, "%s%c", a->segment_name, 0);
335  fs->ssvm.requested_va = sm->next_baseva;
337  fs->ssvm.fd = a->memfd_fd;
338  else
340 
341  if ((rv = ssvm_client_init (&fs->ssvm, a->segment_type)))
342  {
343  _vec_len (fs) = vec_len (fs) - 1;
344  return (rv);
345  }
346 
347  /* Fish the segment header */
348  fs->h = fs->ssvm.sh->opaque[0];
349 
350  vec_add1 (a->new_segment_indices, fs - sm->segments);
351  return (0);
352 }
353 
354 void
356 {
357  ssvm_delete (&s->ssvm);
358  clib_memset (s, 0xfe, sizeof (*s));
359  pool_put (sm->segments, s);
360 }
361 
362 u32
364 {
365  return s - sm->segments;
366 }
367 
370 {
371  return pool_elt_at_index (sm->segments, segment_index);
372 }
373 
374 void
375 fifo_segment_info (fifo_segment_t * seg, char **address, size_t * size)
376 {
377  *address = (char *) seg->ssvm.sh->ssvm_va;
378  *size = seg->ssvm.ssvm_size;
379 }
380 
381 void
383  u32 timeout_in_seconds)
384 {
385  sm->next_baseva = baseva;
386  sm->timeout_in_seconds = timeout_in_seconds;
387 }
388 
389 static inline u32
391 {
393  return 0;
395 }
396 
397 static inline u32
399 {
400  return 1 << (fl_index + FIFO_SEGMENT_MIN_LOG2_FIFO_SIZE);
401 }
402 
403 static inline int
405 {
406  /*
407  * 4K minimum. It's not likely that anything good will happen
408  * with a smaller FIFO.
409  */
410  return size >= FIFO_SEGMENT_MIN_FIFO_SIZE
411  && size <= (1ULL << fsh->max_log2_chunk_size);
412 }
413 
416  fifo_segment_slice_t * fss, u32 data_bytes)
417 {
418  u32 fl_index, fl_size, n_alloc = 0, req_bytes = data_bytes;
419  svm_fifo_chunk_t *c, *first = 0, *next;
420 
421  fl_index = fs_freelist_for_size (req_bytes);
422  if (fl_index > 0)
423  fl_index -= 1;
424 
425  fl_size = fs_freelist_index_to_size (fl_index);
426 
427  while (req_bytes)
428  {
429  c = fss_chunk_free_list_pop (fss, fl_index);
430  if (c)
431  {
432  c->next = first;
433  first = c;
434  n_alloc += fl_size;
435  req_bytes -= clib_min (fl_size, req_bytes);
436  }
437  else
438  {
439  /* Failed to allocate with smaller chunks */
440  if (fl_index == 0)
441  {
442  /* Free all chunks if any allocated */
443  c = first;
444  while (c)
445  {
446  fl_index = fs_freelist_for_size (c->length);
447  next = c->next;
448  fss_chunk_free_list_push (fss, fl_index, c);
449  c = next;
450  }
451  n_alloc = 0;
452  first = 0;
453  /* As last attempt, try allocating a chunk larger than
454  * the requested size, if possible */
455  fl_index = fs_freelist_for_size (data_bytes) + 1;
456  if (!fss_chunk_fl_index_is_valid (fss, fl_index))
457  return 0;
458  first = fss_chunk_free_list_pop (fss, fl_index);
459  if (first)
460  {
461  first->next = 0;
462  n_alloc = fs_freelist_index_to_size (fl_index);
463  goto done;
464  }
465  return 0;
466  }
467  fl_index -= 1;
468  fl_size = fl_size >> 1;
469  }
470  }
471 
472 done:
473  fss_fl_chunk_bytes_sub (fss, n_alloc);
474  fsh_cached_bytes_sub (fsh, n_alloc);
475  return first;
476 }
477 
478 static int
480  fifo_segment_slice_t * fss, u32 batch_size)
481 {
482  svm_fifo_t *f;
483  void *oldheap;
484  uword size;
485  u8 *fmem;
486  int i;
487 
488  ASSERT (batch_size != 0);
489 
490  size = (uword) sizeof (*f) * batch_size;
491 
492  oldheap = ssvm_push_heap (fsh->ssvm_sh);
494  0 /* align_offset */ ,
495  0 /* os_out_of_memory */ );
496  ssvm_pop_heap (oldheap);
497 
498  /* Out of space.. */
499  if (fmem == 0)
500  return -1;
501 
502  /* Carve fifo hdr space */
503  for (i = 0; i < batch_size; i++)
504  {
505  f = (svm_fifo_t *) fmem;
506  memset (f, 0, sizeof (*f));
507  f->next = fss->free_fifos;
508  fss->free_fifos = f;
509  fmem += sizeof (*f);
510  }
511 
512  fsh_free_bytes_sub (fsh, size);
513 
514  return 0;
515 }
516 
517 static int
519  fifo_segment_slice_t * fss,
520  u32 fl_index, u32 batch_size)
521 {
522  svm_fifo_chunk_t *c, *head = 0, *tail;
523  uword size, total_chunk_bytes;
524  u32 rounded_data_size;
525  void *oldheap;
526  u8 *cmem;
527  int i;
528 
529  ASSERT (batch_size != 0);
530 
531  rounded_data_size = fs_freelist_index_to_size (fl_index);
532  total_chunk_bytes = (uword) batch_size *rounded_data_size;
533  size = (uword) (sizeof (*c) + rounded_data_size) * batch_size;
534 
535  oldheap = ssvm_push_heap (fsh->ssvm_sh);
537  0 /* align_offset */ ,
538  0 /* os_out_of_memory */ );
539  ssvm_pop_heap (oldheap);
540 
541  /* Out of space.. */
542  if (cmem == 0)
543  return -1;
544 
545  /* Carve fifo + chunk space */
546  tail = c = (svm_fifo_chunk_t *) cmem;
547  for (i = 0; i < batch_size; i++)
548  {
549  c->start_byte = 0;
550  c->length = rounded_data_size;
551  c->next = head;
552  head = c;
553  cmem += sizeof (*c) + rounded_data_size;
554  c = (svm_fifo_chunk_t *) cmem;
555  }
556 
557  fss_chunk_free_list_push_list (fss, fl_index, head, tail);
558  fss->num_chunks[fl_index] += batch_size;
559  fss_fl_chunk_bytes_add (fss, total_chunk_bytes);
560  fsh_cached_bytes_add (fsh, total_chunk_bytes);
561  fsh_free_bytes_sub (fsh, size);
562 
563  return 0;
564 }
565 
566 static int
568  fifo_segment_slice_t * fss,
569  u32 fl_index, u32 batch_size)
570 {
571  if (fsh_try_alloc_fifo_hdr_batch (fsh, fss, batch_size))
572  return 0;
573  return fsh_try_alloc_chunk_batch (fsh, fss, fl_index, batch_size);
574 }
575 
576 static svm_fifo_t *
578  fifo_segment_slice_t * fss)
579 {
580  svm_fifo_t *f;
581 
582  if (!fss->free_fifos)
583  {
584  if (fsh_try_alloc_fifo_hdr_batch (fsh, fss,
586  return 0;
587  }
588 
589  f = fss->free_fifos;
590  fss->free_fifos = f->next;
591  memset (f, 0, sizeof (*f));
592  return f;
593 }
594 
595 static svm_fifo_chunk_t *
597  fifo_segment_slice_t * fss, u32 data_bytes)
598 {
600  u32 fl_index;
601 
602  fl_index = fs_freelist_for_size (data_bytes);
603 
604 free_list:
605  c = fss_chunk_free_list_pop (fss, fl_index);
606  if (c)
607  {
608  c->next = 0;
611  }
612  else
613  {
614  u32 chunk_size, batch = FIFO_SEGMENT_ALLOC_BATCH_SIZE;
615  uword n_free;
616 
617  chunk_size = fs_freelist_index_to_size (fl_index);
618  n_free = fsh_n_free_bytes (fsh);
619 
620  if (chunk_size <= n_free)
621  {
622  batch = chunk_size * batch <= n_free ? batch : 1;
623  if (!fsh_try_alloc_chunk_batch (fsh, fss, fl_index, batch))
624  goto free_list;
625  }
626  /* Failed to allocate larger chunk, try to allocate multi-chunk
627  * that is close to what was actually requested */
628  if (data_bytes <= fss_fl_chunk_bytes (fss))
629  {
630  c = fs_try_alloc_multi_chunk (fsh, fss, data_bytes);
631  if (c)
632  goto done;
633  batch = n_free / FIFO_SEGMENT_MIN_FIFO_SIZE;
634  if (!batch || fsh_try_alloc_chunk_batch (fsh, fss, 0, batch))
635  {
636  fsh_check_mem (fsh);
637  goto done;
638  }
639  }
640  if (data_bytes <= fss_fl_chunk_bytes (fss) + n_free)
641  {
642  u32 min_size = FIFO_SEGMENT_MIN_FIFO_SIZE;
643 
644  batch = (data_bytes - fss_fl_chunk_bytes (fss)) / min_size;
645  batch = clib_min (batch + 1, n_free / min_size);
646  if (fsh_try_alloc_chunk_batch (fsh, fss, 0, batch))
647  {
648  fsh_check_mem (fsh);
649  goto done;
650  }
651  c = fs_try_alloc_multi_chunk (fsh, fss, data_bytes);
652  }
653  }
654 
655 done:
656 
657  return c;
658 }
659 
660 /**
661  * Try to allocate new fifo
662  *
663  * Tries the following steps in order:
664  * - grab fifo and chunk from freelists
665  * - batch fifo and chunk allocation
666  * - single fifo allocation
667  * - grab multiple fifo chunks from freelists
668  */
669 static svm_fifo_t *
671  u32 data_bytes)
672 {
673  u32 fl_index, min_size;
675  svm_fifo_t *f = 0;
676 
677  min_size = clib_max ((fsh->pct_first_alloc * data_bytes) / 100, 4096);
678  fl_index = fs_freelist_for_size (min_size);
679 
680  if (!fss_chunk_fl_index_is_valid (fss, fl_index))
681  return 0;
682 
683  f = fsh_try_alloc_fifo_hdr (fsh, fss);
684  if (!f)
685  return 0;
686 
687  c = fsh_try_alloc_chunk (fsh, fss, min_size);
688  if (!c)
689  {
690  f->next = fss->free_fifos;
691  fss->free_fifos = f;
692  return 0;
693  }
694 
695  f->start_chunk = c;
696  while (c->next)
697  c = c->next;
698  f->end_chunk = c;
699  f->size = data_bytes;
700  f->fs_hdr = fsh;
701 
702  return f;
703 }
704 
706 fsh_alloc_chunk (fifo_segment_header_t * fsh, u32 slice_index, u32 chunk_size)
707 {
710 
711  fss = fsh_slice_get (fsh, slice_index);
712  c = fsh_try_alloc_chunk (fsh, fss, chunk_size);
713 
714  return c;
715 }
716 
717 static void
720 {
721  u32 n_collect = 0, fl_index;
722  svm_fifo_chunk_t *next;
723 
724  while (c)
725  {
726  CLIB_MEM_UNPOISON (c, sizeof (*c));
727  next = c->next;
728  fl_index = fs_freelist_for_size (c->length);
729  fss_chunk_free_list_push (fss, fl_index, c);
730  n_collect += fs_freelist_index_to_size (fl_index);
731  c = next;
732  }
733 
734  fss_fl_chunk_bytes_add (fss, n_collect);
735  fsh_cached_bytes_add (fsh, n_collect);
736 }
737 
738 void
741 {
743  fss = fsh_slice_get (fsh, slice_index);
744  fsh_slice_collect_chunks (fsh, fss, c);
745 }
746 
747 /**
748  * Allocate fifo in fifo segment
749  */
750 svm_fifo_t *
752  u32 data_bytes, fifo_segment_ftype_t ftype)
753 {
754  fifo_segment_header_t *fsh = fs->h;
756  svm_fifo_t *f = 0;
757 
758  ASSERT (slice_index < fs->n_slices);
759 
760  if (PREDICT_FALSE (data_bytes > 1 << fsh->max_log2_chunk_size))
761  return 0;
762 
763  fss = fsh_slice_get (fsh, slice_index);
764  f = fs_try_alloc_fifo (fsh, fss, data_bytes);
765  if (!f)
766  goto done;
767 
768  f->slice_index = slice_index;
769 
770  svm_fifo_init (f, data_bytes);
771 
772  /* If rx fifo type add to active fifos list. When cleaning up segment,
773  * we need a list of active sessions that should be disconnected. Since
774  * both rx and tx fifos keep pointers to the session, it's enough to track
775  * only one. */
776  if (ftype == FIFO_SEGMENT_RX_FIFO)
777  {
778  fss_fifo_add_active_list (fss, f);
779  f->flags |= SVM_FIFO_F_LL_TRACKED;
780  }
781 
782  fsh_active_fifos_update (fsh, 1);
783  fss->virtual_mem += svm_fifo_size (f);
784 
785 done:
786  return (f);
787 }
788 
789 /**
790  * Free fifo allocated in fifo segment
791  */
792 void
794 {
795  fifo_segment_header_t *fsh = fs->h;
797 
798  ASSERT (f->refcnt > 0);
799 
800  if (--f->refcnt > 0)
801  return;
802 
803  fss = fsh_slice_get (fsh, f->slice_index);
804 
805  /* Remove from active list. Only rx fifos are tracked */
806  if (f->flags & SVM_FIFO_F_LL_TRACKED)
807  {
808  fss_fifo_del_active_list (fss, f);
809  f->flags &= ~SVM_FIFO_F_LL_TRACKED;
810  }
811 
812  /* Free fifo chunks */
813  fsh_slice_collect_chunks (fsh, fss, f->start_chunk);
814 
815  f->start_chunk = f->end_chunk = 0;
816  f->head_chunk = f->tail_chunk = f->ooo_enq = f->ooo_deq = 0;
817 
818  /* not allocated on segment heap */
821 
822  if (CLIB_DEBUG)
823  {
824  f->master_session_index = ~0;
825  f->master_thread_index = ~0;
826  }
827 
828  fss->virtual_mem -= svm_fifo_size (f);
829 
830  /* Add to free list */
831  f->next = fss->free_fifos;
832  f->prev = 0;
833  fss->free_fifos = f;
834 
835  fsh_active_fifos_update (fsh, -1);
836 }
837 
838 void
840 {
843  u32 fl_index;
844 
845  ASSERT (f->refcnt == 1);
846 
847  fss = fsh_slice_get (fs->h, f->slice_index);
848  fss->virtual_mem -= svm_fifo_size (f);
849  if (f->flags & SVM_FIFO_F_LL_TRACKED)
850  fss_fifo_del_active_list (fss, f);
851 
852  c = f->start_chunk;
853  while (c)
854  {
855  fl_index = fs_freelist_for_size (c->length);
856  clib_atomic_fetch_sub_rel (&fss->num_chunks[fl_index], 1);
857  c = c->next;
858  }
859 }
860 
861 void
863  u32 slice_index)
864 {
867  u32 fl_index;
868 
869  f->slice_index = slice_index;
870  fss = fsh_slice_get (fs->h, f->slice_index);
871  fss->virtual_mem += svm_fifo_size (f);
872  if (f->flags & SVM_FIFO_F_LL_TRACKED)
873  fss_fifo_add_active_list (fss, f);
874 
875  c = f->start_chunk;
876  while (c)
877  {
878  fl_index = fs_freelist_for_size (c->length);
879  clib_atomic_fetch_add_rel (&fss->num_chunks[fl_index], 1);
880  c = c->next;
881  }
882 }
883 
884 int
886  u32 batch_size)
887 {
888  fifo_segment_header_t *fsh = fs->h;
890 
891  fss = fsh_slice_get (fsh, slice_index);
892  return fsh_try_alloc_fifo_hdr_batch (fsh, fss, batch_size);
893 }
894 
895 int
897  u32 chunk_size, u32 batch_size)
898 {
899  fifo_segment_header_t *fsh = fs->h;
901  u32 fl_index;
902 
903  if (!fs_chunk_size_is_valid (fsh, chunk_size))
904  {
905  clib_warning ("chunk size out of range %d", chunk_size);
906  return -1;
907  }
908 
909  fl_index = fs_freelist_for_size (chunk_size);
910  fss = fsh_slice_get (fsh, slice_index);
911 
912  return fsh_try_alloc_chunk_batch (fsh, fss, fl_index, batch_size);
913 }
914 
915 /**
916  * Pre-allocates fifo pairs in fifo segment
917  */
918 void
920  u32 rx_fifo_size, u32 tx_fifo_size,
921  u32 * n_fifo_pairs)
922 {
923  u32 rx_rounded_data_size, tx_rounded_data_size, pair_size, pairs_to_alloc;
924  u32 hdrs, pairs_per_slice, alloc_now;
925  fifo_segment_header_t *fsh = fs->h;
926  int rx_fl_index, tx_fl_index, i;
928  uword space_available;
929 
930  /* Parameter check */
931  if (rx_fifo_size == 0 || tx_fifo_size == 0 || *n_fifo_pairs == 0)
932  return;
933 
934  if (!fs_chunk_size_is_valid (fsh, rx_fifo_size))
935  {
936  clib_warning ("rx fifo_size out of range %d", rx_fifo_size);
937  return;
938  }
939 
940  if (!fs_chunk_size_is_valid (fsh, tx_fifo_size))
941  {
942  clib_warning ("tx fifo_size out of range %d", tx_fifo_size);
943  return;
944  }
945 
946  rx_rounded_data_size = (1 << (max_log2 (rx_fifo_size)));
947  rx_fl_index = fs_freelist_for_size (rx_fifo_size);
948  tx_rounded_data_size = (1 << (max_log2 (tx_fifo_size)));
949  tx_fl_index = fs_freelist_for_size (tx_fifo_size);
950 
951  hdrs = sizeof (svm_fifo_t) + sizeof (svm_fifo_chunk_t);
952 
953  /* Calculate space requirements */
954  pair_size = 2 * hdrs + rx_rounded_data_size + tx_rounded_data_size;
955  space_available = fsh_free_space (fsh);
956  pairs_to_alloc = space_available / pair_size;
957  pairs_to_alloc = clib_min (pairs_to_alloc, *n_fifo_pairs);
958  pairs_per_slice = pairs_to_alloc / fs->n_slices;
959  pairs_per_slice += pairs_to_alloc % fs->n_slices ? 1 : 0;
960 
961  if (!pairs_per_slice)
962  return;
963 
964  for (i = 0; i < fs->n_slices; i++)
965  {
966  alloc_now = clib_min (pairs_per_slice, *n_fifo_pairs);
967  if (0 == alloc_now)
968  break;
969 
970  fss = fsh_slice_get (fsh, i);
971  if (fs_try_alloc_fifo_batch (fsh, fss, rx_fl_index, alloc_now))
972  clib_warning ("rx prealloc failed: pairs %u", alloc_now);
973  if (fs_try_alloc_fifo_batch (fsh, fss, tx_fl_index, alloc_now))
974  clib_warning ("tx prealloc failed: pairs %u", alloc_now);
975 
976  /* Account for the pairs allocated */
977  *n_fifo_pairs -= alloc_now;
978  }
979 }
980 
981 /**
982  * Get number of active fifos
983  */
984 u32
986 {
987  return fsh_n_active_fifos (fs->h);
988 }
989 
990 static u32
992 {
993  svm_fifo_t *f;
994  u32 count = 0;
995 
996  f = fss->free_fifos;
997  if (f == 0)
998  return 0;
999 
1000  while (f)
1001  {
1002  f = f->next;
1003  count++;
1004  }
1005  return count;
1006 }
1007 
1008 u32
1010 {
1011  fifo_segment_header_t *fsh = fs->h;
1012  fifo_segment_slice_t *fss;
1013  int slice_index;
1014  u32 count = 0;
1015 
1016  for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
1017  {
1018  fss = fsh_slice_get (fsh, slice_index);
1019  count += fs_slice_num_free_fifos (fss);
1020  }
1021  return count;
1022 }
1023 
1024 static u32
1026 {
1027  u32 count = 0, rounded_size, fl_index;
1029  int i;
1030 
1031  /* Count all free chunks? */
1032  if (size == ~0)
1033  {
1034  for (i = 0; i < vec_len (fss->free_chunks); i++)
1035  {
1036  c = fss->free_chunks[i];
1037  if (c == 0)
1038  continue;
1039 
1040  while (c)
1041  {
1042  c = c->next;
1043  count++;
1044  }
1045  }
1046  return count;
1047  }
1048 
1049  rounded_size = (1 << (max_log2 (size)));
1050  fl_index = fs_freelist_for_size (rounded_size);
1051 
1052  if (fl_index >= vec_len (fss->free_chunks))
1053  return 0;
1054 
1055  c = fss->free_chunks[fl_index];
1056  if (c == 0)
1057  return 0;
1058 
1059  while (c)
1060  {
1061  c = c->next;
1062  count++;
1063  }
1064  return count;
1065 }
1066 
1067 u32
1069 {
1070  fifo_segment_header_t *fsh = fs->h;
1071  fifo_segment_slice_t *fss;
1072  int slice_index;
1073  u32 count = 0;
1074 
1075  for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
1076  {
1077  fss = fsh_slice_get (fsh, slice_index);
1078  count += fs_slice_num_free_chunks (fss, size);
1079  }
1080  return count;
1081 }
1082 
1083 void
1085 {
1086  fsh_update_free_bytes (fs->h);
1087 }
1088 
1089 uword
1091 {
1092  return fs->ssvm.ssvm_size;
1093 }
1094 
1095 u8
1097 {
1098  return (fsh->flags & FIFO_SEGMENT_F_MEM_LIMIT) ? 1 : 0;
1099 }
1100 
1101 void
1103 {
1105 }
1106 
1107 uword
1109 {
1110  return fsh_n_free_bytes (fs->h);
1111 }
1112 
1113 uword
1115 {
1116  return fsh_n_cached_bytes (fs->h);
1117 }
1118 
1119 uword
1121 {
1122  return fsh_n_free_bytes (fs->h) + fsh_n_cached_bytes (fs->h);
1123 }
1124 
1125 uword
1127 {
1128  fifo_segment_header_t *fsh = fs->h;
1129  fifo_segment_slice_t *fss;
1130  uword n_bytes = 0;
1131  int slice_index;
1132 
1133  for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
1134  {
1135  fss = fsh_slice_get (fsh, slice_index);
1136  n_bytes += fss_fl_chunk_bytes (fss);
1137  }
1138 
1139  return n_bytes;
1140 }
1141 
1142 u8
1144 {
1145  return (fsh_n_active_fifos (fs->h) != 0);
1146 }
1147 
1148 svm_fifo_t *
1150 {
1151  fifo_segment_header_t *fsh = fs->h;
1152  fifo_segment_slice_t *fss;
1153 
1154  fss = fsh_slice_get (fsh, slice_index);
1155  return fss->fifos;
1156 }
1157 
1158 u8
1160 {
1161  uword size, in_use;
1162 
1163  size = fifo_segment_size (fs);
1164  in_use =
1166  return (in_use * 100) / size;
1167 }
1168 
1171 {
1172  if (!fsh->high_watermark || !fsh->low_watermark)
1173  return MEMORY_PRESSURE_NO_PRESSURE;
1174 
1175  /* once the no-memory is detected, the status continues
1176  * until memory usage gets below the high watermark
1177  */
1178  if (fsh_has_reached_mem_limit (fsh))
1179  {
1180  if (usage >= fsh->high_watermark)
1181  return MEMORY_PRESSURE_NO_MEMORY;
1182  else
1183  fsh_reset_mem_limit (fsh);
1184  }
1185 
1186  if (usage >= fsh->high_watermark)
1187  return MEMORY_PRESSURE_HIGH_PRESSURE;
1188 
1189  else if (usage >= fsh->low_watermark)
1190  return MEMORY_PRESSURE_LOW_PRESSURE;
1191 
1192  return MEMORY_PRESSURE_NO_PRESSURE;
1193 }
1194 
1197 {
1198  fifo_segment_header_t *fsh = fs->h;
1200 
1201  return fifo_segment_determine_status (fsh, usage);
1202 }
1203 
1204 u8 *
1205 format_fifo_segment_type (u8 * s, va_list * args)
1206 {
1207  fifo_segment_t *sp;
1208  sp = va_arg (*args, fifo_segment_t *);
1209  ssvm_segment_type_t st = ssvm_type (&sp->ssvm);
1210 
1211  if (st == SSVM_SEGMENT_PRIVATE)
1212  s = format (s, "%s", "private");
1213  else if (st == SSVM_SEGMENT_MEMFD)
1214  s = format (s, "%s", "memfd");
1215  else if (st == SSVM_SEGMENT_SHM)
1216  s = format (s, "%s", "shm");
1217  else
1218  s = format (s, "%s", "unknown");
1219  return s;
1220 }
1221 
1222 /**
1223  * Segment format function
1224  */
1225 u8 *
1226 format_fifo_segment (u8 * s, va_list * args)
1227 {
1228  u32 count, indent, active_fifos, free_fifos;
1229  fifo_segment_t *fs = va_arg (*args, fifo_segment_t *);
1230  int verbose __attribute__ ((unused)) = va_arg (*args, int);
1231  uword est_chunk_bytes, est_free_seg_bytes, free_chunks;
1232  uword chunk_bytes = 0, free_seg_bytes, chunk_size;
1233  uword tracked_cached_bytes;
1234  uword fifo_hdr = 0, reserved;
1235  fifo_segment_header_t *fsh;
1236  fifo_segment_slice_t *fss;
1238  u32 slice_index;
1239  char *address;
1240  size_t size;
1241  int i;
1242  uword allocated, in_use, virt;
1243  f64 usage;
1245 
1246  indent = format_get_indent (s) + 2;
1247 
1248  if (fs == 0)
1249  {
1250  s = format (s, "%-20s%10s%15s%15s%15s%15s", "Name", "Type",
1251  "HeapSize (M)", "ActiveFifos", "FreeFifos", "Address");
1252  return s;
1253  }
1254 
1255  fifo_segment_info (fs, &address, &size);
1256  active_fifos = fifo_segment_num_fifos (fs);
1257  free_fifos = fifo_segment_num_free_fifos (fs);
1258 
1259  s = format (s, "%-20v%10U%15llu%15u%15u%15llx", ssvm_name (&fs->ssvm),
1260  format_fifo_segment_type, fs, size >> 20ULL, active_fifos,
1261  free_fifos, address);
1262 
1263  if (!verbose)
1264  return s;
1265 
1266  fsh = fs->h;
1267 
1268  free_chunks = fifo_segment_num_free_chunks (fs, ~0);
1269  if (free_chunks)
1270  s =
1271  format (s, "\n\n%UFree/Allocated chunks by size:\n", format_white_space,
1272  indent + 2);
1273  else
1274  s = format (s, "\n");
1275 
1276  for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
1277  {
1278  fss = fsh_slice_get (fsh, slice_index);
1279  for (i = 0; i < vec_len (fss->free_chunks); i++)
1280  {
1281  c = fss->free_chunks[i];
1282  if (c == 0 && fss->num_chunks[i] == 0)
1283  continue;
1284  count = 0;
1285  while (c)
1286  {
1287  c = c->next;
1288  count++;
1289  }
1290 
1291  chunk_size = fs_freelist_index_to_size (i);
1292  s = format (s, "%U%-5u kB: %u/%u\n", format_white_space, indent + 2,
1293  chunk_size >> 10, count, fss->num_chunks[i]);
1294 
1295  chunk_bytes += count * chunk_size;
1296  }
1297  }
1298 
1299  fifo_hdr = free_fifos * sizeof (svm_fifo_t);
1300  est_chunk_bytes = fifo_segment_fl_chunk_bytes (fs);
1301  est_free_seg_bytes = fifo_segment_free_bytes (fs);
1303  free_seg_bytes = fifo_segment_free_bytes (fs);
1304  tracked_cached_bytes = fifo_segment_cached_bytes (fs);
1305  allocated = fifo_segment_size (fs);
1306  in_use = fifo_segment_size (fs) - est_free_seg_bytes - tracked_cached_bytes;
1307  usage = (100.0 * in_use) / allocated;
1308  mem_st = fifo_segment_get_mem_status (fs);
1309  virt = fsh_virtual_mem (fsh);
1310  reserved = fsh->n_reserved_bytes;
1311 
1312  s = format (s, "\n%Useg free bytes: %U (%lu) estimated: %U (%lu) reserved:"
1313  " %U (%lu)\n", format_white_space, indent + 2,
1314  format_memory_size, free_seg_bytes, free_seg_bytes,
1315  format_memory_size, est_free_seg_bytes, est_free_seg_bytes,
1316  format_memory_size, reserved, reserved);
1317  s = format (s, "%Uchunk free bytes: %U (%lu) estimated: %U (%lu) tracked:"
1318  " %U (%lu)\n", format_white_space, indent + 2,
1319  format_memory_size, chunk_bytes, chunk_bytes,
1320  format_memory_size, est_chunk_bytes, est_chunk_bytes,
1321  format_memory_size, tracked_cached_bytes, tracked_cached_bytes);
1322  s = format (s, "%Ufifo active: %u hdr free bytes: %U (%u) \n",
1323  format_white_space, indent + 2, fsh->n_active_fifos,
1324  format_memory_size, fifo_hdr, fifo_hdr);
1325  s = format (s, "%Usegment usage: %.2f%% (%U / %U) virt: %U status: %s\n",
1326  format_white_space, indent + 2, usage, format_memory_size,
1327  in_use, format_memory_size, allocated, format_memory_size, virt,
1329  s = format (s, "\n");
1330 
1331  return s;
1332 }
1333 
1334 /*
1335  * fd.io coding-style-patch-verification: ON
1336  *
1337  * Local Variables:
1338  * eval: (c-set-style "gnu")
1339  * End:
1340  */
u32 length
length of chunk in bytes
Definition: fifo_types.h:32
void fifo_segment_info(fifo_segment_t *seg, char **address, size_t *size)
Definition: fifo_segment.c:375
u8 low_watermark
Memory pressure watermark low.
Definition: fifo_types.h:125
#define FIFO_SEGMENT_MIN_LOG2_FIFO_SIZE
4kB min fifo size
Definition: fifo_segment.h:30
fifo_segment_header_t * h
fifo segment data
Definition: fifo_segment.h:69
static void fsh_cached_bytes_sub(fifo_segment_header_t *fsh, uword size)
Definition: fifo_segment.c:72
#define CLIB_MEM_UNPOISON(a, s)
Definition: sanitizer.h:47
#define clib_min(x, y)
Definition: clib.h:328
static void fsh_check_mem(fifo_segment_header_t *fsh)
Definition: fifo_segment.c:120
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:121
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:82
uword requested_va
Definition: ssvm.h:85
static uword fsh_n_free_bytes(fifo_segment_header_t *fsh)
Definition: fifo_segment.c:53
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:222
a
Definition: bitmap.h:544
uword ssvm_size
Definition: ssvm.h:84
svm_fifo_t * fifo_segment_get_slice_fifo_list(fifo_segment_t *fs, u32 slice_index)
static void fss_fifo_del_active_list(fifo_segment_slice_t *fss, svm_fifo_t *f)
Definition: fifo_segment.c:198
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:254
void svm_fifo_free_chunk_lookup(svm_fifo_t *f)
Cleanup fifo chunk lookup rb tree.
Definition: svm_fifo.c:755
static u32 svm_fifo_size(svm_fifo_t *f)
Definition: svm_fifo.h:692
volatile u32 ready
Definition: ssvm.h:76
ssvm_shared_header_t * ssvm_sh
Fixed array of slices.
Definition: fifo_types.h:116
uword fifo_segment_cached_bytes(fifo_segment_t *fs)
Fifo segment number of cached bytes.
unsigned long u64
Definition: types.h:89
u8 pct_first_alloc
Pct of fifo size to alloc.
Definition: fifo_types.h:126
u8 n_slices
Number of slices.
Definition: fifo_types.h:123
void fifo_segment_delete(fifo_segment_main_t *sm, fifo_segment_t *s)
Definition: fifo_segment.c:355
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
fifo_segment_mem_status_t
Definition: fifo_segment.h:48
svm_fifo_t * fifo_segment_alloc_fifo_w_slice(fifo_segment_t *fs, u32 slice_index, u32 data_bytes, fifo_segment_ftype_t ftype)
Allocate fifo in fifo segment.
Definition: fifo_segment.c:751
u8 fifo_segment_get_mem_usage(fifo_segment_t *fs)
#define foreach_segment_mem_status
Definition: fifo_segment.h:42
u32 max_log2_chunk_size
Max log2(chunk size) for fs.
Definition: fifo_types.h:121
void * opaque[SSVM_N_OPAQUE]
Definition: ssvm.h:73
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
svm_fifo_chunk_t * fsh_alloc_chunk(fifo_segment_header_t *fsh, u32 slice_index, u32 chunk_size)
Allocate chunks in fifo segment.
Definition: fifo_segment.c:706
void svm_fifo_init(svm_fifo_t *f, u32 size)
Initialize fifo.
Definition: svm_fifo.c:370
static void usage(void)
Definition: health_check.c:14
static u32 format_get_indent(u8 *s)
Definition: format.h:72
static int fsh_try_alloc_fifo_hdr_batch(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 batch_size)
Definition: fifo_segment.c:479
void fsh_virtual_mem_update(fifo_segment_header_t *fsh, u32 slice_index, int n_bytes)
Definition: fifo_segment.c:112
ssvm_shared_header_t * sh
Definition: ssvm.h:83
static void fss_chunk_free_list_push_list(fifo_segment_slice_t *fss, u32 fl_index, svm_fifo_chunk_t *head, svm_fifo_chunk_t *tail)
Definition: fifo_segment.c:153
static u32 fs_slice_num_free_fifos(fifo_segment_slice_t *fss)
Definition: fifo_segment.c:991
static u32 fs_freelist_index_to_size(u32 fl_index)
Definition: fifo_segment.c:398
static int fs_try_alloc_fifo_batch(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 fl_index, u32 batch_size)
Definition: fifo_segment.c:567
unsigned char u8
Definition: types.h:56
u32 fifo_segment_num_free_fifos(fifo_segment_t *fs)
void ssvm_delete(ssvm_private_t *ssvm)
Definition: ssvm.c:445
static void fsh_update_free_bytes(fifo_segment_header_t *fsh)
Definition: fifo_segment.c:60
double f64
Definition: types.h:142
uword next_baseva
Where to put the next one.
Definition: fifo_segment.h:76
u32 fifo_segment_num_free_chunks(fifo_segment_t *fs, u32 size)
Find number of free chunks of given size.
fifo_segment_t * fifo_segment_get_segment(fifo_segment_main_t *sm, u32 segment_index)
Definition: fifo_segment.c:369
static fifo_segment_slice_t * fsh_slice_get(fifo_segment_header_t *fsh, u32 slice_index)
Definition: fifo_segment.c:19
u8 * ssvm_name(const ssvm_private_t *ssvm)
Definition: ssvm.c:457
int ssvm_server_init(ssvm_private_t *ssvm, ssvm_segment_type_t type)
Definition: ssvm.c:433
enum ssvm_segment_type_ ssvm_segment_type_t
u32 n_active_fifos
Number of active fifos.
Definition: fifo_types.h:119
uword virtual_mem
Slice sum of all fifo sizes.
Definition: fifo_types.h:109
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
description fragment has unexpected format
Definition: map.api:433
static u32 fs_freelist_for_size(u32 size)
Definition: fifo_segment.c:390
static int fs_chunk_size_is_valid(fifo_segment_header_t *fsh, u32 size)
Definition: fifo_segment.c:404
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:113
uword n_fl_chunk_bytes
Chunk bytes on freelist.
Definition: fifo_types.h:108
static void * ssvm_push_heap(ssvm_shared_header_t *sh)
Definition: ssvm.h:143
static svm_fifo_t * fsh_try_alloc_fifo_hdr(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss)
Definition: fifo_segment.c:577
unsigned int u32
Definition: types.h:88
int attach_timeout
shm segments attach timeout (sec)
Definition: ssvm.h:94
uword n_cached_bytes
Cached bytes.
Definition: fifo_types.h:118
static void ssvm_pop_heap(void *oldheap)
Definition: ssvm.h:151
char * segment_name
segment name
Definition: fifo_segment.h:85
u8 high_watermark
Memory pressure watermark high.
Definition: fifo_types.h:124
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:65
fifo_segment_mem_status_t fifo_segment_get_mem_status(fifo_segment_t *fs)
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:325
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:919
int fifo_segment_prealloc_fifo_chunks(fifo_segment_t *fs, u32 slice_index, u32 chunk_size, u32 batch_size)
Try to preallocate fifo chunks on segment.
Definition: fifo_segment.c:896
u8 * format_fifo_segment_type(u8 *s, va_list *args)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
static void fss_fifo_add_active_list(fifo_segment_slice_t *fss, svm_fifo_t *f)
Definition: fifo_segment.c:187
struct svm_fifo_chunk_ * next
pointer to next chunk in linked-lists
Definition: fifo_types.h:33
void fsh_collect_chunks(fifo_segment_header_t *fsh, u32 slice_index, svm_fifo_chunk_t *c)
Return chunks to fifo segment.
Definition: fifo_segment.c:739
static uword fsh_free_space(fifo_segment_header_t *fsh)
Fifo segment free space.
Definition: fifo_segment.c:41
svm_fifo_t * free_fifos
Freelists by fifo size.
Definition: fifo_types.h:105
u32 n_reserved_bytes
Bytes not to be allocated.
Definition: fifo_types.h:120
static void fss_fl_chunk_bytes_sub(fifo_segment_slice_t *fss, uword size)
Definition: fifo_segment.c:224
u8 * format_fifo_segment(u8 *s, va_list *args)
Segment format function.
u32 size
Definition: vhost_user.h:106
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
static uword fss_fl_chunk_bytes(fifo_segment_slice_t *fss)
Definition: fifo_segment.c:212
fifo_segment_slice_t * slices
Definition: fifo_types.h:115
#define PREDICT_FALSE(x)
Definition: clib.h:121
#define clib_atomic_fetch_add_rel(a, b)
Definition: atomics.h:54
clib_spinlock_t chunk_lock
Definition: fifo_types.h:110
static u32 fsh_n_active_fifos(fifo_segment_header_t *fsh)
Definition: fifo_segment.c:91
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:291
u32 * num_chunks
Allocated chunks by chunk size.
Definition: fifo_types.h:107
void fifo_segment_detach_fifo(fifo_segment_t *fs, svm_fifo_t *f)
Definition: fifo_segment.c:839
#define FIFO_SEGMENT_MIN_FIFO_SIZE
4kB min fifo size
Definition: fifo_segment.h:31
svm_fifo_t * fifos
Linked list of active RX fifos.
Definition: fifo_types.h:104
static int fsh_try_alloc_chunk_batch(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 fl_index, u32 batch_size)
Definition: fifo_segment.c:518
u32 segment_size
size of the segment
Definition: fifo_segment.h:83
ssvm_private_t ssvm
ssvm segment data
Definition: fifo_segment.h:68
uword clib_mem_get_heap_free_space(clib_mem_heap_t *heap)
Definition: mem_dlmalloc.c:576
svmdb_client_t * c
#define clib_atomic_fetch_add_relax(a, b)
Definition: atomics.h:57
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static uword fsh_n_cached_bytes(fifo_segment_header_t *fsh)
Definition: fifo_segment.c:78
void fifo_segment_main_init(fifo_segment_main_t *sm, u64 baseva, u32 timeout_in_seconds)
Definition: fifo_segment.c:382
#define clib_warning(format, args...)
Definition: error.h:59
uword fifo_segment_fl_chunk_bytes(fifo_segment_t *fs)
Number of bytes on chunk free lists.
u32 my_pid
Definition: ssvm.h:86
u32 start_byte
chunk start byte
Definition: fifo_types.h:31
static void fss_chunk_free_list_push(fifo_segment_slice_t *fss, u32 fl_index, svm_fifo_chunk_t *c)
Definition: fifo_segment.c:143
int memfd_fd
fd for memfd segments
Definition: fifo_segment.h:84
#define clib_atomic_fetch_sub_relax(a, b)
Definition: atomics.h:58
int is_server
Definition: ssvm.h:89
int fd
memfd segments
Definition: ssvm.h:93
static void fsh_cached_bytes_add(fifo_segment_header_t *fsh, uword size)
Definition: fifo_segment.c:66
u8 n_slices
number of fifo segment slices
Definition: fifo_segment.h:70
#define clib_atomic_load_relax_n(a)
Definition: atomics.h:47
void fsh_reset_mem_limit(fifo_segment_header_t *fsh)
Fifo segment reset mem limit flag.
u32 fifo_segment_index(fifo_segment_main_t *sm, fifo_segment_t *s)
Definition: fifo_segment.c:363
#define ASSERT(truth)
int ssvm_client_init(ssvm_private_t *ssvm, ssvm_segment_type_t type)
Definition: ssvm.c:439
manual_print typedef address
Definition: ip_types.api:96
static svm_fifo_chunk_t * fss_chunk_free_list_pop(fifo_segment_slice_t *fss, u32 fl_index)
Definition: fifo_segment.c:164
void fifo_segment_free_fifo(fifo_segment_t *fs, svm_fifo_t *f)
Free fifo allocated in fifo segment.
Definition: fifo_segment.c:793
fifo_segment_t * segments
pool of fifo segments
Definition: fifo_segment.h:75
fifo_segment_ftype_t
Definition: fifo_segment.h:22
#define FIFO_SEGMENT_MAX_FIFO_SIZE
2GB max fifo size
Definition: fifo_segment.h:32
static uword fsh_virtual_mem(fifo_segment_header_t *fsh)
Definition: fifo_segment.c:97
static u32 fs_slice_num_free_chunks(fifo_segment_slice_t *fss, u32 size)
static void fss_fl_chunk_bytes_add(fifo_segment_slice_t *fss, uword size)
Definition: fifo_segment.c:218
static svm_fifo_t * fs_try_alloc_fifo(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 data_bytes)
Try to allocate new fifo.
Definition: fifo_segment.c:670
static void * clib_mem_alloc(uword size)
Definition: mem.h:253
uword fifo_segment_size(fifo_segment_t *fs)
Fifo segment allocated size.
#define clib_atomic_store_rel_n(a, b)
Definition: atomics.h:49
#define clib_max(x, y)
Definition: clib.h:321
u8 * name
Definition: ssvm.h:87
#define clib_atomic_fetch_sub_rel(a, b)
Definition: atomics.h:55
static void fsh_slice_collect_chunks(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, svm_fifo_chunk_t *c)
Definition: fifo_segment.c:718
ssvm_segment_type_t segment_type
type of segment requested
Definition: fifo_segment.h:82
static int fss_chunk_fl_index_is_valid(fifo_segment_slice_t *fss, u32 fl_index)
Definition: fifo_segment.c:137
u32 fifo_segment_num_fifos(fifo_segment_t *fs)
Get number of active fifos.
Definition: fifo_segment.c:985
uword ssvm_size
Definition: ssvm.h:69
static void fsh_free_bytes_sub(fifo_segment_header_t *fsh, int size)
Definition: fifo_segment.c:47
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static uword max_log2(uword x)
Definition: clib.h:209
u8 flags
Segment flags.
Definition: fifo_types.h:122
u64 uword
Definition: types.h:112
int fifo_segment_prealloc_fifo_hdrs(fifo_segment_t *fs, u32 slice_index, u32 batch_size)
Try to preallocate fifo headers.
Definition: fifo_segment.c:885
void fifo_segment_update_free_bytes(fifo_segment_t *fs)
Update fifo segment free bytes estimate.
u8 fsh_has_reached_mem_limit(fifo_segment_header_t *fsh)
Fifo segment has reached mem limit.
u8 fifo_segment_has_fifos(fifo_segment_t *fs)
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:261
u8 count
Definition: dhcp.api:208
static char * fifo_segment_mem_status_strings[]
Definition: fifo_segment.c:24
#define FIFO_SEGMENT_ALLOC_BATCH_SIZE
Definition: fifo_segment.h:33
void fifo_segment_attach_fifo(fifo_segment_t *fs, svm_fifo_t *f, u32 slice_index)
Definition: fifo_segment.c:862
uword fifo_segment_available_bytes(fifo_segment_t *fs)
u32 timeout_in_seconds
Time to wait during attach.
Definition: fifo_segment.h:77
#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:556
#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:233
static void fsh_active_fifos_update(fifo_segment_header_t *fsh, int inc)
Definition: fifo_segment.c:85
struct _svm_fifo svm_fifo_t
static svm_fifo_chunk_t * fsh_try_alloc_chunk(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 data_bytes)
Definition: fifo_segment.c:596
fifo_segment_mem_status_t fifo_segment_determine_status(fifo_segment_header_t *fsh, u8 usage)
svm_fifo_chunk_t * fs_try_alloc_multi_chunk(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 data_bytes)
Definition: fifo_segment.c:415
uword fifo_segment_free_bytes(fifo_segment_t *fs)
Fifo segment estimate of number of free bytes.
svm_fifo_chunk_t ** free_chunks
Freelists by chunk size.
Definition: fifo_types.h:106
uword n_free_bytes
Segment free bytes.
Definition: fifo_types.h:117
u32 * new_segment_indices
return vec of new seg indices
Definition: fifo_segment.h:86
ssvm_segment_type_t ssvm_type(const ssvm_private_t *ssvm)
Definition: ssvm.c:451