From b5ac43a7083b7eab1a27469dcb50de45bdca155b Mon Sep 17 00:00:00 2001 From: handyohos Date: Tue, 5 Sep 2023 17:56:10 +0800 Subject: [PATCH] =?UTF-8?q?Bugfix:=20=E4=BC=98=E5=8C=96bootevent=E5=BA=A6?= =?UTF-8?q?=E9=87=8F=E5=BC=80=E6=9C=BA=E5=90=AF=E5=8A=A8=E8=80=97=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Change-Id: I7cdc269fe1a0eb8e4394de010f1f71e6c16b5a6c #I7XYNX --- .../init_module_engine/include/bootstage.h | 2 - services/etc/param/ohos.para.size | 2 +- services/include/init_utils.h | 3 + services/init/include/init.h | 4 +- services/init/lite/init.c | 4 +- services/init/main.c | 14 +- services/init/standard/init.c | 28 +- services/modules/BUILD.gn | 5 +- services/modules/bootevent/BUILD.gn | 1 + services/modules/bootevent/bootevent.c | 314 +++++++++++------- services/modules/bootevent/bootevent.h | 3 +- services/modules/init_hook/init_hook.c | 46 --- services/modules/init_hook/param_hook.c | 1 - services/modules/trace/BUILD.gn | 9 - services/modules/trace/init_trace_static.c | 33 -- services/utils/init_utils.c | 17 + test/unittest/BUILD.gn | 1 - test/unittest/init/service_unittest.cpp | 1 - test/unittest/innerkits/hookmgr_unittest.cpp | 1 - test/unittest/param/param_stub.cpp | 6 +- 20 files changed, 252 insertions(+), 243 deletions(-) mode change 100644 => 100755 services/modules/bootevent/bootevent.h delete mode 100644 services/modules/trace/init_trace_static.c diff --git a/interfaces/innerkits/init_module_engine/include/bootstage.h b/interfaces/innerkits/init_module_engine/include/bootstage.h index d23debdc8..76004a2d6 100755 --- a/interfaces/innerkits/init_module_engine/include/bootstage.h +++ b/interfaces/innerkits/init_module_engine/include/bootstage.h @@ -222,8 +222,6 @@ int InitAddJobParseHook(JobParseHook hook); */ int InitAddServiceHook(ServiceHook hook, int hookState); -int InitAddClearServiceHook(ServiceHook hook); - #ifdef __cplusplus #if __cplusplus } diff --git a/services/etc/param/ohos.para.size b/services/etc/param/ohos.para.size index 441dd7915..23116936f 100755 --- a/services/etc/param/ohos.para.size +++ b/services/etc/param/ohos.para.size @@ -23,4 +23,4 @@ sys_param=4096 bootevent_param=4096 startup_init_param=40960 hiviewdfx_profiler_param=2048 -ohos_boot_param = 4096 \ No newline at end of file +ohos_boot_param = 8192 \ No newline at end of file diff --git a/services/include/init_utils.h b/services/include/init_utils.h index 0c8cdc772..842364071 100644 --- a/services/include/init_utils.h +++ b/services/include/init_utils.h @@ -20,6 +20,7 @@ #include #include #include +#include #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 } diff --git a/services/init/include/init.h b/services/init/include/init.h index 2268363cb..b856a2f78 100644 --- a/services/init/include/init.h +++ b/services/init/include/init.h @@ -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); diff --git a/services/init/lite/init.c b/services/init/lite/init.c index cc285a010..26b37a849 100644 --- a/services/init/lite/init.c +++ b/services/init/lite/init.c @@ -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 diff --git a/services/init/main.c b/services/init/main.c index 9cba41e4d..a59447075 100644 --- a/services/init/main.c +++ b/services/init/main.c @@ -15,16 +15,24 @@ #include #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; } diff --git a/services/init/standard/init.c b/services/init/standard/init.c index cc1020d0d..6b1af4012 100755 --- a/services/init/standard/init.c +++ b/services/init/standard/init.c @@ -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(); } diff --git a/services/modules/BUILD.gn b/services/modules/BUILD.gn index e60cdcb94..a608033af 100755 --- a/services/modules/BUILD.gn +++ b/services/modules/BUILD.gn @@ -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" ] } } diff --git a/services/modules/bootevent/BUILD.gn b/services/modules/bootevent/BUILD.gn index 3d76368d3..1532f8b50 100755 --- a/services/modules/bootevent/BUILD.gn +++ b/services/modules/bootevent/BUILD.gn @@ -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", ] } diff --git a/services/modules/bootevent/bootevent.c b/services/modules/bootevent/bootevent.c index aec8bb336..ba0e74108 100755 --- a/services/modules/bootevent/bootevent.c +++ b/services/modules/bootevent/bootevent.c @@ -16,6 +16,7 @@ #include #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); + WriteBooteventSysParam(paramName); + + found = (BOOT_EVENT_PARAM_ITEM *)OH_ListFind(&bootEventList, (void *)paramName, BootEventParaListCompareProc); if (found == NULL) { - return; + return 0; } - int ret = ((BOOT_EVENT_PARAM_ITEM *)found)->timestamp[BOOTEVENT_READY].tv_sec; - INIT_CHECK(ret == 0, return); - INIT_CHECK_ONLY_RETURN(clock_gettime(CLOCK_MONOTONIC, - &(((BOOT_EVENT_PARAM_ITEM *)found)->timestamp[BOOTEVENT_READY])) == 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); + 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,96 +374,125 @@ 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); + char buf[MAX_PATH_LEN]; + + FILE *file = fopen(name, "r"); + if (file == NULL) { + return; } - return 0; -} -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--; + while (fgets((void *)buf, sizeof(buf) - 1, file)) { + buf[sizeof(buf) - 1] = '\0'; + char *end = strchr(buf, '\r'); + if (end != NULL) { + *end = '\0'; } - // clear service extra data first - return; + end = strchr(buf, '\n'); + if (end != NULL) { + *end = '\0'; + } + INIT_LOGI("Got priv-app bootevent: %s", buf); + AddBootEventItemByName(buf); } - if (strcmp(serviceCtx->reserved, "clearInitBootevent") == 0) { - // clear init boot event - OH_ListRemoveAll(&bootEventList, BootEventDestroy); - g_bootEventNum = 0; + 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]); + } } - return; + 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) +ListNode *GetBootEventList(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; + return &bootEventList; } -ListNode *GetBootEventList(void) +static void AddCmdBootEvent(INIT_CMD_INFO *cmdCtx) { - return &bootEventList; + 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); } diff --git a/services/modules/bootevent/bootevent.h b/services/modules/bootevent/bootevent.h old mode 100644 new mode 100755 index 922116cc0..9bce4b7d7 --- a/services/modules/bootevent/bootevent.h +++ b/services/modules/bootevent/bootevent.h @@ -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 diff --git a/services/modules/init_hook/init_hook.c b/services/modules/init_hook/init_hook.c index cb8ce5527..abf351307 100755 --- a/services/modules/init_hook/init_hook.c +++ b/services/modules/init_hook/init_hook.c @@ -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); -} diff --git a/services/modules/init_hook/param_hook.c b/services/modules/init_hook/param_hook.c index 5587ee460..dc0e8741d 100755 --- a/services/modules/init_hook/param_hook.c +++ b/services/modules/init_hook/param_hook.c @@ -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 " }, diff --git a/services/modules/trace/BUILD.gn b/services/modules/trace/BUILD.gn index a2fd85441..8e3520303 100644 --- a/services/modules/trace/BUILD.gn +++ b/services/modules/trace/BUILD.gn @@ -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" -} diff --git a/services/modules/trace/init_trace_static.c b/services/modules/trace/init_trace_static.c deleted file mode 100644 index f21a0bbb9..000000000 --- a/services/modules/trace/init_trace_static.c +++ /dev/null @@ -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 -#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); -} diff --git a/services/utils/init_utils.c b/services/utils/init_utils.c index 65ec75c53..678d5931f 100644 --- a/services/utils/init_utils.c +++ b/services/utils/init_utils.c @@ -26,6 +26,7 @@ #include #include #include +#include #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)); +} diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index e0fc34574..62846ded7 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -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", ] diff --git a/test/unittest/init/service_unittest.cpp b/test/unittest/init/service_unittest.cpp index df519b3a6..0dffdb67e 100644 --- a/test/unittest/init/service_unittest.cpp +++ b/test/unittest/init/service_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); diff --git a/test/unittest/innerkits/hookmgr_unittest.cpp b/test/unittest/innerkits/hookmgr_unittest.cpp index c3146fb94..03d091770 100755 --- a/test/unittest/innerkits/hookmgr_unittest.cpp +++ b/test/unittest/innerkits/hookmgr_unittest.cpp @@ -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 diff --git a/test/unittest/param/param_stub.cpp b/test/unittest/param/param_stub.cpp index a2679c132..3340e1d3a 100644 --- a/test/unittest/param/param_stub.cpp +++ b/test/unittest/param/param_stub.cpp @@ -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()); -- Gitee