Re-organized sub-directory by category
[staging/basesystem.git] / service / system / task_manager / server / src / tskm_state.cpp
diff --git a/service/system/task_manager/server/src/tskm_state.cpp b/service/system/task_manager/server/src/tskm_state.cpp
new file mode 100755 (executable)
index 0000000..b777090
--- /dev/null
@@ -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
+