mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-15 17:02:53 +08:00
243 lines
7.4 KiB
C
243 lines
7.4 KiB
C
/*
|
|
* This file is part of the PikaScript project.
|
|
* http://github.com/pikastech/pikascript
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include "dataMemory.h"
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
PikaMemInfo pikaMemInfo = {0};
|
|
|
|
void* pikaMalloc(uint32_t size) {
|
|
/* pika memory lock */
|
|
while (__isLocked_pikaMemory()) {
|
|
}
|
|
pikaMemInfo.heapUsed += size;
|
|
if (pikaMemInfo.heapUsedMax < pikaMemInfo.heapUsed) {
|
|
pikaMemInfo.heapUsedMax = pikaMemInfo.heapUsed;
|
|
}
|
|
__platformDisableIrqHandle();
|
|
void* mem = __impl_pikaMalloc(size);
|
|
__platformEnableIrqHandle();
|
|
if (NULL == mem) {
|
|
__platformPrintf(
|
|
"[error]: No heap space! Please reset the device.\r\n");
|
|
while (1) {
|
|
}
|
|
}
|
|
return mem;
|
|
}
|
|
|
|
void pikaFree(void* mem, uint32_t size) {
|
|
/* pika memory lock */
|
|
while (__isLocked_pikaMemory()) {
|
|
}
|
|
__platformDisableIrqHandle();
|
|
__impl_pikaFree(mem, size);
|
|
__platformEnableIrqHandle();
|
|
pikaMemInfo.heapUsed -= size;
|
|
}
|
|
|
|
uint16_t pikaMemNow(void) {
|
|
return pikaMemInfo.heapUsed;
|
|
}
|
|
|
|
uint16_t pikaMemMax(void) {
|
|
return pikaMemInfo.heapUsedMax;
|
|
}
|
|
|
|
void pikaMemMaxReset(void) {
|
|
pikaMemInfo.heapUsedMax = 0;
|
|
}
|
|
|
|
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 = __platformMalloc(pool_aline(&pool, pool.size));
|
|
pool.block_index_min_free = 0;
|
|
return pool;
|
|
}
|
|
|
|
void pool_deinit(Pool* pool) {
|
|
__platformFree(pool->mem);
|
|
pool->mem = NULL;
|
|
bitmap_deinit(pool->bitmap);
|
|
}
|
|
|
|
void* pool_getMem_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 = (uint64_t)mem - (uint64_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);
|
|
__platformPrintf("[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;
|
|
}
|
|
__platformPrintf("0x%x\t: ", 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;
|
|
}
|
|
__platformPrintf("%d", bitmap_get(pool->bitmap, k));
|
|
}
|
|
__platformPrintf(" ");
|
|
}
|
|
__platformPrintf("\r\n");
|
|
}
|
|
}
|
|
|
|
void* pool_malloc(Pool* pool, uint32_t size) {
|
|
void* mem = NULL;
|
|
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;
|
|
for (uint32_t block_index = pool->block_index_min_free;
|
|
block_index < block_index_max; 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->block_index_min_free = 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) {
|
|
/* set 1 for found blocks */
|
|
for (uint32_t i = 0; i < block_num_need; i++) {
|
|
bitmap_set(pool->bitmap, block_index - i, 1);
|
|
}
|
|
/* return mem by block index */
|
|
return pool_getMem_byBlockIndex(pool,
|
|
block_index - block_num_need + 1);
|
|
}
|
|
}
|
|
return mem;
|
|
}
|
|
|
|
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->block_index_min_free) {
|
|
pool->block_index_min_free = block_index;
|
|
}
|
|
return;
|
|
}
|
|
|
|
uint32_t aline_by(uint32_t size, uint32_t aline) {
|
|
if (size == 0) {
|
|
return 0;
|
|
}
|
|
return ((size - 1) / aline + 1) * aline;
|
|
}
|
|
|
|
BitMap bitmap_init(uint32_t size) {
|
|
BitMap mem_bit_map =
|
|
(BitMap)__platformMalloc(((size - 1) / 8 + 1) * sizeof(char));
|
|
if (mem_bit_map == NULL)
|
|
NULL;
|
|
uint32_t size_mem_bit_map = (size - 1) / 8 + 1;
|
|
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) {
|
|
__platformFree(bitmap);
|
|
} |