#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stgdevinfo.h" #include "mysqlinfo.h" #include "spiinfo.h" #include "adcinfo.h" ///////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG #define TRACE(...) fprintf(stdout, __VA_ARGS__), fflush(stdout) #else // _DEBUG #define TRACE(...) #endif // _DEBUG #define UNUSED(v) (void)v #define _countof(a) (sizeof(a) / sizeof(*a)) ///////////////////////////////////////////////////////////////////////////// #define _APPID GFA_APPCTRL_APPID_SYSINFO #define _APPNAME "GfaSysInfo" #define _CYCLE_INTV 500 ///////////////////////////////////////////////////////////////////////////// static volatile bool g_fRun = false; static volatile bool g_fPause = false; static volatile bool g_fZombie = false; static sigset_t g_set; ///////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG static const char *g_pszStateNames[] = { "Not running", "Initializing", "Running", "Paused", "Hanging", "Terminating", "Invalid" }; #endif // _DEBUG ///////////////////////////////////////////////////////////////////////////// static void _ProcessCtrlMessages(HAPPCTRL hAC, HAPPINFO hAI, bool &bStateTransition, bool &bUpdateStgDevInfo) { ctrlmsg_t nCtrlMsg; while(g_fRun && (nCtrlMsg = ::GfaIpcAppCtrlGetNextCtrlMsg(hAI))) { switch(nCtrlMsg) { case GFA_APPCTRL_CTRLMSG_STOP: bStateTransition = g_fRun; g_fRun = false; TRACE("Received Message: STOP!\n"); break; case GFA_APPCTRL_CTRLMSG_PAUSE: if(!g_fPause) { bStateTransition = true; g_fPause = true; ::GfaIpcAppCtrlSetState(hAC, GIAS_Paused); TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Paused]); } break; case GFA_APPCTRL_CTRLMSG_RESUME: if(g_fPause) { bStateTransition = true; g_fPause = false; ::GfaIpcAppCtrlSetState(hAC, GIAS_Running); TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Running]); } break; case GFA_APPCTRL_CTRLMSG_SYSINFO_UPDATE_STGDEV: bUpdateStgDevInfo = true; break; default: break; } } } ///////////////////////////////////////////////////////////////////////////// static void _LockSHM(HSHM hShm) { ::GfaIpcLockSHMAndSigBlock(hShm, &g_set); } static void _UnlockSHM(HSHM hShm) { ::GfaIpcUnlockSHMAndSigUnblock(hShm, &g_set); } static void _SigHandler(int sig) { TRACE("Received signal '%s'.\n", strsignal(sig)); g_fPause = false; g_fRun = false; g_fZombie = false; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { int c; HAPPCTRL hAC = nullptr; HAPPINFO hAI; CCycleTimer ct(_CYCLE_INTV), perfCnt(0U); cy_time_t wStart, wEnd, wCur = 0; std::string sDbUser, sDbPass; CMySqlInfo mySqlInfo; CStgDevInfo stgDevInfo; CSpiInfo spiInfo; CAdcInfo adcInfo; bool bOsIsHypervised = stgDevInfo.IsSystemHypervised(); bool bTargetHasTiva = spiInfo.TargetHasTiva(); bool bStateTransition, bUpdateStgDevInfo; ///////////////////////////////////////////////////////////////////////// // parse command line options while((c = getopt(argc, argv, "p:u:")) != -1) { switch(c) { case 'p': sDbPass = optarg; break; case 'u': sDbUser = optarg; break; } } ///////////////////////////////////////////////////////////////////////// // signal handling struct sigaction sa; memset(&sa, 0, sizeof(sa)); ::sigfillset(&g_set); // ::sigdelset(&g_set, SIGSEGV); sa.sa_handler = _SigHandler; sigaction(SIGHUP, &sa, nullptr); // handles user's terminal disconnect sigaction(SIGQUIT, &sa, nullptr); // handles Ctrl + '\' sigaction(SIGTERM, &sa, nullptr); // handles normal termination sigaction(SIGABRT, &sa, nullptr); // handles abnormal termination (i.e. abort()) sigaction(SIGINT, &sa, nullptr); // handles Ctrl + 'C' // ignore signals sa.sa_handler = SIG_IGN; sigaction(SIGTSTP, &sa, nullptr); // ignores Ctrl + 'Z' sigaction(SIGCHLD, &sa, nullptr); // ignores child process termination sigaction(0, &sa, nullptr); // ignores shell termination ///////////////////////////////////////////////////////////////////////// // initialize CMySqlInfo::EXEC_PARAMS myep; CStgDevInfo::EXEC_PARAMS step; CSpiInfo::EXEC_PARAMS spep; do { g_fZombie = true; if(!(hAC = ::GfaIpcAppCtrlAcquire(_APPID, _APPNAME, _CYCLE_INTV * 1000, _CYCLE_INTV * 3000))) { TRACE("GfaIpcAppCtrlAcquire failed\n"); break; } ::GfaIpcAppCtrlSetLockUnlockFunctions(hAC, _LockSHM, _UnlockSHM); ::GfaIpcAppCtrlSetState(hAC, GIAS_Initializing); if(!::GfaIpcAppCtrlCreateSysInfo(hAC)) { TRACE("GfaIpcAppCtrlCreateSysInfo failed\n"); break; } ::GfaIpcDumpSHMROT(); TRACE("My Name: %s\n", _APPNAME); TRACE("My AppID: %llu\n", _APPID); TRACE("My PID: %d\n", getpid()); TRACE("My Cycle: %d\n", _CYCLE_INTV); myep = {hAC, sDbUser, sDbPass}; mySqlInfo.Create(&myep); if(!bOsIsHypervised) { step = {hAC}; stgDevInfo.Create(&step); } if(bTargetHasTiva) { spep = {hAC}; spiInfo.Create(&spep); } else { spep = {hAC}; adcInfo.Create(&spep); } g_fZombie = false; g_fRun = true; ::GfaIpcAppCtrlSetState(hAC, GIAS_Running); mySqlInfo.Signal(CMySqlInfo::S_UpdateAll); if(!bOsIsHypervised) stgDevInfo.Signal(CStgDevInfo::S_Init); if(bTargetHasTiva) spiInfo.Signal(CSpiInfo::S_Init); else adcInfo.Signal(CAdcInfo::S_Init); } while(false); ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // run while(g_fRun) { bStateTransition = false; bUpdateStgDevInfo = false; ///////////////////////////////////////////////////////////////////// // trigger cycle timer ct.Trigger(); ///////////////////////////////////////////////////////////////////// // update app control info if((hAI = ::GfaIpcAppCtrlInfoUpdate(hAC, wCur))) { _ProcessCtrlMessages(hAC, hAI, bStateTransition, bUpdateStgDevInfo); } ///////////////////////////////////////////////////////////////////// // if not paused, do work if(g_fRun) { if(bStateTransition) { if(g_fPause) { mySqlInfo.Signal(CMySqlInfo::S_Pause); if(!bOsIsHypervised) stgDevInfo.Signal(CStgDevInfo::S_Pause); if(bTargetHasTiva) spiInfo.Signal(CSpiInfo::S_Pause); else adcInfo.Signal(CAdcInfo::S_Pause); } else { mySqlInfo.Signal(CMySqlInfo::S_Resume); if(!bOsIsHypervised) stgDevInfo.Signal(CStgDevInfo::S_Resume); if(bTargetHasTiva) spiInfo.Signal(CSpiInfo::S_Resume); else adcInfo.Signal(CAdcInfo::S_Resume); } } if(bUpdateStgDevInfo) { if(!bOsIsHypervised) stgDevInfo.Signal(CStgDevInfo::S_Update); } if(!g_fPause) { wStart = ct.GetMicroTick(); ::GfaIpcAppCtrlUpdateSysInfo(hAC); wEnd = ct.GetMicroTick(); wCur = wEnd - wStart; } ct.Sleep1(); } else { ::GfaIpcAppCtrlSetState(hAC, GIAS_Terminating); } } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // terminate mySqlInfo.Signal(CMySqlInfo::S_Terminate); if(!bOsIsHypervised) stgDevInfo.Signal(CStgDevInfo::S_Terminate); if(bTargetHasTiva) spiInfo.Signal(CSpiInfo::S_Terminate); else adcInfo.Signal(CAdcInfo::S_Terminate); mySqlInfo.Join(nullptr); if(!bOsIsHypervised) stgDevInfo.Join(nullptr); if(bTargetHasTiva) spiInfo.Join(nullptr); else adcInfo.Join(nullptr); if(g_fZombie) { if(hAC) ::GfaIpcAppCtrlSetState(hAC, GIAS_Zombie); TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Zombie)); pause(); if(hAC) ::GfaIpcAppCtrlSetState(hAC, GIAS_Terminating); } if(hAC) { ::GfaIpcAppCtrlReleaseSysInfo(hAC); ::GfaIpcAppCtrlRelease(hAC); } return 0; }