275 lines
8.7 KiB
C
Executable File
275 lines
8.7 KiB
C
Executable File
/****************************************************************************
|
||
The MIT License (MIT)
|
||
Copyright(c) 2015-2016 David Newman
|
||
https://github.com/djoldman/fmpool/blob/master/fmpool.h
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a
|
||
copy of this software and associated documentation files (the "Software"),
|
||
to deal in the Software without restriction, including without limitation
|
||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
and/or sell copies of the Software, and to permit persons to whom the
|
||
Software is furnished to do so, subject to the following conditions:
|
||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
The above copyright notice and this permission notice shall be included
|
||
in all copies or substantial portions of the Software.
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
THE SOFTWARE.
|
||
|
||
****************************************************************************
|
||
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
||
|
||
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
||
be copied by any method or incorporated into another program without
|
||
the express written consent of Aerospace C.Power. This Information or any portion
|
||
thereof remains the property of Aerospace C.Power. The Information contained herein
|
||
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
||
liability for its use in any way and conveys no license or title under
|
||
any patent or copyright and makes no representation or warranty that this
|
||
Information is free from patent or copyright infringement.
|
||
|
||
****************************************************************************/
|
||
/* This is file is modified for embeded use, as the memory is limited, the
|
||
* macro define version inlined would take IRAM for every instance, so we
|
||
* change it to the function version
|
||
*/
|
||
|
||
#include "iot_mem_pool.h"
|
||
#include "iot_errno.h"
|
||
#include "os_mem.h"
|
||
|
||
/*
|
||
* create a memory pool structure
|
||
* block_num - how many blocks can be used max
|
||
* block_size - sizeof(block)
|
||
* (OUT)pool_ptr - allocated start pointer for the pool if successful
|
||
* use_mutex - flag to mark if use mutex lock. if the pool will be used in
|
||
* multiple threads, set to 1. otherwise, set to 0.
|
||
*
|
||
* return 0 for success, other for error
|
||
*/
|
||
uint32_t iot_mem_pool_new(module_id_t m_id, uint32_t block_num,
|
||
uint32_t block_size, iot_mem_pool_t **pool_ptr, uint8_t use_mutex)
|
||
{
|
||
if (block_num == 0 || block_size == 0) {
|
||
pool_ptr = NULL;
|
||
return ERR_INVAL;
|
||
}
|
||
iot_mem_pool_t *p = os_mem_malloc(m_id, sizeof(iot_mem_pool_t));
|
||
if (p == NULL) {
|
||
pool_ptr = NULL;
|
||
return ERR_NOMEM;
|
||
}
|
||
else {
|
||
if (iot_mem_pool_init(m_id, block_num, block_size, p, use_mutex)) {
|
||
/* return fail */
|
||
os_mem_free(p);
|
||
pool_ptr = NULL;
|
||
return ERR_NOMEM;
|
||
}
|
||
*pool_ptr = p;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* init an exist memory pool structure
|
||
* block_num - how many blocks can be used max
|
||
* block_size - sizeof(block)
|
||
* (IN)pool_ptr - allocated start pointer for the pool if successful
|
||
* use_mutex - flag to mark if use mutex lock. if the pool will be used in
|
||
* multiple threads, set to 1. otherwise, set to 0.
|
||
*
|
||
* (OUT)return 0 for success, other for error
|
||
*/
|
||
uint32_t iot_mem_pool_init(module_id_t m_id,
|
||
uint32_t block_num, uint32_t block_size, iot_mem_pool_t *pool_ptr,
|
||
uint8_t use_mutex)
|
||
{
|
||
uint32_t size;
|
||
iot_mem_pool_entry_t *block_addr = NULL;
|
||
if (block_num == 0 || block_size == 0 || pool_ptr == 0) {
|
||
pool_ptr = NULL;
|
||
return ERR_INVAL;
|
||
}
|
||
IOT_ASSERT(block_num < 65535);
|
||
/* alloc the pool's mem, make it word align */
|
||
if (block_size % sizeof(iot_mem_pool_entry_t)) {
|
||
size = block_size / sizeof(iot_mem_pool_entry_t) + 1;
|
||
} else {
|
||
size = block_size / sizeof(iot_mem_pool_entry_t);
|
||
}
|
||
iot_mem_pool_t *p = pool_ptr;
|
||
{
|
||
p->entries = os_mem_malloc(m_id,
|
||
block_num * size * sizeof(iot_mem_pool_entry_t));
|
||
if (p->entries == NULL) {
|
||
pool_ptr = NULL;
|
||
return ERR_NOMEM;
|
||
}
|
||
p->pool_mutex = NULL;
|
||
if (use_mutex && (NULL == (p->pool_mutex = os_create_mutex(m_id)))) {
|
||
os_mem_free(p->entries);
|
||
pool_ptr = NULL;
|
||
return ERR_NOMEM;
|
||
}
|
||
}
|
||
/* init the pool */
|
||
p->head = (iot_mem_pool_entry_t*)&p->entries->data; /* the first data */
|
||
p->num = block_num;
|
||
p->free_num = block_num;
|
||
p->align_block_word_size = size;
|
||
for (uint32_t i = 0; i < block_num; i++) {
|
||
block_addr = p->entries + (size * i);
|
||
block_addr->next = (iot_mem_pool_entry_t*)&(block_addr + size)->data;
|
||
if (size > 1) {
|
||
*((uint32_t *)&block_addr->data + 1) = IOT_MEM_POOL_POISON;
|
||
}
|
||
}
|
||
/* fill last block's next to NULL */
|
||
block_addr->next = NULL;
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
/* destroy the pool
|
||
* NB: we shouldn't free the pool normally right now,
|
||
* for fast allocate and recall without memory frag
|
||
*
|
||
* TODO: consider the multi-context case
|
||
* pool_ptr - allocated start pointer for the pool if successful
|
||
* return 0 for success, other for error
|
||
*/
|
||
uint32_t iot_mem_pool_destroy(iot_mem_pool_t *pool_ptr)
|
||
{
|
||
if (pool_ptr) {
|
||
IOT_ASSERT(pool_ptr->free_num == pool_ptr->num);
|
||
if (pool_ptr->pool_mutex) {
|
||
os_delete_mutex(pool_ptr->pool_mutex);
|
||
}
|
||
os_mem_free(pool_ptr->entries);
|
||
pool_ptr->entries = NULL;
|
||
os_mem_free(pool_ptr);
|
||
return 0;
|
||
}
|
||
return ERR_INVAL;
|
||
}
|
||
|
||
void * iot_mem_pool_alloc_with_reserve(iot_mem_pool_t *pool_ptr,
|
||
uint32_t reserved)
|
||
{
|
||
iot_mem_pool_entry_t *p_entry;
|
||
|
||
if (pool_ptr == NULL) {
|
||
return NULL;
|
||
}
|
||
|
||
if (pool_ptr->pool_mutex) {
|
||
os_acquire_mutex(pool_ptr->pool_mutex);
|
||
}
|
||
|
||
if (pool_ptr->free_num <= reserved) {
|
||
if (pool_ptr->pool_mutex) {
|
||
os_release_mutex(pool_ptr->pool_mutex);
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
p_entry = pool_ptr->head;
|
||
pool_ptr->head = p_entry->next;
|
||
pool_ptr->free_num--;
|
||
|
||
if ((pool_ptr->num - pool_ptr->free_num) > pool_ptr->max_num) {
|
||
pool_ptr->max_num = (uint16_t)(pool_ptr->num - pool_ptr->free_num);
|
||
}
|
||
if (pool_ptr->pool_mutex) {
|
||
os_release_mutex(pool_ptr->pool_mutex);
|
||
}
|
||
|
||
return &p_entry->data;
|
||
}
|
||
|
||
uint32_t iot_mem_pool_free(iot_mem_pool_t *pool_ptr, void *data)
|
||
{
|
||
if (NULL == pool_ptr) {
|
||
return ERR_INVAL;
|
||
}
|
||
iot_mem_pool_t *p = pool_ptr;
|
||
iot_mem_pool_entry_t *p_entry = (iot_mem_pool_entry_t *)data;
|
||
|
||
if ((uint32_t)p_entry < (uint32_t)&p->entries->data
|
||
|| (uint32_t)p_entry >
|
||
(uint32_t)(&p->entries->data + p->num * p->align_block_word_size)) {
|
||
IOT_ASSERT(0);
|
||
return ERR_INVAL;
|
||
}
|
||
/* improved check if the correct entry address */
|
||
IOT_ASSERT((((uint32_t*)data - &p->entries->data) \
|
||
% (p->align_block_word_size)) == 0);
|
||
|
||
if (pool_ptr->align_block_word_size > 1) {
|
||
uint32_t *free_ck_addr = (uint32_t *)data + 1;
|
||
#if IOT_MEM_POOL_DOUBLE_FREE_DBG
|
||
IOT_ASSERT((uint32_t)IOT_MEM_POOL_POISON != *free_ck_addr);
|
||
#endif
|
||
*free_ck_addr = (uint32_t)IOT_MEM_POOL_POISON;
|
||
}
|
||
if (pool_ptr->pool_mutex) {
|
||
os_acquire_mutex(pool_ptr->pool_mutex);
|
||
}
|
||
p_entry->next = p->head;
|
||
p->head = p_entry;
|
||
pool_ptr->free_num++;
|
||
if (pool_ptr->pool_mutex) {
|
||
os_release_mutex(pool_ptr->pool_mutex);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
uint32_t iot_mem_pool_force_free(iot_mem_pool_t *pool_ptr, void *data)
|
||
{
|
||
if (NULL == pool_ptr) {
|
||
return ERR_INVAL;
|
||
}
|
||
iot_mem_pool_t *p = pool_ptr;
|
||
iot_mem_pool_entry_t *p_entry = (iot_mem_pool_entry_t *)data;
|
||
|
||
if ((uint32_t)p_entry < (uint32_t)&p->entries->data
|
||
|| (uint32_t)p_entry >
|
||
(uint32_t)(&p->entries->data + p->num * p->align_block_word_size)) {
|
||
//IOT_ASSERT(0);
|
||
return ERR_INVAL;
|
||
}
|
||
return iot_mem_pool_free(pool_ptr, data);
|
||
}
|
||
|
||
uint32_t iot_mem_pool_get_freenum(iot_mem_pool_t *pool_ptr)
|
||
{
|
||
uint32_t freenum = 0;
|
||
if (NULL == pool_ptr) {
|
||
return freenum;
|
||
}
|
||
|
||
freenum = pool_ptr->free_num;
|
||
|
||
return freenum;
|
||
}
|
||
|
||
uint32_t iot_mem_pool_get_align_size(iot_mem_pool_t *pool_ptr)
|
||
{
|
||
uint32_t align_size = 0;
|
||
if (NULL == pool_ptr) {
|
||
return align_size;
|
||
}
|
||
|
||
align_size = pool_ptr->align_block_word_size * sizeof(iot_mem_pool_entry_t);
|
||
|
||
return align_size;
|
||
}
|