21 return &fsh->
slices[slice_index];
25 #define _(sym,str) str, 46 return dlminfo.fordblks;
253 _vec_len (fs) =
vec_len (fs) - 1;
293 u32 timeout_in_seconds)
340 memset (f, 0,
sizeof (*f));
352 u32 fl_index, fl_size, n_alloc = 0, req_bytes = data_bytes;
370 req_bytes -=
clib_min (fl_size, req_bytes);
402 fl_size = fl_size >> 1;
417 u32 fl_index, fl_size, n_alloc = 0;
431 memset (f, 0,
sizeof (*f));
456 data_bytes -=
clib_min (fl_size, data_bytes);
474 data_bytes += fl_size;
491 fl_size = fl_size >> 1;
495 f->start_chunk =
first;
505 u32 fl_index,
u32 batch_size)
507 u32 rounded_data_size;
515 size = (
uword) (
sizeof (*c) + rounded_data_size) * batch_size;
528 for (i = 0; i < batch_size; i++)
532 c->
length = rounded_data_size;
537 cmem +=
sizeof (*c) + rounded_data_size;
551 u32 fl_index,
u32 batch_size)
553 u32 hdrs, rounded_data_size;
562 hdrs =
sizeof (*f) +
sizeof (*c);
563 size = (
uword) (hdrs + rounded_data_size) * batch_size;
576 for (i = 0; i < batch_size; i++)
579 memset (f, 0,
sizeof (*f));
586 for (i = 0; i < batch_size; i++)
590 c->
length = rounded_data_size;
619 u32 fifo_sz, fl_index;
643 fifo_sz += 1 <<
max_log2 (min_size);
665 if (fifo_sz <= n_free_bytes)
679 fifo_sz =
clib_min (fifo_sz, data_bytes);
680 if (fifo_sz <= fss->n_fl_chunk_bytes)
688 f->size = data_bytes;
725 if (chunk_size <= n_free)
741 if (chunk_size <= fss->n_fl_chunk_bytes)
753 if (chunk_size <= fss->n_fl_chunk_bytes + n_free)
758 batch =
clib_min (batch + 1, n_free / min_size);
818 fss->
fifos->prev = f;
819 f->next = fss->
fifos;
830 f->prev->next = f->next;
832 fss->
fifos = f->next;
834 f->next->prev = f->prev;
849 ASSERT (slice_index < fs->n_slices);
859 f->slice_index = slice_index;
912 f->start_chunk = f->end_chunk = 0;
913 f->head_chunk = f->tail_chunk = f->ooo_enq = f->ooo_deq = 0;
921 f->master_session_index = ~0;
922 f->master_thread_index = ~0;
966 f->slice_index = slice_index;
994 size = (
uword) (
sizeof (*f)) * batch_size;
1007 for (i = 0; i < batch_size; i++)
1010 memset (f, 0,
sizeof (*f));
1013 fmem +=
sizeof (*f);
1023 u32 chunk_size,
u32 batch_size)
1026 u32 rounded_data_size, fl_index;
1036 clib_warning (
"chunk size out of range %d", chunk_size);
1042 size = (
uword) (
sizeof (*c) + rounded_data_size) * batch_size;
1057 for (i = 0; i < batch_size; i++)
1061 c->
length = rounded_data_size;
1064 cmem +=
sizeof (*c) + rounded_data_size;
1080 u32 rx_fifo_size,
u32 tx_fifo_size,
1083 u32 rx_rounded_data_size, tx_rounded_data_size, pair_size, pairs_to_alloc;
1084 u32 hdrs, pairs_per_slice, alloc_now;
1086 int rx_fl_index, tx_fl_index,
i;
1088 uword space_available;
1091 if (rx_fifo_size == 0 || tx_fifo_size == 0 || *n_fifo_pairs == 0)
1096 clib_warning (
"rx fifo_size out of range %d", rx_fifo_size);
1102 clib_warning (
"tx fifo_size out of range %d", tx_fifo_size);
1106 rx_rounded_data_size = (1 << (
max_log2 (rx_fifo_size)));
1108 tx_rounded_data_size = (1 << (
max_log2 (tx_fifo_size)));
1114 pair_size = 2 * hdrs + rx_rounded_data_size + tx_rounded_data_size;
1116 pairs_to_alloc = space_available / pair_size;
1117 pairs_to_alloc =
clib_min (pairs_to_alloc, *n_fifo_pairs);
1118 pairs_per_slice = pairs_to_alloc / fs->
n_slices;
1119 pairs_per_slice += pairs_to_alloc % fs->
n_slices ? 1 : 0;
1121 if (!pairs_per_slice)
1127 alloc_now =
clib_min (pairs_per_slice, *n_fifo_pairs);
1129 clib_warning (
"rx prealloc failed: pairs %u", alloc_now);
1131 clib_warning (
"tx prealloc failed: pairs %u", alloc_now);
1134 *n_fifo_pairs -= alloc_now;
1173 for (slice_index = 0; slice_index < fs->
n_slices; slice_index++)
1184 u32 count = 0, rounded_size, fl_index;
1206 rounded_size = (1 << (
max_log2 (size)));
1232 for (slice_index = 0; slice_index < fs->
n_slices; slice_index++)
1290 for (slice_index = 0; slice_index < fs->
n_slices; slice_index++)
1323 return (in_use * 100) /
size;
1330 return MEMORY_PRESSURE_NO_PRESSURE;
1338 return MEMORY_PRESSURE_NO_MEMORY;
1344 return MEMORY_PRESSURE_HIGH_PRESSURE;
1347 return MEMORY_PRESSURE_LOW_PRESSURE;
1349 return MEMORY_PRESSURE_NO_PRESSURE;
1369 s =
format (s,
"%s",
"private-heap");
1371 s =
format (s,
"%s",
"memfd");
1373 s =
format (s,
"%s",
"shm");
1375 s =
format (s,
"%s",
"unknown");
1385 u32 count, indent, active_fifos, free_fifos;
1387 int verbose __attribute__ ((unused)) = va_arg (*args,
int);
1388 uword est_chunk_bytes, est_free_seg_bytes, free_chunks;
1389 uword chunk_bytes = 0, free_seg_bytes, chunk_size;
1390 uword tracked_cached_bytes;
1391 uword fifo_hdr = 0, reserved;
1399 uword allocated, in_use, virt;
1407 s =
format (s,
"%-15s%15s%15s%15s%15s%15s",
"Name",
"Type",
1408 "HeapSize (M)",
"ActiveFifos",
"FreeFifos",
"Address");
1418 free_fifos, address);
1433 for (slice_index = 0; slice_index < fs->
n_slices; slice_index++)
1450 chunk_size >> 10, count, fss->
num_chunks[i]);
1452 chunk_bytes += count * chunk_size;
1464 usage = (100.0 * in_use) / allocated;
1469 s =
format (s,
"\n%Useg free bytes: %U (%lu) estimated: %U (%lu) reserved:" 1474 s =
format (s,
"%Uchunk free bytes: %U (%lu) estimated: %U (%lu) tracked:" 1479 s =
format (s,
"%Ufifo active: %u hdr free bytes: %U (%u) \n",
1482 s =
format (s,
"%Usegment usage: %.2f%% (%U / %U) virt: %U status: %s\n",
u32 length
length of chunk in bytes
void fifo_segment_info(fifo_segment_t *seg, char **address, size_t *size)
#define FIFO_SEGMENT_MIN_LOG2_FIFO_SIZE
4kB min fifo size
fifo_segment_header_t * h
fifo segment data
#define CLIB_MEM_UNPOISON(a, s)
static void fsh_check_mem(fifo_segment_header_t *fsh)
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
static uword fsh_n_free_bytes(fifo_segment_header_t *fsh)
static void * clib_mem_alloc_aligned_at_offset(uword size, uword align, uword align_offset, int os_out_of_memory_on_failure)
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)
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
void svm_fifo_free_chunk_lookup(svm_fifo_t *f)
Cleanup fifo chunk lookup rb tree.
static u32 svm_fifo_size(svm_fifo_t *f)
uword fifo_segment_cached_bytes(fifo_segment_t *fs)
Fifo segment number of cached bytes.
void fifo_segment_delete(fifo_segment_main_t *sm, fifo_segment_t *s)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
fifo_segment_mem_status_t
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.
u8 fifo_segment_get_mem_usage(fifo_segment_t *fs)
#define foreach_segment_mem_status
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
svm_fifo_chunk_t * fsh_alloc_chunk(fifo_segment_header_t *fsh, u32 slice_index, u32 chunk_size)
Allocate chunks in fifo segment.
static heap_elt_t * last(heap_header_t *h)
void svm_fifo_init(svm_fifo_t *f, u32 size)
Initialize fifo.
#define RBTREE_TNIL_INDEX
void fsh_virtual_mem_update(fifo_segment_header_t *fsh, u32 slice_index, int n_bytes)
ssvm_shared_header_t * sh
DLMALLOC_EXPORT struct dlmallinfo mspace_mallinfo(mspace msp)
static u32 fs_slice_num_free_fifos(fifo_segment_slice_t *fss)
static u32 fs_freelist_index_to_size(u32 fl_index)
static int fs_try_alloc_fifo_batch(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 fl_index, u32 batch_size)
u32 fifo_segment_num_free_fifos(fifo_segment_t *fs)
void ssvm_delete(ssvm_private_t *ssvm)
static void fsh_update_free_bytes(fifo_segment_header_t *fsh)
uword next_baseva
Where to put the next one.
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)
static fifo_segment_slice_t * fsh_slice_get(fifo_segment_header_t *fsh, u32 slice_index)
u8 * ssvm_name(const ssvm_private_t *ssvm)
enum ssvm_segment_type_ ssvm_segment_type_t
uword virtual_mem
Slice sum of all fifo sizes.
svm_fifo_chunk_t * svm_fifo_chunk_alloc(u32 size)
Creates a fifo chunk in the current heap.
static u32 fs_freelist_for_size(u32 size)
static svm_fifo_t * fs_try_alloc_fifo_freelist(fifo_segment_slice_t *fss, u32 fl_index)
static int fs_chunk_size_is_valid(fifo_segment_header_t *fsh, u32 size)
void svm_fifo_free_ooo_data(svm_fifo_t *f)
Cleanup fifo ooo data.
static svm_fifo_t * fs_try_alloc_fifo_freelist_multi_chunk(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 data_bytes)
uword n_fl_chunk_bytes
Chunk bytes on freelist.
static void * ssvm_push_heap(ssvm_shared_header_t *sh)
static void fsh_cached_bytes_add(fifo_segment_header_t *fsh, int size)
int attach_timeout
shm segments attach timeout (sec)
static void fsh_cached_bytes_sub(fifo_segment_header_t *fsh, int size)
int ssvm_master_init(ssvm_private_t *ssvm, ssvm_segment_type_t type)
static void ssvm_pop_heap(void *oldheap)
char * segment_name
segment name
static void clib_spinlock_init(clib_spinlock_t *p)
fifo_segment_mem_status_t fifo_segment_get_mem_status(fifo_segment_t *fs)
static heap_elt_t * first(heap_header_t *h)
int fifo_segment_attach(fifo_segment_main_t *sm, fifo_segment_create_args_t *a)
Attach as slave to a fifo segment.
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.
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.
u8 * format_fifo_segment_type(u8 *s, va_list *args)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static void fss_fifo_add_active_list(fifo_segment_slice_t *fss, svm_fifo_t *f)
struct svm_fifo_chunk_ * next
pointer to next chunk in linked-lists
void fsh_collect_chunks(fifo_segment_header_t *fsh, u32 slice_index, svm_fifo_chunk_t *c)
Return chunks to fifo segment.
static uword fsh_free_space(fifo_segment_header_t *fsh)
Fifo segment free space.
svm_fifo_t * free_fifos
Freelists by fifo size.
u8 * format_fifo_segment(u8 *s, va_list *args)
Segment format function.
#define pool_put(P, E)
Free an object E in pool P.
#define clib_atomic_fetch_add_rel(a, b)
clib_spinlock_t chunk_lock
static u32 fsh_n_active_fifos(fifo_segment_header_t *fsh)
int fifo_segment_create(fifo_segment_main_t *sm, fifo_segment_create_args_t *a)
Create a fifo segment and initialize as master.
u32 * num_chunks
Allocated chunks by chunk size.
void fifo_segment_detach_fifo(fifo_segment_t *fs, svm_fifo_t *f)
#define FIFO_SEGMENT_MIN_FIFO_SIZE
4kB min fifo size
svm_fifo_t * fifos
Linked list of active RX fifos.
static int fsh_try_alloc_chunk_batch(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 fl_index, u32 batch_size)
u32 segment_size
size of the segment
ssvm_private_t ssvm
ssvm segment data
sll srl srl sll sra u16x4 i
static uword fsh_n_cached_bytes(fifo_segment_header_t *fsh)
void fifo_segment_main_init(fifo_segment_main_t *sm, u64 baseva, u32 timeout_in_seconds)
#define clib_warning(format, args...)
uword fifo_segment_fl_chunk_bytes(fifo_segment_t *fs)
Number of bytes on chunk free lists.
int ssvm_slave_init(ssvm_private_t *ssvm, ssvm_segment_type_t type)
u32 start_byte
chunk start byte
int memfd_fd
fd for memfd segments
u8 n_slices
number of fifo segment slices
#define clib_atomic_load_relax_n(a)
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)
static void * clib_mem_alloc_aligned_or_null(uword size, uword align)
manual_print typedef address
void fifo_segment_free_fifo(fifo_segment_t *fs, svm_fifo_t *f)
Free fifo allocated in fifo segment.
rb_node_index_t deq_rb_index
deq node index if chunk in rbtree
fifo_segment_t * segments
pool of fifo segments
#define FIFO_SEGMENT_MAX_FIFO_SIZE
2GB max fifo size
static uword fsh_virtual_mem(fifo_segment_header_t *fsh)
static u32 fs_slice_num_free_chunks(fifo_segment_slice_t *fss, u32 size)
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.
static void * clib_mem_alloc(uword size)
uword fifo_segment_size(fifo_segment_t *fs)
Fifo segment allocated size.
#define clib_atomic_store_rel_n(a, b)
#define clib_atomic_fetch_sub_rel(a, b)
static void fsh_slice_collect_chunks(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, svm_fifo_chunk_t *c)
ssvm_segment_type_t segment_type
type of segment requested
u32 fifo_segment_num_fifos(fifo_segment_t *fs)
Get number of active fifos.
static void fsh_free_bytes_sub(fifo_segment_header_t *fsh, int size)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static uword max_log2(uword x)
int fifo_segment_prealloc_fifo_hdrs(fifo_segment_t *fs, u32 slice_index, u32 batch_size)
Try to preallocate fifo headers.
rb_node_index_t enq_rb_index
enq node index if chunk in rbtree
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)
static char * fifo_segment_mem_status_strings[]
#define FIFO_SEGMENT_ALLOC_BATCH_SIZE
void fifo_segment_attach_fifo(fifo_segment_t *fs, svm_fifo_t *f, u32 slice_index)
uword fifo_segment_available_bytes(fifo_segment_t *fs)
u32 timeout_in_seconds
Time to wait during attach.
#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)
#define CLIB_CACHE_LINE_BYTES
int fifo_segment_init(fifo_segment_t *fs)
Initialize fifo segment shared header.
static void fsh_active_fifos_update(fifo_segment_header_t *fsh, int inc)
struct _svm_fifo svm_fifo_t
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)
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.
void svm_fifo_init_ooo_lookup(svm_fifo_t *f, u8 ooo_type)
Initialize rbtrees used for ooo lookups.
struct svm_fifo_chunk_ svm_fifo_chunk_t
u32 * new_segment_indices
return vec of new seg indices
svm_fifo_t * svm_fifo_alloc(u32 data_size_in_bytes)
Creates a fifo in the current heap.
ssvm_segment_type_t ssvm_type(const ssvm_private_t *ssvm)