xref: /rockchip-linux_mpp/kmpp/base/kmpp_meta.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3  * Copyright (c) 2025 Rockchip Electronics Co., Ltd.
4  */
5 
6 #define MODULE_TAG "kmpp_meta"
7 
8 #include <string.h>
9 #include <endian.h>
10 
11 #include "mpp_mem.h"
12 #include "mpp_list.h"
13 #include "mpp_lock.h"
14 #include "mpp_debug.h"
15 #include "mpp_thread.h"
16 #include "mpp_singleton.h"
17 
18 #include "kmpp_obj.h"
19 #include "kmpp_meta_impl.h"
20 
21 #define KMETA_DBG_FUNC              (0x00000001)
22 #define KMETA_DBG_SIZE              (0x00000002)
23 #define KMETA_DBG_SET               (0x00000004)
24 #define KMETA_DBG_GET               (0x00000008)
25 
26 #define kmeta_dbg(flag, fmt, ...)   _mpp_dbg_f(kmpp_meta_debug, flag, fmt, ## __VA_ARGS__)
27 
28 #define kmeta_dbg_func(fmt, ...)    kmeta_dbg(KMETA_DBG_FUNC, fmt, ## __VA_ARGS__)
29 #define kmeta_dbg_size(fmt, ...)    kmeta_dbg(KMETA_DBG_SIZE, fmt, ## __VA_ARGS__)
30 #define kmeta_dbg_set(fmt, ...)     kmeta_dbg(KMETA_DBG_SET, fmt, ## __VA_ARGS__)
31 #define kmeta_dbg_get(fmt, ...)     kmeta_dbg(KMETA_DBG_GET, fmt, ## __VA_ARGS__)
32 
33 #define META_ON_OPS                 (0x00010000)
34 #define META_VAL_INVALID            (0x00000000)
35 #define META_VAL_VALID              (0x00000001)
36 #define META_VAL_READY              (0x00000002)
37 #define META_READY_MASK             (META_VAL_VALID | META_VAL_READY)
38 /* property mask */
39 #define META_VAL_IS_OBJ             (0x00000010)
40 #define META_VAL_IS_SHM             (0x00000020)
41 #define META_PROP_MASK              (META_VAL_IS_OBJ | META_VAL_IS_SHM)
42 #define META_UNMASK_PROP(x)         MPP_FETCH_AND(x, (~META_PROP_MASK))
43 
44 #define META_KEY_TO_U64(key, type)  ((rk_u64)((rk_u32)htobe32(key)) | ((rk_u64)type << 32))
45 
46 typedef enum KmppMetaDataType_e {
47     /* kmpp meta data of normal data type */
48     TYPE_VAL_32         = '3',
49     TYPE_VAL_64         = '6',
50     TYPE_KPTR           = 'k',  /* kernel pointer */
51     TYPE_UPTR           = 'u',  /* userspace pointer */
52     TYPE_SPTR           = 's',  /* share memory pointer */
53 } KmppMetaType;
54 
55 typedef struct KmppMetaSrv_s {
56     pthread_mutex_t     lock;
57     struct list_head    list;
58     KmppObjDef          def;
59 
60     rk_s32              offset_size;
61     rk_u32              meta_id;
62     rk_s32              meta_count;
63 } KmppMetaSrv;
64 
65 typedef struct KmppMetaPriv_s {
66     struct list_head    list;
67 
68     KmppObj             meta;
69     rk_u32              meta_id;
70 } KmppMetaPriv;
71 
72 static KmppMetaSrv *srv_meta = NULL;
73 static rk_u32 kmpp_meta_debug = 0;
74 
75 #define get_meta_srv(caller) \
76     ({ \
77         KmppMetaSrv *__tmp; \
78         if (srv_meta) { \
79             __tmp = srv_meta; \
80         } else { \
81             mpp_loge_f("kmpp meta srv not init at %s : %s\n", __FUNCTION__, caller); \
82             __tmp = NULL; \
83         } \
84         __tmp; \
85     })
86 
kmpp_meta_impl_init(void * entry,KmppObj obj,const char * caller)87 static rk_s32 kmpp_meta_impl_init(void *entry, KmppObj obj, const char *caller)
88 {
89     KmppMetaPriv *priv = (KmppMetaPriv *)kmpp_obj_to_priv(obj);
90     KmppMetaSrv *srv = get_meta_srv(caller);
91     (void)entry;
92 
93     if (srv) {
94         priv->meta = obj;
95         INIT_LIST_HEAD(&priv->list);
96 
97         pthread_mutex_lock(&srv->lock);
98         list_add_tail(&priv->list, &srv->list);
99         priv->meta_id = srv->meta_id++;
100         srv->meta_count++;
101         pthread_mutex_unlock(&srv->lock);
102     }
103 
104     return rk_ok;
105 }
106 
kmpp_meta_impl_deinit(void * entry,KmppObj obj,const char * caller)107 static rk_s32 kmpp_meta_impl_deinit(void *entry, KmppObj obj, const char *caller)
108 {
109     KmppMetaPriv *priv = (KmppMetaPriv *)kmpp_obj_to_priv(obj);
110     KmppMetaSrv *srv = get_meta_srv(caller);
111     (void)entry;
112 
113     if (srv) {
114         pthread_mutex_lock(&srv->lock);
115         list_del_init(&priv->list);
116         srv->meta_count--;
117         pthread_mutex_unlock(&srv->lock);
118     }
119 
120     return rk_ok;
121 }
122 
kmpp_meta_deinit(void)123 static void kmpp_meta_deinit(void)
124 {
125     KmppMetaSrv *srv = srv_meta;
126 
127     if (!srv) {
128         kmeta_dbg_func("kmpp meta already deinit\n");
129         return;
130     }
131 
132     if (srv->def) {
133         kmpp_objdef_put(srv->def);
134         srv->def = NULL;
135     }
136 
137     pthread_mutex_destroy(&srv->lock);
138 
139     MPP_FREE(srv);
140     srv_meta = NULL;
141 }
142 
kmpp_meta_init(void)143 static void kmpp_meta_init(void)
144 {
145     KmppMetaSrv *srv = srv_meta;
146     pthread_mutexattr_t attr;
147 
148     if (srv) {
149         kmeta_dbg_func("kmpp meta %p already init\n", srv);
150         kmpp_meta_deinit();
151     }
152 
153     srv = mpp_calloc(KmppMetaSrv, 1);
154     if (!srv) {
155         mpp_loge_f("kmpp meta malloc failed\n");
156         return;
157     }
158 
159     pthread_mutexattr_init(&attr);
160     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
161     pthread_mutex_init(&srv->lock, &attr);
162     pthread_mutexattr_destroy(&attr);
163 
164     INIT_LIST_HEAD(&srv->list);
165     kmpp_objdef_get(&srv->def, sizeof(KmppMetaPriv), "KmppMeta");
166     if (!srv->def) {
167         kmeta_dbg_func("kmpp meta get objdef failed\n");
168         MPP_FREE(srv);
169         return;
170     }
171 
172     kmpp_objdef_add_init(srv->def, kmpp_meta_impl_init);
173     kmpp_objdef_add_deinit(srv->def, kmpp_meta_impl_deinit);
174 
175     {
176         KmppEntry *tbl = NULL;
177 
178         kmpp_objdef_get_entry(srv->def, "size", &tbl);
179         srv->offset_size = tbl ? tbl->tbl.elem_offset : 0;
180     }
181 
182     srv_meta = srv;
183 }
184 
185 MPP_SINGLETON(MPP_SGLN_KMPP_META, kmpp_meta, kmpp_meta_init, kmpp_meta_deinit);
186 
meta_key_to_addr(KmppObj meta,KmppMetaKey key,KmppMetaType type)187 static void *meta_key_to_addr(KmppObj meta, KmppMetaKey key, KmppMetaType type)
188 {
189     if (meta) {
190         KmppMetaSrv *srv = srv_meta;
191         rk_u64 val = META_KEY_TO_U64(key, type);
192         KmppEntry *tbl = NULL;
193 
194         kmpp_objdef_get_entry(srv->def, (const char *)&val, &tbl);
195         if (tbl)
196             return ((rk_u8 *)kmpp_obj_to_entry(meta)) + tbl->tbl.elem_offset;
197     }
198 
199     return NULL;
200 }
201 
meta_inc_size(KmppObj meta,rk_s32 val,const char * caller)202 static rk_s32 meta_inc_size(KmppObj meta, rk_s32 val, const char *caller)
203 {
204     rk_s32 ret = 0;
205 
206     if (meta && srv_meta) {
207         void *entry = kmpp_obj_to_entry(meta);
208         rk_s32 offset = srv_meta->offset_size;
209 
210         if (entry && offset) {
211             rk_s32 *p = (rk_s32 *)((rk_u8 *)entry + offset);
212 
213             ret = MPP_FETCH_ADD(p, val);
214             kmeta_dbg_size("meta %p size %d -> %d at %s\n",
215                            meta, p[0], ret, caller);
216         }
217     }
218 
219     return ret;
220 }
221 
meta_dec_size(KmppObj meta,rk_s32 val,const char * caller)222 static rk_s32 meta_dec_size(KmppObj meta, rk_s32 val, const char *caller)
223 {
224     rk_s32 ret = 0;
225 
226     if (meta && srv_meta) {
227         void *entry = kmpp_obj_to_entry(meta);
228         rk_s32 offset = srv_meta->offset_size;
229 
230         if (entry && offset) {
231             rk_s32 *p = (rk_s32 *)((rk_u8 *)entry + offset);
232 
233             ret = MPP_FETCH_SUB(p, val);
234             kmeta_dbg_size("meta %p size %d -> %d at %s\n",
235                            meta, p[0], ret, caller);
236         }
237     }
238 
239     return ret;
240 }
241 
kmpp_meta_get(KmppMeta * meta,const char * caller)242 rk_s32 kmpp_meta_get(KmppMeta *meta, const char *caller)
243 {
244     KmppMetaSrv *srv = get_meta_srv(caller);
245 
246     if (!srv)
247         return rk_nok;
248 
249     return kmpp_obj_get(meta, srv->def, caller);
250 }
251 
kmpp_meta_put(KmppMeta meta,const char * caller)252 rk_s32 kmpp_meta_put(KmppMeta meta, const char *caller)
253 {
254     KmppMetaSrv *srv = get_meta_srv(caller);
255 
256     if (!srv)
257         return rk_nok;
258 
259     return kmpp_obj_put(meta, caller);
260 }
261 
kmpp_meta_size(KmppMeta meta,const char * caller)262 rk_s32 kmpp_meta_size(KmppMeta meta, const char *caller)
263 {
264     return meta_inc_size(meta, 0, caller);
265 }
266 
kmpp_meta_dump(KmppMeta meta,const char * caller)267 rk_s32 kmpp_meta_dump(KmppMeta meta, const char *caller)
268 {
269     return kmpp_obj_udump_f(meta, caller);
270 }
271 
kmpp_meta_dump_all(const char * caller)272 rk_s32 kmpp_meta_dump_all(const char *caller)
273 {
274     KmppMetaSrv *srv = get_meta_srv(caller);
275 
276     if (srv) {
277         KmppMeta meta = NULL;
278         KmppMetaPriv *pos, *n;
279 
280         pthread_mutex_lock(&srv->lock);
281         list_for_each_entry_safe(pos, n, &srv->list, KmppMetaPriv, list) {
282             meta = pos->meta;
283             mpp_logi("meta %p:%d size %d\n", meta, pos->meta_id,
284                      kmpp_meta_size(meta, caller));
285             kmpp_meta_dump(meta, caller);
286         }
287     }
288 
289     return rk_ok;
290 }
291 
292 #define KMPP_META_ACCESSOR(func_type, arg_type, key_type, key_field)  \
293     rk_s32 kmpp_meta_set_##func_type(KmppMeta meta, KmppMetaKey key, arg_type val) \
294     { \
295         KmppMetaVal *meta_val = meta_key_to_addr(meta, key, key_type); \
296         if (!meta_val) \
297             return rk_nok; \
298         if (MPP_BOOL_CAS(&meta_val->state, META_VAL_INVALID, META_VAL_VALID)) \
299             meta_inc_size(meta, 1, __FUNCTION__); \
300         meta_val->key_field = val; \
301         MPP_FETCH_OR(&meta_val->state, META_VAL_READY); \
302         return rk_ok; \
303     } \
304     rk_s32 kmpp_meta_get_##func_type(KmppMeta meta, KmppMetaKey key, arg_type *val) \
305     { \
306         KmppMetaVal *meta_val = meta_key_to_addr(meta, key, key_type); \
307         if (!meta_val) \
308             return rk_nok; \
309         if (MPP_BOOL_CAS(&meta_val->state, META_READY_MASK, META_VAL_INVALID)) { \
310             if (val) *val = meta_val->key_field; \
311             meta_dec_size(meta, 1, __FUNCTION__); \
312             return rk_ok; \
313         } \
314         return rk_nok; \
315     } \
316     rk_s32 kmpp_meta_get_##func_type##_d(KmppMeta meta, KmppMetaKey key, arg_type *val, arg_type def) \
317     { \
318         KmppMetaVal *meta_val = meta_key_to_addr(meta, key, key_type); \
319         if (!meta_val) \
320             return rk_nok; \
321         if (MPP_BOOL_CAS(&meta_val->state, META_READY_MASK, META_VAL_INVALID)) { \
322             if (val) *val = meta_val->key_field; \
323             meta_dec_size(meta, 1, __FUNCTION__); \
324         } else { \
325             if (val) *val = def; \
326         } \
327         return rk_ok; \
328     }
329 
KMPP_META_ACCESSOR(s32,rk_s32,TYPE_VAL_32,val_s32)330 KMPP_META_ACCESSOR(s32, rk_s32, TYPE_VAL_32, val_s32)
331 KMPP_META_ACCESSOR(s64, rk_s64, TYPE_VAL_64, val_s64)
332 KMPP_META_ACCESSOR(ptr, void *, TYPE_UPTR, val_ptr)
333 
334 rk_s32 kmpp_meta_set_obj(KmppMeta meta, KmppMetaKey key, KmppObj val)
335 {
336     KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR);
337 
338     if (!meta_obj)
339         return rk_nok;
340 
341     if (MPP_BOOL_CAS(&meta_obj->state, META_VAL_INVALID, META_VAL_VALID))
342         meta_inc_size(meta, 1, __FUNCTION__);
343 
344     {
345         KmppShmPtr *ptr = kmpp_obj_to_shm(val);
346 
347         if (ptr) {
348             meta_obj->val_shm.uaddr = ptr->uaddr;
349             meta_obj->val_shm.kaddr = ptr->kaddr;;
350             MPP_FETCH_OR(&meta_obj->state, META_VAL_IS_SHM);
351         } else {
352             meta_obj->val_shm.uaddr = 0;
353             meta_obj->val_shm.kptr = val;
354             MPP_FETCH_AND(&meta_obj->state, ~META_VAL_IS_SHM);
355         }
356     }
357     MPP_FETCH_OR(&meta_obj->state, META_VAL_READY);
358     return rk_ok;
359 }
360 
kmpp_meta_get_obj(KmppMeta meta,KmppMetaKey key,KmppObj * val)361 rk_s32 kmpp_meta_get_obj(KmppMeta meta, KmppMetaKey key, KmppObj *val)
362 {
363     KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR);
364 
365     if (!meta_obj)
366         return rk_nok;
367 
368     META_UNMASK_PROP(&meta_obj->state);
369     if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) {
370         if (val)
371             *val = meta_obj->val_shm.kptr;
372         meta_dec_size(meta, 1, __FUNCTION__);
373         return rk_ok;
374     }
375 
376     return rk_nok;
377 }
378 
kmpp_meta_get_obj_d(KmppMeta meta,KmppMetaKey key,KmppObj * val,KmppObj def)379 rk_s32 kmpp_meta_get_obj_d(KmppMeta meta, KmppMetaKey key, KmppObj *val, KmppObj def)
380 {
381     KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR);
382 
383     if (!meta_obj)
384         return rk_nok;
385 
386     META_UNMASK_PROP(&meta_obj->state);
387     if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) {
388         if (val)
389             *val = meta_obj->val_shm.kptr;
390         meta_dec_size(meta, 1, __FUNCTION__);
391     } else {
392         if (val)
393             *val = def ? def : NULL;
394     }
395 
396     return rk_ok;
397 }
398 
kmpp_meta_set_shm(KmppMeta meta,KmppMetaKey key,KmppShmPtr * sptr)399 rk_s32 kmpp_meta_set_shm(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr)
400 {
401     KmppMetaObj *meta_obj = (KmppMetaObj *)meta_key_to_addr(meta, key, TYPE_SPTR);
402 
403     if (!meta_obj)
404         return rk_nok;
405 
406     if (MPP_BOOL_CAS(&meta_obj->state, META_VAL_INVALID, META_VAL_VALID))
407         meta_inc_size(meta, 1, __FUNCTION__);
408 
409     if (sptr) {
410         meta_obj->val_shm.uaddr = sptr->uaddr;
411         meta_obj->val_shm.kaddr = sptr->kaddr;
412     } else {
413         meta_obj->val_shm.uaddr = 0;
414         meta_obj->val_shm.kptr = 0;
415     }
416 
417     if (sptr && sptr->uaddr)
418         MPP_FETCH_OR(&meta_obj->state, META_VAL_IS_SHM);
419     else
420         MPP_FETCH_AND(&meta_obj->state, ~META_VAL_IS_SHM);
421 
422     MPP_FETCH_OR(&meta_obj->state, META_VAL_READY);
423 
424     return rk_ok;
425 }
426 
kmpp_meta_get_shm(KmppMeta meta,KmppMetaKey key,KmppShmPtr * sptr)427 rk_s32 kmpp_meta_get_shm(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr)
428 {
429     KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR);
430 
431     if (!meta_obj)
432         return rk_nok;
433 
434     META_UNMASK_PROP(&meta_obj->state);
435     if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) {
436         if (sptr) {
437             sptr->uaddr = meta_obj->val_shm.uaddr;
438             sptr->kaddr = meta_obj->val_shm.kaddr;
439         }
440         meta_dec_size(meta, 1, __FUNCTION__);
441         return rk_ok;
442     }
443     return rk_nok;
444 }
445 
kmpp_meta_get_shm_d(KmppMeta meta,KmppMetaKey key,KmppShmPtr * sptr,KmppShmPtr * def)446 rk_s32 kmpp_meta_get_shm_d(KmppMeta meta, KmppMetaKey key, KmppShmPtr *sptr, KmppShmPtr *def)
447 {
448     KmppMetaObj *meta_obj = meta_key_to_addr(meta, key, TYPE_SPTR);
449 
450     if (!meta_obj)
451         return rk_nok;
452 
453     META_UNMASK_PROP(&meta_obj->state);
454     if (MPP_BOOL_CAS(&meta_obj->state, META_READY_MASK, META_VAL_INVALID)) {
455         if (sptr) {
456             sptr->uaddr = meta_obj->val_shm.uaddr;
457             sptr->kaddr = meta_obj->val_shm.kaddr;
458         }
459         meta_dec_size(meta, 1, __FUNCTION__);
460     } else {
461         if (sptr) {
462             if (def) {
463                 sptr->uaddr = def->uaddr;
464                 sptr->kaddr = def->kaddr;
465             } else {
466                 sptr->uaddr = 0;
467                 sptr->kaddr = 0;
468             }
469         }
470     }
471 
472     return rk_ok;
473 }
474