mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-05 01:02:39 +08:00

UOBJ: deliver userspace buffer for rk3588 and rk3576 SOBJ: deliver shared memory buffer for rv1126b Sync to kmpp-develop patch with the same log: If596371639eaedb01d6900c737d1f7fec49bf8d4 Change-Id: I8927f6341b5d3f94bf52af32c02b75cd24ad0681 Signed-off-by: timkingh.huang <timkingh.huang@rock-chips.com>
475 lines
13 KiB
C
475 lines
13 KiB
C
/* SPDX-License-Identifier: Apache-2.0 OR MIT */
|
|
/*
|
|
* Copyright (c) 2025 Rockchip Electronics Co., Ltd.
|
|
*/
|
|
|
|
#define MODULE_TAG "kmpp_meta"
|
|
|
|
#include <string.h>
|
|
#include <endian.h>
|
|
|
|
#include "mpp_mem.h"
|
|
#include "mpp_list.h"
|
|
#include "mpp_lock.h"
|
|
#include "mpp_debug.h"
|
|
#include "mpp_thread.h"
|
|
#include "mpp_singleton.h"
|
|
|
|
#include "kmpp_obj.h"
|
|
#include "kmpp_meta_impl.h"
|
|
|
|
#define KMETA_DBG_FUNC (0x00000001)
|
|
#define KMETA_DBG_SIZE (0x00000002)
|
|
#define KMETA_DBG_SET (0x00000004)
|
|
#define KMETA_DBG_GET (0x00000008)
|
|
|
|
#define kmeta_dbg(flag, fmt, ...) _mpp_dbg_f(kmpp_meta_debug, flag, fmt, ## __VA_ARGS__)
|
|
|
|
#define kmeta_dbg_func(fmt, ...) kmeta_dbg(KMETA_DBG_FUNC, fmt, ## __VA_ARGS__)
|
|
#define kmeta_dbg_size(fmt, ...) kmeta_dbg(KMETA_DBG_SIZE, fmt, ## __VA_ARGS__)
|
|
#define kmeta_dbg_set(fmt, ...) kmeta_dbg(KMETA_DBG_SET, fmt, ## __VA_ARGS__)
|
|
#define kmeta_dbg_get(fmt, ...) kmeta_dbg(KMETA_DBG_GET, fmt, ## __VA_ARGS__)
|
|
|
|
#define META_ON_OPS (0x00010000)
|
|
#define META_VAL_INVALID (0x00000000)
|
|
#define META_VAL_VALID (0x00000001)
|
|
#define META_VAL_READY (0x00000002)
|
|
#define META_READY_MASK (META_VAL_VALID | META_VAL_READY)
|
|
/* property mask */
|
|
#define META_VAL_IS_OBJ (0x00000010)
|
|
#define META_VAL_IS_SHM (0x00000020)
|
|
#define META_PROP_MASK (META_VAL_IS_OBJ | META_VAL_IS_SHM)
|
|
#define META_UNMASK_PROP(x) MPP_FETCH_AND(x, (~META_PROP_MASK))
|
|
|
|
#define META_KEY_TO_U64(key, type) ((rk_u64)((rk_u32)htobe32(key)) | ((rk_u64)type << 32))
|
|
|
|
typedef enum KmppMetaDataType_e {
|
|
/* kmpp meta data of normal data type */
|
|
TYPE_VAL_32 = '3',
|
|
TYPE_VAL_64 = '6',
|
|
TYPE_KPTR = 'k', /* kernel pointer */
|
|
TYPE_UPTR = 'u', /* userspace pointer */
|
|
TYPE_SPTR = 's', /* share memory pointer */
|
|
} KmppMetaType;
|
|
|
|
typedef struct KmppMetaSrv_s {
|
|
pthread_mutex_t lock;
|
|
struct list_head list;
|
|
KmppObjDef def;
|
|
|
|
rk_s32 offset_size;
|
|
rk_u32 meta_id;
|
|
rk_s32 meta_count;
|
|
} KmppMetaSrv;
|
|
|
|
typedef struct KmppMetaPriv_s {
|
|
struct list_head list;
|
|
|
|
KmppObj meta;
|
|
rk_u32 meta_id;
|
|
} KmppMetaPriv;
|
|
|
|
static KmppMetaSrv *srv_meta = NULL;
|
|
static rk_u32 kmpp_meta_debug = 0;
|
|
|
|
#define get_meta_srv(caller) \
|
|
({ \
|
|
KmppMetaSrv *__tmp; \
|
|
if (srv_meta) { \
|
|
__tmp = srv_meta; \
|
|
} else { \
|
|
mpp_loge_f("kmpp meta srv not init at %s : %s\n", __FUNCTION__, caller); \
|
|
__tmp = NULL; \
|
|
} \
|
|
__tmp; \
|
|
})
|
|
|
|
static rk_s32 kmpp_meta_impl_init(void *entry, KmppObj obj, const char *caller)
|
|
{
|
|
KmppMetaPriv *priv = (KmppMetaPriv *)kmpp_obj_to_priv(obj);
|
|
KmppMetaSrv *srv = get_meta_srv(caller);
|
|
(void)entry;
|
|
|
|
if (srv) {
|
|
priv->meta = obj;
|
|
INIT_LIST_HEAD(&priv->list);
|
|
|
|
pthread_mutex_lock(&srv->lock);
|
|
list_add_tail(&priv->list, &srv->list);
|
|
priv->meta_id = srv->meta_id++;
|
|
srv->meta_count++;
|
|
pthread_mutex_unlock(&srv->lock);
|
|
}
|
|
|
|
return rk_ok;
|
|
}
|
|
|
|
static rk_s32 kmpp_meta_impl_deinit(void *entry, KmppObj obj, const char *caller)
|
|
{
|
|
KmppMetaPriv *priv = (KmppMetaPriv *)kmpp_obj_to_priv(obj);
|
|
KmppMetaSrv *srv = get_meta_srv(caller);
|
|
(void)entry;
|
|
|
|
if (srv) {
|
|
pthread_mutex_lock(&srv->lock);
|
|
list_del_init(&priv->list);
|
|
srv->meta_count--;
|
|
pthread_mutex_unlock(&srv->lock);
|
|
}
|
|
|
|
return rk_ok;
|
|
}
|
|
|
|
static void kmpp_meta_deinit(void)
|
|
{
|
|
KmppMetaSrv *srv = srv_meta;
|
|
|
|
if (!srv) {
|
|
kmeta_dbg_func("kmpp meta already deinit\n");
|
|
return;
|
|
}
|
|
|
|
if (srv->def) {
|
|
kmpp_objdef_put(srv->def);
|
|
srv->def = NULL;
|
|
}
|
|
|
|
pthread_mutex_destroy(&srv->lock);
|
|
|
|
MPP_FREE(srv);
|
|
srv_meta = NULL;
|
|
}
|
|
|
|
static void kmpp_meta_init(void)
|
|
{
|
|
KmppMetaSrv *srv = srv_meta;
|
|
pthread_mutexattr_t attr;
|
|
|
|
if (srv) {
|
|
kmeta_dbg_func("kmpp meta %p already init\n", srv);
|
|
kmpp_meta_deinit();
|
|
}
|
|
|
|
srv = mpp_calloc(KmppMetaSrv, 1);
|
|
if (!srv) {
|
|
mpp_loge_f("kmpp meta malloc failed\n");
|
|
return;
|
|
}
|
|
|
|
pthread_mutexattr_init(&attr);
|
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
|
pthread_mutex_init(&srv->lock, &attr);
|
|
pthread_mutexattr_destroy(&attr);
|
|
|
|
INIT_LIST_HEAD(&srv->list);
|
|
kmpp_objdef_get(&srv->def, "KmppMeta");
|
|
if (!srv->def) {
|
|
kmeta_dbg_func("kmpp meta get objdef failed\n");
|
|
MPP_FREE(srv);
|
|
return;
|
|
}
|
|
|
|
kmpp_objdef_set_prop(srv->def, "priv_size", sizeof(KmppMetaPriv));
|
|
kmpp_objdef_add_init(srv->def, kmpp_meta_impl_init);
|
|
kmpp_objdef_add_deinit(srv->def, kmpp_meta_impl_deinit);
|
|
|
|
{
|
|
KmppEntry *tbl = NULL;
|
|
|
|
kmpp_objdef_get_entry(srv->def, "size", &tbl);
|
|
srv->offset_size = tbl ? tbl->tbl.elem_offset : 0;
|
|
}
|
|
|
|
srv_meta = srv;
|
|
}
|
|
|
|
MPP_SINGLETON(MPP_SGLN_KMPP_META, kmpp_meta, kmpp_meta_init, kmpp_meta_deinit);
|
|
|
|
static void *meta_key_to_addr(KmppObj meta, KmppMetaKey key, KmppMetaType type)
|
|
{
|
|
if (meta) {
|
|
KmppMetaSrv *srv = srv_meta;
|
|
rk_u64 val = META_KEY_TO_U64(key, type);
|
|
KmppEntry *tbl = NULL;
|
|
|
|
kmpp_objdef_get_entry(srv->def, (const char *)&val, &tbl);
|
|
if (tbl)
|
|
return ((rk_u8 *)kmpp_obj_to_entry(meta)) + tbl->tbl.elem_offset;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static rk_s32 meta_inc_size(KmppObj meta, rk_s32 val, const char *caller)
|
|
{
|
|
rk_s32 ret = 0;
|
|
|
|
if (meta && srv_meta) {
|
|
void *entry = kmpp_obj_to_entry(meta);
|
|
rk_s32 offset = srv_meta->offset_size;
|
|
|
|
if (entry && offset) {
|
|
rk_s32 *p = (rk_s32 *)((rk_u8 *)entry + offset);
|
|
|
|
ret = MPP_FETCH_ADD(p, val);
|
|
kmeta_dbg_size("meta %p size %d -> %d at %s\n",
|
|
meta, p[0], ret, caller);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static rk_s32 meta_dec_size(KmppObj meta, rk_s32 val, const char *caller)
|
|
{
|
|
rk_s32 ret = 0;
|
|
|
|
if (meta && srv_meta) {
|
|
void *entry = kmpp_obj_to_entry(meta);
|
|
rk_s32 offset = srv_meta->offset_size;
|
|
|
|
if (entry && offset) {
|
|
rk_s32 *p = (rk_s32 *)((rk_u8 *)entry + offset);
|
|
|
|
ret = MPP_FETCH_SUB(p, val);
|
|
kmeta_dbg_size("meta %p size %d -> %d at %s\n",
|
|
meta, p[0], ret, caller);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
rk_s32 kmpp_meta_get(KmppMeta *meta, const char *caller)
|
|
{
|
|
KmppMetaSrv *srv = get_meta_srv(caller);
|
|
|
|
if (!srv)
|
|
return rk_nok;
|
|
|
|
return kmpp_obj_get(meta, srv->def, caller);
|
|
}
|
|
|
|
rk_s32 kmpp_meta_put(KmppMeta meta, const char *caller)
|
|
{
|
|
KmppMetaSrv *srv = get_meta_srv(caller);
|
|
|
|
if (!srv)
|
|
return rk_nok;
|
|
|
|
return kmpp_obj_put(meta, caller);
|
|
}
|
|
|
|
rk_s32 kmpp_meta_size(KmppMeta meta, const char *caller)
|
|
{
|
|
return meta_inc_size(meta, 0, caller);
|
|
}
|
|
|
|
rk_s32 kmpp_meta_dump(KmppMeta meta, const char *caller)
|
|
{
|
|
return kmpp_obj_udump_f(meta, caller);
|
|
}
|
|
|
|
rk_s32 kmpp_meta_dump_all(const char *caller)
|
|
{
|
|
KmppMetaSrv *srv = get_meta_srv(caller);
|
|
|
|
if (srv) {
|
|
KmppMeta meta = NULL;
|
|
KmppMetaPriv *pos, *n;
|
|
|
|
pthread_mutex_lock(&srv->lock);
|
|
list_for_each_entry_safe(pos, n, &srv->list, KmppMetaPriv, list) {
|
|
meta = pos->meta;
|
|
mpp_logi("meta %p:%d size %d\n", meta, pos->meta_id,
|
|
kmpp_meta_size(meta, caller));
|
|
kmpp_meta_dump(meta, caller);
|
|
}
|
|
}
|
|
|
|
return rk_ok;
|
|
}
|
|
|
|
#define KMPP_META_ACCESSOR(func_type, arg_type, key_type, key_field) \
|
|
rk_s32 kmpp_meta_set_##func_type(KmppMeta meta, KmppMetaKey key, arg_type val) \
|
|
{ \
|
|
KmppMetaVal *meta_val = meta_key_to_addr(meta, key, key_type); \
|
|
if (!meta_val) \
|
|
return rk_nok; \
|
|
if (MPP_BOOL_CAS(&meta_val->state, META_VAL_INVALID, META_VAL_VALID)) \
|
|
meta_inc_size(meta, 1, __FUNCTION__); \
|
|
meta_val->key_field = val; \
|
|
MPP_FETCH_OR(&meta_val->state, META_VAL_READY); \
|
|
return rk_ok; \
|
|
} \
|
|
rk_s32 kmpp_meta_get_##func_type(KmppMeta meta, KmppMetaKey key, arg_type *val) \
|
|
{ \
|
|
KmppMetaVal *meta_val = meta_key_to_addr(meta, key, key_type); \
|
|
if (!meta_val) \
|
|
return rk_nok; \
|
|
if (MPP_BOOL_CAS(&meta_val->state, META_READY_MASK, META_VAL_INVALID)) { \
|
|
if (val) *val = meta_val->key_field; \
|
|
meta_dec_size(meta, 1, __FUNCTION__); \
|
|
return rk_ok; \
|
|
} \
|
|
return rk_nok; \
|
|
} \
|
|
rk_s32 kmpp_meta_get_##func_type##_d(KmppMeta meta, KmppMetaKey key, arg_type *val, arg_type def) \
|
|
{ \
|
|
KmppMetaVal *meta_val = meta_key_to_addr(meta, key, key_type); \
|
|
if (!meta_val) \
|
|
return rk_nok; \
|
|
if (MPP_BOOL_CAS(&meta_val->state, META_READY_MASK, META_VAL_INVALID)) { \
|
|
if (val) *val = meta_val->key_field; \
|
|
meta_dec_size(meta, 1, __FUNCTION__); \
|
|
} else { \
|
|
if (val) *val = def; \
|
|
} \
|
|
return rk_ok; \
|
|
}
|
|
|
|
KMPP_META_ACCESSOR(s32, rk_s32, TYPE_VAL_32, val_s32)
|
|
KMPP_META_ACCESSOR(s64, rk_s64, TYPE_VAL_64, val_s64)
|
|
KMPP_META_ACCESSOR(ptr, void *, TYPE_UPTR, val_ptr)
|
|
|
|
rk_s32 kmpp_meta_set_obj(KmppMeta meta, KmppMetaKey key, KmppObj val)
|
|
{
|
|
KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR);
|
|
|
|
if (!meta_obj)
|
|
return rk_nok;
|
|
|
|
if (MPP_BOOL_CAS(&meta_obj->state, META_VAL_INVALID, META_VAL_VALID))
|
|
meta_inc_size(meta, 1, __FUNCTION__);
|
|
|
|
{
|
|
KmppShmPtr *ptr = kmpp_obj_to_shm(val);
|
|
|
|
if (ptr) {
|
|
meta_obj->val_shm.uaddr = ptr->uaddr;
|
|
meta_obj->val_shm.kaddr = ptr->kaddr;;
|
|
MPP_FETCH_OR(&meta_obj->state, META_VAL_IS_SHM);
|
|
} else {
|
|
meta_obj->val_shm.uaddr = 0;
|
|
meta_obj->val_shm.kptr = val;
|
|
MPP_FETCH_AND(&meta_obj->state, ~META_VAL_IS_SHM);
|
|
}
|
|
}
|
|
MPP_FETCH_OR(&meta_obj->state, META_VAL_READY);
|
|
return rk_ok;
|
|
}
|
|
|
|
rk_s32 kmpp_meta_get_obj(KmppMeta meta, KmppMetaKey key, KmppObj *val)
|
|
{
|
|
KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR);
|
|
|
|
if (!meta_obj)
|
|
return rk_nok;
|
|
|
|
META_UNMASK_PROP(&meta_obj->state);
|
|
if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) {
|
|
if (val)
|
|
*val = meta_obj->val_shm.kptr;
|
|
meta_dec_size(meta, 1, __FUNCTION__);
|
|
return rk_ok;
|
|
}
|
|
|
|
return rk_nok;
|
|
}
|
|
|
|
rk_s32 kmpp_meta_get_obj_d(KmppMeta meta, KmppMetaKey key, KmppObj *val, KmppObj def)
|
|
{
|
|
KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR);
|
|
|
|
if (!meta_obj)
|
|
return rk_nok;
|
|
|
|
META_UNMASK_PROP(&meta_obj->state);
|
|
if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) {
|
|
if (val)
|
|
*val = meta_obj->val_shm.kptr;
|
|
meta_dec_size(meta, 1, __FUNCTION__);
|
|
} else {
|
|
if (val)
|
|
*val = def ? def : NULL;
|
|
}
|
|
|
|
return rk_ok;
|
|
}
|
|
|
|
rk_s32 kmpp_meta_set_shm(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr)
|
|
{
|
|
KmppMetaObj *meta_obj = (KmppMetaObj *)meta_key_to_addr(meta, key, TYPE_SPTR);
|
|
|
|
if (!meta_obj)
|
|
return rk_nok;
|
|
|
|
if (MPP_BOOL_CAS(&meta_obj->state, META_VAL_INVALID, META_VAL_VALID))
|
|
meta_inc_size(meta, 1, __FUNCTION__);
|
|
|
|
if (sptr) {
|
|
meta_obj->val_shm.uaddr = sptr->uaddr;
|
|
meta_obj->val_shm.kaddr = sptr->kaddr;
|
|
} else {
|
|
meta_obj->val_shm.uaddr = 0;
|
|
meta_obj->val_shm.kptr = 0;
|
|
}
|
|
|
|
if (sptr && sptr->uaddr)
|
|
MPP_FETCH_OR(&meta_obj->state, META_VAL_IS_SHM);
|
|
else
|
|
MPP_FETCH_AND(&meta_obj->state, ~META_VAL_IS_SHM);
|
|
|
|
MPP_FETCH_OR(&meta_obj->state, META_VAL_READY);
|
|
|
|
return rk_ok;
|
|
}
|
|
|
|
rk_s32 kmpp_meta_get_shm(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr)
|
|
{
|
|
KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR);
|
|
|
|
if (!meta_obj)
|
|
return rk_nok;
|
|
|
|
META_UNMASK_PROP(&meta_obj->state);
|
|
if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) {
|
|
if (sptr) {
|
|
sptr->uaddr = meta_obj->val_shm.uaddr;
|
|
sptr->kaddr = meta_obj->val_shm.kaddr;
|
|
}
|
|
meta_dec_size(meta, 1, __FUNCTION__);
|
|
return rk_ok;
|
|
}
|
|
return rk_nok;
|
|
}
|
|
|
|
rk_s32 kmpp_meta_get_shm_d(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr, KmppShmPtr *def)
|
|
{
|
|
KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR);
|
|
|
|
if (!meta_obj)
|
|
return rk_nok;
|
|
|
|
META_UNMASK_PROP(&meta_obj->state);
|
|
if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) {
|
|
if (sptr) {
|
|
sptr->uaddr = meta_obj->val_shm.uaddr;
|
|
sptr->kaddr = meta_obj->val_shm.kaddr;
|
|
}
|
|
meta_dec_size(meta, 1, __FUNCTION__);
|
|
} else {
|
|
if (sptr) {
|
|
if (def) {
|
|
sptr->uaddr = def->uaddr;
|
|
sptr->kaddr = def->kaddr;
|
|
} else {
|
|
sptr->uaddr = 0;
|
|
sptr->kaddr = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return rk_ok;
|
|
}
|