xref: /rockchip-linux_mpp/osal/mpp_singleton.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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