diff options
Diffstat (limited to 'middleware/multicore/open-amp/common/shm/sh_mem.c')
-rw-r--r-- | middleware/multicore/open-amp/common/shm/sh_mem.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/middleware/multicore/open-amp/common/shm/sh_mem.c b/middleware/multicore/open-amp/common/shm/sh_mem.c new file mode 100644 index 0000000..6a290a4 --- /dev/null +++ b/middleware/multicore/open-amp/common/shm/sh_mem.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Mentor Graphics Corporation nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/************************************************************************** + * FILE NAME + * + * sh_mem.c + * + * COMPONENT + * + * OpenAMP stack. + * + * DESCRIPTION + * + * Source file for fixed buffer size memory management service. Currently + * it is only being used to manage shared memory. + * + **************************************************************************/ +#include "sh_mem.h" + +/** + * sh_mem_create_pool + * + * Creates new memory pool with the given parameters. + * + * @param start_addr - start address of the memory region + * @param size - size of the memory + * @param buff_size - fixed buffer size + * + * @return - pointer to memory pool + * + */ +struct sh_mem_pool * sh_mem_create_pool(void *start_addr, unsigned int size, + unsigned int buff_size) { + struct sh_mem_pool *mem_pool; + int status, pool_size; + int num_buffs, bmp_size; + + if (!start_addr || !size || !buff_size) + return NULL; + + /* Word align the buffer size */ + buff_size = WORD_ALIGN(buff_size); + + /* Get number of buffers. */ + num_buffs = (size / buff_size) + ((size % buff_size) == 0 ? 0 : 1); + + /* + * Size of the bitmap required to maintain buffers info. One word(32 bit) can + * keep track of 32 buffers. + */ + bmp_size = (num_buffs / BITMAP_WORD_SIZE) + + ((num_buffs % BITMAP_WORD_SIZE) == 0 ? 0 : 1); + + /* Total size required for pool control block. */ + pool_size = sizeof(struct sh_mem_pool) + WORD_SIZE * bmp_size; + + /* Create pool control block. */ + mem_pool = env_allocate_memory(pool_size); + + if (mem_pool) { + /* Initialize pool parameters */ + env_memset(mem_pool, 0x00, pool_size); + status = env_create_mutex(&mem_pool->lock , 1); + if (status){ + env_free_memory(mem_pool); + return NULL; + } + mem_pool->start_addr = start_addr; + mem_pool->buff_size = buff_size; + mem_pool->bmp_size = bmp_size; + mem_pool->total_buffs = num_buffs; + } + + return mem_pool; +} + +/** + * sh_mem_get_buffer + * + * Allocates fixed size buffer from the given memory pool. + * + * @param pool - pointer to memory pool + * + * @return - pointer to allocated buffer + * + */ +void * sh_mem_get_buffer(struct sh_mem_pool *pool) { + void *buff = NULL; + int idx, bit_idx; + + if (!pool) + return NULL; + + env_lock_mutex(pool->lock); + + if (pool->used_buffs >= pool->total_buffs) { + env_unlock_mutex(pool->lock); + return NULL; + } + + for (idx = 0; idx < pool->bmp_size; idx++) { + /* + * Find the first 0 bit in the buffers bitmap. The 0th bit + * represents a free buffer. + */ + bit_idx = get_first_zero_bit(pool->bitmap[idx]); + if (bit_idx < 32) { + /* Set bit to mark it as consumed. */ + pool->bitmap[idx] |= (1 << bit_idx); + buff = (char *) pool->start_addr + + pool->buff_size * (idx * BITMAP_WORD_SIZE + bit_idx); + pool->used_buffs++; + break; + } + } + + env_unlock_mutex(pool->lock); + + return buff; +} + +/** + * sh_mem_free_buffer + * + * Frees the given buffer. + * + * @param pool - pointer to memory pool + * @param buff - pointer to buffer + * + * @return - none + */ +void sh_mem_free_buffer(void *buff, struct sh_mem_pool *pool) { + unsigned long *bitmask; + int bmp_idx, bit_idx, buff_idx; + + if (!pool || !buff) + return; + + /* Acquire the pool lock */ + env_lock_mutex(pool->lock); + + /* Map the buffer address to its index. */ + buff_idx = ((char *) buff - (char*) pool->start_addr) / pool->buff_size; + + /* Translate the buffer index to bitmap index. */ + bmp_idx = buff_idx / BITMAP_WORD_SIZE; + bit_idx = buff_idx % BITMAP_WORD_SIZE; + bitmask = &pool->bitmap[bmp_idx]; + + /* Mark the buffer as free */ + *bitmask ^= (1 << bit_idx); + + pool->used_buffs--; + + /* Release the pool lock. */ + env_unlock_mutex(pool->lock); + +} + +/** + * sh_mem_delete_pool + * + * Deletes the given memory pool. + * + * @param pool - pointer to memory pool + * + * @return - none + */ +void sh_mem_delete_pool(struct sh_mem_pool *pool) { + + if (pool) { + env_delete_mutex(pool->lock); + env_free_memory(pool); + } +} + +/** + * get_first_zero_bit + * + * Provides position of first 0 bit in a 32 bit value + * + * @param value - given value + * + * @return - 0th bit position + */ +unsigned int get_first_zero_bit(unsigned long value) { + unsigned int idx; + unsigned int tmp32; + + /* Invert value */ + value = ~value; + + /* (~value) & (2's complement of value) */ + value = (value & (-value)) - 1; + + /* log2(value) */ + + tmp32 = value - ((value >> 1) & 033333333333) + - ((value >> 2) & 011111111111); + + idx = ((tmp32 + (tmp32 >> 3)) & 030707070707) % 63; + + return idx; +} |