#include #include #include #include #include #include #include #include #include #include "defines.h" #include "uuid.h" #include "appctrl.h" ///////////////////////////////////////////////////////////////////////////// #define _countof(a) (sizeof(a) / sizeof(*a)) #define _INVALID_SLOT_INDEX -1 #define _IS_POWER_OF_2(x) (!!(x) && !((x) & ((x) - 1))) #define _IS_VALID_SLOT_INDEX(i) ((i) >= 0) && ((i) < _APP_CTRL_MAX_SLOTS) #define _IS_VALID_APP_ID(i) _IS_POWER_OF_2(i) #define _IS_VALID_APP_STATE(s) (((s) >= GIAS_StateNotRunning) && ((s) < GIAS_Invalid)) #define _IS_VALID_CTRL_MSG(m) _IS_POWER_OF_2(m) #define _APP_INDEX_FROM_APP_ID(aid) (ffsll(aid) - 1) #define _TIMESPEC_2_US(ts) (((clock64_t)(ts).tv_sec) * 1000000LL + ((clock64_t)(ts).tv_nsec) / 1000LL) #define _TIMESPEC_DIFF(ts1, ts2) (_TIMESPEC_2_US(ts1) - _TIMESPEC_2_US(ts2)) #define _APP_CTRL_MAX_MSG_BITS ((int)(sizeof(ctrlmsg_t) * 8)) #define _IS_KNOWN_APP_INDEX(i) (((i) >= 0) && ((i) < (int)_countof(g_pszKnownAppNames))) #define _MIN_CPU_UPDATE_INTERVAL_US 5000000 #define _COPY_DISK(pd, ps) memcpy(&pd, &ps, sizeof(pd)) #define _DELETE_DISK(pd) pd.valid = false #define _COPY_PARTITION(pd, ps) memcpy(&pd, &ps, sizeof(pd)) #define _DELETE_PARTITION(pd) pd.valid = false #define _COPY_MOUNTPOINT(pd, ps) memcpy(pd.szMntPoint, ps.szMntPoint, sizeof(pd.szMntPoint)), \ pd.nKiBSize = ps.nKiBSize, \ pd.nKiBFree = ps.nKiBFree, \ pd.nKiBUsed = ps.nKiBUsed #define _DELETE_MOUNTPOINT(pd) memset(pd.szMntPoint, 0, sizeof(pd.szMntPoint)) ///////////////////////////////////////////////////////////////////////////// static const char *g_pszKnownAppNames[] = { "Remanent", "Datalogger", "Summarist", "REST", "MqttCl", "GfaSysInfo", "GEB" }; static_assert(_countof(g_pszKnownAppNames) == (GAI_Last - GAI_Remanent), "enum GfaAppIndex does not meet string representation in g_pszKnownAppNames!"); ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// CAppCtrl::CAppCtrlShmLocker::CAppCtrlShmLocker(CAppCtrl &rac) : m_rac(rac) { m_rac.Lock(); m_bLocked = true; } CAppCtrl::CAppCtrlShmLocker::~CAppCtrlShmLocker(void) { Unlock(); } void CAppCtrl::CAppCtrlShmLocker::Unlock(void) { if(m_bLocked) { m_rac.Unlock(); m_bLocked = false; } } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// HSHM CAppCtrl::m_hShm = NULL; CAppCtrl::CAppCtrl(void) : m_pAppCtrl(NULL), m_nSlotIdx(_INVALID_SLOT_INDEX), m_nAppID(0), m_nLockCount(0), m_nLastTimesCallUs(0), m_pfnLockSHM(::GfaIpcLockSHM), m_pfnUnlockSHM(::GfaIpcUnlockSHM) { struct timespec ts; ::clock_gettime(CLOCK_MONOTONIC, &ts); m_nClockStartUs = _TIMESPEC_2_US(ts); m_nClkTicksPerSec = sysconf(_SC_CLK_TCK); m_pid = getpid(); memset(&m_ai, 0, sizeof(m_ai)); } CAppCtrl::~CAppCtrl(void) { Release(); } ///////////////////////////////////////////////////////////////////////////// const char* CAppCtrl::GetAppPath(char *pszPath, size_t nCChPath, pid_t pid) { if(pid == 0) pid = getpid(); char szTmp[32]; if(!pszPath || !nCChPath) { errno = EINVAL; return NULL; } sprintf(szTmp, "/proc/%d/exe", pid); ssize_t nLen = readlink(szTmp, pszPath, nCChPath - 1); if(nLen < 0) { *pszPath = '\0'; return NULL; } pszPath[nLen] = '\0'; return pszPath; } ///////////////////////////////////////////////////////////////////////////// size_t CAppCtrl::GetAppSize(const char *pszAppPath) { struct stat st; if(!::stat(pszAppPath, &st)) return st.st_size; return 0; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::Create(appid_t nAppID, const char *pszDisplayName, clock64_t nCycleIntvUs, clock64_t nMaxHeartbeatDelay) { if(m_hShm) return false; if(!_IS_VALID_APP_ID(nAppID)) return false; if( pszDisplayName && (strlen(pszDisplayName) >= _APP_CTRL_MAX_DISPLAY_NAME_LENGTH)) return false; if(nCycleIntvUs < 0) return false; if((nMaxHeartbeatDelay < 0) || (nMaxHeartbeatDelay < nCycleIntvUs)) return false; char szAppPath[_APP_CTRL_MAX_APP_PATH_LENGTH]; if(!CAppCtrl::GetAppPath(szAppPath, sizeof(szAppPath), m_pid)) return false; if(!m_procMem.Update()) return false; if((m_hShm = ::GfaIpcAcquireSHM(_UUID_SHM_APP_CTRL, sizeof(APP_CTRL), 1, _NAME_SHM_APP_CTRL))) { bool bResetSlot = true; if((m_pAppCtrl = (LPAPP_CTRL)::GfaIpcAcquirePointer(m_hShm))) { m_nSlotIdx = SlotIndexFromAppID(nAppID); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; CAppCtrlShmLocker locker(*this); if((proc.nAppID == nAppID)) { if(!strcmp(proc.szAppPath, szAppPath)) { pid_t pid = getpgid(proc.pid); if((pid < 0) && (errno == ESRCH)) { Release(); return Create(nAppID, pszDisplayName, nCycleIntvUs, nMaxHeartbeatDelay); } } else { } bResetSlot = false; } else { memset(&proc, 0, sizeof(APP_CTRL_PROCESS)); proc.at.nTsStart = time(NULL); proc.pid = m_pid; proc.nAppID = m_nAppID = nAppID; proc.at.nCyclePresetUs = nCycleIntvUs; proc.at.nMaxHeartbeatDelay = nMaxHeartbeatDelay; if(pszDisplayName) strcpy(proc.szDisplayName, pszDisplayName); strcpy(proc.szAppPath, szAppPath); proc.nAppFileSize = (uint32_t)GetAppSize(szAppPath); return true; } } Release(bResetSlot); } return false; } ///////////////////////////////////////////////////////////////////////////// void CAppCtrl::Release(bool bResetSlot) { if(m_hShm) { if(m_pAppCtrl) { if(_IS_VALID_SLOT_INDEX(m_nSlotIdx)) { if(bResetSlot) { CAppCtrlShmLocker locker(*this); SetAppState(GIAS_StateNotRunning); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; proc.nAppID = 0; } m_nSlotIdx = _INVALID_SLOT_INDEX; } ::GfaIpcReleasePointer(m_hShm, m_pAppCtrl); m_pAppCtrl = NULL; } ::GfaIpcReleaseSHM(m_hShm); m_hShm = NULL; } m_nAppID = 0; } ///////////////////////////////////////////////////////////////////////////// appid_t CAppCtrl::GetRunningAppsMask(void) { appid_t mask = 0; if(m_hShm) { CAppCtrlShmLocker locker(*this); for(int i = 0; i < _APP_CTRL_MAX_SLOTS; ++i) { const APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[i]; if(_IS_VALID_APP_ID(proc.nAppID)) mask |= proc.nAppID; } } return mask; } void CAppCtrl::TriggertHeartBeat(void) { struct timespec tsCur; APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; ::clock_gettime(CLOCK_MONOTONIC, &tsCur); CAppCtrlShmLocker locker(*this); proc.nHeartbeatLastUs = proc.nHeartbeatCurUs; proc.nHeartbeatCurUs = _TIMESPEC_2_US(tsCur); } ///////////////////////////////////////////////////////////////////////////// LPAPP_CTRL_INFO CAppCtrl::AppInfoUpdate(clock64_t nCurWorkingTime) { if(m_hShm) { struct timespec tsCur; APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; CAppCtrlShmLocker locker(*this); m_ai.nStateEvtPending = proc.nStateEvtPending; m_ai.nCtrlMsgPending = proc.nCtrlMsgPending; m_ai.nSysEvtPending = proc.nSysEvtPending & ~(GFA_APPCTRL_SYSEVENT_DISK_EVT | GFA_APPCTRL_SYSEVENT_PART_EVT | GFA_APPCTRL_SYSEVENT_MOUNT_EVT); // not GFA_APPCTRL_SYSEVENT_STG_DEV_UPDT_EVT!!! proc.nStateEvtPending = 0; proc.nCtrlMsgPending = 0; proc.nSysEvtPending = 0; if(sys.nPidInCharge) { if(proc.nSysEvtRegistered & GFA_APPCTRL_SYSEVENT_DISK_EVT) { if((proc.nDiskAdded = (proc.nDiskMask ^ sys.nDiskMask) & sys.nDiskMask)) m_ai.nSysEvtPending |= GFA_APPCTRL_SYSEVENT_DISK_EVT; if((proc.nDiskRemoved = (proc.nDiskMask ^ sys.nDiskMask) & ~sys.nDiskMask)) m_ai.nSysEvtPending |= GFA_APPCTRL_SYSEVENT_DISK_EVT; } if(proc.nSysEvtRegistered & GFA_APPCTRL_SYSEVENT_PART_EVT) { if((proc.nPartAdded = (proc.nPartMask ^ sys.nPartMask) & sys.nPartMask)) m_ai.nSysEvtPending |= GFA_APPCTRL_SYSEVENT_PART_EVT; if((proc.nPartRemoved = (proc.nPartMask ^ sys.nPartMask) & ~sys.nPartMask)) m_ai.nSysEvtPending |= GFA_APPCTRL_SYSEVENT_PART_EVT; } if(proc.nSysEvtRegistered & GFA_APPCTRL_SYSEVENT_MOUNT_EVT) { if((proc.nMountAdded = (proc.nMountMask ^ sys.nMountMask) & sys.nMountMask)) m_ai.nSysEvtPending |= GFA_APPCTRL_SYSEVENT_MOUNT_EVT; if((proc.nMountRemoved = (proc.nMountMask ^ sys.nMountMask) & ~sys.nMountMask)) m_ai.nSysEvtPending |= GFA_APPCTRL_SYSEVENT_MOUNT_EVT; } proc.nDiskMask = sys.nDiskMask; proc.nPartMask = sys.nPartMask; proc.nMountMask = sys.nMountMask; } ::clock_gettime(CLOCK_MONOTONIC, &tsCur); proc.nHeartbeatLastUs = proc.nHeartbeatCurUs; proc.nHeartbeatCurUs = _TIMESPEC_2_US(tsCur); if(((uint64_t)proc.nHeartbeatCurUs - (uint64_t)m_nLastTimesCallUs) > _MIN_CPU_UPDATE_INTERVAL_US) { struct tms tms; clock64_t nCpuUsrTimeOldUs = proc.at.nCpuUsrTimeUs; clock64_t nCpuKerTimeOldUs = proc.at.nCpuKerTimeUs; if(times(&tms) != -1) { proc.at.nCpuUsrTimeUs = (clock64_t)tms.tms_utime * 1000000 / m_nClkTicksPerSec; proc.at.nCpuKerTimeUs = (clock64_t)tms.tms_stime * 1000000 / m_nClkTicksPerSec; proc.at.fCpuTime = (double)(proc.at.nCpuUsrTimeUs + proc.at.nCpuKerTimeUs) / 1000000.0; } static struct tms tmsLast = tms; double fUpClockUs = llabs(proc.nHeartbeatCurUs - m_nClockStartUs); proc.at.fCpuAvg = (double)(proc.at.nCpuUsrTimeUs + proc.at.nCpuKerTimeUs) / fUpClockUs * 100.0; tmsLast = tms; if(m_nLastTimesCallUs) { double fIntvClockUs = llabs(proc.nHeartbeatCurUs - m_nLastTimesCallUs); proc.at.fCpuCur = (double)(proc.at.nCpuUsrTimeUs - nCpuUsrTimeOldUs + proc.at.nCpuKerTimeUs - nCpuKerTimeOldUs) / fIntvClockUs * 100.0; } m_nLastTimesCallUs = proc.nHeartbeatCurUs; m_procMem.Update(); const VM_VALUE &rVmPeak = m_procMem.VmPeak(); proc.am.vmPeak = rVmPeak.valid ? rVmPeak.cb : 0; const VM_VALUE &rVmSize = m_procMem.VmSize(); proc.am.vmSize = rVmSize.valid ? rVmSize.cb : 0; const VM_VALUE &rVmHWM = m_procMem.VmHWM(); proc.am.vmHWM = rVmHWM.valid ? rVmHWM.cb : 0; const VM_VALUE &rVmRSS = m_procMem.VmRSS(); proc.am.vmRSS = rVmRSS.valid ? rVmRSS.cb : 0; } if((proc.state == GIAS_Running)) { if(proc.nHeartbeatLastUs) { proc.at.nCycleLastUs = proc.nHeartbeatCurUs - proc.nHeartbeatLastUs; if((proc.at.nCycleMinUs > proc.at.nCycleLastUs) || !proc.at.nCycleMinUs) proc.at.nCycleMinUs = proc.at.nCycleLastUs; if(proc.at.nCycleMaxUs < proc.at.nCycleLastUs) proc.at.nCycleMaxUs = proc.at.nCycleLastUs; } if(nCurWorkingTime) { proc.at.nWorkLastUs = nCurWorkingTime; if((proc.at.nWorkMinUs > nCurWorkingTime) || !proc.at.nWorkMinUs) proc.at.nWorkMinUs = nCurWorkingTime; if(proc.at.nWorkMaxUs < nCurWorkingTime) proc.at.nWorkMaxUs = nCurWorkingTime; } } if(proc.nStateEvtSources) { clock64_t clk; GFA_APPCTRL_APPTIMES at; appid_t app, src = proc.nStateEvtSources; while(src) { int b = ffsll(src) - 1; app = ((appid_t)0x1 << b); src &= ~app; GfaIpcAppStates state = GetAppState(app); APP_CTRL_PROCESS &rhp = m_pAppCtrl->proc[b]; if((rhp.nAppID == app) && rhp.pid) { pid_t pid = getpgid(rhp.pid); if((pid < 0) && (errno == ESRCH) && (rhp.state != GIAS_StateNotRunning)) { proc.nHangingApps &= ~app; AppStateChanged(app, rhp.state, GIAS_StateNotRunning); memset(&rhp, 0, sizeof(rhp)); continue; } } if((state == GIAS_Running) || (state == GIAS_Paused) || (proc.nHangingApps & app)) { if((clk = GetAppTimes(app, &at)) >= 0) { if(at.nMaxHeartbeatDelay > 0) { if(clk > at.nMaxHeartbeatDelay) { if(!(proc.nHangingApps & app)) { proc.nHangingApps |= app; m_ai.nStateEvtPending |= app; } } else { if(proc.nHangingApps & app) { proc.nHangingApps &= ~app; m_ai.nStateEvtPending |= app; } } } } } } } return &m_ai; } return NULL; } ///////////////////////////////////////////////////////////////////////////// GfaIpcAppStates CAppCtrl::GetAppState(appid_t nAppID) { GfaIpcAppStates ret = GIAS_Invalid; if(m_hShm) { CAppCtrlShmLocker locker(*this); int nIndex = SlotIndexFromAppID(nAppID); if(_IS_VALID_SLOT_INDEX(nIndex)) { const APP_CTRL_PROCESS &proc1 = m_pAppCtrl->proc[m_nSlotIdx]; const APP_CTRL_PROCESS &proc2 = m_pAppCtrl->proc[nIndex]; if(proc1.nHangingApps & nAppID) ret = GIAS_Hanging; else ret = proc2.state; } else ret = GIAS_StateNotRunning; } return ret; } ///////////////////////////////////////////////////////////////////////////// const char* CAppCtrl::GetStateText(GfaIpcAppStates state) { static const char *pszStateNames[] = { "Not running", "Initializing", "Running", "Paused", "Hanging", "Terminating", "Zombie", "Invalid" }; static_assert(_countof(pszStateNames) == (GIAS_Invalid - GIAS_StateNotRunning + 1), "enum GfaIpcAppStates does not meet string representation!"); if(state >= GIAS_StateNotRunning && state <= GIAS_Invalid) return pszStateNames[state]; return "n/a"; } ///////////////////////////////////////////////////////////////////////////// GfaIpcAppStates CAppCtrl::SetAppState(GfaIpcAppStates state) { GfaIpcAppStates ret = GIAS_Invalid; if(m_hShm && _IS_VALID_APP_STATE(state)) { CAppCtrlShmLocker locker(*this); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; ret = proc.state; if(ret != state) { proc.state = state; AppStateChanged(m_nAppID, ret, state); } } return ret; } ///////////////////////////////////////////////////////////////////////////// const char* CAppCtrl::GetDisplayName(appid_t nAppID, char *pszName, size_t nCChName) { if(m_hShm && pszName && nCChName) { int nIndex = SlotIndexFromAppID(nAppID); if(_IS_VALID_SLOT_INDEX(nIndex)) { char szUnknown[16]; CAppCtrlShmLocker locker(*this); const APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[nIndex]; const char *pszTmp = proc.szDisplayName; size_t nLen = strlen(pszTmp); if(!nLen) { if(GetKnownAppDisplayName(nAppID, pszName, nCChName)) return pszName; nLen = sprintf(szUnknown, "APP %02d", nIndex + 1); pszTmp = szUnknown; } if(nLen < nCChName) { strcpy(pszName, pszTmp); return pszName; } } } return NULL; } bool CAppCtrl::PresetDisplayName(appid_t nAppID, const char *pszName) { if(m_hShm && pszName) { CAppCtrlShmLocker locker(*this); int nIndex = SlotIndexFromAppID(nAppID); if(_IS_VALID_SLOT_INDEX(nIndex)) { APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[nIndex]; size_t nLen = strlen(pszName); if(nLen < _APP_CTRL_MAX_DISPLAY_NAME_LENGTH) { if(!proc.szDisplayName[0]) strcpy(proc.szDisplayName, pszName); return true; } } } return false; } ///////////////////////////////////////////////////////////////////////////// size_t CAppCtrl::GetAppSize(appid_t nAppID) { if(m_hShm) { CAppCtrlShmLocker locker(*this); int nIndex = SlotIndexFromAppID(nAppID); if(_IS_VALID_SLOT_INDEX(nIndex)) { APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[nIndex]; return proc.nAppFileSize; } } return 0; } ///////////////////////////////////////////////////////////////////////////// const char* CAppCtrl::GetKnownAppDisplayName(appid_t nAppID, char *pszName, size_t nCChName) { if(pszName && nCChName) { int nIndex = SlotIndexFromAppID(nAppID); if(_IS_KNOWN_APP_INDEX(nIndex)) { const char *pszTmp = g_pszKnownAppNames[nIndex]; size_t nLen = strlen(pszTmp); if(nLen < nCChName) { strcpy(pszName, pszTmp); return pszName; } } } return NULL; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::SubscribeStateEvents(appid_t nAppMask) { if(m_hShm) { CAppCtrlShmLocker locker(*this); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; nAppMask &= ~m_nAppID; proc.nStateEvtSources |= nAppMask; proc.nStateEvtPending |= nAppMask; return true; } return false; } bool CAppCtrl::UnsubscribeStateEvents(appid_t nAppMask) { if(m_hShm) { CAppCtrlShmLocker locker(*this); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; proc.nStateEvtSources &= ~nAppMask; proc.nStateEvtPending &= ~nAppMask; return true; } return false; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::SubscribeSysEvents(sysevt_t nEvtMask) { if(m_hShm) { CAppCtrlShmLocker locker(*this); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; proc.nSysEvtRegistered |= nEvtMask; proc.nSysEvtPending |= (nEvtMask & GFA_APPCTRL_SYSEVENT_ALL_MYSQL); return true; } return false; } bool CAppCtrl::UnsubscribeSysEvents(sysevt_t nEvtMask) { if(m_hShm) { CAppCtrlShmLocker locker(*this); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; proc.nSysEvtRegistered &= ~nEvtMask; proc.nSysEvtPending &= ~nEvtMask; return true; } return false; } ///////////////////////////////////////////////////////////////////////////// appid_t CAppCtrl::GetPendingStateEvents(void) { appid_t nRet = 0; if(m_hShm) { CAppCtrlShmLocker locker(*this); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; nRet = proc.nStateEvtPending; if(nRet) proc.nStateEvtPending = 0; } return nRet; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::SendCtrlMsg(appid_t nAppID, ctrlmsg_t msg) { if(m_hShm && _IS_VALID_CTRL_MSG(msg)) { int nIndex = SlotIndexFromAppID(nAppID); if(_IS_VALID_SLOT_INDEX(nIndex)) { CAppCtrlShmLocker locker(*this); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[nIndex]; proc.nCtrlMsgPending |= msg; return true; } } return false; } ctrlmsg_t CAppCtrl::GetPendingCtrlMsg(void) { ctrlmsg_t nRet = 0; if(m_hShm) { CAppCtrlShmLocker locker(*this); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; nRet = proc.nCtrlMsgPending; if(nRet) proc.nCtrlMsgPending = 0; } return nRet; } ///////////////////////////////////////////////////////////////////////////// sysevt_t CAppCtrl::GetPendingSysEvents(void) { sysevt_t nRet = 0; if(m_hShm) { CAppCtrlShmLocker locker(*this); APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; nRet = proc.nSysEvtPending; if(nRet) proc.nSysEvtPending = 0; } return nRet; } ///////////////////////////////////////////////////////////////////////////// clock64_t CAppCtrl::GetAppTimes(appid_t nAppID, LPGFA_APPCTRL_APPTIMES pat) { clock64_t ret = -1; if(m_hShm && _IS_VALID_APP_ID(nAppID)) { int nIndex = SlotIndexFromAppID(nAppID); const APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[nIndex]; CAppCtrlShmLocker locker(*this); if(proc.nAppID == nAppID) { struct timespec tsHeartBeat; if(pat) memcpy(pat, &proc.at, sizeof(GFA_APPCTRL_APPTIMES)); ::clock_gettime(CLOCK_MONOTONIC, &tsHeartBeat); ret = proc.nHeartbeatCurUs ? (_TIMESPEC_2_US(tsHeartBeat) - proc.nHeartbeatCurUs) : 0; } } return ret; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::GetAppMem(appid_t nAppID, LPGFA_APPCTRL_APPMEM pam) { if(m_hShm && _IS_VALID_APP_ID(nAppID)) { int nIndex = SlotIndexFromAppID(nAppID); const APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[nIndex]; CAppCtrlShmLocker locker(*this); if(proc.nAppID == nAppID) { if(pam) { memcpy(pam, &proc.am, sizeof(GFA_APPCTRL_APPMEM)); return true; } } } return false; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::GetSysMem(LPGFA_APPCTRL_SYSMEM psm) { if(m_hShm) { const APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; if(psm) { CAppCtrlShmLocker locker(*this); memcpy(psm, &sys.mem, sizeof(GFA_APPCTRL_SYSMEM)); return true; } } return false; } bool CAppCtrl::GetSysSPI(LPGFA_SYSINFO_SPI pspi) { if(m_hShm) { const APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; if(pspi) { CAppCtrlShmLocker locker(*this); memcpy(pspi, &sys.spi, sizeof(GFA_SYSINFO_SPI)); return true; } } return false; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::GetBootFromEmmc(bool *pbBootFromEmmc) { if(m_hShm && pbBootFromEmmc) { APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; CAppCtrlShmLocker locker(*this); *pbBootFromEmmc = sys.bBootFromEmmc; return true; } return false; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::GetDbInfo(LPGFA_SYSINFO_DATABASE psdb) { if(m_hShm && psdb) { GFA_SYSINFO_DATABASE &sdb = m_pAppCtrl->sdb; CAppCtrlShmLocker locker(*this); memcpy(psdb, &sdb, sizeof(GFA_SYSINFO_DATABASE)); return true; } return false; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::KillApp(appid_t nAppID) { if(m_hShm && _IS_VALID_APP_ID(nAppID)) { int nIndex = SlotIndexFromAppID(nAppID); const APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[nIndex]; if((proc.nAppID == nAppID) && (proc.pid > 0)) { return !kill(proc.pid, SIGTERM); } } return false; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::CreateSysInfo(void) { APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; CAppCtrlShmLocker locker(*this); bool bBootFromEmmc = false; if(!sys.nPidInCharge) { memset(&sys, 0, sizeof(APP_CTRL_SYSTEM)); sys.nPidInCharge = m_pid; #if _TARGET_BUILD if(m_sysInfo.GetBootInfo(bBootFromEmmc)) { sys.bBootFromEmmc = bBootFromEmmc; return true; } #else // _TARGET_BUILD UNUSED(bBootFromEmmc); return true; #endif // _TARGET_BUILD } else { pid_t pid = getpgid(sys.nPidInCharge); if((pid < 0) && (errno == ESRCH)) { memset(&sys, 0, sizeof(APP_CTRL_SYSTEM)); sys.nPidInCharge = m_pid; #if _TARGET_BUILD if(m_sysInfo.GetBootInfo(bBootFromEmmc)) { sys.bBootFromEmmc = bBootFromEmmc; return true; } #else // _TARGET_BUILD return true; #endif // _TARGET_BUILD } } return false; } bool CAppCtrl::ReleaseSysInfo(void) { APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; CAppCtrlShmLocker locker(*this); if(sys.nPidInCharge == m_pid) { memset(&sys, 0, sizeof(APP_CTRL_SYSTEM)); return true; } return false; } bool CAppCtrl::UpdateSysInfo(void) { if(m_hShm) { struct timespec tsCur; ::clock_gettime(CLOCK_MONOTONIC, &tsCur); clock64_t t = _TIMESPEC_2_US(tsCur); APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; CAppCtrlShmLocker locker(*this); if(t < (sys.nClkLastUpdate + 1000000)) return true; if(m_sysInfo.Update()) { const SI_VAL &rMemTotal = m_sysInfo.MemTotal(); sys.mem.nMemTotal = rMemTotal.valid ? (uint32_t)rMemTotal.cb : 0; const SI_VAL &rMemUsed = m_sysInfo.MemUsed(); sys.mem.nMemUsed = rMemUsed.valid ? (uint32_t)rMemUsed.cb : 0; const SI_VAL &rMemFree = m_sysInfo.MemFree(); sys.mem.nMemFree = rMemFree.valid ? (uint32_t)rMemFree.cb : 0; const SI_VAL &rMemAvailable = m_sysInfo.MemAvailable(); sys.mem.nMemAvailable = rMemAvailable.valid ? (uint32_t)rMemAvailable.cb : 0; const SI_VAL &rMemBuffers = m_sysInfo.MemBuffers(); sys.mem.nMemBuffers = rMemBuffers.valid ? (uint32_t)rMemBuffers.cb : 0; const SI_VAL &rMemCached = m_sysInfo.MemCached(); sys.mem.nMemCached = rMemCached.valid ? (uint32_t)rMemCached.cb : 0; sys.nUpdateError = 0; sys.nClkLastUpdate = t; } else { sys.nUpdateError = errno; return false; } } return false; } bool CAppCtrl::UpdateStorageDeviceMap(const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, bool bReset, bool bUpdateOnly) { APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; unsigned int nPartChangeMask = sdm.nPartChangeMask; CAppCtrlShmLocker locker(*this); if(bReset) { for(int i = 0; i < (int)_countof(sys.sdm.disks); ++i) { GFA_SYSINFO_DISK &diskShm = sys.sdm.disks[i]; _DELETE_DISK(diskShm); } for(int i = 0; i < (int)_countof(sys.sdm.parts); ++i) { GFA_SYSINFO_PARTITION &partShm = sys.sdm.parts[i]; _DELETE_PARTITION(partShm); _DELETE_MOUNTPOINT(partShm); } sys.nDiskMask = 0; sys.nPartMask = 0; sys.nMountMask = 0; } else if(bUpdateOnly) { memcpy(&sys.sdm, &sdm, sizeof(sdm)); for(int i = 0; i < (int)_countof(m_pAppCtrl->proc); ++i) { APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[i]; if((proc.pid > 0) && getpgid(proc.pid) > 0) { if(proc.nSysEvtRegistered & GFA_APPCTRL_SYSEVENT_STG_DEV_UPDT_EVT) { proc.nSysEvtPending |= GFA_APPCTRL_SYSEVENT_STG_DEV_UPDT_EVT; } } } } else { while(nPartChangeMask) { int nPartIdx = ffsll(nPartChangeMask) - 1; uint32_t nPartBit = (0x01 << nPartIdx); nPartChangeMask &= ~nPartBit; if((nPartIdx >= 0) && (nPartIdx < (int)_countof(sdm.parts))) { const GFA_SYSINFO_PARTITION &partNew = sdm.parts[nPartIdx]; GFA_SYSINFO_PARTITION &partShm = sys.sdm.parts[nPartIdx]; int nDiskIdx = partNew.nDiskIdx; if((nDiskIdx >= 0) && (nDiskIdx < (ssize_t)_countof(sdm.disks))) { const GFA_SYSINFO_DISK &diskNew = sdm.disks[nDiskIdx]; GFA_SYSINFO_DISK &diskShm = sys.sdm.disks[nDiskIdx]; uint32_t nDiskBit = (0x01 << nDiskIdx); if(diskNew.valid && !diskShm.valid) { // disk add _COPY_DISK(diskShm, diskNew); sys.nDiskMask |= nDiskBit; } else if(!diskNew.valid && diskShm.valid) { // disk remove _DELETE_DISK(diskShm); sys.nDiskMask &= ~nDiskBit; } else if(diskNew.valid && diskShm.valid) { // disk change _COPY_DISK(diskShm, diskNew); sys.nDiskMask |= nDiskBit; } if(partNew.valid && !partShm.valid) { // partition add _COPY_PARTITION(partShm, partNew); sys.nPartMask |= nPartBit; } else if(!partNew.valid && partShm.valid) { // partition remove _DELETE_PARTITION(partShm); sys.nPartMask &= ~nPartBit; } if(partNew.valid && partShm.valid) { // partition change if(*partNew.szMntPoint && !*partShm.szMntPoint) { // mountpoint add _COPY_MOUNTPOINT(partShm, partNew); sys.nMountMask |= nPartBit; } else if(!*partNew.szMntPoint && *partShm.szMntPoint) { // mountpoint remove _DELETE_MOUNTPOINT(partShm); sys.nMountMask &= ~nPartBit; } else if(*partNew.szMntPoint && *partShm.szMntPoint) { // mountpoint change if(strcmp(partNew.szMntPoint, partShm.szMntPoint)) _COPY_MOUNTPOINT(partShm, partNew); sys.nMountMask |= nPartBit; } } } } } } return true; } int CAppCtrl::GetNextDiskAdded(LPGFA_SYSINFO_DISK pDisk) { if(pDisk) { APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; CAppCtrlShmLocker locker(*this); if(proc.nDiskAdded) { int nDiskIdx = ffsll(proc.nDiskAdded) - 1; uint32_t m = 0x1ULL << nDiskIdx; proc.nDiskAdded &= ~m; if((nDiskIdx >= 0) && (nDiskIdx < (int)_countof(sys.sdm.disks))) { memcpy(pDisk, &sys.sdm.disks[nDiskIdx], sizeof(GFA_SYSINFO_DISK)); return nDiskIdx; } } } return -1; } int CAppCtrl::GetNextDiskRemoved(LPGFA_SYSINFO_DISK pDisk) { if(pDisk) { APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; CAppCtrlShmLocker locker(*this); if(proc.nDiskRemoved) { int nDiskIdx = ffsll(proc.nDiskRemoved) - 1; uint32_t m = 0x1ULL << nDiskIdx; proc.nDiskRemoved &= ~m; if((nDiskIdx >= 0) && (nDiskIdx < (int)_countof(sys.sdm.disks))) { memcpy(pDisk, &sys.sdm.disks[nDiskIdx], sizeof(GFA_SYSINFO_DISK)); return nDiskIdx; } } } return -1; } int CAppCtrl::GetNextPartitionAdded(LPGFA_SYSINFO_PARTITION pPart) { if(pPart) { APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; CAppCtrlShmLocker locker(*this); if(proc.nPartAdded) { int nPartIdx = ffsll(proc.nPartAdded) - 1; uint32_t m = 0x1ULL << nPartIdx; proc.nPartAdded &= ~m; if((nPartIdx >= 0) && (nPartIdx < (int)_countof(sys.sdm.parts))) { memcpy(pPart, &sys.sdm.parts[nPartIdx], sizeof(GFA_SYSINFO_PARTITION)); return nPartIdx; } } } return -1; } int CAppCtrl::GetNextPartitionRemoved(LPGFA_SYSINFO_PARTITION pPart) { if(pPart) { APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; CAppCtrlShmLocker locker(*this); if(proc.nPartRemoved) { int nPartIdx = ffsll(proc.nPartRemoved) - 1; uint32_t m = 0x1ULL << nPartIdx; proc.nPartRemoved &= ~m; if((nPartIdx >= 0) && (nPartIdx < (int)_countof(sys.sdm.parts))) { memcpy(pPart, &sys.sdm.parts[nPartIdx], sizeof(GFA_SYSINFO_PARTITION)); return nPartIdx; } } } return -1; } int CAppCtrl::GetNextMountAdded(LPGFA_SYSINFO_PARTITION pPart) { if(pPart) { APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; CAppCtrlShmLocker locker(*this); if(proc.nMountAdded) { int nPartIdx = ffsll(proc.nMountAdded) - 1; uint32_t m = 0x1ULL << nPartIdx; proc.nMountAdded &= ~m; if((nPartIdx >= 0) && (nPartIdx < (int)_countof(sys.sdm.parts))) { memcpy(pPart, &sys.sdm.parts[nPartIdx], sizeof(GFA_SYSINFO_PARTITION)); return nPartIdx; } } } return -1; } int CAppCtrl::GetNextMountRemoved(LPGFA_SYSINFO_PARTITION pPart) { if(pPart) { APP_CTRL_SYSTEM &sys = m_pAppCtrl->sys; APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[m_nSlotIdx]; CAppCtrlShmLocker locker(*this); if(proc.nMountRemoved) { int nPartIdx = ffsll(proc.nMountRemoved) - 1; uint32_t m = 0x1ULL << nPartIdx; proc.nMountRemoved &= ~m; if((nPartIdx >= 0) && (nPartIdx < (int)_countof(sys.sdm.parts))) { memcpy(pPart, &sys.sdm.parts[nPartIdx], sizeof(GFA_SYSINFO_PARTITION)); return nPartIdx; } } } return -1; } bool CAppCtrl::GetStgDevMap(LPGFA_SYSINFO_STORAGE_DEVICE_MAP pStgDevMap) { if(pStgDevMap) { const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm = m_pAppCtrl->sys.sdm; CAppCtrlShmLocker locker(*this); memcpy(pStgDevMap, &sdm, sizeof(sdm)); return true; } return false; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::UpdateDbInfo(const GFA_SYSINFO_DATABASE &sdb) { if(m_hShm) { sysevt_t evt = 0; GFA_SYSINFO_DATABASE &rsdb = m_pAppCtrl->sdb; CAppCtrlShmLocker locker(*this); if(rsdb.bIsInit != sdb.bIsInit) { evt |= GFA_APPCTRL_SYSEVENT_MYSQL_INIT_EVT; rsdb.bIsInit = sdb.bIsInit; } if(sdb.bIsInit) { if(memcmp(&rsdb.svr, &sdb.svr, sizeof(GFA_MYSQL_SERVER))) { evt |= GFA_APPCTRL_SYSEVENT_MYSQL_SERVER_EVT; memcpy(&rsdb.svr, &sdb.svr, sizeof(GFA_MYSQL_SERVER)); } if(memcmp(&rsdb.res, &sdb.res, sizeof(GFA_MYSQL_RESOURCE))) { evt |= GFA_APPCTRL_SYSEVENT_MYSQL_RESOURCE_EVT; memcpy(&rsdb.res, &sdb.res, sizeof(GFA_MYSQL_RESOURCE)); } if(rsdb.nNumDatabases != sdb.nNumDatabases) { rsdb.nNumDatabases = sdb.nNumDatabases; evt |= GFA_APPCTRL_SYSEVENT_MYSQL_DATABASE_EVT; memcpy(&rsdb.dbs, &sdb.dbs, sizeof(GFA_MYSQL_SCHEMA) * GFA_MYSQL_MAX_DATABASES); } else if(memcmp(&rsdb.dbs, &sdb.dbs, sizeof(GFA_MYSQL_SCHEMA) * GFA_MYSQL_MAX_DATABASES)) { evt |= GFA_APPCTRL_SYSEVENT_MYSQL_DATABASE_EVT; memcpy(&rsdb.dbs, &sdb.dbs, sizeof(GFA_MYSQL_SCHEMA) * GFA_MYSQL_MAX_DATABASES); } } else { memset(&rsdb, 0, sizeof(GFA_SYSINFO_DATABASE)); } if(evt) { for(int i = 0; i < _APP_CTRL_MAX_SLOTS; ++i) { APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[i]; if(_IS_VALID_APP_ID(proc.nAppID) && (proc.nSysEvtRegistered & GFA_APPCTRL_SYSEVENT_ALL_MYSQL)) { evt &= proc.nSysEvtRegistered; proc.nSysEvtPending |= evt; } } } return true; } return false; } ///////////////////////////////////////////////////////////////////////////// bool CAppCtrl::UpdateSpiInfo(const GFA_SYSINFO_SPI &spi, bool bReset) { if(m_hShm) { sysevt_t evt = 0; GFA_SYSINFO_SPI &spiShm = m_pAppCtrl->sys.spi; CAppCtrlShmLocker locker(*this); if(bReset) { memset(&spiShm, 0, sizeof(spiShm)); evt |= GFA_APPCTRL_SYSEVENT_TIVA_RST; } else { if(memcmp(&spiShm, &spi, sizeof(spiShm))) { memcpy(&spiShm, &spi, sizeof(spiShm)); evt |= GFA_APPCTRL_SYSEVENT_TIVA_EVT; } } if(evt) { for(int i = 0; i < _APP_CTRL_MAX_SLOTS; ++i) { APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[i]; if(_IS_VALID_APP_ID(proc.nAppID) && (evt & proc.nSysEvtRegistered)) { proc.nSysEvtPending |= evt; } } } return true; } return false; } ///////////////////////////////////////////////////////////////////////////// int CAppCtrl::SlotIndexFromAppID(appid_t nAppID) { if(nAppID == 0) return m_nSlotIdx; else if(_IS_VALID_APP_ID(nAppID)) return _APP_INDEX_FROM_APP_ID(nAppID); return _INVALID_SLOT_INDEX; } ///////////////////////////////////////////////////////////////////////////// void CAppCtrl::AppStateChanged(appid_t nAppID, GfaIpcAppStates oldState, GfaIpcAppStates newState) { if(oldState != newState) { for(int i = 0; i < _APP_CTRL_MAX_SLOTS; ++i) { APP_CTRL_PROCESS &proc = m_pAppCtrl->proc[i]; if(_IS_VALID_APP_ID(proc.nAppID) && (proc.nStateEvtSources & nAppID)) { proc.nStateEvtPending |= nAppID; } } } } ///////////////////////////////////////////////////////////////////////////// void CAppCtrl::Lock(void) { if(m_hShm) { // if(::GfaIpcInterlockedIncrement(m_hShm, &m_nLockCount) == 1) (*m_pfnLockSHM)(m_hShm); } } void CAppCtrl::Unlock(void) { if(m_hShm) { // if(::GfaIpcInterlockedDecrement(m_hShm, &m_nLockCount) == 0) (*m_pfnUnlockSHM)(m_hShm); } } void CAppCtrl::SetLockUnlockFunctions(PFN_GFA_IPC_LOCK_SHM pfnLockSHM, PFN_GFA_IPC_UNLOCK_SHM pfnUnlockSHM) { if(pfnLockSHM && pfnUnlockSHM) { m_pfnLockSHM = pfnLockSHM; m_pfnUnlockSHM = pfnUnlockSHM; } else { m_pfnLockSHM = ::GfaIpcLockSHM; m_pfnUnlockSHM = ::GfaIpcUnlockSHM; } } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// HAPPCTRL GfaIpcAppCtrlAcquire(appid_t nAppID, const char *pszDisplayName, clock64_t nCycleIntvUs, clock64_t nMaxHeartbeatDelayUs) { if(!_IS_VALID_APP_ID(nAppID)) return NULL; CAppCtrl *p = new CAppCtrl; if(p) { if(!p->Create(nAppID, pszDisplayName, nCycleIntvUs, nMaxHeartbeatDelayUs)) delete p; else return reinterpret_cast(p); } return NULL; } ///////////////////////////////////////////////////////////////////////////// void GfaIpcAppCtrlRelease(HAPPCTRL hAC) { CAppCtrl *p = reinterpret_cast(hAC); if(p) { p->Release(); delete p; } } ///////////////////////////////////////////////////////////////////////////// HAPPINFO GfaIpcAppCtrlInfoUpdate(HAPPCTRL hAC, clock64_t nCurWorkingTime) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return reinterpret_cast(p->AppInfoUpdate(nCurWorkingTime)); return NULL; } ///////////////////////////////////////////////////////////////////////////// GfaIpcAppStates GfaIpcAppCtrlGetState(HAPPCTRL hAC, appid_t nAppID) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetAppState(nAppID); return GIAS_Invalid; } GfaIpcAppStates GfaIpcAppCtrlSetState(HAPPCTRL hAC, GfaIpcAppStates state) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->SetAppState(state); return GIAS_Invalid; } const char* GfaIpcAppCtrlGetStateText(GfaIpcAppStates state) { return CAppCtrl::GetStateText(state); } ///////////////////////////////////////////////////////////////////////////// const char* GfaIpcAppCtrlGetDisplayName(HAPPCTRL hAC, appid_t nAppID, char *pszName, size_t nCChName) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetDisplayName(nAppID, pszName, nCChName); return NULL; } ///////////////////////////////////////////////////////////////////////////// bool GfaIpcAppCtrlPresetDisplayName(HAPPCTRL hAC, appid_t nAppID, const char *pszName) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->PresetDisplayName(nAppID, pszName); return false; } ///////////////////////////////////////////////////////////////////////////// appid_t GfaIpcAppCtrlGetRunningMask(HAPPCTRL hAC) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetRunningAppsMask(); return 0; } ///////////////////////////////////////////////////////////////////////////// bool GfaIpcAppCtrlSubscribeStateEvents(HAPPCTRL hAC, appid_t nAppMask) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->SubscribeStateEvents(nAppMask); return false; } ///////////////////////////////////////////////////////////////////////////// bool GfaIpcAppCtrlUnsubscribeStateEvents(HAPPCTRL hAC, appid_t nAppMask) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->UnsubscribeStateEvents(nAppMask); return false; } ///////////////////////////////////////////////////////////////////////////// bool GfaIpcAppCtrlSubscribeSysEvents(HAPPCTRL hAC, sysevt_t nEvtMask) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->SubscribeSysEvents(nEvtMask); return false; } ///////////////////////////////////////////////////////////////////////////// bool GfaIpcAppCtrlUnsubscribeSysEvents(HAPPCTRL hAC, sysevt_t nEvtMask) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->UnsubscribeSysEvents(nEvtMask); return false; } ///////////////////////////////////////////////////////////////////////////// appid_t GfaIpcAppCtrlGetPendingStateEvents(HAPPCTRL hAC) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetPendingStateEvents(); return 0; } ///////////////////////////////////////////////////////////////////////////// bool GfaIpcAppCtrlSendCtrlMsg(HAPPCTRL hAC, appid_t nAppID, ctrlmsg_t msg) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->SendCtrlMsg(nAppID, msg); return false; } ///////////////////////////////////////////////////////////////////////////// ctrlmsg_t GfaIpcAppCtrlGetPendingCtrlMsg(HAPPCTRL hAC) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetPendingCtrlMsg(); return 0; } ///////////////////////////////////////////////////////////////////////////// clock64_t GfaIpcAppCtrlGetAppTimes(HAPPCTRL hAC, appid_t nAppID, LPGFA_APPCTRL_APPTIMES pat) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetAppTimes(nAppID, pat); return -1; } ///////////////////////////////////////////////////////////////////////////// bool GfaIpcAppCtrlGetAppMem(HAPPCTRL hAC, appid_t nAppID, LPGFA_APPCTRL_APPMEM pam) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetAppMem(nAppID, pam); return false; } ///////////////////////////////////////////////////////////////////////////// size_t GfaIpcAppCtrlGetAppSize(HAPPCTRL hAC, appid_t nAppID) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetAppSize(nAppID); return 0; } ///////////////////////////////////////////////////////////////////////////// sysevt_t GfaIpcAppCtrlGetPendingSysEvents(HAPPCTRL hAC) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetPendingSysEvents(); return 0; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // for the GfaSysInfo process only, will not be documented! extern "C" bool GfaIpcAppCtrlCreateSysInfo(HAPPCTRL hAC) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->CreateSysInfo(); return false; } extern "C" bool GfaIpcAppCtrlReleaseSysInfo(HAPPCTRL hAC) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->ReleaseSysInfo(); return false; } extern "C" bool GfaIpcAppCtrlUpdateSysInfo(HAPPCTRL hAC) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->UpdateSysInfo(); return false; } extern "C" bool GfaIpcAppCtrlUpdateStorageDeviceMap(HAPPCTRL hAC, const GFA_SYSINFO_STORAGE_DEVICE_MAP &sdm, bool bReset, bool bUpdateOnly) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->UpdateStorageDeviceMap(sdm, bReset, bUpdateOnly); return false; } extern "C" bool GfaIpcAppCtrlUpdateDbInfo(HAPPCTRL hAC, const GFA_SYSINFO_DATABASE &sdb) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->UpdateDbInfo(sdb); return false; } extern "C" bool GfaIpcAppCtrlUpdateSpiInfo(HAPPCTRL hAC, const GFA_SYSINFO_SPI &spi, bool bReset) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->UpdateSpiInfo(spi, bReset); return false; } extern "C" bool GfaIpcAppCtrlTriggertHeartBeat(HAPPCTRL hAC) { CAppCtrl *p = reinterpret_cast(hAC); if(p) { p->TriggertHeartBeat(); return true; } return false; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// int GfaIpcAppCtrlGetNextDiskAdded(HAPPCTRL hAC, LPGFA_SYSINFO_DISK pDisk) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetNextDiskAdded(pDisk); return -1; } int GfaIpcAppCtrlGetNextDiskRemoved(HAPPCTRL hAC, LPGFA_SYSINFO_DISK pDisk) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetNextDiskRemoved(pDisk); return -1; } int GfaIpcAppCtrlGetNextPartitionAdded(HAPPCTRL hAC, LPGFA_SYSINFO_PARTITION pPart) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetNextPartitionAdded(pPart); return -1; } int GfaIpcAppCtrlGetNextPartitionRemoved(HAPPCTRL hAC, LPGFA_SYSINFO_PARTITION pPart) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetNextPartitionRemoved(pPart); return -1; } int GfaIpcAppCtrlGetNextMountAdded(HAPPCTRL hAC, LPGFA_SYSINFO_PARTITION pPart) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetNextMountAdded(pPart); return -1; } int GfaIpcAppCtrlGetNextMountRemoved(HAPPCTRL hAC, LPGFA_SYSINFO_PARTITION pPart) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetNextMountRemoved(pPart); return -1; } bool GfaIpcAppCtrlGetStgDevMap(HAPPCTRL hAC, LPGFA_SYSINFO_STORAGE_DEVICE_MAP pStgDevMap) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetStgDevMap(pStgDevMap); return false; } bool GfaIpcAppCtrlGetSysMem(HAPPCTRL hAC, LPGFA_APPCTRL_SYSMEM psm) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetSysMem(psm); return false; } bool GfaIpcAppCtrlGetSysSPI(HAPPCTRL hAC, LPGFA_SYSINFO_SPI pspi) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetSysSPI(pspi); return false; } bool GfaIpcAppCtrlGetBootFromEmmc(HAPPCTRL hAC, bool *pbBootFromEmmc) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetBootFromEmmc(pbBootFromEmmc); return false; } bool GfaIpcAppCtrlGetDbInfo(HAPPCTRL hAC, LPGFA_SYSINFO_DATABASE psdb) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->GetDbInfo(psdb); return false; } bool GfaIpcAppCtrlKillApp(HAPPCTRL hAC, appid_t nAppID) { CAppCtrl *p = reinterpret_cast(hAC); if(p) return p->KillApp(nAppID); return false; } bool GfaIpcAppCtrlSetLockUnlockFunctions(HAPPCTRL hAC, PFN_GFA_IPC_LOCK_SHM pfnLockSHM, PFN_GFA_IPC_UNLOCK_SHM pfnUnlockSHM) { CAppCtrl *p = reinterpret_cast(hAC); if(p) { p->SetLockUnlockFunctions(pfnLockSHM, pfnUnlockSHM); return true; } return false; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ctrlmsg_t GfaIpcAppCtrlGetNextCtrlMsg(HAPPINFO hAI) { LPAPP_CTRL_INFO pai = reinterpret_cast(hAI); if(pai && pai->nCtrlMsgPending) { int b = ffsll(pai->nCtrlMsgPending) - 1; ctrlmsg_t ret = ((ctrlmsg_t)0x1 << b); pai->nCtrlMsgPending &= ~ret; return ret; } return 0; } ///////////////////////////////////////////////////////////////////////////// appid_t GfaIpcAppCtrlGetNextStateEvtSrc(HAPPINFO hAI) { LPAPP_CTRL_INFO pai = reinterpret_cast(hAI); if(pai && pai->nStateEvtPending) { int b = ffsll(pai->nStateEvtPending) - 1; appid_t ret = ((appid_t)0x1 << b); pai->nStateEvtPending &= ~ret; return ret; } return 0; } ///////////////////////////////////////////////////////////////////////////// sysevt_t GfaIpcAppCtrlGetNextSysEvt(HAPPINFO hAI) { LPAPP_CTRL_INFO pai = reinterpret_cast(hAI); if(pai && pai->nSysEvtPending) { int b = ffsll(pai->nSysEvtPending) - 1; sysevt_t ret = ((sysevt_t)0x1 << b); pai->nSysEvtPending &= ~ret; return ret; } return 0; } ///////////////////////////////////////////////////////////////////////////// bool GfaIpcAppCtrlSysInfoUpdateStgDevInfo(HAPPCTRL hAC) { return GfaIpcAppCtrlSendCtrlMsg(hAC, GFA_APPCTRL_APPID_SYSINFO, GFA_APPCTRL_CTRLMSG_SYSINFO_UPDATE_STGDEV); }