2021-11-16 21:41:57 +08:00

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);
}