1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2024 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "mpp_singleton"
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "mpp_env.h"
13 #include "mpp_time.h"
14 #include "mpp_singleton.h"
15
16 #define sgln_dbg(fmt, ...) \
17 do { \
18 if (sgln_debug) \
19 printf(MODULE_TAG ": " fmt, ##__VA_ARGS__); \
20 } while (0)
21
22 static MppSingletonInfo sgln_info[MPP_SGLN_MAX_CNT] = {0};
23 static rk_u32 sgln_max_name_len = 12;
24 static rk_u64 sgln_mask = 0;
25 static rk_u32 sgln_debug = 0;
26
mpp_singleton_add(MppSingletonInfo * info,const char * caller)27 rk_s32 mpp_singleton_add(MppSingletonInfo *info, const char *caller)
28 {
29 mpp_env_get_u32("mpp_sgln_debug", &sgln_debug, 0);
30
31 if (!info) {
32 sgln_dbg("can not add NULL info at %s\n", caller);
33 return rk_nok;
34 }
35
36 if (info->id >= MPP_SGLN_MAX_CNT) {
37 sgln_dbg("id %d larger than max %d at %s\n", info->id, MPP_SGLN_MAX_CNT, caller);
38 return rk_nok;
39 }
40
41 if (sgln_mask & ((rk_u64)1 << info->id)) {
42 sgln_dbg("info %d has been registered at %s\n", info->id, caller);
43 return rk_nok;
44 }
45
46 sgln_info[info->id] = *info;
47 sgln_mask |= ((rk_u64)1 << info->id);
48
49 {
50 rk_u32 name_len = strlen(info->name);
51
52 if (name_len > sgln_max_name_len)
53 sgln_max_name_len = name_len;
54 }
55
56 sgln_dbg("info %2d %-*s registered at %s\n", info->id,
57 sgln_max_name_len, info->name, caller);
58
59 return rk_ok;
60 }
61
mpp_singleton_deinit(void)62 static void mpp_singleton_deinit(void)
63 {
64 rk_s32 i;
65
66 sgln_dbg("deinit enter\n");
67
68 /* NOTE: revert deinit order */
69 for (i = MPP_SGLN_MAX_CNT - 1; i >= 0; i--) {
70 if (sgln_mask & ((rk_u64)1 << i)) {
71 MppSingletonInfo *info = &sgln_info[i];
72
73 if (info->deinit) {
74 sgln_dbg("info %2d %-*s deinit start\n", info->id,
75 sgln_max_name_len, info->name);
76
77 info->deinit();
78
79 sgln_dbg("info %2d %-*s deinit finish\n", info->id,
80 sgln_max_name_len, info->name);
81 }
82 }
83 }
84
85 sgln_dbg("deinit leave\n");
86 }
87
mpp_singleton_init(void)88 __attribute__((constructor(65535))) static void mpp_singleton_init(void)
89 {
90 rk_s64 sum = 0;
91 rk_s32 i;
92
93 sgln_dbg("init enter\n");
94
95 /* NOTE: call atexit first to avoid init crash but not deinit */
96 atexit(mpp_singleton_deinit);
97
98 for (i = 0; i < MPP_SGLN_MAX_CNT; i++) {
99 if (sgln_mask & ((rk_u64)1 << i)) {
100 MppSingletonInfo *info = &sgln_info[i];
101
102 if (info->init) {
103 rk_s64 time;
104
105 sgln_dbg("info %2d %-*s init start\n", info->id,
106 sgln_max_name_len, info->name);
107
108 time = mpp_time();
109 info->init();
110 time = mpp_time() - time;
111 sum += time;
112
113 sgln_dbg("info %2d %-*s init finish %lld us\n", info->id,
114 sgln_max_name_len, info->name, time);
115 }
116 }
117 }
118
119 sgln_dbg("init leave total %lld us\n", sum);
120 }
121