141 lines
4.1 KiB
C
141 lines
4.1 KiB
C
/* SPDX-License-Identifier: Apache-2.0 OR MIT */
|
|
/*
|
|
* Copyright (c) 2026 Rockchip Electronics Co., Ltd.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "mpp_common.h"
|
|
#include "mpp_env.h"
|
|
#include "mpp_time.h"
|
|
#include "mpp_sgln_base.h"
|
|
|
|
#define SGLN_LOG(base, fmt, ...) \
|
|
do { if ((base)->debug) printf("%s: " fmt, (base)->name, ##__VA_ARGS__); } while (0)
|
|
|
|
#define SGLN_ERR(base, fmt, ...) \
|
|
printf("%s: " fmt, (base)->name, ##__VA_ARGS__)
|
|
|
|
rk_s32 mpp_sgln_base_add(MppSglnBase *base, MppSglnInfo *info, const char *caller)
|
|
{
|
|
MppSglnList *arr;
|
|
rk_s32 id;
|
|
|
|
mpp_env_get_u32(base->name, &base->debug, 0);
|
|
|
|
if (!info) {
|
|
SGLN_ERR(base, "can not add NULL entry at %s\n", caller);
|
|
return rk_nok;
|
|
}
|
|
|
|
id = info->id;
|
|
|
|
arr = (id < 0 && base->array_count > 1) ? base->arrays[1] : base->arrays[0];
|
|
|
|
if (id >= 0) {
|
|
if (id >= (rk_s32)arr->capacity) {
|
|
SGLN_ERR(base, "id %d larger than max %d at %s\n", id, arr->capacity, caller);
|
|
return rk_nok;
|
|
}
|
|
if (arr->entries[id].name) {
|
|
SGLN_ERR(base, "entry %d has been registered at %s\n", id, caller);
|
|
return rk_nok;
|
|
}
|
|
arr->count = MPP_MAX(arr->count, (rk_u32)id + 1);
|
|
} else {
|
|
/* A second copy of this library may be loaded into the same
|
|
* process (e.g. statically linked into one .so and dlopen-ed
|
|
* again as another). Symbol interposition then routes its
|
|
* registrations to this base and would overflow this list.
|
|
*
|
|
* The dynamic loader runs all constructors of one library
|
|
* (including the final run_init) before any constructor of
|
|
* another library, so a registration arriving after init_done
|
|
* is set always comes from such a second copy and duplicates
|
|
* an existing entry. Reject it and keep the list frozen.
|
|
*/
|
|
if (base->init_done) {
|
|
SGLN_ERR(base, "reject duplicated entry %s at %s\n",
|
|
info->name ? info->name : "?", caller);
|
|
return rk_ok;
|
|
}
|
|
if (arr->count >= arr->capacity) {
|
|
SGLN_ERR(base, "no-id list full at %s\n", caller);
|
|
abort();
|
|
return rk_nok;
|
|
}
|
|
info->id = arr->count++;
|
|
}
|
|
|
|
arr->entries[info->id] = *info;
|
|
|
|
{
|
|
rk_u32 len = strlen(info->name);
|
|
|
|
if (len > base->max_name_len)
|
|
base->max_name_len = len;
|
|
}
|
|
|
|
SGLN_LOG(base, "entry %2d %-*s registered at %s\n",
|
|
info->id, base->max_name_len, info->name, caller);
|
|
|
|
return rk_ok;
|
|
}
|
|
|
|
void mpp_sgln_base_deinit(MppSglnBase *base)
|
|
{
|
|
rk_s32 j;
|
|
|
|
SGLN_LOG(base, "deinit enter\n");
|
|
|
|
for (j = base->array_count - 1; j >= 0; j--) {
|
|
MppSglnList *arr = base->arrays[j];
|
|
rk_s32 i;
|
|
|
|
for (i = (rk_s32)arr->count - 1; i >= 0; i--) {
|
|
MppSglnInfo *info = &arr->entries[i];
|
|
|
|
if (info->name && info->deinit) {
|
|
SGLN_LOG(base, "entry %2d %-*s deinit start\n",
|
|
info->id, base->max_name_len, info->name);
|
|
info->deinit();
|
|
SGLN_LOG(base, "entry %2d %-*s deinit finish\n",
|
|
info->id, base->max_name_len, info->name);
|
|
}
|
|
}
|
|
}
|
|
|
|
SGLN_LOG(base, "deinit leave\n");
|
|
}
|
|
|
|
void mpp_sgln_base_run_init(MppSglnBase *base)
|
|
{
|
|
rk_s64 sum = 0;
|
|
rk_s32 j;
|
|
|
|
SGLN_LOG(base, "init enter\n");
|
|
|
|
for (j = 0; j < (rk_s32)base->array_count; j++) {
|
|
MppSglnList *arr = base->arrays[j];
|
|
rk_s32 i;
|
|
|
|
for (i = 0; i < (rk_s32)arr->count; i++) {
|
|
MppSglnInfo *info = &arr->entries[i];
|
|
|
|
if (info->name && info->init) {
|
|
rk_s64 time = mpp_time();
|
|
SGLN_LOG(base, "entry %2d %-*s init start\n",
|
|
info->id, base->max_name_len, info->name);
|
|
info->init();
|
|
time = mpp_time() - time;
|
|
sum += time;
|
|
SGLN_LOG(base, "entry %2d %-*s init finish %lld us\n",
|
|
info->id, base->max_name_len, info->name, time);
|
|
}
|
|
}
|
|
}
|
|
|
|
base->init_done = 1;
|
|
|
|
SGLN_LOG(base, "init leave total %lld us\n", sum);
|
|
}
|