From 57a0bc9c058d5e9e6e9e5ada46946fa9a8756f05 Mon Sep 17 00:00:00 2001 From: handyohos Date: Sun, 24 Sep 2023 19:41:28 +0800 Subject: [PATCH] Bugfix: Add idle task api for loop event 1) Add idle task list API 2) Call all idle task functions for each loop 3) Call idle task for AutorunModuleMgrUnInstall to make sure it will succeed for plugin to uninstall itself Signed-off-by: handyohos Change-Id: If43f03a2934a5acda779269402a419d7d693973f #I83XRH --- .../innerkits/init_module_engine/BUILD.gn | 1 + .../init_module_engine/init_modulemgr.c | 12 +- .../init_module_engine/stub/libinit.stub.json | 3 + .../innerkits/libbegetutil.versionscript | 3 + services/loopevent/BUILD.gn | 2 + services/loopevent/idle/le_idle.c | 114 ++++++++++++++++++ services/loopevent/idle/le_idle.h | 50 ++++++++ services/loopevent/include/loop_event.h | 47 ++++++++ services/loopevent/loop/le_epoll.c | 3 + services/loopevent/loop/le_loop.c | 2 + services/loopevent/loop/le_loop.h | 3 + test/unittest/BUILD.gn | 3 +- 12 files changed, 241 insertions(+), 2 deletions(-) create mode 100755 services/loopevent/idle/le_idle.c create mode 100755 services/loopevent/idle/le_idle.h diff --git a/interfaces/innerkits/init_module_engine/BUILD.gn b/interfaces/innerkits/init_module_engine/BUILD.gn index 04c560bee..4a3f257a7 100644 --- a/interfaces/innerkits/init_module_engine/BUILD.gn +++ b/interfaces/innerkits/init_module_engine/BUILD.gn @@ -74,6 +74,7 @@ if (defined(ohos_lite)) { "//base/startup/init/interfaces/innerkits/init_module_engine/include", "//base/startup/init/interfaces/innerkits/include", "//base/startup/init/services/include", + "//base/startup/init/services/loopevent/include", "//base/startup/init/services/log", "//third_party/cJSON", ] diff --git a/interfaces/innerkits/init_module_engine/init_modulemgr.c b/interfaces/innerkits/init_module_engine/init_modulemgr.c index 00e25239c..0f5289b7f 100644 --- a/interfaces/innerkits/init_module_engine/init_modulemgr.c +++ b/interfaces/innerkits/init_module_engine/init_modulemgr.c @@ -15,6 +15,7 @@ #include #include "init_log.h" #include "init_module_engine.h" +#include "loop_event.h" static MODULE_MGR *defaultModuleMgr = NULL; static MODULE_MGR *autorunModuleMgr = NULL; @@ -40,11 +41,20 @@ void InitModuleMgrUnInstall(const char *moduleName) ModuleMgrUninstall(defaultModuleMgr, moduleName); } -void AutorunModuleMgrUnInstall(const char *moduleName) +static void DelayedUninstall(const IdleHandle taskHandle, void *context) { + const char *moduleName = (const char *)context; + if (moduleName == NULL) { + return; + } ModuleMgrUninstall(autorunModuleMgr, moduleName); } +void AutorunModuleMgrUnInstall(const char *moduleName) +{ + LE_DelayProc(LE_GetDefaultLoop(), DelayedUninstall, (void *)strdup(moduleName)); +} + static void InitModuleDump(const MODULE_INFO *moduleInfo) { printf("%s\n", moduleInfo->name); diff --git a/interfaces/innerkits/init_module_engine/stub/libinit.stub.json b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json index de34c46e4..28a4c02a3 100644 --- a/interfaces/innerkits/init_module_engine/stub/libinit.stub.json +++ b/interfaces/innerkits/init_module_engine/stub/libinit.stub.json @@ -57,6 +57,9 @@ { "name": "LE_StopAsyncTask" }, { "name": "LE_StopLoop" }, { "name": "LE_StopTimer" }, + { "name": "LE_AddIdle" }, + { "name": "LE_DelIdle" }, + { "name": "LE_DelayProc" }, { "name": "OH_ListAddTail" }, { "name": "OH_ListInit" }, { "name": "OH_ListRemove" }, diff --git a/interfaces/innerkits/libbegetutil.versionscript b/interfaces/innerkits/libbegetutil.versionscript index d29cc76d6..0806824c9 100644 --- a/interfaces/innerkits/libbegetutil.versionscript +++ b/interfaces/innerkits/libbegetutil.versionscript @@ -87,6 +87,9 @@ LE_StopAsyncTask; LE_StopLoop; LE_StopTimer; + LE_AddIdle; + LE_DelIdle; + LE_DelayProc; ModuleMgrCreate; ModuleMgrDestroy; ModuleMgrGetArgs; diff --git a/services/loopevent/BUILD.gn b/services/loopevent/BUILD.gn index 8ad82da8f..ef610513c 100644 --- a/services/loopevent/BUILD.gn +++ b/services/loopevent/BUILD.gn @@ -12,6 +12,7 @@ # limitations under the License. common_sources = [ + "idle/le_idle.c", "loop/le_epoll.c", "loop/le_loop.c", "signal/le_signal.c", @@ -36,6 +37,7 @@ common_include = [ "timer", "utils", "signal", + "idle", ] config("exported_header_files") { diff --git a/services/loopevent/idle/le_idle.c b/services/loopevent/idle/le_idle.c new file mode 100755 index 000000000..b230bb2eb --- /dev/null +++ b/services/loopevent/idle/le_idle.c @@ -0,0 +1,114 @@ +/* + * 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 "le_idle.h" + +#include +#include +#include + +#include "le_loop.h" +#include "le_task.h" +#include "loop_event.h" + +/** + * @brief Add a new idle handler + * + * @param loopHandle the running loop this idle will be attached + * @param idle optional output parameter for the created idle handler + * @param processIdle the idle handler function + * @param context optional idle handler context + * @param repeat if the idle function will be repeated forevent (non zero) or once (zero) + * @return status code, 0 means succeed + */ +LE_STATUS LE_AddIdle(const LoopHandle loopHandle, IdleHandle *idle, + LE_ProcessIdle processIdle, void *context, int repeat) +{ + LE_CHECK(loopHandle != NULL && processIdle != NULL, return LE_INVALID_PARAM, "Invalid parameters"); + IdleTask *task = (IdleTask *)calloc(1, sizeof(IdleTask)); + LE_CHECK(task != NULL, + return LE_NO_MEMORY, "Failed to create task"); + + task->loop = (EventLoop *)loopHandle; + task->processIdle = processIdle; + task->context = context; + task->repeat = repeat; + if (idle != NULL) { + *idle = (IdleHandle)task; + } + + // Add to list + OH_ListAddTail(&(task->loop->idleList), &(task->node)); + return LE_SUCCESS; +} + +/** + * @brief Delete an idle handler + * + * @param idle idle handler + * @return None + */ +void LE_DelIdle(IdleHandle idle) +{ + LE_CHECK(idle != NULL, return, "Invalid parameters"); + IdleTask *task = (IdleTask *)idle; + OH_ListRemove(&(task->node)); + free((void *)task); +} + +/** + * @brief Execute an function once in the next loop + * + * @param loopHandle the running loop this idle will be attached + * @param idle the function to be executed + * @param context optional idle handler context + * @return status code, 0 means succeed + */ +int LE_DelayProc(const LoopHandle loopHandle, LE_ProcessIdle idle, void *context) +{ + return LE_AddIdle(loopHandle, NULL, idle, context, 0); +} + +static int IdleListTraversalProc(ListNode *node, void *data) +{ + IdleTask *task = (IdleTask *)node; + + // Do idle proc + task->processIdle(task, task->context); + + if (task->repeat) { + return 0; + } + + // Remove if no need to repeat + LE_DelIdle((IdleHandle)task); + return 0; +} + +/** + * @brief Execute all idle functions + * + * @param loopHandle the running loop + * @return None + */ +void LE_RunIdle(const LoopHandle loopHandle) +{ + if (loopHandle == NULL) { + return; + } + EventLoop *loop = (EventLoop *)loopHandle; + + OH_ListTraversal(&(loop->idleList), NULL, IdleListTraversalProc, 0); +} diff --git a/services/loopevent/idle/le_idle.h b/services/loopevent/idle/le_idle.h new file mode 100755 index 000000000..99a1442de --- /dev/null +++ b/services/loopevent/idle/le_idle.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#ifndef LOOP_IDLE_H +#define LOOP_IDLE_H +#include "le_task.h" +#include "le_loop.h" +#include "loop_event.h" + +/** + * @brief Idle Task Structure + */ +typedef struct { + /* List Node */ + ListNode node; + + /* The loop handler this idle task belongs to */ + EventLoop *loop; + + /* The actual function to be executed */ + LE_ProcessIdle processIdle; + + /* The function context pointer */ + void *context; + + /* This task will be repeat forever or just once */ + int repeat; +} IdleTask; + +/** + * @brief Execute all idle functions + * + * @param loopHandle the running loop + * @return None + */ +void LE_RunIdle(const LoopHandle loopHandle); + +#endif diff --git a/services/loopevent/include/loop_event.h b/services/loopevent/include/loop_event.h index 217a57ee4..47812d1d7 100644 --- a/services/loopevent/include/loop_event.h +++ b/services/loopevent/include/loop_event.h @@ -184,6 +184,53 @@ LE_STATUS LE_StartWatcher(const LoopHandle loopHandle, WatcherHandle *watcherHandle, const LE_WatchInfo *info, const void *context); void LE_RemoveWatcher(const LoopHandle loopHandle, const WatcherHandle watcherHandle); +/** + * Idle Processing:Idle handlers will be called for every loop + */ + +/* Idle Handler */ +typedef void *IdleHandle; + +/** + * @brief Idle process function prototype + * + * @param taskHandle idle handler + * @param context idle function context + * @return None + */ +typedef void (*LE_ProcessIdle)(const IdleHandle taskHandle, void *context); + +/** + * @brief Add a new idle handler + * + * @param loopHandle the running loop this idle will be attached + * @param idle optional output parameter for the created idle handler + * @param processIdle the idle handler function + * @param context optional idle handler context + * @param repeat if the idle function will be repeated forevent (non zero) or once (zero) + * @return status code, 0 means succeed + */ +LE_STATUS LE_AddIdle(const LoopHandle loopHandle, IdleHandle *idle, + LE_ProcessIdle processIdle, void *context, int repeat); + +/** + * @brief Delete an idle handler + * + * @param idle idle handler + * @return None + */ +void LE_DelIdle(IdleHandle idle); + +/** + * @brief Execute an function once in the next loop + * + * @param loopHandle the running loop this idle will be attached + * @param idle the function to be executed + * @param context optional idle handler context + * @return status code, 0 means succeed + */ +int LE_DelayProc(const LoopHandle loopHandle, LE_ProcessIdle idle, void *context); + #ifdef __cplusplus #if __cplusplus } diff --git a/services/loopevent/loop/le_epoll.c b/services/loopevent/loop/le_epoll.c index 947695e3a..31413c16e 100644 --- a/services/loopevent/loop/le_epoll.c +++ b/services/loopevent/loop/le_epoll.c @@ -16,6 +16,7 @@ #include #include "le_epoll.h" +#include "le_idle.h" static int IsValid_(const EventEpoll *loop) { @@ -96,6 +97,8 @@ static LE_STATUS RunLoop_(const EventLoop *loop) return LE_FAILURE; } while (1) { + LE_RunIdle((LoopHandle)&(epoll->loop)); + int number = epoll_wait(epoll->epollFd, epoll->waitEvents, loop->maxevents, -1); for (int index = 0; index < number; index++) { if ((epoll->waitEvents[index].events & EPOLLIN) == EPOLLIN) { diff --git a/services/loopevent/loop/le_loop.c b/services/loopevent/loop/le_loop.c index 6b375eeb7..86b00a7e7 100644 --- a/services/loopevent/loop/le_loop.c +++ b/services/loopevent/loop/le_loop.c @@ -61,6 +61,8 @@ static LE_STATUS CreateLoop_(EventLoop **loop, uint32_t maxevents, uint32_t time (*loop)->stop = 0; LoopMutexInit(&(*loop)->mutex); + OH_ListInit(&((*loop)->idleList)); + HashInfo info = { TaskNodeCompare, TaskKeyCompare, diff --git a/services/loopevent/loop/le_loop.h b/services/loopevent/loop/le_loop.h index 80dd85502..c2a905ec2 100644 --- a/services/loopevent/loop/le_loop.h +++ b/services/loopevent/loop/le_loop.h @@ -19,6 +19,7 @@ #include "le_task.h" #include "le_utils.h" +#include "list.h" #include "init_hashmap.h" #ifdef __cplusplus @@ -43,6 +44,8 @@ typedef struct EventLoop_ { char mutex; #endif HashMapHandle taskMap; + + ListNode idleList; } EventLoop; LE_STATUS CloseLoop(EventLoop *loop); diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 62846ded7..283101984 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -91,6 +91,7 @@ ohos_unittest("init_unittest") { "//base/startup/init/services/init/standard/init_signal_handler.c", "//base/startup/init/services/log/init_commlog.c", "//base/startup/init/services/log/init_log.c", + "//base/startup/init/services/loopevent/idle/le_idle.c", "//base/startup/init/services/loopevent/loop/le_epoll.c", "//base/startup/init/services/loopevent/loop/le_loop.c", "//base/startup/init/services/loopevent/signal/le_signal.c", @@ -234,6 +235,7 @@ ohos_unittest("init_unittest") { "//base/startup/init/services/loopevent/task", "//base/startup/init/services/loopevent/timer", "//base/startup/init/services/loopevent/utils", + "//base/startup/init/services/loopevent/idle", "//base/startup/init/services/modules", "//base/startup/init/services/modules/bootchart", "//base/startup/init/services/modules/init_hook", @@ -241,7 +243,6 @@ ohos_unittest("init_unittest") { "//base/startup/init/services/modules/reboot", "//base/startup/init/services/modules/udid", "//base/startup/init/services/modules/init_eng", - "//base/startup/init/services/loopevent/utils", "//base/startup/init/services/param/adapter", "//base/startup/init/services/param/base", "//base/startup/init/services/param/linux", -- Gitee