mirror of
https://gitee.com/openharmony/startup_init
synced 2025-02-25 23:15:38 +00:00
Bugfix: 优化bootevent度量开机启动耗时
1) 去掉无效的init_trace静态插件 2)去掉InitAddServiceHook在INIT_SERVICE_FORK_BEFORE阶段的无效记录时间戳 3)优化INIT_CMD_RECORD的hook,只对耗时超过100ms的命令加入到bootevents列表 4)每次开机都记录同名的startup.bootevent文件,防止开机次数过多,产生过多垃圾文件 5)简化bootevent的clear命令处理逻辑 6)记录每个bootevent时间点到系统参数中 7)支持为系统应用预置bootevents Signed-off-by: handyohos <zhangxiaotian@huawei.com> Change-Id: I7cdc269fe1a0eb8e4394de010f1f71e6c16b5a6c #I7XYNX
This commit is contained in:
parent
749ff1b9f4
commit
b5ac43a708
@ -222,8 +222,6 @@ int InitAddJobParseHook(JobParseHook hook);
|
||||
*/
|
||||
int InitAddServiceHook(ServiceHook hook, int hookState);
|
||||
|
||||
int InitAddClearServiceHook(ServiceHook hook);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
|
@ -23,4 +23,4 @@ sys_param=4096
|
||||
bootevent_param=4096
|
||||
startup_init_param=40960
|
||||
hiviewdfx_profiler_param=2048
|
||||
ohos_boot_param = 4096
|
||||
ohos_boot_param = 8192
|
@ -20,6 +20,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "beget_ext.h"
|
||||
|
||||
@ -104,6 +105,8 @@ int GetParameterFromCmdLine(const char *paramName, char *value, size_t valueLen)
|
||||
*/
|
||||
int StrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase);
|
||||
|
||||
long long GetUptimeInMicroSeconds(const struct timespec *uptime);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ extern "C" {
|
||||
|
||||
void SystemInit(void);
|
||||
void LogInit(void);
|
||||
void SystemPrepare(void);
|
||||
void SystemConfig(void);
|
||||
void SystemPrepare(long long uptime);
|
||||
void SystemConfig(const char *uptime);
|
||||
void SystemRun(void);
|
||||
void SystemExecuteRcs(void);
|
||||
|
||||
|
@ -46,7 +46,7 @@ void LogInit(void)
|
||||
return;
|
||||
}
|
||||
|
||||
void SystemPrepare(void)
|
||||
void SystemPrepare(long long uptime)
|
||||
{
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ void ParseInitCfgByPriority(void)
|
||||
ReadFileInDir("/vendor/etc/init", ".cfg", ParseInitCfg, NULL);
|
||||
}
|
||||
|
||||
void SystemConfig(void)
|
||||
void SystemConfig(const char *uptime)
|
||||
{
|
||||
InitServiceSpace();
|
||||
#ifdef LITEOS_SUPPORT
|
||||
|
@ -15,16 +15,24 @@
|
||||
#include <signal.h>
|
||||
#include "init.h"
|
||||
#include "init_log.h"
|
||||
#include "init_utils.h"
|
||||
|
||||
static const pid_t INIT_PROCESS_PID = 1;
|
||||
|
||||
int main(int argc, char * const argv[])
|
||||
{
|
||||
const char *uptime = NULL;
|
||||
long long upTimeInMicroSecs = 0;
|
||||
int isSecondStage = 0;
|
||||
(void)signal(SIGPIPE, SIG_IGN);
|
||||
// Number of command line parameters is 2
|
||||
if (argc == 2 && (strcmp(argv[1], "--second-stage") == 0)) {
|
||||
if (argc > 1 && (strcmp(argv[1], "--second-stage") == 0)) {
|
||||
isSecondStage = 1;
|
||||
if (argc > 2) {
|
||||
uptime = argv[2];
|
||||
}
|
||||
} else {
|
||||
upTimeInMicroSecs = GetUptimeInMicroSeconds(NULL);
|
||||
}
|
||||
if (getpid() != INIT_PROCESS_PID) {
|
||||
INIT_LOGE("Process id error %d!", getpid());
|
||||
@ -32,13 +40,13 @@ int main(int argc, char * const argv[])
|
||||
}
|
||||
EnableInitLog(INIT_INFO);
|
||||
if (isSecondStage == 0) {
|
||||
SystemPrepare();
|
||||
SystemPrepare(upTimeInMicroSecs);
|
||||
} else {
|
||||
LogInit();
|
||||
}
|
||||
SystemInit();
|
||||
SystemExecuteRcs();
|
||||
SystemConfig();
|
||||
SystemConfig(uptime);
|
||||
SystemRun();
|
||||
return 0;
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ static int StartUeventd(char **requiredDevices, int num)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void StartInitSecondStage(void)
|
||||
static void StartInitSecondStage(long long uptime)
|
||||
{
|
||||
int requiredNum = 0;
|
||||
Fstab *fstab = LoadRequiredFstab();
|
||||
@ -210,10 +210,13 @@ static void StartInitSecondStage(void)
|
||||
|
||||
INIT_LOGI("Start init second stage.");
|
||||
SwitchRoot("/usr");
|
||||
char buf[64];
|
||||
snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%lld", uptime);
|
||||
// Execute init second stage
|
||||
char * const args[] = {
|
||||
"/bin/init",
|
||||
"--second-stage",
|
||||
buf,
|
||||
NULL,
|
||||
};
|
||||
if (execv("/bin/init", args) != 0) {
|
||||
@ -222,7 +225,7 @@ static void StartInitSecondStage(void)
|
||||
}
|
||||
}
|
||||
|
||||
void SystemPrepare(void)
|
||||
void SystemPrepare(long long uptime)
|
||||
{
|
||||
MountBasicFs();
|
||||
CreateDeviceNode();
|
||||
@ -235,7 +238,7 @@ void SystemPrepare(void)
|
||||
// two stages of init.
|
||||
// If we are in updater mode, only one stage of init.
|
||||
if (InUpdaterMode() == 0) {
|
||||
StartInitSecondStage();
|
||||
StartInitSecondStage(uptime);
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,7 +391,19 @@ void ParseInitCfgByPriority(void)
|
||||
FreeCfgFiles(files);
|
||||
}
|
||||
|
||||
void SystemConfig(void)
|
||||
static void WriteUptimeSysParam(const char *param, const char *uptime)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
if (uptime == NULL) {
|
||||
snprintf_s(buf, sizeof(buf), sizeof(buf) - 1,
|
||||
"%lld", GetUptimeInMicroSeconds(NULL));
|
||||
uptime = buf;
|
||||
}
|
||||
SystemWriteParam(param, uptime);
|
||||
}
|
||||
|
||||
void SystemConfig(const char *uptime)
|
||||
{
|
||||
INIT_TIMING_STAT timingStat;
|
||||
|
||||
@ -424,6 +439,10 @@ void SystemConfig(void)
|
||||
// parse parameters
|
||||
HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_PARAM_LOAD, (void *)&timingStat, (void *)&options);
|
||||
InitLoadParamFiles();
|
||||
|
||||
// Write kernel uptime into system parameter
|
||||
WriteUptimeSysParam("ohos.boot.time.kernel", uptime);
|
||||
|
||||
// read config
|
||||
HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, (void *)&timingStat, (void *)&options);
|
||||
ReadConfig();
|
||||
@ -443,5 +462,6 @@ void SystemConfig(void)
|
||||
|
||||
void SystemRun(void)
|
||||
{
|
||||
WriteUptimeSysParam("ohos.boot.time.init", NULL);
|
||||
StartParamService();
|
||||
}
|
||||
|
@ -29,10 +29,7 @@ group("static_modules") {
|
||||
if (build_selinux) {
|
||||
deps += [ "selinux:libselinuxadp_static" ]
|
||||
}
|
||||
deps += [
|
||||
"trace:inittrace_cfg",
|
||||
"trace:libinittrace_static",
|
||||
]
|
||||
deps += [ "trace:inittrace_cfg" ]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ config("bootevent_static_config") {
|
||||
"//base/startup/init/services/param/include",
|
||||
"//base/startup/init/services/include/param",
|
||||
"//third_party/bounds_checking_function/include/",
|
||||
"//base/customization/config_policy/interfaces/inner_api/include",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "init_module_engine.h"
|
||||
#include "init_group_manager.h"
|
||||
#include "init_cmdexecutor.h"
|
||||
#include "trigger_manager.h"
|
||||
#include "init_log.h"
|
||||
@ -26,10 +27,21 @@
|
||||
#include "securec.h"
|
||||
#include "init_utils.h"
|
||||
#include "init_cmds.h"
|
||||
#include "config_policy_utils.h"
|
||||
|
||||
static int GetBootEventEnable(void)
|
||||
{
|
||||
char bootEventOpen[6] = ""; // 6 is length of bool value
|
||||
uint32_t len = sizeof(bootEventOpen);
|
||||
SystemReadParam("persist.init.bootevent.enable", bootEventOpen, &len);
|
||||
if (strcmp(bootEventOpen, "true") == 0 || strcmp(bootEventOpen, "1") == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int g_bootEventNum = 0;
|
||||
// check bootevent enable
|
||||
static int g_bootEventEnable = 1;
|
||||
|
||||
static ListNode bootEventList = {&bootEventList, &bootEventList};
|
||||
|
||||
static int BootEventParaListCompareProc(ListNode *node, void *data)
|
||||
@ -53,6 +65,33 @@ static int ParseBooteventCompareProc(ListNode *node, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int AddBootEventItem(BOOT_EVENT_PARAM_ITEM *item, const char *paramName)
|
||||
{
|
||||
OH_ListInit(&item->node);
|
||||
for (int i = 0; i < BOOTEVENT_MAX; i++) {
|
||||
item->timestamp[i].tv_nsec = 0;
|
||||
item->timestamp[i].tv_sec = 0;
|
||||
}
|
||||
item->paramName = strdup(paramName);
|
||||
if (item->paramName == NULL) {
|
||||
return -1;
|
||||
}
|
||||
item->flags = BOOTEVENT_TYPE_SERVICE;
|
||||
OH_ListAddTail(&bootEventList, (ListNode *)&item->node);
|
||||
g_bootEventNum++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int AddBootEventItemByName(const char *paramName)
|
||||
{
|
||||
BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)calloc(1, sizeof(BOOT_EVENT_PARAM_ITEM));
|
||||
if (item == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return AddBootEventItem(item, paramName);
|
||||
}
|
||||
|
||||
static int AddServiceBootEvent(const char *serviceName, const char *paramName)
|
||||
{
|
||||
ServiceExtData *extData = NULL;
|
||||
@ -64,6 +103,7 @@ static int AddServiceBootEvent(const char *serviceName, const char *paramName)
|
||||
if (found != NULL) {
|
||||
return -1;
|
||||
}
|
||||
// Find an empty bootevent data position
|
||||
for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) {
|
||||
extData = AddServiceExtData(serviceName, i, NULL, sizeof(BOOT_EVENT_PARAM_ITEM));
|
||||
if (extData != NULL) {
|
||||
@ -74,28 +114,21 @@ static int AddServiceBootEvent(const char *serviceName, const char *paramName)
|
||||
INIT_CHECK(extData != NULL, return -1);
|
||||
|
||||
BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)extData->data;
|
||||
OH_ListInit(&item->node);
|
||||
for (int i = 0; i < BOOTEVENT_MAX; i++) {
|
||||
item->timestamp[i].tv_nsec = 0;
|
||||
item->timestamp[i].tv_sec = 0;
|
||||
}
|
||||
item->paramName = strdup(paramName);
|
||||
if (item->paramName == NULL) {
|
||||
|
||||
if (AddBootEventItem(item, paramName) != 0) {
|
||||
DelServiceExtData(serviceName, extData->dataId);
|
||||
INIT_LOGI("strdup failed");
|
||||
return -1;
|
||||
}
|
||||
item->flags = BOOTEVENT_TYPE_SERVICE;
|
||||
OH_ListAddTail(&bootEventList, (ListNode *)&item->node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void AddInitBootEvent(const char *bootEventName)
|
||||
{
|
||||
ListNode *found = NULL;
|
||||
found = OH_ListFind(&bootEventList, (void *)bootEventName, ParseBooteventCompareProc);
|
||||
BOOT_EVENT_PARAM_ITEM *found = NULL;
|
||||
found = (BOOT_EVENT_PARAM_ITEM *)OH_ListFind(&bootEventList, (void *)bootEventName, ParseBooteventCompareProc);
|
||||
if (found != NULL) {
|
||||
(void)clock_gettime(CLOCK_MONOTONIC, &(((BOOT_EVENT_PARAM_ITEM *)found)->timestamp[BOOTEVENT_READY]));
|
||||
(void)clock_gettime(CLOCK_MONOTONIC, &(found->timestamp[BOOTEVENT_READY]));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -167,16 +200,8 @@ static int BootEventTraversal(ListNode *node, void *root)
|
||||
static int SaveServiceBootEvent()
|
||||
{
|
||||
INIT_CHECK(GetBootEventEnable(), return 0);
|
||||
time_t nowTime = time(NULL);
|
||||
INIT_CHECK_RETURN_VALUE(nowTime > 0, -1);
|
||||
struct tm *p = localtime(&nowTime);
|
||||
INIT_CHECK_RETURN_VALUE(p != NULL, -1);
|
||||
char bootEventFileName[BOOT_EVENT_FILEPATH_MAX_LEN] = "";
|
||||
INIT_CHECK_RETURN_VALUE(snprintf_s(bootEventFileName, BOOT_EVENT_FILEPATH_MAX_LEN, BOOT_EVENT_FILEPATH_MAX_LEN - 1,
|
||||
BOOTEVENT_OUTPUT_PATH"%d%d%d-%d%d.bootevent",
|
||||
1900 + p->tm_year, p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min) >= 0, -1); // 1900 is start year
|
||||
CheckAndCreatFile(bootEventFileName, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
||||
FILE *tmpFile = fopen(bootEventFileName, "wr");
|
||||
CheckAndCreatFile(BOOTEVENT_OUTPUT_PATH "bootup.trace", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
||||
FILE *tmpFile = fopen(BOOTEVENT_OUTPUT_PATH "bootup.trace", "wr");
|
||||
INIT_CHECK_RETURN_VALUE(tmpFile != NULL, -1);
|
||||
cJSON *root = cJSON_CreateArray();
|
||||
INIT_CHECK(root != NULL, (void)fclose(tmpFile);
|
||||
@ -218,50 +243,89 @@ static void SetServiceBooteventHookMgr(const char *name, int state)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void BootEventParaFireByName(const char *paramName)
|
||||
static void BootCompleteClearAll(void)
|
||||
{
|
||||
ListNode *found = NULL;
|
||||
char *bootEventValue = strrchr(paramName, '.');
|
||||
INIT_CHECK(bootEventValue != NULL, return);
|
||||
InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
|
||||
while (node != NULL) {
|
||||
if (node->data.service == NULL) {
|
||||
node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
|
||||
continue;
|
||||
}
|
||||
for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) {
|
||||
ServiceExtData *extData = GetServiceExtData(node->name, i);
|
||||
if (extData == NULL) {
|
||||
return;
|
||||
}
|
||||
free(((BOOT_EVENT_PARAM_ITEM *)extData->data)->paramName);
|
||||
OH_ListRemove(&((BOOT_EVENT_PARAM_ITEM *)extData->data)->node);
|
||||
DelServiceExtData(node->name, i);
|
||||
}
|
||||
}
|
||||
|
||||
// clear init boot event
|
||||
OH_ListRemoveAll(&bootEventList, BootEventDestroy);
|
||||
g_bootEventNum = 0;
|
||||
}
|
||||
|
||||
static void WriteBooteventSysParam(const char *paramName)
|
||||
{
|
||||
char buf[64];
|
||||
long long uptime;
|
||||
char name[PARAM_NAME_LEN_MAX];
|
||||
|
||||
uptime = GetUptimeInMicroSeconds(NULL);
|
||||
|
||||
snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%lld", uptime);
|
||||
snprintf_s(name, sizeof(name), sizeof(name) - 1, "ohos.boot.time.%s", paramName);
|
||||
SystemWriteParam(name, buf);
|
||||
}
|
||||
|
||||
static int BootEventParaFireByName(const char *paramName)
|
||||
{
|
||||
BOOT_EVENT_PARAM_ITEM *found = NULL;
|
||||
|
||||
char *bootEventValue = strrchr(paramName, '.');
|
||||
INIT_CHECK(bootEventValue != NULL, return 0);
|
||||
bootEventValue[0] = '\0';
|
||||
|
||||
found = OH_ListFind(&bootEventList, (void *)paramName, BootEventParaListCompareProc);
|
||||
if (found == NULL) {
|
||||
return;
|
||||
}
|
||||
int ret = ((BOOT_EVENT_PARAM_ITEM *)found)->timestamp[BOOTEVENT_READY].tv_sec;
|
||||
INIT_CHECK(ret == 0, return);
|
||||
WriteBooteventSysParam(paramName);
|
||||
|
||||
found = (BOOT_EVENT_PARAM_ITEM *)OH_ListFind(&bootEventList, (void *)paramName, BootEventParaListCompareProc);
|
||||
if (found == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Already fired
|
||||
if (found->timestamp[BOOTEVENT_READY].tv_sec > 0) {
|
||||
return 0;
|
||||
}
|
||||
INIT_CHECK_RETURN_VALUE(clock_gettime(CLOCK_MONOTONIC,
|
||||
&(found->timestamp[BOOTEVENT_READY])) == 0, 0);
|
||||
|
||||
INIT_CHECK_ONLY_RETURN(clock_gettime(CLOCK_MONOTONIC,
|
||||
&(((BOOT_EVENT_PARAM_ITEM *)found)->timestamp[BOOTEVENT_READY])) == 0);
|
||||
g_bootEventNum--;
|
||||
SetServiceBooteventHookMgr(paramName, 2); // 2: bootevent service has ready
|
||||
// Check if all boot event params are fired
|
||||
if (g_bootEventNum > 0) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
// All parameters are fired, set boot completed now ...
|
||||
INIT_LOGI("All boot events are fired, boot complete now ...");
|
||||
SystemWriteParam(BOOT_EVENT_BOOT_COMPLETED, "true");
|
||||
g_bootEventEnable = BOOT_EVENT_FINISH;
|
||||
SaveServiceBootEvent();
|
||||
// report complete event
|
||||
ReportSysEvent();
|
||||
const char *clearBootEventArgv[] = {"bootevent"};
|
||||
// clear servie extra data
|
||||
PluginExecCmd("clear", ARRAY_LENGTH(clearBootEventArgv), clearBootEventArgv);
|
||||
BootCompleteClearAll();
|
||||
#ifndef STARTUP_INIT_TEST
|
||||
HookMgrExecute(GetBootStageHookMgr(), INIT_BOOT_COMPLETE, NULL, NULL);
|
||||
#endif
|
||||
AutorunModuleMgrUnInstall("init_bootDetector");
|
||||
return;
|
||||
RemoveCmdExecutor("bootevent", -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define BOOT_EVENT_FIELD_NAME "bootevents"
|
||||
static void ServiceParseBootEventHook(SERVICE_PARSE_CTX *serviceParseCtx)
|
||||
{
|
||||
INIT_CHECK(g_bootEventEnable != 0, return);
|
||||
int cnt;
|
||||
cJSON *bootEvents = cJSON_GetObjectItem(serviceParseCtx->serviceNode, BOOT_EVENT_FIELD_NAME);
|
||||
|
||||
@ -279,7 +343,6 @@ static void ServiceParseBootEventHook(SERVICE_PARSE_CTX *serviceParseCtx)
|
||||
INIT_LOGI("Add service bootEvent failed %s", serviceParseCtx->serviceName);
|
||||
return;
|
||||
}
|
||||
g_bootEventNum++;
|
||||
SetServiceBooteventHookMgr(serviceParseCtx->serviceName, 1); // 1: bootevent service is starting
|
||||
return;
|
||||
}
|
||||
@ -293,47 +356,15 @@ static void ServiceParseBootEventHook(SERVICE_PARSE_CTX *serviceParseCtx)
|
||||
INIT_LOGI("Add service bootEvent failed %s", serviceParseCtx->serviceName);
|
||||
continue;
|
||||
}
|
||||
g_bootEventNum++;
|
||||
SetServiceBooteventHookMgr(serviceParseCtx->serviceName, 1); // 1: bootevent service is starting
|
||||
}
|
||||
}
|
||||
|
||||
static void AddCmdBootEvent(int argc, const char **argv)
|
||||
{
|
||||
if (argc < 4) { // 4 is min args cmd boot event required
|
||||
return;
|
||||
}
|
||||
|
||||
BOOT_EVENT_PARAM_ITEM *item = calloc(1, sizeof(BOOT_EVENT_PARAM_ITEM));
|
||||
INIT_CHECK(item != NULL, return);
|
||||
OH_ListInit(&item->node);
|
||||
item->timestamp[BOOTEVENT_FORK] = ((INIT_TIMING_STAT *)argv[3])->startTime; // 3 args
|
||||
item->timestamp[BOOTEVENT_READY] = ((INIT_TIMING_STAT *)argv[3])->endTime; // 3 args
|
||||
int cmdLen = strlen(argv[1]) + strlen(argv[2]) + 1; // 2 args 1 '\0'
|
||||
item->paramName = calloc(1, cmdLen);
|
||||
if (item->paramName == NULL) {
|
||||
free(item);
|
||||
return;
|
||||
}
|
||||
for (int i = 1; i < 3; i++) { // 3 cmd content end
|
||||
INIT_CHECK_ONLY_ELOG(strcat_s(item->paramName, cmdLen, argv[i]) >= 0, "combine cmd args failed");
|
||||
}
|
||||
item->flags = BOOTEVENT_TYPE_CMD;
|
||||
OH_ListAddTail(&bootEventList, (ListNode *)&item->node);
|
||||
return;
|
||||
}
|
||||
|
||||
static int DoBootEventCmd(int id, const char *name, int argc, const char **argv)
|
||||
{
|
||||
if (g_bootEventEnable == BOOT_EVENT_FINISH) {
|
||||
return 0;
|
||||
}
|
||||
// clear init boot events that recorded before persist param read
|
||||
if (g_bootEventEnable == 0) {
|
||||
const char *clearBootEventArgv[] = {"bootevent"};
|
||||
PluginExecCmd("clear", ARRAY_LENGTH(clearBootEventArgv), clearBootEventArgv);
|
||||
OH_ListRemoveAll(&bootEventList, BootEventDestroy);
|
||||
g_bootEventEnable = BOOT_EVENT_FINISH;
|
||||
static int finished = 0;
|
||||
|
||||
if (finished) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -343,75 +374,70 @@ static int DoBootEventCmd(int id, const char *name, int argc, const char **argv)
|
||||
return 0;
|
||||
}
|
||||
AddInitBootEvent(argv[1]);
|
||||
} else if (strcmp(argv[0], "cmd") == 0) {
|
||||
AddCmdBootEvent(argc, argv);
|
||||
} else {
|
||||
// argv[0] samgr.ready.true
|
||||
BootEventParaFireByName(argv[0]);
|
||||
finished = BootEventParaFireByName(argv[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t g_executorId = -1;
|
||||
static int ParamSetBootEventHook(const HOOK_INFO *hookInfo, void *cookie)
|
||||
static void AddReservedBooteventsByFile(const char *name)
|
||||
{
|
||||
if (g_executorId == -1) {
|
||||
g_executorId = AddCmdExecutor("bootevent", DoBootEventCmd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
char buf[MAX_PATH_LEN];
|
||||
|
||||
static void ClearServiceBootEvent(SERVICE_INFO_CTX *serviceCtx)
|
||||
{
|
||||
if (serviceCtx->reserved == NULL || strcmp(serviceCtx->reserved, "bootevent") == 0) {
|
||||
for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) {
|
||||
ServiceExtData *extData = GetServiceExtData(serviceCtx->serviceName, i);
|
||||
if (extData == NULL) {
|
||||
return;
|
||||
}
|
||||
free(((BOOT_EVENT_PARAM_ITEM *)extData->data)->paramName);
|
||||
OH_ListRemove(&((BOOT_EVENT_PARAM_ITEM *)extData->data)->node);
|
||||
DelServiceExtData(serviceCtx->serviceName, i);
|
||||
g_bootEventNum--;
|
||||
}
|
||||
// clear service extra data first
|
||||
FILE *file = fopen(name, "r");
|
||||
if (file == NULL) {
|
||||
return;
|
||||
}
|
||||
if (strcmp(serviceCtx->reserved, "clearInitBootevent") == 0) {
|
||||
// clear init boot event
|
||||
OH_ListRemoveAll(&bootEventList, BootEventDestroy);
|
||||
g_bootEventNum = 0;
|
||||
|
||||
while (fgets((void *)buf, sizeof(buf) - 1, file)) {
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
char *end = strchr(buf, '\r');
|
||||
if (end != NULL) {
|
||||
*end = '\0';
|
||||
}
|
||||
end = strchr(buf, '\n');
|
||||
if (end != NULL) {
|
||||
*end = '\0';
|
||||
}
|
||||
INIT_LOGI("Got priv-app bootevent: %s", buf);
|
||||
AddBootEventItemByName(buf);
|
||||
}
|
||||
return;
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
static void AddReservedBootevents(void) {
|
||||
CfgFiles *files = GetCfgFiles("etc/init/priv_app.bootevents");
|
||||
for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; files && i >= 0; i--) {
|
||||
if (files->paths[i]) {
|
||||
AddReservedBooteventsByFile(files->paths[i]);
|
||||
}
|
||||
}
|
||||
FreeCfgFiles(files);
|
||||
}
|
||||
|
||||
static int ParamSetBootEventHook(const HOOK_INFO *hookInfo, void *cookie)
|
||||
{
|
||||
AddReservedBootevents();
|
||||
AddCmdExecutor("bootevent", DoBootEventCmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SetServiceBootEventFork(SERVICE_INFO_CTX *serviceCtx)
|
||||
{
|
||||
INIT_CHECK(g_bootEventEnable != 0, return);
|
||||
BOOT_EVENT_PARAM_ITEM *item;
|
||||
for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) {
|
||||
ServiceExtData *extData = GetServiceExtData(serviceCtx->serviceName, i);
|
||||
if (extData == NULL) {
|
||||
return;
|
||||
}
|
||||
item = (BOOT_EVENT_PARAM_ITEM *)extData->data;
|
||||
if (serviceCtx->reserved != NULL) {
|
||||
((BOOT_EVENT_PARAM_ITEM *)extData->data)->pid = *((int *)serviceCtx->reserved);
|
||||
continue;
|
||||
item->pid = *((int *)serviceCtx->reserved);
|
||||
}
|
||||
INIT_CHECK_ONLY_RETURN(clock_gettime(CLOCK_MONOTONIC,
|
||||
&(((BOOT_EVENT_PARAM_ITEM *)extData->data)->timestamp[BOOTEVENT_FORK])) == 0);
|
||||
&(item->timestamp[BOOTEVENT_FORK])) == 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int GetBootEventEnable(void)
|
||||
{
|
||||
char bootEventOpen[6] = ""; // 6 is length of bool value
|
||||
uint32_t len = sizeof(bootEventOpen);
|
||||
SystemReadParam("persist.init.bootevent.enable", bootEventOpen, &len);
|
||||
if (strcmp(bootEventOpen, "true") == 0 || strcmp(bootEventOpen, "1") == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ListNode *GetBootEventList(void)
|
||||
@ -419,20 +445,54 @@ ListNode *GetBootEventList(void)
|
||||
return &bootEventList;
|
||||
}
|
||||
|
||||
static void AddCmdBootEvent(INIT_CMD_INFO *cmdCtx)
|
||||
{
|
||||
INIT_TIMING_STAT *timeStat = (INIT_TIMING_STAT *)cmdCtx->reserved;
|
||||
long long diff = InitDiffTime(timeStat);
|
||||
// If not time cost, just ignore
|
||||
if (diff < SAVEINITBOOTEVENTMSEC) {
|
||||
return;
|
||||
}
|
||||
BOOT_EVENT_PARAM_ITEM *item = calloc(1, sizeof(BOOT_EVENT_PARAM_ITEM));
|
||||
if (item == NULL) {
|
||||
return;
|
||||
}
|
||||
OH_ListInit(&item->node);
|
||||
item->timestamp[BOOTEVENT_FORK] = timeStat->startTime;
|
||||
item->timestamp[BOOTEVENT_READY] = timeStat->endTime;
|
||||
int cmdLen = strlen(cmdCtx->cmdName) + strlen(cmdCtx->cmdContent) + 1; // 2 args 1 '\0'
|
||||
item->paramName = calloc(1, cmdLen);
|
||||
if (item->paramName == NULL) {
|
||||
free(item);
|
||||
return;
|
||||
}
|
||||
INIT_CHECK_ONLY_ELOG(snprintf_s(item->paramName, cmdLen, cmdLen - 1, "%s%s",
|
||||
cmdCtx->cmdName, cmdCtx->cmdContent) >= 0,
|
||||
"combine cmd args failed");
|
||||
item->flags = BOOTEVENT_TYPE_CMD;
|
||||
OH_ListAddTail(&bootEventList, (ListNode *)&item->node);
|
||||
}
|
||||
|
||||
static int RecordInitCmd(const HOOK_INFO *info, void *cookie)
|
||||
{
|
||||
INIT_CMD_INFO *cmdCtx = (INIT_CMD_INFO *)cookie;
|
||||
const char *bootEventArgv[] = {"cmd", cmdCtx->cmdName, cmdCtx->cmdContent, cmdCtx->reserved};
|
||||
return DoBootEventCmd(0, NULL, ARRAY_LENGTH(bootEventArgv), bootEventArgv);
|
||||
if (cookie == NULL) {
|
||||
return 0;
|
||||
}
|
||||
AddCmdBootEvent((INIT_CMD_INFO *)cookie);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_CONSTRUCTOR(void)
|
||||
{
|
||||
// Add hook to record time-cost commands
|
||||
HOOK_INFO info = {INIT_CMD_RECORD, 0, RecordInitCmd, NULL};
|
||||
HookMgrAddEx(GetBootStageHookMgr(), &info);
|
||||
InitAddServiceHook(SetServiceBootEventFork, INIT_SERVICE_FORK_BEFORE);
|
||||
InitAddServiceHook(SetServiceBootEventFork, INIT_SERVICE_FORK_AFTER);
|
||||
InitAddClearServiceHook(ClearServiceBootEvent);
|
||||
|
||||
// Add hook to parse all services with bootevents
|
||||
InitAddServiceParseHook(ServiceParseBootEventHook);
|
||||
|
||||
// Add hook to record start time for services with bootevents
|
||||
InitAddServiceHook(SetServiceBootEventFork, INIT_SERVICE_FORK_AFTER);
|
||||
|
||||
InitAddGlobalInitHook(0, ParamSetBootEventHook);
|
||||
}
|
||||
|
3
services/modules/bootevent/bootevent.h
Normal file → Executable file
3
services/modules/bootevent/bootevent.h
Normal file → Executable file
@ -37,7 +37,7 @@ extern "C" {
|
||||
#define SECTONSEC 1000000000
|
||||
#define USTONSEC 1000
|
||||
#define SAVEINITBOOTEVENTMSEC 100000
|
||||
#define BOOTEVENT_OUTPUT_PATH "/data/service/el0/startup/init/"
|
||||
#define BOOTEVENT_OUTPUT_PATH "/data/log/startup/"
|
||||
|
||||
enum {
|
||||
BOOTEVENT_FORK,
|
||||
@ -53,7 +53,6 @@ typedef struct tagBOOT_EVENT_PARAM_ITEM {
|
||||
int flags;
|
||||
} BOOT_EVENT_PARAM_ITEM;
|
||||
|
||||
int GetBootEventEnable(void);
|
||||
ListNode *GetBootEventList(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -85,24 +85,6 @@ ServiceExtData *GetServiceExtData(const char *serviceName, uint32_t id)
|
||||
return GetServiceExtData_(service, id);
|
||||
}
|
||||
|
||||
static int ServiceClearHookWrapper(const HOOK_INFO *hookInfo, void *executionContext)
|
||||
{
|
||||
SERVICE_INFO_CTX *ctx = (SERVICE_INFO_CTX *)executionContext;
|
||||
ServiceHook realHook = (ServiceHook)hookInfo->hookCookie;
|
||||
realHook(ctx);
|
||||
return 0;
|
||||
};
|
||||
|
||||
int InitAddClearServiceHook(ServiceHook hook)
|
||||
{
|
||||
HOOK_INFO info;
|
||||
info.stage = INIT_SERVICE_CLEAR;
|
||||
info.prio = 0;
|
||||
info.hook = ServiceClearHookWrapper;
|
||||
info.hookCookie = (void *)hook;
|
||||
return HookMgrAddEx(GetBootStageHookMgr(), &info);
|
||||
}
|
||||
|
||||
static int JobParseHookWrapper(const HOOK_INFO *hookInfo, void *executionContext)
|
||||
{
|
||||
JOB_PARSE_CTX *jobParseContext = (JOB_PARSE_CTX *)executionContext;
|
||||
@ -122,27 +104,6 @@ int InitAddJobParseHook(JobParseHook hook)
|
||||
return HookMgrAddEx(GetBootStageHookMgr(), &info);
|
||||
}
|
||||
|
||||
static int CmdClear(int id, const char *name, int argc, const char **argv)
|
||||
{
|
||||
SERVICE_INFO_CTX ctx = {0};
|
||||
ctx.reserved = argc >= 1 ? argv[0] : NULL;
|
||||
PLUGIN_LOGI("CmdClear %s cmd: %s", name, ctx.reserved);
|
||||
|
||||
InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
|
||||
while (node != NULL) {
|
||||
if (node->data.service == NULL) {
|
||||
node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
|
||||
continue;
|
||||
}
|
||||
ctx.serviceName = node->name;
|
||||
HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_CLEAR, (void *)&ctx, NULL);
|
||||
node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
|
||||
}
|
||||
ctx.reserved = "clearInitBootevent";
|
||||
HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_CLEAR, (void *)&ctx, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SetLogLevelFunc(const char *value)
|
||||
{
|
||||
unsigned int level;
|
||||
@ -176,7 +137,6 @@ static int InitCmd(int id, const char *name, int argc, const char **argv)
|
||||
|
||||
static int ParamSetInitCmdHook(const HOOK_INFO *hookInfo, void *cookie)
|
||||
{
|
||||
AddCmdExecutor("clear", CmdClear);
|
||||
AddCmdExecutor("setloglevel", CmdSetLogLevel);
|
||||
AddCmdExecutor("initcmd", InitCmd);
|
||||
return 0;
|
||||
@ -256,9 +216,3 @@ MODULE_CONSTRUCTOR(void)
|
||||
// Depends on parameter service
|
||||
InitAddPostPersistParamLoadHook(0, InitDebugHook);
|
||||
}
|
||||
|
||||
MODULE_DESTRUCTOR(void)
|
||||
{
|
||||
const char *clearBootEventArgv[] = {"bootevent"};
|
||||
PluginExecCmd("clear", ARRAY_LENGTH(clearBootEventArgv), clearBootEventArgv);
|
||||
}
|
||||
|
@ -63,7 +63,6 @@ const ParamCmdInfo *GetServiceCtl(size_t *size)
|
||||
static const ParamCmdInfo installParam[] = {
|
||||
{"ohos.servicectrl.install", "install", "install" },
|
||||
{"ohos.servicectrl.uninstall", "uninstall", "uninstall" },
|
||||
{"ohos.servicectrl.clear", "clear", "clear" },
|
||||
{"ohos.servicectrl.bootchart", "bootchart", "bootchart" },
|
||||
{"ohos.servicectrl.init_trace", "init_trace", "init_trace" },
|
||||
{"ohos.servicectrl.timer_start", "timer_start", "timer_start " },
|
||||
|
@ -52,12 +52,3 @@ ohos_prebuilt_etc("inittrace_cfg") {
|
||||
part_name = "init"
|
||||
subsystem_name = "startup"
|
||||
}
|
||||
|
||||
ohos_source_set("libinittrace_static") {
|
||||
sources = [ "init_trace_static.c" ]
|
||||
include_dirs = comm_include
|
||||
public_configs = [ ":inittrace_static_config" ]
|
||||
public_configs += [ "../../../interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ]
|
||||
part_name = "init"
|
||||
subsystem_name = "startup"
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "init_module_engine.h"
|
||||
#include "bootevent.h"
|
||||
#include "plugin_adapter.h"
|
||||
|
||||
static int InitTraceEarlyHook(const HOOK_INFO *info, void *cookie)
|
||||
{
|
||||
if (GetBootEventEnable()) {
|
||||
PLUGIN_LOGI("init trace enabled.");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_CONSTRUCTOR(void)
|
||||
{
|
||||
// Depends on parameter service
|
||||
InitAddPostPersistParamLoadHook(0, InitTraceEarlyHook);
|
||||
}
|
@ -26,6 +26,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "init_log.h"
|
||||
#include "securec.h"
|
||||
@ -734,3 +735,19 @@ int StrArrayGetIndex(const char *strArray[], const char *target, int ignoreCase)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
long long GetUptimeInMicroSeconds(const struct timespec *uptime)
|
||||
{
|
||||
struct timespec now;
|
||||
|
||||
if (uptime == NULL) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
uptime = &now;
|
||||
}
|
||||
|
||||
#define SECOND_TO_MICRO_SECOND (1000000)
|
||||
#define MICRO_SECOND_TO_NANOSECOND (1000)
|
||||
|
||||
return (long long)((uptime->tv_sec * SECOND_TO_MICRO_SECOND) +
|
||||
(uptime->tv_nsec / MICRO_SECOND_TO_NANOSECOND));
|
||||
}
|
||||
|
@ -386,7 +386,6 @@ ohos_unittest("init_unittest") {
|
||||
|
||||
sources += [
|
||||
"//base/startup/init/services/modules/trace/init_trace.c",
|
||||
"//base/startup/init/services/modules/trace/init_trace_static.c",
|
||||
"//base/startup/init/test/unittest/modules/trace_unittest.cpp",
|
||||
]
|
||||
|
||||
|
@ -319,7 +319,6 @@ HWTEST_F(ServiceUnitTest, TestServiceBootEventHook, TestSize.Level1)
|
||||
(void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&serviceInfoContext), nullptr);
|
||||
cJSON *fileRoot = cJSON_Parse(serviceStr);
|
||||
ASSERT_NE(nullptr, fileRoot);
|
||||
PluginExecCmd("clear", 0, nullptr);
|
||||
ConfigContext context = { INIT_CONTEXT_MAIN };
|
||||
ParseAllServices(fileRoot, &context);
|
||||
(void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_FORK_BEFORE, (void *)(&serviceInfoContext), nullptr);
|
||||
|
@ -305,6 +305,5 @@ HWTEST_F(HookMgrUnitTest, HookMgrExecuteInit_unitest, TestSize.Level1)
|
||||
{
|
||||
HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
|
||||
HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, nullptr, nullptr);
|
||||
InitAddClearServiceHook([](SERVICE_INFO_CTX *serviceCtx) {return;});
|
||||
}
|
||||
} // namespace init_ut
|
||||
|
@ -596,12 +596,12 @@ static __attribute__((constructor(101))) void ParamTestStubInit(void)
|
||||
#ifndef OHOS_LITE
|
||||
TestBeforeInit();
|
||||
#endif
|
||||
SystemPrepare();
|
||||
SystemPrepare(0);
|
||||
#ifndef __LITEOS_A__
|
||||
SystemInit();
|
||||
#endif
|
||||
PARAM_LOGI("SystemConfig \n");
|
||||
SystemConfig();
|
||||
SystemConfig(NULL);
|
||||
PrepareInitUnitTestEnv();
|
||||
}
|
||||
|
||||
@ -616,8 +616,6 @@ __attribute__((destructor)) static void ParamTestStubExit(void)
|
||||
|
||||
HookMgrExecute(GetBootStageHookMgr(), INIT_BOOT_COMPLETE, nullptr, nullptr);
|
||||
CloseUeventConfig();
|
||||
const char *clearBootEventArgv[] = {"bootevent"};
|
||||
PluginExecCmd("clear", ARRAY_LENGTH(clearBootEventArgv), clearBootEventArgv);
|
||||
CloseServiceSpace();
|
||||
demoExit();
|
||||
LE_CloseLoop(LE_GetDefaultLoop());
|
||||
|
Loading…
x
Reference in New Issue
Block a user