21 return &fsh->
slices[slice_index];
25 #define _(sym,str) str, 191 fss->
fifos->prev = f;
192 f->next = fss->
fifos;
203 f->prev->next = f->next;
205 fss->
fifos = f->next;
207 f->next->prev = f->prev;
343 _vec_len (fs) =
vec_len (fs) - 1;
383 u32 timeout_in_seconds)
418 u32 fl_index, fl_size, n_alloc = 0, req_bytes = data_bytes;
435 req_bytes -=
clib_min (fl_size, req_bytes);
468 fl_size = fl_size >> 1;
490 size = (
uword)
sizeof (*f) * batch_size;
503 for (i = 0; i < batch_size; i++)
506 memset (f, 0,
sizeof (*f));
520 u32 fl_index,
u32 batch_size)
524 u32 rounded_data_size;
532 total_chunk_bytes = (
uword) batch_size *rounded_data_size;
533 size = (
uword) (
sizeof (*c) + rounded_data_size) * batch_size;
547 for (i = 0; i < batch_size; i++)
550 c->
length = rounded_data_size;
553 cmem +=
sizeof (*c) + rounded_data_size;
569 u32 fl_index,
u32 batch_size)
591 memset (f, 0,
sizeof (*f));
620 if (chunk_size <= n_free)
622 batch = chunk_size * batch <= n_free ? batch : 1;
645 batch =
clib_min (batch + 1, n_free / min_size);
673 u32 fl_index, min_size;
699 f->size = data_bytes;
721 u32 n_collect = 0, fl_index;
758 ASSERT (slice_index < fs->n_slices);
768 f->slice_index = slice_index;
815 f->start_chunk = f->end_chunk = 0;
816 f->head_chunk = f->tail_chunk = f->ooo_enq = f->ooo_deq = 0;
824 f->master_session_index = ~0;
825 f->master_thread_index = ~0;
869 f->slice_index = slice_index;
897 u32 chunk_size,
u32 batch_size)
905 clib_warning (
"chunk size out of range %d", chunk_size);
920 u32 rx_fifo_size,
u32 tx_fifo_size,
923 u32 rx_rounded_data_size, tx_rounded_data_size, pair_size, pairs_to_alloc;
924 u32 hdrs, pairs_per_slice, alloc_now;
926 int rx_fl_index, tx_fl_index,
i;
928 uword space_available;
931 if (rx_fifo_size == 0 || tx_fifo_size == 0 || *n_fifo_pairs == 0)
936 clib_warning (
"rx fifo_size out of range %d", rx_fifo_size);
942 clib_warning (
"tx fifo_size out of range %d", tx_fifo_size);
946 rx_rounded_data_size = (1 << (
max_log2 (rx_fifo_size)));
948 tx_rounded_data_size = (1 << (
max_log2 (tx_fifo_size)));
954 pair_size = 2 * hdrs + rx_rounded_data_size + tx_rounded_data_size;
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;
961 if (!pairs_per_slice)
966 alloc_now =
clib_min (pairs_per_slice, *n_fifo_pairs);
972 clib_warning (
"rx prealloc failed: pairs %u", alloc_now);
974 clib_warning (
"tx prealloc failed: pairs %u", alloc_now);
977 *n_fifo_pairs -= alloc_now;
1016 for (slice_index = 0; slice_index < fs->
n_slices; slice_index++)
1027 u32 count = 0, rounded_size, fl_index;
1049 rounded_size = (1 << (
max_log2 (size)));
1075 for (slice_index = 0; slice_index < fs->
n_slices; slice_index++)
1133 for (slice_index = 0; slice_index < fs->
n_slices; slice_index++)
1166 return (in_use * 100) /
size;
1173 return MEMORY_PRESSURE_NO_PRESSURE;
1181 return MEMORY_PRESSURE_NO_MEMORY;
1187 return MEMORY_PRESSURE_HIGH_PRESSURE;
1190 return MEMORY_PRESSURE_LOW_PRESSURE;
1192 return MEMORY_PRESSURE_NO_PRESSURE;
1212 s =
format (s,
"%s",
"private");
1214 s =
format (s,
"%s",
"memfd");
1216 s =
format (s,
"%s",
"shm");
1218 s =
format (s,
"%s",
"unknown");
1228 u32 count, indent, active_fifos, free_fifos;
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;
1242 uword allocated, in_use, virt;
1250 s =
format (s,
"%-20s%10s%15s%15s%15s%15s",
"Name",
"Type",
1251 "HeapSize (M)",
"ActiveFifos",
"FreeFifos",
"Address");
1261 free_fifos, address);
1276 for (slice_index = 0; slice_index < fs->
n_slices; slice_index++)
1293 chunk_size >> 10, count, fss->
num_chunks[i]);
1295 chunk_bytes += count * chunk_size;
1307 usage = (100.0 * in_use) / allocated;
1312 s =
format (s,
"\n%Useg free bytes: %U (%lu) estimated: %U (%lu) reserved:" 1317 s =
format (s,
"%Uchunk free bytes: %U (%lu) estimated: %U (%lu) tracked:" 1322 s =
format (s,
"%Ufifo active: %u hdr free bytes: %U (%u) \n",
1325 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
static void fsh_cached_bytes_sub(fifo_segment_header_t *fsh, uword size)
#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.
void svm_fifo_init(svm_fifo_t *f, u32 size)
Initialize fifo.
static int fsh_try_alloc_fifo_hdr_batch(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 batch_size)
void fsh_virtual_mem_update(fifo_segment_header_t *fsh, u32 slice_index, int n_bytes)
ssvm_shared_header_t * sh
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)
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)
int ssvm_server_init(ssvm_private_t *ssvm, ssvm_segment_type_t type)
enum ssvm_segment_type_ ssvm_segment_type_t
uword virtual_mem
Slice sum of all fifo sizes.
description fragment has unexpected format
static u32 fs_freelist_for_size(u32 size)
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.
uword n_fl_chunk_bytes
Chunk bytes on freelist.
static void * ssvm_push_heap(ssvm_shared_header_t *sh)
static svm_fifo_t * fsh_try_alloc_fifo_hdr(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss)
int attach_timeout
shm segments attach timeout (sec)
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.
static void fss_fl_chunk_bytes_sub(fifo_segment_slice_t *fss, uword 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.
static uword fss_fl_chunk_bytes(fifo_segment_slice_t *fss)
#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
uword clib_mem_get_heap_free_space(clib_mem_heap_t *heap)
#define clib_atomic_fetch_add_relax(a, b)
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.
u32 start_byte
chunk start byte
static void fss_chunk_free_list_push(fifo_segment_slice_t *fss, u32 fl_index, svm_fifo_chunk_t *c)
int memfd_fd
fd for memfd segments
#define clib_atomic_fetch_sub_relax(a, b)
static void fsh_cached_bytes_add(fifo_segment_header_t *fsh, uword size)
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)
int ssvm_client_init(ssvm_private_t *ssvm, ssvm_segment_type_t type)
manual_print typedef address
static svm_fifo_chunk_t * fss_chunk_free_list_pop(fifo_segment_slice_t *fss, u32 fl_index)
void fifo_segment_free_fifo(fifo_segment_t *fs, svm_fifo_t *f)
Free fifo allocated in fifo segment.
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 void fss_fl_chunk_bytes_add(fifo_segment_slice_t *fss, uword 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
static int fss_chunk_fl_index_is_valid(fifo_segment_slice_t *fss, u32 fl_index)
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.
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
static svm_fifo_chunk_t * fsh_try_alloc_chunk(fifo_segment_header_t *fsh, fifo_segment_slice_t *fss, u32 data_bytes)
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.
u32 * new_segment_indices
return vec of new seg indices
ssvm_segment_type_t ssvm_type(const ssvm_private_t *ssvm)