if (!f)
return 0;
memset (f, 0, sizeof (*f));
+ fsh->n_free_bytes -= sizeof (*f);
+ }
+ else
+ {
+ fsh->free_fifos = f->next;
}
fl_index = fs_freelist_for_size (data_bytes) - 1;
last = c;
c->next = first;
first = c;
- n_alloc += c->length;
+ n_alloc += fl_size;
c->length = clib_min (fl_size, data_bytes);
data_bytes -= c->length;
}
/* (re)initialize the fifo, as in svm_fifo_create */
svm_fifo_init (f, data_bytes);
+ /* Initialize chunks and rbtree for multi-chunk fifos */
+ if (f->start_chunk->next != f->start_chunk)
+ {
+ void *oldheap = ssvm_push_heap (fs->ssvm.sh);
+ svm_fifo_init_chunks (f);
+ ssvm_pop_heap (oldheap);
+ }
+
/* If rx fifo type add to active fifos list. When cleaning up segment,
* we need a list of active sessions that should be disconnected. Since
* both rx and tx fifos keep pointers to the session, it's enough to track
}
while (cur != f->start_chunk);
+ f->start_chunk = f->end_chunk = f->new_chunks = 0;
+ f->head_chunk = f->tail_chunk = f->ooo_enq = f->ooo_deq = 0;
+
oldheap = ssvm_push_heap (sh);
svm_fifo_free_chunk_lookup (f);
ssvm_pop_heap (oldheap);
/* Calculate space requirements */
pair_size = 2 * hdrs + rx_rounded_data_size + tx_rounded_data_size;
space_available = fs_free_space (fs);
- pairs_to_alloc = clib_min (space_available / pair_size, *n_fifo_pairs);
+ pairs_to_alloc = space_available / pair_size;
+ pairs_to_alloc = clib_min (pairs_to_alloc, *n_fifo_pairs);
+
+ if (!pairs_to_alloc)
+ return;
if (fs_try_alloc_fifo_batch (fs, rx_fl_index, pairs_to_alloc))
- clib_warning ("rx prealloc failed");
+ clib_warning ("rx prealloc failed: pairs %u", pairs_to_alloc);
if (fs_try_alloc_fifo_batch (fs, tx_fl_index, pairs_to_alloc))
- clib_warning ("tx prealloc failed");
+ clib_warning ("tx prealloc failed: pairs %u", pairs_to_alloc);
/* Account for the pairs allocated */
*n_fifo_pairs -= pairs_to_alloc;
if (!fs_chunk_size_is_valid (chunk_size))
{
clib_warning ("chunk size out of range %d", chunk_size);
- return 0;
+ return -1;
}
fl_index = fs_freelist_for_size (chunk_size);
if (!c)
{
ssvm_pop_heap (oldheap);
+ ssvm_unlock_non_recursive (sh);
return -1;
}
}
{
fs->h->free_chunks[fl_index] = c->next;
c->next = 0;
+ fs->h->n_fl_chunk_bytes -= fs_freelist_index_to_size (fl_index);
}
svm_fifo_add_chunk (f, c);
}
u32
-fifo_segment_chunk_prealloc_bytes (fifo_segment_t * fs)
+fifo_segment_fl_chunk_bytes (fifo_segment_t * fs)
{
return fs->h->n_fl_chunk_bytes;
}
u8 *
format_fifo_segment (u8 * s, va_list * args)
{
- fifo_segment_t *sp = va_arg (*args, fifo_segment_t *);
+ fifo_segment_t *fs = va_arg (*args, fifo_segment_t *);
int verbose __attribute__ ((unused)) = va_arg (*args, int);
- fifo_segment_header_t *fsh = sp->h;
- u32 count, indent;
+ fifo_segment_header_t *fsh;
svm_fifo_chunk_t *c;
+ u32 count, indent;
+ u32 active_fifos;
+ u32 free_fifos;
+ char *address;
+ size_t size;
int i;
indent = format_get_indent (s) + 2;
#if USE_DLMALLOC == 0
s = format (s, "%U segment heap: %U\n", format_white_space, indent,
- format_mheap, svm_fifo_segment_heap (sp), verbose);
+ format_mheap, svm_fifo_segment_heap (fs), verbose);
s = format (s, "%U segment has %u active fifos\n",
- format_white_space, indent, fifo_segment_num_fifos (sp));
+ format_white_space, indent, fifo_segment_num_fifos (fs));
#endif
+ if (fs == 0)
+ {
+ s = format (s, "%-15s%15s%15s%15s%15s%15s", "Name", "Type",
+ "HeapSize (M)", "ActiveFifos", "FreeFifos", "Address");
+ return s;
+ }
+
+ fsh = fs->h;
+ fifo_segment_info (fs, &address, &size);
+ active_fifos = fifo_segment_num_fifos (fs);
+ free_fifos = fifo_segment_num_free_fifos (fs);
+
+ s = format (s, "%-15v%15U%15llu%15u%15u%15llx", ssvm_name (&fs->ssvm),
+ format_fifo_segment_type, fs, size >> 20ULL, active_fifos,
+ free_fifos, address);
+
+ if (!verbose)
+ return s;
+
+ s = format (s, "\n");
for (i = 0; i < vec_len (fsh->free_chunks); i++)
{
c = fsh->free_chunks[i];
count++;
}
- s = format (s, "%U%-5u Kb: %u free",
- format_white_space, indent + 2,
+ s = format (s, "%U%-5u Kb: %u free", format_white_space, indent + 2,
1 << (i + max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE) - 10),
count);
}
+ s = format (s, "%Ufree bytes %U", format_white_space, indent + 2,
+ format_memory_size, fsh->n_free_bytes);
+
return s;
}