main.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <string.h>
  4. #include <signal.h>
  5. #include <poll.h>
  6. #include <vector>
  7. #include <gfa/gfasitarautils.h>
  8. #include <gfa/gfaipc.h>
  9. #include "../src/defines.h"
  10. #include "app.h"
  11. /////////////////////////////////////////////////////////////////////////////
  12. #define _APPNAME_MQTTCL "MQTTCL"
  13. #define _APPNAME_REMANENT "Remanent"
  14. #define _APPNAME_REST "REST"
  15. #define _CTRL_MSG_HANG 0x08
  16. #define _CTRL_MSG_ALLOC 0x10
  17. #define _CTRL_MSG_FREE 0x20
  18. #define _CTRL_MSG_ZOMBIE 0x40
  19. #define _HANG_LOOPS 1000000000
  20. #define _NORMAL_LOOPS 100000
  21. #define _MEM_WASTE_SIZE 524288
  22. /////////////////////////////////////////////////////////////////////////////
  23. #define UNUSED(v) (void)v
  24. static volatile bool g_fRun = false;
  25. static volatile bool g_fPause = false;
  26. static volatile bool g_fHang = false;
  27. static volatile bool g_fZombie = false;
  28. static volatile bool g_fAlloc = false;
  29. static volatile bool g_fFree = false;
  30. static volatile bool g_fSysInfoRunning = false;
  31. /////////////////////////////////////////////////////////////////////////////
  32. static std::vector<void*> g_vP;
  33. /////////////////////////////////////////////////////////////////////////////
  34. static void _SigHandler(int sig)
  35. {
  36. UNUSED(sig);
  37. g_fPause = false;
  38. g_fRun = false;
  39. g_fZombie = false;
  40. }
  41. /////////////////////////////////////////////////////////////////////////////
  42. static int _InputAvailable(void)
  43. {
  44. static struct pollfd poIn[1] = {{0, POLLIN, 0}};
  45. int n = poll(poIn, 1, 0);
  46. return n;
  47. }
  48. /////////////////////////////////////////////////////////////////////////////
  49. static void _ProcessCtrlMessages(HAPPCTRL hAC, HAPPINFO hAI)
  50. {
  51. ctrlmsg_t nCtrlMsg;
  52. while(g_fRun && (nCtrlMsg = ::GfaIpcAppCtrlGetNextCtrlMsg(hAI)))
  53. {
  54. switch(nCtrlMsg)
  55. {
  56. case GFA_APPCTRL_CTRLMSG_STOP:
  57. g_fRun = false;
  58. TRACE("Received Message: STOP!\n");
  59. break;
  60. case GFA_APPCTRL_CTRLMSG_PAUSE:
  61. if(!g_fPause)
  62. {
  63. g_fPause = true;
  64. ::GfaIpcAppCtrlSetState(hAC, GIAS_Paused);
  65. TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Paused));
  66. }
  67. break;
  68. case GFA_APPCTRL_CTRLMSG_RESUME:
  69. if(g_fPause)
  70. {
  71. g_fPause = false;
  72. ::GfaIpcAppCtrlSetState(hAC, GIAS_Running);
  73. TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Running));
  74. }
  75. break;
  76. case _CTRL_MSG_HANG:
  77. g_fHang = true;
  78. break;
  79. case _CTRL_MSG_ALLOC:
  80. g_fAlloc = true;
  81. break;
  82. case _CTRL_MSG_FREE:
  83. g_fFree = true;
  84. break;
  85. case _CTRL_MSG_ZOMBIE:
  86. g_fRun = false;
  87. g_fZombie = true;
  88. break;
  89. default:
  90. break;
  91. }
  92. }
  93. }
  94. /////////////////////////////////////////////////////////////////////////////
  95. static void _ProcessStateEvents(HAPPCTRL hAC, HAPPINFO hAI)
  96. {
  97. appid_t nAppIdSrc;
  98. char szDispName[128];
  99. while(g_fRun && (nAppIdSrc = ::GfaIpcAppCtrlGetNextStateEvtSrc(hAI)))
  100. {
  101. GfaIpcAppStates state = ::GfaIpcAppCtrlGetState(hAC, nAppIdSrc);
  102. GfaIpcAppCtrlGetDisplayName(hAC, nAppIdSrc, szDispName, sizeof(szDispName));
  103. TRACE("%-8s: State: %s\n", szDispName, ::GfaIpcAppCtrlGetStateText(state));
  104. switch(nAppIdSrc)
  105. {
  106. case GFA_APPCTRL_APPID_REMANENT:
  107. if(state == GIAS_Running)
  108. {
  109. if(g_fPause)
  110. {
  111. g_fPause = false;
  112. ::GfaIpcAppCtrlSetState(hAC, GIAS_Running);
  113. TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Running));
  114. }
  115. }
  116. else
  117. {
  118. if(!g_fPause)
  119. {
  120. g_fPause = true;
  121. ::GfaIpcAppCtrlSetState(hAC, GIAS_Paused);
  122. TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Paused));
  123. }
  124. }
  125. break;
  126. case GFA_APPCTRL_APPID_SYSINFO:
  127. if(!(g_fSysInfoRunning = (state == GIAS_Running)))
  128. {
  129. TRACE("SysInfo not running - System information not available!\n");
  130. }
  131. else
  132. {
  133. TRACE("SysInfo running - System information is available!\n");
  134. }
  135. break;
  136. }
  137. }
  138. }
  139. /////////////////////////////////////////////////////////////////////////////
  140. static void _ProcessSystemEvents(HAPPCTRL hAC, HAPPINFO hAI)
  141. {
  142. int nIndex;
  143. sysevt_t nEvent;
  144. GFA_SYSINFO_DISK disk;
  145. GFA_SYSINFO_PARTITION part;
  146. if(!g_fSysInfoRunning)
  147. return;
  148. while(g_fRun && (nEvent = ::GfaIpcAppCtrlGetNextSysEvt(hAI)))
  149. {
  150. switch(nEvent)
  151. {
  152. case GFA_APPCTRL_SYSEVENT_DISK_EVT:
  153. while((nIndex = ::GfaIpcAppCtrlGetNextDiskRemoved(hAC, &disk)) >= 0)
  154. {
  155. TRACE("Disk [ID=%d] removed: %s [%s]\n", nIndex, disk.szDevNode, *disk.szName ? disk.szName : "Unnamed");
  156. }
  157. while((nIndex = ::GfaIpcAppCtrlGetNextDiskAdded(hAC, &disk)) >= 0)
  158. {
  159. TRACE("Disk [ID=%d] added: %s [%s]\n", nIndex, disk.szDevNode, *disk.szName ? disk.szName : "Unnamed");
  160. }
  161. break;
  162. case GFA_APPCTRL_SYSEVENT_PART_EVT:
  163. while((nIndex = ::GfaIpcAppCtrlGetNextPartitionRemoved(hAC, &part)) >= 0)
  164. {
  165. TRACE("Partition [ID=%d:%d] removed: %s [%s]\n", part.nDiskIdx, nIndex, part.szDevNode, *part.szFsLabel ? part.szFsLabel : "Unnamed");
  166. }
  167. while((nIndex = ::GfaIpcAppCtrlGetNextPartitionAdded(hAC, &part)) >= 0)
  168. {
  169. TRACE("Partition [ID=%d:%d] added: %s [%s]\n", part.nDiskIdx, nIndex, part.szDevNode, *part.szFsLabel ? part.szFsLabel : "Unnamed");
  170. }
  171. break;
  172. case GFA_APPCTRL_SYSEVENT_MOUNT_EVT:
  173. while((nIndex = ::GfaIpcAppCtrlGetNextMountRemoved(hAC, &part)) >= 0)
  174. {
  175. TRACE("Partition [ID=%d:%d] unmounted: %s\n", part.nDiskIdx, nIndex, part.szDevNode);
  176. }
  177. while((nIndex = ::GfaIpcAppCtrlGetNextMountAdded(hAC, &part)) >= 0)
  178. {
  179. TRACE("Partition [ID=%d:%d] mounted: %s -> %s\n", part.nDiskIdx, nIndex, part.szDevNode, part.szMntPoint);
  180. }
  181. break;
  182. }
  183. }
  184. }
  185. /////////////////////////////////////////////////////////////////////////////
  186. static void _ProcessInput(HAPPCTRL hAC)
  187. {
  188. if(_InputAvailable())
  189. {
  190. ctrlmsg_t msg = 0;
  191. appid_t aiTarget = 0;
  192. int nRet = scanf("%llu %llu", &aiTarget, &msg);
  193. if(nRet == 2)
  194. {
  195. ::GfaIpcAppCtrlSendCtrlMsg(hAC, aiTarget, msg);
  196. }
  197. }
  198. }
  199. /////////////////////////////////////////////////////////////////////////////
  200. static int _DoWork(void)
  201. {
  202. int i, j = 0, k = _NORMAL_LOOPS;
  203. if(g_fAlloc)
  204. {
  205. TRACE("Allocating %d KiB of memory.\n", _MEM_WASTE_SIZE >> 10);
  206. void *p = malloc(_MEM_WASTE_SIZE);
  207. g_vP.push_back(p);
  208. g_fAlloc = false;
  209. UNUSED(p);
  210. }
  211. if(g_fFree)
  212. {
  213. TRACE("Freeing memory.\n");
  214. for(auto i = g_vP.begin(); i != g_vP.end(); i++)
  215. {
  216. free(*i);
  217. }
  218. g_vP.clear();
  219. g_fFree = false;
  220. }
  221. if(g_fHang)
  222. {
  223. k = _HANG_LOOPS;
  224. TRACE("Performing %d nonsense loops.\n", k);
  225. g_fHang = false;
  226. }
  227. for(i = 0; i < k; ++i)
  228. {
  229. j += 4;
  230. j -= 2;
  231. j += 1;
  232. j -= 3;
  233. }
  234. return j;
  235. }
  236. /////////////////////////////////////////////////////////////////////////////
  237. /////////////////////////////////////////////////////////////////////////////
  238. /////////////////////////////////////////////////////////////////////////////
  239. int main(void)
  240. {
  241. HAPPCTRL hAC = NULL;
  242. HAPPINFO hAI;
  243. /////////////////////////////////////////////////////////////////////////
  244. /////////////////////////////////////////////////////////////////////////
  245. /////////////////////////////////////////////////////////////////////////
  246. // signal handling
  247. struct sigaction sa;
  248. memset(&sa, 0, sizeof(sa));
  249. // handle signals
  250. sa.sa_handler = _SigHandler;
  251. sigaction(SIGHUP, &sa, NULL); // handles user's terminal disconnect
  252. sigaction(SIGQUIT, &sa, NULL); // handles Ctrl + '\'
  253. sigaction(SIGTERM, &sa, NULL); // handles normal termination
  254. sigaction(SIGABRT, &sa, NULL); // handles abnormal termination (i.e. abort())
  255. sigaction(SIGINT, &sa, NULL); // handles Ctrl + 'C'
  256. // ignore signals
  257. sa.sa_handler = SIG_IGN;
  258. sigaction(SIGTSTP, &sa, NULL); // ignores Ctrl + 'Z'
  259. sigaction(SIGCHLD, &sa, NULL); // ignores child process termination
  260. sigaction(0, &sa, NULL); // ignores shell termination
  261. /////////////////////////////////////////////////////////////////////////
  262. /////////////////////////////////////////////////////////////////////////
  263. /////////////////////////////////////////////////////////////////////////
  264. // initialize
  265. do
  266. {
  267. g_fZombie = true;
  268. if(!(hAC = ::GfaIpcAppCtrlAcquire(_APPID_0, _APPNAME_0, _CYCLE_INTV * 1000, _CYCLE_INTV * 3000)))
  269. break;
  270. ;;GfaIpcDumpSHMROT();
  271. ::GfaIpcAppCtrlPresetDisplayName(hAC, GFA_APPCTRL_APPID_USER_01, "qmlApp");
  272. ::GfaIpcAppCtrlSetState(hAC, GIAS_Initializing);
  273. if(!::GfaIpcAppCtrlSubscribeStateEvents(hAC, _APPID_1 | _APPID_2 | GFA_APPCTRL_APPID_USER_01 | GFA_APPCTRL_APPID_SYSINFO | GFA_APPCTRL_APPID_DATALOGGER))
  274. break;
  275. if(!::GfaIpcAppCtrlSubscribeSysEvents(hAC, GFA_APPCTRL_SYSEVENT_ALL_STG_DEV))
  276. break;
  277. TRACE("My Name: %s\n", _APPNAME_0);
  278. TRACE("My AppID: %llu\n", _APPID_0);
  279. TRACE("My PID: %d\n", getpid());
  280. TRACE("My Cycle: %d\n", _CYCLE_INTV);
  281. g_fZombie = false;
  282. g_fRun = true;
  283. ::GfaIpcAppCtrlSetState(hAC, GIAS_Running);
  284. }
  285. while(false);
  286. /////////////////////////////////////////////////////////////////////////
  287. /////////////////////////////////////////////////////////////////////////
  288. /////////////////////////////////////////////////////////////////////////
  289. // run
  290. CCycleTimer ct(_CYCLE_INTV);
  291. cy_time_t wStart, wEnd, wCur = 0;
  292. while(g_fRun)
  293. {
  294. /////////////////////////////////////////////////////////////////////
  295. // trigger cycle timer
  296. ct.Trigger();
  297. /////////////////////////////////////////////////////////////////////
  298. // test input
  299. _ProcessInput(hAC);
  300. /////////////////////////////////////////////////////////////////////
  301. // update app control info
  302. if((hAI = ::GfaIpcAppCtrlInfoUpdate(hAC, wCur)))
  303. {
  304. _ProcessCtrlMessages(hAC, hAI);
  305. _ProcessStateEvents(hAC, hAI);
  306. _ProcessSystemEvents(hAC, hAI);
  307. }
  308. /////////////////////////////////////////////////////////////////////
  309. // if not paused, do work
  310. if(!g_fPause && g_fRun)
  311. {
  312. wStart = ct.GetMicroTick();
  313. _DoWork();
  314. wEnd = ct.GetMicroTick();
  315. wCur = wEnd - wStart;
  316. }
  317. /////////////////////////////////////////////////////////////////////
  318. // if running, sleep
  319. if(g_fRun)
  320. ct.Sleep1();
  321. }
  322. /////////////////////////////////////////////////////////////////////////
  323. /////////////////////////////////////////////////////////////////////////
  324. /////////////////////////////////////////////////////////////////////////
  325. // terminate
  326. if(g_fZombie)
  327. {
  328. if(hAC)
  329. ::GfaIpcAppCtrlSetState(hAC, GIAS_Zombie);
  330. TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Zombie));
  331. pause();
  332. }
  333. if(hAC)
  334. {
  335. ::GfaIpcAppCtrlSetState(hAC, GIAS_Terminating);
  336. TRACE("%-8s: State: %s\n", "Me", ::GfaIpcAppCtrlGetStateText(GIAS_Terminating));
  337. ::GfaIpcAppCtrlRelease(hAC);
  338. }
  339. return 0;
  340. }