275 lines
8.7 KiB
C
275 lines
8.7 KiB
C
|
/****************************************************************************
|
|||
|
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;
|
|||
|
}
|