b77709014fb69773f76f3d44b8da7e552f10b8d1
[staging/basesystem.git] / service / system / task_manager / server / src / tskm_state.cpp
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "tskm_state.h"
18 #include <stdlib.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"
25
26
27
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);
32
33 TSKM_ERR_t tskm_entryAccon(TSKM_MAIN_CTX_t* p_main);
34 TSKM_ERR_t tskm_exitAccon(TSKM_MAIN_CTX_t* p_main);
35
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);
39
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);
45
46 typedef struct {
47   TSKM_STATE_t state;
48   entry_state_t entry_func;
49   exit_state_t exit_func;
50   event_handler_t event_handler;
51 } state_func_table_t;
52
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 } };
60
61 /****************************************************
62  *        ACC OFF ENTRY
63  ****************************************************/
64 TSKM_ERR_t tskm_entryAccoff(TSKM_MAIN_CTX_t* p_main) {
65   TSKM_FUNC_IN();
66   p_main->state = TSKM_ST_ACCOFF;
67   TSKM_FUNC_OUT();
68   return TSKM_E_OK;
69 }
70
71 /*************************************************************************
72  *              ACC OFF EXIT
73  *************************************************************************/
74 TSKM_ERR_t tskm_exitAccoff(TSKM_MAIN_CTX_t* p_main) {
75   // Do nothing
76   // Called only once at startup
77   return TSKM_E_OK;
78 }
79
80 /*************************************************************************
81  *              ACC OFF HANDLE
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
85   return TSKM_E_OK;
86 }
87
88 /*************************************************************************
89  *              ACC ON ENTRY
90  *************************************************************************/
91 TSKM_ERR_t tskm_entryAccon(TSKM_MAIN_CTX_t* p_main) {
92   TSKM_FUNC_IN();
93   p_main->state = TSKM_ST_ACCON;
94
95   tskm_entryState(p_main, TSKM_ST_WAKEUP);
96   TSKM_FUNC_OUT();
97   return TSKM_E_OK;
98 }
99
100 /*************************************************************************
101  *              ACC ON HANDLE
102  *************************************************************************/
103 TSKM_ERR_t tskm_exitAccon(TSKM_MAIN_CTX_t* p_main) {
104   TSKM_FUNC_IN();
105
106   TSKM_ERR_t tskmRet = TSKM_E_OK;
107
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);
112     // LCOV_EXCL_STOP
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);
117     // LCOV_EXCL_STOP
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);
120   }
121
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;
124   ERROR:
125   TSKM_FUNC_OUT();
126   return tskmRet;
127 }
128
129 /*************************************************************************
130  *              POLL EVENT HANDLE
131  *************************************************************************/
132 TSKM_STATIC void checkHungSvcs(TSKM_MAIN_CTX_t* p_main) {
133   int ret;
134   TSKM_HUNG_INFO_t *p_hungSvcList = NULL;
135
136   p_hungSvcList = tskm_sub_searchHungSvcs();
137   if (p_hungSvcList != NULL) {
138     int hungSvcNum = 0;
139
140     while (p_hungSvcList[hungSvcNum].pid != -1) {
141       pid_t pid = p_hungSvcList[hungSvcNum].pid;
142
143       TSKM_SVC_CTX_t* p_svc = tskm_svcsGetSvcByPid(&p_main->svcs, pid);
144
145       if (p_svc) {
146         TSKM_PRINTF(TSKM_LOG_SYSTEMDATA, "HUNG SVC(%s:%d), TYPE(%d)",
147                     p_svc->attr->name, pid, p_hungSvcList[hungSvcNum].type);
148
149         ret = tskm_pf_terminateProcGroup(static_cast<uint16_t>(pid));
150         if (ret != 0) {
151           TSKM_ASSERT(0);
152         }
153
154       } else {
155         TSKM_PRINTF(TSKM_LOG_WARN, "UNKNOWN HUNG SVC(%d), TYPE(%d)", pid,
156                     p_hungSvcList[hungSvcNum].type);
157       }
158
159       hungSvcNum++;
160     }
161
162     free(p_hungSvcList);
163   }
164
165   return;
166 }
167
168 #define AVAILABILITY_CHECK_RETRY_COUNT 24
169
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);
183
184       if (p_main->svcs.svcList[ii].watchCnt > AVAILABILITY_CHECK_RETRY_COUNT) {
185         int ret;
186
187         ret = tskm_pf_terminateProcGroup(static_cast<uint16_t>(p_main->svcs.svcList[ii].pid));
188         if (ret != 0) {
189           TSKM_ASSERT(0);
190         }
191       }
192     }
193   }
194
195   return;
196 }
197
198 /*************************************************************************
199  *              POLL EVENT HANDLE
200  *************************************************************************/
201 TSKM_STATIC void handlePolling(TSKM_MAIN_CTX_t* p_main) {
202   checkHungSvcs(p_main);
203
204   checkSvcAvailability(p_main);
205
206   return;
207 }
208
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;
214
215   tskmRet = tskm_svcsCallLowMem(&p_main->svcs);
216   if (TSKM_E_OK != tskmRet) {
217     TSKM_ASSERT(0);
218   }
219
220   return;
221 }
222 /*************************************************************************
223  *              ACC ON HANDLE
224  *************************************************************************/
225 TSKM_ERR_t tskm_handleAccon(TSKM_MAIN_CTX_t* p_main, TSKM_EVENT_INFO_t* p_ev) {
226   TSKM_FUNC_IN();
227
228   switch (p_ev->event) {
229     case TSKM_EV_LCL_REQ_SDUMP:
230       tskm_svcsDump(&p_main->svcs);
231       break;
232       // LCOV_EXCL_STOP
233     case TSKM_EV_LCL_REP_POLLING:
234       TSKM_PRINTF(TSKM_LOG_DEBUG, "watch timer polling event.");
235       handlePolling(p_main);
236       break;
237     default:
238       TSKM_PRINTF(TSKM_LOG_STATE, "IGNORE:%s(%d)",
239                   tskm_convEvent2Str(p_ev->event), p_ev->event);
240       break;
241   }
242   TSKM_FUNC_OUT();
243   return TSKM_E_OK;
244 }
245
246 /*************************************************************************
247  *              BOOT RESERVED SERVICES
248  *************************************************************************/
249 static int bootRsvSvcs(TSKM_MAIN_CTX_t* p_main) {
250   uint32_t ii;
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;
254
255   TSKM_PRINTF(TSKM_LOG_STATE, "RSV SVC NUM = %d", rsvSvcNum);
256
257   for (ii = 0; ii < rsvSvcNum; ii++) {
258     TSKM_GSTEP_REQ_INFO_t req = { 0 };
259     TSKM_SVC_CTX_t* p_svc;
260
261     p_svc = tskm_svcsGetSvcBySvcId(&p_main->svcs, p_rsvSvcs[ii]);
262     if (p_svc == NULL) {
263       TSKM_ASSERT(0);
264       continue;
265     }
266
267     tskmRet = tskm_svcExec(p_svc);
268     if (TSKM_E_OK != tskmRet) {
269       TSKM_ASSERT(0);
270       continue;
271     }
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);
281         continue;
282         // LCOV_EXCL_STOP
283       }
284     }
285   }
286
287   if (rsvSvcNum != 0) {
288     int ret;
289
290     for (ii = 0; ii < TSKM_SVC_RESERVE_MAX; ii++) {
291       p_rsvSvcs[ii] = TSKM_SVCID_NONE;
292     }
293
294     p_main->nvInfo.body.rsvSvcNum = 0;
295
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
300       TSKM_ASSERT(0);
301       goto ERROR;
302       // LCOV_EXCL_STOP
303     }
304   }
305
306   return 0;
307   // LCOV_EXCL_START 8: Because the tskm_pf_nvFileWrite() only returns a return value of 0
308   ERROR:
309   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
310   return -1;
311   // LCOV_EXCL_STOP
312 }
313
314 /*************************************************************************
315  *              RUN ENTRY
316  *************************************************************************/
317 TSKM_ERR_t tskm_entryRunning(TSKM_MAIN_CTX_t* p_main) {
318   int ret;
319
320   TSKM_FUNC_IN();
321   p_main->state = TSKM_ST_RUNNING;
322
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
327     TSKM_ASSERT(0);
328     // LCOV_EXCL_STOP
329   }
330
331   TSKM_FUNC_OUT();
332   return TSKM_E_OK;
333 }
334
335 /*************************************************************************
336  *              RUN EXIT
337  *************************************************************************/
338 TSKM_ERR_t tskm_exitRunning(TSKM_MAIN_CTX_t* p_main) {
339   TSKM_FUNC_IN();
340
341   TSKM_FUNC_OUT();
342   return TSKM_E_OK;
343 }
344
345 /*************************************************************************
346  *              RUN HANDLE
347  *************************************************************************/
348 TSKM_ERR_t tskm_handleRunning(TSKM_MAIN_CTX_t* p_main,
349                               TSKM_EVENT_INFO_t* p_ev) {
350   TSKM_FUNC_IN();
351
352   switch (p_ev->event) {
353     case TSKM_EV_LCL_REQ_STOP:
354       tskm_stateTransit(p_main, TSKM_ST_RUNNING, TSKM_ST_DOWN);
355       break;
356     case TSKM_EV_LCL_REP_LOWMEM:
357       handleLowMem(p_main);
358       break;
359     default:
360       tskm_handleAccon(p_main, p_ev);
361       break;
362   }
363
364   TSKM_FUNC_OUT();
365   return TSKM_E_OK;
366 }
367
368 /*************************************************************************
369  *                Get transition table
370  *************************************************************************/
371 static const state_func_table_t*
372 tskm_getFuncTable(TSKM_STATE_t state) {
373   int i;
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];
377     }
378   }
379   TSKM_ASSERT(0);
380   return &state_func_table[0];
381 }
382
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) {
388   TSKM_ERR_t tskmRet;
389   TSKM_PRINTF(TSKM_LOG_STATE, "STATE:%s(%s) -> %s",
390               tskm_convState2Str(srcState), tskm_convState2Str(p_main->state),
391               tskm_convState2Str(dstState));
392
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
397   return TSKM_E_OK;
398
399   // LCOV_EXCL_START 8: Because TSKM_ERR_CHK does not specify a goto ERROR condition
400   ERROR:
401   AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
402   return TSKM_E_NG;
403   // LCOV_EXCL_STOP
404 }
405
406 /*************************************************************************
407  *                Event handler
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);
413 }
414
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);
421
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));
425   } else {
426     // LCOV_EXCL_START 8: Because p_table->entry_func never becomes 0
427     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
428     TSKM_ASSERT(0);
429     // LCOV_EXCL_STOP
430   }
431   return ret;
432 }
433
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);
440
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);
443   } else {
444     // LCOV_EXCL_START 8: Because p_table->exit_func never becomes 0
445     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
446     TSKM_ASSERT(0);
447     // LCOV_EXCL_STOP
448   }
449   TSKM_PRINTF(TSKM_LOG_DEBUG, "exit :%s", tskm_convState2Str(state));
450   return ret;
451 }  // LCOV_EXCL_BR_LINE 10: Final line
452