diff options
author | Florin Coras <fcoras@cisco.com> | 2019-04-24 14:44:46 -0700 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2019-04-25 18:05:16 +0000 |
commit | 88001c64e9e5d0dc08e303857ca34687454ebf10 (patch) | |
tree | f747dabb08b764514c3465ca854ebed87031e8bb /src/svm/svm_fifo_segment.c | |
parent | 1ccbbfbf972eefc87491dd7c260bc0c4dcef8ac9 (diff) |
session: cleanup segment manager and fifo segment
Change-Id: I984f347fb465c0c405cef668d8690457e81788e2
Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/svm/svm_fifo_segment.c')
-rw-r--r-- | src/svm/svm_fifo_segment.c | 668 |
1 files changed, 0 insertions, 668 deletions
diff --git a/src/svm/svm_fifo_segment.c b/src/svm/svm_fifo_segment.c deleted file mode 100644 index 8a8bd4aa7ff..00000000000 --- a/src/svm/svm_fifo_segment.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * Copyright (c) 2016-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <svm/svm_fifo_segment.h> - -static void -fifo_init_for_segment (svm_fifo_segment_header_t * fsh, u8 * fifo_space, - u32 size, u32 freelist_index) -{ - svm_fifo_t *f; - - f = (svm_fifo_t *) fifo_space; - f->freelist_index = freelist_index; - f->default_chunk.start_byte = 0; - f->default_chunk.length = size; - f->default_chunk.next = f->start_chunk = f->end_chunk = &f->default_chunk; - f->head_chunk = f->tail_chunk = f->ooo_enq = f->ooo_deq = f->start_chunk; - f->next = fsh->free_fifos[freelist_index]; - fsh->free_fifos[freelist_index] = f; -} - -static void -allocate_new_fifo_chunk (svm_fifo_segment_header_t * fsh, - u32 data_size_in_bytes, int chunk_size) -{ - int freelist_index; - u32 size; - u8 *fifo_space; - u32 rounded_data_size; - svm_fifo_t *f; - int i; - - rounded_data_size = (1 << (max_log2 (data_size_in_bytes))); - freelist_index = max_log2 (rounded_data_size) - - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE); - - /* Calculate space requirement $$$ round-up data_size_in_bytes */ - size = (sizeof (*f) + rounded_data_size) * chunk_size; - - /* Allocate fifo space. May fail. */ - fifo_space = clib_mem_alloc_aligned_at_offset - (size, CLIB_CACHE_LINE_BYTES, 0 /* align_offset */ , - 0 /* os_out_of_memory */ ); - - /* Out of space.. */ - if (fifo_space == 0) - return; - - /* Carve fifo space */ - for (i = 0; i < chunk_size; i++) - { - fifo_init_for_segment (fsh, fifo_space, rounded_data_size, - freelist_index); - fifo_space += sizeof (*f) + rounded_data_size; - } -} - -/** - * Pre-allocates fifo pairs in fifo segment - * - * The number of fifos pre-allocated is the minimum of the requested number - * of pairs and the maximum number that fit within the segment. If the maximum - * is hit, the number of fifo pairs requested is updated by subtracting the - * number of fifos that have been successfully allocated. - */ -void -svm_fifo_segment_preallocate_fifo_pairs (svm_fifo_segment_private_t * s, - u32 rx_fifo_size, u32 tx_fifo_size, - u32 * n_fifo_pairs) -{ - u32 rx_rounded_data_size, tx_rounded_data_size, pair_size; - u32 rx_fifos_size, tx_fifos_size, pairs_to_allocate; - int rx_freelist_index, tx_freelist_index; - ssvm_shared_header_t *sh = s->ssvm.sh; - svm_fifo_segment_header_t *fsh = s->h; - u8 *rx_fifo_space, *tx_fifo_space; - uword space_available; - void *oldheap; - svm_fifo_t *f; - int i; - - /* Parameter check */ - if (rx_fifo_size == 0 || tx_fifo_size == 0 || *n_fifo_pairs == 0) - return; - - if (rx_fifo_size < FIFO_SEGMENT_MIN_FIFO_SIZE || - rx_fifo_size > FIFO_SEGMENT_MAX_FIFO_SIZE) - { - clib_warning ("rx fifo_size out of range %d", rx_fifo_size); - return; - } - - if (tx_fifo_size < FIFO_SEGMENT_MIN_FIFO_SIZE || - tx_fifo_size > FIFO_SEGMENT_MAX_FIFO_SIZE) - { - clib_warning ("tx fifo_size out of range %d", rx_fifo_size); - return; - } - - rx_rounded_data_size = (1 << (max_log2 (rx_fifo_size))); - rx_freelist_index = max_log2 (rx_fifo_size) - - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE); - tx_rounded_data_size = (1 << (max_log2 (tx_fifo_size))); - tx_freelist_index = max_log2 (tx_fifo_size) - - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE); - - /* Calculate space requirements */ - pair_size = 2 * sizeof (*f) + rx_rounded_data_size + tx_rounded_data_size; -#if USE_DLMALLOC == 0 - space_available = s->ssvm.ssvm_size - mheap_bytes (sh->heap); -#else - space_available = s->ssvm.ssvm_size - mspace_usable_size (sh->heap); -#endif - - pairs_to_allocate = clib_min (space_available / pair_size, *n_fifo_pairs); - rx_fifos_size = (sizeof (*f) + rx_rounded_data_size) * pairs_to_allocate; - tx_fifos_size = (sizeof (*f) + tx_rounded_data_size) * pairs_to_allocate; - - vec_validate_init_empty (fsh->free_fifos, - clib_max (rx_freelist_index, tx_freelist_index), - 0); - - oldheap = ssvm_push_heap (sh); - /* Allocate rx fifo space. May fail. */ - rx_fifo_space = clib_mem_alloc_aligned_at_offset - (rx_fifos_size, CLIB_CACHE_LINE_BYTES, 0 /* align_offset */ , - 0 /* os_out_of_memory */ ); - - /* Same for TX */ - tx_fifo_space = clib_mem_alloc_aligned_at_offset - (tx_fifos_size, CLIB_CACHE_LINE_BYTES, 0 /* align_offset */ , - 0 /* os_out_of_memory */ ); - - /* Make sure it worked. Clean up if it didn't... */ - if (rx_fifo_space == 0 || tx_fifo_space == 0) - { - if (rx_fifo_space) - clib_mem_free (rx_fifo_space); - else - clib_warning ("rx fifo preallocation failure: size %d npairs %d", - rx_fifo_size, *n_fifo_pairs); - - if (tx_fifo_space) - clib_mem_free (tx_fifo_space); - else - clib_warning ("tx fifo preallocation failure: size %d nfifos %d", - tx_fifo_size, *n_fifo_pairs); - ssvm_pop_heap (oldheap); - return; - } - - /* Carve rx fifo space */ - for (i = 0; i < pairs_to_allocate; i++) - { - fifo_init_for_segment (fsh, rx_fifo_space, rx_rounded_data_size, - rx_freelist_index); - rx_fifo_space += sizeof (*f) + rx_rounded_data_size; - } - /* Carve tx fifo space */ - for (i = 0; i < pairs_to_allocate; i++) - { - fifo_init_for_segment (fsh, tx_fifo_space, tx_rounded_data_size, - tx_freelist_index); - tx_fifo_space += sizeof (*f) + tx_rounded_data_size; - } - - /* Account for the pairs allocated */ - *n_fifo_pairs -= pairs_to_allocate; - ssvm_pop_heap (oldheap); -} - -/** - * Initialize svm fifo segment shared header - */ -int -svm_fifo_segment_init (svm_fifo_segment_private_t * s) -{ - svm_fifo_segment_header_t *fsh; - ssvm_shared_header_t *sh; - void *oldheap; - - sh = s->ssvm.sh; - oldheap = ssvm_push_heap (sh); - - fsh = clib_mem_alloc (sizeof (*fsh)); - clib_memset (fsh, 0, sizeof (*fsh)); - s->h = sh->opaque[0] = fsh; - - ssvm_pop_heap (oldheap); - - sh->ready = 1; - return (0); -} - -/** - * Create an svm fifo segment and initialize as master - */ -int -svm_fifo_segment_create (svm_fifo_segment_main_t * sm, - svm_fifo_segment_create_args_t * a) -{ - svm_fifo_segment_private_t *s; - int rv; - - /* Allocate a fresh segment */ - pool_get (sm->segments, s); - clib_memset (s, 0, sizeof (*s)); - - s->ssvm.ssvm_size = a->segment_size; - s->ssvm.i_am_master = 1; - s->ssvm.my_pid = getpid (); - s->ssvm.name = format (0, "%s%c", a->segment_name, 0); - s->ssvm.requested_va = sm->next_baseva; - - if ((rv = ssvm_master_init (&s->ssvm, a->segment_type))) - { - pool_put (sm->segments, s); - return (rv); - } - - /* Note: requested_va updated due to seg base addr randomization */ - sm->next_baseva = s->ssvm.sh->ssvm_va + a->segment_size; - - svm_fifo_segment_init (s); - vec_add1 (a->new_segment_indices, s - sm->segments); - return (0); -} - -/** - * Create an svm fifo segment in process-private memory - */ -int -svm_fifo_segment_create_process_private (svm_fifo_segment_main_t * sm, - svm_fifo_segment_create_args_t * a) -{ - svm_fifo_segment_private_t *s; - ssvm_shared_header_t *sh; - u32 rnd_size = 0; - u8 *heap; - u32 pagesize = clib_mem_get_page_size (); - - pool_get (sm->segments, s); - clib_memset (s, 0, sizeof (*s)); - - rnd_size = (a->segment_size + (pagesize - 1)) & ~pagesize; - -#if USE_DLMALLOC == 0 - heap = mheap_alloc (0, rnd_size); - if (heap == 0) - { - clib_unix_warning ("mheap alloc"); - pool_put (sm->segments, s); - return -1; - } - { - mheap_t *heap_header; - heap_header = mheap_header (heap); - heap_header->flags |= MHEAP_FLAG_THREAD_SAFE; - } -#else - heap = create_mspace (rnd_size, 1 /* locked */ ); -#endif - - s->ssvm.ssvm_size = rnd_size; - s->ssvm.i_am_master = 1; - s->ssvm.my_pid = getpid (); - s->ssvm.name = format (0, "%s%c", a->segment_name, 0); - s->ssvm.requested_va = ~0; - - /* Allocate a [sic] shared memory header, in process memory... */ - sh = clib_mem_alloc_aligned (sizeof (*sh), CLIB_CACHE_LINE_BYTES); - s->ssvm.sh = sh; - - clib_memset (sh, 0, sizeof (*sh)); - sh->heap = heap; - - svm_fifo_segment_init (s); - vec_add1 (a->new_segment_indices, s - sm->segments); - - return (0); -} - -/** - * Attach as slave to an svm fifo segment - */ -int -svm_fifo_segment_attach (svm_fifo_segment_main_t * sm, - svm_fifo_segment_create_args_t * a) -{ - svm_fifo_segment_private_t *s; - int rv; - - /* Allocate a fresh segment */ - pool_get (sm->segments, s); - clib_memset (s, 0, sizeof (*s)); - - s->ssvm.ssvm_size = a->segment_size; - s->ssvm.my_pid = getpid (); - s->ssvm.name = format (0, "%s%c", a->segment_name, 0); - s->ssvm.requested_va = sm->next_baseva; - if (a->segment_type == SSVM_SEGMENT_MEMFD) - s->ssvm.fd = a->memfd_fd; - else - s->ssvm.attach_timeout = sm->timeout_in_seconds; - - if ((rv = ssvm_slave_init (&s->ssvm, a->segment_type))) - { - _vec_len (s) = vec_len (s) - 1; - return (rv); - } - - /* Fish the segment header */ - s->h = s->ssvm.sh->opaque[0]; - - vec_add1 (a->new_segment_indices, s - sm->segments); - return (0); -} - -void -svm_fifo_segment_delete (svm_fifo_segment_main_t * sm, - svm_fifo_segment_private_t * s) -{ - ssvm_delete (&s->ssvm); - clib_memset (s, 0xfe, sizeof (*s)); - pool_put (sm->segments, s); -} - -/** - * Allocate fifo in svm segment - */ -svm_fifo_t * -svm_fifo_segment_alloc_fifo (svm_fifo_segment_private_t * fs, - u32 data_size_in_bytes, - svm_fifo_segment_freelist_t list_index) -{ - ssvm_shared_header_t *sh; - svm_fifo_segment_header_t *fsh; - svm_fifo_t *f = 0; - void *oldheap; - int freelist_index; - - /* - * 4K minimum. It's not likely that anything good will happen - * with a smaller FIFO. - */ - if (data_size_in_bytes < FIFO_SEGMENT_MIN_FIFO_SIZE || - data_size_in_bytes > FIFO_SEGMENT_MAX_FIFO_SIZE) - { - clib_warning ("fifo size out of range %d", data_size_in_bytes); - return 0; - } - - freelist_index = max_log2 (data_size_in_bytes) - - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE); - - sh = fs->ssvm.sh; - ssvm_lock_non_recursive (sh, 1); - fsh = (svm_fifo_segment_header_t *) sh->opaque[0]; - - switch (list_index) - { - case FIFO_SEGMENT_RX_FREELIST: - case FIFO_SEGMENT_TX_FREELIST: - vec_validate_init_empty (fsh->free_fifos, freelist_index, 0); - f = fsh->free_fifos[freelist_index]; - if (PREDICT_FALSE (!f)) - { - oldheap = ssvm_push_heap (sh); - allocate_new_fifo_chunk (fsh, data_size_in_bytes, - FIFO_SEGMENT_ALLOC_CHUNK_SIZE); - ssvm_pop_heap (oldheap); - f = fsh->free_fifos[freelist_index]; - } - if (PREDICT_TRUE (f != 0)) - { - fsh->free_fifos[freelist_index] = f->next; - /* (re)initialize the fifo, as in svm_fifo_create */ - clib_memset (f, 0, sizeof (*f)); - svm_fifo_init (f, data_size_in_bytes); - goto found; - } - break; - case FIFO_SEGMENT_FREELIST_NONE: - break; - - default: - clib_warning ("ignore bogus freelist %d", list_index); - break; - } - - /* Catch all that allocates just one fifo. Note: this can fail, - * in which case: create another segment */ - oldheap = ssvm_push_heap (sh); - f = svm_fifo_create (data_size_in_bytes); - ssvm_pop_heap (oldheap); - if (PREDICT_FALSE (f == 0)) - goto done; - f->freelist_index = freelist_index; - -found: - /* If rx_freelist 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 - * only one. */ - if (list_index == FIFO_SEGMENT_RX_FREELIST) - { - if (fsh->fifos) - { - fsh->fifos->prev = f; - f->next = fsh->fifos; - } - fsh->fifos = f; - } - fsh->n_active_fifos++; - -done: - ssvm_unlock_non_recursive (sh); - return (f); -} - -void -svm_fifo_segment_free_fifo (svm_fifo_segment_private_t * s, svm_fifo_t * f, - svm_fifo_segment_freelist_t list_index) -{ - ssvm_shared_header_t *sh; - svm_fifo_segment_header_t *fsh; - int freelist_index; - - ASSERT (f->refcnt > 0); - - if (--f->refcnt > 0) - return; - - sh = s->ssvm.sh; - fsh = (svm_fifo_segment_header_t *) sh->opaque[0]; - - freelist_index = f->freelist_index; - - ASSERT (freelist_index < vec_len (fsh->free_fifos)); - - ssvm_lock_non_recursive (sh, 2); - - switch (list_index) - { - case FIFO_SEGMENT_RX_FREELIST: - /* Remove from active list */ - if (f->prev) - f->prev->next = f->next; - else - fsh->fifos = f->next; - if (f->next) - f->next->prev = f->prev; - /* Fall through: we add only rx fifos to active pool */ - case FIFO_SEGMENT_TX_FREELIST: - /* Add to free list */ - f->next = fsh->free_fifos[freelist_index]; - f->prev = 0; - fsh->free_fifos[freelist_index] = f; - break; - case FIFO_SEGMENT_FREELIST_NONE: - break; - - default: - clib_warning ("ignore bogus freelist %d", list_index); - break; - } - - if (CLIB_DEBUG) - { - f->master_session_index = ~0; - f->master_thread_index = ~0; - } - - fsh->n_active_fifos--; - ssvm_unlock_non_recursive (sh); -} - -void -svm_fifo_segment_main_init (svm_fifo_segment_main_t * sm, u64 baseva, - u32 timeout_in_seconds) -{ - sm->next_baseva = baseva; - sm->timeout_in_seconds = timeout_in_seconds; -} - -u32 -svm_fifo_segment_index (svm_fifo_segment_main_t * sm, - svm_fifo_segment_private_t * s) -{ - return s - sm->segments; -} - -/** - * Retrieve svm segments pool. Used only for debug purposes. - */ -svm_fifo_segment_private_t * -svm_fifo_segment_segments_pool (svm_fifo_segment_main_t * sm) -{ - return sm->segments; -} - -/** - * Get number of active fifos - */ -u32 -svm_fifo_segment_num_fifos (svm_fifo_segment_private_t * fifo_segment) -{ - return fifo_segment->h->n_active_fifos; -} - -u32 -svm_fifo_segment_num_free_fifos (svm_fifo_segment_private_t * fifo_segment, - u32 fifo_size_in_bytes) -{ - ssvm_shared_header_t *sh; - svm_fifo_segment_header_t *fsh; - svm_fifo_t *f; - int i; - u32 count = 0, rounded_data_size, freelist_index; - - sh = fifo_segment->ssvm.sh; - fsh = (svm_fifo_segment_header_t *) sh->opaque[0]; - - /* Count all free fifos? */ - if (fifo_size_in_bytes == ~0) - { - for (i = 0; i < vec_len (fsh->free_fifos); i++) - { - f = fsh->free_fifos[i]; - if (f == 0) - continue; - - while (f) - { - f = f->next; - count++; - } - } - return count; - } - - rounded_data_size = (1 << (max_log2 (fifo_size_in_bytes))); - freelist_index = max_log2 (rounded_data_size) - - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE); - - if (freelist_index >= vec_len (fsh->free_fifos)) - return 0; - - f = fsh->free_fifos[freelist_index]; - if (f == 0) - return 0; - - while (f) - { - f = f->next; - count++; - } - return count; -} - -void -svm_fifo_segment_info (svm_fifo_segment_private_t * seg, char **address, - size_t * size) -{ - if (ssvm_type (&seg->ssvm) == SSVM_SEGMENT_PRIVATE) - { -#if USE_DLMALLOC == 0 - mheap_t *heap_header; - - *address = pointer_to_uword (seg->ssvm.sh->heap); - heap_header = mheap_header (seg->ssvm.sh->heap); - *size = heap_header->max_size; -#else - mspace_get_address_and_size (seg->ssvm.sh->heap, address, size); -#endif - } - else - { - *address = (char *) seg->ssvm.sh->ssvm_va; - *size = seg->ssvm.ssvm_size; - } -} - -void * -svm_fifo_segment_heap (svm_fifo_segment_private_t * seg) -{ - return seg->ssvm.sh->heap; -} - -u8 * -format_svm_fifo_segment_type (u8 * s, va_list * args) -{ - svm_fifo_segment_private_t *sp; - sp = va_arg (*args, svm_fifo_segment_private_t *); - ssvm_segment_type_t st = ssvm_type (&sp->ssvm); - - if (st == SSVM_SEGMENT_PRIVATE) - s = format (s, "%s", "private-heap"); - else if (st == SSVM_SEGMENT_MEMFD) - s = format (s, "%s", "memfd"); - else if (st == SSVM_SEGMENT_SHM) - s = format (s, "%s", "shm"); - else - s = format (s, "%s", "unknown"); - return s; -} - -/** - * Segment format function - */ -u8 * -format_svm_fifo_segment (u8 * s, va_list * args) -{ - svm_fifo_segment_private_t *sp - = va_arg (*args, svm_fifo_segment_private_t *); - int verbose __attribute__ ((unused)) = va_arg (*args, int); - svm_fifo_segment_header_t *fsh = sp->h; - u32 count, indent; - svm_fifo_t *f; - 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); - s = format (s, "%U segment has %u active fifos\n", - format_white_space, indent, svm_fifo_segment_num_fifos (sp)); -#endif - - for (i = 0; i < vec_len (fsh->free_fifos); i++) - { - f = fsh->free_fifos[i]; - if (f == 0) - continue; - count = 0; - while (f) - { - f = f->next; - count++; - } - - s = format (s, "%U%-5u Kb: %u free", - format_white_space, indent + 2, - 1 << (i + max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE) - 10), - count); - } - return s; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |