diff --git a/interfaces/innerkits/init_module_engine/BUILD.gn b/interfaces/innerkits/init_module_engine/BUILD.gn index 04c560beed46e44084db692d27911b51685a910f..4a3f257a7833c7b008c76fd7f329bbc738463361 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 00e25239cf1f161542210fbdb187599723f55947..0f5289b7f5aef23b679a12bb15659b82860074b1 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 de34c46e4ee59458735ec377bb55dac1abdcbb66..28a4c02a3089c838562563b9a74b9cb21d2cbd2b 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 d29cc76d65cb60063f3b72f283037a54466578dc..0806824c902ddedf89d3ff7bce8da2f2b887f7e6 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 8ad82da8f856a3b93c6f523dabcaf2dd788ca987..ef610513c494076b31d959546985dfe88bfae7a5 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 0000000000000000000000000000000000000000..b230bb2ebc799f4eea5deb12aeeb80527a918c78 --- /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 0000000000000000000000000000000000000000..99a1442de6e608b0d6b20da53824f83e1ffa414f --- /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 217a57ee4a63ec5f63431a6efd595689aedb3a4f..47812d1d760b54b4bda5f07504ef74c3e159c52f 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 947695e3a75f4fef6766046dd86f4024f2d97366..31413c16ede46ecd151b4c61bd5e6c3ba276f371 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 6b375eeb7b2b9c921d5b626303bd75486eef0bb8..86b00a7e76d11c4e62f1b12bae50009930856479 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 80dd85502ef3b562303b736976cf1fd22bfd40f6..c2a905ec20f537514702f742726f43e0a538d746 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 62846ded7043e94fb422c819c8628dff2cdec7ed..28310198417f3ac9ca1f031aeaad95aac7f1908b 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",