mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 21:14:37 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			261 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			261 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /******************************************************************************
 | |
|  *
 | |
|  *  Copyright (C) 2014 Google, Inc.
 | |
|  *
 | |
|  *  Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  *  you may not use this file except in compliance with the License.
 | |
|  *  You may obtain a copy of the License at:
 | |
|  *
 | |
|  *  http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  *  Unless required by applicable law or agreed to in writing, software
 | |
|  *  distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  *  See the License for the specific language governing permissions and
 | |
|  *  limitations under the License.
 | |
|  *
 | |
|  ******************************************************************************/
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #include "bt_common.h"
 | |
| #include "osi/allocator.h"
 | |
| 
 | |
| extern void *pvPortZalloc(size_t size);
 | |
| extern void vPortFree(void *pv);
 | |
| 
 | |
| 
 | |
| #if HEAP_MEMORY_DEBUG
 | |
| 
 | |
| #define OSI_MEM_DBG_INFO_MAX    1024*3
 | |
| typedef struct {
 | |
|     void *p;
 | |
|     int size;
 | |
|     const char *func;
 | |
|     int line;
 | |
| } osi_mem_dbg_info_t;
 | |
| 
 | |
| static uint32_t mem_dbg_count = 0;
 | |
| static osi_mem_dbg_info_t mem_dbg_info[OSI_MEM_DBG_INFO_MAX];
 | |
| static uint32_t mem_dbg_current_size = 0;
 | |
| static uint32_t mem_dbg_max_size = 0;
 | |
| 
 | |
| #define OSI_MEM_DBG_MAX_SECTION_NUM 5
 | |
| typedef struct {
 | |
|     bool used;
 | |
|     uint32_t max_size;
 | |
| } osi_mem_dbg_max_size_section_t;
 | |
| static osi_mem_dbg_max_size_section_t mem_dbg_max_size_section[OSI_MEM_DBG_MAX_SECTION_NUM];
 | |
| 
 | |
| void osi_mem_dbg_init(void)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < OSI_MEM_DBG_INFO_MAX; i++) {
 | |
|         mem_dbg_info[i].p = NULL;
 | |
|         mem_dbg_info[i].size = 0;
 | |
|         mem_dbg_info[i].func = NULL;
 | |
|         mem_dbg_info[i].line = 0;
 | |
|     }
 | |
|     mem_dbg_count = 0;
 | |
|     mem_dbg_current_size = 0;
 | |
|     mem_dbg_max_size = 0;
 | |
| 
 | |
