Files
mpp/kmpp/base/kmpp_meta.c
timkingh.huang 6588b71f2b fix[mpp_meta]: Add KEY_NPU_UOBJ_FLAG and KEY_NPU_SOBJ_FLAG
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>
2025-09-01 17:35:25 +08:00

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;
}