Files
2026-08-24 10:03:24 +08:00

266 lines
7.8 KiB
C

/*
* Copyright (C) 2019 Amlogic Corporation.
*
* 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.
*/
#define LOG_TAG "aml_audio_malloc"
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <cutils/list.h>
#include "aml_audio_log.h"
#include "aml_malloc_debug.h"
#define MEMINFO_SHOW_FILENAME "/data/audio_meminfo"
struct aml_malloc_node {
struct listnode list;
char file_name[128];
uint32_t line;
void * pointer;
size_t size;
};
struct aml_malloc_debug {
struct listnode malloc_list;
pthread_mutex_t malloc_lock;
};
static struct aml_malloc_debug *gaudio_malloc_handle = NULL;
static char aml_malloc_temp_buf[256];
static void add_malloc_node(struct aml_malloc_node * malloc_node)
{
struct aml_malloc_debug *pmalloc_handle = NULL;
pmalloc_handle = gaudio_malloc_handle;
pthread_mutex_lock(&pmalloc_handle->malloc_lock);
list_add_tail(&pmalloc_handle->malloc_list, &malloc_node->list);
pthread_mutex_unlock(&pmalloc_handle->malloc_lock);
return;
}
static void remove_malloc_item(void* pointer)
{
struct listnode *node = NULL;
struct aml_malloc_node * malloc_node = NULL;
struct aml_malloc_debug *pmalloc_handle = NULL;
pmalloc_handle = gaudio_malloc_handle;
pthread_mutex_lock(&pmalloc_handle->malloc_lock);
list_for_each(node, &pmalloc_handle->malloc_list) {
malloc_node = node_to_item(node, struct aml_malloc_node, list);
if (malloc_node->pointer == pointer) {
list_remove(&malloc_node->list);
free(malloc_node);
break;
}
}
pthread_mutex_unlock(&pmalloc_handle->malloc_lock);
return;
}
void aml_audio_debug_malloc_open(void)
{
struct aml_malloc_debug *pmalloc_handle = NULL;
pmalloc_handle = (struct aml_malloc_debug *)malloc(sizeof(struct aml_malloc_debug));
if (pmalloc_handle == NULL) {
ALOGE("%s failed", __FUNCTION__);
return;
}
list_init(&pmalloc_handle->malloc_list);
pthread_mutex_init(&pmalloc_handle->malloc_lock, NULL);
gaudio_malloc_handle = pmalloc_handle;
return;
}
void aml_audio_debug_malloc_close(void)
{
struct aml_malloc_debug *pmalloc_handle = NULL;
struct aml_malloc_node *malloc_node = NULL;
struct listnode *node = NULL, *n = NULL;
pmalloc_handle = gaudio_malloc_handle;
if (pmalloc_handle == NULL) {
return;
}
pthread_mutex_lock(&pmalloc_handle->malloc_lock);
list_for_each_safe(node, n, &pmalloc_handle->malloc_list) {
malloc_node = node_to_item(node, struct aml_malloc_node, list);
list_remove(&malloc_node->list);
free(malloc_node);
}
pthread_mutex_unlock(&pmalloc_handle->malloc_lock);
free(pmalloc_handle);
gaudio_malloc_handle = NULL;
return;
}
void* aml_audio_debug_malloc(size_t size, const char * file_name, uint32_t line)
{
void * pointer = NULL;
struct aml_malloc_node * malloc_node = NULL;
pointer = malloc(size);
if (pointer == NULL) {
return NULL;
}
malloc_node = (struct aml_malloc_node *)malloc(sizeof(struct aml_malloc_node));
if (malloc_node == NULL) {
free(pointer);
return NULL;
}
snprintf(malloc_node->file_name, 128, "malloc=%s", file_name);
malloc_node->line = line;
malloc_node->pointer = pointer;
malloc_node->size = size;
add_malloc_node(malloc_node);
return pointer;
}
void* aml_audio_debug_realloc(void* pointer, size_t bytes, const char * file_name, uint32_t line)
{
void * new_pointer = NULL;
struct aml_malloc_node * malloc_node = NULL;
if (pointer) {
remove_malloc_item(pointer);
}
new_pointer = realloc(pointer, bytes);
if (new_pointer == NULL) {
return NULL;
}
malloc_node = (struct aml_malloc_node *)malloc(sizeof(struct aml_malloc_node));
if (malloc_node == NULL) {
free(new_pointer);
return NULL;
}
snprintf(malloc_node->file_name, 128, "realloc=%s", file_name);
malloc_node->line = line;
malloc_node->pointer = new_pointer;
malloc_node->size = bytes;
add_malloc_node(malloc_node);
return new_pointer;
}
void* aml_audio_debug_calloc(size_t nmemb, size_t bytes, const char * file_name, uint32_t line)
{
void * pointer = NULL;
struct aml_malloc_node * malloc_node = NULL;
pointer = calloc(nmemb, bytes);
if (pointer == NULL) {
return NULL;
}
malloc_node = (struct aml_malloc_node *)malloc(sizeof(struct aml_malloc_node));
if (malloc_node == NULL) {
free(pointer);
return NULL;
}
snprintf(malloc_node->file_name, 128, "calloc:%s", file_name);
malloc_node->line = line;
malloc_node->pointer = pointer;
malloc_node->size = nmemb * bytes;
add_malloc_node(malloc_node);
return pointer;
}
void aml_audio_debug_free(void* pointer)
{
if (pointer) {
remove_malloc_item(pointer);
}
free(pointer);
return;
}
void aml_audio_debug_malloc_showinfo(uint32_t level)
{
struct listnode *node = NULL;
struct aml_malloc_node * malloc_node = NULL;
struct aml_malloc_debug *pmalloc_handle = NULL;
FILE *fp1 = NULL;
uint32_t total_mem = 0;
pmalloc_handle = gaudio_malloc_handle;
if (level == MEMINFO_SHOW_FILE) {
fp1 = fopen(MEMINFO_SHOW_FILENAME, "w+");
if (fp1 == NULL) {
return;
}
}
pthread_mutex_lock(&pmalloc_handle->malloc_lock);
list_for_each(node, &pmalloc_handle->malloc_list) {
malloc_node = node_to_item(node, struct aml_malloc_node, list);
if (malloc_node) {
total_mem += malloc_node->size;
if (level == MEMINFO_SHOW_PRINT) {
ALOGI("mem info:%s line=%d pointer =%p size=0x%zx", malloc_node->file_name, malloc_node->line, malloc_node->pointer, malloc_node->size);
} else if (level == MEMINFO_SHOW_FILE) {
if (fp1) {
memset(aml_malloc_temp_buf, 0, sizeof(aml_malloc_temp_buf));
sprintf(aml_malloc_temp_buf, "mem info:%s line=%d pointer =%p size=0x%zx\n", malloc_node->file_name, malloc_node->line, malloc_node->pointer, malloc_node->size);
fwrite((char *)aml_malloc_temp_buf, 1, sizeof(aml_malloc_temp_buf), fp1);
}
}
}
}
if (level == MEMINFO_SHOW_PRINT) {
ALOGI("HAL Audio total use mem =0x%x\n", total_mem);
} else if (level == MEMINFO_SHOW_FILE) {
memset(aml_malloc_temp_buf, 0, sizeof(aml_malloc_temp_buf));
sprintf(aml_malloc_temp_buf, "HAL Audio total use mem =0x%x\n", total_mem);
fwrite((char *)aml_malloc_temp_buf, 1, sizeof(aml_malloc_temp_buf), fp1);
fclose(fp1);
}
pthread_mutex_unlock(&pmalloc_handle->malloc_lock);
return;
}
int aml_audio_check_and_realloc(void** pointer, size_t* cur_size, size_t need_size)
{
if (pointer == NULL || cur_size == NULL) {
ALOGE("[%s:%d] pointer:%p or cur_size:%p is null", __func__, __LINE__, pointer, cur_size);
return -1;
}
if (*cur_size < need_size || *pointer == NULL) {
void *p = aml_audio_realloc(*pointer, need_size);
if (p == NULL) {
ALOGE("[%s:%d] realloc buffer failed size:%zu", __func__, __LINE__, need_size);
return -ENOMEM;
} else {
memset(p, 0, need_size);
*pointer = p;
}
*cur_size = need_size;
}
return 0;
}