|     for (i = 0; i < OSI_MEM_DBG_MAX_SECTION_NUM; i++){
 | |
|         mem_dbg_max_size_section[i].used = false;
 | |
|         mem_dbg_max_size_section[i].max_size = 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void osi_mem_dbg_record(void *p, int size, const char *func, int line)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     if (!p || size == 0) {
 | |
|         OSI_TRACE_ERROR("%s invalid !!\n", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < OSI_MEM_DBG_INFO_MAX; i++) {
 | |
|         if (mem_dbg_info[i].p == NULL) {
 | |
|             mem_dbg_info[i].p = p;
 | |
|             mem_dbg_info[i].size = size;
 | |
|             mem_dbg_info[i].func = func;
 | |
|             mem_dbg_info[i].line = line;
 | |
|             mem_dbg_count++;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (i >= OSI_MEM_DBG_INFO_MAX) {
 | |
|         OSI_TRACE_ERROR("%s full %s %d !!\n", __func__, func, line);
 | |
|     }
 | |
| 
 | |
|     mem_dbg_current_size += size;
 | |
|     if(mem_dbg_max_size < mem_dbg_current_size) {
 | |
|         mem_dbg_max_size = mem_dbg_current_size;
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < OSI_MEM_DBG_MAX_SECTION_NUM; i++){
 | |
|         if (mem_dbg_max_size_section[i].used) {
 | |
|             if(mem_dbg_max_size_section[i].max_size < mem_dbg_current_size) {
 | |
|                 mem_dbg_max_size_section[i].max_size = mem_dbg_current_size;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void osi_mem_dbg_clean(void *p, const char *func, int line)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     if (!p) {
 | |
|         OSI_TRACE_ERROR("%s invalid\n", __func__);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < OSI_MEM_DBG_INFO_MAX; i++) {
 | |
|         if (mem_dbg_info[i].p == p) {
 | |
|             mem_dbg_current_size -= mem_dbg_info[i].size;
 | |
|             mem_dbg_info[i].p = NULL;
 | |
|             mem_dbg_info[i].size = 0;
 | |
|             mem_dbg_info[i].func = NULL;
 | |
|             mem_dbg_info[i].line = 0;
 | |
|             mem_dbg_count--;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (i >= OSI_MEM_DBG_INFO_MAX) {
 | |
|         OSI_TRACE_ERROR("%s full %s %d !!\n", __func__, func, line);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void osi_mem_dbg_show(void)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < OSI_MEM_DBG_INFO_MAX; i++) {
 | |
|         if (mem_dbg_info[i].p || mem_dbg_info[i].size != 0 ) {
 | |
|             OSI_TRACE_ERROR("--> p %p, s %d, f %s, l %d\n", mem_dbg_info[i].p, mem_dbg_info[i].size, mem_dbg_info[i].func, mem_dbg_info[i].line);
 | |
|         }
 | |
|     }
 | |
|     OSI_TRACE_ERROR("--> count %d\n", mem_dbg_count);
 | |
|     OSI_TRACE_ERROR("--> size %dB\n--> max size %dB\n", mem_dbg_current_size, mem_dbg_max_size);
 | |
| }
 | |
| 
 | |
| uint32_t osi_mem_dbg_get_max_size(void)
 | |
| {
 | |
|     return mem_dbg_max_size;
 | |
| }
 | |
| 
 | |
| uint32_t osi_mem_dbg_get_current_size(void)
 | |
| {
 | |
|     return mem_dbg_current_size;
 | |
| }
 | |
| 
 | |
| void osi_men_dbg_set_section_start(uint8_t index)
 | |
| {
 | |
|     if (index >= OSI_MEM_DBG_MAX_SECTION_NUM) {
 | |
|         OSI_TRACE_ERROR("Then range of index should be between 0 and %d, current index is %d.\n",
 | |
|                             OSI_MEM_DBG_MAX_SECTION_NUM - 1, index);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (mem_dbg_max_size_section[index].used) {
 | |
|         OSI_TRACE_WARNING("This index(%d) has been started, restart it.\n", index);
 | |
|     }
 | |
| 
 | |
|     mem_dbg_max_size_section[index].used = true;
 | |
|     mem_dbg_max_size_section[index].max_size = mem_dbg_current_size;
 | |
| }
 | |
| 
 | |
| void osi_men_dbg_set_section_end(uint8_t index)
 | |
| {
 | |
|     if (index >= OSI_MEM_DBG_MAX_SECTION_NUM) {
 | |
|         OSI_TRACE_ERROR("Then range of index should be between 0 and %d, current index is %d.\n",
 | |
|                             OSI_MEM_DBG_MAX_SECTION_NUM - 1, index);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (!mem_dbg_max_size_section[index].used) {
 | |
|         OSI_TRACE_ERROR("This index(%d) has not been started.\n", index);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     mem_dbg_max_size_section[index].used = false;
 | |
| }
 | |
| 
 | |
| uint32_t osi_mem_dbg_get_max_size_section(uint8_t index)
 | |
| {
 | |
|     if (index >= OSI_MEM_DBG_MAX_SECTION_NUM){
 | |
|         OSI_TRACE_ERROR("Then range of index should be between 0 and %d, current index is %d.\n",
 | |
|                             OSI_MEM_DBG_MAX_SECTION_NUM - 1, index);
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     return mem_dbg_max_size_section[index].max_size;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| char *osi_strdup(const char *str)
 | |
| {
 | |
|     size_t size = strlen(str) + 1;  // + 1 for the null terminator
 | |
|     char *new_string = (char *)osi_calloc(size);
 | |
| 
 | |
|     if (!new_string) {
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     memcpy(new_string, str, size);
 | |
|     return new_string;
 | |
| }
 | |
| 
 | |
| void *osi_malloc_func(size_t size)
 | |
| {
 | |
| #if HEAP_MEMORY_DEBUG
 | |
|     void *p;
 | |
| #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
 | |
|     p = heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
 | |
| #else
 | |
|     p = malloc(size);
 | |
| #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
 | |
|     osi_mem_dbg_record(p, size, __func__, __LINE__);
 | |
|     return p;
 | |
| #else
 | |
| #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
 | |
|     return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
 | |
| #else
 | |
|     return malloc(size);
 | |
| #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
 | |
| #endif /* #if HEAP_MEMORY_DEBUG */
 | |
| }
 | |
| 
 | |
| void *osi_calloc_func(size_t size)
 | |
| {
 | |
| #if HEAP_MEMORY_DEBUG
 | |
|     void *p;
 | |
| #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
 | |
|     p = heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
 | |
| #else
 | |
|     p = calloc(1, size);
 | |
| #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
 | |
|     osi_mem_dbg_record(p, size, __func__, __LINE__);
 | |
|     return p;
 | |
| #else
 | |
| #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
 | |
|     return heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
 | |
| #else
 | |
|     return calloc(1, size);
 | |
| #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
 | |
| #endif /* #if HEAP_MEMORY_DEBUG */
 | |
| }
 | |
| 
 | |
| void osi_free_func(void *ptr)
 | |
| {
 | |
| #if HEAP_MEMORY_DEBUG
 | |
|     osi_mem_dbg_clean(ptr, __func__, __LINE__);
 | |
| #endif
 | |
|     free(ptr);
 | |
| }
 | 
