Files
luban-lite-t3e-pro/packages/artinchip/mpp/ve/common/ve_buffer.c
刘可亮 7bbc029dae v1.0.0
2023-08-30 16:21:18 +08:00

202 lines
4.9 KiB
C

/*
* Copyright (C) 2020-2022 Artinchip Technology Co. Ltd
*
* author: <qi.xu@artinchip.com>
* Desc: allocator of physic continuous buffer used by ve
*/
#define LOG_TAG "ve_buffer"
//#include <pthread.h>
#include "aic_core.h"
#include "ve_buffer.h"
#include "mpp_mem.h"
#include "mpp_list.h"
#include "dma_allocator.h"
#include "ve.h"
#include "mpp_log.h"
#define align_cache_line(addr, len, a, l) \
unsigned long a = (unsigned long)addr; \
unsigned long l = (unsigned long)len; \
if (addr % CACHE_LINE_SIZE) { \
a -= (addr % CACHE_LINE_SIZE); \
l += (addr % CACHE_LINE_SIZE); \
} \
if (l % CACHE_LINE_SIZE) { \
l += CACHE_LINE_SIZE - (l % CACHE_LINE_SIZE); \
}
struct ve_buffer_allocator {
unsigned int addr;
int total_count;
int total_size;
//pthread_mutex_t lock;
aicos_mutex_t lock;
struct mpp_list list;
};
struct ve_buffer_impl {
struct ve_buffer ve_buf;
struct mpp_list list_status;
};
struct ve_buffer_allocator *ve_buffer_allocator_create(enum ve_buffer_type type)
{
struct ve_buffer_allocator *ctx;
ctx = mpp_alloc(sizeof(struct ve_buffer_allocator));
if (!ctx)
return NULL;
memset(ctx, 0, sizeof(struct ve_buffer_allocator));
ctx->total_size = 0;
ctx->total_count = 0;
//pthread_mutex_init(&ctx->lock, NULL);
ctx->lock = aicos_mutex_create();
mpp_list_init(&ctx->list);
return ctx;
}
void ve_buffer_allocator_destroy(struct ve_buffer_allocator *ctx)
{
struct ve_buffer_impl *node = NULL;
struct ve_buffer_impl *m = NULL;
if (!ctx)
return;
//pthread_mutex_lock(&ctx->lock);
aicos_mutex_take(ctx->lock,AICOS_WAIT_FOREVER);
if (!mpp_list_empty(&ctx->list)) {
mpp_list_for_each_entry_safe(node, m, &ctx->list, list_status) {
ctx->total_size -= node->ve_buf.size;
ctx->total_count--;
mpp_list_del_init(&node->list_status);
logw("ve_buffer leak, dma-buf fd: %d, size: %d", node->ve_buf.fd, node->ve_buf.size);
mpp_phy_free((unsigned long)node->ve_buf.vir_addr);
mpp_free(node);
node = NULL;
}
}
mpp_list_del_init(&ctx->list);
//pthread_mutex_unlock(&ctx->lock);
aicos_mutex_give(ctx->lock);
if (ctx->total_count > 0) {
loge("mppbuffer ctx deinit, there are %d buffers not released.", ctx->total_count);
}
//pthread_mutex_destroy(&ctx->lock);
aicos_mutex_delete(ctx->lock);
mpp_free(ctx);
}
struct ve_buffer *ve_buffer_alloc(struct ve_buffer_allocator *ctx, int size, enum ve_buffer_flag flag)
{
logd("ve_buffer_alloc, size: %d", size);
struct ve_buffer_impl *buf_impl;
if (!ctx || size <= 0) {
return NULL;
}
buf_impl = (struct ve_buffer_impl*)mpp_alloc(sizeof(struct ve_buffer_impl));
if(!buf_impl) {
return NULL;
}
memset(buf_impl, 0, sizeof(struct ve_buffer_impl));
//* 1. alloc dma-buf
buf_impl->ve_buf.phy_addr = mpp_phy_alloc(size);
buf_impl->ve_buf.vir_addr = (unsigned char*)buf_impl->ve_buf.phy_addr;
buf_impl->ve_buf.size = size;
//pthread_mutex_lock(&ctx->lock);
aicos_mutex_take(ctx->lock,AICOS_WAIT_FOREVER);
ctx->total_size += size;
ctx->total_count++;
mpp_list_init(&buf_impl->list_status);
mpp_list_add_tail(&buf_impl->list_status, &ctx->list);
//pthread_mutex_unlock(&ctx->lock);
aicos_mutex_give(ctx->lock);
logi("ve_buffer alloc success, fd: %d, size: %d", buf_impl->ve_buf.fd, buf_impl->ve_buf.size);
return (struct ve_buffer *)buf_impl;
}
int ve_buffer_sync(struct ve_buffer *buf, enum dma_buf_sync_flag flag)
{
unsigned long* addr = (unsigned long*)buf->vir_addr;
int size = buf->size;
if(flag == CACHE_CLEAN) {
align_cache_line((unsigned long)addr, size, a, l);
aicos_dcache_clean_range((unsigned long *)a, (int64_t)l);
} else if (flag == CACHE_INVALID) {
align_cache_line((unsigned long)addr, size, a, l);
aicos_dcache_invalid_range((unsigned long *)a, (int64_t)l);
} else {
logw("unkown cache flag: %d", flag);
return -1;
}
return 0;
}
int ve_buffer_sync_range(struct ve_buffer *buf, unsigned char* start_addr, int size, enum dma_buf_sync_flag flag)
{
if(flag == CACHE_CLEAN) {
align_cache_line((unsigned long)start_addr, size, a, l);
aicos_dcache_clean_range((unsigned long *)a, (int64_t)l);
} else if (flag == CACHE_INVALID) {
align_cache_line((unsigned long)start_addr, size, a, l);
aicos_dcache_invalid_range((unsigned long *)a, (int64_t)l);
} else {
logw("unkown cache flag: %d", flag);
return -1;
}
return 0;
}
void ve_buffer_free(struct ve_buffer_allocator *ctx, struct ve_buffer *buf)
{
struct ve_buffer_impl* buf_impl = (struct ve_buffer_impl*)buf;
if(!ctx || !buf)
return;
logi("ve_buffer_free, fd: %d, size: %d", buf->fd, buf->size);
//pthread_mutex_lock(&ctx->lock);
aicos_mutex_take(ctx->lock,AICOS_WAIT_FOREVER);
ctx->total_size -= buf->size;
ctx->total_count--;
mpp_list_del_init(&buf_impl->list_status);
//pthread_mutex_unlock(&ctx->lock);
aicos_mutex_give(ctx->lock);
mpp_phy_free(buf->phy_addr);
mpp_free(buf_impl);
}