mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-02-05 17:28:23 +08:00
325 lines
9.7 KiB
C
325 lines
9.7 KiB
C
/*
|
|
* This file is part of the PikaPython project.
|
|
* http://github.com/pikastech/pikapython
|
|
*
|
|
* MIT License
|
|
*
|
|
* Copyright (c) 2021 lyon liang6516@outlook.com
|
|
*
|
|
* 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:
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#define __DATA_MEMORY_CLASS_IMPLEMENT__
|
|
#include "dataMemory.h"
|
|
#include "PikaPlatform.h"
|
|
|
|
volatile PikaMemInfo g_PikaMemInfo = {0};
|
|
|
|
void* pikaMalloc(uint32_t size) {
|
|
/* pika memory lock */
|
|
if (0 != pika_is_locked_pikaMemory()) {
|
|
pika_platform_wait();
|
|
}
|
|
|
|
//! if you unsure about the __impl_pikaMalloc, uncomment this to force alignment
|
|
#if PIKA_ARG_ALIGN_ENABLE
|
|
/* force alignment to avoid unaligned access */
|
|
size = mem_align(size);
|
|
#endif
|
|
|
|
g_PikaMemInfo.heapUsed += size;
|
|
if (g_PikaMemInfo.heapUsedMax < g_PikaMemInfo.heapUsed) {
|
|
g_PikaMemInfo.heapUsedMax = g_PikaMemInfo.heapUsed;
|
|
}
|
|
pika_platform_disable_irq_handle();
|
|
void* mem = pika_user_malloc(size);
|
|
pika_platform_enable_irq_handle();
|
|
if (NULL == mem) {
|
|
pika_platform_printf(
|
|
"Error: No heap space! Please reset the device.\r\n");
|
|
while (1) {
|
|
}
|
|
}
|
|
return mem;
|
|
}
|
|
|
|
void pikaFree(void* mem, uint32_t size) {
|
|
if (0 != pika_is_locked_pikaMemory()) {
|
|
pika_platform_wait();
|
|
}
|
|
|
|
//! if you unsure about the __impl_pikaMalloc, uncomment this to force alignment
|
|
#if PIKA_ARG_ALIGN_ENABLE
|
|
/* force alignment to avoid unaligned access */
|
|
size = mem_align(size);
|
|
#endif
|
|
|
|
pika_platform_disable_irq_handle();
|
|
pika_user_free(mem, size);
|
|
pika_platform_enable_irq_handle();
|
|
g_PikaMemInfo.heapUsed -= size;
|
|
}
|
|
|
|
uint32_t pikaMemNow(void) {
|
|
return g_PikaMemInfo.heapUsed;
|
|
// return 0;
|
|
}
|
|
|
|
uint32_t pikaMemMax(void) {
|
|
return g_PikaMemInfo.heapUsedMax;
|
|
}
|
|
|
|
void pikaMemMaxReset(void) {
|
|
g_PikaMemInfo.heapUsedMax = 0;
|
|
}
|
|
|
|
#if PIKA_POOL_ENABLE
|
|
uint32_t pool_getBlockIndex_byMemSize(Pool* pool, uint32_t size) {
|
|
if (0 == size) {
|
|
return 0;
|
|
}
|
|
return (size - 1) / pool->aline + 1;
|
|
}
|
|
|
|
uint32_t pool_aline(Pool* pool, uint32_t size) {
|
|
return pool_getBlockIndex_byMemSize(pool, size) * pool->aline;
|
|
}
|
|
|
|
Pool pool_init(uint32_t size, uint8_t aline) {
|
|
Pool pool;
|
|
pool.aline = aline;
|
|
uint32_t block_size = pool_getBlockIndex_byMemSize(&pool, size);
|
|
pool.size = pool_aline(&pool, size);
|
|
pool.bitmap = bitmap_init(block_size);
|
|
pool.mem = pika_platform_malloc(pool_aline(&pool, pool.size));
|
|
pool.first_free_block = 0;
|
|
pool.purl_free_block_start = 0;
|
|
pool.inited = pika_true;
|
|
return pool;
|
|
}
|
|
|
|
void pool_deinit(Pool* pool) {
|
|
pika_platform_free(pool->mem);
|
|
pool->mem = NULL;
|
|
bitmap_deinit(pool->bitmap);
|
|
}
|
|
|
|
void* pool_getBytes_byBlockIndex(Pool* pool, uint32_t block_index) {
|
|
return pool->mem + block_index * pool->aline;
|
|
}
|
|
|
|
uint32_t pool_getBlockIndex_byMem(Pool* pool, void* mem) {
|
|
uint32_t mem_size = (uintptr_t)mem - (uintptr_t)pool->mem;
|
|
return pool_getBlockIndex_byMemSize(pool, mem_size);
|
|
}
|
|
|
|
void pool_printBlocks(Pool* pool, uint32_t size_min, uint32_t size_max) {
|
|
uint32_t block_index_min = pool_getBlockIndex_byMemSize(pool, size_min);
|
|
uint32_t block_index_max = pool_getBlockIndex_byMemSize(pool, size_max);
|
|
pika_platform_printf("[bitmap]\r\n");
|
|
uint8_t is_end = 0;
|
|
for (uint32_t i = block_index_min; i < block_index_max; i += 16) {
|
|
if (is_end) {
|
|
break;
|
|
}
|
|
pika_platform_printf("0x%x\t: 0x%d", i * pool->aline,
|
|
(i + 15) * pool->aline);
|
|
for (uint32_t j = i; j < i + 16; j += 4) {
|
|
if (is_end) {
|
|
break;
|
|
}
|
|
for (uint32_t k = j; k < j + 4; k++) {
|
|
if (k >= block_index_max) {
|
|
is_end = 1;
|
|
break;
|
|
}
|
|
pika_platform_printf("%d", bitmap_get(pool->bitmap, k));
|
|
}
|
|
pika_platform_printf(" ");
|
|
}
|
|
pika_platform_printf("\r\n");
|
|
}
|
|
}
|
|
|
|
void* pool_malloc(Pool* pool, uint32_t size) {
|
|
uint32_t block_index_max = pool_getBlockIndex_byMemSize(pool, pool->size);
|
|
uint32_t block_num_need = pool_getBlockIndex_byMemSize(pool, size);
|
|
uint32_t block_num_found = 0;
|
|
uint8_t found_first_free = 0;
|
|
uint32_t block_index;
|
|
/* high speed malloc */
|
|
block_index = pool->purl_free_block_start + block_num_need - 1;
|
|
if (block_index < block_index_max) {
|
|
goto found;
|
|
}
|
|
/* low speed malloc */
|
|
for (block_index = pool->first_free_block;
|
|
block_index < pool->purl_free_block_start; block_index++) {
|
|
/* 8 bit is not free */
|
|
uint8_t bitmap_byte = bitmap_getByte(pool->bitmap, block_index);
|
|
if (0xFF == bitmap_byte) {
|
|
block_index = 8 * (block_index / 8) + 7;
|
|
block_num_found = 0;
|
|
continue;
|
|
}
|
|
/* found a free block */
|
|
if (0 == bitmap_get(pool->bitmap, block_index)) {
|
|
/* save the first free */
|
|
if (!found_first_free) {
|
|
pool->first_free_block = block_index;
|
|
found_first_free = 1;
|
|
}
|
|
block_num_found++;
|
|
} else {
|
|
/* a used block appeared, find again */
|
|
block_num_found = 0;
|
|
}
|
|
/* found all request blocks */
|
|
if (block_num_found >= block_num_need) {
|
|
goto found;
|
|
}
|
|
}
|
|
/* malloc for purl free blocks */
|
|
block_index = pool->purl_free_block_start + block_num_need - 1;
|
|
if (block_index < block_index_max) {
|
|
goto found;
|
|
}
|
|
|
|
/* no found */
|
|
return NULL;
|
|
found:
|
|
/* set 1 for found blocks */
|
|
for (uint32_t i = 0; i < block_num_need; i++) {
|
|
bitmap_set(pool->bitmap, block_index - i, 1);
|
|
}
|
|
/* save last used block */
|
|
if (block_index >= pool->purl_free_block_start) {
|
|
pool->purl_free_block_start = block_index + 1;
|
|
}
|
|
/* return mem by block index */
|
|
return pool_getBytes_byBlockIndex(pool, block_index - block_num_need + 1);
|
|
}
|
|
|
|
void pool_free(Pool* pool, void* mem, uint32_t size) {
|
|
uint32_t block_num = pool_getBlockIndex_byMemSize(pool, size);
|
|
uint32_t block_index = pool_getBlockIndex_byMem(pool, mem);
|
|
for (uint32_t i = 0; i < block_num; i++) {
|
|
bitmap_set(pool->bitmap, block_index + i, 0);
|
|
}
|
|
/* save min free block index to add speed */
|
|
if (block_index < pool->first_free_block) {
|
|
pool->first_free_block = block_index;
|
|
}
|
|
/* save last free block index to add speed */
|
|
uint32_t block_end = block_index + block_num - 1;
|
|
if (block_end == pool->purl_free_block_start - 1) {
|
|
uint32_t first_pure_free_block = block_index;
|
|
/* back to first used block */
|
|
if (0 != first_pure_free_block) {
|
|
while (0 == bitmap_get(pool->bitmap, first_pure_free_block - 1)) {
|
|
first_pure_free_block--;
|
|
if (0 == first_pure_free_block) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pool->purl_free_block_start = first_pure_free_block;
|
|
}
|
|
return;
|
|
}
|
|
|
|
BitMap bitmap_init(uint32_t size) {
|
|
BitMap mem_bit_map =
|
|
(BitMap)pika_platform_malloc(((size - 1) / 8 + 1) * sizeof(char));
|
|
if (mem_bit_map == NULL) {
|
|
return NULL;
|
|
}
|
|
uint32_t size_mem_bit_map = (size - 1) / 8 + 1;
|
|
pika_platform_memset(mem_bit_map, 0x0, size_mem_bit_map);
|
|
return mem_bit_map;
|
|
}
|
|
|
|
void bitmap_set(BitMap bitmap, uint32_t index, uint8_t bit) {
|
|
uint32_t index_byte = index / 8;
|
|
uint8_t index_bit = index % 8;
|
|
uint8_t x = (0x1 << index_bit);
|
|
/* set 1 */
|
|
if (bit) {
|
|
bitmap[index_byte] |= x;
|
|
return;
|
|
}
|
|
/* set 0 */
|
|
bitmap[index_byte] &= ~x;
|
|
return;
|
|
}
|
|
|
|
uint8_t bitmap_getByte(BitMap bitmap, uint32_t index) {
|
|
uint32_t index_byte = (index) / 8;
|
|
uint8_t byte;
|
|
byte = bitmap[index_byte];
|
|
return byte;
|
|
}
|
|
|
|
uint8_t bitmap_get(BitMap bitmap, uint32_t index) {
|
|
uint32_t index_byte = (index) / 8;
|
|
uint8_t index_bit = (index) % 8;
|
|
uint8_t x = (0x1 << index_bit);
|
|
uint8_t bit;
|
|
bit = bitmap[index_byte] & x;
|
|
return bit > 0 ? 1 : 0;
|
|
}
|
|
|
|
void bitmap_deinit(BitMap bitmap) {
|
|
pika_platform_free(bitmap);
|
|
}
|
|
|
|
Pool pikaPool = {0};
|
|
void* pika_user_malloc(size_t size) {
|
|
return pool_malloc(&pikaPool, size);
|
|
}
|
|
void pika_user_free(void* ptrm, size_t size) {
|
|
pool_free(&pikaPool, ptrm, size);
|
|
}
|
|
#endif
|
|
|
|
void mem_pool_init(void) {
|
|
#if PIKA_POOL_ENABLE
|
|
if (!pikaPool.inited) {
|
|
pikaPool = pool_init(PIKA_POOL_SIZE, PIKA_POOL_ALIGN);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void _mem_cache_deinit(void) {
|
|
#if PIKA_ARG_CACHE_ENABLE
|
|
while (g_PikaMemInfo.cache_pool_top) {
|
|
pika_user_free(
|
|
g_PikaMemInfo.cache_pool[g_PikaMemInfo.cache_pool_top - 1], 0);
|
|
g_PikaMemInfo.cache_pool_top--;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void mem_pool_deinit(void) {
|
|
_mem_cache_deinit();
|
|
#if PIKA_POOL_ENABLE
|
|
pool_deinit(&pikaPool);
|
|
#endif
|
|
}
|