Init basesystem source codes.
[staging/basesystem.git] / video_in_hal / systemservice / system_manager / server / src / ss_system_memory_monitor.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 ///////////////////////////////////////////////////////////////////////////////
18 /// \ingroup  tag_SystemManager
19 /// \brief    This file provides support for System Manager System Low Memory
20 ///           detection.
21 ///
22 ///////////////////////////////////////////////////////////////////////////////
23 #include <native_service/frameworkunified_framework_if.h>
24 #include <native_service/frameworkunified_multithreading.h>
25 #include <native_service/frameworkunified_thread_priority.h>
26 #include <system_service/ss_sm_thread_names_local.h>
27 #include <system_service/ss_templates.h>
28 #include <stub/Clock_API.h>
29
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include <sys/resource.h>
33 #include <boost/bind.hpp>
34 #include <fstream>
35 #include <sstream>
36 #include <string>
37
38 #include "ss_system_memory_monitor.h"
39 #include "ss_sm_systemmanagerlog.h"
40
41 CSysMemoryMonitor::CSysMemoryMonitor() :
42         m_hThread(NULL),
43         m_hParentApp(NULL),
44         m_SLMCheckCounter(0),
45         m_siPriority(-1),
46         m_NbrSamplesBeforeSystemmanagerlog(0),
47         m_memMonitorThreadName(SS_SMLowMemMonitor),
48         m_resmSession(-1) {  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
49   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
50   m_SLMConfig.SLMTimerValue = 0;
51   m_SLMConfig.SLMMaxRetryCount = 0;
52   m_SLMConfig.SLMThresholdValue = 0;
53   m_SLMConfig.SLMSystemmanagerLogIntervalMs = 0;
54   bzero(&m_sysMemInfoLast, sizeof(m_sysMemInfoLast));
55   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
56 }
57
58 CSysMemoryMonitor::~CSysMemoryMonitor(void) {
59   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
60   StopAndFreeObjects(m_hParentApp);
61   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
62 }
63
64 EFrameworkunifiedStatus CSysMemoryMonitor::Initialize(HANDLE f_hApp) {
65   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
66   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
67
68   if (NULL == f_hApp) {  // LCOV_EXCL_BR_LINE 4:NSFW
69     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
70     l_eStatus = eFrameworkunifiedStatusNullPointer;  // LCOV_EXCL_LINE 4:NSFW
71     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " Error. Argument f_hApp passed NULL pointer.");
72   } else if (NULL == (m_hThread = FrameworkunifiedCreateChildThreadWithPriority(f_hApp, SS_SMLowMemMonitor, boost::bind(&CSysMemoryMonitor::CPUMemThreadStart, this, _1), boost::bind(&CSysMemoryMonitor::CPUMemThreadStop, this, _1), PR_SMLOWMEMMON))) {  // LCOV_EXCL_BR_LINE 4:NSFW  // NOLINT(whitespace/line_length)
73     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
74     l_eStatus = eFrameworkunifiedStatusInvldHandle;  // LCOV_EXCL_LINE 4:NSFW
75     LOG_ERROR("FrameworkunifiedCreateChildThreadWithPriority()");  // LCOV_EXCL_LINE 4:NSFW
76   } else if (eFrameworkunifiedStatusOK != (l_eStatus = FrameworkunifiedStartChildThread(f_hApp, m_hThread, 0, NULL))) {  // LCOV_EXCL_BR_LINE 4:NSFW  // NOLINT(whitespace/line_length)
77     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
78     LOG_ERROR("FrameworkunifiedStartChildThread()");  // LCOV_EXCL_LINE 4:NSFW
79   } else {
80     m_hParentApp = f_hApp;
81     m_sysMemInfoLast.TotalMemoryBytes = GetSystemRamSize();
82     FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, " Info. SLM thread successfully initialized.");
83   }
84
85   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
86   return (l_eStatus);
87 }
88
89 EFrameworkunifiedStatus CSysMemoryMonitor::StopAndFreeObjects(HANDLE f_hApp) {
90   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
91   EFrameworkunifiedStatus l_eStatus;
92
93   CALL_AND_LOG_STATUS(FrameworkunifiedStopChildThread(f_hApp, m_hThread, 0, NULL));  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
94   CALL_AND_LOG_STATUS(FrameworkunifiedDestroyChildThread(f_hApp, m_hThread));  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
95
96   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
97   return (l_eStatus);
98 }
99
100 const std::string CSysMemoryMonitor::GetThreadName(void) {
101   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
102   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
103   return (m_memMonitorThreadName);
104 }
105
106 void CSysMemoryMonitor::SetSLMConfigData(SLMConfigParameters & f_ConfigData) {
107   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
108
109   m_SLMConfig.SLMTimerValue = f_ConfigData.SLMTimerValue;
110   m_SLMConfig.SLMMaxRetryCount = f_ConfigData.SLMMaxRetryCount;
111   m_SLMConfig.SLMThresholdValue = f_ConfigData.SLMThresholdValue;
112   m_SLMConfig.SLMSystemmanagerLogIntervalMs = f_ConfigData.SLMSystemmanagerLogIntervalMs;
113
114   FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__,
115           "Timer value '%d', Retry Count '%d', threshold '%d', log interval '%dms'",
116           m_SLMConfig.SLMTimerValue, m_SLMConfig.SLMMaxRetryCount,
117           m_SLMConfig.SLMThresholdValue, m_SLMConfig.SLMSystemmanagerLogIntervalMs);
118
119   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
120 }
121
122 EFrameworkunifiedStatus CSysMemoryMonitor::CPUMemThreadStart(HANDLE f_hThread) {
123   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
124   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
125
126   l_eStatus = FrameworkunifiedSubscribeNotificationWithCallback(f_hThread,
127           NTFY_ResourceMgr_Availability,
128           boost::bind(&CSysMemoryMonitor::OnAvailability, this, _1));
129   if (l_eStatus != eFrameworkunifiedStatusOK) {  // LCOV_EXCL_BR_LINE 4:NSFW
130     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
131     SS_ASERT(0);  // LCOV_EXCL_LINE 4:NSFW
132   }
133
134   if (FALSE == (m_memMonitorTimer.Initialize(f_hThread, SS_SLM_MEM_MONITOR_TIMER_ID, boost::bind(&CSysMemoryMonitor::OnMemoryTimerExpiry, this, _1)))) {  // LCOV_EXCL_BR_LINE 4:NSFW  // NOLINT(whitespace/line_length)
135     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
136     l_eStatus = eFrameworkunifiedStatusBadConnection;  // LCOV_EXCL_LINE 4:NSFW
137     LOG_ERROR("m_memMonitorTimer.Initialize() returned 'FALSE'");  // LCOV_EXCL_LINE 4:NSFW
138   } else if (FALSE == (m_systemmanagerlogTimer.Initialize(f_hThread, SS_SLM_SYSTEMMANAGERLOG_TIMER_ID, boost::bind(&CSysMemoryMonitor::OnSystemmanagerlogTimerExpiry, this, _1)))) {  // LCOV_EXCL_BR_LINE 4:NSFW  // NOLINT(whitespace/line_length)
139     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
140     l_eStatus = eFrameworkunifiedStatusBadConnection;  // LCOV_EXCL_LINE 4:NSFW
141     LOG_ERROR("m_systemmanagerlogTimer.Initialize() returned 'FALSE'");  // LCOV_EXCL_LINE 4:NSFW
142   } else {
143     if (m_SLMConfig.SLMTimerValue > 0) {
144       m_memMonitorTimer.SetTime(m_SLMConfig.SLMTimerValue / 1000,
145               m_SLMConfig.SLMTimerValue % 1000,
146               m_SLMConfig.SLMTimerValue / 1000,
147               m_SLMConfig.SLMTimerValue % 1000);
148     } else {
149       // default timer settings
150       m_memMonitorTimer.SetTime(SS_MEMORY_TIMER_CONFIG_MS / 1000,
151               SS_MEMORY_TIMER_CONFIG_MS % 1000,
152               SS_MEMORY_TIMER_CONFIG_MS / 1000,
153               SS_MEMORY_TIMER_CONFIG_MS % 1000);
154
155       FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__,
156               " Warning. SLM monitor timer configuration invalid. Using default values.");
157     }
158
159     if (m_SLMConfig.SLMSystemmanagerLogIntervalMs > 0) {
160       m_systemmanagerlogTimer.SetTime(m_SLMConfig.SLMSystemmanagerLogIntervalMs / 1000,
161               m_SLMConfig.SLMSystemmanagerLogIntervalMs % 1000,
162               m_SLMConfig.SLMSystemmanagerLogIntervalMs / 1000,
163               m_SLMConfig.SLMSystemmanagerLogIntervalMs % 1000);
164     } else {
165       // default timer settings
166       m_systemmanagerlogTimer.SetTime(SS_SYSTEMMANAGERLOG_TIMER_CONFIG_MS / 1000,
167               SS_SYSTEMMANAGERLOG_TIMER_CONFIG_MS % 1000,
168               SS_SYSTEMMANAGERLOG_TIMER_CONFIG_MS / 1000,
169               SS_SYSTEMMANAGERLOG_TIMER_CONFIG_MS % 1000);
170
171       FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__,
172               " Warning. SLM FRAMEWORKUNIFIEDLOG timer configuration invalid. Using default values.");
173     }
174
175     if (FALSE == (m_memMonitorTimer.Start())) {  // LCOV_EXCL_BR_LINE 4:NSFW
176       // LCOV_EXCL_START 4:NSFW
177       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
178       l_eStatus = eFrameworkunifiedStatusFault;
179       LOG_ERROR("m_memMonitorTimer.Start() returned 'FALSE'");
180       // LCOV_EXCL_STOP 4:NSFW
181     } else if (FALSE == (m_systemmanagerlogTimer.Start())) {  // LCOV_EXCL_BR_LINE 4:NSFW
182       // LCOV_EXCL_START 4:NSFW
183       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
184       l_eStatus = eFrameworkunifiedStatusFault;
185       LOG_ERROR("m_systemmanagerlogTimer.Start() returned 'FALSE'");
186       // LCOV_EXCL_STOP 4:NSFW
187     } else {
188       FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, " Success.");
189     }
190   }
191   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
192   return (l_eStatus);
193 }
194
195 EFrameworkunifiedStatus CSysMemoryMonitor::CPUMemThreadStop(HANDLE f_hThread) {
196   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
197   EFrameworkunifiedStatus l_eStatus;
198
199   l_eStatus = StopTimers();
200   LOG_STATUS_IF_ERRORED(l_eStatus, "StopTimers");  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
201   if ((uint32_t) -1 != m_resmSession) {
202     if (RESM_E_OK != RESM_Close(m_resmSession)) {
203       l_eStatus = eFrameworkunifiedStatusFault;
204       LOG_ERROR("RESM_Close()");  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
205     }
206   }
207
208   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
209   return (l_eStatus);
210 }
211
212 EFrameworkunifiedStatus CSysMemoryMonitor::StopTimers(void) {
213   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
214   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
215
216   if (FALSE == (m_memMonitorTimer.Stop())) {  // LCOV_EXCL_BR_LINE 4:NSFW's error
217     l_eStatus = eFrameworkunifiedStatusFault;
218     LOG_ERROR("m_memMonitorTimer.Stop() returned 'FALSE'");  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
219   }
220
221   if (FALSE == (m_systemmanagerlogTimer.Stop())) {  // LCOV_EXCL_BR_LINE 4:NSFW's error
222     l_eStatus = eFrameworkunifiedStatusFault;
223     LOG_ERROR("m_systemmanagerlogTimer.Stop() returned 'FALSE'");  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
224   }
225   FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
226   return (l_eStatus);
227 }
228
229 EFrameworkunifiedStatus CSysMemoryMonitor::OnMemoryTimerExpiry(HANDLE hThread) {
230   FRAMEWORKUNIFIEDLOG(ZONE_PERIODIC_FUNC, __FUNCTION__, "+");
231   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
232   RESM_STATUS_t l_resmStatus;
233
234   if ((uint32_t) -1 == m_resmSession) {
235     return eFrameworkunifiedStatusOK;
236   }
237
238   if (RESM_E_OK != RESM_GetStatus(m_resmSession, &l_resmStatus)) {
239     LOG_ERROR("RESM_GetStatus()");  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
240     l_eStatus = eFrameworkunifiedStatusFail;
241   } else {
242     m_sysMemInfoLast.FreeMemoryBytes = l_resmStatus.restMemSize;
243     if ((m_sysMemInfoLast.FreeMemoryBytes * 1024)
244             < (UI_32) m_SLMConfig.SLMThresholdValue) {
245       m_SLMCheckCounter++;
246
247       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, " Low Memory detected(%d/%d).",
248               m_SLMCheckCounter, m_SLMConfig.SLMMaxRetryCount);
249
250       if (m_SLMCheckCounter >= m_SLMConfig.SLMMaxRetryCount) {
251         l_eStatus = FrameworkunifiedSendParent(hThread,
252                 eSysMemThrdCmd_SYS_LOW_MEMORY, sizeof(m_sysMemInfoLast),
253                 &m_sysMemInfoLast);
254         LOG_STATUS_IF_ERRORED(l_eStatus,  // LCOV_EXCL_BR_LINE 15: marco defined in ns_logger_if.h  // NOLINT(whitespace/line_length)
255                 "FrameworkunifiedSendParent(eSysMemThrdCmd_SYS_LOW_MEMORY)");  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
256
257         l_eStatus = StopTimers();
258         LOG_STATUS_IF_ERRORED(l_eStatus, "StopTimers");  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
259       }
260     } else {
261       m_SLMCheckCounter = 0;
262     }
263   }
264
265   FRAMEWORKUNIFIEDLOG(ZONE_PERIODIC_FUNC, __FUNCTION__, "-");
266   return (l_eStatus);
267 }
268
269 EFrameworkunifiedStatus CSysMemoryMonitor::OnSystemmanagerlogTimerExpiry(HANDLE hThread) {
270   FRAMEWORKUNIFIEDLOG(ZONE_PERIODIC_FUNC, __FUNCTION__, "+");
271   EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
272   UI_32 l_freeMemoryObfuscated;
273   UI_32 l_totalMemoryObfuscated;
274
275   l_freeMemoryObfuscated = BitReverse32(m_sysMemInfoLast.FreeMemoryBytes);
276   l_totalMemoryObfuscated = BitReverse32(m_sysMemInfoLast.TotalMemoryBytes);
277
278   // Print to ZONE_WARN as per IAT requirement see WI 219056.
279   FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "FM: [%d/%d].", l_freeMemoryObfuscated,
280           l_totalMemoryObfuscated);
281
282   static int count = 0;
283
284   if (!(count %= 2)) {
285     CHAR l_format[256];
286     uint32_t timebuf;
287     uint8_t status;
288     struct tm gmt;
289     struct tm local;
290     Clock_getSystemTimeY2K38(&timebuf, &status);
291     Clock_CnvSecToDateY2K38(&timebuf, &gmt);
292     Clock_getLocalTimeY2K38(&timebuf, &local);
293
294     sprintf(l_format, " G%02d %02d%02d%02d L%02d %02d%02d%02d", gmt.tm_mday, // NOLINT
295             gmt.tm_hour, gmt.tm_min, gmt.tm_sec, local.tm_mday,
296             local.tm_hour, local.tm_min, local.tm_sec);
297
298     FRAMEWORKUNIFIEDLOG(ZONE_STATE, __FUNCTION__, "%s", l_format);
299   }
300
301   count++;
302
303   FRAMEWORKUNIFIEDLOG(ZONE_PERIODIC_FUNC, __FUNCTION__, "-");
304   return (l_eStatus);
305 }
306
307 EFrameworkunifiedStatus CSysMemoryMonitor::OnAvailability(HANDLE hThread) {
308   if (FrameworkunifiedIsServiceAvailable(hThread)) {
309     if (m_resmSession == (uint32_t) -1) {
310       if (RESM_E_OK != RESM_Open(NULL, &m_resmSession)) {
311           m_resmSession = -1;
312           SS_ASERT(0);  // LCOV_EXCL_BR_LINE 15: marco defined in ss_templates.h  // NOLINT(whitespace/line_length)
313       }
314     }
315   }
316   return eFrameworkunifiedStatusOK;
317 }
318
319 UI_32 CSysMemoryMonitor::GetSystemRamSize(void) {
320   UI_32 l_ramTotalBytes = 0;
321   std::ifstream l_sFile("/proc/meminfo");
322
323   if (l_sFile.fail()) {  // LCOV_EXCL_BR_LINE 5: Standard lib error
324     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
325     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Open /proc/meminfo");
326   } else {
327     ssize_t l_position;
328     std::string l_str;
329
330     while (getline(l_sFile, l_str)) {
331
332 //      if (std::string::npos
333 //            != (l_position = static_cast<unsigned int>(l_str.find("MemTotal:", 0)))) {
334       if (0 <= (l_position = l_str.find("MemTotal:", 0))) {  // LCOV_EXCL_BR_LINE 200:linux system information
335
336         l_str.erase(l_position, l_position + strlen("MemTotal:"));  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
337
338         if (std::string::npos != (l_position = static_cast<unsigned int>(l_str.find("kB", 0)))) {  // LCOV_EXCL_BR_LINE 200:linux system information
339           l_str.erase(l_position, l_position + strlen("kB"));  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
340         }
341
342         std::istringstream l_istr(l_str);  // LCOV_EXCL_BR_LINE 11:unexpected branch  // NOLINT(whitespace/line_length)
343
344         l_istr >> l_ramTotalBytes;
345
346         break;
347       }
348     }
349   }
350
351   return (l_ramTotalBytes);
352 }
353
354 UI_32 CSysMemoryMonitor::BitReverse32(UI_32 f_val) {
355   // Don't print FRAMEWORKUNIFIEDLOG(ZONE_FUNC) to prevent obfuscation method from being revealed.
356   f_val = (((f_val & 0xaaaaaaaa) >> 1) | ((f_val & 0x55555555) << 1));
357   f_val = (((f_val & 0xcccccccc) >> 2) | ((f_val & 0x33333333) << 2));
358   f_val = (((f_val & 0xf0f0f0f0) >> 4) | ((f_val & 0x0f0f0f0f) << 4));
359   f_val = (((f_val & 0xff00ff00) >> 8) | ((f_val & 0x00ff00ff) << 8));
360   f_val = (f_val >> 16) | (f_val << 16);
361   return (f_val);
362 }