2024-05-16 01:47:21 +10:00
|
|
|
#include <furi.h>
|
|
|
|
|
#include <tlsf.h>
|
|
|
|
|
#include <tlsf_block_functions.h>
|
2023-11-01 16:24:11 +09:00
|
|
|
#include <FreeRTOS.h>
|
|
|
|
|
#include <task.h>
|
2024-05-16 01:47:21 +10:00
|
|
|
#include <m-dict.h>
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2021-07-25 22:37:43 +10:00
|
|
|
extern const void __heap_start__;
|
|
|
|
|
extern const void __heap_end__;
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
static tlsf_t tlsf = NULL;
|
|
|
|
|
static size_t heap_used = 0;
|
|
|
|
|
static size_t heap_max_used = 0;
|
|
|
|
|
|
|
|
|
|
// Allocation tracking types
|
2023-10-13 01:34:30 +09:00
|
|
|
DICT_DEF2(MemmgrHeapAllocDict, uint32_t, uint32_t) //-V1048
|
|
|
|
|
|
|
|
|
|
DICT_DEF2( //-V1048
|
2021-06-23 17:48:44 +03:00
|
|
|
MemmgrHeapThreadDict,
|
|
|
|
|
uint32_t,
|
|
|
|
|
M_DEFAULT_OPLIST,
|
|
|
|
|
MemmgrHeapAllocDict_t,
|
|
|
|
|
DICT_OPLIST(MemmgrHeapAllocDict))
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// Thread allocation tracing storage
|
2021-06-23 17:48:44 +03:00
|
|
|
static MemmgrHeapThreadDict_t memmgr_heap_thread_dict = {0};
|
|
|
|
|
static volatile uint32_t memmgr_heap_thread_trace_depth = 0;
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
static inline void memmgr_lock(void) {
|
|
|
|
|
vTaskSuspendAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void memmgr_unlock(void) {
|
|
|
|
|
xTaskResumeAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline size_t memmgr_get_heap_size(void) {
|
|
|
|
|
return (size_t)&__heap_end__ - (size_t)&__heap_start__;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize tracing storage
|
|
|
|
|
static void memmgr_heap_init(void) {
|
2021-06-23 17:48:44 +03:00
|
|
|
MemmgrHeapThreadDict_init(memmgr_heap_thread_dict);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
__attribute__((constructor)) static void memmgr_init(void) {
|
|
|
|
|
size_t pool_size = (size_t)&__heap_end__ - (size_t)&__heap_start__;
|
|
|
|
|
tlsf = tlsf_create_with_pool((void*)&__heap_start__, pool_size, pool_size);
|
|
|
|
|
memmgr_heap_init();
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-20 17:54:48 +03:00
|
|
|
void memmgr_heap_enable_thread_trace(FuriThreadId thread_id) {
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_lock();
|
2021-06-23 17:48:44 +03:00
|
|
|
{
|
|
|
|
|
memmgr_heap_thread_trace_depth++;
|
2021-07-07 11:57:49 +03:00
|
|
|
furi_check(MemmgrHeapThreadDict_get(memmgr_heap_thread_dict, (uint32_t)thread_id) == NULL);
|
2021-06-23 17:48:44 +03:00
|
|
|
MemmgrHeapAllocDict_t alloc_dict;
|
|
|
|
|
MemmgrHeapAllocDict_init(alloc_dict);
|
|
|
|
|
MemmgrHeapThreadDict_set_at(memmgr_heap_thread_dict, (uint32_t)thread_id, alloc_dict);
|
2021-06-24 16:16:03 +03:00
|
|
|
MemmgrHeapAllocDict_clear(alloc_dict);
|
2021-06-23 17:48:44 +03:00
|
|
|
memmgr_heap_thread_trace_depth--;
|
|
|
|
|
}
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_unlock();
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
|
2022-06-20 17:54:48 +03:00
|
|
|
void memmgr_heap_disable_thread_trace(FuriThreadId thread_id) {
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_lock();
|
2021-06-23 17:48:44 +03:00
|
|
|
{
|
|
|
|
|
memmgr_heap_thread_trace_depth++;
|
2022-11-06 00:07:24 +09:00
|
|
|
furi_check(MemmgrHeapThreadDict_erase(memmgr_heap_thread_dict, (uint32_t)thread_id));
|
2021-06-23 17:48:44 +03:00
|
|
|
memmgr_heap_thread_trace_depth--;
|
|
|
|
|
}
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_unlock();
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
static inline void memmgr_heap_trace_malloc(void* pointer, size_t size) {
|
|
|
|
|
FuriThreadId thread_id = furi_thread_get_current_id();
|
|
|
|
|
if(thread_id && memmgr_heap_thread_trace_depth == 0) {
|
2021-06-23 17:48:44 +03:00
|
|
|
memmgr_heap_thread_trace_depth++;
|
|
|
|
|
MemmgrHeapAllocDict_t* alloc_dict =
|
|
|
|
|
MemmgrHeapThreadDict_get(memmgr_heap_thread_dict, (uint32_t)thread_id);
|
2021-09-16 19:12:07 +03:00
|
|
|
if(alloc_dict) {
|
2024-05-16 01:47:21 +10:00
|
|
|
MemmgrHeapAllocDict_set_at(*alloc_dict, (uint32_t)pointer, (uint32_t)size);
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
memmgr_heap_thread_trace_depth--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
static inline void memmgr_heap_trace_free(void* pointer) {
|
2022-06-20 17:54:48 +03:00
|
|
|
FuriThreadId thread_id = furi_thread_get_current_id();
|
2021-06-23 17:48:44 +03:00
|
|
|
if(thread_id && memmgr_heap_thread_trace_depth == 0) {
|
|
|
|
|
memmgr_heap_thread_trace_depth++;
|
|
|
|
|
MemmgrHeapAllocDict_t* alloc_dict =
|
|
|
|
|
MemmgrHeapThreadDict_get(memmgr_heap_thread_dict, (uint32_t)thread_id);
|
|
|
|
|
if(alloc_dict) {
|
2024-05-16 01:47:21 +10:00
|
|
|
// In some cases thread may want to release memory that was not allocated by it
|
|
|
|
|
const bool res = MemmgrHeapAllocDict_erase(*alloc_dict, (uint32_t)pointer);
|
|
|
|
|
UNUSED(res);
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
memmgr_heap_thread_trace_depth--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
size_t memmgr_heap_get_thread_memory(FuriThreadId thread_id) {
|
|
|
|
|
size_t leftovers = MEMMGR_HEAP_UNKNOWN;
|
|
|
|
|
memmgr_lock();
|
|
|
|
|
{
|
2021-06-23 17:48:44 +03:00
|
|
|
memmgr_heap_thread_trace_depth++;
|
|
|
|
|
MemmgrHeapAllocDict_t* alloc_dict =
|
|
|
|
|
MemmgrHeapThreadDict_get(memmgr_heap_thread_dict, (uint32_t)thread_id);
|
|
|
|
|
if(alloc_dict) {
|
2024-05-16 01:47:21 +10:00
|
|
|
leftovers = 0;
|
|
|
|
|
MemmgrHeapAllocDict_it_t alloc_dict_it;
|
|
|
|
|
for(MemmgrHeapAllocDict_it(alloc_dict_it, *alloc_dict);
|
|
|
|
|
!MemmgrHeapAllocDict_end_p(alloc_dict_it);
|
|
|
|
|
MemmgrHeapAllocDict_next(alloc_dict_it)) {
|
|
|
|
|
MemmgrHeapAllocDict_itref_t* data = MemmgrHeapAllocDict_ref(alloc_dict_it);
|
|
|
|
|
if(data->key != 0) {
|
|
|
|
|
block_header_t* block = block_from_ptr((uint8_t*)data->key);
|
|
|
|
|
if(!block_is_free(block)) {
|
|
|
|
|
leftovers += data->value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
memmgr_heap_thread_trace_depth--;
|
|
|
|
|
}
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_unlock();
|
|
|
|
|
return leftovers;
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
static bool tlsf_walker_max_free(void* ptr, size_t size, int used, void* user) {
|
|
|
|
|
UNUSED(ptr);
|
2021-07-05 23:01:02 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
bool free = !used;
|
|
|
|
|
size_t* max_free_block_size = (size_t*)user;
|
|
|
|
|
if(free && size > *max_free_block_size) {
|
|
|
|
|
*max_free_block_size = size;
|
2021-07-05 23:01:02 +10:00
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
return true;
|
2021-07-05 23:01:02 +10:00
|
|
|
}
|
[FL-1191][FL-1524] Filesystem rework (#568)
* FS-Api: removed datetime manipulation functions and most of the file flags
* Filesystem: common proxy api
* Filesystem: renamed to Storage. Work has begun on a glue layer. Added functions for reentrance.
* Storage: sd mount and sd file open
* Storage: sd file close
* Storage: temporary test app
* Storage: free filedata on close
* Storage: sd file read and write
* Storage: added internal storage (LittleFS)
* Storage: renamed internal commands
* Storage: seek, tell, truncate, size, sync, eof
* Storage: error descriptions
* Storage: directory management api (open, close, read, rewind)
* Storage: common management api (stat, fs_stat, remove, rename, mkdir)
* Dolphin app and Notifications app now use raw storage.
* Storage: storage statuses renamed. Implemented sd card icon.
* Storage: added raw sd-card api.
* Storage settings: work started
* Assets: use new icons approach
* Storage settings: working storage settings
* Storage: completely redesigned api, no longer sticking out FS_Api
* Storage: more simplified api, getting error_id from file is hidden from user, pointer to api is hidden inside file
* Storage: cli info and format commands
* Storage-cli: file list
* Storage: a simpler and more reliable api
* FatFS: slightly lighter and faster config. Also disabled reentrancy and file locking functions. They moved to a storage service.
* Storage-cli: accommodate to the new cli api.
* Storage: filesystem api is separated into internal and common api.
* Cli: added the ability to print the list of free heap blocks
* Storage: uses a list instead of an array to store the StorageFile. Rewrote api calls to use semaphores instead of thread flags.
* Storage settings: added the ability to benchmark the SD card.
* Gui module file select: uses new storage api
* Apps: removed deprecated sd_card_test application
* Args lib: support for enquoted arguments
* Dialogs: a new gui app for simple non-asynchronous apps
* Dialogs: view holder for easy single view work
* File worker: use new storage api
* IButton and lfrrfid apps: save keys to any storage
* Apps: fix ibutton and lfrfid stack, remove sd_card_test.
* SD filesystem: app removed
* File worker: fixed api pointer type
* Subghz: loading assets using the new storage api
* NFC: use the new storage api
* Dialogs: the better api for the message element
* Archive: use new storage api
* Irda: changed assest path, changed app path
* FileWorker: removed unused file_buf_cnt
* Storage: copying and renaming files now works between storages
* Storage cli: read, copy, remove, rename commands
* Archive: removed commented code
* Storage cli: write command
* Applications: add SRV_STORAGE and SRV_DIALOGS
* Internal-storage: removed
* Storage: improved api
* Storage app: changed api pointer from StorageApp to Storage
* Storage: better file_id handling
* Storage: more consistent errors
* Loader: support for NULL icons
* Storage: do nothing with the lfs file or directory if it is not open
* Storage: fix typo
* Storage: minor float usage cleanup, rename some symbols.
* Storage: compact doxygen comments.
Co-authored-by: あく <alleteam@gmail.com>
2021-07-23 22:20:19 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
size_t memmgr_heap_get_max_free_block(void) {
|
|
|
|
|
size_t max_free_block_size = 0;
|
[FL-1191][FL-1524] Filesystem rework (#568)
* FS-Api: removed datetime manipulation functions and most of the file flags
* Filesystem: common proxy api
* Filesystem: renamed to Storage. Work has begun on a glue layer. Added functions for reentrance.
* Storage: sd mount and sd file open
* Storage: sd file close
* Storage: temporary test app
* Storage: free filedata on close
* Storage: sd file read and write
* Storage: added internal storage (LittleFS)
* Storage: renamed internal commands
* Storage: seek, tell, truncate, size, sync, eof
* Storage: error descriptions
* Storage: directory management api (open, close, read, rewind)
* Storage: common management api (stat, fs_stat, remove, rename, mkdir)
* Dolphin app and Notifications app now use raw storage.
* Storage: storage statuses renamed. Implemented sd card icon.
* Storage: added raw sd-card api.
* Storage settings: work started
* Assets: use new icons approach
* Storage settings: working storage settings
* Storage: completely redesigned api, no longer sticking out FS_Api
* Storage: more simplified api, getting error_id from file is hidden from user, pointer to api is hidden inside file
* Storage: cli info and format commands
* Storage-cli: file list
* Storage: a simpler and more reliable api
* FatFS: slightly lighter and faster config. Also disabled reentrancy and file locking functions. They moved to a storage service.
* Storage-cli: accommodate to the new cli api.
* Storage: filesystem api is separated into internal and common api.
* Cli: added the ability to print the list of free heap blocks
* Storage: uses a list instead of an array to store the StorageFile. Rewrote api calls to use semaphores instead of thread flags.
* Storage settings: added the ability to benchmark the SD card.
* Gui module file select: uses new storage api
* Apps: removed deprecated sd_card_test application
* Args lib: support for enquoted arguments
* Dialogs: a new gui app for simple non-asynchronous apps
* Dialogs: view holder for easy single view work
* File worker: use new storage api
* IButton and lfrrfid apps: save keys to any storage
* Apps: fix ibutton and lfrfid stack, remove sd_card_test.
* SD filesystem: app removed
* File worker: fixed api pointer type
* Subghz: loading assets using the new storage api
* NFC: use the new storage api
* Dialogs: the better api for the message element
* Archive: use new storage api
* Irda: changed assest path, changed app path
* FileWorker: removed unused file_buf_cnt
* Storage: copying and renaming files now works between storages
* Storage cli: read, copy, remove, rename commands
* Archive: removed commented code
* Storage cli: write command
* Applications: add SRV_STORAGE and SRV_DIALOGS
* Internal-storage: removed
* Storage: improved api
* Storage app: changed api pointer from StorageApp to Storage
* Storage: better file_id handling
* Storage: more consistent errors
* Loader: support for NULL icons
* Storage: do nothing with the lfs file or directory if it is not open
* Storage: fix typo
* Storage: minor float usage cleanup, rename some symbols.
* Storage: compact doxygen comments.
Co-authored-by: あく <alleteam@gmail.com>
2021-07-23 22:20:19 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_lock();
|
[FL-1191][FL-1524] Filesystem rework (#568)
* FS-Api: removed datetime manipulation functions and most of the file flags
* Filesystem: common proxy api
* Filesystem: renamed to Storage. Work has begun on a glue layer. Added functions for reentrance.
* Storage: sd mount and sd file open
* Storage: sd file close
* Storage: temporary test app
* Storage: free filedata on close
* Storage: sd file read and write
* Storage: added internal storage (LittleFS)
* Storage: renamed internal commands
* Storage: seek, tell, truncate, size, sync, eof
* Storage: error descriptions
* Storage: directory management api (open, close, read, rewind)
* Storage: common management api (stat, fs_stat, remove, rename, mkdir)
* Dolphin app and Notifications app now use raw storage.
* Storage: storage statuses renamed. Implemented sd card icon.
* Storage: added raw sd-card api.
* Storage settings: work started
* Assets: use new icons approach
* Storage settings: working storage settings
* Storage: completely redesigned api, no longer sticking out FS_Api
* Storage: more simplified api, getting error_id from file is hidden from user, pointer to api is hidden inside file
* Storage: cli info and format commands
* Storage-cli: file list
* Storage: a simpler and more reliable api
* FatFS: slightly lighter and faster config. Also disabled reentrancy and file locking functions. They moved to a storage service.
* Storage-cli: accommodate to the new cli api.
* Storage: filesystem api is separated into internal and common api.
* Cli: added the ability to print the list of free heap blocks
* Storage: uses a list instead of an array to store the StorageFile. Rewrote api calls to use semaphores instead of thread flags.
* Storage settings: added the ability to benchmark the SD card.
* Gui module file select: uses new storage api
* Apps: removed deprecated sd_card_test application
* Args lib: support for enquoted arguments
* Dialogs: a new gui app for simple non-asynchronous apps
* Dialogs: view holder for easy single view work
* File worker: use new storage api
* IButton and lfrrfid apps: save keys to any storage
* Apps: fix ibutton and lfrfid stack, remove sd_card_test.
* SD filesystem: app removed
* File worker: fixed api pointer type
* Subghz: loading assets using the new storage api
* NFC: use the new storage api
* Dialogs: the better api for the message element
* Archive: use new storage api
* Irda: changed assest path, changed app path
* FileWorker: removed unused file_buf_cnt
* Storage: copying and renaming files now works between storages
* Storage cli: read, copy, remove, rename commands
* Archive: removed commented code
* Storage cli: write command
* Applications: add SRV_STORAGE and SRV_DIALOGS
* Internal-storage: removed
* Storage: improved api
* Storage app: changed api pointer from StorageApp to Storage
* Storage: better file_id handling
* Storage: more consistent errors
* Loader: support for NULL icons
* Storage: do nothing with the lfs file or directory if it is not open
* Storage: fix typo
* Storage: minor float usage cleanup, rename some symbols.
* Storage: compact doxygen comments.
Co-authored-by: あく <alleteam@gmail.com>
2021-07-23 22:20:19 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
pool_t pool = tlsf_get_pool(tlsf);
|
|
|
|
|
tlsf_walk_pool(pool, tlsf_walker_max_free, &max_free_block_size);
|
2022-02-19 05:53:46 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_unlock();
|
2022-02-19 05:53:46 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
return max_free_block_size;
|
2022-02-19 05:53:46 +10:00
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
typedef struct {
|
|
|
|
|
BlockWalker walker;
|
|
|
|
|
void* context;
|
|
|
|
|
} BlockWalkerWrapper;
|
2022-02-19 05:53:46 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
static bool tlsf_walker_wrapper(void* ptr, size_t size, int used, void* user) {
|
|
|
|
|
BlockWalkerWrapper* wrapper = (BlockWalkerWrapper*)user;
|
|
|
|
|
return wrapper->walker(ptr, size, used, wrapper->context);
|
2022-02-19 05:53:46 +10:00
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
void memmgr_heap_walk_blocks(BlockWalker walker, void* context) {
|
|
|
|
|
memmgr_lock();
|
2022-02-19 05:53:46 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
BlockWalkerWrapper wrapper = {walker, context};
|
|
|
|
|
pool_t pool = tlsf_get_pool(tlsf);
|
|
|
|
|
tlsf_walk_pool(pool, tlsf_walker_wrapper, &wrapper);
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_unlock();
|
|
|
|
|
}
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
void* pvPortMalloc(size_t xSize) {
|
|
|
|
|
// memory management in ISR is not allowed
|
2022-11-29 22:50:55 +10:00
|
|
|
if(FURI_IS_IRQ_MODE()) {
|
|
|
|
|
furi_crash("memmgt in ISR");
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_lock();
|
|
|
|
|
|
|
|
|
|
// allocate block
|
|
|
|
|
void* data = tlsf_malloc(tlsf, xSize);
|
|
|
|
|
if(data == NULL) {
|
|
|
|
|
if(xSize == 0) {
|
|
|
|
|
furi_crash("malloc(0)");
|
|
|
|
|
} else {
|
|
|
|
|
furi_crash("out of memory");
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
2022-02-19 05:53:46 +10:00
|
|
|
}
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// update heap usage
|
|
|
|
|
heap_used += tlsf_block_size(data);
|
|
|
|
|
heap_used += tlsf_alloc_overhead();
|
|
|
|
|
if(heap_used > heap_max_used) {
|
|
|
|
|
heap_max_used = heap_used;
|
|
|
|
|
}
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// trace allocation
|
|
|
|
|
memmgr_heap_trace_malloc(data, xSize);
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_unlock();
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// clear block content
|
|
|
|
|
memset(data, 0, xSize);
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
return data;
|
|
|
|
|
}
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
void vPortFree(void* pv) {
|
|
|
|
|
// memory management in ISR is not allowed
|
|
|
|
|
if(FURI_IS_IRQ_MODE()) {
|
|
|
|
|
furi_crash("memmgt in ISR");
|
|
|
|
|
}
|
2022-02-19 05:53:46 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// ignore NULL pointer
|
|
|
|
|
if(pv != NULL) {
|
|
|
|
|
memmgr_lock();
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// get block size
|
|
|
|
|
size_t block_size = tlsf_block_size(pv);
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// clear block content
|
|
|
|
|
memset(pv, 0, block_size);
|
2022-02-19 05:53:46 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// update heap usage
|
|
|
|
|
heap_used -= block_size;
|
|
|
|
|
heap_used -= tlsf_alloc_overhead();
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// free
|
|
|
|
|
tlsf_free(tlsf, pv);
|
2022-02-19 05:53:46 +10:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// trace free
|
|
|
|
|
memmgr_heap_trace_free(pv);
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_unlock();
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
extern void* pvPortAllocAligned(size_t xSize, size_t xAlignment) {
|
|
|
|
|
// memory management in ISR is not allowed
|
2022-11-29 22:50:55 +10:00
|
|
|
if(FURI_IS_IRQ_MODE()) {
|
|
|
|
|
furi_crash("memmgt in ISR");
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// alignment must be power of 2
|
|
|
|
|
if((xAlignment & (xAlignment - 1)) != 0) {
|
|
|
|
|
furi_crash("invalid alignment");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memmgr_lock();
|
|
|
|
|
|
|
|
|
|
// allocate block
|
|
|
|
|
void* data = tlsf_memalign(tlsf, xAlignment, xSize);
|
|
|
|
|
if(data == NULL) {
|
|
|
|
|
if(xSize == 0) {
|
|
|
|
|
furi_crash("malloc_aligned(0)");
|
2021-06-23 17:48:44 +03:00
|
|
|
} else {
|
2024-05-16 01:47:21 +10:00
|
|
|
furi_crash("out of memory");
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// update heap usage
|
|
|
|
|
heap_used += tlsf_block_size(data);
|
|
|
|
|
heap_used += tlsf_alloc_overhead();
|
|
|
|
|
if(heap_used > heap_max_used) {
|
|
|
|
|
heap_max_used = heap_used;
|
|
|
|
|
}
|
2022-04-13 23:50:25 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// trace allocation
|
|
|
|
|
memmgr_heap_trace_malloc(data, xSize);
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_unlock();
|
|
|
|
|
|
|
|
|
|
// clear block content
|
|
|
|
|
memset(data, 0, xSize);
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
return data;
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
extern void* pvPortRealloc(void* pv, size_t xSize) {
|
|
|
|
|
// realloc(ptr, 0) is equivalent to free(ptr)
|
|
|
|
|
if(xSize == 0) {
|
|
|
|
|
vPortFree(pv);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// realloc(NULL, size) is equivalent to malloc(size)
|
|
|
|
|
if(pv == NULL) {
|
|
|
|
|
return pvPortMalloc(xSize);
|
|
|
|
|
}
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
/* realloc things */
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// memory management in ISR is not allowed
|
|
|
|
|
if(FURI_IS_IRQ_MODE()) {
|
|
|
|
|
furi_crash("memmgt in ISR");
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
memmgr_lock();
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// trace old block as free
|
|
|
|
|
size_t old_size = tlsf_block_size(pv);
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// trace free
|
|
|
|
|
memmgr_heap_trace_free(pv);
|
2021-06-23 17:48:44 +03:00
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// reallocate block
|
|
|
|
|
void* data = tlsf_realloc(tlsf, pv, xSize);
|
|
|
|
|
if(data == NULL) {
|
|
|
|
|
furi_crash("out of memory");
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// update heap usage
|
|
|
|
|
heap_used -= old_size;
|
|
|
|
|
heap_used += tlsf_block_size(data);
|
|
|
|
|
if(heap_used > heap_max_used) {
|
|
|
|
|
heap_max_used = heap_used;
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
|
|
|
|
|
2024-05-16 01:47:21 +10:00
|
|
|
// trace allocation
|
|
|
|
|
memmgr_heap_trace_malloc(data, xSize);
|
|
|
|
|
|
|
|
|
|
memmgr_unlock();
|
|
|
|
|
|
|
|
|
|
// clear remain block content, if the new size is bigger
|
|
|
|
|
// can't guarantee that all data will be zeroed, cos tlsf_block_size is not always the same as xSize
|
|
|
|
|
if(xSize > old_size) {
|
|
|
|
|
memset((uint8_t*)data + old_size, 0, xSize - old_size);
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
2024-05-16 01:47:21 +10:00
|
|
|
|
|
|
|
|
return data;
|
2021-06-23 17:48:44 +03:00
|
|
|
}
|
2024-05-16 01:47:21 +10:00
|
|
|
|
|
|
|
|
size_t xPortGetFreeHeapSize(void) {
|
|
|
|
|
return memmgr_get_heap_size() - heap_used - tlsf_size(tlsf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t xPortGetTotalHeapSize(void) {
|
|
|
|
|
return memmgr_get_heap_size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t xPortGetMinimumEverFreeHeapSize(void) {
|
|
|
|
|
return memmgr_get_heap_size() - heap_max_used - tlsf_size(tlsf);
|
|
|
|
|
}
|