/* * 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) { pika_assert(mem != NULL); 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 }