diff options
Diffstat (limited to 'systemservice/task_manager/server/src')
-rw-r--r-- | systemservice/task_manager/server/src/pri_main.cpp | 840 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_api.cpp | 268 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_comm.cpp | 402 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_debug.cpp | 286 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_main.cpp | 727 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_port_pf.cpp | 884 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_port_subsys.cpp | 297 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_shutdown.cpp | 242 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_state.cpp | 452 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_svc.cpp | 970 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_wakeup.cpp | 201 | ||||
-rw-r--r-- | systemservice/task_manager/server/src/tskm_watch.cpp | 101 |
12 files changed, 5670 insertions, 0 deletions
diff --git a/systemservice/task_manager/server/src/pri_main.cpp b/systemservice/task_manager/server/src/pri_main.cpp new file mode 100644 index 00000000..2c87623b --- /dev/null +++ b/systemservice/task_manager/server/src/pri_main.cpp @@ -0,0 +1,840 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "pri_main.h" +#include <string.h> +#include <errno.h> +#include <pthread.h> +#include <sys/eventfd.h> +#include <stdlib.h> +#include <native_service/frameworkunified_dispatcher.h> +#include <system_service/ss_system_if.h> + +#include "tskm_debug.h" +#include "tskm_comm.h" +#include "tskm_port_pf.h" +#include "tskm_port_subsys.h" +#include "tskm_util.h" + + + +#define PRI_PROC_NAME_MAX 32 + +// Context +typedef struct { + T_PRIM_PRM prm; + + TSKM_SVCID_t svcId; // Set valid value by REQ_WAKEUP + char procName[PRI_PROC_NAME_MAX]; + // State + TSKM_BOOL_t isExec; + T_SS_SM_START_DataStructType bootInfo; + T_SS_SM_START_ExtDataStructType extBootInfo; TSKM_BOOL_t isDynamic; + uint32_t wakeupStepDone; // Executed local step + TSKM_BOOL_t shmDone; + uint32_t downStepDone; // Executed local step + TSKM_BOOL_t isExitStart; + +#define PRI_MONITOR_DEFAULT_TIMEOUT 50 + uint32_t timeout; // Service monitoring timeout period (valid only for the INI_Main type service) + + // Resources + int connFd; // TSKM communication socket + int nsFd; // NSFW socket + int pipeFd[2]; // for exitDone + HANDLE hApp; // appHandle +} PRI_CTX_t; + +static PRI_CTX_t g_pri; + +/********************************************* + * Create shared memory + *********************************************/ +TSKM_STATIC void shmMake(PRI_CTX_t* p_ctx) { + const PRIM_SHAREDATA_TBL* shmEntry; + for (shmEntry = p_ctx->prm.shmTbl; shmEntry->shmName[0] != '\0'; shmEntry++) { + int ret; + ret = tskm_pf_shmCreate(shmEntry->shmName, shmEntry->size, NULL); + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded + } + } + p_ctx->shmDone = TSKM_TRUE; + return; + + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + tskm_pf_abort(); + // LCOV_EXCL_STOP +} + +/********************************************* + * Call backup check CB + *********************************************/ +TSKM_STATIC uint32_t wakeupExFuncCallback(PRI_CTX_t* p_ctx, + TSKM_EV_PRI_REQ_WAKEUP_PRM_t* p_prm) { + const PRIM_EXFUNC_TBL* funcEntry; + uint32_t maxStep = 0; + + for (funcEntry = p_ctx->prm.wakeupExFuncTbl; funcEntry->localStep != 0; + funcEntry++) { + if (funcEntry->localStep == p_prm->localStep) { + funcEntry->func(funcEntry->prm); + } + maxStep = TSKM_MAX(maxStep, funcEntry->localStep); + } + return maxStep; +} + +/********************************************* + * Gradual startup request + *********************************************/ +TSKM_STATIC void wakeupRequest(PRI_CTX_t* p_ctx, + TSKM_EV_PRI_REQ_WAKEUP_PRM_t* p_prm) { + TSKM_EV_PRI_REQ_WAKEUP_PRM_t prm = *p_prm; + uint32_t max = 0; + + // Execute step by step + for (prm.localStep = p_ctx->wakeupStepDone + 1; + (prm.localStep <= p_prm->localStep && prm.localStep < PRIM_STEPFORK_MAX); + prm.localStep++) { + max = wakeupExFuncCallback(p_ctx, &prm); + } + + if (max <= p_prm->localStep) { + // Completed gradual startup + p_ctx->wakeupStepDone = PRIM_STEPFORK_MAX; + } else { + p_ctx->wakeupStepDone = p_prm->localStep; + } +} + +/********************************************* + * All startup requests + *********************************************/ +TSKM_STATIC void allWakeup(PRI_CTX_t* p_ctx, + TSKM_EV_PRI_REQ_WAKEUP_PRM_t* p_prm) { + if (!p_ctx->shmDone) { + shmMake(p_ctx); + } + + if (p_ctx->wakeupStepDone < PRIM_STEPFORK_MAX) { + wakeupRequest(p_ctx, p_prm); + } +} + +/********************************************* + * Startup request handles + *********************************************/ +TSKM_STATIC void wakeupRequestHandle(PRI_CTX_t* p_ctx, + TSKM_EV_PRI_REQ_WAKEUP_PRM_t* p_prm) { + TSKM_EVENT_INFO_t ev; + int ret; + + bzero(&ev, sizeof(ev)); + + p_ctx->svcId = p_prm->svcId; + memcpy(&p_ctx->bootInfo, &p_prm->bootInfo, sizeof(p_ctx->bootInfo)); + memcpy(&p_ctx->extBootInfo, &p_prm->extBootInfo, sizeof(p_ctx->extBootInfo)); + p_ctx->isDynamic = p_prm->isDynamic; + + if (p_prm->localStep == TSKM_LSTEP_ALL) { + allWakeup(p_ctx, p_prm); + } else if (p_prm->localStep == TSKM_LSTEP_LAST) { + wakeupRequest(p_ctx, p_prm); + } else if (p_prm->localStep == TSKM_LSTEP_SHM) { + shmMake(p_ctx); + } else { + wakeupRequest(p_ctx, p_prm); + } + + ev.prm.resWakeup.isShmDone = p_ctx->shmDone; + ev.prm.resWakeup.isStepDone = + (p_ctx->wakeupStepDone >= PRIM_STEPFORK_MAX) ? + TSKM_TRUE : + TSKM_FALSE; + + // LCOV_EXCL_BR_START 6: Because it depends on the test order + if (ev.prm.resWakeup.isShmDone && ev.prm.resWakeup.isStepDone) { + // LCOV_EXCL_BR_STOP + ev.prm.resWakeup.isLast = TSKM_TRUE; + } + + ev.event = TSKM_EV_PRI_RES_WAKEUP; + ev.errCode = TSKM_E_OK; + ret = tskm_sockSend(p_ctx->connFd, &ev); + if (ret <= 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + tskm_pf_abort(); + // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded + } +} + +/********************************************* + * Gradual termination callback + *********************************************/ +TSKM_STATIC uint32_t downExFuncCallback(PRI_CTX_t* p_ctx, + TSKM_EV_PRI_REQ_DOWN_PRM_t* p_prm) { + const PRIM_EXFUNC_TBL* funcEntry; + uint32_t maxStep = 0; + + for (funcEntry = p_ctx->prm.downExFuncTbl; funcEntry->localStep != 0; + funcEntry++) { + if (funcEntry->localStep == p_prm->localStep) { + funcEntry->func(funcEntry->prm); + } + maxStep = TSKM_MAX(maxStep, funcEntry->localStep); + } + return maxStep; +} + +/********************************************* + * Gradual termination requests + *********************************************/ +TSKM_STATIC void downRequest(PRI_CTX_t* p_ctx, + TSKM_EV_PRI_REQ_DOWN_PRM_t* p_prm) { + TSKM_EV_PRI_REQ_DOWN_PRM_t prm = *p_prm; + uint32_t max = 0; + + // Execute step by step + for (prm.localStep = p_ctx->downStepDone + 1; + (prm.localStep <= p_prm->localStep && prm.localStep < PRIM_ACCOFF_MAX); + prm.localStep++) { + max = downExFuncCallback(p_ctx, &prm); + } + + if (max <= p_prm->localStep) { + p_ctx->downStepDone = PRIM_ACCOFF_MAX; // Completed all steps + } else { + p_ctx->downStepDone = p_prm->localStep; + } +} + +TSKM_STATIC void downRequestHandle(PRI_CTX_t* p_ctx, + TSKM_EV_PRI_REQ_DOWN_PRM_t* p_prm) { + TSKM_EVENT_INFO_t ev; + int ret; + + bzero(&ev, sizeof(ev)); + + if (p_prm->localStep == TSKM_LSTEP_ALL || p_prm->localStep == TSKM_LSTEP_LAST) { + downRequest(p_ctx, p_prm); + } else if (p_prm->localStep == TSKM_LSTEP_SHM) { + TSKM_ASSERT(0); + } else if (p_prm->localStep == TSKM_LSTEP_BUPCHK) { + TSKM_ASSERT(0); + } else { + downRequest(p_ctx, p_prm); + } + + if (p_ctx->downStepDone >= PRIM_ACCOFF_MAX) { + /* It is not notified when the last function is executed, and it is left to the exitDone. + TSKM_PRINTF(TSKM_LOG_DEBUG,"ACCOFF DONE"); + ev.prm.resDown.isLast = TSKM_TRUE; + p_ctx->isExec = TSKM_FALSE; + ret = tskm_sockSend(p_ctx->connFd,&ev); + if(ret <= 0){ + TSKM_ASSERT(0); + tskm_pf_abort(); + } + */ + } else { + ev.event = TSKM_EV_PRI_RES_DOWN; + ev.errCode = TSKM_E_OK; + ret = tskm_sockSend(p_ctx->connFd, &ev); + if (ret <= 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + tskm_pf_abort(); + // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded + } + } +} + +/********************************************* + * Termination completion notification to the TSKM + *********************************************/ +TSKM_STATIC void sendLastDoneRes(PRI_CTX_t* p_ctx) { + int ret; + TSKM_EVENT_INFO_t ev; + + bzero(&ev, sizeof(ev)); + + ev.event = TSKM_EV_PRI_RES_DOWN; + ev.errCode = TSKM_E_OK; + ev.prm.resDown.isLast = TSKM_TRUE; + ret = tskm_sockSend(p_ctx->connFd, &ev); + if (ret <= 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + tskm_pf_abort(); + // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded + } +} + +/********************************************* + * Call Touch CB + *********************************************/ +TSKM_STATIC void touchService(PRI_CTX_t* p_ctx) { + char touchName[32]; + + if (p_ctx->isExitStart) { + // If termination has already begun, the system just processes as timeout for retrying not respond Touch + return; + } + + p_ctx->prm.onTouch(p_ctx->hApp); + + tskm_pf_mkTouchFileName(getpid(), touchName); + + if ((access(touchName, F_OK) == 0)) { + // Synchronize by deleting files. + TSKM_PRINTF(TSKM_LOG_STATE, "del:%s", touchName); + unlink(touchName); + } else { + TSKM_ASSERT_PRINT(0, "%s", touchName); + } +} + +/********************************************* + * Call Debugdump CB + *********************************************/ +TSKM_STATIC void callDebugDump(PRI_CTX_t* p_ctx) { + if (!p_ctx->prm.onDebugDump) { // LCOV_EXCL_BR_LINE 6: As NULL checked by INI_Init + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); // LCOV_EXCL_LINE 6: As NULL checked by INI_Init + } else { + p_ctx->prm.onDebugDump(p_ctx->hApp); + } +} + +/********************************************* + * Call LowMemory detection + *********************************************/ +TSKM_STATIC void callLowMem(PRI_CTX_t* p_ctx) { + if (!p_ctx->prm.onLowMem) { + TSKM_ASSERT(0); + } else if (!p_ctx->isExitStart) { + // Notify LowMemory only before starting terminating process + p_ctx->prm.onLowMem(p_ctx->hApp); + } +} + +/********************************************* + * Event handles + *********************************************/ +TSKM_STATIC void eventHandle(PRI_CTX_t* p_ctx, TSKM_EVENT_INFO_t* p_ev) { + //Processing according to the request + switch (p_ev->event) { + case TSKM_EV_PRI_REQ_WAKEUP: + wakeupRequestHandle(p_ctx, &p_ev->prm.reqWakeup); + break; + case TSKM_EV_PRI_REQ_DOWN: + downRequestHandle(p_ctx, &p_ev->prm.reqDown); + break; + case TSKM_EV_PRI_REQ_TOUCH: + touchService(p_ctx); + break; + case TSKM_EV_PRI_REQ_DEBUGDUMP: + callDebugDump(p_ctx); + break; + case TSKM_EV_PRI_REP_LOWMEM: + callLowMem(p_ctx); + break; + default: + TSKM_ASSERT(0); + break; + } +} + +/********************************************* + * Initialize Context + *********************************************/ +TSKM_STATIC void initCtx(T_PRIM_PRM* p_prm, PRI_CTX_t* p_ctx, int argc, + char* argv[]) { + FrameworkunifiedDefaultCallbackHandler cbFuncs; + + p_ctx->prm = *p_prm; + + cbFuncs.onInitilization = p_ctx->prm.onInit; + cbFuncs.onDestroy = p_ctx->prm.onDestory; + cbFuncs.onDebugDump = p_ctx->prm.onDebugDump; + cbFuncs.onStart = FrameworkunifiedOnStart; + cbFuncs.onStop = FrameworkunifiedOnStop; + cbFuncs.createStateMachine = FrameworkunifiedCreateStateMachine; + cbFuncs.ssFrameworkInterface = FrameworkunifiedSSFrameworkInterface; + + EFrameworkunifiedStatus taskmanagerRet; + taskmanagerRet = FrameworkunifiedCreateDispatcherWithoutLoop(p_ctx->prm.name, p_ctx->hApp, argc, + argv, &cbFuncs, FALSE); + if (eFrameworkunifiedStatusOK != taskmanagerRet) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_PRINT(0, "%d", taskmanagerRet); + goto ERROR; + // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded + } + + taskmanagerRet = FrameworkunifiedGetDispatcherFD(p_ctx->hApp, &p_ctx->nsFd); + if (taskmanagerRet != eFrameworkunifiedStatusOK) { + TSKM_ASSERT_PRINT(0, "%d", taskmanagerRet); + exit(EXIT_FAILURE); + } + p_ctx->connFd = tskm_cliSockConnect(TSKM_SOCKET_NAME); + if (p_ctx->connFd < 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded + } + if (pipe(p_ctx->pipeFd) != 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded + } + + return; + + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + tskm_pf_abort(); + // LCOV_EXCL_STOP +} + +/********************************************* + * Destroy context + *********************************************/ +TSKM_STATIC void termCtx(PRI_CTX_t* p_ctx) { + if (p_ctx->shmDone) { // LCOV_EXCL_BR_LINE 6: Since it has been set to True by INI_Handler and cannot be changed + const PRIM_SHAREDATA_TBL* shmEntry = p_ctx->prm.shmTbl; + for (shmEntry = p_ctx->prm.shmTbl; shmEntry->shmName[0] != '\0'; + shmEntry++) { + TSKM_ASSERT(0 == tskm_pf_shmDelete(shmEntry->shmName)); // LCOV_EXCL_BR_LINE 8: For processing in which only return value 0 is set + } + } + + if (p_ctx->connFd > 0) { // LCOV_EXCL_BR_LINE 6: For processing in which only return value 0 is set + tskm_sockDestory(p_ctx->connFd); + } + + EFrameworkunifiedStatus taskmanagerRet; + taskmanagerRet = FrameworkunifiedDestroyDispatcherWithoutLoop(p_ctx->hApp); + TSKM_ASSERT(taskmanagerRet == eFrameworkunifiedStatusOK); + + if (p_ctx->isDynamic) { + TSKM_PRINTF(TSKM_LOG_STATE, "EXIT %s", p_ctx->procName); + } else { + // Hung up running services to prevent adversely affecting to system termination processing during process termination processing + sleep(TSKM_CFG_WAIT_SHUTDOWN); + } +} + +/******************************************************************* + * Initialize PRI context + *******************************************************************/ +void pri_init(T_PRIM_PRM* p_prm, int argc, char* argv[], int *fdNum, + int fdlist[INI_FD_MAX]) { + int ret = 0; + PRI_CTX_t* p_ctx = &g_pri; + + strncpy(p_ctx->procName, basename(argv[0]), sizeof(p_ctx->procName) - 1); + + ret = tskm_pf_procInit(); + if (ret != 0) { // LCOV_EXCL_BR_LINE 6: Return value of 0 only + // LCOV_EXCL_START 6: Return value of 0 only + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP 6: Return value of 0 only + } + + ret = tskm_comm_procInit(); + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP 5: Checked in Death testing, but it is not reflected in the coverage and excluded + } + + initCtx(p_prm, p_ctx, argc, argv); + + *fdNum = 3; + fdlist[0] = p_ctx->connFd; + fdlist[1] = p_ctx->pipeFd[0]; + fdlist[2] = p_ctx->nsFd; + + p_ctx->svcId = TSKM_SVCID_NONE; + p_ctx->isExec = TSKM_TRUE; + + p_ctx->bootInfo.startupReason = epswfINVALID; + p_ctx->bootInfo.isUserModeOn = FALSE; + p_ctx->bootInfo.dataResetMode = e_SS_SM_DATA_RESET_MODE_NONE; + p_ctx->bootInfo.securityStatus = epsssINVALID; + p_ctx->bootInfo.wakeupType = epsstINVALID; + p_ctx->bootInfo.dramBackupStatus = e_SS_SM_DRAM_BACKUP_UNSET; + p_ctx->bootInfo.resetStatus = e_SS_SM_RESET_STATUS_UNSET; + + memset(&p_ctx->extBootInfo, 0, sizeof(p_ctx->extBootInfo)); + + p_ctx->timeout = PRI_MONITOR_DEFAULT_TIMEOUT; + + return; + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + tskm_pf_abort(); // ABORT +// LCOV_EXCL_STOP +} + +/******************************************************************* + * Primary library handler + *******************************************************************/ +BOOL pri_handler(fd_set* p_fds) { + PRI_CTX_t* p_ctx = &g_pri; + + if (FD_ISSET(p_ctx->connFd, p_fds)) { + int ret; + TSKM_EVENT_INFO_t ev; + ret = tskm_sockRcv(p_ctx->connFd, &ev); + // LCOV_EXCL_BR_START 5: True condition is checked in Death tests, but not reflected in coverage and excluded + if (ret > 0) { + // LCOV_EXCL_BR_STOP + eventHandle(p_ctx, &ev); + } else { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + } + + if (FD_ISSET(p_ctx->pipeFd[0], p_fds)) { + // only use exitDone + uint32_t tmp; + TSKM_ASSERT(sizeof(tmp) == read(p_ctx->pipeFd[0], &tmp, sizeof(tmp))); + TSKM_ASSERT(p_ctx->downStepDone == PRIM_ACCOFF_MAX); // Check if all exit functions are complete + if (p_ctx->isDynamic) { + // A nonresident service completes its termination processing by terminating the process (because the SIGNAL will overtake the sockets) + } else { + // The resident service completes termination processing with a termination notice (Do not terminate processes to reduce the impact on system termination) + sendLastDoneRes(p_ctx); + } + p_ctx->isExec = TSKM_FALSE; + } + + if (FD_ISSET(p_ctx->nsFd, p_fds)) { + FrameworkunifiedDispatchProcessWithoutLoop(p_ctx->hApp); + } + return p_ctx->isExec; + + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + tskm_pf_abort(); // ABORT + return 0; +// LCOV_EXCL_STOP +} + +/******************************************************************* + * Process termination + *******************************************************************/ +void pri_term(void) { + PRI_CTX_t* p_ctx = &g_pri; + termCtx(p_ctx); +} + +/******************************************************************* + * Service Monitoring Status Setting + *******************************************************************/ +int pri_setMonitorState(BOOL bIsRun, uint32_t timeout) { + PRI_CTX_t* p_ctx = &g_pri; + int ret = INI_SUCCESS; + + if (TSKM_SVCID_NONE == p_ctx->svcId) { + // Ignore requests until svcId is acquired + } else if ((TRUE == bIsRun) && (0 == timeout)) { + // When RUN is specified with timeout = 0, monitoring is disabled + } else { + ret = tskm_comm_setSvcWatchState(p_ctx->svcId, bIsRun, timeout); + if (INI_SUCCESS != ret) { + TSKM_ASSERT(0); + } + } + + return ret; +} + +/******************************************************************* + * MAIN function + *******************************************************************/ +int pri_main(T_PRIM_PRM* p_prm, int argc, char* argv[]) { + int mainRet = -1; + int fdlist[INI_FD_MAX]; + int fdNum; + int ii; + BOOL isExec = TRUE; + + pri_init(p_prm, argc, argv, &fdNum, fdlist); + + while (isExec) { + PRI_CTX_t* p_ctx = &g_pri; + int maxFd = 0; + fd_set fds; + int ret; + + FD_ZERO(&fds); + + for (ii = 0; ii < fdNum; ii++) { + FD_SET(fdlist[ii], &fds); + maxFd = TSKM_MAX(fdlist[ii], maxFd); + } + + TSKM_ASSERT(INI_SUCCESS == pri_setMonitorState(FALSE, 0)); + ret = select(maxFd + 1, &fds, NULL, NULL, NULL); + TSKM_ASSERT(INI_SUCCESS == pri_setMonitorState(TRUE, p_ctx->timeout)); + if (ret < 1) { + if (errno != EINTR) { + TSKM_ASSERT(0); + } + continue; + } + + isExec = pri_handler(&fds); + } + + mainRet = 0; + + pri_term(); + return mainRet; +} + +/******************************************************************* + * Termination request + *******************************************************************/ +void pri_exitStart(void *rsv) { + int ret; + PRI_CTX_t* p_ctx = &g_pri; + TSKM_EVENT_INFO_t ev; + + bzero(&ev, sizeof(ev)); + p_ctx->isExitStart = TRUE; + ev.event = TSKM_EV_PRI_REQ_EXIT; + ev.errCode = TSKM_E_OK; + + ret = tskm_sockSend(p_ctx->connFd, &ev); + if (ret <= 0) { // LCOV_EXCL_BR_LINE 6: The caller's external API does not execute the second or subsequent processing and cannot be checked + TSKM_ASSERT(0); + goto ERROR; + } + return; + // LCOV_EXCL_START 6: The caller's external API does not execute the second or subsequent processing and cannot be checked + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + tskm_pf_abort(); + // LCOV_EXCL_STOP +} + +void pri_exitDone(int status) { + PRI_CTX_t* p_ctx = &g_pri; + uint32_t l_status = (uint32_t) status; + + // LCOV_EXCL_BR_START 6: The caller's external API does not execute the second or subsequent processing and cannot be checked + if (p_ctx->pipeFd[1] > 0) { + // LCOV_EXCL_BR_STOP + // LCOV_EXCL_START 6: The caller's external API does not execute the second or subsequent processing and cannot be checked + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO( + write(p_ctx->pipeFd[1], &l_status, sizeof(l_status)) + == sizeof(l_status)); + // LCOV_EXCL_STOP + } else { + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); // LCOV_EXCL_LINE 6: The caller's external API does not execute the second or subsequent processing and cannot be checked + } +} + +/******************************************************************* + * Event completion notification at startup + *******************************************************************/ +int32_t pri_stepForkComp(uint64_t id) { + int ret; + PRI_CTX_t* p_ctx = &g_pri; + TSKM_EVENT_INFO_t ev; + + bzero(&ev, sizeof(ev)); + ev.event = TSKM_EV_PRI_REP_WAKEUP_COMP; + ev.errCode = TSKM_E_OK; + ev.prm.repWakeupComp.compId = id; + ret = tskm_sockSend(p_ctx->connFd, &ev); + if (ret <= 0) { + TSKM_ASSERT(0); + goto ERROR; + } + return INI_SUCCESS; + ERROR: return INI_FALSE; +} + +/******************************************************************* + * Event completion notification at termination + *******************************************************************/ +int32_t pri_accOffComp(uint64_t id) { + int ret; + PRI_CTX_t* p_ctx = &g_pri; + TSKM_EVENT_INFO_t ev; + + bzero(&ev, sizeof(ev)); + + ev.event = TSKM_EV_PRI_REP_DOWN_COMP; + ev.errCode = TSKM_E_OK; + ev.prm.repDownComp.compId = id; + ret = tskm_sockSend(p_ctx->connFd, &ev); + if (ret <= 0) { + TSKM_ASSERT(0); + goto ERROR; + } + return INI_SUCCESS; + ERROR: return INI_FALSE; +} + +/******************************************************************* + * Get private info + *******************************************************************/ +void* +pri_getPrivate() { + PRI_CTX_t* p_ctx = &g_pri; + return p_ctx->prm.priv; +} + +/******************************************************************* + * Get app-handle + *******************************************************************/ +HANDLE pri_getHandle() { + PRI_CTX_t* p_ctx = &g_pri; + return p_ctx->hApp; +} + +/******************************************************************* + * Service monitoring status setting timeout setting + *******************************************************************/ +int32_t pri_setMonitorTimeout(uint32_t timeout) { + PRI_CTX_t* p_ctx = &g_pri; + p_ctx->timeout = timeout; + return INI_SUCCESS; +} + +/******************************************************************* + * Get boot info + *******************************************************************/ +int32_t pri_getBootInfo(T_SS_SM_START_DataStructType *info) { + PRI_CTX_t* p_ctx = &g_pri; + + if (p_ctx->bootInfo.startupReason == epswfINVALID) { + TSKM_ASSERT(0); + return INI_FALSE; + } + + *info = p_ctx->bootInfo; + + return INI_SUCCESS; +} + +/******************************************************************* + * Get extended boot info + *******************************************************************/ +int32_t pri_getExtBootInfo(T_SS_SM_START_ExtDataStructType *info) { + PRI_CTX_t* p_ctx = &g_pri; + + if (p_ctx->bootInfo.startupReason == epswfINVALID) { + TSKM_ASSERT(0); + return INI_FALSE; + } + + *info = p_ctx->extBootInfo; + + return INI_SUCCESS; +} + +/******************************************************************* + * DebugDump response + *******************************************************************/ +void pri_sendDebugDumpRes(const char *buf) { // LCOV_EXCL_START 7: Debugging code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + int ret; + PRI_CTX_t* p_ctx = &g_pri; + TSKM_EVENT_INFO_t ev; + TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t *p_prm; + + ev.event = TSKM_EV_PRI_RES_DEBUGDUMP; + ev.errCode = TSKM_E_OK; + ev.hasExtend = TSKM_TRUE; + + ev.extendPrm = malloc(sizeof(TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t)); + if (!ev.extendPrm) { + TSKM_ASSERT(0); + goto ERROR; + } + + ev.extendSize = sizeof(TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t); + + p_prm = (TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t *) ev.extendPrm; // NOLINT (readability/casting) + snprintf(p_prm->dumpMsg, TSKM_EV_DEBUGDUMP_SIZE, "%s", buf); + + ret = tskm_sockSend(p_ctx->connFd, &ev); + if (ret <= 0) { + TSKM_ASSERT(0); + } + + ERROR: return; +} +// LCOV_EXCL_STOP +/************************************************* + * Empty functions implemented for building software + **************************************************/ +EFrameworkunifiedStatus FrameworkunifiedOnStart(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} +EFrameworkunifiedStatus FrameworkunifiedOnStop(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} + +EFrameworkunifiedStatus FrameworkunifiedCreateStateMachine(HANDLE hApp) { // LCOV_EXCL_START 6: Because the condition cannot be set + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} +// LCOV_EXCL_STOP diff --git a/systemservice/task_manager/server/src/tskm_api.cpp b/systemservice/task_manager/server/src/tskm_api.cpp new file mode 100644 index 00000000..94c8226e --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_api.cpp @@ -0,0 +1,268 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "tskm_debug.h" +#include "tskm_main.h" +#include "tskm_state.h" +#include "tskm_util.h" + +#include "tskm_srvr.h" +#include "tskm_port_pf.h" +#include "tskm_port_subsys.h" + +/** + * _TSKM_SvcCtl Sub-func Task-startup-process + * @param svcId service id + * @param p_main TSKM_MAIN_CTX_t* + * @param p_svc TSKM_SVC_CTX_t* + * @return TSKM_E_OK Succeeded + * @return other Failed + */ + +TSKM_ERR_t tskm_svcExecRequest(TSKM_SVCID_t svcId, TSKM_MAIN_CTX_t* p_main, TSKM_SVC_CTX_t* p_svc) { + TSKM_ERR_t tskmRet = TSKM_E_OK; + + // Startup tasks + TSKM_GSTEP_REQ_INFO_t req = { 0 }; + + if (p_main->isOnStartDone == TSKM_FALSE) { + TSKM_PRINTF(TSKM_LOG_WARN, "Transient SVC cannot exec before get BootInfo"); + return TSKM_E_STATE; + } else if (p_main->isOnStopDone == TSKM_TRUE) { + TSKM_PRINTF(TSKM_LOG_WARN, "Transient SVC cannot exec after FrameworkunifiedOnStop"); + return TSKM_E_STATE; + } + + tskmRet = tskm_svcExec(p_svc); + TSKM_ERR_CHK_DFT; + if (p_svc->state == TSKM_SVC_WAITCONNECT) { + // In the state of waiting to execute + req.svcId = svcId; + req.localStep = TSKM_LSTEP_ALL; + tskmRet = tskm_svcWakeupRequest(p_svc, &req); + TSKM_ERR_CHK_DFT; // LCOV_EXCL_BR_LINE 6: Because TSKM_ERR_CHK_DFT does not specify a condition for goto to ERROR + } + ERROR: return tskmRet; +} + +/** + * _TSKM_SvcCtl Sub-func Task-startup-process + * @param p_main TSKM_MAIN_CTX_t* + * @param svcId TSKM_SVCID_t + * @return TSKM_E_OK Succeeded + * @return other Failed + */ + +TSKM_ERR_t tskm_svcReserveRequest(TSKM_MAIN_CTX_t* p_main, TSKM_SVCID_t svcId) { + uint8_t rsvSvcNum = p_main->nvInfo.body.rsvSvcNum; + TSKM_SVCID_t* p_rsvSvcs = p_main->nvInfo.body.rsvSvcs; + TSKM_ERR_t tskmRet = TSKM_E_OK; + + if (rsvSvcNum >= TSKM_SVC_RESERVE_MAX) { + tskmRet = TSKM_E_STATE; + } else { + int ii; + int ret; + + for (ii = 0; ii < rsvSvcNum; ii++) { + if (p_rsvSvcs[ii] == svcId) { + TSKM_ASSERT_PRINT(0, "Rsv Req already registered(%d)", svcId); + // Return OK as continuable + return tskmRet; + } + } + + p_rsvSvcs[rsvSvcNum] = svcId; + p_main->nvInfo.body.rsvSvcNum++; + + TSKM_PRINTF(TSKM_LOG_STATE, "Rsv Svc registered(%#x)", svcId); + + ret = tskm_pf_nvFileWrite(&p_main->nvInfo); // LCOV_EXCL_BR_LINE 6: Return value of 0 only + if (ret == -1) { + TSKM_ASSERT(0); + tskmRet = TSKM_E_NG; + return tskmRet; + } + } + return tskmRet; +} + +/** + * Service control + * @param svcId service id + * @param ctl control command + * @return TSKM_E_OK Succeeded + * @return other Failed + */ +TSKM_ERR_t _TSKM_SvcCtl(TSKM_SVCID_t svcId, const TSKM_SVC_CTL_t* ctl) { + TSKM_ERR_t tskmRet = TSKM_E_OK; + TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx(); + + TSKM_SVC_CTX_t* p_svc; + + if (ctl == NULL) { + TSKM_ASSERT(0); + return TSKM_E_PAR; + } + + p_svc = tskm_svcsGetSvcBySvcId(&p_main->svcs, svcId); + if (p_svc == NULL) { + TSKM_ASSERT(0); + TSKM_PRINTF(TSKM_LOG_ERROR, "unknown svcId:%#x", svcId); + return TSKM_E_PAR; + } + + TSKM_PRINTF(TSKM_LOG_API, "%s(%#x,%d)", __FUNCTION__, svcId, ctl->cmd); + + if (ctl->cmd == TSKM_SVC_CMD_EXEC) { + tskmRet = tskm_svcExecRequest(svcId, p_main, p_svc); + } else if (ctl->cmd == TSKM_SVC_CMD_ENABLE) { + tskmRet = tskm_svcEnableRequest(p_svc); + TSKM_ERR_CHK_DFT; // LCOV_EXCL_BR_LINE 8: Because TSKM_ERR_CHK_DFT does not specify a condition for goto to ERROR + + } else if (ctl->cmd == TSKM_SVC_CMD_DISABLE) { + tskmRet = tskm_svcDisableRequest(p_svc); + TSKM_ERR_CHK_DFT; + + } else if (ctl->cmd == TSKM_SVC_CMD_RESERVE) { + tskmRet = tskm_svcReserveRequest(p_main, svcId); + + } else { + return TSKM_E_PAR; + } + + ERROR: return tskmRet; +} + +/** + * Get service info + * @param svcId service id + * @param svcInfo[O] service info + * @return TSKM_E_OK Succeeded + * @return other Failed + */ +TSKM_ERR_t TSKM_SvcGetInfo(TSKM_SVCID_t svcId, TSKM_SVC_INFO_t* svcInfo) { +// Do not LOG acquisition APIs TSKM_PRINTF(TSKM_LOG_API,"%s()",__FUNCTION__) + + TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx(); + TSKM_SVC_CTX_t* p_svc = tskm_svcsGetSvcBySvcId(&p_main->svcs, svcId); + + if (p_svc == NULL || svcInfo == NULL) { + return TSKM_E_PAR; + } + + svcInfo->svcId = p_svc->attr->svcId; + svcInfo->isExecDisable = + (p_svc->state == TSKM_SVC_DISABLE) ? TSKM_TRUE : TSKM_FALSE; + + return TSKM_E_OK; +} + +RPC_Result _TSKM_ErrorReboot(const TSKM_ERROR_REBOOT_t* p_info) { + RPC_Result rpcRet = RPC_OK; + TSKM_ERROR_REBOOT_t rebootInfo; + + if (!p_info || (p_info->type != TSKM_ERROR_REBOOT_NORMAL)) { + TSKM_ASSERT(0); + return RPC_ERR_Fatal; + } + + memset(&rebootInfo, 0, sizeof(TSKM_ERROR_REBOOT_t)); + rebootInfo.type = p_info->type; + snprintf(rebootInfo.log.messageStr, TSKM_LOGGING_MSG_STR_SIZE, "%s", + p_info->log.messageStr); + + TSKM_PRINTF(TSKM_LOG_API, "%s(%d)", __FUNCTION__, p_info->type); + + tskm_sub_reboot(&rebootInfo); + + return rpcRet; +} + +/** + * Reboot service + * @param p_rsv Reserved + * @return TSKM_E_OK Succeeded + * @return other Failed + */ +TSKM_ERR_t TSKM_Reboot(const TSKM_RSV_t * p_rsv) { + TSKM_ERR_t tskmRet = TSKM_E_OK; + + TSKM_PRINTF(TSKM_LOG_API, "%s()", __FUNCTION__) + if (p_rsv != NULL) { + TSKM_ASSERT(0); + return TSKM_E_PAR; + } + + tskm_sub_reboot_normal(); + + return tskmRet; +} + +/** + * Save LOGs + * @param p_info LOG storage info + * @return TSKM_E_OK Succeeded + * @return other Failed + */ +TSKM_ERR_t TSKM_Logging(const TSKM_LOGGING_INFO_t* p_info) { + TSKM_LOGGING_INFO_t logInfo; + TSKM_PRINTF(TSKM_LOG_API, "%s()", __FUNCTION__) + + if (!p_info) { + TSKM_ASSERT(0); + return TSKM_E_PAR; + } else { + switch (p_info->type) { + case TSKM_LOGGING_TYPE_MODULE_LOGS: + case TSKM_LOGGING_TYPE_GRP_RELAUNCH: + break; + default: + TSKM_ASSERT(0); + return TSKM_E_PAR; + } + } + + logInfo.type = p_info->type; + snprintf(logInfo.messageStr, TSKM_LOGGING_MSG_STR_SIZE, "%s", + p_info->messageStr); + + tskm_sub_logging(&logInfo); + + return TSKM_E_OK; +} + +TSKM_ERR_t TSKM_SetWakeupOrder(const TSKM_WAKEUP_ORDER_t* p_order) { + TSKM_ERR_t tskmRet = TSKM_E_OK; + + TSKM_PRINTF(TSKM_LOG_API, "%s()", __FUNCTION__) + + if (p_order == NULL) { + return TSKM_E_PAR; + } + + if (strnlen(p_order->orderName, TSKM_ORDER_NAME_MAX) >= TSKM_ORDER_NAME_MAX) { + return TSKM_E_PAR; + } + + if (tskm_sub_setWakeupOrder(p_order->orderName) != 0) { + TSKM_ASSERT(0); + tskmRet = TSKM_E_NG; + } + + return tskmRet; +} // LCOV_EXCL_BR_LINE 10: Final line + diff --git a/systemservice/task_manager/server/src/tskm_comm.cpp b/systemservice/task_manager/server/src/tskm_comm.cpp new file mode 100644 index 00000000..b177b9b8 --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_comm.cpp @@ -0,0 +1,402 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 _GNU_SOURCE +#warning "_GNU_SOURCE not defined, so define here" +#define _GNU_SOURCE +#endif +#include "tskm_comm.h" +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> + +#include <native_service/cl_monitor.h> + +#include "tskm_debug.h" +#include "tskm_util.h" + + +/********************************************************** + * Internal functions + **********************************************************/ +TSKM_STATIC TSKM_SRV_CONNENT_t* +addConnFd(TSKM_SRV_CONNENT_LIST_t* list, TSKM_SRV_CONNENT_t* conn) { + TSKM_SRV_CONNENT_t* retConn; + if (list->num >= TSKM_COMM_CONNECT_MAX) { + TSKM_ASSERT(0) + return NULL; + } + + retConn = &list->conn[list->num]; + list->conn[list->num] = *conn; + list->num++; + return retConn; +} + +TSKM_STATIC void delConnFd(TSKM_SRV_CONNENT_LIST_t* list, + TSKM_SRV_CONNENT_t* conn) { + uint32_t ii; + TSKM_BOOL_t isFind = TSKM_FALSE; + for (ii = 0; ii < list->num; ii++) { + if (!isFind && list->conn[ii].connFd == conn->connFd) { + isFind = TSKM_TRUE; + list->num--; + } + + if (isFind && (ii < list->num)) { + list->conn[ii] = list->conn[ii + 1]; + } + } + TSKM_ASSERT(isFind); +} + +/********************************************************** + * Public functions + **********************************************************/ +TSKM_ERR_t tskm_srvSockCreate(const char *sockName, + TSKM_SRV_SOCK_CTX_t* p_sock) { + int fd = -1; + int ret; + int sockRet; + int enable = 1; + int listenNum = TSKM_COMM_CONNECT_MAX; + + struct sockaddr_un unix_addr = { }; + + fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) { // LCOV_EXCL_BR_LINE 5: For processing initializing process + // LCOV_EXCL_START 5: For processing initializing process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + if (0 == access(sockName, F_OK)) { // LCOV_EXCL_BR_LINE 5: For processing initializing process + TSKM_ASSERT(0); + unlink(sockName); + } + + unix_addr.sun_family = AF_UNIX; + strncpy(unix_addr.sun_path, sockName, sizeof(unix_addr.sun_path) - 1); + + sockRet = bind(fd, (struct sockaddr *) &unix_addr, sizeof(unix_addr)); + if (sockRet != 0) { // LCOV_EXCL_BR_LINE 5: For processing initializing process + // LCOV_EXCL_START 5: For processing initializing process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + ret = chmod(sockName, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH); + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: For processing initializing process + // LCOV_EXCL_START 5: For processing initializing process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + sockRet = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)); + if (sockRet != 0) { // LCOV_EXCL_BR_LINE 5:For processing initializing process + // LCOV_EXCL_START 5: For processing initializing process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + sockRet = listen(fd, listenNum); + if (sockRet != 0) { // LCOV_EXCL_BR_LINE 5: For process initialization processing + // LCOV_EXCL_START 5: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + memset(p_sock, 0, sizeof(*p_sock)); + p_sock->sockFd = fd; + p_sock->sockName = sockName; + + return TSKM_E_OK; + // LCOV_EXCL_START 5: For process initialization processing + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if (fd != -1) { + close(fd); + } + return TSKM_E_NG; + // LCOV_EXCL_STOP +} + +TSKM_SRV_CONNENT_t* +tskm_srvSockConnect(TSKM_SRV_SOCK_CTX_t* p_sock) { + int fd = -1; + socklen_t len; + int sockRet; + TSKM_SRV_CONNENT_t conn; + TSKM_SRV_CONNENT_t *retConn; + struct ucred credent; + struct sockaddr_un unix_addr; + + memset(&conn, 0, sizeof(conn)); + conn.connFd = -1; + + len = sizeof(unix_addr); + fd = accept(p_sock->sockFd, (struct sockaddr*) &unix_addr, + (socklen_t *) &len); // NOLINT (readability/casting) + if (fd < 0) { // LCOV_EXCL_BR_LINE 5: Accept's Error-Handling Process + // LCOV_EXCL_START 5: Accept's Error-Handling Process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + conn.connFd = fd; + + len = sizeof(credent); + sockRet = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &credent, &len); + if (sockRet != 0) { // LCOV_EXCL_BR_LINE 5: Getsockopt's Error-Handling Process + // LCOV_EXCL_START 5: Getsockopt's Error-Handling Process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + conn.pid = credent.pid; + + retConn = addConnFd(&p_sock->connList, &conn); + if (retConn == NULL) { // LCOV_EXCL_BR_LINE 5: Connect's Error-Handling Process + // LCOV_EXCL_START 5: Connect's Error-Handling Process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + return retConn; + // LCOV_EXCL_START 5: Error-Handling Process + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if (conn.connFd != -1) { + tskm_sockDestory(conn.connFd); + } + return NULL; + // LCOV_EXCL_STOP +} + +void tskm_srvSockDisconnect(TSKM_SRV_SOCK_CTX_t* p_sock, + TSKM_SRV_CONNENT_t *p_conn) { + int fd = p_conn->connFd; + delConnFd(&p_sock->connList, p_conn); + tskm_sockDestory(fd); +} + +void tskm_srvSockDestory(TSKM_SRV_SOCK_CTX_t* p_sock) { // LCOV_EXCL_START 6: Because the condition cannot be set + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if (p_sock->sockFd) { + tskm_sockDestory(p_sock->sockFd); + p_sock->sockFd = 0; + + TSKM_ASSERT_ERRNO(0 == unlink(p_sock->sockName)); + } +} +// LCOV_EXCL_STOP +int tskm_cliSockConnect(const char* sockName) { + int fd = -1; + int sockRet; + struct sockaddr_un unix_addr = { }; + + /* Create socket */ + fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + unix_addr.sun_family = AF_UNIX; + strncpy(unix_addr.sun_path, sockName, sizeof(unix_addr.sun_path) - 1); + sockRet = connect(fd, (struct sockaddr*) &unix_addr, sizeof(unix_addr)); + if (sockRet < 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + return fd; + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if (fd != -1) { + TSKM_ASSERT_ERRNO(0 == close(fd)); + } + return -1; + // LCOV_EXCL_STOP +} + +int tskm_sockRcv(int fd, TSKM_EVENT_INFO_t* p_ev) { + int ret; + TSKM_EVENT_INFO_t ev; + ret = static_cast<int>(recv(fd, &ev, sizeof(ev), 0)); + + // LCOV_EXCL_BR_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + if (ret > (int) sizeof(ev)) { // NOLINT (readability/casting) + // LCOV_EXCL_BR_STOP + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + if (ret < 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + if (ret > 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + TSKM_PRINTF(TSKM_LOG_MSG, "recv:%s from:%d ret:%d", + tskm_convEvent2Str(ev.event), ev.fromPid, ret); + } + + *p_ev = ev; + + if (p_ev->hasExtend && (0 != p_ev->extendSize)) { + TSKM_PRINTF(TSKM_LOG_MSG, "rcv:ex(%d) ", p_ev->extendSize); + + p_ev->extendPrm = malloc(p_ev->extendSize); + if (!p_ev->extendPrm) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + ret = static_cast<int>(recv(fd, p_ev->extendPrm, p_ev->extendSize, 0)); + + // LCOV_EXCL_BR_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + if (ret > (int) p_ev->extendSize) { // NOLINT (readability/casting) + // LCOV_EXCL_BR_STOP + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + if (ret < 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + } + + return ret; + + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return -1; + // LCOV_EXCL_STOP +} + +int tskm_sockSend(int fd, TSKM_EVENT_INFO_t* p_ev) { + int ret; + p_ev->fromPid = getpid(); + TSKM_PRINTF(TSKM_LOG_MSG, "send:%s ", tskm_convEvent2Str(p_ev->event)); + ret = static_cast<int>(send(fd, p_ev, sizeof(*p_ev), MSG_NOSIGNAL)); + if (ret != sizeof(*p_ev)) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + // Because it is entered only when called from a debugging function (pri_sendDebugDumpRes) + if (p_ev->hasExtend && p_ev->extendPrm && (0 != p_ev->extendSize)) { + TSKM_PRINTF(TSKM_LOG_MSG, "send:ex(%d) ", p_ev->extendSize); + + ret = static_cast<int>(send(fd, p_ev->extendPrm, p_ev->extendSize, MSG_NOSIGNAL)); + if (ret != (int)p_ev->extendSize) { // NOLINT (readability/casting) + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + } + + return ret; + + ERROR: return -1; +} + +void tskm_sockDestory(int fd) { + TSKM_ASSERT_ERRNO(0 == shutdown(fd, SHUT_RDWR)); + TSKM_ASSERT_ERRNO(0 == close(fd)); +} + +/****************************************************************** + * Initializing (Process) + ******************************************************************/ +int tskm_comm_procInit(void) { + int ret; + + ret = CL_MonitorInit(CL_MONITOR_INIT_USER); + + if (ret != 0) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + return 0; + + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return -1; + // LCOV_EXCL_STOP +} + +/********************************************************* + * Service Error Monitoring Status Setting + *********************************************************/ +int tskm_comm_setSvcWatchState(uint32_t id, BOOL bIsRun, uint32_t timeout) { + int ret = 0; + + CL_MonitorState_t state = CL_MONITOR_STATE_SLEEP; + + if (bIsRun) { + state = CL_MONITOR_STATE_RUN; + } + + ret = CL_MonitorSetEntry(CL_MONITOR_TYPE_GENERIC, id, state, timeout, 0); + if (0 != ret) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + return 0; + ERROR: return -1; +} // LCOV_EXCL_BR_LINE 10: Final line + diff --git a/systemservice/task_manager/server/src/tskm_debug.cpp b/systemservice/task_manager/server/src/tskm_debug.cpp new file mode 100644 index 00000000..5881f9af --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_debug.cpp @@ -0,0 +1,286 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "tskm_debug.h" + +const char* +tskm_convState2Str(TSKM_STATE_t state) { + const char* ret = "UNKNONW"; + switch (state) { // LCOV_EXCL_BR_LINE 7:debug code + case TSKM_ST_ACCOFF: + ret = "ACCOFF"; + break; + case TSKM_ST_ACCON: + ret = "ACCON"; + break; + case TSKM_ST_WAKEUP: + ret = "WAKEUP"; + break; + case TSKM_ST_RUNNING: + ret = "RUNNING"; + break; + case TSKM_ST_DOWN: + ret = "DOWN"; + break; + } + return ret; +} + +const char* +tskm_convEvent2Str(TSKM_EVENT_t event) { + switch (event) { // LCOV_EXCL_BR_LINE 7:debug code + case TSKM_EV_NOP: + return "NOP"; + case TSKM_EV_PRI_REQ_WAKEUP: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "PRI_REQ_WAKEUP"; + // LCOV_EXCL_STOP + case TSKM_EV_PRI_REQ_DOWN: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "PRI_REQ_DOWN"; + // LCOV_EXCL_STOP + case TSKM_EV_PRI_REQ_TOUCH: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "PRI_REQ_TOUCH"; + // LCOV_EXCL_STOP + case TSKM_EV_PRI_REQ_DEBUGDUMP: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "PRI_REQ_DEBUGDUMP"; + // LCOV_EXCL_STOP + case TSKM_EV_PRI_REP_LOWMEM: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "PRI_REP_LOWMEM"; + // LCOV_EXCL_STOP + case TSKM_EV_PRI_REP_WAKEUP_COMP: + return "PRI_REP_WAKEUP_COMP"; + case TSKM_EV_PRI_REP_DOWN_COMP: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "PRI_REP_DOWN_COMP"; + // LCOV_EXCL_STOP + case TSKM_EV_PRI_REP_CONNECT: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "PRI_REP_CONNECT"; + // LCOV_EXCL_STOP + case TSKM_EV_PRI_REP_DISCONNECT: + return "PRI_REP_DISCONNECT"; + case TSKM_EV_PRI_RES_WAKEUP: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "PRI_RES_WAKEUP"; + // LCOV_EXCL_STOP + case TSKM_EV_PRI_RES_DOWN: + return "PRI_RES_DOWN"; + case TSKM_EV_PRI_RES_DEBUGDUMP: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "PRI_RES_DEBUGDUMP"; + // LCOV_EXCL_STOP + case TSKM_EV_PRI_REQ_EXIT: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "PRI_REQ_EXIT"; + // LCOV_EXCL_STOP + case TSKM_EV_SVC_REP_TERM: + return "SVC_REP_TERM"; + case TSKM_EV_API_REQ_REBOOT: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "API_REQ_REBOOT"; + // LCOV_EXCL_STOP + case TSKM_EV_API_REQ_SVC_CTL: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "API_REQ_SVC_CTL"; + // LCOV_EXCL_STOP + case TSKM_EV_API_REQ_SVC_DISABLE: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "API_REQ_SVC_DISABLE"; + // LCOV_EXCL_STOP + case TSKM_EV_LCL_REQ_STOP: + return "API_REQ_STOP"; + case TSKM_EV_LCL_CHG_SVC_STATE: + return "LCL_CHG_SVC_STATE"; + case TSKM_EV_LCL_REQ_SDUMP: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "LCL_REQ_SDUMP"; + // LCOV_EXCL_STOP + case TSKM_EV_LCL_REP_TIMEOUT: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "LCL_REP_TIMEOUT"; + // LCOV_EXCL_STOP + case TSKM_EV_LCL_REP_POLLING: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "LCL_REP_POLLING"; + // LCOV_EXCL_STOP + case TSKM_EV_LCL_REP_LOWMEM: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "LCL_REP_LOWMEM"; + // LCOV_EXCL_STOP + case TSKM_EV_LCL_REQ_TRANS_STEP: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "LCL_REQ_TRANS_STEP"; + // LCOV_EXCL_STOP + default: + break; + } + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "UNKNOWN"; + // LCOV_EXCL_STOP +} + +const char* +tskm_convInitCompId2Str(uint64_t compId) { + switch (compId) { // LCOV_EXCL_BR_LINE 7:debug code + case INI_INITCOMP_NONE: + return "NONE"; + case INI_INITCOMP_ON_START: + return "ONSTART"; + case INI_INITCOMP_NVM_ACCESS: + return "NVM_ACCESS"; + case INI_INITCOMP_TEST0: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "TEST0"; + // LCOV_EXCL_STOP + case INI_INITCOMP_TEST1: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "TEST1"; + // LCOV_EXCL_STOP + case INI_INITCOMP_TEST2: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "TEST2"; + // LCOV_EXCL_STOP + case INI_INITCOMP_TEST3: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "TEST3"; + // LCOV_EXCL_STOP + } + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "UNKNONW"; + // LCOV_EXCL_STOP +} + +const char* +tskm_convTermCompId2Str(uint64_t compId) { + switch (compId) { // LCOV_EXCL_BR_LINE 7:debug code + case INI_TERMCOMP_NONE: + return "NONE"; + case INI_TERMCOMP_ACTIVITYMGR: + return "ACTIVITYMGR"; + case INI_TERMCOMP_RESIDENT: + return "RESIDENT"; + case INI_TERMCOMP_TRANSIENT: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "TRANSIENT"; + // LCOV_EXCL_STOP + case INI_TERMCOMP_TEST0: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "TEST0"; + // LCOV_EXCL_STOP + case INI_TERMCOMP_TEST1: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "TEST1"; + // LCOV_EXCL_STOP + case INI_TERMCOMP_TEST2: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "TEST2"; + // LCOV_EXCL_STOP + case INI_TERMCOMP_TEST3: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "TEST3"; + // LCOV_EXCL_STOP + } + return "UNKNONW"; +} + +const char* +tskm_convSvcState2Str(TSKM_SVC_STATE_t state) { + switch (state) { // LCOV_EXCL_BR_LINE 7:debug code + case TSKM_SVC_DORMANT: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "DORMANT"; + // LCOV_EXCL_STOP + case TSKM_SVC_WAITCONNECT: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "WAITCONNECT"; + // LCOV_EXCL_STOP + case TSKM_SVC_WAKEUP: + return "WAKEUP"; + case TSKM_SVC_RUNNING: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "RUNNING"; + // LCOV_EXCL_STOP + case TSKM_SVC_DOWN: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "DOWN"; + // LCOV_EXCL_STOP + case TSKM_SVC_FINDOWN: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "FINDOWN"; + // LCOV_EXCL_STOP + case TSKM_SVC_DISABLE: + // LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return "DISABLE"; + // LCOV_EXCL_STOP + default: + break; + } + return "UNKNONW"; +} + +TSKM_STATIC void svcDump(TSKM_SVC_CTX_t* p_svc) { + TSKM_PRINTF(TSKM_LOG_STATE, "<%s>", p_svc->attr->name); + TSKM_PRINTF(TSKM_LOG_STATE, " pid:%d svcId:%#x state:%s waitResCnt:%d", + p_svc->pid, p_svc->attr->svcId, + tskm_convSvcState2Str(p_svc->state), p_svc->waitResCnt); +} + +void tskm_svcsDump(TSKM_SVCS_CTX_t* p_svcs) { + uint32_t ii; + for (ii = 0; ii < p_svcs->svcNum; ii++) { + svcDump(&p_svcs->svcList[ii]); + } +} + diff --git a/systemservice/task_manager/server/src/tskm_main.cpp b/systemservice/task_manager/server/src/tskm_main.cpp new file mode 100644 index 00000000..33c10fa7 --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_main.cpp @@ -0,0 +1,727 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "tskm_main.h" +#include <stdio.h> +#include <string.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <errno.h> +#include <sys/inotify.h> +#include <getopt.h> +#include <system_service/ss_services.h> +#include <native_service/ns_version_if.h> +#include <native_service/ns_np_service_protocol.h> +#include <system_service/ss_system_if.h> +#include <system_service/ss_version.h> +#include <system_service/ss_templates.h> +#include <native_service/frameworkunified_dispatcher.h> +#include <other_service/rpc.h> +#include <system_service/resm.h> + +#include "tskm_data_init_local.h" +#include "tskm_port_pf.h" +#include "tskm_port_subsys.h" +#include "tskm_debug.h" +#include "tskm_util.h" +#include "tskm_srvr.h" +#include "tskm_comm.h" +#include "tskm_watch.h" +#include "system_service/tskm_local_type.h" +#include "system_service/tskm_xml_data.h" +#include "tskm_state.h" + +#define TSKM_DATA_KEY "TSKM_KEY" + +TSKM_STATIC TSKM_MAIN_CTX_t g_mainCtx; // Main context + +TSKM_STATIC BOOL s_isVupMode = FALSE; + +CFrameworkunifiedVersion g_FrameworkunifiedVersion(MAJORNO, MINORNO, REVISION); + +// For NsLog +FRAMEWORKUNIFIEDLOGPARAM g_FrameworkunifiedLogParams = { +FRAMEWORKUNIFIEDLOGOPTIONS, { +ZONE_TEXT_10, ZONE_TEXT_11, ZONE_TEXT_12, +ZONE_TEXT_13, ZONE_TEXT_14, ZONE_TEXT_15, +ZONE_TEXT_16, ZONE_TEXT_17, ZONE_TEXT_18, +ZONE_TEXT_19, ZONE_TEXT_20, ZONE_TEXT_21, +ZONE_TEXT_22, ZONE_TEXT_23, ZONE_TEXT_24, +ZONE_TEXT_25, ZONE_TEXT_26, ZONE_TEXT_27, +ZONE_TEXT_28, ZONE_TEXT_29, ZONE_TEXT_30, +ZONE_TEXT_31 }, FRAMEWORKUNIFIEDLOGZONES }; + +EFrameworkunifiedStatus OnFinishLoadFile(HANDLE hApp) { // LCOV_EXCL_START 6: Because the condition cannot be set + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + int ret; + TSKM_MAIN_CTX_t* p_main = &g_mainCtx; + TSKM_EVENT_INFO_t ev; + + ret = tskm_pf_nvFileRead(hApp, &p_main->nvInfo); + if (ret != 0) { + TSKM_ASSERT(0); + } + + // issure INI_INITCOMP_NVM_ACCESS + bzero(&ev, sizeof(ev)); + ev.event = TSKM_EV_PRI_REP_WAKEUP_COMP; + ev.errCode = TSKM_E_OK; + ev.prm.repWakeupComp.compId = INI_INITCOMP_NVM_ACCESS; + tskm_handleEvent(p_main, &ev); + + return l_eStatus; +} +// LCOV_EXCL_STOP + +EFrameworkunifiedStatus onDataInitRequest(HANDLE hApp) { + TSKM_ERR_t l_tskmRet = TSKM_E_OK; + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx(); + + TSKM_PRINTF(TSKM_LOG_API, "%s()", __FUNCTION__) + + if (p_main->bootInfo.startupReason == epswfINVALID) { + // Before issuing FrameworkunifiedOnStart = Requests before TaskManager became Availabile are not accepted + TSKM_ASSERT(0); + l_tskmRet = TSKM_E_STATE; + } else { + T_SS_SM_START_DataStructType bootInfo(epswfIGN_ACC, TRUE, + e_SS_SM_DATA_RESET_MODE_USER, + epsssUNLOCK, epsstWARMSTART, + e_SS_SM_DRAM_BACKUP_OK, + e_SS_SM_RESET_STATUS_NONE, 0); + + T_SS_SM_START_ExtDataStructType extBootInfo; + + memcpy(&extBootInfo, &p_main->extBootInfo, sizeof(extBootInfo)); + + // After updating the program, + // FALSE is notified here because it is notified when data initialization I/F is called at startup + extBootInfo.isProgUpdated = FALSE; + + tskm_dataInitAll(&bootInfo, &extBootInfo); + } + + PCSTR l_senderName = FrameworkunifiedGetMsgSrc(hApp); + if (NULL != l_senderName) { + HANDLE hSession = FrameworkunifiedMcOpenSender(hApp, l_senderName); + if (hSession == NULL) { + TSKM_ASSERT(0); + } else { + TSKM_ASSERT( + eFrameworkunifiedStatusOK + == FrameworkunifiedSendMsg(hSession, TSKM_DATAINIT_RESP, sizeof(l_tskmRet), + &l_tskmRet)); + TSKM_ASSERT(eFrameworkunifiedStatusOK == FrameworkunifiedMcClose(hSession)); + } + } + + return l_eStatus; +} + +EFrameworkunifiedStatus onTransStepRequest(HANDLE hApp) { // LCOV_EXCL_START 6:Because the condition cannot be set + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_MAIN_CTX_t* p_main = &g_mainCtx; + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + TSKM_EVENT_INFO_t ev; + bzero(&ev, sizeof(ev)); + + ev.event = TSKM_EV_LCL_REQ_TRANS_STEP; + ev.errCode = TSKM_E_OK; + tskm_handleEvent(p_main, &ev); + + return l_eStatus; +} +// LCOV_EXCL_STOP + +EFrameworkunifiedStatus OnResmAvailability(HANDLE hApp) { // LCOV_EXCL_START 6: Because the condition cannot be set + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_MAIN_CTX_t* p_main = &g_mainCtx; + + if (0 != strcmp(NTFY_ResourceMgr_Availability, FrameworkunifiedGetLastNotification(hApp))) { + TSKM_ASSERT(0); + } else if (FrameworkunifiedIsServiceAvailable(hApp)) { + // Availability = TRUE + + p_main->resmFd = tskm_sub_resmInit(); + if (-1 == p_main->resmFd) { + TSKM_ASSERT(0); + } + } + return eFrameworkunifiedStatusOK; +} +// LCOV_EXCL_STOP + +//************ NS Framework Callback : must implemet ****************** +EFrameworkunifiedStatus FrameworkunifiedOnInitialization(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + TSKM_PRINTF(TSKM_LOG_STATE, "+"); + + l_eStatus = FrameworkunifiedRegisterServiceAvailabilityNotification(hApp, NTFY_SS_TaskManager_Availability); + if (eFrameworkunifiedStatusOK != l_eStatus) { + TSKM_ASSERT(0); + } + + l_eStatus = FrameworkunifiedPublishServiceAvailability(hApp, FALSE); + if (eFrameworkunifiedStatusOK != l_eStatus) { + TSKM_ASSERT(0); + } + + l_eStatus = FrameworkunifiedAttachCallbackToDispatcher(hApp, FRAMEWORKUNIFIED_NS_NPSERVICE, + NPS_GET_PERS_FILE_ACK, + OnFinishLoadFile); + if (eFrameworkunifiedStatusOK != l_eStatus) { + TSKM_ASSERT(0); + } + + l_eStatus = FrameworkunifiedAttachCallbackToDispatcher(hApp, FRAMEWORKUNIFIED_ANY_SOURCE, + TSKM_DATAINIT_REQ, + onDataInitRequest); + if (eFrameworkunifiedStatusOK != l_eStatus) { + TSKM_ASSERT(0); + } + + l_eStatus = FrameworkunifiedAttachCallbackToDispatcher(hApp, FrameworkunifiedGetAppName(hApp), + TSKM_TRANS_STEP_REQ, + onTransStepRequest); + if (eFrameworkunifiedStatusOK != l_eStatus) { + TSKM_ASSERT(0); + } + + l_eStatus = FrameworkunifiedSubscribeNotificationWithCallback(hApp, NTFY_ResourceMgr_Availability, OnResmAvailability); + if (eFrameworkunifiedStatusOK != l_eStatus) { + TSKM_ASSERT(0); + } + + TSKM_PRINTF(TSKM_LOG_STATE, "-"); + + return l_eStatus; +} + +EFrameworkunifiedStatus FrameworkunifiedOnStart(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + TSKM_PRINTF(TSKM_LOG_STATE, "+"); + l_eStatus = OnStart(hApp); + TSKM_PRINTF(TSKM_LOG_STATE, "-"); + return l_eStatus; +} + +EFrameworkunifiedStatus FrameworkunifiedOnPreStart(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + TSKM_PRINTF(TSKM_LOG_STATE, "+"); + l_eStatus = OnStart(hApp); + TSKM_PRINTF(TSKM_LOG_STATE, "-"); + return l_eStatus; +} + +EFrameworkunifiedStatus FrameworkunifiedOnBackgroundStart(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + TSKM_PRINTF(TSKM_LOG_STATE, "+"); + l_eStatus = OnStart(hApp); + TSKM_PRINTF(TSKM_LOG_STATE, "-"); + return l_eStatus; +} + +EFrameworkunifiedStatus FrameworkunifiedOnStop(HANDLE hApp) { + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + TSKM_MAIN_CTX_t* p_main = &g_mainCtx; + // Returns Fail to send asynchronous STOP reply to SM + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail; + + TSKM_EVENT_INFO_t ev; + bzero(&ev, sizeof(ev)); + + ev.event = TSKM_EV_LCL_REQ_STOP; + ev.errCode = TSKM_E_OK; + tskm_handleEvent(p_main, &ev); + + p_main->isOnStopDone = TSKM_TRUE; + + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} + +EFrameworkunifiedStatus FrameworkunifiedOnPreStop(HANDLE hApp) { + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return eFrameworkunifiedStatusOK; +} + +EFrameworkunifiedStatus FrameworkunifiedOnBackgroundStop(HANDLE hApp) { + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return eFrameworkunifiedStatusOK; +} + +EFrameworkunifiedStatus FrameworkunifiedOnDestroy(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} + +EFrameworkunifiedStatus FrameworkunifiedOnDebugDump(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + TSKM_MAIN_CTX_t* p_main = &g_mainCtx; + TSKM_ERR_t l_tskmRet; + + // Call DebugDump of all running SVCs + l_tskmRet = tskm_svcsCallDebugDump(&p_main->svcs); + if (TSKM_E_OK != l_tskmRet) { + TSKM_ASSERT(0); + } + + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} + +EFrameworkunifiedStatus FrameworkunifiedCreateStateMachine(HANDLE hApp) { // LCOV_EXCL_START 6: Because the condition cannot be set + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} +// LCOV_EXCL_STOP + +/********************************************************* + * System start process + *********************************************************/ +EFrameworkunifiedStatus OnStart(const HANDLE hApp) { + TSKM_PRINTF(TSKM_LOG_STATE, "+"); + TSKM_MAIN_CTX_t* const p_main = &g_mainCtx; + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + if (p_main->isOnStartDone == TSKM_FALSE) { + T_SS_SM_START_DataStructType startupInfo; + TSKM_EVENT_INFO_t ev; + l_eStatus = ReadMsg<T_SS_SM_START_DataStructType>(hApp, startupInfo); + if (l_eStatus != eFrameworkunifiedStatusOK) { + TSKM_ASSERT(0); + } else { + memcpy(&p_main->bootInfo, &startupInfo, sizeof(T_SS_SM_START_DataStructType)); + } + + if (0 != tskm_sub_getExtBootInfo(&p_main->extBootInfo)) { + TSKM_ASSERT(0); + } + + tskm_dataInitAll(&p_main->bootInfo, &p_main->extBootInfo); + + tskm_svcsSetBootInfo(&p_main->svcs, &p_main->bootInfo, &p_main->extBootInfo); + p_main->isOnStartDone = TSKM_TRUE; + + l_eStatus = FrameworkunifiedPublishServiceAvailability(hApp, TRUE); + if (l_eStatus != eFrameworkunifiedStatusOK) { + TSKM_ASSERT(0); + } else { + TSKM_PRINTF(TSKM_LOG_STATE, "Availability TRUE"); + } + + // Issure INI_INITCOMP_ON_START + bzero(&ev, sizeof(ev)); + ev.event = TSKM_EV_PRI_REP_WAKEUP_COMP; + ev.errCode = TSKM_E_OK; + ev.prm.repWakeupComp.compId = INI_INITCOMP_ON_START; + tskm_handleEvent(p_main, &ev); + } + + TSKM_PRINTF(TSKM_LOG_STATE, "-"); + return l_eStatus; +} + +/********************************************************* + * Argument analysis process + *********************************************************/ +TSKM_STATIC EFrameworkunifiedStatus argParser(SI_32 argument, PCHAR argumentValue) { // LCOV_EXCL_START 6: for process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if ('v' == argument) { + s_isVupMode = TRUE; + } + + return eFrameworkunifiedStatusOK; +} +// LCOV_EXCL_STOP +/********************************************************* + * Creating process for TSKM internal context + *********************************************************/ +TSKM_STATIC void ctxCreate(TSKM_MAIN_CTX_t* p_main, int argc, char* argv[]) { + int ret; + EFrameworkunifiedStatus taskmanagerRet; + TSKM_ERR_t tskmRet; + FrameworkunifiedDefaultCallbackHandler cbFuncs; + FRAMEWORKUNIFIED_MAKE_DEFAULT_CALLBACK(cbFuncs); + CustomCommandLineOptions cmdLineOpt = { "v", NULL, argParser }; + + p_main->state = TSKM_ST_ACCOFF; + p_main->isOnStartDone = TSKM_FALSE; + + // Create dispatcher + taskmanagerRet = FrameworkunifiedCreateDispatcherWithoutLoop(SS_TASK_MANAGER, p_main->hApp, argc, + argv, &cbFuncs, TRUE, &cmdLineOpt); + if (eFrameworkunifiedStatusOK != taskmanagerRet) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + // LCOV_EXCL_START 6: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_PRINT(0, "%d", taskmanagerRet); + goto ERROR; + // LCOV_EXCL_STOP + } + + TSKM_PRINTF(TSKM_LOG_STATE, "s_isVupMode :%s", s_isVupMode ? "TRUE" : "FALSE"); + + taskmanagerRet = FrameworkunifiedGetDispatcherFD(p_main->hApp, &p_main->nsFd); + if (taskmanagerRet != eFrameworkunifiedStatusOK) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + // LCOV_EXCL_START 6: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_PRINT(0, "%d", taskmanagerRet); + exit(EXIT_FAILURE); + // LCOV_EXCL_STOP + } + + p_main->sigFd = tskm_pf_sysInit(); // Platform initialization + if (p_main->sigFd == -1) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + // LCOV_EXCL_LINE 6: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + p_main->iFd = inotify_init1(IN_CLOEXEC); + if (p_main->sigFd == -1) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + // LCOV_EXCL_LINE 6: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + // Obtain RESM FDs after waiting for Availability + p_main->resmFd = -1; + + tskmRet = tskm_srvSockCreate(TSKM_SOCKET_NAME, &p_main->sock); + TSKM_ERR_CHK(tskmRet, TSKM_E_OK, ERROR); // LCOV_EXCL_BR_LINE 6: For process initialization processing + + ret = tskm_pf_nvFileInit(p_main->hApp); + if (ret != 0) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + // LCOV_EXCL_START 6: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + ret = tskm_initServiceList(&p_main->svcs, p_main->iFd); // Service to be started + if (0 != ret) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + // LCOV_EXCL_START 6: For For process initialization process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + tskm_initWakeupCtx(&p_main->wakeup, s_isVupMode); // Gradual startup info + tskm_initDownCtx(&p_main->down, s_isVupMode); // Gradual termination info + return; + + // LCOV_EXCL_START 6: For process initialization processing + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + tskm_pf_exit(EXIT_FAILURE); + return; + // LCOV_EXCL_STOP +} + +/********************************************************* + * Get main context + *********************************************************/ +TSKM_MAIN_CTX_t* +tskm_getMainCtx(void) { + return &g_mainCtx; +} + +/********************************************************* + * Process initialization process (MAIN function sub) + *********************************************************/ +int Init_Process(int* rpcFd, int* sockFd, int* maxFd, fd_set* fds, TSKM_MAIN_CTX_t* p_main) { + int ret; + uint32_t ii; + + TSKM_SRV_CONNENT_LIST_t* p_connList = &p_main->sock.connList; + + FD_ZERO(fds); + + FD_SET(*rpcFd, fds); + *maxFd = TSKM_MAX(*rpcFd, *maxFd); // LCOV_EXCL_BR_LINE 6: For process initialization processing + + FD_SET(*sockFd, fds); + *maxFd = TSKM_MAX(*sockFd, *maxFd); // LCOV_EXCL_BR_LINE 6: For process initialization processing + + FD_SET(p_main->nsFd, fds); + *maxFd = TSKM_MAX(p_main->nsFd, *maxFd); // LCOV_EXCL_BR_LINE 6: For process initialization processing + + FD_SET(p_main->sigFd, fds); + *maxFd = TSKM_MAX(p_main->sigFd, *maxFd); // LCOV_EXCL_BR_LINE 6: For process initialization processing + + if (-1 != p_main->resmFd) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + // LCOV_EXCL_START 6: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FD_SET(p_main->resmFd, fds); + *maxFd = TSKM_MAX(p_main->resmFd, *maxFd); + // LCOV_EXCL_STOP + } + + for (ii = 0; ii < p_connList->num; ii++) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + // LCOV_EXCL_START 6: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_SRV_CONNENT_t* p_conn = &p_connList->conn[ii]; + FD_SET(p_conn->connFd, fds); + *maxFd = TSKM_MAX(p_conn->connFd, *maxFd); + // LCOV_EXCL_STOP + } + + TSKM_PRINTF(TSKM_LOG_FUNC, "SELECT IN"); + ret = select(*maxFd + 1, fds, NULL, NULL, NULL); + if (ret < 1) { + if (errno != EINTR) { + TSKM_ASSERT(0); + } + return ret; + } + TSKM_PRINTF(TSKM_LOG_FUNC, "SELECT OUT"); + return 0; +} + +/********************************************************* + * Receiving Messages from CONNECT Clients (MAIN Functions Sub) + *********************************************************/ +void Recv_Msg_FromConnectClient(fd_set* fds, TSKM_MAIN_CTX_t* p_main) { + uint32_t ii; + TSKM_SRV_CONNENT_LIST_t* p_connList = &p_main->sock.connList; + + // Messages from CONNECT clients + for (ii = 0; ii < p_connList->num; ii++) { + TSKM_SRV_CONNENT_t* p_conn = &p_connList->conn[ii]; + if (FD_ISSET(p_conn->connFd, fds)) { + TSKM_PRINTF(TSKM_LOG_FUNC, "connFd IN"); + TSKM_EVENT_INFO_t ev; + int ret; + ret = tskm_sockRcv(p_conn->connFd, &ev); + + if (ret < 0) { + TSKM_ASSERT(0); + } else { + TSKM_SVC_CTX_t* p_svc; + + if (ret == 0) { + // Closed Connection + TSKM_PRINTF(TSKM_LOG_STATE, "DISSCON pid:%d", p_conn->pid); + ev.event = TSKM_EV_PRI_REP_DISCONNECT; + ev.errCode = TSKM_E_OK; + ev.fromPid = p_conn->pid; + tskm_srvSockDisconnect(&p_main->sock, p_conn); + p_conn = NULL; // If the connection is lost, it cannot be referenced. + } + + p_svc = tskm_svcsGetSvcByPid(&p_main->svcs, ev.fromPid); + if (p_svc) { // Events from service + TSKM_ERR_t tskmRet; + tskmRet = tskm_svcEventHandle(p_svc, &ev); // Service handler + if (tskmRet != TSKM_E_OK) { + TSKM_ASSERT(0); + } + } + if (ev.event != TSKM_EV_NOP) { + tskm_handleEvent(p_main, &ev); // Main handler + } + } + TSKM_PRINTF(TSKM_LOG_FUNC, "connFd OUT"); + } + } +} + +/********************************************************* + * CONNECT Requests (MAIN Functions Sub) + *********************************************************/ +void Recv_Req_Connect(fd_set* fds, TSKM_MAIN_CTX_t* p_main, int sockFd) { + // CONNECT requests + if (FD_ISSET(sockFd, fds)) { + TSKM_PRINTF(TSKM_LOG_FUNC, "sockFd IN"); + + TSKM_SRV_CONNENT_t* conn; + conn = tskm_srvSockConnect(&p_main->sock); + if (conn == NULL) { + TSKM_ASSERT(0); + } else { + TSKM_SVC_CTX_t* p_svc; + TSKM_PRINTF(TSKM_LOG_STATE, "CONNECT pid:%d", conn->pid); + + p_svc = tskm_svcsGetSvcByPid(&p_main->svcs, conn->pid); + if (p_svc) { + TSKM_ERR_t tskmRet; + TSKM_EVENT_INFO_t ev; + + ev.event = TSKM_EV_PRI_REP_CONNECT; + ev.errCode = TSKM_E_OK; + ev.fromPid = conn->pid; + ev.prm.repConnect.connFd = conn->connFd; + + tskmRet = tskm_svcEventHandle(p_svc, &ev); // Service handler + if (tskmRet != TSKM_E_OK) { + TSKM_ASSERT(0); + } else if (ev.event != TSKM_EV_NOP) { + tskm_handleEvent(p_main, &ev); // Main hander + } + } + } + TSKM_PRINTF(TSKM_LOG_FUNC, "sockFd OUT"); + } +} + +/********************************************************* + * MAIN Function + *********************************************************/ +int main(int argc, char* argv[]) { + RPC_ID rpcId = TSKM_RPC_ID; + int rpcFd = 0; + int maxFd = 0; + int ret; + fd_set fds; + TSKM_MAIN_CTX_t* p_main = &g_mainCtx; + + // Logging setting + FRAMEWORKUNIFIED_SET_ZONES(); + + ctxCreate(p_main, argc, argv); // Initialize context + + tskm_sub_init(); // Initialize sub systems + + RPC_START_SECURE_SERVER(rpcId); + RPC_get_fd(rpcId, &rpcFd); + + uid_t uid[2]; + gid_t gid[2]; + + uid[0] = 0; + gid[0] = 0; + uid[1] = getuid(); + gid[1] = getgid(); + + if (RPC_OK != RPC_regist_credential(2, uid, 2, gid)) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); // LCOV_EXCL_LINE 6: For process initialization processing + } + + // Start periodic timer thread + ret = tskm_watch_startTimer(); + if (ret != 0) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); // LCOV_EXCL_LINE 6: For process initialization processing + } + + tskm_stateTransit(p_main, TSKM_ST_ACCOFF, TSKM_ST_ACCON); + + p_main->isExec = TSKM_TRUE; + while (p_main->isExec) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + int sockFd = p_main->sock.sockFd; + + // Initialization processing + if (Init_Process(&rpcFd, &sockFd, &maxFd, &fds, p_main) != 0) { // LCOV_EXCL_BR_LINE 6: For process initialization processing + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + continue; // LCOV_EXCL_LINE 6: For process initialization processing + } + + // RPC API + if (FD_ISSET(rpcFd, &fds)) { + RPC_process_API_request(rpcId); + } + + // Process termination signal + if (FD_ISSET(p_main->sigFd, &fds)) { + int count = 0; + + do { + TSKM_EVENT_INFO_t ev; + ev.event = TSKM_EV_SVC_REP_TERM; + + count++; + + ret = tskm_pf_cleanupProc(p_main->sigFd, &ev.fromPid, &ev.errCode); + if (ret == -1) { + TSKM_ASSERT(0); + break; + } + + TSKM_SVC_CTX_t* p_svc; + + p_svc = tskm_svcsGetSvcByPid(&p_main->svcs, ev.fromPid); + if (p_svc) { + TSKM_ERR_t tskmRet; + + tskmRet = tskm_svcEventHandle(p_svc, &ev); // Service handler + if (tskmRet != TSKM_E_OK) { + TSKM_ASSERT(0); + } + if (ev.event != TSKM_EV_NOP) { + tskm_handleEvent(p_main, &ev); // Main handler + } + } + } while (ret == 1 && count < 50); + } + + if (FD_ISSET(p_main->nsFd, &fds)) { + FrameworkunifiedDispatchProcessWithoutLoop(p_main->hApp); + } + + // EV from RESM + if (-1 != p_main->resmFd) { + if (FD_ISSET(p_main->resmFd, &fds)) { + TSKM_EVENT_INFO_t ev; + int ret; + ret = tskm_sub_resmRcv(&ev); + + if (-1 == ret) { + TSKM_ASSERT(0); + } else { + tskm_handleEvent(p_main, &ev); + } + } + } + + // Messages from connected clients + Recv_Msg_FromConnectClient(&fds, p_main); + + // CONNECT request + Recv_Req_Connect(&fds, p_main, sockFd); + } + + tskm_srvSockDestory(&p_main->sock); + + RPC_end(rpcId); + + FrameworkunifiedDestroyDispatcherWithoutLoop(p_main->hApp); + TSKM_PRINTF(TSKM_LOG_STATE, "tskm end"); + + sleep(TSKM_CFG_WAIT_SHUTDOWN); + return 0; +} // LCOV_EXCL_BR_LINE 10: Final line + diff --git a/systemservice/task_manager/server/src/tskm_port_pf.cpp b/systemservice/task_manager/server/src/tskm_port_pf.cpp new file mode 100644 index 00000000..f4272553 --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_port_pf.cpp @@ -0,0 +1,884 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "tskm_port_pf.h" +#include <pthread.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <pwd.h> +#include <fcntl.h> +#include <errno.h> +#include <signal.h> +#include <string.h> +#include <stdlib.h> + +#include <native_service/cl_process.h> +#include <native_service/cl_monitor.h> +#include <system_service/ss_services.h> +#include <system_service/ss_sm_client_if.h> + +#include "system_service/tskm_svc.h" +#include "tskm_debug.h" + +#define TSKM_PORTPF_IN() TSKM_PRINTF(TSKM_LOG_PORTPF, "%s:IN", __FUNCTION__) +#define TSKM_PORTPF_IN_ARG(format, ...) TSKM_PRINTF(TSKM_LOG_PORTPF, "%s:IN:" format, __FUNCTION__, __VA_ARGS__) +#define TSKM_PORTPF_OUT() TSKM_PRINTF(TSKM_LOG_PORTPF, "%s:OUT", __FUNCTION__) + +#define TSKM_PRIO_MIN 1 +#define TSKM_PRIO_MAX 99 +#define TSKM_PRIO_MIN_TSS -20 +#define TSKM_PRIO_MAX_TSS 19 + +#define TSKM_TMP_DIRECTORY "/tmp" +#define TSKM_TMP_TSKM_DIRECTORY TSKM_TMP_DIRECTORY "/tskm" +#define TSKM_TMP_NV_INFO_FILEPATH TSKM_TMP_TSKM_DIRECTORY "/nvInfo" + +#define TSKM_NPP_NV_FILE_TAG SS_TASK_MANAGER "/nvInfo" + +/********************************************************* + * user->uid/gid conversion + *********************************************************/ +TSKM_STATIC int cnvUserName2UidGid(const char *user, uid_t *uid, gid_t *gid) { + int ret = -1; + + if (0 == strcmp(user, "")) { + *uid = geteuid(); + *gid = getegid(); + } else { + static __thread size_t bufSize = 0; + static __thread char *buf = NULL; + struct passwd pwd; + struct passwd *result; + + if (0 == bufSize) { + struct stat statInfo; + + bufSize = -1; + + if (0 != stat("/etc/passwd", &statInfo) || 0 >= statInfo.st_size) { // LCOV_EXCL_START 8: Because buf is a static variable and cannot be passed test + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + // LCOV_EXCL_STOP + + bufSize = statInfo.st_size * 2; + + // Since TaskManager is a resident service, the area allocated here is expected to be released at process termination and is not explicitly released by free() + buf = (char *) malloc(sizeof(char) * bufSize); // NOLINT (runtime/printf) + if (NULL == buf) { // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function malloc + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); // LCOV_EXCL_LINE 5: Error branching of the standard-function malloc + goto ERROR; // LCOV_EXCL_LINE 5: Error branching of the standard-function malloc + } + } + + if (NULL == buf) { // LCOV_EXCL_BR_LINE 8: Because buf is a static variable and cannot be passed test + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); // LCOV_EXCL_LINE 8: Because buf is a static variable and cannot be passed test + goto ERROR; // LCOV_EXCL_LINE 8: Because buf is a static variable and cannot be passed test + } + + ret = getpwnam_r(user, &pwd, buf, bufSize, &result); + if (ret != 0 || result == NULL) { + TSKM_ASSERT_PRINT(0, "ret = %d[%s]", ret, user); + goto ERROR; + } + + *uid = pwd.pw_uid; + *gid = pwd.pw_gid; + } + + ret = 0; + + ERROR: + + return ret; +} + +/********************************************************* + * Convert Scheduling Policy Definitions Values (TSKM -> CL) + *********************************************************/ +TSKM_STATIC CL_ProcessSchedPolicy_t cnvTskmPolicy2ClPolicy( + TSKM_SVC_POLICY_t policy) { + switch (policy) { + case TSKM_SVC_POLICY_FIFO: + return CL_PROCESS_SCHED_POLICY_FIFO; + case TSKM_SVC_POLICY_TSS: + return CL_PROCESS_SCHED_POLICY_OTHER; + case TSKM_SVC_POLICY_RR: + return CL_PROCESS_SCHED_POLICY_RR; + default: + TSKM_ASSERT(0); + break; + } + return CL_PROCESS_SCHED_POLICY_OTHER; +} + +/********************************************************* + * Process priority valid value determination + *********************************************************/ +TSKM_STATIC int chkPrioValue(TSKM_SVC_POLICY_t policy, int prio) { + switch (policy) { + case TSKM_SVC_POLICY_FIFO: + case TSKM_SVC_POLICY_RR: + if ((TSKM_PRIO_MIN > prio) || (prio > TSKM_PRIO_MAX)) { + TSKM_ASSERT(0); + } + break; + case TSKM_SVC_POLICY_TSS: + default: + if ((TSKM_PRIO_MIN_TSS > prio) || (prio > TSKM_PRIO_MAX_TSS)) { + TSKM_ASSERT(0); + } + break; + } + + return prio; +} + +/********************************************************* + * COMMONLIB initialization (at system startup) + *********************************************************/ +int tskm_pf_sysInit() { + int fd = 0; + int ret = 0; + + TSKM_PORTPF_IN(); + + fd = CL_ProcessInit(); + if (fd == -1) { // LCOV_EXCL_BR_LINE 6: Error branching during process initialization + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); // LCOV_EXCL_LINE 6: Error branching during process initialization + goto ERROR; // LCOV_EXCL_LINE 6: Error branching during process initialization + } + + ret = CL_MonitorInit(CL_MONITOR_INIT_USER); + if (ret != 0) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + TSKM_ASSERT_ERRNO(0); + } + + TSKM_PORTPF_OUT(); + return fd; + // LCOV_EXCL_START 6: Error branching during process initialization + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return -1; + // LCOV_EXCL_STOP +} + +/********************************************************* + * COMMONLIB initialization (at process startup) + *********************************************************/ +int tskm_pf_procInit() { + TSKM_PORTPF_IN(); + // Originally called the _sys_Setup_CWORD64_API (NULL), but changed to empty function along to derete "_sys" + + TSKM_PORTPF_OUT(); + return 0; +} + +/********************************************************* + * Process startup + *********************************************************/ +pid_t tskm_pf_createProc(TSKM_SVC_ATTR_t* p_svcAttr) { + TSKM_PORTPF_IN(); + pid_t retPid = -1; + pid_t pid = -1; + + CL_ProcessAttr_t attr; + char procPath[255]; + char* procName; + uid_t setUid = 0; + gid_t setGid = 0; + + if (0 != CL_ProcessCreateAttrInit(&attr)) { // LCOV_EXCL_BR_LINE 6: Error branching during process initialization + // LCOV_EXCL_START 6: Error branching during process initialization + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + // Process name setting(from basename) + if (strlen(p_svcAttr->path) < sizeof(procPath)) { + strcpy(procPath, p_svcAttr->path); // NOLINT (runtime/printf) + } else { + TSKM_ASSERT(0); + goto ERROR; + } + + procName = basename(procPath); + if (strlen(procName) >= 16) { + TSKM_ASSERT(0); + procName[16] = '\0'; + } + + if (0 != CL_ProcessCreateAttrSetName(&attr, procName)) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + // LCOV_EXCL_START 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + if (0 != cnvUserName2UidGid(p_svcAttr->user, &setUid, &setGid)) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + // LCOV_EXCL_START 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + setUid = geteuid(); + setGid = getegid(); + // LCOV_EXCL_STOP + } + + if (0 != CL_ProcessCreateAttrSetUid(&attr, setUid)) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + // LCOV_EXCL_START 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + if (0 != CL_ProcessCreateAttrSetGid(&attr, setGid)) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + // LCOV_EXCL_START 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + // All are group leaders in order to recover to the child processes of the service + if (0 != CL_ProcessCreateAttrSetGroup(&attr, 1)) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + // LCOV_EXCL_START 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + if (0 != CL_ProcessCreateAttrSetCpuAssign(&attr, p_svcAttr->cpuAssign)) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + if (0 + != CL_ProcessCreateAttrSetSchedule( + &attr, cnvTskmPolicy2ClPolicy(p_svcAttr->policy), + chkPrioValue(p_svcAttr->policy, p_svcAttr->prio))) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + pid = CL_ProcessCreate(p_svcAttr->path, p_svcAttr->args, NULL, &attr); + if (pid == -1) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + retPid = pid; + ERROR: + + TSKM_PORTPF_OUT(); + return retPid; +} + +/********************************************************* + * Recover termination processes + *********************************************************/ +int tskm_pf_cleanupProc(int sigFd, pid_t* p_pid, TSKM_ERR_t* p_err) { + int ret; + CL_ProcessCleanupInfo_t info; + + ret = CL_ProcessCleanup(sigFd, &info); + if (ret != 0 && ret != 1) { + TSKM_ASSERT_PRINT(0, "ret = %d", ret); + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + TSKM_PRINTF(TSKM_LOG_STATE, "SVC TERM:pid:%d code:%d status:%d", info.pid, + info.code, info.status); + + switch (info.code) { + case CLD_STOPPED: + // Not comes here usually + TSKM_PRINTF(TSKM_LOG_STATE, "svc stoped\n"); + goto ERROR; + case CLD_TRAPPED: + // Comes here only during debugging + TSKM_PRINTF(TSKM_LOG_STATE, "svc traped\n"); + goto ERROR; + case CLD_CONTINUED: + // Not comes here usually + TSKM_PRINTF(TSKM_LOG_STATE, "svc continue\n"); + goto ERROR; + default: + break; + } + + *p_pid = info.pid; + *p_err = + (info.code != CLD_EXITED) ? TSKM_E_NG : + (info.code == CLD_EXITED && info.status != EXIT_SUCCESS) ? + TSKM_E_NG : TSKM_E_OK; + + if (TSKM_E_OK != *p_err) { + TSKM_PRINTF(TSKM_LOG_SYSTEMDATA, "SVC ERR TERM:pid:%d code:%d status:%d", + info.pid, info.code, info.status); + } + + return ret; + ERROR: return -1; +} + +/********************************************************* + * Force Terminating a Process Group + *********************************************************/ +int tskm_pf_terminateProcGroup(uint16_t pid) { + int ret; + pid_t pgid; + + pgid = getpgid(pid); + if (pgid < 0) { + TSKM_ASSERT(0); + goto ERROR; + } + + TSKM_PRINTF(TSKM_LOG_STATE, "TERM SVC GROUP:pid:%dpgid:%d", pid, pgid); + + ret = CL_ProcessEuthanizeGroup(pgid); + if (ret != 0) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + return 0; + ERROR: return -1; +} + +/********************************************************* + * Opening shared memory and trancating + *********************************************************/ +int tskm_pf_shmCreate_Open_Ftrn(const char* name, int32_t size, void** p_addr) { + int ret = 0; + int fd = 0; + + fd = shm_open(name, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); + if (fd == -1) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + ret = -1; // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + if (fd > 0) { // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + TSKM_ASSERT_ERRNO(close(fd) == 0); // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + } // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + return ret; // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + } + + ret = ftruncate(fd, size); + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + if (fd > 0) { // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + TSKM_ASSERT_ERRNO(close(fd) == 0); // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + } // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + return ret; // LCOV_EXCL_LINE 5: Checked in Death testing, but it is not reflected in the coverage and excluded. + } + + if (p_addr) { // LCOV_EXCL_BR_LINE 8: Because p_addr is set to NULL only + // LCOV_EXCL_START 8: Because p_addr is set to NULL only + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + // Not supported + TSKM_ASSERT_ERRNO(0); + ret = -1; + if (fd > 0) { + TSKM_ASSERT_ERRNO(close(fd) == 0); + } + return ret; + // LCOV_EXCL_STOP + } + + ret = 0; + if (fd > 0) { + TSKM_ASSERT_ERRNO(close(fd) == 0); + } + return ret; +} + +/********************************************************* + * Creating shared memory + *********************************************************/ +int tskm_pf_shmCreate(const char* name, int32_t size, void** p_addr) { + TSKM_PORTPF_IN_ARG("%s,%d", name, size); + struct stat statInfo; + int ret = -1; + + if (stat(name, &statInfo) == 0) { + TSKM_ASSERT_PRINT(0, "Already Exist %s", name); + ret = 0; // To be Succeeded + TSKM_PORTPF_OUT(); + return ret; + } + + ret = tskm_pf_shmCreate_Open_Ftrn(name, size, p_addr); + + TSKM_PORTPF_OUT(); + return ret; +} + +/********************************************************* + * Deleting shared memory + *********************************************************/ +int tskm_pf_shmDelete(const char* name) { + TSKM_PORTPF_IN_ARG("%s", name); + int ret = 0; + + if (0 != shm_unlink(name)) { + TSKM_ASSERT_ERRNO(0); + } + + TSKM_PORTPF_OUT(); + return ret; +} + +/********************************************************* + * Starting thread + *********************************************************/ +int tskm_pf_createThread(void* (*threadFunc)(void*), void* prm, + uint32_t priority, const char* threadName, + pthread_t* p_thId) { + TSKM_PORTPF_IN(); + + int ret; + CL_ThreadAttr_t cl_attr; + + ret = CL_ThreadCreateAttrInit(&cl_attr); + if (ret != 0) { // LCOV_EXCL_BR_LINE 6: For processing initializing process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); // LCOV_EXCL_LINE 6: For processing initializing process + goto ERROR; // LCOV_EXCL_LINE 6: For processing initializing process + } + + if (threadName) { + ret = CL_ThreadCreateAttrSetName(&cl_attr, threadName); + TSKM_ASSERT_ERRNO(ret == 0); + } + + ret = CL_ThreadCreate(p_thId, NULL, &cl_attr, threadFunc, prm); + if (ret != 0) { // LCOV_EXCL_BR_LINE 6: For processing initializing process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); // LCOV_EXCL_LINE 6: For processing initializing process + goto ERROR; // LCOV_EXCL_LINE 6: For processing initializing process + } + int sched_policy; + struct sched_param sparam; + + pthread_getschedparam(*p_thId, &sched_policy, &sparam); + + sparam.sched_priority = priority; + if ((priority != 0) && (sched_policy == SCHED_OTHER)) { + sched_policy = SCHED_FIFO; + } else if ((priority == 0) && (sched_policy != SCHED_OTHER)) { + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + sched_policy = SCHED_OTHER; // LCOV_EXCL_LINE 6: For processing initializing process + } + + ret = pthread_setschedparam(*p_thId, sched_policy, &sparam); + TSKM_ASSERT(ret == 0); + TSKM_PORTPF_OUT(); + return 0; + ERROR: return -1; +} +/********************************************************* + * Send Stop Complete Response + *********************************************************/ +int tskm_pf_sendStopCompResp() { + EFrameworkunifiedStatus l_eStatus; + TSKM_PORTPF_IN(); + + l_eStatus = SendInterfaceunifiedOnStopResponseToSystemManager(eFrameworkunifiedStatusOK); + if (l_eStatus != eFrameworkunifiedStatusOK) { + TSKM_ASSERT(0); + } + + TSKM_PORTPF_OUT(); + return 0; +} + +/********************************************************* + * ABORT + *********************************************************/ +int tskm_pf_abort() { + TSKM_PORTPF_IN(); + + TSKM_ASSERT(0); + sleep(1); // Sleep a little so that the logging at the time of abnormality may be interrupted + + // Issure SIGSEG + printf("%d\n", *(int *) 0); // NOLINT (readability/casting) + + TSKM_PORTPF_OUT(); + return 0; +} + +/********************************************************* + * EXIT + *********************************************************/ +int tskm_pf_exit(int status) { //LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_PORTPF_IN(); + + exit(status); + + TSKM_PORTPF_OUT(); + return 0; +} +// LCOV_EXCL_STOP + +/********************************************************* + * TOUCH + *********************************************************/ +int tskm_pf_touch(char* path) { + TSKM_PORTPF_IN(); + int fd; + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + TSKM_ASSERT_ERRNO(close(fd) == 0); + TSKM_PORTPF_OUT(); + return 0; + ERROR: + return -1; +} + +/********************************************************* + * Touch + *********************************************************/ +int tskm_pf_mkTouchFileName(pid_t pid, char name[32]) { + TSKM_PORTPF_IN(); + + sprintf(name, "/tmp/tskm_touch%d", pid); // NOLINT (runtime/printf) + + TSKM_PORTPF_OUT(); + return 0; +} + +/********************************************************* + * Read file + *********************************************************/ +static ssize_t readFile(const char* filePath, void* l_buf, ssize_t bufSize) { + int fd = -1; + ssize_t readSize, totalReadSize = 0; + char *p_buf = (char*) l_buf; // NOLINT (readability/casting) + fd = open(filePath, O_RDONLY); + if (fd == -1) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + do { + readSize = read(fd, p_buf, bufSize); + if (readSize == -1) { + if (errno == EINTR) { + continue; + } else { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + } else if (readSize == 0) { + break; + } + + p_buf += readSize; + bufSize -= readSize; + totalReadSize += readSize; + } while (bufSize > 0); + + ERROR: if (fd != -1) { + close(fd); + } + + return totalReadSize; +} + +/********************************************************* + * Write to file + *********************************************************/ +static ssize_t writeFile(const char *filePath, const void* l_buf, + ssize_t bufSize) { + int ret = -1; + int fd = -1; + + const char *p_buf = (const char*) l_buf; + + ssize_t writeSize, totalWriteSize = 0; + + fd = open(filePath, O_RDWR | O_TRUNC | O_CREAT, S_IRWXU); + if (fd == -1) { // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function open() + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); // LCOV_EXCL_LINE 5: Error branching of the standard-function open() + goto ERROR; // LCOV_EXCL_LINE 5: Error branching of the standard-function open() + } + + do { + writeSize = write(fd, p_buf, bufSize); + if (writeSize == -1) { // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function write() + // LCOV_EXCL_START 5: Error branching of the standard-function write() + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if (errno == EINTR) { + continue; + } else { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + // LCOV_EXCL_STOP + } else if (writeSize == 0) { // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function write() + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + break; // LCOV_EXCL_LINE 5: Error branching of the standard-function write() + } + p_buf += writeSize; + bufSize -= writeSize; + totalWriteSize += writeSize; + } while (bufSize > 0); // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function write() + + ret = fsync(fd); + if (ret == -1) { // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function fsync() + // LCOV_EXCL_START 5: Error branching of the standard-function fsync() + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + ERROR: if (fd != -1) { // LCOV_EXCL_BR_LINE 5: Error branching of the standard-function open() + close(fd); + } + + return totalWriteSize; +} + +/********************************************************* + * Checksum calculation + *********************************************************/ +static uint32_t calcCheckSum(const void* p_buf, size_t bufSize) { + int ii; + int blockNum; + uint32_t sum = 0; + uint32_t *p_calcBuf = (uint32_t*) p_buf; // NOLINT (readability/casting) + + blockNum = static_cast<int>(bufSize) / static_cast<int>(sizeof(uint32_t)); + + for (ii = 0; ii < blockNum; ii++) { + sum += p_calcBuf[ii]; + } + + return sum; +} + +/********************************************************* + * Checking files + *********************************************************/ +static TSKM_BOOL_t checkFile(const char *filePath) { // LCOV_EXCL_START 6: Because the condition cannot be set + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + uint32_t checkSum; + struct stat st; + ssize_t readSize; + TSKM_NV_INFO_t nvInfo; + TSKM_BOOL_t isFileOk = TSKM_FALSE; + + if (stat(filePath, &st) != 0) { + goto ERROR; + } + + readSize = readFile(filePath, &nvInfo, sizeof(TSKM_NV_INFO_t)); + if (readSize != sizeof(TSKM_NV_INFO_t)) { + TSKM_ASSERT(0); + goto ERROR; + } + + checkSum = calcCheckSum(&nvInfo, offsetof(TSKM_NV_INFO_t, footer.checkSum)); + + if (checkSum != nvInfo.footer.checkSum) { + TSKM_ASSERT(0); + goto ERROR; + } + + if (strncmp(nvInfo.header.version, TSKM_NV_STRUCT_VERSION, + sizeof(TSKM_NV_STRUCT_VERSION)) != 0) { + TSKM_ASSERT(0); + goto ERROR; + } + + isFileOk = TSKM_TRUE; + ERROR: return isFileOk; +} +// LCOV_EXCL_STOP +/********************************************************* + * Non-volatile file initialization (Including checksum write) + *********************************************************/ +static int initNvFile() { + int ii; + ssize_t writeSize; + TSKM_NV_INFO_t nvInfo; + + TSKM_STATIC_ASSERT(sizeof(TSKM_NV_INFO_t) == TSKM_NV_SIZE_ALL); + TSKM_STATIC_ASSERT( + offsetof(TSKM_NV_INFO_t, footer.checkSum) % sizeof(uint32_t) == 0); + + memset(&nvInfo, 0, sizeof(TSKM_NV_INFO_t)); + sprintf(nvInfo.header.version, TSKM_NV_STRUCT_VERSION); // NOLINT (readability/casting) + nvInfo.body.rsvSvcNum = 0; + for (ii = 0; ii < TSKM_SVC_RESERVE_MAX; ii++) { + nvInfo.body.rsvSvcs[ii] = TSKM_SVCID_NONE; + } + nvInfo.footer.checkSum = calcCheckSum( + &nvInfo, offsetof(TSKM_NV_INFO_t, footer.checkSum)); + + writeSize = writeFile(TSKM_TMP_NV_INFO_FILEPATH, &nvInfo, + sizeof(TSKM_NV_INFO_t)); + if (writeSize != sizeof(TSKM_NV_INFO_t)) { // LCOV_EXCL_BR_LINE 6: writeSize must be the size of TSKM_NV_INFO_t + // LCOV_EXCL_START 6: writeSize must be the size of TSKM_NV_INFO_t + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + return 0; + ERROR: return -1; +} + +/********************************************************* + * Non-volatile file initialization + *********************************************************/ +int tskm_pf_nvFileInit(HANDLE hApp) { + int ret = -1; + struct stat st; + EFrameworkunifiedStatus l_eStatus; + + if (stat(TSKM_TMP_TSKM_DIRECTORY, &st) != 0) { // LCOV_EXCL_BR_LINE 5:Standard C function return value + // LCOV_EXCL_START 5:Standard C function return value + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + ret = mkdir(TSKM_TMP_TSKM_DIRECTORY, S_IRWXU); + if (ret == -1) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + // LCOV_EXCL_STOP + } + + l_eStatus = FrameworkunifiedNPRegisterPersistentFile(hApp, TSKM_NPP_NV_FILE_TAG); + if (eFrameworkunifiedStatusOK != l_eStatus) { // LCOV_EXCL_BR_LINE 6: For processing initializing process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); // LCOV_EXCL_LINE 6: For processing initializing process + goto ERROR; // LCOV_EXCL_LINE 6: For processing initializing process + } + + l_eStatus = FrameworkunifiedNPLoadPersistentFile(hApp, TSKM_TMP_NV_INFO_FILEPATH, TSKM_NPP_NV_FILE_TAG); + if (eFrameworkunifiedStatusOK != l_eStatus) { // LCOV_EXCL_BR_LINE 6: For processing initializing process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); // LCOV_EXCL_LINE 6: For processing initializing process + goto ERROR; // LCOV_EXCL_LINE 6: For processing initializing process + } + + return 0; + ERROR: return -1; +} + +/********************************************************* + * Non-volatile file read + *********************************************************/ +int tskm_pf_nvFileRead(HANDLE hApp, TSKM_NV_INFO_t* p_nvInfo) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + NC_LoadPersistedAck l_tMsgAck; + ssize_t readSize; + TSKM_BOOL_t isTmpFileOk = TSKM_FALSE; + + if (sizeof(l_tMsgAck) != FrameworkunifiedGetMsgLength(hApp)) { + TSKM_ASSERT(0); + goto ERROR; + } else if (eFrameworkunifiedStatusOK != (l_eStatus = FrameworkunifiedGetMsgDataOfSize(hApp, &l_tMsgAck, sizeof(l_tMsgAck)))) { // LCOV_EXCL_BR_LINE 4: NSFW error case // NOLINT[whitespace/line_length] + // LCOV_EXCL_START 4: NSFW error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + if ((strncmp(l_tMsgAck.cTag, TSKM_NPP_NV_FILE_TAG, sizeof(TSKM_NPP_NV_FILE_TAG)) == 0) + && (eFrameworkunifiedStatusOK == l_tMsgAck.eStatus)) { + if (checkFile(TSKM_TMP_NV_INFO_FILEPATH) == TSKM_TRUE) { + isTmpFileOk = TSKM_TRUE; + } + } + + if (isTmpFileOk == TSKM_FALSE) { + int ret; + + ret = initNvFile(); + if (ret == -1) { // LCOV_EXCL_BR_LINE 6: must return ok + // LCOV_EXCL_START 6: must return ok + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + } + + readSize = readFile(TSKM_TMP_NV_INFO_FILEPATH, p_nvInfo, + sizeof(TSKM_NV_INFO_t)); + if (readSize != sizeof(TSKM_NV_INFO_t)) { // LCOV_EXCL_BR_LINE 6: readSize must be the size of TSKM_NV_INFO_t + // LCOV_EXCL_START 6: readSize must be the size of TSKM_NV_INFO_t + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + l_eStatus = FrameworkunifiedNPReleasePersistentFile(hApp, eFrameworkunifiedPersistOnShutdown, TSKM_NPP_NV_FILE_TAG, TSKM_TMP_NV_INFO_FILEPATH); + if (eFrameworkunifiedStatusOK != l_eStatus) { + TSKM_ASSERT(0); + } + + return 0; + ERROR: return -1; +} + +/********************************************************* + * Write non-volatile file (Including checksum) + *********************************************************/ +int tskm_pf_nvFileWrite(const TSKM_NV_INFO_t* p_nvInfo) { + ssize_t writeSize; + TSKM_NV_INFO_t nvInfo; + + memcpy(&nvInfo, p_nvInfo, sizeof(TSKM_NV_INFO_t)); + + nvInfo.footer.checkSum = calcCheckSum( + &nvInfo, offsetof(TSKM_NV_INFO_t, footer.checkSum)); + + writeSize = writeFile(TSKM_TMP_NV_INFO_FILEPATH, &nvInfo, + sizeof(TSKM_NV_INFO_t)); + if (writeSize != sizeof(TSKM_NV_INFO_t)) { // LCOV_EXCL_BR_LINE 6: writeSize must be the size of TSKM_NV_INFO_t + // LCOV_EXCL_START 6: writeSize must be the size of TSKM_NV_INFO_t + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + return -1; + // LCOV_EXCL_STOP + } + return 0; +} // LCOV_EXCL_BR_LINE 10: Final line diff --git a/systemservice/task_manager/server/src/tskm_port_subsys.cpp b/systemservice/task_manager/server/src/tskm_port_subsys.cpp new file mode 100644 index 00000000..cfdec490 --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_port_subsys.cpp @@ -0,0 +1,297 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "tskm_port_subsys.h" +#include <pthread.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +#include <native_service/cl_monitor.h> +#include <system_service/ss_sm_client_if.h> +#include <system_service/resm.h> +//#include <stub/ss_diag.h> +#include <string> + +#include "agl_thread.h" + +#include "tskm_main.h" +#include "tskm_debug.h" +#include "tskm_util.h" +#include "tskm_port_pf.h" + + +#ifndef oops_name2pid + #define oops_name2pid(processname) syscall(OOPSTRACE_SYSCALL, 17, processname) +#endif + + +typedef struct { + CL_MonitorSearch_t clMonSearch; + uint32_t resmId; // Session ID of RESM +} SUB_SYS_CTX_t; + +static SUB_SYS_CTX_t g_sub; + +/****************************************************************** + * Subsystem initialization + ******************************************************************/ +int tskm_sub_init(void) { + int clRet; + SUB_SYS_CTX_t* p_ctx = &g_sub; + + clRet = CL_MonitorSearchInit(&p_ctx->clMonSearch); + if (clRet != 0) { // LCOV_EXCL_BR_LINE 6: For processing intializing process + // LCOV_EXCL_START 6:For processing initializing process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP 6: For processing initializing process + } + + return 0; + // LCOV_EXCL_START 6:For processing initializing process + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return 1; + // LCOV_EXCL_STOP +} + +/****************************************************************** + * Subsystem termination + ******************************************************************/ +int tskm_sub_term(void) { + int ret; + SUB_SYS_CTX_t* p_ctx = &g_sub; + + ret = CL_MonitorSearchDestroy(&p_ctx->clMonSearch); + if (ret != 0) { + TSKM_ASSERT_ERRNO(0); + } + + return 0; +} +/********************************************************* + * REBOOT + *********************************************************/ +void tskm_sub_reboot(const TSKM_ERROR_REBOOT_t* p_info) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + TSKM_ASSERT(0); + + l_eStatus = SendCpuResetRequestToSystemManager( + e_SS_SM_CPU_RESET_REASON_GENERIC_ERR, p_info->log.messageStr); + if (eFrameworkunifiedStatusOK != l_eStatus) { + TSKM_ASSERT(0); + } +} + +/********************************************************* + * REBOOT NORMAL + *********************************************************/ +void tskm_sub_reboot_normal(void) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + l_eStatus = SendCpuResetRequestToSystemManager( + e_SS_SM_CPU_RESET_REASON_NORMAL); + if (l_eStatus != eFrameworkunifiedStatusOK) { + TSKM_ASSERT(0); + } +} + +/********************************************************* + * LOGGING + *********************************************************/ +void tskm_sub_logging(const TSKM_LOGGING_INFO_t* p_info) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + eSMUserLogType l_eType; + + switch (p_info->type) { + case TSKM_LOGGING_TYPE_GRP_RELAUNCH: + l_eType = e_SS_SM_CAPTURE_GROUP_RELAUNCH; + break; + case TSKM_LOGGING_TYPE_MODULE_LOGS: + default: + l_eType = e_SS_SM_CAPTURE_MODULE_LOGS; + break; + } + + l_eStatus = SendUserInvokedLoggingRequestToSystemManager(l_eType, + p_info->messageStr); + if (eFrameworkunifiedStatusOK != l_eStatus) { + TSKM_ASSERT(0); + } +} + +/********************************************************* + * DEBUG DUMP + *********************************************************/ +void tskm_sub_debugDumpRes(BOOL bIsNeedSvcName, const char *p_dumpMsg) { + if (bIsNeedSvcName) { // LCOV_EXCL_BR_LINE 8: As the bIsNeedSvcName is set to FALSE only + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + SSDEBUGDUMP("%s", p_dumpMsg); // LCOV_EXCL_LINE 8: As the bIsNeedSvcName is set to FALSE only + } else { + SSDEBUGDUMP_RAW("%s", p_dumpMsg); + } +} + +/********************************************************* + * EXT BOOT INFO + *********************************************************/ +int tskm_sub_getExtBootInfo(T_SS_SM_START_ExtDataStructType *p_info) { + EFrameworkunifiedStatus l_eStatus; + T_SS_SM_START_ExtDataStructType extStartupInfo; + + l_eStatus = GetInterfaceunifiedOnStartExtInfo(extStartupInfo); + if (l_eStatus != eFrameworkunifiedStatusOK) { + TSKM_ASSERT(0); + goto ERROR; + } + + memcpy(p_info, &extStartupInfo, sizeof(extStartupInfo)); + + return 0; + ERROR: return -1; +} + +/********************************************************* + * Service Error Monitoring Check + *********************************************************/ +TSKM_HUNG_INFO_t* +tskm_sub_searchHungSvcs() { + int ret; + TSKM_HUNG_INFO_t *p_hungList = NULL; + SUB_SYS_CTX_t* p_ctx = &g_sub; + + ret = CL_MonitorSearchTimeout(&p_ctx->clMonSearch); + if (ret == -1) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + if (0 < p_ctx->clMonSearch.entry_num) { + int ii; + + TSKM_PRINTF(TSKM_LOG_DEBUG, "TimeoutSvcNum = %d", + p_ctx->clMonSearch.entry_num); + + if (NULL == p_ctx->clMonSearch.entry_list) { + TSKM_ASSERT(0); + goto ERROR; + } + + p_hungList = (TSKM_HUNG_INFO_t *) malloc( // NOLINT (readability/casting) + sizeof(TSKM_HUNG_INFO_t) * (p_ctx->clMonSearch.entry_num + 1)); + if (p_hungList == NULL) { // LCOV_EXCL_BR_LINE 5: malloc's error case. + // LCOV_EXCL_START 5: Checked in Death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_ERRNO(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + for (ii = 0; ii < p_ctx->clMonSearch.entry_num; ii++) { + p_hungList[ii].pid = p_ctx->clMonSearch.entry_list[ii].pid; + p_hungList[ii].type = p_ctx->clMonSearch.entry_list[ii].type; + } + // set "-1" to pid at the end of list. + p_hungList[p_ctx->clMonSearch.entry_num].pid = -1; + } + + ERROR: return p_hungList; +} + +/********************************************************* + * RESM Initialization + *********************************************************/ +int tskm_sub_resmInit(void) { // LCOV_EXCL_START 6: Because the condition cannot be set + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + int redmFd; + SUB_SYS_CTX_t* p_ctx = &g_sub; + RESM_ERR_t resmRet = RESM_E_OK; + RESM_REQ_EVENT_t ev; + + int pid; + + resmRet = RESM_Open(NULL, &(p_ctx->resmId)); + if (RESM_E_OK != resmRet) { + TSKM_ASSERT(0); + +#warning RESM backtrace disabled, because 'print_backtrace_pid' not support. +#if 0 + // Backtrace outoutput of the RESM + pid = oops_name2pid(MN_SS_RESOURCEMGR); + if(pid > 0){ + TSKM_ASSERT(-1 != print_backtrace_pid(pid)); + }else{ + TSKM_PRINTF(TSKM_LOG_ERROR, "ERR : oops_name2pid %d , err:%d, msg:%s", + pid, errno, strerror(errno)); + } +#endif + + goto ERROR; + } + + resmRet = RESM_GetEventFd(p_ctx->resmId, &redmFd); + if (RESM_E_OK != resmRet) { + TSKM_ASSERT(0); + goto ERROR; + } + + ev.reqEvent = RESM_EV_MEM; + ev.prm.restMemThresh = 512; // Threshold(BYTE) + + resmRet = RESM_ReqEvent(p_ctx->resmId, &ev); + if (RESM_E_OK != resmRet) { + TSKM_ASSERT(0); + goto ERROR; + } + + return redmFd; + ERROR: return -1; +} +// LCOV_EXCL_STOP +/********************************************************* + * Get EV of RESM + *********************************************************/ +int tskm_sub_resmRcv(TSKM_EVENT_INFO_t* p_ev) { + SUB_SYS_CTX_t* p_ctx = &g_sub; + RESM_ERR_t resmRet = RESM_E_OK; + RESM_EV_t evFlag; + + resmRet = RESM_GetEvent(p_ctx->resmId, &evFlag); + if (RESM_E_OK != resmRet) { + TSKM_ASSERT(0); + goto ERROR; + } + + if (RESM_EV_MEM != evFlag) { + TSKM_ASSERT(0); + goto ERROR; + } + + TSKM_PRINTF(TSKM_LOG_ERROR, "Detect LowMem"); + + p_ev->event = TSKM_EV_LCL_REP_LOWMEM; + + return 0; + ERROR: return -1; +} + +int tskm_sub_setWakeupOrder(const char* p_order) { + // Under consideration + return 0; +} // LCOV_EXCL_BR_LINE 10: Gcov constraints (last row) diff --git a/systemservice/task_manager/server/src/tskm_shutdown.cpp b/systemservice/task_manager/server/src/tskm_shutdown.cpp new file mode 100644 index 00000000..1699f90f --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_shutdown.cpp @@ -0,0 +1,242 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "tskm_shutdown.h" +#include "tskm_util.h" +#include "tskm_debug.h" +#include "tskm_state.h" + +#include "tskm_port_pf.h" +#include "tskm_port_subsys.h" +#include "tskm_gstep.h" + + +/********************************************************* + * Get context of gradual startup + *********************************************************/ +TSKM_STATIC TSKM_GSTEP_CTX_t* +gstepGetDownCtx(TSKM_MAIN_CTX_t* p_main) { + return &p_main->down; +} + +/********************************************************* + * System shutdown completed + *********************************************************/ +TSKM_STATIC void downFinish(TSKM_MAIN_CTX_t* p_main) { + int ret; + + // Send FrameworkunifiedOnStop response + ret = tskm_pf_sendStopCompResp(); + if (ret != 0) { // LCOV_EXCL_BR_LINE 8: As ret never becomes non-zero + // LCOV_EXCL_START 8: As ret never becomes non-zero + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + // LCOV_EXCL_STOP + } + + // Terminate subsystems + tskm_sub_term(); +} +/********************************************************* + * Challenge for a transition to the next state + *********************************************************/ +TSKM_STATIC void tryTransNextState(TSKM_MAIN_CTX_t* p_main) { + TSKM_GSTEP_CTX_t* p_down; + TSKM_GSTEP_t* p_current; + + p_down = gstepGetDownCtx(p_main); + p_current = gstepGetCurrent(p_down); + + if (gstepIsLast(p_down)) { + TSKM_SVC_WAIT_STATE_t waitState; + + // Checking the ShutdownWaitSVC termination status + waitState = tskm_svcsGetSvcTermWaitState(&p_main->svcs); + switch (waitState) { + case TSKM_SVC_WAIT_BOTH: + break; + case TSKM_SVC_WAIT_TRANSIENT: + if ((p_down->compState & INI_TERMCOMP_RESIDENT) != INI_TERMCOMP_RESIDENT) { + // Nonresident service termination processing + if (TSKM_E_OK != tskm_svcsAvtiveSvcTerm(&p_main->svcs)) { // LCOV_EXCL_BR_LINE 5: tskm_svcsAvtiveSvcTerm is always return TSKM_E_OK + // LCOV_EXCL_START 5: tskm_svcsAvtiveSvcTerm is always return TSKM_E_OK + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + // LCOV_EXCL_STOP + } + // Nonresident SVC terminated and started + p_down->compState |= INI_TERMCOMP_RESIDENT; + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "TERM COMP :%s(%#llx)", + tskm_convTermCompId2Str(INI_TERMCOMP_RESIDENT), + INI_TERMCOMP_RESIDENT); + } + break; + case TSKM_SVC_WAIT_NONE: + // Complete ShutdownWaitSVC + // Nonresident SVC terminated and started + p_down->compState |= INI_TERMCOMP_TRANSIENT; + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "TERM COMP :%s(%#llx)", + tskm_convTermCompId2Str(INI_TERMCOMP_TRANSIENT), + INI_TERMCOMP_TRANSIENT); + break; + default: + // LCOV_EXCL_START 8: As it does not meet the default requirements + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + break; + // LCOV_EXCL_STOP + } + } + + if (tskm_svcsIsWaiting(&p_main->svcs) == TSKM_FALSE && // No waiting services + ((p_down->compState & p_current->nextTransCond) + == p_current->nextTransCond)) { // Event completion condition + if (gstepIsLast(p_down)) { + tskm_stateTransit(p_main, TSKM_ST_ACCON, TSKM_ST_ACCOFF); + } else { + tskm_stateTransit(p_main, TSKM_ST_DOWN, TSKM_ST_DOWN); + } + } +} + +/********************************************************* + * Check and process gradual termination request + *********************************************************/ +TSKM_ERR_t tskm_entryDown_Check_Req(TSKM_MAIN_CTX_t* p_main, + TSKM_GSTEP_t* p_current) { + uint32_t ii; + + if (0 == p_current->reqNum) { + EFrameworkunifiedStatus l_eStatus; + + // If there is no gradual termination request, check the transition to the next step. + l_eStatus = FrameworkunifiedSendSelf(p_main->hApp, TSKM_TRANS_STEP_REQ, 0, NULL); + if (eFrameworkunifiedStatusOK != l_eStatus) { // LCOV_EXCL_BR_LINE 5: Checked in death testing, but it is not reflected in the coverage and excluded + // LCOV_EXCL_START 5: Checked in death testing, but it is not reflected in the coverage and excluded + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + return TSKM_E_NG; + // LCOV_EXCL_STOP + } + + } else { + // Gradual termination request + for (ii = 0; ii < p_current->reqNum; ii++) { + TSKM_ERR_t tskmRet; + TSKM_GSTEP_REQ_INFO_t* p_req = &p_current->reqList[ii]; + TSKM_SVC_CTX_t* p_svc = tskm_svcsGetSvcBySvcId(&p_main->svcs, + p_req->svcId); + + tskmRet = tskm_svcDownRequest(p_svc, p_req); + if (tskmRet != TSKM_E_OK) { + TSKM_ASSERT(0); + } + } + } + return TSKM_E_OK; +} + +/********************************************************* + * Gradual termination entry process + *********************************************************/ +TSKM_ERR_t tskm_entryDown(TSKM_MAIN_CTX_t* p_main) { + TSKM_FUNC_IN(); + + TSKM_GSTEP_CTX_t* p_down; + TSKM_GSTEP_t* p_current; + + p_main->state = TSKM_ST_DOWN; + p_down = gstepGetDownCtx(p_main); + p_current = gstepGetCurrent(p_down); + if (p_current == NULL) { // LCOV_EXCL_BR_LINE 200:p_current can not be null + // LCOV_EXCL_START 200:p_current can not be null + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "DOWN GSTEP:%d", p_down->gstepIdx); + + if (tskm_entryDown_Check_Req(p_main, p_current) == TSKM_E_NG) { // LCOV_EXCL_BR_LINE 200:the function of tskm_entryDown_Check_Req can not be TSKM_E_NG at this case // NOLINT(whitespace/line_length) + // LCOV_EXCL_START 200:tskm_entryDown_Check_Req can not be TSKM_E_NG at this case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + goto ERROR; + // LCOV_EXCL_STOP + } + + if (p_current->nextTransCond) { + TSKM_PRINTF(TSKM_LOG_STATE, "WAIT COMP:%s(%llx)", + tskm_convTermCompId2Str(p_current->nextTransCond), + p_current->nextTransCond); + } + + TSKM_FUNC_OUT(); + return TSKM_E_OK; + + ERROR: tskm_pf_abort(); + return TSKM_E_NG; +} + +/********************************************************* + * Gradual termination exit process + *********************************************************/ +TSKM_ERR_t tskm_exitDown(TSKM_MAIN_CTX_t* p_main) { + TSKM_FUNC_IN(); + TSKM_GSTEP_CTX_t* p_down; + + p_down = gstepGetDownCtx(p_main); + + if (gstepIsLast(p_down)) { + TSKM_PRINTF(TSKM_LOG_STATE, "DOWN FINISH"); + downFinish(p_main); // Final process of termination + } + + changeNextStep(p_down); // Proceed to the next step + + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} +/********************************************************* + * Hander during gradual termination + *********************************************************/ +TSKM_ERR_t tskm_handleDown(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev) { + TSKM_FUNC_IN(); + + switch (p_ev->event) { + case TSKM_EV_PRI_REP_DOWN_COMP: // Notificaton for event completion in termination + { + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "TERM COMP :%s(%#llx) from:%d", + tskm_convTermCompId2Str(p_ev->prm.repDownComp.compId), + p_ev->prm.repDownComp.compId, p_ev->fromPid); + TSKM_GSTEP_CTX_t* p_down = gstepGetDownCtx(p_main); + p_down->compState |= p_ev->prm.repDownComp.compId; + tryTransNextState(p_main); + } + break; + case TSKM_EV_LCL_CHG_SVC_STATE: // Service state change + tryTransNextState(p_main); + break; + case TSKM_EV_LCL_REQ_TRANS_STEP: //Step transition request + tryTransNextState(p_main); + break; + default: + tskm_handleAccon(p_main, p_ev); + break; + } + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} // LCOV_EXCL_BR_LINE 10: Final line + diff --git a/systemservice/task_manager/server/src/tskm_state.cpp b/systemservice/task_manager/server/src/tskm_state.cpp new file mode 100644 index 00000000..b7770901 --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_state.cpp @@ -0,0 +1,452 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "tskm_state.h" +#include <stdlib.h> +#include "tskm_util.h" +#include "tskm_debug.h" +#include "tskm_wakeup.h" +#include "tskm_shutdown.h" +#include "tskm_port_subsys.h" +#include "tskm_port_pf.h" + + + +// Prototype declarations +TSKM_ERR_t tskm_entryAccoff(TSKM_MAIN_CTX_t* p_main); +TSKM_ERR_t tskm_exitAccoff(TSKM_MAIN_CTX_t* p_main); +TSKM_ERR_t tskm_handleAccoff(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev); + +TSKM_ERR_t tskm_entryAccon(TSKM_MAIN_CTX_t* p_main); +TSKM_ERR_t tskm_exitAccon(TSKM_MAIN_CTX_t* p_main); + +TSKM_ERR_t tskm_entryRunning(TSKM_MAIN_CTX_t* p_main); +TSKM_ERR_t tskm_exitRunning(TSKM_MAIN_CTX_t* p_main); +TSKM_ERR_t tskm_handleRunning(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev); + +// Structures of state transitioning callback functions +typedef TSKM_ERR_t (*entry_state_t)(TSKM_MAIN_CTX_t* p_main); +typedef TSKM_ERR_t (*exit_state_t)(TSKM_MAIN_CTX_t* p_main); +typedef TSKM_ERR_t (*event_handler_t)(TSKM_MAIN_CTX_t* p_main, + TSKM_EVENT_INFO_t* p_ev); + +typedef struct { + TSKM_STATE_t state; + entry_state_t entry_func; + exit_state_t exit_func; + event_handler_t event_handler; +} state_func_table_t; + +// State specific function table +static const state_func_table_t state_func_table[] = { { TSKM_ST_ACCOFF, + tskm_entryAccoff, tskm_exitAccoff, tskm_handleAccoff }, { TSKM_ST_ACCON, + tskm_entryAccon, tskm_exitAccon, tskm_handleAccon }, { TSKM_ST_WAKEUP, + tskm_entryWakeup, tskm_exitWakeup, tskm_handleWakeup }, { TSKM_ST_RUNNING, + tskm_entryRunning, tskm_exitRunning, tskm_handleRunning }, { TSKM_ST_DOWN, + tskm_entryDown, tskm_exitDown, tskm_handleDown }, { 0, 0, 0, 0 } }; + +/**************************************************** + * ACC OFF ENTRY + ****************************************************/ +TSKM_ERR_t tskm_entryAccoff(TSKM_MAIN_CTX_t* p_main) { + TSKM_FUNC_IN(); + p_main->state = TSKM_ST_ACCOFF; + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} + +/************************************************************************* + * ACC OFF EXIT + *************************************************************************/ +TSKM_ERR_t tskm_exitAccoff(TSKM_MAIN_CTX_t* p_main) { + // Do nothing + // Called only once at startup + return TSKM_E_OK; +} + +/************************************************************************* + * ACC OFF HANDLE + *************************************************************************/ +TSKM_ERR_t tskm_handleAccoff(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev) { + TSKM_ASSERT(0); // Do nothing + return TSKM_E_OK; +} + +/************************************************************************* + * ACC ON ENTRY + *************************************************************************/ +TSKM_ERR_t tskm_entryAccon(TSKM_MAIN_CTX_t* p_main) { + TSKM_FUNC_IN(); + p_main->state = TSKM_ST_ACCON; + + tskm_entryState(p_main, TSKM_ST_WAKEUP); + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} + +/************************************************************************* + * ACC ON HANDLE + *************************************************************************/ +TSKM_ERR_t tskm_exitAccon(TSKM_MAIN_CTX_t* p_main) { + TSKM_FUNC_IN(); + + TSKM_ERR_t tskmRet = TSKM_E_OK; + + if (TSKM_SUB_STATE_IS(p_main, TSKM_ST_WAKEUP)) { // LCOV_EXCL_BR_LINE 8:Because the condition is never true + // LCOV_EXCL_START 8: Because the condition is never true + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + tskmRet = tskm_exitState(p_main, TSKM_ST_WAKEUP); + // LCOV_EXCL_STOP + } else if (TSKM_SUB_STATE_IS(p_main, TSKM_ST_RUNNING)) { // LCOV_EXCL_BR_LINE 8: Because the condition is never true + // LCOV_EXCL_START 8: Because the condition is never true + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + tskmRet = tskm_exitState(p_main, TSKM_ST_RUNNING); + // LCOV_EXCL_STOP + } else if (TSKM_SUB_STATE_IS(p_main, TSKM_ST_DOWN)) { // LCOV_EXCL_BR_LINE 8:Because the condition is never false + tskmRet = tskm_exitState(p_main, TSKM_ST_DOWN); + } + + TSKM_ERR_CHK(tskmRet, TSKM_E_OK, ERROR); // LCOV_EXCL_BR_LINE 8: Because the tskmRet does not change to NG + p_main->isExec = TSKM_FALSE; + ERROR: + TSKM_FUNC_OUT(); + return tskmRet; +} + +/************************************************************************* + * POLL EVENT HANDLE + *************************************************************************/ +TSKM_STATIC void checkHungSvcs(TSKM_MAIN_CTX_t* p_main) { + int ret; + TSKM_HUNG_INFO_t *p_hungSvcList = NULL; + + p_hungSvcList = tskm_sub_searchHungSvcs(); + if (p_hungSvcList != NULL) { + int hungSvcNum = 0; + + while (p_hungSvcList[hungSvcNum].pid != -1) { + pid_t pid = p_hungSvcList[hungSvcNum].pid; + + TSKM_SVC_CTX_t* p_svc = tskm_svcsGetSvcByPid(&p_main->svcs, pid); + + if (p_svc) { + TSKM_PRINTF(TSKM_LOG_SYSTEMDATA, "HUNG SVC(%s:%d), TYPE(%d)", + p_svc->attr->name, pid, p_hungSvcList[hungSvcNum].type); + + ret = tskm_pf_terminateProcGroup(static_cast<uint16_t>(pid)); + if (ret != 0) { + TSKM_ASSERT(0); + } + + } else { + TSKM_PRINTF(TSKM_LOG_WARN, "UNKNOWN HUNG SVC(%d), TYPE(%d)", pid, + p_hungSvcList[hungSvcNum].type); + } + + hungSvcNum++; + } + + free(p_hungSvcList); + } + + return; +} + +#define AVAILABILITY_CHECK_RETRY_COUNT 24 + +/************************************************************************* + * CHECK SVC AVAILABILITY + *************************************************************************/ +TSKM_STATIC void checkSvcAvailability(TSKM_MAIN_CTX_t* p_main) { + for (uint32_t ii = 0; ii < p_main->svcs.svcNum; ii++) { + if (p_main->svcs.svcList[ii].state == TSKM_SVC_RUNNING + && !p_main->svcs.svcList[ii].isAvailable) { + p_main->svcs.svcList[ii].watchCnt++; + TSKM_ASSERT_PRINT(0, "WAIT AVAILABILITY FOR %s(%d) (%d/%d)", + p_main->svcs.svcList[ii].attr->name, + p_main->svcs.svcList[ii].pid, + p_main->svcs.svcList[ii].watchCnt, + AVAILABILITY_CHECK_RETRY_COUNT); + + if (p_main->svcs.svcList[ii].watchCnt > AVAILABILITY_CHECK_RETRY_COUNT) { + int ret; + + ret = tskm_pf_terminateProcGroup(static_cast<uint16_t>(p_main->svcs.svcList[ii].pid)); + if (ret != 0) { + TSKM_ASSERT(0); + } + } + } + } + + return; +} + +/************************************************************************* + * POLL EVENT HANDLE + *************************************************************************/ +TSKM_STATIC void handlePolling(TSKM_MAIN_CTX_t* p_main) { + checkHungSvcs(p_main); + + checkSvcAvailability(p_main); + + return; +} + +/************************************************************************* + * LOW MEMORY EVENT HANDLE + *************************************************************************/ +TSKM_STATIC void handleLowMem(TSKM_MAIN_CTX_t* p_main) { + TSKM_ERR_t tskmRet = TSKM_E_OK; + + tskmRet = tskm_svcsCallLowMem(&p_main->svcs); + if (TSKM_E_OK != tskmRet) { + TSKM_ASSERT(0); + } + + return; +} +/************************************************************************* + * ACC ON HANDLE + *************************************************************************/ +TSKM_ERR_t tskm_handleAccon(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev) { + TSKM_FUNC_IN(); + + switch (p_ev->event) { + case TSKM_EV_LCL_REQ_SDUMP: + tskm_svcsDump(&p_main->svcs); + break; + // LCOV_EXCL_STOP + case TSKM_EV_LCL_REP_POLLING: + TSKM_PRINTF(TSKM_LOG_DEBUG, "watch timer polling event."); + handlePolling(p_main); + break; + default: + TSKM_PRINTF(TSKM_LOG_STATE, "IGNORE:%s(%d)", + tskm_convEvent2Str(p_ev->event), p_ev->event); + break; + } + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} + +/************************************************************************* + * BOOT RESERVED SERVICES + *************************************************************************/ +static int bootRsvSvcs(TSKM_MAIN_CTX_t* p_main) { + uint32_t ii; + TSKM_ERR_t tskmRet = TSKM_E_OK; + uint8_t rsvSvcNum = p_main->nvInfo.body.rsvSvcNum; + TSKM_SVCID_t* p_rsvSvcs = p_main->nvInfo.body.rsvSvcs; + + TSKM_PRINTF(TSKM_LOG_STATE, "RSV SVC NUM = %d", rsvSvcNum); + + for (ii = 0; ii < rsvSvcNum; ii++) { + TSKM_GSTEP_REQ_INFO_t req = { 0 }; + TSKM_SVC_CTX_t* p_svc; + + p_svc = tskm_svcsGetSvcBySvcId(&p_main->svcs, p_rsvSvcs[ii]); + if (p_svc == NULL) { + TSKM_ASSERT(0); + continue; + } + + tskmRet = tskm_svcExec(p_svc); + if (TSKM_E_OK != tskmRet) { + TSKM_ASSERT(0); + continue; + } + if (p_svc->state == TSKM_SVC_WAITCONNECT) { + // In the state waiting for execution + req.svcId = p_rsvSvcs[ii]; + req.localStep = TSKM_LSTEP_ALL; + tskmRet = tskm_svcWakeupRequest(p_svc, &req); + if (TSKM_E_OK != tskmRet) { // LCOV_EXCL_BR_LINE 8: Because the condition is never true + // LCOV_EXCL_START 8: Because the condition is never true + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT_PRINT(0, "tskmRet = %d", tskmRet); + continue; + // LCOV_EXCL_STOP + } + } + } + + if (rsvSvcNum != 0) { + int ret; + + for (ii = 0; ii < TSKM_SVC_RESERVE_MAX; ii++) { + p_rsvSvcs[ii] = TSKM_SVCID_NONE; + } + + p_main->nvInfo.body.rsvSvcNum = 0; + + ret = tskm_pf_nvFileWrite(&p_main->nvInfo); + if (ret == -1) { // LCOV_EXCL_BR_LINE 8: Because the tskm_pf_nvFileWrite() only returns a return value of 0 + // LCOV_EXCL_START 8:Because the condition is never true + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + } + + return 0; + // LCOV_EXCL_START 8: Because the tskm_pf_nvFileWrite() only returns a return value of 0 + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return -1; + // LCOV_EXCL_STOP +} + +/************************************************************************* + * RUN ENTRY + *************************************************************************/ +TSKM_ERR_t tskm_entryRunning(TSKM_MAIN_CTX_t* p_main) { + int ret; + + TSKM_FUNC_IN(); + p_main->state = TSKM_ST_RUNNING; + + ret = bootRsvSvcs(p_main); + if (ret != 0) { // LCOV_EXCL_BR_LINE 8: Because bootRsvSvcs returns only a return value of 0 + // LCOV_EXCL_START 8: Because bootRsvSvcs returns only a return value of 0 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + // LCOV_EXCL_STOP + } + + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} + +/************************************************************************* + * RUN EXIT + *************************************************************************/ +TSKM_ERR_t tskm_exitRunning(TSKM_MAIN_CTX_t* p_main) { + TSKM_FUNC_IN(); + + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} + +/************************************************************************* + * RUN HANDLE + *************************************************************************/ +TSKM_ERR_t tskm_handleRunning(TSKM_MAIN_CTX_t* p_main, + TSKM_EVENT_INFO_t* p_ev) { + TSKM_FUNC_IN(); + + switch (p_ev->event) { + case TSKM_EV_LCL_REQ_STOP: + tskm_stateTransit(p_main, TSKM_ST_RUNNING, TSKM_ST_DOWN); + break; + case TSKM_EV_LCL_REP_LOWMEM: + handleLowMem(p_main); + break; + default: + tskm_handleAccon(p_main, p_ev); + break; + } + + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} + +/************************************************************************* + * Get transition table + *************************************************************************/ +static const state_func_table_t* +tskm_getFuncTable(TSKM_STATE_t state) { + int i; + for (i = 0; state_func_table[i].state != 0; i++) { + if (state == state_func_table[i].state) { + return &state_func_table[i]; + } + } + TSKM_ASSERT(0); + return &state_func_table[0]; +} + +/************************************************************************* + * State transition instructions + *************************************************************************/ +TSKM_ERR_t tskm_stateTransit(TSKM_MAIN_CTX_t* p_main, TSKM_STATE_t srcState, + TSKM_STATE_t dstState) { + TSKM_ERR_t tskmRet; + TSKM_PRINTF(TSKM_LOG_STATE, "STATE:%s(%s) -> %s", + tskm_convState2Str(srcState), tskm_convState2Str(p_main->state), + tskm_convState2Str(dstState)); + + tskmRet = tskm_exitState(p_main, srcState); + TSKM_ERR_CHK(tskmRet, TSKM_E_OK, ERROR); // LCOV_EXCL_BR_LINE 8: Because TSKM_ERR_CHK does not specify a goto ERROR condition + tskmRet = tskm_entryState(p_main, dstState); + TSKM_ERR_CHK(tskmRet, TSKM_E_OK, ERROR); // LCOV_EXCL_BR_LINE 8: Because TSKM_ERR_CHK does not specify a goto ERROR condition + return TSKM_E_OK; + + // LCOV_EXCL_START 8: Because TSKM_ERR_CHK does not specify a goto ERROR condition + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return TSKM_E_NG; + // LCOV_EXCL_STOP +} + +/************************************************************************* + * Event handler + *************************************************************************/ +void tskm_handleEvent(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev) { + event_handler_t handlerFunc; + handlerFunc = tskm_getFuncTable(p_main->state)->event_handler; + handlerFunc(p_main, p_ev); +} + +/**************************************************** + * State transitioning entry process + ****************************************************/ +TSKM_ERR_t tskm_entryState(TSKM_MAIN_CTX_t* p_rec, TSKM_STATE_t state) { + TSKM_ERR_t ret = TSKM_E_NG; + const state_func_table_t* p_table = tskm_getFuncTable(state); + + TSKM_PRINTF(TSKM_LOG_DEBUG, "entry :%s", tskm_convState2Str(state)); + if (p_table->entry_func) { // LCOV_EXCL_BR_LINE 8: Because p_table->entry_func never becomes 0 + ret = ((*p_table->entry_func)(p_rec)); + } else { + // LCOV_EXCL_START 8: Because p_table->entry_func never becomes 0 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + // LCOV_EXCL_STOP + } + return ret; +} + +/**************************************************** + * State transitioning exit process + ****************************************************/ +TSKM_ERR_t tskm_exitState(TSKM_MAIN_CTX_t* p_rec, TSKM_STATE_t state) { + TSKM_ERR_t ret = TSKM_E_NG; + const state_func_table_t* p_table = tskm_getFuncTable(state); + + if (p_table->exit_func) { // LCOV_EXCL_BR_LINE 8: Because p_table->exit_func never becomes 0 + ret = (*p_table->exit_func)(p_rec); + } else { + // LCOV_EXCL_START 8: Because p_table->exit_func never becomes 0 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + // LCOV_EXCL_STOP + } + TSKM_PRINTF(TSKM_LOG_DEBUG, "exit :%s", tskm_convState2Str(state)); + return ret; +} // LCOV_EXCL_BR_LINE 10: Final line + diff --git a/systemservice/task_manager/server/src/tskm_svc.cpp b/systemservice/task_manager/server/src/tskm_svc.cpp new file mode 100644 index 00000000..2f9abc1e --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_svc.cpp @@ -0,0 +1,970 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "system_service/tskm_svc.h" +#include <string.h> +#include <stdlib.h> +#include <sys/inotify.h> +#include <errno.h> + +#include <native_service/ns_np_service_if.h> +#include <string> + +#include "tskm_debug.h" +#include "tskm_util.h" +#include "tskm_port_pf.h" +#include "tskm_port_subsys.h" +#include "tskm_comm.h" + + +/********************************************************* + * Is the target event of the service handler? + + *********************************************************/ +TSKM_STATIC TSKM_BOOL_t isSvcEvent(const TSKM_EVENT_INFO_t* p_ev) { + switch (p_ev->event) { + case TSKM_EV_PRI_REP_CONNECT: + case TSKM_EV_PRI_REP_DISCONNECT: + case TSKM_EV_PRI_RES_WAKEUP: + case TSKM_EV_PRI_RES_DOWN: + case TSKM_EV_PRI_RES_DEBUGDUMP: + case TSKM_EV_PRI_REQ_EXIT: + case TSKM_EV_SVC_REP_TERM: + return TSKM_TRUE; + break; + default: + break; + } + return TSKM_FALSE; +} + +/********************************************************* + * Get service context + *********************************************************/ +TSKM_STATIC TSKM_SVC_CTX_t* +getSvcCtxBySvcId(TSKM_SVCS_CTX_t* p_svcs, TSKM_SVCID_t svcId) { + uint32_t ii; + + for (ii = 0; ii < p_svcs->svcNum; ii++) { + if (p_svcs->svcList[ii].attr->svcId == svcId) { + return &p_svcs->svcList[ii]; + } + } + TSKM_ASSERT(0); + return NULL; +} + +/********************************************************* + * Get service context + *********************************************************/ +TSKM_STATIC TSKM_SVC_CTX_t* +getSvcCtxByPid(TSKM_SVCS_CTX_t* p_svcs, pid_t pid) { + uint32_t ii; + + for (ii = 0; ii < p_svcs->svcNum; ii++) { + if (p_svcs->svcList[ii].pid == pid) { + return &p_svcs->svcList[ii]; + } + } + return NULL; +} + +/********************************************************* + * Get service context + *********************************************************/ +TSKM_STATIC TSKM_SVC_CTX_t* +getSvcCtxByName(TSKM_SVCS_CTX_t* p_svcs, const char *p_name) { // LCOV_EXCL_START 6: Because the condition cannot be set + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + uint32_t ii; + + for (ii = 0; ii < p_svcs->svcNum; ii++) { + if (0 + == strncmp(p_svcs->svcList[ii].attr->name, p_name, + strlen(p_svcs->svcList[ii].attr->name))) { + return &p_svcs->svcList[ii]; + } + } + return NULL; +} +// LCOV_EXCL_STOP +/********************************************************* + * Issuing a start request to the service + *********************************************************/ +TSKM_STATIC TSKM_ERR_t wakeupRequest(TSKM_SVC_CTX_t* p_svc, + TSKM_GSTEP_REQ_INFO_t* p_req) { + TSKM_EVENT_INFO_t ev; + int ret; + bzero(&ev, sizeof(ev)); + + ev.event = TSKM_EV_PRI_REQ_WAKEUP; + ev.errCode = TSKM_E_OK; + ev.prm.reqWakeup.svcId = p_svc->attr->svcId; + ev.prm.reqWakeup.localStep = p_req->localStep; + ev.prm.reqWakeup.isDynamic = + (p_svc->attr->lifeCycle == TSKM_SVC_LC_DYNAMIC) ? TSKM_TRUE : TSKM_FALSE; + // Since there is no startup in the P_CWORD72_ but only communication in the ALL/LAST, + // the startup information is optimized including the startup information in the communication of the WakeupRequest. + memcpy(&ev.prm.reqWakeup.bootInfo, &p_svc->bootInfo, + sizeof(ev.prm.reqWakeup.bootInfo)); + memcpy(&ev.prm.reqWakeup.extBootInfo, &p_svc->extBootInfo, + sizeof(ev.prm.reqWakeup.extBootInfo)); + + ret = tskm_sockSend(p_svc->connFd, &ev); + if (ret <= 0) { + TSKM_ASSERT(0); + goto ERROR; + } + p_svc->waitResCnt++; + p_svc->state = TSKM_SVC_WAKEUP; + + return TSKM_E_OK; + ERROR: return TSKM_E_NG; +} + +/********************************************************* + * Touch services and extend EXIT timeouts + *********************************************************/ +TSKM_STATIC TSKM_ERR_t reqTouch(TSKM_SVC_CTX_t* p_svc) { +#define TSKM_BUF_LEN ( 4 * ( sizeof(struct inotify_event) ) ) /* read size */ + TSKM_ERR_t funcRet = TSKM_E_NG; + char touchFileName[32]; + BOOL isNeedRetry = FALSE; + + int iFd = p_svc->iFd; + int wd = 0; + + TSKM_EVENT_INFO_t ev; + int ret; + bzero(&ev, sizeof(ev)); + + // Create monitoring files + tskm_pf_mkTouchFileName(p_svc->pid, touchFileName); + if (0 != tskm_pf_touch(touchFileName)) { + goto ERROR; + } + + // Synchronize by iNortify + wd = inotify_add_watch(iFd, touchFileName, IN_DELETE_SELF); + if (wd == -1) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + + // Send Touch request + ev.event = TSKM_EV_PRI_REQ_TOUCH; + ev.errCode = TSKM_E_OK; + ret = tskm_sockSend(p_svc->connFd, &ev); + if (ret <= 0) { + // Immediately after the nonresident service process terminates, since the TaskManager service status is other than DORMANT + // (mainly DOWN), the socket may be discarded and communication may fail, so retry + funcRet = TSKM_E_RETRY; + TSKM_PRINTF(TSKM_LOG_WARN, "ret = %d", ret); + goto ERROR; + } + + // Wait for Touch completion + while (1) { + int maxFd = 0; + int ret; + fd_set fds; + FD_ZERO(&fds); + struct timeval timeout = { 0 }; + timeout.tv_sec = TSKM_CFG_TOUCH_TIMEOUT; + + FD_SET(iFd, &fds); + maxFd = iFd; + + ret = select(maxFd + 1, &fds, NULL, NULL, &timeout); + if (ret == 0) { + TSKM_ASSERT_PRINT(0, "TIMEOUT:%s", touchFileName); // Timeout occurs + isNeedRetry = TRUE; + break; + } else if (ret < 1) { + if (errno == EINTR) { + continue; + } else { + TSKM_ASSERT(0); + goto ERROR; + } + } + + if (FD_ISSET(iFd, &fds)) { + int length; + uint8_t buf[TSKM_BUF_LEN]; + + length = static_cast<int>(read(iFd, buf, TSKM_BUF_LEN)); + if (length < 0) { + TSKM_ASSERT_ERRNO(0); + goto ERROR; + } + struct inotify_event *event = (struct inotify_event *) buf; + if (event->mask & IN_DELETE_SELF) { + TSKM_PRINTF(TSKM_LOG_STATE, "TouchOK"); + wd = 0; + // When a file is deleted, the association with the monitoring target is automatically released and inotify_rm_watch is no longer needed. + break; + } else { + TSKM_ASSERT_PRINT(0, "%x", event->mask); + } + } + } + + if (isNeedRetry) { + funcRet = TSKM_E_RETRY; + } else { + funcRet = TSKM_E_OK; + } + + ERROR: if (wd > 0) { + TSKM_ASSERT_ERRNO(0 == inotify_rm_watch(iFd, wd)) + } + + if (access(touchFileName, F_OK) == 0) { + // Timeout care + unlink(touchFileName); + } + + return funcRet; +} + +/********************************************************* + * Availability Monitoring Callbacks for Services + *********************************************************/ +EFrameworkunifiedStatus OnSvcAvailability(HANDLE hApp) { // LCOV_EXCL_START 6: Because the condition cannot be set + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + PCSTR availabilityName; + TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx(); + TSKM_SVC_CTX_t* p_svc; + + availabilityName = FrameworkunifiedGetLastNotification(hApp); + + std::string str = availabilityName; + +// unsigned int position; +// if (std::string::npos != (position = static_cast<unsigned int>(str.find("/Availability", 0)))) { + ssize_t position; + if (0 <= (position = str.find("/Availability", 0))) { + str.erase(position, position + strlen("/Availability")); + } + + p_svc = getSvcCtxByName(&p_main->svcs, str.c_str()); + if (p_svc) { + p_svc->isAvailable = FrameworkunifiedIsServiceAvailable(hApp) ? TSKM_TRUE : TSKM_FALSE; + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "%s Availability %s", p_svc->attr->name, + (p_svc->isAvailable == TSKM_TRUE) ? "TRUE" : "FALSE"); + } + + return eFrameworkunifiedStatusOK; +} +// LCOV_EXCL_STOP +/********************************************************* + * Starting Availability Monitoring of Services + *********************************************************/ +TSKM_STATIC TSKM_ERR_t startWatchAvailability(TSKM_SVC_CTX_t* p_svc) { + TSKM_ERR_t funcRet = TSKM_E_OK; + + // LCOV_EXCL_BR_START 8: Since the condition is checked by the caller, it is not true. + if (p_svc->attr->type == TSKM_SVC_TYPE_UNKNONW) { + // LCOV_EXCL_BR_STOP + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + p_svc->isAvailable = TSKM_TRUE; // LCOV_EXCL_LINE 8: Since the condition is checked by the caller, it is not true. + } else { + EFrameworkunifiedStatus taskmanagerStatus; + TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx(); + SS_String availabilityName = p_svc->attr->name; + + availabilityName.append("/Availability"); + + taskmanagerStatus = FrameworkunifiedSubscribeNotificationWithCallback(p_main->hApp, + availabilityName.c_str(), + OnSvcAvailability); + if (eFrameworkunifiedStatusOK != taskmanagerStatus) { + TSKM_ASSERT(0); + funcRet = TSKM_E_NG; + } + } + + return funcRet; +} + +/********************************************************* + * Service startup sub + *********************************************************/ +void svcExec_Process(TSKM_SVC_CTX_t* p_svc) { + TSKM_ERR_t funcRet; + + if (p_svc->attr->type == TSKM_SVC_TYPE_NATIVE) { + p_svc->state = TSKM_SVC_WAITCONNECT; + TSKM_PRINTF(TSKM_LOG_DEBUG, "[ST:%d] WAIT_EXEC", p_svc->pid); + funcRet = startWatchAvailability(p_svc); + if (TSKM_E_OK != funcRet) { + TSKM_ASSERT(0); + p_svc->isAvailable = TSKM_TRUE; + } + } else { + p_svc->state = TSKM_SVC_RUNNING; + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "[ST:%d] RUN", p_svc->pid); + p_svc->isAvailable = TSKM_TRUE; + } + return; +} + +/********************************************************* + * Service startup main + *********************************************************/ +TSKM_STATIC TSKM_ERR_t svcExec(TSKM_SVC_CTX_t* p_svc) { + TSKM_ERR_t funcRet = TSKM_E_NG; + pid_t pid; + + if (p_svc == NULL) { // LCOV_EXCL_BR_LINE 6:double check + // LCOV_EXCL_START 6: double check + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP + } + + if (p_svc->state == TSKM_SVC_DISABLE) { + // Prohibited startup + TSKM_ASSERT(0); + return TSKM_E_STATE; + } else if (p_svc->state == TSKM_SVC_WAITCONNECT) { + return TSKM_E_OK; + } else if (p_svc->state != TSKM_SVC_DORMANT) { + // Already started + funcRet = reqTouch(p_svc); + if (TSKM_E_OK != funcRet) { + TSKM_PRINTF(TSKM_LOG_WARN, "funcRet = %d", funcRet); + goto ERROR; + } + return TSKM_E_OK; + } + + pid = tskm_pf_createProc(p_svc->attr); + if (pid <= 0) { + TSKM_ASSERT(0); + goto ERROR; + } + TSKM_PRINTF(TSKM_LOG_STATE, "EXEC %s:%d", p_svc->attr->name, pid); + + p_svc->pid = pid; + p_svc->waitReqCnt = 0; + + // Startup service + svcExec_Process(p_svc); + + funcRet = TSKM_E_OK; + ERROR: return funcRet; +} + +/********************************************************* + * Issuing a start request to the service + *********************************************************/ +TSKM_STATIC TSKM_ERR_t svcWakeupRequest(TSKM_SVC_CTX_t* p_svc, + TSKM_GSTEP_REQ_INFO_t* p_req) { + if (p_svc == NULL || p_svc->state == TSKM_SVC_DISABLE) { // LCOV_EXCL_BR_LINE 6: Since this function has always been called after checking // NOLINT(whitespace/line_length) + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return TSKM_E_STATE; // LCOV_EXCL_LINE 6: Since this function has always been called after checking + } else if (p_svc->state == TSKM_SVC_WAITCONNECT) { + // Remember it once and issue a request when the CONNECT completes. + p_svc->request[p_svc->waitReqCnt] = *p_req; + p_svc->waitReqCnt++; + } else { + TSKM_ERR_t tskmRet; + tskmRet = wakeupRequest(p_svc, p_req); + TSKM_ERR_CHK_DFT; + } + + return TSKM_E_OK; + ERROR: return TSKM_E_NG; +} + +/********************************************************* + * Service reboot processing + *********************************************************/ +TSKM_STATIC TSKM_ERR_t svcErrTermPost(TSKM_SVC_CTX_t* p_svc) { + TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx(); + + TSKM_PRINTF(TSKM_LOG_SYSTEMDATA, "ERR TERM SVC(%s:%d)", p_svc->attr->name, + p_svc->pid); + + if (p_svc->attr->lifeCycle == TSKM_SVC_LC_ALWAYS || (p_svc->errTermCnt > p_svc->attr->retryCnt && (uint32_t) -1 != p_svc->attr->retryCnt)) { // NOLINT(whitespace/line_length) + TSKM_ERROR_REBOOT_t rebootInfo; + + TSKM_ASSERT(0); + memset(&rebootInfo, 0, sizeof(TSKM_ERROR_REBOOT_t)); + rebootInfo.type = TSKM_ERROR_REBOOT_NORMAL; + snprintf(rebootInfo.log.messageStr, TSKM_LOGGING_MSG_STR_SIZE, + "TaskManager:SVC ErrTerm"); + tskm_sub_reboot(&rebootInfo); + } else { + TSKM_LOGGING_INFO_t logInfo; + logInfo.type = TSKM_LOGGING_TYPE_MODULE_LOGS; + + snprintf(logInfo.messageStr, TSKM_LOGGING_MSG_STR_SIZE, + "TaskManager:SVC ErrTerm"); + tskm_sub_logging(&logInfo); + + if (p_svc->attr->lifeCycle == TSKM_SVC_LC_ALWAYS_RECOVERABLE) { + TSKM_ERR_t ret; + TSKM_GSTEP_REQ_INFO_t req = { 0 }; + + ret = svcExec(p_svc); + + if (TSKM_E_OK != ret) { + TSKM_ASSERT_PRINT(0, "ret = %d", ret); + goto ERROR; + } else if (p_svc->state == TSKM_SVC_WAITCONNECT) { + // In the state waiting for execution + req.svcId = p_svc->attr->svcId; + req.localStep = TSKM_LSTEP_ALL; + ret = svcWakeupRequest(p_svc, &req); + if (TSKM_E_OK != ret) { + TSKM_ASSERT_PRINT(0, "ret = %d", ret); + goto ERROR; + } + } + } + } + + return TSKM_E_OK; + ERROR: return TSKM_E_NG; +} + +/********************************************************* + * Connection handler + * ret:TRUE SVC status changed + * ret:FALSE SVC status not changed + *********************************************************/ +TSKM_STATIC TSKM_BOOL_t connectHandle(TSKM_SVC_CTX_t* p_svc, + const TSKM_EVENT_INFO_t* p_inEv) { + uint32_t ii; + + TSKM_ASSERT(p_svc->state == TSKM_SVC_WAITCONNECT); + + p_svc->connFd = p_inEv->prm.repConnect.connFd; + p_svc->state = TSKM_SVC_WAKEUP; + TSKM_PRINTF(TSKM_LOG_DEBUG, "[ST:%d] WAKEUP", p_svc->pid); + + p_svc->waitResCnt = 0; + + if (p_svc->waitReqCnt) { + for (ii = 0; ii < p_svc->waitReqCnt; ii++) { + TSKM_ASSERT(TSKM_E_OK == wakeupRequest(p_svc, &p_svc->request[ii])); + } + p_svc->waitReqCnt = 0; + } + + return TSKM_TRUE; +} + +/********************************************************* + * Disconnection handler + * ret:TRUE SVC status changed + * ret:FALSE SVC status not changed + *********************************************************/ +TSKM_STATIC TSKM_BOOL_t disConnectHandle(TSKM_SVC_CTX_t* p_svc, + const TSKM_EVENT_INFO_t* p_inEv) { + // No status change + + return TSKM_TRUE; +} + +/********************************************************* + * Response handler for the activation request + * ret:TRUE SVC status changed + * ret:FALSE SVC status not changed + *********************************************************/ +TSKM_STATIC TSKM_BOOL_t resWakeupHandle(TSKM_SVC_CTX_t* p_svc, + const TSKM_EVENT_INFO_t* p_inEv) { + TSKM_ASSERT(p_svc->state == TSKM_SVC_WAKEUP); + TSKM_ASSERT(p_svc->waitResCnt > 0); + TSKM_BOOL_t isStateChg = TSKM_FALSE; + + if (p_svc->isShmDone == TSKM_FALSE && p_inEv->prm.resWakeup.isShmDone) { + p_svc->isShmDone = TSKM_TRUE; + isStateChg = TSKM_TRUE; + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "%s:SHM DONE", p_svc->attr->name); + } + if (p_svc->isStepDone == TSKM_FALSE && p_inEv->prm.resWakeup.isStepDone) { + p_svc->isStepDone = TSKM_TRUE; + isStateChg = TSKM_TRUE; + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "%s:STEP DONE", p_svc->attr->name); + } + + if (p_svc->waitResCnt > 0) { + p_svc->waitResCnt--; + if (p_svc->waitResCnt == 0) { // Transition when the wait runs out + if (p_inEv->prm.resWakeup.isLast) { + p_svc->state = TSKM_SVC_RUNNING; // Startup completed + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "[ST:%d] RUN", p_svc->pid); + } + isStateChg = TSKM_TRUE; + } + } + return isStateChg; +} + +/********************************************************* + * Response handler for the termination request + * ret:TRUE SVC state changed + * ret:FALSE SVC state not changed + *********************************************************/ +TSKM_STATIC TSKM_BOOL_t resDownHandle(TSKM_SVC_CTX_t* p_svc, + const TSKM_EVENT_INFO_t* p_inEv) { + TSKM_ASSERT(p_svc->state == TSKM_SVC_DOWN); + TSKM_ASSERT(p_svc->waitResCnt > 0); + TSKM_BOOL_t isStateChg = TSKM_FALSE; + + TSKM_PRINTF(TSKM_LOG_DEBUG, "pid:%d waitCnt:%d", p_svc->pid, + p_svc->waitResCnt); + if (p_svc->waitResCnt > 0) { + p_svc->waitResCnt--; + if (p_svc->waitResCnt == 0) { // Transition when the wait runs out + if (p_inEv->prm.resWakeup.isLast) { + p_svc->state = TSKM_SVC_FINDOWN; // Termination complete + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "[ST:%d] FIN_DOWN", p_svc->pid); + } + isStateChg = TSKM_TRUE; + } + } + return isStateChg; +} + +/********************************************************* + * Response Handlers for DebugDump Requests + * ret:TRUE SVC state changed + * ret:FALSE SVC state not changed + *********************************************************/ +TSKM_STATIC TSKM_BOOL_t resDebugDumpHandle(TSKM_SVC_CTX_t* p_svc, + const TSKM_EVENT_INFO_t* p_inEv) { + TSKM_BOOL_t isStateChg = TSKM_FALSE; + TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t *p_prm; + + if (!p_inEv->hasExtend || !p_inEv->extendPrm) { + TSKM_ASSERT(0); + goto ERROR; + } + + p_prm = (TSKM_EV_PRI_EX_RES_DEBUGDUMP_PRM_t *) p_inEv->extendPrm; // NOLINT (readability/casting) + + // FALSE is specified here because the required service names have been added in the PrimaryLib. + tskm_sub_debugDumpRes(FALSE, p_prm->dumpMsg); + + ERROR: return isStateChg; +} + +/********************************************************* + * Service termination request + * ret:TRUE SVC state changed + * ret:FALSE SVC state not changed + *********************************************************/ +TSKM_STATIC TSKM_BOOL_t reqExit(TSKM_SVC_CTX_t* p_svc, + const TSKM_EVENT_INFO_t* p_inEv) { + int ret; + TSKM_ERR_t tskmRet; + TSKM_ASSERT(p_svc->state == TSKM_SVC_RUNNING); + TSKM_ASSERT(p_svc->waitResCnt == 0); + TSKM_GSTEP_REQ_INFO_t req = { 0 }; + + req.svcId = p_svc->attr->svcId; + req.localStep = TSKM_LSTEP_ALL; + tskmRet = tskm_svcDownRequest(p_svc, &req); + TSKM_ERR_CHK_DFT; + + return TSKM_TRUE; + + // LCOV_EXCL_START 8: dead code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + ERROR: ret = tskm_pf_terminateProcGroup(static_cast<uint16_t>(p_svc->pid)); + if (ret != 0) { // LCOV_EXCL_BR_LINE 8: dead code + TSKM_PRINTF(TSKM_LOG_WARN, "ret = %d", ret); + } + + return TSKM_TRUE; + // LCOV_EXCL_STOP +} + +/********************************************************* + * Service termination handler + * ret:TRUE SVC state changed + * ret:FALSE SVC state not changed + *********************************************************/ +TSKM_STATIC TSKM_BOOL_t repTermHandle(TSKM_SVC_CTX_t* p_svc, + const TSKM_EVENT_INFO_t* p_inEv) { + int ret; + + // Check error + if (p_svc->attr->lifeCycle == TSKM_SVC_LC_DYNAMIC) { + if (p_svc->state != TSKM_SVC_DOWN) { + // A STATE other than DOWN does not terminate. + TSKM_PRINTF(TSKM_LOG_ERROR, "ERR TERM %s(%d) waitCnt:%d", + p_svc->attr->name, p_svc->pid, p_svc->waitResCnt); + TSKM_ASSERT(0); + } + } else { + // The resident service terminated. + TSKM_PRINTF(TSKM_LOG_ERROR, "ERR TERM %s(%d) waitCnt:%d", p_svc->attr->name, + p_svc->pid, p_svc->waitResCnt); + TSKM_ASSERT(0); + } + + TSKM_PRINTF(TSKM_LOG_STATE, "[ST:%d] DORMANT", p_svc->pid); + + p_svc->state = TSKM_SVC_DORMANT; + p_svc->waitResCnt = 0; + p_svc->pid = 0; + + if (p_svc->attr->type == TSKM_SVC_TYPE_NATIVE) { + EFrameworkunifiedStatus taskmanagerStatus; + TSKM_MAIN_CTX_t* p_main = tskm_getMainCtx(); + SS_String availabilityName = p_svc->attr->name; + availabilityName.append("/Availability"); + + taskmanagerStatus = FrameworkunifiedUnsubscribeNotificationWithCallback( + p_main->hApp, availabilityName.c_str()); + if (eFrameworkunifiedStatusOK != taskmanagerStatus) { + TSKM_ASSERT(0); + } + + p_svc->isAvailable = TSKM_FALSE; + p_svc->watchCnt = 0; + + HANDLE hMq = McOpenSender(FRAMEWORKUNIFIED_NS_NPSERVICE); + if (NULL == hMq) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); // LCOV_EXCL_LINE 4: NSFW error case. + } else { + ServiceAvailability availInfo = { }; + + snprintf(availInfo.cServiceName, MAX_NAME_SIZE_APP, "%s", + p_svc->attr->name); + availInfo.eServiceAvailability = eFrameworkunifiedServiceNotAvailable; + + taskmanagerStatus = NPPublishNotification(hMq, p_svc->attr->name, + availabilityName.c_str(), &availInfo, + sizeof(availInfo)); + if (eFrameworkunifiedStatusOK != taskmanagerStatus) { + TSKM_ASSERT(0); + } + + taskmanagerStatus = McClose(hMq); + if (eFrameworkunifiedStatusOK != taskmanagerStatus) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); // LCOV_EXCL_LINE 4: NSFW error case. + } + } + } + + if (p_inEv->errCode != TSKM_E_OK) { + p_svc->errTermCnt++; + // Notify 'NG' at Relaunch after abnormal termination + p_svc->bootInfo.resetStatus = e_SS_SM_RESET_STATUS_NG; + + ret = svcErrTermPost(p_svc); + if (ret != TSKM_E_OK) { + TSKM_ASSERT(0); + } + } else { + // NONE is notified at Relaunch after normal completion. + p_svc->bootInfo.resetStatus = e_SS_SM_RESET_STATUS_NONE; + } + + return TSKM_TRUE; +} + +/********************************************************* + * Get service context + *********************************************************/ +TSKM_SVC_CTX_t* +tskm_svcsGetSvcBySvcId(TSKM_SVCS_CTX_t* p_svcs, TSKM_SVCID_t svcId) { + return getSvcCtxBySvcId(p_svcs, svcId); +} + +/********************************************************* + * Get service context + *********************************************************/ +TSKM_SVC_CTX_t* +tskm_svcsGetSvcByPid(TSKM_SVCS_CTX_t* p_svcs, pid_t pid) { + return getSvcCtxByPid(p_svcs, pid); +} + +/********************************************************* + * Check for waiting services + *********************************************************/ +TSKM_BOOL_t tskm_svcsIsWaiting(TSKM_SVCS_CTX_t* p_svcs) { + uint32_t ii; + for (ii = 0; ii < p_svcs->svcNum; ii++) { + if (p_svcs->svcList[ii].waitResCnt > 0 + || p_svcs->svcList[ii].state == TSKM_SVC_WAITCONNECT) { + return TSKM_TRUE; + } + } + return TSKM_FALSE; +} + +/********************************************************* + * Check if ShutdownWait services are terminated + *********************************************************/ +TSKM_SVC_WAIT_STATE_t tskm_svcsGetSvcTermWaitState(TSKM_SVCS_CTX_t* p_svcs) { + uint32_t ii; + TSKM_SVC_WAIT_STATE_t waitState = TSKM_SVC_WAIT_NONE; + + for (ii = 0; ii < p_svcs->svcNum; ii++) { + if (p_svcs->svcList[ii].attr->shotdownWait) { + // Check shutdownWait SVC Only + if (p_svcs->svcList[ii].state != TSKM_SVC_DORMANT) { + // DORMANT is terminated or not started, so no checking is required + if (TSKM_SVC_LC_DYNAMIC != p_svcs->svcList[ii].attr->lifeCycle + && p_svcs->svcList[ii].state != TSKM_SVC_FINDOWN) { // Check of termination of resident SVCs + waitState = TSKM_SVC_WAIT_BOTH; + break; + } else if (TSKM_SVC_LC_DYNAMIC == p_svcs->svcList[ii].attr->lifeCycle) { // Check of termination of non-resident SVCs + waitState = TSKM_SVC_WAIT_TRANSIENT; + } + } + } + } + return waitState; +} + +/********************************************************* + * Update boot info of all services + *********************************************************/ +TSKM_ERR_t tskm_svcsSetBootInfo(TSKM_SVCS_CTX_t* p_svcs, + T_SS_SM_START_DataStructType* p_info, + T_SS_SM_START_ExtDataStructType *p_exInfo) { + uint32_t ii = 0; + + for (ii = 0; ii < p_svcs->svcNum; ii++) { + p_svcs->svcList[ii].bootInfo = *p_info; + p_svcs->svcList[ii].extBootInfo = *p_exInfo; + } + return TSKM_E_OK; +} + +/********************************************************* + * Terminates a running non-resident services + *********************************************************/ +TSKM_ERR_t tskm_svcsAvtiveSvcTerm(TSKM_SVCS_CTX_t* p_svcs) { + uint32_t ii; + + for (ii = 0; ii < p_svcs->svcNum; ii++) { + TSKM_SVC_CTX_t* p_svc = &p_svcs->svcList[ii]; + + if (TSKM_SVC_LC_DYNAMIC == p_svc->attr->lifeCycle && // Non-resident SVC + TSKM_SVC_RUNNING == p_svc->state && p_svc->waitResCnt == 0) { // Running + TSKM_ERR_t tskmRet; + TSKM_GSTEP_REQ_INFO_t req = { 0 }; + + req.svcId = p_svc->attr->svcId; + req.localStep = TSKM_LSTEP_ALL; + tskmRet = tskm_svcDownRequest(p_svc, &req); + TSKM_ERR_CHK_DFT; + } + } + + return TSKM_E_OK; + + ERROR: + return TSKM_E_NG; +} + +/********************************************************* + * Calls back the DebugDump of the running services + *********************************************************/ +TSKM_ERR_t tskm_svcsCallDebugDump(TSKM_SVCS_CTX_t* p_svcs) { + for (uint32_t ii = 0; ii < p_svcs->svcNum; ii++) { + TSKM_SVC_CTX_t* p_svc = &p_svcs->svcList[ii]; + + if (TSKM_SVC_RUNNING == p_svc->state) { // Running + TSKM_EVENT_INFO_t ev; + bzero(&ev, sizeof(ev)); + + // Send DebugDump request + ev.event = TSKM_EV_PRI_REQ_DEBUGDUMP; + ev.errCode = TSKM_E_OK; + if (0 >= tskm_sockSend(p_svc->connFd, &ev)) { + TSKM_ASSERT(0); + goto ERROR; + } + } + } + + return TSKM_E_OK; + ERROR: return TSKM_E_NG; +} + +/********************************************************* + * Calls back the LowMemory of the running services + *********************************************************/ +TSKM_ERR_t tskm_svcsCallLowMem(TSKM_SVCS_CTX_t* p_svcs) { + for (uint32_t ii = 0; ii < p_svcs->svcNum; ii++) { + TSKM_SVC_CTX_t* p_svc = &p_svcs->svcList[ii]; + if (TSKM_SVC_RUNNING == p_svc->state) { // Running + TSKM_EVENT_INFO_t ev; + bzero(&ev, sizeof(ev)); + + // Send LowMemory detection notification + ev.event = TSKM_EV_PRI_REP_LOWMEM; + ev.errCode = TSKM_E_OK; + if (0 >= tskm_sockSend(p_svc->connFd, &ev)) { + TSKM_ASSERT(0); + goto ERROR; + } + } + } + + return TSKM_E_OK; + ERROR: return TSKM_E_NG; +} + +/********************************************************* + * Event handler + *********************************************************/ +TSKM_ERR_t tskm_svcEventHandle(TSKM_SVC_CTX_t* p_svc, TSKM_EVENT_INFO_t* p_ev) { + TSKM_FUNC_IN(); + TSKM_BOOL_t isStateChg = TSKM_FALSE; + + if (isSvcEvent(p_ev) == TSKM_FALSE) { + // If it is not an event for the service, it will be sent as follows. + TSKM_FUNC_OUT(); + return TSKM_E_OK; + } + + switch (p_ev->event) { + case TSKM_EV_PRI_REP_CONNECT: // Connection Registration from Service + isStateChg = connectHandle(p_svc, p_ev); + break; + case TSKM_EV_PRI_REP_DISCONNECT: // Disconnection Registration from Service + isStateChg = disConnectHandle(p_svc, p_ev); + break; + case TSKM_EV_PRI_RES_WAKEUP: // Response to a startup request from a service + isStateChg = resWakeupHandle(p_svc, p_ev); + break; + case TSKM_EV_PRI_RES_DOWN: + isStateChg = resDownHandle(p_svc, p_ev); + break; + case TSKM_EV_PRI_RES_DEBUGDUMP: + isStateChg = resDebugDumpHandle(p_svc, p_ev); + break; + case TSKM_EV_PRI_REQ_EXIT: + isStateChg = reqExit(p_svc, p_ev); + break; + case TSKM_EV_SVC_REP_TERM: // Service termination + isStateChg = repTermHandle(p_svc, p_ev); + break; + default: + break; + } + + // Overwrite service state change + if (isStateChg) { + p_ev->event = TSKM_EV_LCL_CHG_SVC_STATE; + p_ev->prm.chgSvc.svcId = p_svc->attr->svcId; + } else { + p_ev->event = TSKM_EV_NOP; + } + + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} +/********************************************************* + * Startup service + *********************************************************/ +TSKM_ERR_t tskm_svcExec(TSKM_SVC_CTX_t* p_svc) { + return svcExec(p_svc); +} + +/********************************************************* + * Issue a startup request to the service + *********************************************************/ +TSKM_ERR_t tskm_svcWakeupRequest(TSKM_SVC_CTX_t* p_svc, + TSKM_GSTEP_REQ_INFO_t* p_req) { + return svcWakeupRequest(p_svc, p_req); +} + +/********************************************************* + * Issue a termination request to the service + *********************************************************/ +TSKM_ERR_t tskm_svcDownRequest(TSKM_SVC_CTX_t* p_svc, + TSKM_GSTEP_REQ_INFO_t* p_req) { + int ret; + TSKM_EVENT_INFO_t ev; + + bzero(&ev, sizeof(ev)); + + if (tskm_svcIsCommunicatable(p_svc) == TSKM_FALSE) { + return TSKM_E_OK; + } + + ev.event = TSKM_EV_PRI_REQ_DOWN; + ev.errCode = TSKM_E_OK; + ev.prm.reqDown.localStep = p_req->localStep; + + ret = tskm_sockSend(p_svc->connFd, &ev); + if (ret <= 0) { + TSKM_ASSERT(0); + goto ERROR; + } + p_svc->waitResCnt++; + p_svc->state = TSKM_SVC_DOWN; + + return TSKM_E_OK; + ERROR: return TSKM_E_NG; +} + +/********************************************************* + * Prohibit starting service + *********************************************************/ +TSKM_ERR_t tskm_svcDisableRequest(TSKM_SVC_CTX_t* p_svc) { + if (p_svc->state == TSKM_SVC_DORMANT || p_svc->state == TSKM_SVC_DISABLE) { + p_svc->state = TSKM_SVC_DISABLE; + return TSKM_E_OK; + } + return TSKM_E_STATE; +} + +/********************************************************* + * Allow starting service + *********************************************************/ +TSKM_ERR_t tskm_svcEnableRequest(TSKM_SVC_CTX_t* p_svc) { + if (p_svc->state == TSKM_SVC_DISABLE) { + p_svc->state = TSKM_SVC_DORMANT; + } + return TSKM_E_OK; +} + +/********************************************************* + * Queriy whether the service is ready for communication + *********************************************************/ +TSKM_BOOL_t tskm_svcIsCommunicatable(TSKM_SVC_CTX_t* p_svc) { + TSKM_BOOL_t ret = TSKM_FALSE; + if (p_svc == NULL || p_svc->attr->type == TSKM_SVC_TYPE_UNKNONW) { + } else { + switch (p_svc->state) { + case TSKM_SVC_WAKEUP: + case TSKM_SVC_RUNNING: + case TSKM_SVC_DOWN: + ret = TSKM_TRUE; + break; + default: + break; + } + } + return ret; +} // LCOV_EXCL_BR_LINE 10: Final line + diff --git a/systemservice/task_manager/server/src/tskm_wakeup.cpp b/systemservice/task_manager/server/src/tskm_wakeup.cpp new file mode 100644 index 00000000..b5c6e896 --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_wakeup.cpp @@ -0,0 +1,201 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "tskm_wakeup.h" +#include "tskm_debug.h" +#include "tskm_util.h" +#include "tskm_state.h" +#include "tskm_port_subsys.h" +#include "tskm_port_pf.h" + +#include "tskm_gstep.h" + + +/********************************************************* + * Get gradual startup context + *********************************************************/ +TSKM_STATIC TSKM_GSTEP_CTX_t* +gstepGetWakeupCtx(TSKM_MAIN_CTX_t* p_main) { + return &p_main->wakeup; +} + +/*********************************************************************** + * Startup completion process + ***********************************************************************/ +TSKM_STATIC void wakeupFinish(TSKM_MAIN_CTX_t* p_main) { + return; +} + +/********************************************************* + * Challenge for a transition to the next state + *********************************************************/ +TSKM_STATIC void tryTransNextState(TSKM_MAIN_CTX_t* p_main) { + TSKM_GSTEP_CTX_t* p_wakeup; + TSKM_GSTEP_t* p_current; + + p_wakeup = gstepGetWakeupCtx(p_main); + p_current = gstepGetCurrent(p_wakeup); + + if (!p_current) { + return; + } + + // LCOV_EXCL_BR_START 8: Because the second condition in the if statement is never false + if (tskm_svcsIsWaiting(&p_main->svcs) == TSKM_FALSE && // No waiting services + ((p_wakeup->compState & p_current->nextTransCond) + == p_current->nextTransCond)) { // Event completion condition + // LCOV_EXCL_BR_STOP + if (gstepIsLast(p_wakeup)) { + tskm_stateTransit(p_main, TSKM_ST_WAKEUP, TSKM_ST_RUNNING); + } else { + tskm_stateTransit(p_main, TSKM_ST_WAKEUP, TSKM_ST_WAKEUP); + } + } +} + +/********************************************************* + * Gradual startup request issuance process + *********************************************************/ +TSKM_ERR_t tskm_entryWakeup_Req(TSKM_MAIN_CTX_t* p_main, + TSKM_GSTEP_t* p_current) { + uint32_t ii; + + // Refer to the stepId and perform preprocessing if needed. + if (p_current->gstepId == TSKM_GSTEP_BUPCHK) { + TSKM_PRINTF(TSKM_LOG_STATE, "BUPCHK EXE"); + // When TaskManager is used as a system Launcher, system data is initialized here. + } + + // Start process + for (ii = 0; ii < p_current->execSvcNum; ii++) { + TSKM_ERR_t tskmRet; + TSKM_SVCID_t svcId = p_current->execSvcIdList[ii]; + TSKM_SVC_CTX_t* p_svc = tskm_svcsGetSvcBySvcId(&p_main->svcs, svcId); + + tskmRet = tskm_svcExec(p_svc); + TSKM_ERR_CHK_DFT; + } + + // Issue gradual startup request + for (ii = 0; ii < p_current->reqNum; ii++) { + TSKM_ERR_t tskmRet; + TSKM_GSTEP_REQ_INFO_t* p_req = &p_current->reqList[ii]; + TSKM_SVC_CTX_t* p_svc = tskm_svcsGetSvcBySvcId(&p_main->svcs, p_req->svcId); + + // Queuing in the SVC layer even for services that are not started. + tskmRet = tskm_svcWakeupRequest(p_svc, p_req); + TSKM_ERR_CHK_DFT; // LCOV_EXCL_BR_LINE 6: Because TSKM_ERR_CHK_DFT does not specify a condition for goto to ERROR + } + + if (p_current->nextTransCond) { + TSKM_PRINTF(TSKM_LOG_STATE, "WAIT COMP:%s(%llx)", + tskm_convInitCompId2Str(p_current->nextTransCond), + p_current->nextTransCond); + } + + return TSKM_E_OK; + + // LCOV_EXCL_START 6: Checked in Death testing, but it is not reflected in the coverage and excluded + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return TSKM_E_NG; + // LCOV_EXCL_STOP +} + +/********************************************************* + * Gradual startup entry process + *********************************************************/ +TSKM_ERR_t tskm_entryWakeup(TSKM_MAIN_CTX_t* p_main) { + TSKM_FUNC_IN(); + + TSKM_GSTEP_CTX_t* p_wakeup; + TSKM_GSTEP_t* p_current; + + p_main->state = TSKM_ST_WAKEUP; + p_wakeup = gstepGetWakeupCtx(p_main); + p_current = gstepGetCurrent(p_wakeup); + + if (p_current == NULL) { // LCOV_EXCL_BR_LINE 8: Because condition false setting is not possible + // LCOV_EXCL_START 8: Because condition false setting is not possible + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + tskm_pf_exit(EXIT_FAILURE); + // LCOV_EXCL_STOP + } + + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "WAKEUP GSTEP:%d", p_wakeup->gstepIdx); + + if (tskm_entryWakeup_Req(p_main, p_current) == TSKM_E_NG) { // LCOV_EXCL_BR_LINE 200:the function of tskm_entryWakeup_Req can not be TSKM_E_NG at this case // NOLINT(whitespace/line_length) + // LCOV_EXCL_START 200:the function of tskm_entryWakeup_Req can not be TSKM_E_NG at this case // NOLINT(whitespace/line_length) + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + tskm_pf_exit(EXIT_FAILURE); + // LCOV_EXCL_STOP + } + + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} + +/********************************************************* + * Gradual startup exit process + *********************************************************/ +TSKM_ERR_t tskm_exitWakeup(TSKM_MAIN_CTX_t* p_main) { + TSKM_GSTEP_CTX_t* p_wakeup; + + TSKM_FUNC_IN(); + p_wakeup = gstepGetWakeupCtx(p_main); + + // Exit process at the end of the gradual startup + if (gstepIsLast(p_wakeup)) { + TSKM_PRINTF(TSKM_LOG_STATE, "WAKEUP FIN"); + wakeupFinish(p_main); + } + + changeNextStep(p_wakeup); // Transition to next step + + TSKM_FUNC_OUT(); + return TSKM_E_OK; +} + +/********************************************************* + * Gradual startup handler + *********************************************************/ +TSKM_ERR_t tskm_handleWakeup(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev) { + TSKM_FUNC_IN(); + TSKM_ERR_t tskmRet = TSKM_E_OK; + + switch (p_ev->event) { + case TSKM_EV_PRI_REP_WAKEUP_COMP: // Event completion notification at startup + { + TSKM_PRINTF(TSKM_LOG_SVCSTATE, "INIT COMP :%s(%#llx) from:%d", + tskm_convInitCompId2Str(p_ev->prm.repWakeupComp.compId), + p_ev->prm.repWakeupComp.compId, p_ev->fromPid); + TSKM_GSTEP_CTX_t* p_wakeup = gstepGetWakeupCtx(p_main); + p_wakeup->compState |= p_ev->prm.repWakeupComp.compId; + tryTransNextState(p_main); + } + break; + case TSKM_EV_LCL_CHG_SVC_STATE: // Service state change + tryTransNextState(p_main); + break; + default: + tskmRet = tskm_handleAccon(p_main, p_ev); + break; + } + TSKM_FUNC_OUT(); + return tskmRet; +} // LCOV_EXCL_BR_LINE 10: Final line + diff --git a/systemservice/task_manager/server/src/tskm_watch.cpp b/systemservice/task_manager/server/src/tskm_watch.cpp new file mode 100644 index 00000000..455de0b3 --- /dev/null +++ b/systemservice/task_manager/server/src/tskm_watch.cpp @@ -0,0 +1,101 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * 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 "tskm_watch.h" +#include <agl_thread.h> + +#include "tskm_debug.h" +#include "tskm_port_pf.h" +#include "tskm_comm.h" + + +#define WATCH_CYCLE 5 + +#define TIMER_THREAD_NAME "SS_TskmTimer" + +/******************************************************************* + * Periodic Timer-Thread MAIN Function + *******************************************************************/ +void * +watchMain(void *arg) { + int connFd = -1; + + connFd = tskm_cliSockConnect(TSKM_SOCKET_NAME); + if (connFd < 0) { // LCOV_EXCL_BR_LINE 5: system function(uinx) "socket" fail process + // LCOV_EXCL_START 5: system function(uinx) "socket" fail process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP 5 + } + + while (1) { + int ret; + TSKM_EVENT_INFO_t ev; + + sleep(WATCH_CYCLE); + + ev.event = TSKM_EV_LCL_REP_POLLING; + ev.errCode = TSKM_E_OK; + ret = tskm_sockSend(connFd, &ev); + if (ret <= 0) { // LCOV_EXCL_BR_LINE 5: system function(uinx) "send" fail process + // LCOV_EXCL_START 5: system function(uinx) "send" fail process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP 5 + } + } + + // LCOV_EXCL_START 6: system function(uinx) call fail process + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if (connFd != -1) { + tskm_sockDestory(connFd); + } + + return 0; + // LCOV_EXCL_STOP +} + +/******************************************************************* + * Periodic Timer thread start + *******************************************************************/ +int tskm_watch_startTimer() { + int ret; + pthread_t thId = { 0 }; + + ret = tskm_pf_createThread(watchMain, NULL, PR_SS_TSKMTIMER, + TIMER_THREAD_NAME, &thId); + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: system function(uinx) "pthread_*" fail process + // LCOV_EXCL_START 5: system function(uinx) "pthread_*" fail process + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + TSKM_ASSERT(0); + goto ERROR; + // LCOV_EXCL_STOP 5 + } else { + TSKM_PRINTF(TSKM_LOG_STATE, "watch thread created."); + } + + return 0; + + // LCOV_EXCL_LINE 6: system function(uinx) "pthread_*" fail process + ERROR: + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return -1; + // LCOV_EXCL_STOP +} + |