#include #include #include #include #include #include #include #include #include "../src/defines.h" #include "app.h" ///////////////////////////////////////////////////////////////////////////// #define _APPNAME_MQTTCL "MQTTCL" #define _APPNAME_REMANENT "Remanent" #define _APPNAME_REST "REST" #define _CTRL_MSG_HANG 0x08 #define _CTRL_MSG_ALLOC 0x10 #define _CTRL_MSG_FREE 0x20 #define _CTRL_MSG_ZOMBIE 0x40 #define _HANG_LOOPS 1000000000 #define _NORMAL_LOOPS 100000 #define _MEM_WASTE_SIZE 524288 ///////////////////////////////////////////////////////////////////////////// #define UNUSED(v) (void)v static volatile bool g_fRun = false; static volatile bool g_fPause = false; static volatile bool g_fHang = false; static volatile bool g_fZombie = false; static volatile bool g_fAlloc = false; static volatile bool g_fFree = false; static volatile bool g_fSysInfoRunning = false; ///////////////////////////////////////////////////////////////////////////// static std::vector g_vP; ///////////////////////////////////////////////////////////////////////////// static void _SigHandler(int sig) { UNUSED(sig); g_fPause = false; g_fRun = false; g_fZombie = false; } ///////////////////////////////////////////////////////////////////////////// static int _InputAvailable(void) { static struct pollfd poIn[1] = {{0, POLLIN, 0}}; int n = poll(poIn, 1, 0); return n; } ///////////////////////////////////////////////////////////////////////////// static void _ProcessCtrlMessages(HAPPCTRL hAC, HAPPINFO hAI) { ctrlmsg_t nCtrlMsg; while(g_fRun && (nCtrlMsg = ::GfaIpcAppCtrlGetNextCtrlMsg(hAI))) { switch(nCtrlMsg) { case GFA_APPCTRL_CTRLMSG_STOP: g_fRun = false; TRACE("Received Message: STOP!\n"); break; case GFA_APPCTRL_CTRLMSG_PAUSE: if(!g_fPause) { g_fPause = true; ::GfaIpcAppCtrlSetState(hAC, GIAS_Paused); TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Paused)); } break; case GFA_APPCTRL_CTRLMSG_RESUME: if(g_fPause) { g_fPause = false; ::GfaIpcAppCtrlSetState(hAC, GIAS_Running); TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Running)); } break; case _CTRL_MSG_HANG: g_fHang = true; break; case _CTRL_MSG_ALLOC: g_fAlloc = true; break; case _CTRL_MSG_FREE: g_fFree = true; break; case _CTRL_MSG_ZOMBIE: g_fRun = false; g_fZombie = true; break; default: break; } } } ///////////////////////////////////////////////////////////////////////////// static void _ProcessStateEvents(HAPPCTRL hAC, HAPPINFO hAI) { appid_t nAppIdSrc; char szDispName[128]; while(g_fRun && (nAppIdSrc = ::GfaIpcAppCtrlGetNextStateEvtSrc(hAI))) { GfaIpcAppStates state = ::GfaIpcAppCtrlGetState(hAC, nAppIdSrc); GfaIpcAppCtrlGetDisplayName(hAC, nAppIdSrc, szDispName, sizeof(szDispName)); TRACE("%-8s: State: %s\n", szDispName, ::GfaIpcAppCtrlGetStateText(state)); switch(nAppIdSrc) { case GFA_APPCTRL_APPID_REMANENT: if(state == GIAS_Running) { if(g_fPause) { g_fPause = false; ::GfaIpcAppCtrlSetState(hAC, GIAS_Running); TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Running)); } } else { if(!g_fPause) { g_fPause = true; ::GfaIpcAppCtrlSetState(hAC, GIAS_Paused); TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Paused)); } } break; case GFA_APPCTRL_APPID_SYSINFO: if(!(g_fSysInfoRunning = (state == GIAS_Running))) { TRACE("SysInfo not running - System information not available!\n"); } else { TRACE("SysInfo running - System information is available!\n"); } break; } } } ///////////////////////////////////////////////////////////////////////////// static void _ProcessSystemEvents(HAPPCTRL hAC, HAPPINFO hAI) { int nIndex; sysevt_t nEvent; GFA_SYSINFO_DISK disk; GFA_SYSINFO_PARTITION part; if(!g_fSysInfoRunning) return; while(g_fRun && (nEvent = ::GfaIpcAppCtrlGetNextSysEvt(hAI))) { switch(nEvent) { case GFA_APPCTRL_SYSEVENT_DISK_EVT: while((nIndex = ::GfaIpcAppCtrlGetNextDiskRemoved(hAC, &disk)) >= 0) { TRACE("Disk [ID=%d] removed: %s [%s]\n", nIndex, disk.szDevNode, *disk.szName ? disk.szName : "Unnamed"); } while((nIndex = ::GfaIpcAppCtrlGetNextDiskAdded(hAC, &disk)) >= 0) { TRACE("Disk [ID=%d] added: %s [%s]\n", nIndex, disk.szDevNode, *disk.szName ? disk.szName : "Unnamed"); } break; case GFA_APPCTRL_SYSEVENT_PART_EVT: while((nIndex = ::GfaIpcAppCtrlGetNextPartitionRemoved(hAC, &part)) >= 0) { TRACE("Partition [ID=%d:%d] removed: %s [%s]\n", part.nDiskIdx, nIndex, part.szDevNode, *part.szFsLabel ? part.szFsLabel : "Unnamed"); } while((nIndex = ::GfaIpcAppCtrlGetNextPartitionAdded(hAC, &part)) >= 0) { TRACE("Partition [ID=%d:%d] added: %s [%s]\n", part.nDiskIdx, nIndex, part.szDevNode, *part.szFsLabel ? part.szFsLabel : "Unnamed"); } break; case GFA_APPCTRL_SYSEVENT_MOUNT_EVT: while((nIndex = ::GfaIpcAppCtrlGetNextMountRemoved(hAC, &part)) >= 0) { TRACE("Partition [ID=%d:%d] unmounted: %s\n", part.nDiskIdx, nIndex, part.szDevNode); } while((nIndex = ::GfaIpcAppCtrlGetNextMountAdded(hAC, &part)) >= 0) { TRACE("Partition [ID=%d:%d] mounted: %s -> %s\n", part.nDiskIdx, nIndex, part.szDevNode, part.szMntPoint); } break; } } } ///////////////////////////////////////////////////////////////////////////// static void _ProcessInput(HAPPCTRL hAC) { if(_InputAvailable()) { ctrlmsg_t msg = 0; appid_t aiTarget = 0; int nRet = scanf("%llu %llu", &aiTarget, &msg); if(nRet == 2) { ::GfaIpcAppCtrlSendCtrlMsg(hAC, aiTarget, msg); } } } ///////////////////////////////////////////////////////////////////////////// static int _DoWork(void) { int i, j = 0, k = _NORMAL_LOOPS; if(g_fAlloc) { TRACE("Allocating %d KiB of memory.\n", _MEM_WASTE_SIZE >> 10); void *p = malloc(_MEM_WASTE_SIZE); g_vP.push_back(p); g_fAlloc = false; UNUSED(p); } if(g_fFree) { TRACE("Freeing memory.\n"); for(auto i = g_vP.begin(); i != g_vP.end(); i++) { free(*i); } g_vP.clear(); g_fFree = false; } if(g_fHang) { k = _HANG_LOOPS; TRACE("Performing %d nonsense loops.\n", k); g_fHang = false; } for(i = 0; i < k; ++i) { j += 4; j -= 2; j += 1; j -= 3; } return j; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// int main(void) { HAPPCTRL hAC = NULL; HAPPINFO hAI; ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // signal handling struct sigaction sa; memset(&sa, 0, sizeof(sa)); // handle signals sa.sa_handler = _SigHandler; sigaction(SIGHUP, &sa, NULL); // handles user's terminal disconnect sigaction(SIGQUIT, &sa, NULL); // handles Ctrl + '\' sigaction(SIGTERM, &sa, NULL); // handles normal termination sigaction(SIGABRT, &sa, NULL); // handles abnormal termination (i.e. abort()) sigaction(SIGINT, &sa, NULL); // handles Ctrl + 'C' // ignore signals sa.sa_handler = SIG_IGN; sigaction(SIGTSTP, &sa, NULL); // ignores Ctrl + 'Z' sigaction(SIGCHLD, &sa, NULL); // ignores child process termination sigaction(0, &sa, NULL); // ignores shell termination ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // initialize do { g_fZombie = true; if(!(hAC = ::GfaIpcAppCtrlAcquire(_APPID_0, _APPNAME_0, _CYCLE_INTV * 1000, _CYCLE_INTV * 3000))) break; ;;GfaIpcDumpSHMROT(); ::GfaIpcAppCtrlPresetDisplayName(hAC, GFA_APPCTRL_APPID_USER_01, "qmlApp"); ::GfaIpcAppCtrlSetState(hAC, GIAS_Initializing); if(!::GfaIpcAppCtrlSubscribeStateEvents(hAC, _APPID_1 | _APPID_2 | GFA_APPCTRL_APPID_USER_01 | GFA_APPCTRL_APPID_SYSINFO)) break; if(!::GfaIpcAppCtrlSubscribeSysEvents(hAC, GFA_APPCTRL_SYSEVENT_ALL_STG_DEV)) break; TRACE("My Name: %s\n", _APPNAME_0); TRACE("My AppID: %llu\n", _APPID_0); TRACE("My PID: %d\n", getpid()); TRACE("My Cycle: %d\n", _CYCLE_INTV); g_fZombie = false; g_fRun = true; ::GfaIpcAppCtrlSetState(hAC, GIAS_Running); } while(false); ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // run CCycleTimer ct(_CYCLE_INTV); cy_time_t wStart, wEnd, wCur = 0; while(g_fRun) { ///////////////////////////////////////////////////////////////////// // trigger cycle timer ct.Trigger(); ///////////////////////////////////////////////////////////////////// // test input _ProcessInput(hAC); ///////////////////////////////////////////////////////////////////// // update app control info if((hAI = ::GfaIpcAppCtrlInfoUpdate(hAC, wCur))) { _ProcessCtrlMessages(hAC, hAI); _ProcessStateEvents(hAC, hAI); _ProcessSystemEvents(hAC, hAI); } ///////////////////////////////////////////////////////////////////// // if not paused, do work if(!g_fPause && g_fRun) { wStart = ct.GetMicroTick(); _DoWork(); wEnd = ct.GetMicroTick(); wCur = wEnd - wStart; } ///////////////////////////////////////////////////////////////////// // if running, sleep if(g_fRun) ct.Sleep1(); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // terminate 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); TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Terminating)); ::GfaIpcAppCtrlRelease(hAC); } return 0; }