unified: Support heap memory pool
Fleshes out the prototype heap memory pool support to make it fully operational. Noteworthy changes are listed below: Tweaks arguments to k_malloc() and k_free() to be more like malloc() and free(). Similarly, modifies k_free() to take no action when passed a NULL pointer. Now stores the complete block descriptor at the start of any block allocated from the heap memory pool. This increases memory overhead by 4 bytes per block, but streamlines the allocation and freeing algorithms. It also ensures that the routines will work if the block descriptor internals are changed in the future. Now allows the heap memory pool to be defined using the HEAP_MEM_POOL_SIZE configuration option. This will be the official configuration approach in the unified kernel. Also allows the heap memory pool to be defined using the (undocumented) HEAP_SIZE entry in the MDEF. This is provided for legacy reasons only. Co-locates memory pool initialization code to keep the line that causes memory pool initialization to be done during booting right next to the routine that does the initialization. Change-Id: Ifea9d88142fb434d4bea38bb1fcc4856a3853d8d Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
This commit is contained in:
parent
904cf97263
commit
480a131ad9
4 changed files with 87 additions and 61 deletions
|
@ -1814,10 +1814,10 @@ extern void k_mem_pool_free(struct k_mem_block *block);
|
|||
extern void k_mem_pool_defrag(struct k_mem_pool *pool);
|
||||
|
||||
/**
|
||||
* @brief Allocate memory from heap pool
|
||||
* @brief Allocate memory from heap
|
||||
*
|
||||
* This routine provides traditional malloc semantics; internally it uses
|
||||
* the memory pool APIs on a dedicated HEAP pool
|
||||
* This routine provides traditional malloc() semantics. The memory is
|
||||
* allocated from the heap memory pool.
|
||||
*
|
||||
* @param size Size of memory requested by the caller (in bytes)
|
||||
*
|
||||
|
@ -1826,7 +1826,10 @@ extern void k_mem_pool_defrag(struct k_mem_pool *pool);
|
|||
extern void *k_malloc(size_t size);
|
||||
|
||||
/**
|
||||
* @brief Free memory allocated through k_malloc()
|
||||
* @brief Free memory allocated from heap
|
||||
*
|
||||
* This routine provides traditional free() semantics. The memory being
|
||||
* returned must have been allocated from the heap memory pool.
|
||||
*
|
||||
* @param ptr Pointer to previously allocated memory
|
||||
*
|
||||
|
|
|
@ -319,4 +319,14 @@ config MEM_POOL_AD_AFTER_SEARCH_FOR_BIGGERBLOCK
|
|||
|
||||
endchoice
|
||||
|
||||
config HEAP_MEM_POOL_SIZE
|
||||
int
|
||||
prompt "Heap memory pool size (in bytes)"
|
||||
default 0
|
||||
help
|
||||
This option specifies the size of the heap memory pool used when
|
||||
dynamically allocating memory using k_malloc(). Supported values
|
||||
are: 256, 1024, 4096, and 16384. A size of zero means that no
|
||||
heap memory pool is defined.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -24,17 +24,14 @@
|
|||
#include <ksched.h>
|
||||
#include <wait_q.h>
|
||||
#include <init.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define _QUAD_BLOCK_AVAILABLE 0x0F
|
||||
#define _QUAD_BLOCK_ALLOCATED 0x0
|
||||
|
||||
extern struct k_mem_pool _k_mem_pool_start[];
|
||||
extern struct k_mem_pool _k_mem_pool_end[];
|
||||
#if defined _HEAP_MEM_POOL
|
||||
static struct k_mem_pool *heap_mem_pool = _HEAP_MEM_POOL;
|
||||
#else
|
||||
static struct k_mem_pool *heap_mem_pool;
|
||||
#endif
|
||||
|
||||
static void init_one_memory_pool(struct k_mem_pool *pool);
|
||||
|
||||
|
@ -61,6 +58,8 @@ static int init_static_pools(struct device *unused)
|
|||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(init_static_pools, PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Initialize the memory pool
|
||||
|
@ -523,45 +522,6 @@ int k_mem_pool_alloc(struct k_mem_pool *pool, struct k_mem_block *block,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
#define MALLOC_ALIGN (sizeof(uint32_t))
|
||||
|
||||
void *k_malloc(size_t size)
|
||||
{
|
||||
uint32_t new_size;
|
||||
uint32_t *aligned_addr;
|
||||
struct k_mem_block mem_block;
|
||||
|
||||
__ASSERT(heap_mem_pool != NULL,
|
||||
"Try to allocate a block in undefined heap\n");
|
||||
|
||||
/* The address pool returns, may not be aligned. Also
|
||||
* pool_free requires both start address and size. So
|
||||
* we end up needing 2 slots to save the size and
|
||||
* start address in addition to padding space
|
||||
*/
|
||||
new_size = size + (sizeof(uint32_t) << 1) + MALLOC_ALIGN - 1;
|
||||
|
||||
if (k_mem_pool_alloc(heap_mem_pool, &mem_block, new_size,
|
||||
K_NO_WAIT) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the next aligned address following the address returned by pool*/
|
||||
aligned_addr = (uint32_t *) ROUND_UP(mem_block.addr_in_pool,
|
||||
MALLOC_ALIGN);
|
||||
|
||||
/* Save the size requested to the pool API, to be used while freeing */
|
||||
*aligned_addr = new_size;
|
||||
|
||||
/* Save the original unaligned_addr pointer too */
|
||||
aligned_addr++;
|
||||
*((void **) aligned_addr) = mem_block.addr_in_pool;
|
||||
|
||||
/* return the subsequent address */
|
||||
return ++aligned_addr;
|
||||
}
|
||||
|
||||
void k_mem_pool_free(struct k_mem_block *block)
|
||||
{
|
||||
int offset;
|
||||
|
@ -579,22 +539,70 @@ void k_mem_pool_free(struct k_mem_block *block)
|
|||
k_sched_unlock();
|
||||
}
|
||||
|
||||
void k_free(void *ptr)
|
||||
|
||||
/*
|
||||
* Heap memory pool support
|
||||
*/
|
||||
|
||||
#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
|
||||
|
||||
/*
|
||||
* Case 1: Heap is defined using HEAP_MEM_POOL_SIZE configuration option.
|
||||
*
|
||||
* This module defines the heap memory pool and the _HEAP_MEM_POOL symbol
|
||||
* that has the address of the associated memory pool struct.
|
||||
*/
|
||||
|
||||
K_MEM_POOL_DEFINE(_heap_mem_pool, 64, CONFIG_HEAP_MEM_POOL_SIZE, 1, 4);
|
||||
#define _HEAP_MEM_POOL (&_heap_mem_pool)
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Case 2: Heap is defined using HEAP_SIZE item type in MDEF.
|
||||
*
|
||||
* Sysgen defines the heap memory pool and the _heap_mem_pool_ptr variable
|
||||
* that has the address of the associated memory pool struct. This module
|
||||
* defines the _HEAP_MEM_POOL symbol as an alias for _heap_mem_pool_ptr.
|
||||
*
|
||||
* Note: If the MDEF does not define the heap memory pool k_malloc() will
|
||||
* compile successfully, but will trigger a link error if it is used.
|
||||
*/
|
||||
|
||||
extern struct k_mem_pool * const _heap_mem_pool_ptr;
|
||||
#define _HEAP_MEM_POOL _heap_mem_pool_ptr
|
||||
|
||||
#endif /* CONFIG_HEAP_MEM_POOL_SIZE */
|
||||
|
||||
|
||||
void *k_malloc(size_t size)
|
||||
{
|
||||
struct k_mem_block mem_block;
|
||||
struct k_mem_block block;
|
||||
|
||||
__ASSERT(heap_mem_pool != NULL,
|
||||
"Try to free a block in undefined heap\n");
|
||||
/*
|
||||
* get a block large enough to hold an initial (hidden) block
|
||||
* descriptor, as well as the space the caller requested
|
||||
*/
|
||||
size += sizeof(struct k_mem_block);
|
||||
if (k_mem_pool_alloc(_HEAP_MEM_POOL, &block, size, K_NO_WAIT) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mem_block.pool_id = heap_mem_pool;
|
||||
/* save the block descriptor info at the start of the actual block */
|
||||
memcpy(block.data, &block, sizeof(struct k_mem_block));
|
||||
|
||||
/* Fetch the pointer returned by the pool API */
|
||||
mem_block.addr_in_pool = *((void **) ((uint32_t *)ptr - 1));
|
||||
mem_block.data = *((void **) ((uint32_t *)ptr - 1));
|
||||
/* Further fetch the size asked from pool */
|
||||
mem_block.req_size = *((uint32_t *)ptr - 2);
|
||||
|
||||
k_mem_pool_free(&mem_block);
|
||||
/* return address of the user area part of the block to the caller */
|
||||
return (char *)block.data + sizeof(struct k_mem_block);
|
||||
}
|
||||
|
||||
SYS_INIT(init_static_pools, PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
|
||||
|
||||
void k_free(void *ptr)
|
||||
{
|
||||
if (ptr != NULL) {
|
||||
/* point to hidden block descriptor at start of block */
|
||||
ptr = (char *)ptr - sizeof(struct k_mem_block);
|
||||
|
||||
/* return block to the heap memory pool */
|
||||
k_mem_pool_free(ptr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -898,6 +898,11 @@ def kernel_main_c_pools():
|
|||
pool_descriptors += "K_MEM_POOL_DEFINE(_k_mem_pool_obj_%s, %d, %d, %d, 4);\n" % \
|
||||
(pool[0], min_block_size, max_block_size,
|
||||
num_maximal_blocks)
|
||||
|
||||
if (heap_pos_in_pool_list != -1):
|
||||
kernel_main_c_out(
|
||||
"\nkmemory_pool_t _heap_mem_pool_ptr = " +
|
||||
"&_k_mem_pool_obj__HEAP_MEM_POOL;\n")
|
||||
kernel_main_c_out(pool_descriptors)
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue