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