2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "tskm_state.h"
19 #include "tskm_util.h"
20 #include "tskm_debug.h"
21 #include "tskm_wakeup.h"
22 #include "tskm_shutdown.h"
23 #include "tskm_port_subsys.h"
24 #include "tskm_port_pf.h"
28 // Prototype declarations
29 TSKM_ERR_t tskm_entryAccoff(TSKM_MAIN_CTX_t* p_main);
30 TSKM_ERR_t tskm_exitAccoff(TSKM_MAIN_CTX_t* p_main);
31 TSKM_ERR_t tskm_handleAccoff(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev);
33 TSKM_ERR_t tskm_entryAccon(TSKM_MAIN_CTX_t* p_main);
34 TSKM_ERR_t tskm_exitAccon(TSKM_MAIN_CTX_t* p_main);
36 TSKM_ERR_t tskm_entryRunning(TSKM_MAIN_CTX_t* p_main);
37 TSKM_ERR_t tskm_exitRunning(TSKM_MAIN_CTX_t* p_main);
38 TSKM_ERR_t tskm_handleRunning(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev);
40 // Structures of state transitioning callback functions
41 typedef TSKM_ERR_t (*entry_state_t)(TSKM_MAIN_CTX_t* p_main);
42 typedef TSKM_ERR_t (*exit_state_t)(TSKM_MAIN_CTX_t* p_main);
43 typedef TSKM_ERR_t (*event_handler_t)(TSKM_MAIN_CTX_t* p_main,
44 TSKM_EVENT_INFO_t* p_ev);
48 entry_state_t entry_func;
49 exit_state_t exit_func;
50 event_handler_t event_handler;
53 // State specific function table
54 static const state_func_table_t state_func_table[] = { { TSKM_ST_ACCOFF,
55 tskm_entryAccoff, tskm_exitAccoff, tskm_handleAccoff }, { TSKM_ST_ACCON,
56 tskm_entryAccon, tskm_exitAccon, tskm_handleAccon }, { TSKM_ST_WAKEUP,
57 tskm_entryWakeup, tskm_exitWakeup, tskm_handleWakeup }, { TSKM_ST_RUNNING,
58 tskm_entryRunning, tskm_exitRunning, tskm_handleRunning }, { TSKM_ST_DOWN,
59 tskm_entryDown, tskm_exitDown, tskm_handleDown }, { 0, 0, 0, 0 } };
61 /****************************************************
63 ****************************************************/
64 TSKM_ERR_t tskm_entryAccoff(TSKM_MAIN_CTX_t* p_main) {
66 p_main->state = TSKM_ST_ACCOFF;
71 /*************************************************************************
73 *************************************************************************/
74 TSKM_ERR_t tskm_exitAccoff(TSKM_MAIN_CTX_t* p_main) {
76 // Called only once at startup
80 /*************************************************************************
82 *************************************************************************/
83 TSKM_ERR_t tskm_handleAccoff(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev) {
84 TSKM_ASSERT(0); // Do nothing
88 /*************************************************************************
90 *************************************************************************/
91 TSKM_ERR_t tskm_entryAccon(TSKM_MAIN_CTX_t* p_main) {
93 p_main->state = TSKM_ST_ACCON;
95 tskm_entryState(p_main, TSKM_ST_WAKEUP);
100 /*************************************************************************
102 *************************************************************************/
103 TSKM_ERR_t tskm_exitAccon(TSKM_MAIN_CTX_t* p_main) {
106 TSKM_ERR_t tskmRet = TSKM_E_OK;
108 if (TSKM_SUB_STATE_IS(p_main, TSKM_ST_WAKEUP)) { // LCOV_EXCL_BR_LINE 8:Because the condition is never true
109 // LCOV_EXCL_START 8: Because the condition is never true
110 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
111 tskmRet = tskm_exitState(p_main, TSKM_ST_WAKEUP);
113 } else if (TSKM_SUB_STATE_IS(p_main, TSKM_ST_RUNNING)) { // LCOV_EXCL_BR_LINE 8: Because the condition is never true
114 // LCOV_EXCL_START 8: Because the condition is never true
115 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
116 tskmRet = tskm_exitState(p_main, TSKM_ST_RUNNING);
118 } else if (TSKM_SUB_STATE_IS(p_main, TSKM_ST_DOWN)) { // LCOV_EXCL_BR_LINE 8:Because the condition is never false
119 tskmRet = tskm_exitState(p_main, TSKM_ST_DOWN);
122 TSKM_ERR_CHK(tskmRet, TSKM_E_OK, ERROR); // LCOV_EXCL_BR_LINE 8: Because the tskmRet does not change to NG
123 p_main->isExec = TSKM_FALSE;
129 /*************************************************************************
131 *************************************************************************/
132 TSKM_STATIC void checkHungSvcs(TSKM_MAIN_CTX_t* p_main) {
134 TSKM_HUNG_INFO_t *p_hungSvcList = NULL;
136 p_hungSvcList = tskm_sub_searchHungSvcs();
137 if (p_hungSvcList != NULL) {
140 while (p_hungSvcList[hungSvcNum].pid != -1) {
141 pid_t pid = p_hungSvcList[hungSvcNum].pid;
143 TSKM_SVC_CTX_t* p_svc = tskm_svcsGetSvcByPid(&p_main->svcs, pid);
146 TSKM_PRINTF(TSKM_LOG_SYSTEMDATA, "HUNG SVC(%s:%d), TYPE(%d)",
147 p_svc->attr->name, pid, p_hungSvcList[hungSvcNum].type);
149 ret = tskm_pf_terminateProcGroup(static_cast<uint16_t>(pid));
155 TSKM_PRINTF(TSKM_LOG_WARN, "UNKNOWN HUNG SVC(%d), TYPE(%d)", pid,
156 p_hungSvcList[hungSvcNum].type);
168 #define AVAILABILITY_CHECK_RETRY_COUNT 24
170 /*************************************************************************
171 * CHECK SVC AVAILABILITY
172 *************************************************************************/
173 TSKM_STATIC void checkSvcAvailability(TSKM_MAIN_CTX_t* p_main) {
174 for (uint32_t ii = 0; ii < p_main->svcs.svcNum; ii++) {
175 if (p_main->svcs.svcList[ii].state == TSKM_SVC_RUNNING
176 && !p_main->svcs.svcList[ii].isAvailable) {
177 p_main->svcs.svcList[ii].watchCnt++;
178 TSKM_ASSERT_PRINT(0, "WAIT AVAILABILITY FOR %s(%d) (%d/%d)",
179 p_main->svcs.svcList[ii].attr->name,
180 p_main->svcs.svcList[ii].pid,
181 p_main->svcs.svcList[ii].watchCnt,
182 AVAILABILITY_CHECK_RETRY_COUNT);
184 if (p_main->svcs.svcList[ii].watchCnt > AVAILABILITY_CHECK_RETRY_COUNT) {
187 ret = tskm_pf_terminateProcGroup(static_cast<uint16_t>(p_main->svcs.svcList[ii].pid));
198 /*************************************************************************
200 *************************************************************************/
201 TSKM_STATIC void handlePolling(TSKM_MAIN_CTX_t* p_main) {
202 checkHungSvcs(p_main);
204 checkSvcAvailability(p_main);
209 /*************************************************************************
210 * LOW MEMORY EVENT HANDLE
211 *************************************************************************/
212 TSKM_STATIC void handleLowMem(TSKM_MAIN_CTX_t* p_main) {
213 TSKM_ERR_t tskmRet = TSKM_E_OK;
215 tskmRet = tskm_svcsCallLowMem(&p_main->svcs);
216 if (TSKM_E_OK != tskmRet) {
222 /*************************************************************************
224 *************************************************************************/
225 TSKM_ERR_t tskm_handleAccon(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev) {
228 switch (p_ev->event) {
229 case TSKM_EV_LCL_REQ_SDUMP:
230 tskm_svcsDump(&p_main->svcs);
233 case TSKM_EV_LCL_REP_POLLING:
234 TSKM_PRINTF(TSKM_LOG_DEBUG, "watch timer polling event.");
235 handlePolling(p_main);
238 TSKM_PRINTF(TSKM_LOG_STATE, "IGNORE:%s(%d)",
239 tskm_convEvent2Str(p_ev->event), p_ev->event);
246 /*************************************************************************
247 * BOOT RESERVED SERVICES
248 *************************************************************************/
249 static int bootRsvSvcs(TSKM_MAIN_CTX_t* p_main) {
251 TSKM_ERR_t tskmRet = TSKM_E_OK;
252 uint8_t rsvSvcNum = p_main->nvInfo.body.rsvSvcNum;
253 TSKM_SVCID_t* p_rsvSvcs = p_main->nvInfo.body.rsvSvcs;
255 TSKM_PRINTF(TSKM_LOG_STATE, "RSV SVC NUM = %d", rsvSvcNum);
257 for (ii = 0; ii < rsvSvcNum; ii++) {
258 TSKM_GSTEP_REQ_INFO_t req = { 0 };
259 TSKM_SVC_CTX_t* p_svc;
261 p_svc = tskm_svcsGetSvcBySvcId(&p_main->svcs, p_rsvSvcs[ii]);
267 tskmRet = tskm_svcExec(p_svc);
268 if (TSKM_E_OK != tskmRet) {
272 if (p_svc->state == TSKM_SVC_WAITCONNECT) {
273 // In the state waiting for execution
274 req.svcId = p_rsvSvcs[ii];
275 req.localStep = TSKM_LSTEP_ALL;
276 tskmRet = tskm_svcWakeupRequest(p_svc, &req);
277 if (TSKM_E_OK != tskmRet) { // LCOV_EXCL_BR_LINE 8: Because the condition is never true
278 // LCOV_EXCL_START 8: Because the condition is never true
279 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
280 TSKM_ASSERT_PRINT(0, "tskmRet = %d", tskmRet);
287 if (rsvSvcNum != 0) {
290 for (ii = 0; ii < TSKM_SVC_RESERVE_MAX; ii++) {
291 p_rsvSvcs[ii] = TSKM_SVCID_NONE;
294 p_main->nvInfo.body.rsvSvcNum = 0;
296 ret = tskm_pf_nvFileWrite(&p_main->nvInfo);
297 if (ret == -1) { // LCOV_EXCL_BR_LINE 8: Because the tskm_pf_nvFileWrite() only returns a return value of 0
298 // LCOV_EXCL_START 8:Because the condition is never true
299 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
307 // LCOV_EXCL_START 8: Because the tskm_pf_nvFileWrite() only returns a return value of 0
309 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
314 /*************************************************************************
316 *************************************************************************/
317 TSKM_ERR_t tskm_entryRunning(TSKM_MAIN_CTX_t* p_main) {
321 p_main->state = TSKM_ST_RUNNING;
323 ret = bootRsvSvcs(p_main);
324 if (ret != 0) { // LCOV_EXCL_BR_LINE 8: Because bootRsvSvcs returns only a return value of 0
325 // LCOV_EXCL_START 8: Because bootRsvSvcs returns only a return value of 0
326 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
335 /*************************************************************************
337 *************************************************************************/
338 TSKM_ERR_t tskm_exitRunning(TSKM_MAIN_CTX_t* p_main) {
345 /*************************************************************************
347 *************************************************************************/
348 TSKM_ERR_t tskm_handleRunning(TSKM_MAIN_CTX_t* p_main,
349 TSKM_EVENT_INFO_t* p_ev) {
352 switch (p_ev->event) {
353 case TSKM_EV_LCL_REQ_STOP:
354 tskm_stateTransit(p_main, TSKM_ST_RUNNING, TSKM_ST_DOWN);
356 case TSKM_EV_LCL_REP_LOWMEM:
357 handleLowMem(p_main);
360 tskm_handleAccon(p_main, p_ev);
368 /*************************************************************************
369 * Get transition table
370 *************************************************************************/
371 static const state_func_table_t*
372 tskm_getFuncTable(TSKM_STATE_t state) {
374 for (i = 0; state_func_table[i].state != 0; i++) {
375 if (state == state_func_table[i].state) {
376 return &state_func_table[i];
380 return &state_func_table[0];
383 /*************************************************************************
384 * State transition instructions
385 *************************************************************************/
386 TSKM_ERR_t tskm_stateTransit(TSKM_MAIN_CTX_t* p_main, TSKM_STATE_t srcState,
387 TSKM_STATE_t dstState) {
389 TSKM_PRINTF(TSKM_LOG_STATE, "STATE:%s(%s) -> %s",
390 tskm_convState2Str(srcState), tskm_convState2Str(p_main->state),
391 tskm_convState2Str(dstState));
393 tskmRet = tskm_exitState(p_main, srcState);
394 TSKM_ERR_CHK(tskmRet, TSKM_E_OK, ERROR); // LCOV_EXCL_BR_LINE 8: Because TSKM_ERR_CHK does not specify a goto ERROR condition
395 tskmRet = tskm_entryState(p_main, dstState);
396 TSKM_ERR_CHK(tskmRet, TSKM_E_OK, ERROR); // LCOV_EXCL_BR_LINE 8: Because TSKM_ERR_CHK does not specify a goto ERROR condition
399 // LCOV_EXCL_START 8: Because TSKM_ERR_CHK does not specify a goto ERROR condition
401 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
406 /*************************************************************************
408 *************************************************************************/
409 void tskm_handleEvent(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev) {
410 event_handler_t handlerFunc;
411 handlerFunc = tskm_getFuncTable(p_main->state)->event_handler;
412 handlerFunc(p_main, p_ev);
415 /****************************************************
416 * State transitioning entry process
417 ****************************************************/
418 TSKM_ERR_t tskm_entryState(TSKM_MAIN_CTX_t* p_rec, TSKM_STATE_t state) {
419 TSKM_ERR_t ret = TSKM_E_NG;
420 const state_func_table_t* p_table = tskm_getFuncTable(state);
422 TSKM_PRINTF(TSKM_LOG_DEBUG, "entry :%s", tskm_convState2Str(state));
423 if (p_table->entry_func) { // LCOV_EXCL_BR_LINE 8: Because p_table->entry_func never becomes 0
424 ret = ((*p_table->entry_func)(p_rec));
426 // LCOV_EXCL_START 8: Because p_table->entry_func never becomes 0
427 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
434 /****************************************************
435 * State transitioning exit process
436 ****************************************************/
437 TSKM_ERR_t tskm_exitState(TSKM_MAIN_CTX_t* p_rec, TSKM_STATE_t state) {
438 TSKM_ERR_t ret = TSKM_E_NG;
439 const state_func_table_t* p_table = tskm_getFuncTable(state);
441 if (p_table->exit_func) { // LCOV_EXCL_BR_LINE 8: Because p_table->exit_func never becomes 0
442 ret = (*p_table->exit_func)(p_rec);
444 // LCOV_EXCL_START 8: Because p_table->exit_func never becomes 0
445 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
449 TSKM_PRINTF(TSKM_LOG_DEBUG, "exit :%s", tskm_convState2Str(state));
451 } // LCOV_EXCL_BR_LINE 10: Final line