From 2eb42c0a484db599949a4b18eef3c62deb3c42a6 Mon Sep 17 00:00:00 2001 From: ToshikazuOhiwa Date: Mon, 30 Mar 2020 09:41:30 +0900 Subject: ss-resourcemanager branch --- resource_manager/server/Makefile | 57 + resource_manager/server/include/proc_watch.h | 25 + resource_manager/server/include/resm_cfg.h | 132 + resource_manager/server/include/resm_internal.h | 40 + .../server/include/ss_resm_resourcemanagerlog.h | 82 + .../server/include/system_service/resm.h | 325 +++ .../server/include/system_service/resm_type.h | 85 + .../include/system_service/resource_manager.h | 43 + resource_manager/server/src/cpuload_custom.cpp | 512 ++++ resource_manager/server/src/proc_watch.cpp | 319 +++ resource_manager/server/src/resm.cpp | 2755 ++++++++++++++++++++ .../server/src/resourcemanager_application.cpp | 155 ++ 12 files changed, 4530 insertions(+) create mode 100644 resource_manager/server/Makefile create mode 100644 resource_manager/server/include/proc_watch.h create mode 100644 resource_manager/server/include/resm_cfg.h create mode 100644 resource_manager/server/include/resm_internal.h create mode 100644 resource_manager/server/include/ss_resm_resourcemanagerlog.h create mode 100644 resource_manager/server/include/system_service/resm.h create mode 100644 resource_manager/server/include/system_service/resm_type.h create mode 100644 resource_manager/server/include/system_service/resource_manager.h create mode 100644 resource_manager/server/src/cpuload_custom.cpp create mode 100644 resource_manager/server/src/proc_watch.cpp create mode 100644 resource_manager/server/src/resm.cpp create mode 100644 resource_manager/server/src/resourcemanager_application.cpp (limited to 'resource_manager/server') diff --git a/resource_manager/server/Makefile b/resource_manager/server/Makefile new file mode 100644 index 00000000..18b40989 --- /dev/null +++ b/resource_manager/server/Makefile @@ -0,0 +1,57 @@ +# +# @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +######### installed program ############# +INST_PROGS = resm + +######### compiled sources ############# +resm_SRCS += resm.cpp +resm_SRCS += proc_watch.cpp +resm_SRCS += resourcemanager_application.cpp +resm_SRCS += cpuload_custom.cpp +resm_SRCS += resmgr_srvr_stub.cpp + +######### add source path ############# +VPATH += ./src +VPATH += ./include/$(COMPONENT_NAME) +VPATH += ../client + +######### add include path ############# +CPPFLAGS += -I./include +CPPFLAGS += -I../client + +######## add compile option ######## +CPPFLAGS += -DFRAMEWORKUNIFIEDLOGOPTIONS=0x08 +CPPFLAGS += -DFRAMEWORKUNIFIEDLOGAPPZONES=104,64,31,30,29,28 +CPPFLAGS += -DTARGET_SOC_$(TARGET_SOC) +CPPFLAGS += -DIMPL_AGL_APPLICATION_CALLBACKS_PRE_BACKGROUND +CPPFLAGS += -fno-exceptions + +######### linked library (dynamic) ############# +LDFLAGS += -Wl,--no-as-needed +LDLIBS += -Wl,--no-as-needed +LDLIBS += -Wl,-Bdynamic -lstdc++ +LDLIBS += -Wl,-Bdynamic -lSS_SystemIfUnified +LDLIBS += -Wl,-Bdynamic -lNS_FrameworkUnified +#LDLIBS += -Wl,-Bdynamic -lsoc_temperature_hal +LDLIBS += -Wl,-Bdynamic -lcommon +LDLIBS += -Wl,-Bdynamic -lvp +LDLIBS += -Wl,-Bdynamic -lrpc + +LDLIBS += -Wl,-Bdynamic -lev +#LDLIBS += -Wl,-Bdynamic -lDiagCodeAPI + +include ../../system_service.mk diff --git a/resource_manager/server/include/proc_watch.h b/resource_manager/server/include/proc_watch.h new file mode 100644 index 00000000..d7621451 --- /dev/null +++ b/resource_manager/server/include/proc_watch.h @@ -0,0 +1,25 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESOURCE_MANAGER_SERVER_INCLUDE_PROC_WATCH_H_ +#define RESOURCE_MANAGER_SERVER_INCLUDE_PROC_WATCH_H_ + +/********************************************** + * Prototype declaration + **********************************************/ +void *PRCW_main(void *p); + +#endif // RESOURCE_MANAGER_SERVER_INCLUDE_PROC_WATCH_H_ diff --git a/resource_manager/server/include/resm_cfg.h b/resource_manager/server/include/resm_cfg.h new file mode 100644 index 00000000..df282378 --- /dev/null +++ b/resource_manager/server/include/resm_cfg.h @@ -0,0 +1,132 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/****************************************************************************** +File name : resm_cfg.h +******************************************************************************/ +#ifndef RESOURCE_MANAGER_SERVER_INCLUDE_RESM_CFG_H_ +#define RESOURCE_MANAGER_SERVER_INCLUDE_RESM_CFG_H_ + +/****************************************************************************** +Configuration +******************************************************************************/ +/************************************************* + * Delay time from process start to monitoring start (sec) + * def:60 max:- min:0 + * (0: stop timer) + *************************************************/ +#define MONITORING_START_DELAT_TIME (60) + + +/************************************************* + * Delay time until authentication service monitoring start (sec) + * def:30 max:- min:0 + * (0: stop timer) + * MONITORING_START_DELAT_TIME > set to this value + *************************************************/ +#define EUA_MONITORING_START_DELAT_TIME (30) + + +/************************************************* + * Delay from drop_caches process startup (sec) + * def:20 max:- min:0 + * (0: stop timer) + *************************************************/ +#define DROP_CACHES_START_DELAT_TIME (20) + + +///************************************************* +// * CPU load threshold (%) +// * def:70 max:100 min:0 +// *************************************************/ +//#define CPU_LOAD_THRESHOLD (70) +/************************************************* + * CPU load threshold(%:XX.X) + * threshold:875 max:1000 min:0 + *************************************************/ +#define CPU_LOAD_THRESHOLD (875) + + +/************************************************* + * Number of CPU overload processes to be logged (rows) + * def:5 max:- min:0 + *************************************************/ +#define CPU_HIGH_LOAD_P_LOG_NUM (5) + + +///************************************************* +// * Log output frequency during CPU overload continuation (sec) +// * def:30 max:- min:0 +// * +// * Specify as a multiple of the polling interval(WTC_CPU_INTERVAL) for CPU load monitoring +// *************************************************/ +//#define CPU_HIGH_LOAD_LOG_FREQ (30) +/************************************************* + * Log output frequency during CPU overload continuation (sec) + * def:60 max:- min:0 + * + * Specify as a multiple of the polling interval(WTC_CPU_INTERVAL) for CPU load monitoring + *************************************************/ +#define CPU_HIGH_LOAD_LOG_FREQ (60) + + +/************************************************* + * perf Profiling/Measurement Processes + * def:1 max:- min:1 + *************************************************/ +#define PERF_MAX_PROCS (1) + +/************************************************* + * perf profiling/Output rows (functions) + * def:5 max:- min:1 + *************************************************/ +#define PERF_MAX_LINES (5) + +/************************************************* + * perf pofiling/perf-record running time (sec) + * def:1 max:- min:1 + *************************************************/ +#define PERF_RECORD_SPAN (1) + +#define TOP_TIMEOUT (60) + +#define RESET_SEC (60) + + +#define WTC_CPU_INTERVAL (6) + +#define TASK_STAT_THRESHOLD (70) +#define FIFO_TIMER_LIMIT (6) +#define TSS_TIMER_LIMIT (60) + +#define CPU_TASK_INIT (1) +#define CPU_TASK_SHOW_BF (2) +#define CPU_TASK_SHOW_AF (3) +#define FIFO_TASK_SHOW (4) +#define TSS_TASK_SHOW (5) +#define CPU_FIFO_TASK_GET_ID (6) +#define CPU_TSS_TASK_GET_ID (7) +#define CPU_FIFO_TASK_GET_OCCUPANCY (8) +#define CPU_TSS_TASK_GET_OCCUPANCY (9) + +#define STATUS_IDOL (1) +#define STATUS_CHECK_CPU (2) +#define STATUS_WATCH_PROCESS (3) + +#define TASK_STAT_RANK_NUM (5) + + +#endif // RESOURCE_MANAGER_SERVER_INCLUDE_RESM_CFG_H_ diff --git a/resource_manager/server/include/resm_internal.h b/resource_manager/server/include/resm_internal.h new file mode 100644 index 00000000..2c7e16b2 --- /dev/null +++ b/resource_manager/server/include/resm_internal.h @@ -0,0 +1,40 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESOURCE_MANAGER_SERVER_INCLUDE_RESM_INTERNAL_H_ +#define RESOURCE_MANAGER_SERVER_INCLUDE_RESM_INTERNAL_H_ + +#include +#include + +#include +#include "system_service/resm_type.h" + +#define Resm_Flag_ID_Base EV_Flag_ID_Base(RESMGR_MID) + +/******************************************************************************* + * User defined + *******************************************************************************/ +#define MY_MAX(a, b) ((a) > (b) ? (a) : (b)) + +/*********************************************************** + * Internal API definitions + ***********************************************************/ +RESM_ERR_t RESM_SV_Open(const RESM_RSV_t* p_prim, uint32_t* p_ssnld); +RESM_ERR_t RESM_SV_Close(uint32_t ssnld); +RESM_ERR_t RESM_SV_ChkSsnId(uint32_t ssnld); + +#endif // RESOURCE_MANAGER_SERVER_INCLUDE_RESM_INTERNAL_H_ diff --git a/resource_manager/server/include/ss_resm_resourcemanagerlog.h b/resource_manager/server/include/ss_resm_resourcemanagerlog.h new file mode 100644 index 00000000..20d00d04 --- /dev/null +++ b/resource_manager/server/include/ss_resm_resourcemanagerlog.h @@ -0,0 +1,82 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RESOURCE_MANAGER_SERVER_INCLUDE_SS_RESM_RESOURCEMANAGERLOG_H_ +#define RESOURCE_MANAGER_SERVER_INCLUDE_SS_RESM_RESOURCEMANAGERLOG_H_ + +#include + +#define ZONE_INIT ZONEMASK(10) // LIB common definition +#define ZONE_FUNC ZONEMASK(11) // LIB common definition +#define ZONE_MEM ZONEMASK(12) // LIB common definition +#define ZONE_13 ZONEMASK(13) +#define ZONE_14 ZONEMASK(14) +#define ZONE_15 ZONEMASK(15) +#define ZONE_16 ZONEMASK(16) +#define ZONE_17 ZONEMASK(17) +#define ZONE_18 ZONEMASK(18) +#define ZONE_19 ZONEMASK(19) +#define ZONE_20 ZONEMASK(20) +#define ZONE_21 ZONEMASK(21) +#define ZONE_22 ZONEMASK(22) +#define ZONE_23 ZONEMASK(23) +#define ZONE_24 ZONEMASK(24) +#define ZONE_25 ZONEMASK(25) +#define ZONE_26 ZONEMASK(26) +#define ZONE_27 ZONEMASK(27) +#define ZONE_RESM_DEBUG ZONEMASK(28) // DEBUG +#define ZONE_INFO ZONEMASK(29) // LIB common definition +#define ZONE_WARN ZONEMASK(30) // LIB common definition +#define ZONE_ERR ZONEMASK(31) // LIB common definition + +#define ZONE_SOC_TEMP ZONEMASK(104) + +#define ZONE_TEXT_10 "Init" +#define ZONE_TEXT_11 "Function" +#define ZONE_TEXT_12 "Memory" +#define ZONE_TEXT_13 "" +#define ZONE_TEXT_14 "" +#define ZONE_TEXT_15 "" +#define ZONE_TEXT_16 "" +#define ZONE_TEXT_17 "" +#define ZONE_TEXT_18 "" +#define ZONE_TEXT_19 "" +#define ZONE_TEXT_20 "" +#define ZONE_TEXT_21 "" +#define ZONE_TEXT_22 "" +#define ZONE_TEXT_23 "" +#define ZONE_TEXT_24 "" +#define ZONE_TEXT_25 "" +#define ZONE_TEXT_26 "" +#define ZONE_TEXT_27 "" +#define ZONE_TEXT_28 "ResmDebug" +#define ZONE_TEXT_29 "Info" +#define ZONE_TEXT_30 "Warning" +#define ZONE_TEXT_31 "Error" + +#define ALL_ZONES_BUT_IPC_INFO 0xEFFFFFFF + +#ifndef FRAMEWORKUNIFIEDLOGOPTIONS +#define FRAMEWORKUNIFIEDLOGOPTIONS (LSHAREDMEM) // LPRINT,LSHAREDMEM +#endif + +#ifndef FRAMEWORKUNIFIEDLOGAPPZONES + +#define FRAMEWORKUNIFIEDLOGAPPZONES ZONE_WARN, ZONE_ERR, ZONE_INFO +// #define FRAMEWORKUNIFIEDLOGAPPZONES ZONE_WARN,ZONE_ERR,ZONE_INFO,ZONE_RESM_DEBUG //DEBUG +#endif /* FRAMEWORKUNIFIEDLOGAPPZONES */ + +#endif // RESOURCE_MANAGER_SERVER_INCLUDE_SS_RESM_RESOURCEMANAGERLOG_H_ diff --git a/resource_manager/server/include/system_service/resm.h b/resource_manager/server/include/system_service/resm.h new file mode 100644 index 00000000..6490b4a6 --- /dev/null +++ b/resource_manager/server/include/system_service/resm.h @@ -0,0 +1,325 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file resm.h + * @brief \~english This file contains declaration of APIs for resm library + */ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup system_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup resource_manager + * @ingroup system_service + * @{ + */ + +#ifndef RESOURCE_MANAGER_SERVER_INCLUDE_SYSTEM_SERVICE_RESM_H_ +#define RESOURCE_MANAGER_SERVER_INCLUDE_SYSTEM_SERVICE_RESM_H_ + +#include "system_service/resm_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RESM_Open +/// \~english @par Summary +/// Opens the session with resource manager. +/// \~english @param [in] p_prim +/// RESM_RSV_t* - Unused, NULL +/// \~english @param [out] p_ssnId +/// uint32_t* - Pointer to session ID +/// \~english @par +/// RESM_RSV_t Variables +/// \~english @code +/// #define RESM_RSV_t int32_t +/// #define RESM_RSV_NULL (0x00) // NULL +/// @endcode +/// \~english @retval RESM_E_OK Succeeded +/// \~english @retval RESM_E_PAR %Parameter error +/// \~english @retval RESM_E_NG Unexpected error +/// \~english @par Preconditions +/// - Availability of ResourceManager must be TRUE. +/// \~english @par Change of the internal state +/// - The internal state is not changed. +/// \~english @par Causes of failures +/// - p_ssnId is NULL. [RESM_E_PAR] +/// - The global variable for getting RPC_ID of program (rpcId) is NULL. [RESM_E_NG] +/// - The area for RPC ID(rpcId) is not gotten. [RESM_E_NG] +/// - The number of the thread able to register in a process exceeds limit. [RESM_E_NG] +/// - It failed to get the area for thread information. [RESM_E_NG] +/// - It failed to get the area for ID information storage. [RESM_E_NG] +/// - It failed to generate the datagram socket for API request receiving. [RESM_E_NG] +/// - It failed to bind a socket. [RESM_E_NG] +/// - It failed to get a socket name. [RESM_E_NG] +/// - The number of sessions exceeds the maximum value. [RESM_E_NG] +/// - There is no space in the thread information area for event registration. [RESM_E_NG] +/// - It failed to get the thread information area for event registration. [RESM_E_NG] +/// - The file descriptor for getting an event is created. [RESM_E_NG] +/// - The generated session ID exists (EEXIST error at ioctl). [RESM_E_NG] +/// - Any error occurred during registering an event flag (EEXIST error at ioctl). [RESM_E_NG] +/// - Any error occurred during processing poling setting (error at ioctl). [RESM_E_NG] +/// \~english @par Classification +/// Public +/// \~english @par Type +/// None +/// \~english @par Detail +/// Opens a session. \n +/// An application can use another API by using the gotten ssnID. +/// \~english @see RESM_Close +//////////////////////////////////////////////////////////////////////////////////// +RESM_ERR_t RESM_Open(const RESM_RSV_t* p_prim, uint32_t* p_ssnld); + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RESM_Close +/// \~english @par Summary +/// Closes the session with resource manager. +/// \~english @param [in] ssnld +/// uint32_t - Session ID +/// \~english @retval RESM_E_OK Succeeded +/// \~english @retval RESM_E_PAR %Parameter error +/// \~english @par Preconditions +/// - An application must finish getting a session ID by RESM_Open(). +/// \~english @par Change of the internal state +/// - The internal state is not changed. +/// \~english @par Causes of failures +/// - ssnId exceeds the maximum value (EV_MAX_IDS_IN_THREAD). [RESM_E_PAR] +/// - The in-use flag of a global variable (g_resmgr.ssnInfo[ssnId].useFlag) is FALSE. [RESM_E_PAR] +/// \~english @par Classification +/// Public +/// \~english @par Type +/// None +/// \~english @par Detail +/// Closes a session. +/// \~english @see RESM_Open +//////////////////////////////////////////////////////////////////////////////////// +RESM_ERR_t RESM_Close(uint32_t ssnld); + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RESM_ReqEvent +/// \~english @par Summary +/// Requests to issue an event. +/// \~english @param [in] ssnld +/// uint32_t - Session ID +/// \~english @param [in] p_reqEvent +/// RESM_REQ_EVENT_t* - Pointer to event +/// \~english @par +/// RESM_REQ_EVENT_t Structure +/// \~english @code +/// typedef struct { +/// RESM_EV_t reqEvent; /* Event flag necessary to report */ +/// struct { +/// uint32_t restMemThresh; /* Threshold of the remaining capacity of system memory */ +/// } prm; +/// }RESM_REQ_EVENT_t; +/// @endcode +/// \~english @par +/// RESM_EV_t Variables +/// \~english @code +/// #define RESM_EV_t uint32_t +/// #define RESM_EV_NOP (0x00) +/// #define RESM_EV_MEM (0x01) +/// #define RESM_EV_NAND_STATUS (0x02) +/// @endcode +/// \~english @par +/// - RESM_EV_NOP : No event notification +/// - RESM_EV_MEM : Event notification for memory +/// - RESM_EV_NAND_STATUS : Eventnotification for NAND state +/// \~english @par +/// Notes +/// - restMemThresh is valid only when RESM_EV_MEM is set to reqEvent. \n +/// ResourceManager issues RESM_EV_MEM event at the timing +/// when the remaining capacity of system memory fell below the value (unit is BYTE) +/// which an application specifies. +/// \~english @retval RESM_E_OK Succeeded +/// \~english @retval RESM_E_PAR %Parameter error +/// \~english @par Preconditions +/// - An application must finish getting a session ID by RESM_Open(). +/// \~english @par Change of the internal state +/// - The internal state is not changed. +/// \~english @par Causes of failures +/// - p_reqEvent is NULL. [RESM_E_PAR] +/// - ssnId exceeds the maximum value (EV_MAX_IDS_IN_THREAD). [RESM_E_PAR] +/// - The in-use flag of a global variable (g_resmgr.ssnInfo[ssnId].useFlag) is FALSE. [RESM_E_PAR] +/// \~english @par Classification +/// Public +/// \~english @par Type +/// None +/// \~english @par Detail +/// Requests to issue an event. +/// This API is called from the RPC library. +/// \~english @see RESM_GetEvent +//////////////////////////////////////////////////////////////////////////////////// +RESM_ERR_t RESM_ReqEvent(uint32_t ssnld, const RESM_REQ_EVENT_t* p_reqEvent); + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RESM_GetEventFd +/// \~english @par Summary +/// Gets FD of the event to receive from resource manager. +/// \~english @param [in] ssnld +/// uint32_t - Session ID +/// \~english @param [out] p_fd +/// int* - Pointer to file descriptor +/// \~english @retval RESM_E_OK Succeeded +/// \~english @retval RESM_E_PAR %Parameter error +/// \~english @retval RESM_E_NG Unexpected error +/// \~english @par Preconditions +/// - An application must finish getting a session ID by RESM_Open(). +/// \~english @par Change of the internal state +/// - The internal state is not changed. +/// \~english @par Causes of failures +/// - p_fd is NULL. [RESM_E_PAR] +/// - ssnId exceeds the maximum value (EV_MAX_IDS_IN_THREAD). [RESM_E_PAR] +/// - The in-use flag of a global variable (g_resmgr.ssnInfo[ssnId].useFlag) is FALSE. [RESM_E_PAR] +/// - ssnId rewrites bit for an event flag decision by invalid values. [RESM_E_NG] +/// - The file descriptor corresponding to ssnId is not found. [RESM_E_NG] +/// \~english @par Classification +/// Public +/// \~english @par Type +/// None +/// \~english @par Detail +/// Gets FD of the event to receive from resource manager. \n +/// An application can do simultaneous wait of other events with the event of ResourceManager +/// by oversighting the gotten FD by select,poll etc. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +RESM_ERR_t RESM_GetEventFd(uint32_t ssnld, int* p_fd); + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RESM_GetEvent +/// \~english @par Summary +/// Gets the event from resource manager. +/// \~english @param [in] ssnld +/// uint32_t - Session ID +/// \~english @param [out] p_evFlag +/// RESM_EV_t* - Pointer to event +/// \~english @par +/// RESM_EV_t Variables +/// \~english @code +/// #define RESM_EV_t uint32_t +/// #define RESM_EV_NOP (0x00) +/// #define RESM_EV_MEM (0x01) +/// #define RESM_EV_NAND_STATUS (0x02) +/// @endcode +/// \~english @par +/// - RESM_EV_NOP : No event notification +/// - RESM_EV_MEM : Event notification for memory +/// - RESM_EV_NAND_STATUS : Event notification for NAND state +/// \~english @retval RESM_E_OK Succeeded +/// \~english @retval RESM_E_PAR %Parameter error +/// \~english @retval RESM_E_NG Unexpected error +/// \~english @par Preconditions +/// - An application must finish getting a session ID by RESM_Open(). +/// \~english @par Change of the internal state +/// - The internal state is not changed. +/// \~english @par Causes of failures +/// - p_evFlag is NULL. [RESM_E_PAR] +/// - ssnId exceeds the maximum value (EV_MAX_IDS_IN_THREAD). [RESM_E_PAR] +/// - The in-use flag of a global variable (g_resmgr.ssnInfo[ssnId].useFlag) is FALSE. [RESM_E_PAR] +/// - ssnId rewrites bit for an event flag decision by invalid values. [RESM_E_NG] +/// - The file descriptor corresponding to ssnId is not found. [RESM_E_NG] +/// - The flag of ssnId is not registered. (The returned value of ioctl is EOENT.) [RESM_E_NG] +/// - Any interruption occurred during getting an event. (The returned value of ioctl is EINTR.) [RESM_E_NG] +/// - Any error occurred during getting an event. (The returned value of ioctl is the error value +/// except for EOENT and EINTR.) [RESM_E_NG] +/// \~english @par Classification +/// Public +/// \~english @par Type +/// None +/// \~english @par Detail +/// When an event flag is not set, this is blocked. \n +/// If an event flag is set, this stores event contents to p_evFlag and this ends. \n +/// If this ends, it clears all of event flags. +/// \~english @see RESM_ReqEvent +//////////////////////////////////////////////////////////////////////////////////// +RESM_ERR_t RESM_GetEvent(uint32_t ssnld, RESM_EV_t* p_evFlag); + +///////////////////////////////////////////////////////////////////////////////////// +/// \ingroup RESM_GetStatus +/// \~english @par Summary +/// Gets system state. +/// \~english @param [in] ssnld +/// uint32_t - Session ID +/// \~english @param [out] p_status +/// RESM_STATUS_t* - Pointer to system state +/// \~english @par +/// RESM_STATUS_t Structure +/// \~english @code +/// typedef struct { +/// uint32_t restMemSize; /* Remaining memory length (KB) */ +/// RESM_NAND_WRITE_STATUS_t nandWriteStatus; /* Access permission / Prohibition state to NAND flash */ +/// RESM_INET_STATUS_t inetStatus; /* Network IF statistical information after start */ +/// } RESM_STATUS_t; +/// @endcode +/// \~english @par +/// enum RESM_NAND_WRITE_STATUS_t Variables +/// - RESM_NAND_WRITE_ENABLE : NAND access permission +/// - RESM_NAND_WRITE_DISABLE : NAND access prohibition +/// \~english @par +/// Notes +/// - When system records in NAND flash and it influences the lifetime of a device, +/// STATUS(nandWriteStatus) becomes RESM_NAND_WRITE_DISABLE. It is not in the state where WRITE fails. \n +/// \~english @par +/// RESM_INET_STATUS_t Structure +/// \~english @code +/// typedef struct { +/// uint32_t ifNum; /* Valid array at the number of interface and ifInfo */ +/// struct { +/// char name[64]; /* Interface name */ +/// uint64_t rxSize; /* Receiving data length (KiB) */ +/// uint64_t txSize; /* Transmission data length (KiB) */ +/// uint8_t hwaddr[HWADDR_LEN]; /* Hardware address (MAC address) */ +/// } ifInfo[RESM_INET_IF_MAX]; +/// }RESM_INET_STATUS_t; +/// @endcode +/// \~english @retval RESM_E_OK Succeeded +/// \~english @retval RESM_E_PAR %Parameter error +/// \~english @retval RESM_E_NG Unexpected error +/// \~english @par Preconditions +/// - An application must finish getting a session ID by RESM_Open(). +/// \~english @par Change of the internal state +/// - The internal state is not changed. +/// \~english @par Causes of failures +/// - p_evFlag is NULL. [RESM_E_PAR] +/// - ssnId exceeds the maximum value (EV_MAX_IDS_IN_THREAD). [RESM_E_PAR] +/// - The in-use flag of a global variable (g_resmgr.ssnInfo[ssnId].useFlag) is FALSE. [RESM_E_PAR] +/// - It failed to open the device file for network. [RESM_E_NG] +/// - The number of the gotten network IF is 0. [RESM_E_NG] +/// \~english @par Classification +/// Public +/// \~english @par Type +/// None +/// \~english @par Detail +/// Gets system state. +/// This API is called from the RPC library. +/// \~english @see None +//////////////////////////////////////////////////////////////////////////////////// +RESM_ERR_t RESM_GetStatus(uint32_t ssnld, RESM_STATUS_t* p_status); + +#ifdef __cplusplus +} +#endif + +#endif // RESOURCE_MANAGER_SERVER_INCLUDE_SYSTEM_SERVICE_RESM_H_ + +/** @}*/ // end of ResourceManager +/** @}*/ // end of SystemService +/** @}*/ // end of BaseSystem diff --git a/resource_manager/server/include/system_service/resm_type.h b/resource_manager/server/include/system_service/resm_type.h new file mode 100644 index 00000000..a1d42f90 --- /dev/null +++ b/resource_manager/server/include/system_service/resm_type.h @@ -0,0 +1,85 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @file resm_type.h + * @brief \~english This file contains declaration of common enum and structures for resm library + */ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup system_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup resource_manager + * @ingroup system_service + * @{ + */ +#ifndef RESOURCE_MANAGER_SERVER_INCLUDE_SYSTEM_SERVICE_RESM_TYPE_H_ +#define RESOURCE_MANAGER_SERVER_INCLUDE_SYSTEM_SERVICE_RESM_TYPE_H_ + +#include + +#define NTFY_ResourceMgr_Availability MN_SS_RESOURCEMGR"/Availability" + +#define RESM_ERR_t int32_t +#define RESM_E_OK (0) +#define RESM_E_PAR (-1) +#define RESM_E_NG (-2) + +// Event flags (bit pattern) +#define RESM_EV_t uint32_t +#define RESM_EV_NOP (0x00) +#define RESM_EV_MEM (0x01) +#define RESM_EV_NAND_STATUS (0x02) + +#define RESM_RSV_t int32_t + +typedef enum { + RESM_NAND_WRITE_ENABLE = 0, + RESM_NAND_WRITE_DISABLE = -1 +} RESM_NAND_WRITE_STATUS_t; + +typedef struct { + RESM_EV_t reqEvent; + struct { + uint32_t restMemThresh; + } prm; +} RESM_REQ_EVENT_t; + +#define RESM_INET_IF_MAX 5 /* tentative */ +#define HWADDR_LEN (6) +typedef struct { + uint32_t ifNum; + struct { + char name[64]; + uint64_t rxSize; + uint64_t txSize; + uint8_t hwaddr[HWADDR_LEN]; + } ifInfo[RESM_INET_IF_MAX]; +} RESM_INET_STATUS_t; + +typedef struct { + uint32_t restMemSize; + RESM_NAND_WRITE_STATUS_t nandWriteStatus; + RESM_INET_STATUS_t inetStatus; +} RESM_STATUS_t; + +#endif // RESOURCE_MANAGER_SERVER_INCLUDE_SYSTEM_SERVICE_RESM_TYPE_H_ +/** @}*/ +/** @}*/ +/** @}*/ diff --git a/resource_manager/server/include/system_service/resource_manager.h b/resource_manager/server/include/system_service/resource_manager.h new file mode 100644 index 00000000..437a1cb8 --- /dev/null +++ b/resource_manager/server/include/system_service/resource_manager.h @@ -0,0 +1,43 @@ +/* + * @copyright Copyright (c) 2017-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file resource_manager.h + * @brief \~english include all resm_library head files + */ + +/** @addtogroup BaseSystem + * @{ + */ +/** @addtogroup system_service + * @ingroup BaseSystem + * @{ + */ +/** @addtogroup resource_manager + * @ingroup system_service + * @{ + */ + +#ifndef RESOURCE_MANAGER_SERVER_INCLUDE_SYSTEM_SERVICE_RESOURCE_MANAGER_H_ +#define RESOURCE_MANAGER_SERVER_INCLUDE_SYSTEM_SERVICE_RESOURCE_MANAGER_H_ + +#include "system_service/resm.h" +#include "system_service/resm_type.h" + +#endif // RESOURCE_MANAGER_SERVER_INCLUDE_SYSTEM_SERVICE_RESOURCE_MANAGER_H_ +/** @}*/ +/** @}*/ +/** @}*/ diff --git a/resource_manager/server/src/cpuload_custom.cpp b/resource_manager/server/src/cpuload_custom.cpp new file mode 100644 index 00000000..c4b1e60c --- /dev/null +++ b/resource_manager/server/src/cpuload_custom.cpp @@ -0,0 +1,512 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ss_resm_resourcemanagerlog.h" + +#include "resm_cfg.h" + +typedef struct _task_stat { + struct _task_stat *next; + char path[64]; + pid_t pid_nr_ns; + char tcomm[64]; + char state; + pid_t ppid; + pid_t pgid; + unsigned long utime; // NOLINT + unsigned long stime; // NOLINT + int priority; + int nice; + int task_cpu; + unsigned int task_rt_priority; + unsigned int task_policy; +} TASK_STAT; + + +typedef struct _task_rank +{ + pid_t pid_nr_ns; + char state; + unsigned long taskOccupancy; + unsigned long utime; + unsigned long stime; + int priority; + unsigned int task_policy; + int task_cpu; + char tcomm[64]; +} TASK_RANK; + + +static TASK_STAT *g_task_stat = NULL; + +static int32_t g_fifo_task_pid = -1; +static int32_t g_tss_task_pid = -1; +static unsigned long g_fifo_task_occ = -1; +static unsigned long g_tss_task_occ = -1; +static int32_t g_fifo_show_timer = 0; +static int32_t g_tss_show_timer = 0; +static unsigned int g_startTime = 0; +static char g_fifo_path[64]; +static char g_tss_path[64]; +static unsigned long g_fifo_utime; +static unsigned long g_fifo_stime; +static unsigned long g_tss_utime; +static unsigned long g_tss_stime; + + +static void cleanup_task_stat(void) { + TASK_STAT *p, *q; + + p = g_task_stat; + while (p) { + q = p->next; + free(p); + p = q; + } + g_task_stat = NULL; +} + +static int add_task_stat(TASK_STAT *tstat) { + TASK_STAT *p; + + p = reinterpret_cast(malloc(sizeof(TASK_STAT))); + if (p == NULL) { // LCOV_EXCL_BR_LINE 5: malloc error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return -1; // LCOV_EXCL_LINE 5: malloc error case + } + memcpy(p, tstat, sizeof(TASK_STAT)); + p->next = 0; + + if (g_task_stat) { + p->next = g_task_stat; + } + g_task_stat = p; + + return 0; +} + +// No error : > 0 +static int get_task_stat(const char *path, TASK_STAT *tstat) { + pid_t sid; + int tty_nr, tty_pgrp; + unsigned long task_flags; // NOLINT + unsigned long min_flt, cmin_flt, maj_flt, cmaj_flt; // NOLINT + signed long cutime, cstime; // NOLINT + int num_threads, zero1; + unsigned long long start_time; // NOLINT + unsigned long vsize, mm_rss, rsslim, start_code, end_code, start_stack; // NOLINT + unsigned long esp, eip, task_pending_signal_sig, task_blocked_sig; // NOLINT + unsigned long sigign_sig, sigcatch_sig, wchan, zero2, zero3; // NOLINT + int exit_signal; + unsigned long long delayacct_blkio_ticks; // NOLINT + unsigned long guest_time; // NOLINT + signed long cguest_time; // NOLINT + + int fd; + int ret = -1; +#define READ_MAX_SIZE 4096 + char buf[READ_MAX_SIZE]; + + fd = open(path, O_RDONLY); + if (fd != -1) { + if (read(fd, buf, sizeof(buf)) != -1) { // LCOV_EXCL_BR_LINE 5: read's error case + ret = + sscanf( + buf, + "%d %32s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %d %d %d %d %llu %lu %lu" + " %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld", + &(tstat->pid_nr_ns), tstat->tcomm, &(tstat->state), + &(tstat->ppid), &(tstat->pgid), &sid, &tty_nr, &tty_pgrp, + &task_flags, &min_flt, &cmin_flt, &maj_flt, &cmaj_flt, + &(tstat->utime), &(tstat->stime), &cutime, &cstime, + &(tstat->priority), &(tstat->nice), &num_threads, &zero1, + &start_time, &vsize, &mm_rss, &rsslim, &start_code, &end_code, + &start_stack, &esp, &eip, &task_pending_signal_sig, + &task_blocked_sig, &sigign_sig, &sigcatch_sig, &wchan, &zero2, + &zero3, &exit_signal, &(tstat->task_cpu), + &(tstat->task_rt_priority), &(tstat->task_policy), + &delayacct_blkio_ticks, &guest_time, &cguest_time); + } + close(fd); + } + return ret; +} + +static void get_current_task_stat(void) { + TASK_STAT tstat; + DIR *dirp; + struct dirent entry; + struct dirent *result; + char path[64]; + + struct timespec tp; + + dirp = opendir("/proc"); + if (dirp == NULL) { // LCOV_EXCL_BR_LINE 5: opendir error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return; // LCOV_EXCL_LINE 5: opendir error case + } + + if (clock_gettime (CLOCK_MONOTONIC, &tp) == 0) { + g_startTime = ((tp.tv_sec * 1000) + (tp.tv_nsec / 1000000)); // Unit is msec + } else { + g_startTime = 0; + } + + while ((readdir_r(dirp, &entry, &result) == 0) && (result != NULL)) { + if ((entry.d_name[0] >= '1') && (entry.d_name[0] <= '9')) { + DIR *dirp2; + struct dirent entry2; + struct dirent *result2; + + sprintf(path, "/proc/%s/task", entry.d_name); // NOLINT + dirp2 = opendir(path); + if (dirp2 == NULL) { // LCOV_EXCL_BR_LINE 5: opendir error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + continue; // LCOV_EXCL_LINE 5: opendir error case + } + + while ((readdir_r(dirp2, &entry2, &result2) == 0) && (result2 != NULL)) { + if ((entry2.d_name[0] >= '1') && (entry2.d_name[0] <= '9')) { + char path2[64]; + int ret; + struct timespec req = { 0, 1000000 }; // 1msec + + sprintf(path2, "%s/%s/stat", path, entry2.d_name); // NOLINT + ret = get_task_stat(path2, &tstat); + +// if ((ret > 0) && (tstat.task_policy == SCHED_FIFO)) { + if (ret > 0) { // LCOV_EXCL_BR_LINE 200: ret must be bigger than 0 + + strcpy(tstat.path, path2); // NOLINT + add_task_stat(&tstat); + } + nanosleep(&req, NULL); + } + } + closedir(dirp2); + } + } + closedir(dirp); +} + +static void show_cpuload(void) { + int ret; + TASK_STAT tstat; + TASK_STAT *p = g_task_stat; + + TASK_RANK ttaskRankData[TASK_STAT_RANK_NUM+1]; + TASK_RANK t_eva_taskRank; + int setRankDatanum = 0; + int checkCounter; + + unsigned long dtime; // NOLINT + unsigned long dtime_urank; + unsigned long dtime_drank; + struct timespec tp; + unsigned int endTime = 0; + +// if (p) { +// FRAMEWORKUNIFIEDLOG( +// ZONE_INFO, +// __FUNCTION__, +// "[CpuHighLoad]Please check User backtrace of following processes in kernel.log"); +// FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, +// "[CpuHighLoad] PID ST PRI POLICY cpuX %%CPU (ut:st) comm"); +// } + if (clock_gettime (CLOCK_MONOTONIC, &tp) == 0) { + endTime = ((tp.tv_sec * 1000) + (tp.tv_nsec / 1000000)); // Unit is msec + } else { + endTime = (WTC_CPU_INTERVAL * 1000) + g_startTime; + } + if (endTime - g_startTime <= 0) { // LCOV_EXCL_BR_LINE 200: (endTime - g_startTime) must be bigger than 0 + // LCOV_EXCL_START 200: (endTime - g_startTime) must be bigger than 0 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG (ZONE_WARN, __FUNCTION__, "[CpuHighLoad] Timer abnormality."); + endTime = g_startTime + 1; + // LCOV_EXCL_STOP + } + + while (p) { + ret = get_task_stat(p->path, &tstat); + if (ret >= 0) { + +#if 0 + dtime = (tstat.utime + tstat.stime) - (p->utime + p->stime); + if (dtime > 0) { + FRAMEWORKUNIFIEDLOG( + ZONE_INFO, + __FUNCTION__, + "[CpuHighLoad]%5d %c %3d %5s cpu%d %4lu (%lu:%lu) %s", + p->pid_nr_ns, + p->state, + p->priority, + p->task_policy == SCHED_FIFO ? "FIFO" : + p->task_policy == SCHED_RR ? "RR" : "OTHER", + p->task_cpu, dtime, tstat.utime - p->utime, tstat.stime - p->stime, + p->tcomm); + if ((dtime >= 70) // %%CPU 70% over only + && (getpid() != p->pid_nr_ns) // except current process + && (strcmp(p->tcomm, "(NS_BackupMgr)"))) { // except "BackupMgr" +// print_backtrace_pid (p->pid_nr_ns); // backtrace in kernel.log + } + } + } + p = p->next; + } +#endif + dtime = (((tstat.utime + tstat.stime) - (p->utime + p->stime)) * 1000) / (endTime - g_startTime); + if (((tstat.utime + tstat.stime) - (p->utime + p->stime)) > 0) { + if (setRankDatanum <= TASK_STAT_RANK_NUM) { + ttaskRankData[setRankDatanum].pid_nr_ns = p->pid_nr_ns; + ttaskRankData[setRankDatanum].state = p->state; + ttaskRankData[setRankDatanum].priority = p->priority; + ttaskRankData[setRankDatanum].task_policy = p->task_policy; + ttaskRankData[setRankDatanum].task_cpu = p->task_cpu; + ttaskRankData[setRankDatanum].taskOccupancy = dtime; + ttaskRankData[setRankDatanum].utime = tstat.utime - p->utime; + ttaskRankData[setRankDatanum].stime = tstat.stime - p->stime; + strcpy(ttaskRankData[setRankDatanum].tcomm, p->tcomm); + setRankDatanum++; + } else { + ttaskRankData[TASK_STAT_RANK_NUM].pid_nr_ns = p->pid_nr_ns; + ttaskRankData[TASK_STAT_RANK_NUM].state = p->state; + ttaskRankData[TASK_STAT_RANK_NUM].priority = p->priority; + ttaskRankData[TASK_STAT_RANK_NUM].task_policy = p->task_policy; + ttaskRankData[TASK_STAT_RANK_NUM].task_cpu = p->task_cpu; + ttaskRankData[TASK_STAT_RANK_NUM].taskOccupancy = dtime; + ttaskRankData[TASK_STAT_RANK_NUM].utime = tstat.utime - p->utime; + ttaskRankData[TASK_STAT_RANK_NUM].stime = tstat.stime - p->stime; + strcpy(ttaskRankData[TASK_STAT_RANK_NUM].tcomm, p->tcomm); + } + for (checkCounter = (setRankDatanum - 1); checkCounter > 0; checkCounter--) { + dtime_urank = ttaskRankData[checkCounter - 1].utime + ttaskRankData[checkCounter - 1].stime; + dtime_drank = ttaskRankData[checkCounter].utime + ttaskRankData[checkCounter].stime; + if (dtime_urank < dtime_drank) { + t_eva_taskRank.pid_nr_ns = ttaskRankData[checkCounter].pid_nr_ns; + t_eva_taskRank.state = ttaskRankData[checkCounter].state; + t_eva_taskRank.priority = ttaskRankData[checkCounter].priority; + t_eva_taskRank.task_policy = ttaskRankData[checkCounter].task_policy; + t_eva_taskRank.task_cpu = ttaskRankData[checkCounter].task_cpu; + t_eva_taskRank.taskOccupancy = ttaskRankData[checkCounter].taskOccupancy; + t_eva_taskRank.utime = ttaskRankData[checkCounter].utime; + t_eva_taskRank.stime = ttaskRankData[checkCounter].stime; + strcpy(t_eva_taskRank.tcomm, ttaskRankData[checkCounter].tcomm); + + ttaskRankData[checkCounter].pid_nr_ns = ttaskRankData[checkCounter - 1].pid_nr_ns; + ttaskRankData[checkCounter].state = ttaskRankData[checkCounter - 1].state; + ttaskRankData[checkCounter].priority = ttaskRankData[checkCounter - 1].priority; + ttaskRankData[checkCounter].task_policy = ttaskRankData[checkCounter - 1].task_policy; + ttaskRankData[checkCounter].task_cpu = ttaskRankData[checkCounter - 1].task_cpu; + ttaskRankData[checkCounter].taskOccupancy = ttaskRankData[checkCounter - 1].taskOccupancy; + ttaskRankData[checkCounter].utime = ttaskRankData[checkCounter - 1].utime; + ttaskRankData[checkCounter].stime = ttaskRankData[checkCounter - 1].stime; + strcpy(ttaskRankData[checkCounter].tcomm, ttaskRankData[checkCounter - 1].tcomm); + + ttaskRankData[checkCounter - 1].pid_nr_ns = t_eva_taskRank.pid_nr_ns; + ttaskRankData[checkCounter - 1].state = t_eva_taskRank.state; + ttaskRankData[checkCounter - 1].priority = t_eva_taskRank.priority; + ttaskRankData[checkCounter - 1].task_policy = t_eva_taskRank.task_policy; + ttaskRankData[checkCounter - 1].task_cpu = t_eva_taskRank.task_cpu; + ttaskRankData[checkCounter - 1].taskOccupancy = t_eva_taskRank.taskOccupancy; + ttaskRankData[checkCounter - 1].utime = t_eva_taskRank.utime; + ttaskRankData[checkCounter - 1].stime = t_eva_taskRank.stime; + strcpy(ttaskRankData[checkCounter - 1].tcomm, t_eva_taskRank.tcomm); + } else { + break; + } + } + if ((dtime >= TASK_STAT_THRESHOLD) && // %%CPU over only + (getpid() != p->pid_nr_ns) && // except current process + (strcmp (p->tcomm, "(NS_BackupMgr)"))) { // except "BackupMgr" + if (p->task_policy == SCHED_FIFO) { + if ((g_fifo_task_occ < dtime) && (g_fifo_show_timer == 0)) { // first time only + g_fifo_task_pid = p->pid_nr_ns; + g_fifo_task_occ = dtime; + g_fifo_utime = tstat.utime; + g_fifo_stime = tstat.stime; + strcpy(g_fifo_path,p->path); + } else if (g_fifo_task_pid == p->pid_nr_ns) { + g_fifo_task_occ = dtime; + g_fifo_utime = tstat.utime; + g_fifo_stime = tstat.stime; + strcpy(g_fifo_path,p->path); + } + } else { + if ((g_tss_task_occ < dtime) && (g_tss_show_timer == 0)) { // first time only + g_tss_task_pid = p->pid_nr_ns; + g_tss_task_occ = dtime; + g_tss_utime = tstat.utime; + g_tss_stime = tstat.stime; + strcpy(g_tss_path,p->path); + } else if (g_tss_task_pid == p->pid_nr_ns) { + g_tss_task_occ = dtime; + g_tss_utime = tstat.utime; + g_tss_stime = tstat.stime; + strcpy(g_tss_path,p->path); + } + } + } + } + } + p = p->next; + } + + if (setRankDatanum != 0) { + FRAMEWORKUNIFIEDLOG (ZONE_WARN, __FUNCTION__, "[CpuHighLoad] PID ST PRI POLICY cpuX %%CPU (%%ut:%%st) comm"); + for (checkCounter = 0; + checkCounter < (setRankDatanum < TASK_STAT_RANK_NUM ? setRankDatanum : TASK_STAT_RANK_NUM); checkCounter++) { + FRAMEWORKUNIFIEDLOG (ZONE_WARN, __FUNCTION__, "[CpuHighLoad]%5d %c %3d %5s cpu%d %4lu (%2lu.%03lu:%2lu.%03lu) %s", + ttaskRankData[checkCounter].pid_nr_ns, + ttaskRankData[checkCounter].state, + ttaskRankData[checkCounter].priority, + ttaskRankData[checkCounter].task_policy == SCHED_FIFO ? "FIFO" + : ttaskRankData[checkCounter].task_policy == SCHED_RR ? "RR" : "TSS", + ttaskRankData[checkCounter].task_cpu, + ttaskRankData[checkCounter].taskOccupancy, + ttaskRankData[checkCounter].utime * 100 / ((endTime - g_startTime)/10), + ttaskRankData[checkCounter].utime * 100 % ((endTime - g_startTime)/10), + ttaskRankData[checkCounter].stime * 100 / ((endTime - g_startTime)/10), + ttaskRankData[checkCounter].stime * 100 % ((endTime - g_startTime)/10), + ttaskRankData[checkCounter].tcomm); + } + FRAMEWORKUNIFIEDLOG (ZONE_WARN, __FUNCTION__, "[CpuHighLoad] -------------------------------------------------"); + } + +} + + +static void +show_cpuload_onetask(int loadType) { + int ret; + TASK_STAT tstat; + unsigned long dtime; + struct timespec tp; + unsigned int endTime = 0; + char loadPath[64]; + unsigned long beforeUtime; + unsigned long beforeStime; + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) { + endTime = ((tp.tv_sec * 1000) + (tp.tv_nsec / 1000000)); // Unit is msec + } else { + endTime = (WTC_CPU_INTERVAL * 1000) + g_startTime; + } + if (endTime - g_startTime <= 0) { // LCOV_EXCL_BR_LINE 200: (endTime - g_startTime) must be bigger than 0 + // LCOV_EXCL_START 200: (endTime - g_startTime) must be bigger than 0 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG (ZONE_WARN, __FUNCTION__, "[CpuHighLoad] Timer abnormality."); + endTime = g_startTime + 1; + // LCOV_EXCL_STOP + } + if (loadType == FIFO_TASK_SHOW) { // LCOV_EXCL_BR_LINE 200: loadType can't be FIFO_TASK_SHOW + // LCOV_EXCL_START 200: loadType can't be FIFO_TASK_SHOW + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + strcpy(loadPath,g_fifo_path); + beforeUtime = g_fifo_utime; + beforeStime = g_fifo_stime; + // LCOV_EXCL_STOP + } else { + strcpy(loadPath,g_tss_path); + beforeUtime = g_tss_utime; + beforeStime = g_tss_stime; + } + if (strlen(loadPath) > 0) { + ret = get_task_stat(loadPath, &tstat); + if (ret >= 0) { + dtime = (((tstat.utime + tstat.stime) - (beforeUtime + beforeStime)) * 1000) / (endTime - g_startTime); + if (tstat.task_policy == SCHED_FIFO) { + g_fifo_task_occ = dtime; + g_fifo_utime = tstat.utime; + g_fifo_stime = tstat.stime; + } else { + g_tss_task_occ = dtime; + g_tss_utime = tstat.utime; + g_tss_stime = tstat.stime; + } + } + } +} + + + +//void logging_cpuload_custom(void) { +// struct timespec req = { 1, 0 }; // 1sec +// +// cleanup_task_stat(); +// get_current_task_stat(); +// +// nanosleep(&req, NULL); +// +// show_cpuload(); +//} +unsigned long +logging_cpuload_custom(int32_t tmode) { + int32_t res = 0; + if (tmode == CPU_TASK_INIT) { + g_fifo_task_pid = -1; + g_tss_task_pid = -1; + g_fifo_task_occ = 0; + g_tss_task_occ = 0; + g_fifo_utime = 0; + g_fifo_stime = 0; + g_tss_utime = 0; + g_tss_stime = 0; + memset(g_fifo_path, 0x00, sizeof(g_fifo_path)); + memset(g_tss_path, 0x00, sizeof(g_tss_path)); + cleanup_task_stat(); + get_current_task_stat(); + } else if (tmode == CPU_TASK_SHOW_BF) { + cleanup_task_stat(); + get_current_task_stat(); + } else if (tmode == CPU_TASK_SHOW_AF) { + show_cpuload(); + } else if (tmode == FIFO_TASK_SHOW) { // LCOV_EXCL_BR_LINE 200: tmode can't be FIFO_TASK_SHOW + // LCOV_EXCL_START 200: tmode can't be FIFO_TASK_SHOW + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + show_cpuload_onetask(FIFO_TASK_SHOW); + // LCOV_EXCL_STOP + } else if (tmode == TSS_TASK_SHOW) { + show_cpuload_onetask(TSS_TASK_SHOW); + } else if (tmode == CPU_FIFO_TASK_GET_ID) { + res = g_fifo_task_pid; + g_fifo_show_timer = 0; + } else if (tmode == CPU_TSS_TASK_GET_ID) { + res = g_tss_task_pid; + g_tss_show_timer = 0; + } else if (tmode == CPU_FIFO_TASK_GET_OCCUPANCY) { + g_fifo_show_timer = g_fifo_show_timer + WTC_CPU_INTERVAL; + res = g_fifo_task_occ; + g_fifo_task_occ = 0; + } else if (tmode == CPU_TSS_TASK_GET_OCCUPANCY) { // LCOV_EXCL_BR_LINE 200: tmode can't be other value + g_tss_show_timer = g_tss_show_timer + WTC_CPU_INTERVAL; + res = g_tss_task_occ; + g_tss_task_occ = 0; + } + return res; +} + diff --git a/resource_manager/server/src/proc_watch.cpp b/resource_manager/server/src/proc_watch.cpp new file mode 100644 index 00000000..fcbec3c9 --- /dev/null +++ b/resource_manager/server/src/proc_watch.cpp @@ -0,0 +1,319 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* or */ +#include + +//#include +#include +#include +//#include + +#include "ss_resm_resourcemanagerlog.h" +#include "proc_watch.h" +#include "resm_cfg.h" +#include "resm_internal.h" + +#define WTC_TMPFS_INTERVAL (5) +#define WTC_MEM_INTERVAL (5) +#define DEBUG_INFO_OUTPUT_FREQ (1) + +extern int isNfs; +extern void watchMem(void); +extern void outputResouceInfo(void); +extern EFrameworkunifiedStatus resourcemanagerlog_flag_check(UI_8 *mode); + +#define _SOC_TEMP_MONITOR_ + +#if defined(_SOC_TEMP_MONITOR_) + +extern void set_diag_ss_resourcemanager_err(uint16_t resourcemanager_code); + +/********************************************************************************* + * Soc Temperature + register THSSR : T = CTEMP[5-0] x 5 - 65 [Celsius] + *********************************************************************************/ +#define SOC_TEMP_WATCH_INTVAL_TIMESEC (3 * 60) // 3 minutes +// #define SOC_TEMP_WATCH_INTVAL_TIMESEC (1 * 5) // for debug +#define THSSR_TEMP_MASK 0x0000003F +#define TEMP_120 (120) +#define TEMP_125 (125) +#define TEMP_130 (130) + +static float last_temp; +static int last_diag; + +static void soc_temp_init(void) { + FRAMEWORKUNIFIEDLOG(ZONE_SOC_TEMP, __FUNCTION__, "start"); + last_temp = 0.0f; + last_diag = 0; +} + +static void soc_temp(void) { + float temp = 0.0f; +// EFrameworkunifiedStatus e_status = GetSoCTemperature(&temp); +// if (eFrameworkunifiedStatusOK != e_status) { +// FRAMEWORKUNIFIEDLOG(ZONE_SOC_TEMP, __FUNCTION__, +// "THSSR:GetSoCTemperature e_status(%d)", e_status); +// return; +// } + + if (TEMP_120 <= temp) { + // FRAMEWORKUNIFIEDLOG + FRAMEWORKUNIFIEDLOG(ZONE_SOC_TEMP, __FUNCTION__, "%f", temp); // LCOV_EXCL_BR_LINE 15: marco defined in "native_service/ns_logger_if.h" // NOLINT[whitespace/line_length] + + // DIAGCODE + if (TEMP_130 <= temp) { + if (TEMP_130 != last_diag) { +#if 0 // TODO(Workaround to avoid build errors for customization by suppliers. Planned to fix on MK.) + set_diag_ss_resourcemanager_err(DIAGCODE_VIDEOINHALEX_OVERTEMP_3); /* SoC Temperature anomaly(130 degree Or more) */ +#endif + last_diag = TEMP_130; + } + } else if (TEMP_125 <= temp) { + if (TEMP_125 != last_diag) { +#if 0 // TODO(Workaround to avoid build errors for customization by suppliers. Planned to fix on MK.) + set_diag_ss_resourcemanager_err(DIAGCODE_VIDEOINHALEX_OVERTEMP_2); /* SoC Temperature anomaly(125 degree Or more) */ +#endif + last_diag = TEMP_125; + } + } else { + if (TEMP_120 != last_diag) { +#if 0 // TODO(Workaround to avoid build errors for customization by suppliers. Planned to fix on MK.) + set_diag_ss_resourcemanager_err(DIAGCODE_VIDEOINHALEX_OVERTEMP_1); /* SoC Temperature anomaly(120 degree Or more) */ +#endif + last_diag = TEMP_120; + } + } + } else { + // FRAMEWORKUNIFIEDLOG + if (TEMP_120 <= last_temp) { + FRAMEWORKUNIFIEDLOG(ZONE_SOC_TEMP, __FUNCTION__, "%f", temp); // LCOV_EXCL_BR_LINE 15: marco defined in "native_service/ns_logger_if.h" // NOLINT[whitespace/line_length] + } + + // DIAGCODE + last_diag = 0; + } + last_temp = temp; +} +#endif // defined ( _SOC_TEMP_MONITOR_ ) + +// +// Monitor /tmp +// +#define TMP_USED_SIZE (100*1024) // 100MB +#define TMPFS_PATH "/tmp" +static int watch_tmpfs_enable = 1; + +static void printdir(const char* path) { + DIR *dirp; + struct dirent entry, *next; + char buf[512]; + + dirp = opendir(path); + if (dirp == NULL) { // LCOV_EXCL_BR_LINE 5: opendir's error case. + // LCOV_EXCL_START 5: opendir's error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "opendir(%s) error.(%d)\n", path, errno); + return; + // LCOV_EXCL_STOP 5: opendir's error case. + } + while ((readdir_r(dirp, &entry, &next) == 0) && next != NULL) { + if (((strlen(entry.d_name) == 1) && (strcmp(entry.d_name, ".") == 0)) + || ((strlen(entry.d_name) == 2) && (strcmp(entry.d_name, "..") == 0))) { + continue; + } + if ((strlen(path) + strlen(entry.d_name) + 2) <= sizeof(buf)) {/* 2: '/','\0' */ + struct stat stat_buf; + + strcpy(buf, path); // NOLINT + strcat(buf, "/"); // NOLINT + strcat(buf, entry.d_name); // NOLINT + if (stat(buf, &stat_buf) == -1) { // LCOV_EXCL_BR_LINE 5: stat error case + // LCOV_EXCL_START 5: stat error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "%s stat error! (%d)\n", buf, errno); + // LCOV_EXCL_STOP 5: stat's error case. + } else if (S_ISDIR(stat_buf.st_mode)) { + printdir(buf); + } else { + FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "%s %ld bytes", buf, stat_buf.st_size); + } + } else { + FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "path(%s) name(%s) length over!\n", path, + entry.d_name); + } + } + closedir(dirp); + + return; +} + +static void watchtmpfs(void) { + int ret; + struct statfs buf; + long used; // NOLINT + + if (!watch_tmpfs_enable) { + return; + } + ret = statfs(TMPFS_PATH, &buf); + if (ret < 0) { // LCOV_EXCL_BR_LINE 5: statfs error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return; // LCOV_EXCL_LINE 5: statfs error case + } + used = (buf.f_blocks - buf.f_bavail) * buf.f_bsize / 1024; // KB + if (used > TMP_USED_SIZE) { + FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "%s Used %ld KB > %d KB", + TMPFS_PATH, + used, TMP_USED_SIZE); + FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "----- print %s start -----", TMPFS_PATH); + printdir(TMPFS_PATH); + FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "----- print %s end -----", TMPFS_PATH); + watch_tmpfs_enable = 0; + } +} + +/********************************************************************************* + * proc_watch thread main + *********************************************************************************/ +void * +PRCW_main(void *p) { + fd_set fds; + int32_t maxFd = 0; + int32_t timerFd; + struct itimerspec tm; + int32_t sec = 0; + EFrameworkunifiedStatus flagRet; + uint64_t exp; + int ret; + UI_8 mode; +#if defined(_SOC_TEMP_MONITOR_) + int32_t timerFd2; + struct itimerspec tm2; +#endif // defined(_SOC_TEMP_MONITOR_) + + /* Memory monitoring and display debug information */ + timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + if (timerFd == -1) { // LCOV_EXCL_BR_LINE 5: timerfd_create error case + // LCOV_EXCL_START 5: timerfd_create error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Create timerFd Failed. errno[%d]", errno); + // LCOV_EXCL_STOP 5: timerfd_create error case + } else { + tm.it_value.tv_sec = MONITORING_START_DELAT_TIME; + tm.it_value.tv_nsec = 0; + tm.it_interval.tv_sec = 1; + tm.it_interval.tv_nsec = 0; + if (timerfd_settime(timerFd, 0, &tm, NULL) == -1) { // LCOV_EXCL_BR_LINE 5: timerfd_create error case + // LCOV_EXCL_START 5: timerfd_settime error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Set timerFd Failed. errno[%d]", errno); + // LCOV_EXCL_STOP 5: timerfd_settime error case + } + } + +#if defined(_SOC_TEMP_MONITOR_) + /* Soc temperature monitoring */ + timerFd2 = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + if (timerFd2 == -1) { // LCOV_EXCL_BR_LINE 5: timerfd_create error case + // LCOV_EXCL_START 5: timerfd_create error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Create timerFd2 Failed. errno[%d]", errno); + // LCOV_EXCL_STOP 5: timerfd_create error case + } else { + tm2.it_value.tv_sec = 1; + tm2.it_value.tv_nsec = 0; + tm2.it_interval.tv_sec = SOC_TEMP_WATCH_INTVAL_TIMESEC; + tm2.it_interval.tv_nsec = 0; + if (timerfd_settime(timerFd2, 0, &tm2, NULL) == -1) { // LCOV_EXCL_BR_LINE 5: timerfd_settime error case + // LCOV_EXCL_START 5: timerfd_settime error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Set timerFd2 Failed. errno[%d]", errno); + // LCOV_EXCL_STOP 5: timerfd_settime error case + } + soc_temp_init(); + } +#endif // defined(_SOC_TEMP_MONITOR_) + + while (1) { + FD_ZERO(&fds); + if (timerFd != -1) { // LCOV_EXCL_BR_LINE 5: timerfd_create's error case + FD_SET(timerFd, &fds); + maxFd = MY_MAX(maxFd, timerFd); + } +#if defined(_SOC_TEMP_MONITOR_) + if (timerFd2 != -1) { // LCOV_EXCL_BR_LINE 5: timerfd_create's error case + FD_SET(timerFd2, &fds); + maxFd = MY_MAX(maxFd, timerFd2); + } +#endif // defined(_SOC_TEMP_MONITOR_) + + ret = select(maxFd + 1, &fds, NULL, NULL, NULL); + if (ret < 0) { // LCOV_EXCL_BR_LINE 5: select error case + // LCOV_EXCL_START 5: select error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if (errno != EINTR) { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "[RESM_ERR]ResMgr Handle Error"); + exit(EXIT_FAILURE); + } + continue; + // LCOV_EXCL_STOP 5: select error case + } + + if ((timerFd != -1) && FD_ISSET(timerFd, &fds)) { + read(timerFd, &exp, sizeof(uint64_t)); + /* Memory monitoring */ + if ((sec % WTC_MEM_INTERVAL) == 0) { + watchMem(); + } + /* tmpfs monitoring */ + if (!isNfs && ((sec % WTC_TMPFS_INTERVAL) == 0)) { + watchtmpfs(); + } + /* Display debug information */ + if ((sec % DEBUG_INFO_OUTPUT_FREQ) == 0) { + flagRet = resourcemanagerlog_flag_check(&mode); + if ((flagRet == eFrameworkunifiedStatusOK) && (mode == FRAMEWORKUNIFIEDLOG_FLAG_MODE_DEBUG)) { + outputResouceInfo(); + } + } + if (sec >= RESET_SEC) { + sec = 0; + } + sec++; + } +#if defined(_SOC_TEMP_MONITOR_) + if ((timerFd2 != -1) && FD_ISSET(timerFd2, &fds)) { + read(timerFd2, &exp, sizeof(uint64_t)); + soc_temp(); + } +#endif // defined(_SOC_TEMP_MONITOR_) + } + return p; +} diff --git a/resource_manager/server/src/resm.cpp b/resource_manager/server/src/resm.cpp new file mode 100644 index 00000000..189590b1 --- /dev/null +++ b/resource_manager/server/src/resm.cpp @@ -0,0 +1,2755 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include + +// NSFW +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "resmgr_srvr.h" +#include "resm_internal.h" +#include "resmgr_api.h" +#include "ss_resm_resourcemanagerlog.h" +#include "resm_cfg.h" +#include "proc_watch.h" + + +// NSFW +CFrameworkunifiedVersion g_FrameworkunifiedVersion(MAJORNO, MINORNO, REVISION); +/********************************************** + * Constant definitions + **********************************************/ +#define Resm_Flag_ID_Base EV_Flag_ID_Base(RESMGR_MID) +#define RESM_SUB_PRIORITY (0) + +// #define WTC_CPU_INTERVAL (3) + +#define CPULOAD_INVALID (-2) +#define CPULOAD_READY (-1) +#define CPULOG_TIMER_CLEAR (1) +#define CPULOG_LOGGING (0) +#define CPULOG_NO_LOGGING (-1) + +#define PROCNET_DEV_FILE "/proc/net/dev" +#define MEMINFO_FILE "/proc/meminfo" +#define PROC_STAT_FILE "/proc/stat" + +#define BYTE_TO_KIBIBYTE (1024) +#define KIBIBYTE_TO_BYTE (1024) +#define PERF_PNAME_MAX 128 // Max path name of process +#define PERF_PATH "/usr/bin/perf" +#define PERF_FILE "/tmp/perf" +#define PERF_DUMP "/tmp/perf_dump" +#define PERF_REPORT_DELAY 1 // 1 sec +#define PERF_REPORT_RETRY 3 // retry 3 times +#define CPULOAD_NICEVAL 10 // value of nice() to lower priority + +#define DEBUG_INFO_DIRPATH "/tmp/diag_analysis" +#define DEBUG_INFO_FPATH DEBUG_INFO_DIRPATH"/dispinfo_resource.dbg" +#define DEBUG_INFO_TMPPATH DEBUG_INFO_DIRPATH"/dispinfo_resource.tmp" +#define DEBUG_INFO_MEM_LETTERS (25) +#define DEBUG_INFO_CPU_TOP_LINES (10) +#define DEBUG_INFO_CMA_MIN (160000) // in KB +#define DEBUG_INFO_CMA_LETTERS (20) +#define DEBUG_INFO_DSP_PG_PATH "/usr/agl/bin/bs_analysis_dispinfo_debug" + +#define DROP_CACHES_PG_PATH "/usr/agl/bin/drop_caches" + +#define READLINE_MAX_SIZE 512 +#define READ_MAX_SIZE 4096 +#define LF (0x0A) + +/********************************************** + * Structure definitions + **********************************************/ +// App session information +typedef struct { + BOOL useFlag; + RESM_REQ_EVENT_t reqEv; // event request +} SSN_INFO_t; + +// CPU usage information +typedef struct { + char cpuname[8]; + int32_t user; + int32_t nice; + int32_t system; + int32_t idle; + int32_t iowait; + int32_t irq; + int32_t softirq; + int32_t steal; + int32_t guest; + int32_t guest_nice; +} CPU_INFO_t; + +//Context +typedef struct { + char procName[128]; + HANDLE hApp; // DispatcherHandle + int32_t nsFd; // For receiving from the NSFW + + // Session information + SSN_INFO_t ssnInfo[EV_MAX_IDS_IN_THREAD]; + + // Memory information + uint32_t restMem; // Remaining memory information + BOOL restMemFlag; + + // CMA information + uint32_t restCma; + BOOL restCmaFlag; + + + // CPU load information +// int32_t cpuloadRate; +} SVC_COMMON_t; + +// meminfo table +typedef struct { + const char* name; + uint32_t* value; +} meminfo_tbl; + +/********************************************** + * External variable definitions + **********************************************/ +// FRAMEWORKUNIFIEDLOG +FRAMEWORKUNIFIEDLOGPARAM g_FrameworkunifiedLogParams = { + FRAMEWORKUNIFIEDLOGOPTIONS, { + ZONE_TEXT_10, ZONE_TEXT_11, ZONE_TEXT_12, + ZONE_TEXT_13, ZONE_TEXT_14, ZONE_TEXT_15, + ZONE_TEXT_16, ZONE_TEXT_17, ZONE_TEXT_18, + ZONE_TEXT_19, ZONE_TEXT_20, ZONE_TEXT_21, + ZONE_TEXT_22, ZONE_TEXT_23, ZONE_TEXT_24, + ZONE_TEXT_25, ZONE_TEXT_26, ZONE_TEXT_27, + ZONE_TEXT_28, ZONE_TEXT_29, ZONE_TEXT_30, + ZONE_TEXT_31 + }, FRAMEWORKUNIFIEDLOGZONES +}; + +int isNfs; // NFS env : 1 + +static SVC_COMMON_t g_resmgr; // NOLINT (readability/nolint) +static int32_t g_sock = -1; +static uint32_t inactFile_kib; +static uint32_t mainFree_kib; +static uint32_t memTotal_kib; +static uint32_t cmaFree_kib; +static uint32_t cmaTotal_kib; +static uint32_t minRestMem; // Minimum memory available +static uint32_t minRestCma; // Minimum CMA available +static int32_t g_cpuloadRate1000; +static int g_cpu_num; +static CPU_INFO_t *g_cpuload_pre; +static CPU_INFO_t *g_cpuload; + +static int32_t g_fifo_status = STATUS_IDOL; +static int32_t g_tss_status = STATUS_IDOL; +static int32_t g_fifo_timer = 0; +static int32_t g_tss_timer = 0; + + +/********************************************** + * Local function definition + **********************************************/ +static void ctxCreate(SVC_COMMON_t* p_ctx, int32_t argc, char* argv[]); + +// Session related +static int32_t get_new_id(uint32_t* ssnId); + +// Memory monitoring +void watchMem(void); +static int32_t comp_meminfo_tbl(const void* a, const void* b); +static int32_t get_meminfo(void); + +// Network monitoring +static int32_t getInetStatus(RESM_INET_STATUS_t* p_iStatus); +static char* get_aliasName(char* name, char* line); +static int32_t get_hwaddr(char* name, char* hwaddr); + +// CPU monitoring + +static void watchCPUStatus(void); +static void watchCPU(void); +static int32_t get_cpuload(CPU_INFO_t* p_cpu); +static int32_t calc_cpuloadRate(void); +static int32_t calc_cpuloadRate_each(int num); + +// static int32_t chk_logging(int32_t cpuload, int32_t timer); +// static void logging_cpuload(void); + +static void trim_end(char* buf); + +// static void escape_percent(char* in, char* out); +static void init_cpuload(void); + +// extern void logging_cpuload_custom(void); +static void exec_perf(int32_t t_pid); +extern unsigned long logging_cpuload_custom(int32_t tmode); + + +// Debug information output +void outputResouceInfo(void); +static int write_meminfo_work(FILE *wfp); +static int write_cpuinfo_work(FILE *wfp); +static int write_cmainfo_work(FILE *wfp); +static int write_resourcemanagerloginfo_work(void); + +/******************************************************************************* + * RPC public API + *******************************************************************************/ +/* Event issuance request */ +RESM_ERR_t RESM_ReqEvent(uint32_t ssnId, const RESM_REQ_EVENT_t* p_reqEvent) { + // Argument check + if (p_reqEvent == NULL) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr ReqEvent Invalid Arg"); + return RESM_E_PAR; + } + + if (ssnId >= EV_MAX_IDS_IN_THREAD) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr ReqEvent Invalid Arg"); + return RESM_E_PAR; + } + + if (!g_resmgr.ssnInfo[ssnId].useFlag) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr ReqEvent Invalid Arg"); + return RESM_E_PAR; + } + + // Event type check + if (p_reqEvent->reqEvent == RESM_EV_MEM) { + // Record event issuance request + memcpy(&g_resmgr.ssnInfo[ssnId].reqEv, p_reqEvent, + sizeof(RESM_REQ_EVENT_t)); + } + + return RESM_E_OK; +} + +/* Get system status */ +RESM_ERR_t RESM_GetStatus(uint32_t ssnId, RESM_STATUS_t* p_status) { + int32_t ret; + + // Argument check + if (p_status == NULL) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr GetStatus Invalid Arg"); + return RESM_E_PAR; + } + + if (ssnId >= EV_MAX_IDS_IN_THREAD) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr GetStatus Invalid Arg"); + return RESM_E_PAR; + } + + if (!g_resmgr.ssnInfo[ssnId].useFlag) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr GetStatus Invalid Arg"); + return RESM_E_PAR; + } + + if (!g_resmgr.restMemFlag) { + // No remaining memory information + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr GetStatus get restmem Error"); // LCOV_EXCL_BR_LINE 15:marco defined in "native_service/ns_logger_if.h" // NOLINT[whitespace/line_length] + return RESM_E_NG; + } + p_status->restMemSize = g_resmgr.restMem; + p_status->nandWriteStatus = RESM_NAND_WRITE_ENABLE; //[]Always possible + + ret = getInetStatus(&p_status->inetStatus); + if (ret != 0) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr GetStatus getInetStatus Error"); + return RESM_E_NG; + } + + return RESM_E_OK; +} + +/******************************************************************************* + * Internal API + *******************************************************************************/ +/* Session connection */ +RESM_ERR_t RESM_SV_Open(const RESM_RSV_t* p_prim, uint32_t* p_ssnId) { + int32_t ret; + + ret = get_new_id(p_ssnId); + if (ret != 0) { + return RESM_E_NG; + } + // FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "ResMgr Open Session:ID=[%d]", *p_ssnId); + + return RESM_E_OK; +} + +/* Session disconnection */ +RESM_ERR_t RESM_SV_Close(uint32_t ssnId) { + // Argument check + if (ssnId >= EV_MAX_IDS_IN_THREAD) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr Close Invalid Arg"); + return RESM_E_PAR; + } + + if (!g_resmgr.ssnInfo[ssnId].useFlag) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr Close Invalid Arg"); + return RESM_E_PAR; + } + + // Turn off used flag + g_resmgr.ssnInfo[ssnId].useFlag = FALSE; + + // Clear event request + memset(&g_resmgr.ssnInfo[ssnId].reqEv, 0, sizeof(RESM_REQ_EVENT_t)); + + return RESM_E_OK; +} + +/* Session ID check */ +RESM_ERR_t RESM_SV_ChkSsnId(uint32_t ssnId) { + if (ssnId >= EV_MAX_IDS_IN_THREAD) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr ssnId[%d] over MAX", ssnId); + return RESM_E_NG; + } + + if (!g_resmgr.ssnInfo[ssnId].useFlag) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr ssnId[%d] is unidentified", + ssnId); + return RESM_E_NG; + } + + return RESM_E_OK; +} + +/********************************************** + * Initialization function + **********************************************/ +/* Context Initialization */ +static void ctxCreate(SVC_COMMON_t* p_ctx, int32_t argc, char* argv[]) { + EFrameworkunifiedStatus resourcemanagerRet; + FrameworkunifiedDefaultCallbackHandler cbFuncs; + FRAMEWORKUNIFIED_MAKE_DEFAULT_CALLBACK(cbFuncs); + FRAMEWORKUNIFIED_SET_ZONES(); + + memset(p_ctx, 0, sizeof(SVC_COMMON_t)); + strcpy(p_ctx->procName, SS_RESOURCE_MANAGER); // NOLINT + + // Create a Dispatcher + resourcemanagerRet = FrameworkunifiedCreateDispatcherWithoutLoop(p_ctx->procName, p_ctx->hApp, argc, + argv, &cbFuncs, TRUE); + if (resourcemanagerRet != eFrameworkunifiedStatusOK) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + // LCOV_EXCL_START 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Create Dispatcher Failed. ret[%d]", resourcemanagerRet); + exit(EXIT_FAILURE); + // LCOV_EXCL_STOP 4: NSFW error case. + } + + resourcemanagerRet = FrameworkunifiedGetDispatcherFD(p_ctx->hApp, &p_ctx->nsFd); + if (resourcemanagerRet != eFrameworkunifiedStatusOK) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + // LCOV_EXCL_START 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Get Dispatcher FD Failed. ret[%d]", resourcemanagerRet); + exit(EXIT_FAILURE); + // LCOV_EXCL_STOP 4: NSFW error case. + } + + // Initialize session + memset(p_ctx->ssnInfo, 0, sizeof(p_ctx->ssnInfo)); + + +// // Initialize CPU Information +// g_resmgr.cpuloadRate = CPULOAD_INVALID; + + + return; +} + +/********************************************** + * Get FRAMEWORKUNIFIEDLOG BasePF Flag + **********************************************/ +static EFrameworkunifiedStatus resourcemanagerlog_output_debug_info; +#define RESOURCEMANAGERLOG_BASEPF_FLAG_ID (11) + +EFrameworkunifiedStatus resourcemanagerlog_flag_check(UI_8 *mode) { + if (resourcemanagerlog_output_debug_info != eFrameworkunifiedStatusOK) + return eFrameworkunifiedStatusFail; + + return NsLogGetFrameworkunifiedLogFlag(RESOURCEMANAGERLOG_BASEPF_FLAG_ID, mode); +} + +/********************************************** + * Set DIAGCODE + **********************************************/ +void set_diag_ss_resourcemanager_err(uint16_t resourcemanager_code) { +#if 0 // TODO(Workaround to avoid build errors for customization by suppliers. Planned to fix on MK.) + SVC_COMMON_t* p_ctx = &g_resmgr; + switch (resourcemanager_code) { + case DIAGCODE_VIDEOINHALEX_OVERTEMP_3: + SS_PUTDIAG(p_ctx->hApp, DIAGCODE_VIDEOINHALEX_OVERTEMP_3); + break; + case DIAGCODE_VIDEOINHALEX_OVERTEMP_2: + SS_PUTDIAG(p_ctx->hApp, DIAGCODE_VIDEOINHALEX_OVERTEMP_2); + break; + case DIAGCODE_VIDEOINHALEX_OVERTEMP_1: + SS_PUTDIAG(p_ctx->hApp, DIAGCODE_VIDEOINHALEX_OVERTEMP_1); + break; + default: + break; + } +#endif +} + +/* drop_caches Start update Task */ +static void start_drop_caches(void) { + pid_t pid = fork(); + if (pid == 0) { + if (setuid(0) == -1) { // LCOV_EXCL_BR_LINE 5: setuid's error case + // LCOV_EXCL_START 5: setuid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to setuid(0)-1, errno=%d", errno); + // LCOV_EXCL_STOP + } else { + struct sched_param param; + // Exec drop_caches + param.sched_priority = 0; + if (sched_setscheduler(getpid(), SCHED_OTHER, ¶m) < 0) { // LCOV_EXCL_BR_LINE 5: sched_setscheduler's error case + // LCOV_EXCL_START 5: sched_setscheduler's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to sched_setscheduler errno=%d", + errno); + // LCOV_EXCL_STOP + } else { + execl(DROP_CACHES_PG_PATH, basename(DROP_CACHES_PG_PATH), NULL); + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to execl %s errno=%d", + DROP_CACHES_PG_PATH, + errno); + } + } + exit(1); + } + if (pid == (pid_t) -1) { // LCOV_EXCL_BR_LINE 5: fork's error case + // LCOV_EXCL_START 5: fork's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to fork=-1, errno=%d", errno); + // LCOV_EXCL_STOP + } +} + +static unsigned long tick_msec_get(void) { + struct timespec tp; + + if (clock_gettime(CLOCK_MONOTONIC, &tp) != 0) { + return 0; /* NG */ + } + return ((tp.tv_sec * 1000) + (tp.tv_nsec / 1000000)); +} + +#define UNITAUTH_MONITOR "/tmp/UNITAUTH_MONITOR" +#define CHECK_UNITAUTH_MONITOR_TIME (2 * 1000) // 2sec + +static void check_unitauth(void) { + int fd; + int ret; + char buf[64]; + pid_t pid_uauth; + unsigned long ctime_uauth; // NOLINT + unsigned long ctime; // NOLINT + ssize_t size; + + fd = open(UNITAUTH_MONITOR, O_RDONLY); + if (fd == -1) { + return; + } + + pid_uauth = 0; + ctime_uauth = 0; + size = read(fd, buf, sizeof(buf)); + close(fd); + if (size != -1) { // LCOV_EXCL_BR_LINE 5: read's error case + ret = sscanf(buf, "%u %lu", &pid_uauth, &ctime_uauth); + if ((ret == 0) || (ret == EOF)) { // LCOV_EXCL_BR_LINE 5: C sscanf error + // LCOV_EXCL_START 5: C sscanf error + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return; + // LCOV_EXCL_STOP + } + } + if (ctime_uauth) { // 0:ignore + ctime = tick_msec_get(); + if (ctime > ctime_uauth) { + if (((ctime - ctime_uauth) > CHECK_UNITAUTH_MONITOR_TIME) + && (getpid() != pid_uauth)) { +// print_backtrace_pid (pid_uauth); // backtrace in kernel.log + } + } + } +} + +/********************************************** + * Main Function + **********************************************/ +int32_t main(int32_t argc, char* argv[]) { + int32_t mainRet = -1; + int32_t rpcFd; + int32_t timerFd; + struct itimerspec tm; + int32_t timerFd2; + struct itimerspec tm2; + uint64_t exp; + int32_t maxFd = 0; + fd_set fds; + struct sched_param prcwParam; + pthread_t ptPRCW; + int32_t sec = 0; + int32_t ret; + + int32_t cpu_ret; + bool fork_dsp_task = false; + CL_ProcessAttr_t attr; + const char *prName; + const char *args[iProcess_MAXIMUM_NUMBER_OF_PROCESS_ARGUMENTS]; + UI_8 mode; + EFrameworkunifiedStatus eRet; + struct stat statbuf; + + RPC_ID rpcId = RESMGR_RPC_ID; + SVC_COMMON_t* p_ctx = &g_resmgr; + EFrameworkunifiedStatus resourcemanagerRet = eFrameworkunifiedStatusOK; + + { + const char* nfsenv = getenv("AGL_NFS"); + isNfs = (nfsenv && strcmp(nfsenv, "y") == 0) ? 1 : 0; + } + + /* Clear context */ + ctxCreate(p_ctx, argc, argv); + + /* Start debug information display task */ + { + char *tmp; + tmp = getenv("AGL_DEVDIAG_FLAG"); + if ((tmp == NULL) || strcmp(tmp, "ON")) { // != "ON" + resourcemanagerlog_output_debug_info = eFrameworkunifiedStatusFail; + } else { + resourcemanagerlog_output_debug_info = eFrameworkunifiedStatusOK; + } + } + eRet = resourcemanagerlog_flag_check(&mode); + if (eRet == eFrameworkunifiedStatusOK && mode == FRAMEWORKUNIFIEDLOG_FLAG_MODE_DEBUG) { + fork_dsp_task = true; + } + if (fork_dsp_task) { + // LCOV_EXCL_START 8: there is no bs_analysis_dispinfo_debug + if (0 == stat(DEBUG_INFO_DSP_PG_PATH, &statbuf)) { + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if (0 != CL_ProcessCreateAttrInit(&attr)) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "CL_ProcessCreateAttrInit Error"); // LCOV_EXCL_LINE 4: NSFW error case. + } + prName = basename(DEBUG_INFO_DSP_PG_PATH); + if (0 != CL_ProcessCreateAttrSetName(&attr, prName)) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Set Name Error"); // LCOV_EXCL_LINE 4: NSFW error case. + } + args[0] = prName; + args[1] = NULL; + if (CL_ProcessCreate(DEBUG_INFO_DSP_PG_PATH, (char* const *) args, NULL, + &attr) < 0) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "CL_ProcessCreate Error"); // LCOV_EXCL_LINE 4: NSFW error case. + } + } + // LCOV_EXCL_STOP 8: there is no bs_analysis_dispinfo_debug + } + + /* Create socket */ + g_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (g_sock < 0) { // LCOV_EXCL_BR_LINE 5: socket error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "[RESM_ERR]ResMgr Create Socket Failed"); // LCOV_EXCL_LINE 5: socket error case + } + + FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "[%s:%d] ResMgr Wakeup", p_ctx->procName, + getpid()); + + RPC_START_SERVER(rpcId); // Start RPC Server + RPC_get_fd(rpcId, &rpcFd); // Event reception FD of RPC + + /* Create proc_watch thread */ + ret = pthread_create(&ptPRCW, NULL, &PRCW_main, reinterpret_cast(NULL)); + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: pthread_create error case + // LCOV_EXCL_START 5: pthread_create error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Create Thread Failed. code[%d]", ret); + // LCOV_EXCL_STOP 5: pthread_create error case + } else { + prcwParam.sched_priority = RESM_SUB_PRIORITY; + ret = pthread_setschedparam(ptPRCW, SCHED_OTHER, &prcwParam); + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: pthread_setschedparam error case + // LCOV_EXCL_START 5: pthread_setschedparam error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Set Thread Schedparam Failed. code[%d]", ret); + // LCOV_EXCL_STOP 5: pthread_setschedparam error case + } + } + + /* Create timer */ + if ((timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC)) == -1) { // LCOV_EXCL_BR_LINE 5: timerfd_create error case // NOLINT[whitespace/line_length] + // LCOV_EXCL_START 5: timerfd_create error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Create timerFd Failed. errno[%d]", errno); + exit(EXIT_FAILURE); + // LCOV_EXCL_STOP 5: timerfd_create error case + } + // for drop_caches + { + if ((timerFd2 = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC)) == -1) { // LCOV_EXCL_BR_LINE 5: timerfd_create error case // NOLINT[whitespace/line_length] + // LCOV_EXCL_START 5: timerfd_create error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Create timerFd2 Failed. errno[%d]", errno); + exit(EXIT_FAILURE); + // LCOV_EXCL_STOP 5: timerfd_create error case + } + } + + // Initialize remaining memory acquisition + mainFree_kib = 0; + inactFile_kib = 0; + memTotal_kib = 0; + cmaFree_kib = 0; + cmaTotal_kib = 0; + get_meminfo(); + g_resmgr.restMem = mainFree_kib + inactFile_kib; + minRestMem = g_resmgr.restMem; + g_resmgr.restMemFlag = TRUE; + g_resmgr.restCma = cmaFree_kib; + minRestCma = g_resmgr.restCma; + g_resmgr.restCmaFlag = TRUE; + + tm.it_value.tv_sec = MONITORING_START_DELAT_TIME; + tm.it_value.tv_nsec = 0; + tm.it_interval.tv_sec = 1; + tm.it_interval.tv_nsec = 0; + if (timerfd_settime(timerFd, 0, &tm, NULL) == -1) { // LCOV_EXCL_BR_LINE 5: timerfd_settime error case + // LCOV_EXCL_START 5: timerfd_settime error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Set timerFd Failed. errno[%d]", errno); + exit(EXIT_FAILURE); + // LCOV_EXCL_STOP 5: timerfd_settime error case + } + + if (timerFd2 != -1) { // LCOV_EXCL_BR_LINE 200: timerFd2 can't be -1 + tm2.it_value.tv_sec = DROP_CACHES_START_DELAT_TIME; + tm2.it_value.tv_nsec = 0; + tm2.it_interval.tv_sec = 0; + tm2.it_interval.tv_nsec = 0; + if (timerfd_settime(timerFd2, 0, &tm2, NULL) == -1) { // LCOV_EXCL_BR_LINE 5: timerfd_settime error case + // LCOV_EXCL_START 5: timerfd_settime error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM_ERR]ResMgr Set timerFd2 Failed. errno[%d]", errno); + exit(EXIT_FAILURE); + // LCOV_EXCL_STOP 5: timerfd_settime error case + } + } + + /* API to Publish Service Availability Notification. */ + resourcemanagerRet = FrameworkunifiedPublishServiceAvailability(p_ctx->hApp, TRUE); + if (eFrameworkunifiedStatusOK != resourcemanagerRet) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + // LCOV_EXCL_START 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to Publish Service Availability Notification:0x%x", resourcemanagerRet); + exit(EXIT_FAILURE); + // LCOV_EXCL_STOP 4: NSFW error case. + } + + + /* CPU Load init */ + g_fifo_status = STATUS_CHECK_CPU; + g_tss_status = STATUS_CHECK_CPU; + g_cpuloadRate1000 = 0; + init_cpuload(); + cpu_ret = get_cpuload(g_cpuload); + if ( cpu_ret != 0 ) { // LCOV_EXCL_BR_LINE 200: cpu_ret must be 0 + // LCOV_EXCL_START 200: cpu_ret must be 0 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "Get cpuload Failed"); + g_cpuloadRate1000 = 0; + // LCOV_EXCL_STOP + } + + + while (1) { + FD_ZERO(&fds); + FD_SET(rpcFd, &fds); + maxFd = MY_MAX(maxFd, rpcFd); + + FD_SET(p_ctx->nsFd, &fds); + maxFd = MY_MAX(maxFd, p_ctx->nsFd); + + FD_SET(timerFd, &fds); + maxFd = MY_MAX(maxFd, timerFd); + + if (timerFd2 != -1) { + FD_SET(timerFd2, &fds); + maxFd = MY_MAX(maxFd, timerFd2); + } + ret = select(maxFd + 1, &fds, NULL, NULL, NULL); + if (ret < 0) { // LCOV_EXCL_BR_LINE 5: select error case + // LCOV_EXCL_START 5: select error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if (errno != EINTR) { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "[RESM_ERR]ResMgr Handle Error"); + exit(EXIT_FAILURE); + } + continue; + // LCOV_EXCL_STOP 5: select error case + } + /* API CALL from RPC */ + if ((timerFd2 != -1) && FD_ISSET(timerFd2, &fds)) { + start_drop_caches(); + timerFd2 = -1; + } + + /* API CALL from RPC */ + if (FD_ISSET(rpcFd, &fds)) { + RPC_process_API_request(rpcId); + } + /* Events from the NSFW */ + if (FD_ISSET(p_ctx->nsFd, &fds)) { + FrameworkunifiedDispatchProcessWithoutLoop(p_ctx->hApp); + } + + /* Timer expiration */ + if (FD_ISSET(timerFd, &fds)) { + read(timerFd, &exp, sizeof(uint64_t)); + /* CPU load monitoring */ + if ((sec % WTC_CPU_INTERVAL) == 0) { + watchCPUStatus(); + } + /* UNITAUTH monitor */ + check_unitauth(); + + if (sec >= RESET_SEC) { + sec = 0; + } + sec++; + } + } + + // Close socket + close(g_sock); + + mainRet = 0; + RPC_end(rpcId); + + return mainRet; +} + +/********************************************************************************* + * Session Related + *********************************************************************************/ +/* Numbering session ID */ +static int32_t get_new_id(uint32_t* ssnId) { + int32_t i; + SSN_INFO_t* p_ssnInfo; + + for (i = 0; i < EV_MAX_IDS_IN_THREAD; i++) { + p_ssnInfo = &g_resmgr.ssnInfo[i]; + + if (p_ssnInfo->useFlag) { + // in-use + continue; + } + *ssnId = i; + p_ssnInfo->useFlag = TRUE; + + return 0; + } + + return -1; +} + +/********************************************************************************* + * Memory monitoring + *********************************************************************************/ +/* Memory monitoring */ +void watchMem(void) { + uint32_t restMem_b; + SSN_INFO_t* p_ssnInfo; + uint32_t ssnId; + int32_t i; + int32_t ret; + + // Get remaining memory + mainFree_kib = 0; + inactFile_kib = 0; + memTotal_kib = 0; + cmaFree_kib = 0; + cmaTotal_kib = 0; + g_resmgr.restMemFlag = FALSE; + g_resmgr.restCmaFlag = FALSE; + ret = get_meminfo(); + // KiB -> Byte + // [Note] Unit of the value gotten by the meminfo is KiB + restMem_b = (mainFree_kib + inactFile_kib) * KIBIBYTE_TO_BYTE; + + if (ret != 0) { + // Failed to get remaining memory info + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr get_meminfo Failed"); + return; + } + g_resmgr.restMem = mainFree_kib + inactFile_kib; + g_resmgr.restMemFlag = TRUE; + g_resmgr.restCma = cmaFree_kib; + g_resmgr.restCmaFlag = TRUE; + + if (g_resmgr.restMem < minRestMem) { + // Update minimum available memory + minRestMem = g_resmgr.restMem; + } + if (g_resmgr.restCma < minRestCma) { + // Update minimum available CMA + minRestCma = g_resmgr.restCma; + } + + for (i = 0; i < RESM_INET_IF_MAX; i++) { + p_ssnInfo = &g_resmgr.ssnInfo[i]; + if (!p_ssnInfo->useFlag) { + // Unused sessions + continue; + } + ssnId = i; + + // Check event type + if (p_ssnInfo->reqEv.reqEvent != RESM_EV_MEM) { + // Other than memory monitoring + continue; + } + // Check free memory + if (p_ssnInfo->reqEv.prm.restMemThresh > restMem_b) { + // Issue event + ret = EV_set_flag(Resm_Flag_ID_Base + ssnId, RESM_EV_MEM); + if (ret != EV_OK) { // LCOV_EXCL_BR_LINE 200: EV_set_flag will not return ng + // LCOV_EXCL_START 200: EV_set_flag will not return ng + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr EV_set_flag Failed. ssnId[%d]", ssnId); + // LCOV_EXCL_STOP 200: EV_set_flag will not return ng + } + } + } + + return; +} + +void FlushMemInfo(void) { + FRAMEWORKUNIFIEDLOG( + ZONE_INFO, + __FUNCTION__, + "MEMORY Info(KB):REST(%d) [Memtotal(%d)] / CMA Info(KB):REST(%d) [CMAtotal(%d)]", + minRestMem, memTotal_kib, minRestCma, cmaTotal_kib); +} + +/* Compare memory information */ +static int32_t comp_meminfo_tbl(const void* data1, const void* data2) { + return strcmp(((const meminfo_tbl*) data1)->name, + ((const meminfo_tbl*) data2)->name); +} + +/* Get memory information */ +static int32_t get_meminfo(void) { + int32_t meminfo_fd = -1; + char srch_name[16]; + char buf[2048]; + meminfo_tbl target = { srch_name, NULL }; + meminfo_tbl* found; + char* head; + char* tail; + int32_t read_byte; + /* Strings must be in ascending order when adding entries to this table (for bsearch) */ + static const meminfo_tbl mem_table[] = { + { "CmaFree", &cmaFree_kib }, + { "CmaTotal", &cmaTotal_kib }, + { "Inactive(file)", &inactFile_kib }, + { "MemFree", &mainFree_kib }, + { "MemTotal", &memTotal_kib }, + }; + const int32_t mem_table_count = sizeof(mem_table) / sizeof(meminfo_tbl); + + if (meminfo_fd == -1) { + meminfo_fd = open(MEMINFO_FILE, O_RDONLY); + if (meminfo_fd == -1) { + fflush(NULL); + return -1; + } + } + + lseek(meminfo_fd, 0L, SEEK_SET); + read_byte = read(meminfo_fd, buf, sizeof buf - 1); + if (read_byte < 0) { // LCOV_EXCL_BR_LINE 200: if file exist, it will not be -1 + // LCOV_EXCL_START 200: if file exist, it will not be -1 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + fflush(NULL); + close(meminfo_fd); + return -1; + // LCOV_EXCL_STOP 200: if file exis, it will not be -1 + } + buf[read_byte] = '\0'; + + head = buf; + while (1) { + tail = strchr(head, ':'); + if (!tail) { + break; + } + + *tail = '\0'; + if (strlen(head) >= sizeof(srch_name)) { + head = tail + 1; + } else { + strcpy(srch_name, head); // NOLINT + found = reinterpret_cast(bsearch(&target, mem_table, mem_table_count, + sizeof(meminfo_tbl), comp_meminfo_tbl)); + head = tail + 1; + if (found) { + *(found->value) = strtoul(head, &tail, 10); + } + } + tail = strchr(head, '\n'); + if (!tail) + break; + head = tail + 1; + } + close(meminfo_fd); + + return 0; +} + +/********************************************************************************* + * Network monitoring + *********************************************************************************/ +/* Get system information */ +static int32_t getInetStatus(RESM_INET_STATUS_t* p_iStatus) { + FILE* fh; + char buf[READLINE_MAX_SIZE]; + char* tmp; + char name[IFNAMSIZ]; + char hwaddr[HWADDR_LEN]; + uint32_t rx_b; + uint32_t rx_pckt; + uint32_t rx_err; + uint32_t rx_drp; + uint32_t rx_fifo; + uint32_t rx_frm; + uint32_t rx_mlt; + uint32_t tx_b; + uint32_t tx_pckt; + uint32_t tx_err; + uint32_t tx_drp; + uint32_t tx_fifo; + uint32_t tx_cll; + uint32_t tx_crr; + int32_t ret; + + // Open file + fh = fopen(PROCNET_DEV_FILE, "r"); + if (fh == NULL) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr getInetStatus() File Open Error. errno[%d]", errno); + return -1; + } + + // Initialize interface count + p_iStatus->ifNum = 0; + + while (fgets(buf, sizeof(buf), fh)) { + // Get Alias name + tmp = get_aliasName(name, buf); + if (tmp == NULL) { + // No alias name + continue; + } + // Get amount of receive/transmit data + ret = sscanf(tmp, "%u%u%u%u%u%u%u%*u%u%u%u%u%u%u%u", &rx_b, &rx_pckt, + &rx_err, &rx_drp, &rx_fifo, &rx_frm, &rx_mlt, &tx_b, &tx_pckt, + &tx_err, &tx_drp, &tx_fifo, &tx_cll, &tx_crr); + if (ret != 14) { // LCOV_EXCL_BR_LINE 200: ret is always 14 + // LCOV_EXCL_START 200: ret is always 14 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr getInetStatus() GET Rx and Tx size Failed"); + continue; + // LCOV_EXCL_STOP 200: ret is always 14 + } + // Get hardware address + ret = get_hwaddr(name, hwaddr); + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: get_hwaddr will not return !0 + // LCOV_EXCL_START 5: get_hwaddr will not return !0 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr getInetStatus() GET hwaddr Failed"); + continue; + // LCOV_EXCL_STOP 5: get_hwaddr will not return !0 + } + + // Set values in the system information structure + strcpy(p_iStatus->ifInfo[p_iStatus->ifNum].name, name); // NOLINT + p_iStatus->ifInfo[p_iStatus->ifNum].rxSize = rx_b / BYTE_TO_KIBIBYTE; + p_iStatus->ifInfo[p_iStatus->ifNum].txSize = tx_b / BYTE_TO_KIBIBYTE; + memcpy(p_iStatus->ifInfo[p_iStatus->ifNum].hwaddr, hwaddr, HWADDR_LEN); + + p_iStatus->ifNum++; + + if (p_iStatus->ifNum >= RESM_INET_IF_MAX) { + break; + } + } + + // Termination processing + fclose(fh); + + if (p_iStatus->ifNum == 0) { + return -1; + } + return 0; +} + +/* Get Alias name */ +static char *get_aliasName(char* name, char* line) { + char* dot; + char* dotname; + + while (isspace(*line)) { + line++; + } + while (*line) { + if (isspace(*line)) { + *name++ = '\0'; + return NULL; + } + + if (*line == ':') { + dot = line, dotname = name; + *name++ = *line++; + + while (isdigit(*line)) { + *name++ = *line++; + } + if (*line != ':') { + line = dot; + name = dotname; + } + if (*line == '\0') { + return NULL; + } + line++; + break; + } + *name++ = *line++; + } + *name++ = '\0'; + + return line; +} + +/* Get hardware address */ +static int32_t get_hwaddr(char* name, char* hwaddr) { + struct ifreq ifr; + int32_t ret; + + if (g_sock < 0) { // LCOV_EXCL_BR_LINE 6: g_sock is not -1 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return -1; // LCOV_EXCL_LINE 6: g_sock is not -1 + } + // Initialization + memset(&ifr, 0, sizeof(ifr)); + + // Set alias name + strncpy(ifr.ifr_name, name, (sizeof(ifr.ifr_name) - 1)); + + // Get hardware address + ret = ioctl(g_sock, SIOCGIFHWADDR, &ifr); + if (ret < 0) { // LCOV_EXCL_BR_LINE 5: ioctl error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + return -1; // LCOV_EXCL_LINE 5: ioctl error case + } + memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, HWADDR_LEN); + + return 0; +} + +/********************************************************************************* + * CPU monitoring + *********************************************************************************/ +// // CPU monitoring +// static void watchCPU() { +// Main processing of CPU monitoring +static void watchCPUStatus() { + unsigned long fifo_task_occ = 0; + unsigned long tss_task_occ = 0; + int32_t fifo_status = g_fifo_status; + int32_t tss_status = g_tss_status; + int32_t cpu_load_status = CPU_TASK_INIT; + +// int32_t ret; +// static int32_t cpuLogTimer = 0; + if ((g_fifo_status == STATUS_CHECK_CPU) || (g_tss_status == STATUS_CHECK_CPU)) { + watchCPU(); + +// if (cpuLogTimer > 0) { // LCOV_EXCL_BR_LINE 6:Because the condition cannot be set +// // Make to progress the timer +// cpuLogTimer -= WTC_CPU_INTERVAL; // LCOV_EXCL_LINE 6:Because the condition cannot be set +// } + if (g_cpuloadRate1000 >= CPU_LOAD_THRESHOLD) { + FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "CPU TOTAL:(%d.%d%%)",g_cpuloadRate1000/10, g_cpuloadRate1000%10); + int i; + int32_t cpuloadRate1000; + for (i = 1; i < g_cpu_num; i++) { + char buf[16]; + cpuloadRate1000 = calc_cpuloadRate_each(i); + sprintf (buf, "%s(%d.%d%%) ", g_cpuload[i].cpuname, cpuloadRate1000/10, cpuloadRate1000%10); + FRAMEWORKUNIFIEDLOG (ZONE_INFO, __FUNCTION__, "%s", buf); + } + if (g_fifo_status == STATUS_CHECK_CPU) { // LCOV_EXCL_BR_LINE 6: g_fifo_status must be STATUS_CHECK_CPU + fifo_status = STATUS_WATCH_PROCESS; + g_fifo_timer = 0; + } + if (g_tss_status == STATUS_CHECK_CPU) { // LCOV_EXCL_BR_LINE 6: g_tss_status must be STATUS_CHECK_CPU + tss_status = STATUS_WATCH_PROCESS; + g_tss_timer = 0; + } + if ((g_fifo_status != STATUS_WATCH_PROCESS ) && ( g_tss_status != STATUS_WATCH_PROCESS)) { // LCOV_EXCL_BR_LINE 6: g_fifo_status must be STATUS_CHECK_CPU and g_tss_status must be STATUS_CHECK_CPU // NOLINT[whitespace/line_length] + logging_cpuload_custom(CPU_TASK_INIT); + } + } + } + +#if 0 + // Get CPU usage + if (g_resmgr.cpuloadRate == CPULOAD_INVALID) { + // First time + init_cpuload(); + ret = get_cpuload(g_cpuload); + if (ret == 0) { // LCOV_EXCL_BR_LINE 5: get_cpuload will not return -1 + g_resmgr.cpuloadRate = CPULOAD_READY; + } else { + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "watchCPU() Get cpuload Failed"); // LCOV_EXCL_LINE 5: get_cpuload will not return -1 // NOLINT[whitespace/line_length] + } +#endif + if ((g_fifo_status == STATUS_WATCH_PROCESS) || (g_tss_status == STATUS_WATCH_PROCESS)) { + if (g_fifo_status == STATUS_WATCH_PROCESS) { + g_fifo_timer = g_fifo_timer + WTC_CPU_INTERVAL; + if ((g_fifo_timer == WTC_CPU_INTERVAL) || (g_fifo_timer >= FIFO_TIMER_LIMIT)) { // LCOV_EXCL_BR_LINE 200: g_fifo_timer must be bigger than WTC_CPU_INTERVAL/FIFO_TIMER_LIMIT // NOLINT[whitespace/line_length] + cpu_load_status = CPU_TASK_SHOW_AF; + } else { + // LCOV_EXCL_START 200: g_fifo_timer must be bigger than WTC_CPU_INTERVAL/FIFO_TIMER_LIMIT + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + logging_cpuload_custom(FIFO_TASK_SHOW); + // LCOV_EXCL_STOP + } + } +#if 0 + return; + } else { + memcpy(g_cpuload_pre, g_cpuload, sizeof(*g_cpuload_pre)*g_cpu_num); + ret = get_cpuload(g_cpuload); + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: get_cpuload will not return -1 + // LCOV_EXCL_START 5: get_cpuload will not return -1 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "watchCPU() Get cpuload Failed"); + return; + // LCOV_EXCL_STOP 5: get_cpuload will not return -1 +#endif + if (g_tss_status == STATUS_WATCH_PROCESS) { + g_tss_timer = g_tss_timer + WTC_CPU_INTERVAL; + if ((g_tss_timer == WTC_CPU_INTERVAL) || (g_tss_timer >= TSS_TIMER_LIMIT)) { + cpu_load_status = CPU_TASK_SHOW_AF; + } else { + logging_cpuload_custom(TSS_TASK_SHOW); + } + } +#if 0 + } + // Calculate CPU usage (Notes! Return as a thousandth rate(10 times of %) + g_cpuloadRate1000 = calc_cpuloadRate(); + g_resmgr.cpuloadRate = g_cpuloadRate1000 / 10; + + ret = chk_logging(g_resmgr.cpuloadRate, cpuLogTimer); + if (ret == CPULOG_LOGGING) { + // Logging +#endif + if (cpu_load_status == CPU_TASK_SHOW_AF) { +#if 0 + int i; + int32_t cpuloadRate1000; + char *cpunames = (char *) malloc( // NOLINT + sizeof("[CpuHighLoad]") + (sizeof("cpuXX(xxx%) ") * g_cpu_num)); + cpuloadRate1000 = calc_cpuloadRate(); + sprintf(cpunames, "[CpuHighLoad]%s(%d%%) ", g_cpuload[0].cpuname, cpuloadRate1000/10); // NOLINT + for (i = 1; i < g_cpu_num; i++) { + char buf[16]; + cpuloadRate1000 = calc_cpuloadRate_each(i); + sprintf(buf, "%s(%d%%) ", g_cpuload[i].cpuname, cpuloadRate1000 / 10); // NOLINT + strcat(cpunames, buf); // NOLINT + } + free(cpunames); + FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "%s", cpunames); + } +#endif + logging_cpuload_custom(cpu_load_status); + } + if (g_fifo_status == STATUS_WATCH_PROCESS) { + fifo_task_occ = logging_cpuload_custom(CPU_FIFO_TASK_GET_OCCUPANCY); + if ((fifo_task_occ >= TASK_STAT_THRESHOLD) && (g_fifo_timer >= FIFO_TIMER_LIMIT)) { + fifo_status = STATUS_IDOL; + g_fifo_timer = 0; + exec_perf(logging_cpuload_custom(CPU_FIFO_TASK_GET_ID)); + } else if (fifo_task_occ < TASK_STAT_THRESHOLD) { + fifo_status = STATUS_CHECK_CPU; + g_fifo_timer = 0; + logging_cpuload_custom(CPU_FIFO_TASK_GET_ID); + } + } + if (g_tss_status == STATUS_WATCH_PROCESS) { + tss_task_occ = logging_cpuload_custom(CPU_TSS_TASK_GET_OCCUPANCY); + if ((tss_task_occ >= TASK_STAT_THRESHOLD) && (g_tss_timer >= TSS_TIMER_LIMIT)) { + tss_status = STATUS_IDOL; + g_tss_timer = 0; + exec_perf(logging_cpuload_custom(CPU_TSS_TASK_GET_ID)); + } else if(tss_task_occ < TASK_STAT_THRESHOLD) { + tss_status = STATUS_CHECK_CPU; + g_tss_timer = 0; + logging_cpuload_custom(CPU_TSS_TASK_GET_ID); + } + } +#if 0 + logging_cpuload_custom(); + logging_cpuload(); + // Set timer + cpuLogTimer = CPU_HIGH_LOAD_LOG_FREQ; + } else if (ret == CPULOG_TIMER_CLEAR) { + // Clear Timer + cpuLogTimer = 0; + } + + return; +#endif + logging_cpuload_custom(CPU_TASK_SHOW_BF); + } + if ((g_fifo_status == STATUS_IDOL) || (g_tss_status == STATUS_IDOL)) { + if (g_fifo_status == STATUS_IDOL) { + g_fifo_timer = g_fifo_timer + WTC_CPU_INTERVAL; + if (g_fifo_timer >= CPU_HIGH_LOAD_LOG_FREQ) { + fifo_status = STATUS_CHECK_CPU; + g_fifo_timer = 0; + } + } + if (g_tss_status == STATUS_IDOL) { + g_tss_timer = g_tss_timer + WTC_CPU_INTERVAL; + if (g_tss_timer >= CPU_HIGH_LOAD_LOG_FREQ) { + tss_status = STATUS_CHECK_CPU; + g_tss_timer = 0; + } + } + } + g_fifo_status = fifo_status; + g_tss_status = tss_status; + + return; +} + + + +// CPU monitoring +static void +watchCPU() { + int32_t ret; + + memcpy(g_cpuload_pre, g_cpuload, sizeof(*g_cpuload_pre)*g_cpu_num); + ret = get_cpuload(g_cpuload); + if ( ret != 0 ) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "watchCPU() Get cpuload Failed"); + g_cpuloadRate1000 = 0; + } else { + // Calculate CPU usage (Notes! Return as a thousandth rate(10 times of percentage) + g_cpuloadRate1000 = calc_cpuloadRate(); + } + + return; +} + + +static void init_cpuload(void) { + int fd; + char buf[READ_MAX_SIZE]; + int32_t ret; + CPU_INFO_t p_cpu; + ssize_t rsize; + char *p, *ep; + struct timespec req = { 0, 1000000 }; // 1msec + + g_cpu_num = 0; + g_cpuload_pre = NULL; + + fd = open(PROC_STAT_FILE, O_RDONLY); + if (fd == -1) { // LCOV_EXCL_BR_LINE 5: open error case + // LCOV_EXCL_START 5: open error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr File Open Error. errno[%d]", + errno); + return; + // LCOV_EXCL_STOP 5: open error case + } + rsize = read(fd, buf, sizeof(buf)); + if (rsize == -1) { // LCOV_EXCL_BR_LINE 5: read error case + // LCOV_EXCL_START 5: read error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr File Read Error. errno[%d]", + errno); + close(fd); + return; + // LCOV_EXCL_STOP 5: read error case + } + nanosleep(&req, NULL); + p = buf; + ep = buf + rsize; + while (p < ep) { + if (strncmp(p, "cpu", 3) == 0) { + ret = sscanf(p, "%8s %d %d %d %d %d %d %d %d %d %d", &p_cpu.cpuname[0], + &p_cpu.user, &p_cpu.nice, &p_cpu.system, &p_cpu.idle, + &p_cpu.iowait, &p_cpu.irq, &p_cpu.softirq, &p_cpu.steal, + &p_cpu.guest, &p_cpu.guest_nice); + if (ret < 11) { // LCOV_EXCL_BR_LINE 200: ret will always 11 + // LCOV_EXCL_START 200: ret will always 11 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr get_cpuload() File Read Error"); + close(fd); + return; + // LCOV_EXCL_STOP 200: ret will always 11 + } + g_cpu_num++; + while (++p < ep) { + if (*p == LF) { + p++; + break; + } + } + } else { + break; + } + } + close(fd); + + g_cpuload_pre = reinterpret_cast(malloc(sizeof(CPU_INFO_t) * g_cpu_num)); + g_cpuload = reinterpret_cast(malloc(sizeof(CPU_INFO_t) * g_cpu_num)); + if ((g_cpuload_pre == NULL) || (g_cpuload == NULL)) { // LCOV_EXCL_BR_LINE 5: malloc error case + // LCOV_EXCL_START 5: malloc error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr malloc Error. g_cpu_num[%d] errno[%d]", g_cpu_num, errno); + return; + // LCOV_EXCL_STOP 5: malloc error case + } + + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr cpu_num:%d", g_cpu_num); + + return; +} + +// Get CPU usage +static int32_t get_cpuload(CPU_INFO_t* p_cpu) { + int fd; + char buf[READ_MAX_SIZE]; + int32_t ret; + int i = 0; + ssize_t rsize; + char *p, *ep; + struct timespec req = { 0, 1000000 }; // 1msec + + // Open file + fd = open(PROC_STAT_FILE, O_RDONLY); + if (fd == -1) { // LCOV_EXCL_BR_LINE 5: open's error case + // LCOV_EXCL_START 5: open's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr get_cpuload() File Open Error. errno[%d]", errno); + return -1; + // LCOV_EXCL_STOP + } + rsize = read(fd, buf, sizeof(buf)); + if (rsize == -1) { // LCOV_EXCL_BR_LINE 5: read error case + // LCOV_EXCL_START 5: read error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr File Read Error. errno[%d]", + errno); + close(fd); + return -1; + // LCOV_EXCL_STOP 5: read error case + } + nanosleep(&req, NULL); + p = buf; + ep = buf + rsize; + while (p < ep) { + if (strncmp(p, "cpu", 3) == 0) { + ret = sscanf(p, "%8s %d %d %d %d %d %d %d %d %d %d", &p_cpu[i].cpuname[0], + &p_cpu[i].user, &p_cpu[i].nice, &p_cpu[i].system, + &p_cpu[i].idle, &p_cpu[i].iowait, &p_cpu[i].irq, + &p_cpu[i].softirq, &p_cpu[i].steal, &p_cpu[i].guest, + &p_cpu[i].guest_nice); + if (ret < 11) { // LCOV_EXCL_BR_LINE 200: ret will always 11 + // LCOV_EXCL_START 200: ret will always 11 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr get_cpuload() File Read Error"); + close(fd); + return -1; + // LCOV_EXCL_STOP 200: ret will always 11 + } + i++; + while (++p < ep) { + if (*p == LF) { + p++; + break; + } + } + } else { + break; + } + } + close(fd); + + return 0; +} + +// Calcurate CPU usage +static int32_t calc_cpuloadRate(void) { + int val; + int val_others; + int total; + int rate; + CPU_INFO_t* info; + CPU_INFO_t* info_pre; + + info = &g_cpuload[0]; + info_pre = &g_cpuload_pre[0]; + + val = (info->user - info_pre->user) + + (info->system - info_pre->system) + + (info->irq - info_pre->irq) + + (info->softirq - info_pre->softirq); + + val_others = (info->idle - info_pre->idle) + + (info->iowait - info_pre->iowait); + + total = val + val_others; + rate = (total > 0) ? (val*1000 / total) : 0; + + return rate; +} + +// Calcurate CPU usage for each CPU +static int32_t calc_cpuloadRate_each(int num) { + int val, valn; + int rate; + CPU_INFO_t* info; + CPU_INFO_t* info_pre; + + // cpu + info = &g_cpuload[0]; + info_pre = &g_cpuload_pre[0]; + val = (info->user - info_pre->user) + + (info->system - info_pre->system) + + (info->irq - info_pre->irq) + + (info->softirq - info_pre->softirq); + + // cpu-num + info = &g_cpuload[num]; + info_pre = &g_cpuload_pre[num]; + valn = (info->user - info_pre->user) + + (info->system - info_pre->system) + + (info->softirq - info_pre->softirq); + + rate = valn * 1000 / val; + return rate; +} + + +//// Logging check at CPU overload +//static int32_t chk_logging(int32_t cpuload, int32_t timer) { +// if (cpuload >= CPU_LOAD_THRESHOLD) { +// if (timer > 0) { +// return CPULOG_NO_LOGGING; +// } +// return CPULOG_LOGGING; +// } +// +// return CPULOG_TIMER_CLEAR; +//} + + +// Check if cmd to perf + // LCOV_EXCL_START 8: dead code +bool valid_perf_cmd(char *buf) { // LCOV_EXCL_BR_LINE 8: dead code + const char *cmd2exclude[] = { "top", "init", "bash", NULL }; + char cmdstr[64]; + + for (int i = 0;; i++) { + if (cmd2exclude[i] == NULL) { + break; + } + sprintf(cmdstr, " %s ", cmd2exclude[i]); // NOLINT + if (strstr(buf, cmdstr) == NULL) { + continue; + } else { + return false; + } + } + return true; +} + // LCOV_EXCL_STOP 8: dead code + +//// exec perf to pids +//static pid_t pids[PERF_MAX_PROCS]; + + +static bool lower_sched_priority(int niceval) { + struct sched_param sparam = { }; + sparam.sched_priority = 0; + if (sched_setscheduler(0, SCHED_OTHER, &sparam) == -1) { // LCOV_EXCL_BR_LINE 5: sched_setscheduler's error case + // LCOV_EXCL_START 5: sched_setscheduler's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed change scheduler to TSS, errno=%d", + errno); + return false; + // LCOV_EXCL_STOP + } + if (nice(niceval) == -1) { // LCOV_EXCL_BR_LINE 5: nice's error case + // LCOV_EXCL_START 5: nice's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to add nice val %d, errno=%d", + niceval, errno); + return false; + // LCOV_EXCL_STOP + } + return true; +} + +/********************************************************************************* + * exec_perf sub function RECORD perf data processing + *********************************************************************************/ +static void exec_perf_Record_Perf_Data( + pid_t* c_pids, char* perf_file, char* pidstr, int* status, + +// char pnames[PERF_MAX_PROCS][PERF_PNAME_MAX]) { + pid_t pids[PERF_MAX_PROCS]) { + + int i; + int fd; + pid_t term_pid; + int waitret; + bool do_sigkill = false; + + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "+"); + + /* RECORD perf data */ + for (i = 0; i < PERF_MAX_PROCS; i++) { + if (pids[i] <= 0) { + break; + } + sprintf(perf_file, PERF_FILE"%06d", pids[i]); // NOLINT + sprintf(pidstr, "%d", pids[i]); // NOLINT + if ((c_pids[i] = fork()) == 0) { + if (lower_sched_priority(CPULOAD_NICEVAL) == false) { // LCOV_EXCL_BR_LINE 200: lower_sched_priority() must be true + // LCOV_EXCL_START 200: lower_sched_priority() must be true + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to lower scheduler-1"); + exit(1); + // LCOV_EXCL_STOP + } + if (setuid(0) == -1) { // LCOV_EXCL_BR_LINE 5: setuid's error case + // LCOV_EXCL_START 5: setuid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to setuid(0)-1, errno=%d", + errno); + exit(1); + // LCOV_EXCL_STOP + } + // Redirect STDERR + fd = open("/dev/null", O_WRONLY); + if (fd > 0) { // LCOV_EXCL_BR_LINE 5: open's error case + dup2(fd, 2); + } + // Exec perf + execl(PERF_PATH, basename(PERF_PATH), "record", "-p", pidstr, "-o", + perf_file, NULL); + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to execl %s record, errno=%d", + PERF_PATH, + errno); + exit(1); + } + if (c_pids[i] == (pid_t) -1) { // LCOV_EXCL_BR_LINE 5: fork's error case + // LCOV_EXCL_START 5: fork's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to fork-1, errno=%d", errno); + continue; + // LCOV_EXCL_STOP + } + // Kill perf after PERF_RECORD_SPAN sec + // (Killed by child process to avoid making resm process super-user with setuid.) + if ((term_pid = fork()) == 0) { + const struct timespec delay = { PERF_RECORD_SPAN, 0 }; + if (setuid(0) == -1) { // LCOV_EXCL_BR_LINE 5: setuid's error case + // LCOV_EXCL_START 5: setuid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to setuid(0)-2, errno=%d", + errno); + exit(1); + // LCOV_EXCL_STOP + } + nanosleep(&delay, NULL); // Let perf record run for a while before kill it. + if (kill(c_pids[i], SIGINT) == -1) { // LCOV_EXCL_BR_LINE 5: kill's error case + // LCOV_EXCL_START 5: kill's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to kill(SIGINT), pid=%d, errno=%d", (int) c_pids[i], + errno); + // LCOV_EXCL_STOP + } + nanosleep(&delay, NULL); // Allow perf to do ending procedure. + exit(0); + } else if (term_pid == (pid_t) -1) { // LCOV_EXCL_BR_LINE 5: fork's error case + // LCOV_EXCL_START 5: fork's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to fork-2, errno=%d", errno); + continue; + // LCOV_EXCL_STOP + } else { + if (waitpid(term_pid, status, 0) == -1) { // LCOV_EXCL_BR_LINE 5: waitpid's error case + // LCOV_EXCL_START 5: waitpid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to waitpid of killer %d, errno=%d", term_pid, errno); + continue; + // LCOV_EXCL_STOP + } + } + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, ""); + // NOT block even if perf is not terminated + if ((waitret = waitpid(c_pids[i], status, WNOHANG)) == -1) { // LCOV_EXCL_BR_LINE 5: waitpid's error case + // LCOV_EXCL_START 5: waitpid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to waitpid of RECORD %d, errno=%d", + c_pids[i], errno); + // LCOV_EXCL_STOP + } else if (waitret == 0) { + // NOT exited + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to terminate perf record, pid=%d", + c_pids[i]); + pids[i] = -2; // Skip following sequences + do_sigkill = true; + } else if (WEXITSTATUS(*status) != 0 && WEXITSTATUS(*status) != 2) { + +// FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, +// "perf record %d exited abnormally, target=%s(%d), status=%d", +// c_pids[i], pnames[i], pids[i], WEXITSTATUS(*status)); + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "perf record %d exited abnormally, target=(%d), status=%d", + c_pids[i], pids[i], WEXITSTATUS(*status)); + + pids[i] = -2; // Skip following sequences + do_sigkill = false; + } + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, ""); + if (pids[i] == -2) { + if ((term_pid = fork()) == 0) { + const struct timespec delay = { PERF_RECORD_SPAN, 0 }; + if (setuid(0) == -1) { // LCOV_EXCL_BR_LINE 5: setuid's error case + // LCOV_EXCL_START 5: setuid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to setuid(0)-2B, errno=%d", + errno); + exit(1); + // LCOV_EXCL_STOP + } + // Kill "perf record" by SIGKILL signal + if (do_sigkill) { + int sigret = kill(c_pids[i], SIGKILL); + if (sigret == 0) { // LCOV_EXCL_BR_LINE 5: kill case + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "SIGKILL has been sent to perf record process, pid=%d", + c_pids[i]); + } else { + // LCOV_EXCL_START 5: kill case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "sending SIGKILL to perf record failed, pid=%d, errno=%d", + c_pids[i], errno); + // LCOV_EXCL_STOP 5: kill case + } + } + nanosleep(&delay, NULL); + // remove perf data file possibly made + unlink(perf_file); + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, ""); + exit(0); + } else if (term_pid == (pid_t) -1) { // LCOV_EXCL_BR_LINE 5: fork's error case + // LCOV_EXCL_START 5: fork's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to fork-2B, errno=%d", errno); + // LCOV_EXCL_STOP + } else { + if (waitpid(term_pid, status, 0) == -1) { // LCOV_EXCL_BR_LINE 5: waitpid's error case + // LCOV_EXCL_START 5: waitpid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to waitpid of killer-2 %d, errno=%d", term_pid, errno); + // LCOV_EXCL_STOP + } + if (do_sigkill) { + if ((waitret = waitpid(c_pids[i], status, WNOHANG)) == -1) { // LCOV_EXCL_BR_LINE 5: waitpid's error case + // LCOV_EXCL_START 5: waitpid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to waitpid of RECORD(2) %d, errno=%d", c_pids[i], + errno); + // LCOV_EXCL_STOP + } else if (waitret == 0) { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to terminate perf record by SIGKILL, pid=%d", + c_pids[i]); + } + } + } + } + } + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, ""); +} + +/********************************************************************************* + * exec_perf sub function make perf file available to default user processing + *********************************************************************************/ + +//static int32_t exec_perf_Make_Perf_File(pid_t* c_pids, char* perf_file) { +static int32_t exec_perf_Make_Perf_File(pid_t* c_pids, char* perf_file, pid_t pids[PERF_MAX_PROCS]) { + + int i; + + /* make perf file available to default user */ + if ((c_pids[0] = fork()) == 0) { + if (setuid(0) == -1) { // LCOV_EXCL_BR_LINE 5: setuid's error case + // LCOV_EXCL_START 5: setuid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to setuid(0)-3, errno=%d", errno); + exit(1); + // LCOV_EXCL_STOP + } + for (i = 0; i < PERF_MAX_PROCS; i++) { + if (pids[i] == -2) { + // killed by SIGKILL + continue; + } + if (pids[i] <= 0) { + break; + } + sprintf(perf_file, PERF_FILE"%06d", pids[i]); // NOLINT + if (chmod(perf_file, 0666) != 0) { // LCOV_EXCL_BR_LINE 5: chmod's error case + // LCOV_EXCL_START 5: chmod's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to chmod %s, errno=%d\n", + perf_file, errno); + // LCOV_EXCL_STOP + } + } + exit(0); + } + if (c_pids[0] == (pid_t) -1) { // LCOV_EXCL_BR_LINE 5: fork's error case + // LCOV_EXCL_START 5: fork's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to fork-3, errno=%d", errno); + return -1; + // LCOV_EXCL_STOP + } + if (waitpid(c_pids[0], NULL, 0) == -1) { // LCOV_EXCL_BR_LINE 5: waitpid's error case + // LCOV_EXCL_START 5: waitpid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to waitpid of CHMOD %d, errno=%d\n", + c_pids[0], errno); + // LCOV_EXCL_STOP + } + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, ""); + return 0; +} + +/********************************************************************************* + * exec_perf sub function REPORT perf data into dump file processing + *********************************************************************************/ +static void exec_perf_Report_Perf_Data(pid_t* c_pids, char* perf_file, + +// char* perf_dump, int* status) { + char* perf_dump, int* status, pid_t pids[PERF_MAX_PROCS]) { + + int i; + int fd; + int waitret; + + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, ""); + /* REPORT perf data into dump file */ + for (i = 0; i < PERF_MAX_PROCS; i++) { + const struct timespec delay = { PERF_REPORT_DELAY, 0 }; + if (pids[i] == -2) { + // killed by SIGKILL + continue; + } + if (pids[i] <= 0) { + break; + } + sprintf(perf_file, PERF_FILE"%06d", pids[i]); // NOLINT + sprintf(perf_dump, PERF_DUMP"%06d", pids[i]); // NOLINT + if ((c_pids[i] = fork()) == 0) { + if (lower_sched_priority(CPULOAD_NICEVAL) == false) { // LCOV_EXCL_BR_LINE 200: lower_sched_priority() will not return false + // LCOV_EXCL_START 200: lower_sched_priority() will not return false + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to lower scheduler-2"); + exit(1); + // LCOV_EXCL_STOP + } + if ((fd = open(perf_dump, (O_CREAT | O_WRONLY), 0666)) < 0) { // LCOV_EXCL_BR_LINE 5: open error case + // LCOV_EXCL_START 5: open error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to open %s, errno=%d\n", + perf_dump, errno); + // LCOV_EXCL_STOP 5: open error case + } else { + // Redirect STDOUT + dup2(fd, 1); + close(fd); + // Redirect STDERR + fd = open("/dev/null", O_WRONLY); + if (fd > 0) { // redirect stderr // LCOV_EXCL_BR_LINE 5: open's error case + dup2(fd, 2); + close(fd); + } + // Exec perf + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "execl perf report"); + execl(PERF_PATH, basename(PERF_PATH), "report", "-i", perf_file, NULL); + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to execl %s report, errno=%d", + PERF_PATH, + errno); + } + exit(1); + } + if (c_pids[i] == (pid_t) -1) { // LCOV_EXCL_BR_LINE 5: fork's error case + // LCOV_EXCL_START 5: fork's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to fork-4, errno=%d", errno); + continue; + // LCOV_EXCL_STOP + } + int ii = 0; + for (; ii < PERF_REPORT_RETRY; ii++) { + nanosleep(&delay, NULL); // Make sure waitpid() to killer returns after perf process exited. + if ((waitret = waitpid(c_pids[i], status, WNOHANG)) == -1) { // LCOV_EXCL_BR_LINE 5: waitpid's error case + // LCOV_EXCL_START 5: waitpid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to waitpid for REPORT %d, errno=%d", c_pids[i], errno); + pids[i] = -2; // Skip FRAMEWORKUNIFIEDLOG perf data + break; + // LCOV_EXCL_STOP + } else if (waitret == c_pids[i]) { + break; + } + } + if (ii >= PERF_REPORT_RETRY) { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "perf report Failed to exit, pid=%d", + c_pids[i]); + pids[i] = -2; // Skip FRAMEWORKUNIFIEDLOG perf data + } + if (pids[i] == -2) { + // Terminate perf report with SIGKILL + const struct timespec delay = { PERF_RECORD_SPAN, 0 }; + int sigret = kill(c_pids[i], SIGKILL); + if (sigret != 0) { // LCOV_EXCL_BR_LINE 5: kill's error case + // LCOV_EXCL_START 5: kill's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed in sending SIGKILL to perf report, pid=%d, errno=%d", + c_pids[i], errno); + // LCOV_EXCL_STOP + } else { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "SIGKILL has been sent to perf report process, pid=%d", + c_pids[i]); + } + nanosleep(&delay, NULL); // Make sure waitpid() to killer returns after perf process exited. + if ((waitret = waitpid(c_pids[i], status, WNOHANG)) == -1) { // LCOV_EXCL_BR_LINE 5: waitpid's error case + // LCOV_EXCL_START 5: waitpid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to waitpid of REPORT(2) %d, errno=%d", c_pids[i], errno); + // LCOV_EXCL_STOP + } else if (waitret == 0) { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to terminate perf report by SIGKILL, pid=%d", c_pids[i]); + } + // Cleanup + unlink(perf_dump); + unlink(perf_file); + } + } +} + +/********************************************************************************* + * exec_perf FRAMEWORKUNIFIEDLOG perf data processing + *********************************************************************************/ +static void exec_perf_Resourcemanagerlog_Perf_Data( + char* perf_file, char* perf_dump, + +// char pnames[PERF_MAX_PROCS][PERF_PNAME_MAX]) { + pid_t pids[PERF_MAX_PROCS]) { + + int i; + int perf_lines; + char buf[READLINE_MAX_SIZE]; + FILE *rfd; + + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, ""); + /* FRAMEWORKUNIFIEDLOG perf data */ + for (i = 0; i < PERF_MAX_PROCS; i++) { + if (pids[i] == -2) { + // killed by SIGKILL + continue; + } + if (pids[i] <= 0) { + break; + } + sprintf(perf_file, PERF_FILE"%06d", pids[i]); // NOLINT + sprintf(perf_dump, PERF_DUMP"%06d", pids[i]); // NOLINT + if ((rfd = fopen(perf_dump, "r")) == NULL) { // LCOV_EXCL_BR_LINE 5: fopen error case + // LCOV_EXCL_START 5: fopen error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to open-2 %s, errno=%d\n", + perf_dump, errno); + continue; + // LCOV_EXCL_STOP 5: fopen error case + } + perf_lines = 0; + while (fgets(buf, sizeof(buf), rfd) > 0) { + if (perf_lines >= PERF_MAX_LINES) { + break; + } + /* skip header */ + if (buf[0] == '#') { + continue; + } + if (buf[0] == '\n' || buf[0] == '\r') { + continue; + } + trim_end(buf); + if (perf_lines == 0) { + +// FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "[CpuHLPerf:%s(%d)]report by result of 'perf record -p %d'", +// pnames[i], pids[i], pids[i]); + FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "[CpuHLPerf:(%d)]report by result of 'perf record -p %d'", + pids[i], pids[i]); + + } + FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "[CpuHLPerf]%s\n", buf); + perf_lines++; + } + fclose(rfd); + // Check if no line is acquired + if (perf_lines == 0) { + +// FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "[CpuHLPerf:%s(%d)] NO_DATA_acquired", +// pnames[i], pids[i]); + FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "[CpuHLPerf:(%d)] NO_DATA_acquired", + pids[i]); + + } + // Cleanup + unlink(perf_dump); + unlink(perf_file); + } + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "-"); +} + +/********************************************************************************* + * exec_perf Main processing + *********************************************************************************/ + +//static void exec_perf(char pnames[PERF_MAX_PROCS][PERF_PNAME_MAX]) { +static void exec_perf(int32_t t_pid) { + + pid_t c_pids[PERF_MAX_PROCS]; // max process to exec perf(forked child pids) + + pid_t pids[PERF_MAX_PROCS]; + char perf_file[128]; + char perf_dump[128]; + char pidstr[64]; + struct stat statbuf; + int status; + + /* Check existance of perf exec file */ + if (stat(PERF_PATH, &statbuf) == -1 || !(statbuf.st_mode & S_IXUSR)) { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "%s is not available", PERF_PATH); + return; + } + + FRAMEWORKUNIFIEDLOG (ZONE_INFO, __FUNCTION__, "[CpuHighLoad]Please check User backtrace of following processes in kernel.log"); +// print_backtrace_pid(t_pid); + for (int i = 0; i < PERF_MAX_PROCS; i++) { + pids[i] = -1; + } + + pids[0] = t_pid; + + + /* RECORD perf data */ + +// exec_perf_Record_Perf_Data(c_pids, perf_file, pidstr, &status, pnames); + exec_perf_Record_Perf_Data(c_pids, perf_file, pidstr, &status, pids); + + + /* make perf file available to default user */ + +// if (exec_perf_Make_Perf_File(c_pids, perf_file) != 0) + if (exec_perf_Make_Perf_File(c_pids, perf_file, pids) != 0) + + return; + + /* REPORT perf data into dump file */ + +// exec_perf_Report_Perf_Data(c_pids, perf_file, perf_dump, &status); + exec_perf_Report_Perf_Data(c_pids, perf_file, perf_dump, &status, pids); + + + /* FRAMEWORKUNIFIEDLOG perf data */ + +// exec_perf_Resourcemanagerlog_Perf_Data(perf_file, perf_dump, pnames); + exec_perf_Resourcemanagerlog_Perf_Data(perf_file, perf_dump, pids); + +} + +// Logging at CPU overload +#define WAIT_RETRY 3 // 3sec + + +#if 0 +static void logging_cpuload(void) { + int32_t pipe_fd[2]; // 0:stdin,1:stdout + pid_t c_pid; + char buf[READLINE_MAX_SIZE]; + char buf2[READLINE_MAX_SIZE]; + char tmp[READLINE_MAX_SIZE]; + int32_t logLine = 0; + char* ptr; + int32_t ret; + int32_t status; + int32_t perfNum = 0; + char pnames[PERF_MAX_PROCS][PERF_PNAME_MAX] = { }; + int save_0 = -1; + int kill_flag = 1; + int waitret; + + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "+"); + + // Create pipe + ret = pipe(pipe_fd); + + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: pipe error case + // LCOV_EXCL_START 5: pipe error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr logging_cpuload() pipe Error"); + return; + // LCOV_EXCL_STOP 5: pipe error case + } + + // Create child process + c_pid = fork(); + if (c_pid < 0) { // LCOV_EXCL_BR_LINE 5: fork error case + // LCOV_EXCL_START 5: fork error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, + "ResMgr logging_cpuload() fork Error"); + close(pipe_fd[0]); + close(pipe_fd[1]); + + return; + // LCOV_EXCL_STOP 5: fork error case + } + + if (c_pid == 0) { + /******************************************************* + * Child-process + * The use of dup() and Close() between fork()-> exec() has been + * confirmed no probrem. + *******************************************************/ + if (lower_sched_priority(CPULOAD_NICEVAL) == false) { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to lower scheduler"); + exit(1); + } + close(pipe_fd[0]); // Unneeded pipes (close stdin) + + close(1); // Close stdout + dup2(pipe_fd[1], 1); // Duplicate stdout to pipe_fd[1] + close(pipe_fd[1]); + + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "execl top"); + execl("/usr/bin/top", "top", "-n", "1", "-b", NULL); + // error + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "ResMgr logging_cpuload() execl Error"); + exit(1); + } else { + close(pipe_fd[1]); // Unneeded pipes(Close stdout) + + save_0 = dup(0); + close(0); // Close stdin + dup2(pipe_fd[0], 0); // Duplicate stdin to pipe_fd[0] + close(pipe_fd[0]); + + for (int i = 0; i < PERF_MAX_PROCS; i++) { + pids[i] = -1; + } + + { + fd_set fds; + int32_t maxFd; + int ret; + struct timeval tmout = { TOP_TIMEOUT, 0 }; + + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + maxFd = STDIN_FILENO; + ret = select(maxFd + 1, &fds, NULL, NULL, &tmout); + if (ret < 0) { // LCOV_EXCL_BR_LINE 5: select error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "[RESM]Handle Error errno:%d", errno); // LCOV_EXCL_LINE 5: select error case + } else if (FD_ISSET(STDIN_FILENO, &fds)) { + kill_flag = 0; + } else { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM]'top': No response during %d seconds", TOP_TIMEOUT); + } + if (kill_flag) { + // Kill top after TOP_TIMEOUT sec + // (Killed by child process to avoid making resm process super-user with setuid.) + if (kill(c_pid, SIGKILL) == -1) { // LCOV_EXCL_BR_LINE 5: kill error case + // LCOV_EXCL_START 5: kill error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to kill(SIGKILL), pid=%d, errno=%d", (int) c_pid, + errno); + // LCOV_EXCL_STOP 5: kill error case + } + } else { + while (fgets(buf, sizeof(buf), stdin) > 0) { + // Save ProcessName and Process ID to exec perf + if (logLine >= 2 && perfNum < PERF_MAX_PROCS) { + buf2[0] = 0; + strncat(buf2, buf, sizeof(buf2) - 1); + buf2[sizeof(buf2) - 1] = 0; + if (valid_perf_cmd(buf2)) { + pids[perfNum] = atoi(buf2); + trim_end(buf2); + strncat(pnames[perfNum], rindex(buf2, ' ') + 1, + sizeof(pnames[0]) - 1); + if (pids[perfNum] >= 0 + && strnlen(pnames[perfNum], sizeof(pnames[perfNum]) - 1)) { + perfNum++; + } else { + pids[perfNum] = -1; + } + } + } + if (logLine == 0) { + if ((buf[0] != 'C') && (buf[0] != '%')) { + continue; + } + ptr = strstr(buf, "sy"); + if (ptr == NULL) { + continue; + } + while (isalpha(*ptr)) { + ptr++; + } + *ptr = '\0'; + escape_percent(buf, tmp); + FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "[CpuHighLoad]%s", tmp); + logLine++; + } else if (logLine == 1) { + ptr = strstr(buf, "PID"); + if (ptr == NULL) { + continue; + } + trim_end(buf); + escape_percent(buf, tmp); + FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "[CpuHighLoad]%s", tmp); + logLine++; + } else if (logLine < (CPU_HIGH_LOAD_P_LOG_NUM + 2)) { + trim_end(buf); + FRAMEWORKUNIFIEDLOG(ZONE_WARN, __FUNCTION__, "[CpuHighLoad]%s", buf); + logLine++; + } + } + } + } + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "wait pid(%d) kill_flag(%d)", c_pid, kill_flag); + if (kill_flag) { + const struct timespec delay = {1, 0}; + int i; + for (i = 0; i < WAIT_RETRY; i++) { + nanosleep(&delay, NULL); + if ((waitret = waitpid(c_pid, &status, WNOHANG)) == -1) { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to waitpid for top %d, errno=%d", c_pid, errno); + break; + } else if (waitret == c_pid) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "waitpid OK"); + break; + } + } + if (i >= WAIT_RETRY) { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "top Failed to exit, pid=%d", c_pid); + } + } else { + if ((waitret = waitpid(static_cast(c_pid), &status, 0)) < 0) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "waitpid(%d) Error errno(%d)", c_pid, errno); + } + } + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "waitpid(%d) returned (%d) errno(%d) status=%d", + c_pid, waitret, errno, WEXITSTATUS(*status)); + if (save_0 >= 0) { + dup2(save_0, 0); // Reset the stdin to 0 + close(save_0); + } + if (!kill_flag) { + exec_perf(pnames); + } + } + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "-"); + + return; +} +#endif + + +// Tail adjustment +static void trim_end(char* buf) { + int32_t len; + + len = strlen(buf); + while (len > 0) { + if (isspace(buf[len - 1])) { + buf[len - 1] = '\0'; + len--; + continue; + } + break; + } + + return; +} + + +#if 0 +// Escape character "%" +static void escape_percent(char* in, char* out) { + char* head; + char* tail; + + head = in; + + out[0] = '\0'; + + while (1) { + tail = strchr(head, '%'); + if (tail == NULL) { + strcat(out, head); // NOLINT + break; + } + *tail = '\0'; + + strcat(out, head); // NOLINT + strcat(out, "%%"); // NOLINT + + tail++; + head = tail; + } + + return; +} +#endif + + +/********************************************************************************* + * Output debug information display + *********************************************************************************/ +void outputResouceInfo(void) { + static bool madedir = false; + struct stat sbuf; + FILE *wfp; + + // Create directory + if (!madedir) { + if (stat(DEBUG_INFO_DIRPATH, &sbuf) != 0) { // LCOV_EXCL_BR_LINE 5: stat's error case + if (mkdir(DEBUG_INFO_DIRPATH, 0777) != 0) { // LCOV_EXCL_BR_LINE 5: mkdir's error case + // LCOV_EXCL_START 5: mkdir's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to mkdir %s, errno=%d", + DEBUG_INFO_DIRPATH, + errno); + return; + // LCOV_EXCL_STOP + } + } + madedir = true; + } + // Open files to work + if ((wfp = fopen(DEBUG_INFO_TMPPATH, "w")) == NULL) { // LCOV_EXCL_BR_LINE 5: fopen error case + // LCOV_EXCL_START 5: fopen error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to open %s, errno=%d", + DEBUG_INFO_TMPPATH, + errno); + return; + // LCOV_EXCL_STOP 5: fopen error case + } + // Output memory information work + if (write_meminfo_work(wfp) != 0) { // LCOV_EXCL_BR_LINE 6: write_meminfo_work will not be error + // LCOV_EXCL_START 6: write_meminfo_work will not be error + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to edit and output in write_meminfo_work()"); + fclose(wfp); + return; + // LCOV_EXCL_STOP 6: write_meminfo_work will not be error + } + // Get CMA MEMORY information and output working info + if (write_cmainfo_work(wfp) != 0) { // LCOV_EXCL_BR_LINE 6: write_cmainfo_work will not be error + // LCOV_EXCL_START 6: write_cmainfo_work will not be error + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to edit and output in write_cmainfo_work()"); + fclose(wfp); + return; + // LCOV_EXCL_STOP 6: write_cmainfo_work will not be error + } + // Get top information and output work info + if (write_cpuinfo_work(wfp) != 0) { // LCOV_EXCL_BR_LINE 6: write_cpuinfo_work will not be error + // LCOV_EXCL_START 6: write_cpuinfo_work will not be error + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to edit and output in write_cpuinfo_work()"); + fclose(wfp); + return; + // LCOV_EXCL_STOP 6: write_cpuinfo_work will not be error + } + fclose(wfp); + // Create output file + if (rename(DEBUG_INFO_TMPPATH, DEBUG_INFO_FPATH) != 0) { // LCOV_EXCL_BR_LINE 5:rename error case + // LCOV_EXCL_START 5:rename error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to make output file %s, errno=%d", + DEBUG_INFO_FPATH, + errno); + // LCOV_EXCL_STOP 5:rename error case + } + // Write information and output FRAMEWORKUNIFIEDLOG + if (write_resourcemanagerloginfo_work() != 0) { // LCOV_EXCL_BR_LINE 6: write_resourcemanagerloginfo_work will not be error + // LCOV_EXCL_START 6: write_resourcemanagerloginfo_work will not be error + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to output in write_resourcemanagerloginfo_work()"); + // LCOV_EXCL_STOP 6: write_resourcemanagerloginfo_work will not be error + } +} + +// Output memory information work +static int write_meminfo_work(FILE *wfp) { + float total; + float avail; + float used; + float min_remain; + uint32_t used_rate; + uint32_t used_letters; + // Output meminfo: Getting info from the proc/meminfo is performed at 5-second intervals in watchMem, so it is diverted. + avail = static_cast((mainFree_kib + inactFile_kib)); + total = static_cast(memTotal_kib); + used = total - avail; + min_remain = static_cast(minRestMem); + // "*MEMORY @@@@@@ Warning!! @@@@@" + fprintf(wfp, "*MEMORY"); + if (avail * 10 < total) { // (Less than 1/10) + fprintf(wfp, " @@@@@@ Warning!! @@@@@\n"); + } else { + fprintf(wfp, " \n"); + } + // "used/avail/total/used max xxx.xMB / xxx.xMB / xxx.xMB(xx.x%) / xxx.xMB + used /= 1024; + avail /= 1024; + total /= 1024; + min_remain /= 1024; + if (total == 0) { + used_rate = 0; + } else { + used_rate = (uint32_t) (used * 1000 / total); + if (used_rate >= 1000) { + used_rate = 999; + } + } + fprintf( + wfp, + " used/avail/total/min remain %5.1fMB / %5.1fMB / %5.1fMB(%2d.%d%%) / %5.1fMB\n", + used, avail, total, used_rate / 10, used_rate % 10, min_remain); + if (total == 0) { + used_letters = 0; + } else { + used_letters = (uint32_t) (DEBUG_INFO_MEM_LETTERS * used / total); + if (used_letters > DEBUG_INFO_MEM_LETTERS) { + used_letters = DEBUG_INFO_MEM_LETTERS; + } + } + // "------------------*******" + int i; + for (i = 0; i < static_cast(used_letters); i++) { + fprintf(wfp, "-"); + } + for (; i < DEBUG_INFO_MEM_LETTERS; i++) { + fprintf(wfp, "*"); + } + fprintf(wfp, "\n\n"); + + return 0; +} +// Get top information and Output work +static int write_cpuinfo_work(FILE *wfp) { + int32_t pipe_fd[2]; // 0:stdin,1:stdout + pid_t c_pid; + char buf[READLINE_MAX_SIZE]; + int32_t logLine = 0; + char* ptr; + int32_t ret; + int32_t status; + int save_0 = -1; + int32_t cpu_rate; + char fields[12][128]; + int kill_flag = 1; + int waitret; + + // Output CPU load + cpu_rate = g_cpuloadRate1000 < 0 ? 0 : g_cpuloadRate1000; + fprintf(wfp, "*CPU %2d.%d%%\n", cpu_rate / 10, cpu_rate % 10); + + // Create pipe + ret = pipe(pipe_fd); + + if (ret != 0) { // LCOV_EXCL_BR_LINE 5: pipe error case + // LCOV_EXCL_START 5: pipe error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "pipe Error"); + return -1; + // LCOV_EXCL_STOP 5: pipe error case + } + + // Create child process + c_pid = fork(); + if (c_pid < 0) { // LCOV_EXCL_BR_LINE 5: fork error case + // LCOV_EXCL_START 5: fork error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "fork Error"); + close(pipe_fd[0]); + close(pipe_fd[1]); + + return -1; + // LCOV_EXCL_STOP 5: fork error case + } + + if (c_pid == 0) { + /******************************************************* + * Child process + *******************************************************/ + if (lower_sched_priority(CPULOAD_NICEVAL) == false) { // LCOV_EXCL_BR_LINE 200: lower_sched_priority can't be false + // LCOV_EXCL_START 200: lower_sched_priority can't be false + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to lower scheduler"); + exit(1); + // LCOV_EXCL_STOP + } + close(pipe_fd[0]); // Unneeded pipes (close stdin) + + close(1); // Close stdout + dup2(pipe_fd[1], 1); // Duplicate stdout to pipe_fd[1] + close(pipe_fd[1]); + + execl("/usr/bin/top", "top", "-n", "1", "-b", NULL); + // error + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "execl top Error"); + exit(1); + } else { + close(pipe_fd[1]); // Unneeded pipes(Close stdout) + + save_0 = dup(0); + close(0); // Close stdin + dup2(pipe_fd[0], 0); // Duplicate stdin to pipe_fd[0] + close(pipe_fd[0]); + + { + fd_set fds; + int32_t maxFd; + int ret; + struct timeval tmout = { TOP_TIMEOUT, 0 }; + + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + maxFd = STDIN_FILENO; + ret = select(maxFd + 1, &fds, NULL, NULL, &tmout); + if (ret < 0) { // LCOV_EXCL_BR_LINE 5: select error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "[RESM]Handle Error errno:%d", errno); // LCOV_EXCL_LINE 5: select error case + } else if (FD_ISSET(STDIN_FILENO, &fds)) { // LCOV_EXCL_BR_LINE 5: FD_ISSET's error case + kill_flag = 0; + } else { + // LCOV_EXCL_START 5: FD_ISSET's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "[RESM]'top': No response during %d seconds", TOP_TIMEOUT); + // LCOV_EXCL_STOP + } + if (kill_flag) { // LCOV_EXCL_BR_LINE 200: kill_flag must be 0 + // LCOV_EXCL_START 200: kill_flag must be 0 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + // Kill top after TOP_TIMEOUT sec + // (Killed by child process to avoid making resm process super-user with setuid.) + if (kill(c_pid, SIGKILL) == -1) { + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to kill(SIGKILL), pid=%d, errno=%d", (int) c_pid, + errno); + } + // LCOV_EXCL_STOP + } else { + while (fgets(buf, sizeof(buf), stdin) > 0) { + if (logLine == 0) { + if (buf[0] != 'C') { + continue; + } + if (strstr(buf, "Cpu(s)") == NULL || strstr(buf, "sy") == NULL) { + continue; + } + logLine++; + } else if (logLine == 1) { + ptr = strstr(buf, "PID"); + if (ptr == NULL) { + continue; + } + logLine++; + } else if (logLine < (DEBUG_INFO_CPU_TOP_LINES + 2)) { + ret = sscanf(buf, "%128s %128s %128s %128s %128s %128s %128s %128s %128s %128s %128s %128s", fields[0], + fields[1], fields[2], fields[3], fields[4], fields[5], + fields[6], fields[7], fields[8], fields[9], fields[10], + fields[11]); + fprintf(wfp, "%4s%% %s\n", fields[8], fields[11]); + logLine++; + } + } + fprintf(wfp, "\n\n"); + } + } + ret = 0; + if (kill_flag) { // LCOV_EXCL_BR_LINE 200: kill_flag must be 0 + // LCOV_EXCL_START 200: kill_flag must be 0 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + const struct timespec delay = {1, 0}; + int i; + for (i = 0; i < WAIT_RETRY; i++) { + nanosleep(&delay, NULL); + if ((waitret = waitpid(c_pid, &status, WNOHANG)) == -1) { + ret = -1; + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to waitpid for top %d, errno=%d", c_pid, errno); + break; + } else if (waitret == c_pid) { + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "waitpid OK"); + break; + } + } + if (i >= WAIT_RETRY) { + ret = -1; + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "top Failed to exit, pid=%d", c_pid); + } + // LCOV_EXCL_STOP + } else { + if ((waitret = waitpid(static_cast(c_pid), &status, 0)) < 0) { // LCOV_EXCL_BR_LINE 5: waitpid's error case + // LCOV_EXCL_START 5: waitpid's error case + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + ret = -1; + FRAMEWORKUNIFIEDLOG(ZONE_RESM_DEBUG, __FUNCTION__, "waitpid(%d) Error errno(%d)", c_pid, errno); + // LCOV_EXCL_STOP + } + } + if (ret < 0) { // LCOV_EXCL_BR_LINE 200: ret must be 0 + // LCOV_EXCL_START 200: ret must be 0 + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "wait Error"); + if (save_0 >= 0) { + close(save_0); + } + return -1; + // LCOV_EXCL_STOP + } + if (save_0 >= 0) { + dup2(save_0, 0); // Reset the stdin to 0 + close(save_0); + } + } + + return 0; +} +// Get CMA information and Output work +static int write_cmainfo_work(FILE *wfp) { + float total; + float avail; + float used; + float min_remain; + uint32_t used_rate; + uint32_t used_letters; + + avail = static_cast(cmaFree_kib); + total = static_cast(cmaTotal_kib); + used = total - avail; + min_remain = static_cast(minRestCma); + // "*CMA MEMORY @@@@@@ Warning!! @@@@@" + fprintf(wfp, "*CMA MEMORY"); + if (used * 5 > total * 4) { // (4/5 Or more) + fprintf(wfp, " @@@@@@ Warning!! @@@@@\n"); + } else { + fprintf(wfp, " \n"); + } + // "used/avail/total xxx.xMB / xxx.xMB / xxx.xMB(xx.x%) + used /= 1024; + avail /= 1024; + total /= 1024; + min_remain /= 1024; + if (total != 0) { + used_rate = (uint32_t) (used * 1000 / total); + } else { + used_rate = 0; + } + if (used_rate >= 1000) { + used_rate = 999; + } + fprintf( + wfp, + " used/avail/total/min remain %5.1fMB / %5.1fMB / %5.1fMB(%2d.%d%%) / %5.1fMB\n", + used, avail, total, used_rate / 10, used_rate % 10, min_remain); + if (total == 0) { + used_letters = 0; + } else { + used_letters = (uint32_t) (DEBUG_INFO_CMA_LETTERS * used / total); + if (used_letters > DEBUG_INFO_CMA_LETTERS) { + used_letters = DEBUG_INFO_CMA_LETTERS; + } + } + // "------------------*******" + int i; + for (i = 0; i < static_cast(used_letters); i++) { + fprintf(wfp, "-"); + } + for (; i < DEBUG_INFO_CMA_LETTERS; i++) { + fprintf(wfp, "*"); + } + fprintf(wfp, "\n\n"); + + return 0; +} +// Write information and Output FRAMEWORKUNIFIEDLOG +static int write_resourcemanagerloginfo_work(void) { + FILE *wfp; + char l_read[READLINE_MAX_SIZE]; + int ret; + + wfp = fopen(DEBUG_INFO_FPATH, "r"); + if (wfp == NULL) { // LCOV_EXCL_BR_LINE 5: fopen error case + // LCOV_EXCL_START 5: fopen case error + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to open %s, errno=%d", + DEBUG_INFO_FPATH, + errno); + return -1; + // LCOV_EXCL_STOP 5: fopen case error + } + while (1) { + if (fgets(l_read, READLINE_MAX_SIZE, wfp) == NULL) { + ret = feof(wfp); + if (ret == 0) { // LCOV_EXCL_BR_LINE 5: feof case error + // LCOV_EXCL_START 5: feof case error + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_PERFORMANCE, __FUNCTION__, "Failed to fgets %s", + DEBUG_INFO_FPATH); + // LCOV_EXCL_STOP 5: feof case error + } + break; + } else { + char *line; + line = strchr(l_read, '\n'); + if (line != NULL) { + *line = '\0'; + } + if (l_read[0] != '\0') { + FRAMEWORKUNIFIEDLOG(ZONE_PERFORMANCE, __FUNCTION__, "%s", l_read); + } + } + } + fclose(wfp); + return 0; +} diff --git a/resource_manager/server/src/resourcemanager_application.cpp b/resource_manager/server/src/resourcemanager_application.cpp new file mode 100644 index 00000000..c1583c18 --- /dev/null +++ b/resource_manager/server/src/resourcemanager_application.cpp @@ -0,0 +1,155 @@ +/* + * @copyright Copyright (c) 2016-2019 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "ss_resm_resourcemanagerlog.h" +#include "system_service/resm_type.h" + +extern void FlushMemInfo(void); + +// Called at process startup +/******************************************************** + * EFrameworkunifiedStatus FrameworkunifiedOnInitialization(HANDLE hApp) + * + * System callbacks that applications should address. + ********************************************************/ +EFrameworkunifiedStatus FrameworkunifiedOnInitialization(HANDLE hApp) { + EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + + // API to Register Notification for Service Availability. + eStatus = FrameworkunifiedRegisterServiceAvailabilityNotification(hApp, NTFY_ResourceMgr_Availability); + if (eFrameworkunifiedStatusOK != eStatus) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + // LCOV_EXCL_START 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Failed to Register Service Availability Notification:%s", + NTFY_ResourceMgr_Availability); + return eStatus; + // LCOV_EXCL_STOP 4: NSFW error case. + } + // API to Publish Service Availability Notification. + eStatus = FrameworkunifiedPublishServiceAvailability(hApp, FALSE); + if (eFrameworkunifiedStatusOK != eStatus) { // LCOV_EXCL_BR_LINE 4: NSFW error case. + // LCOV_EXCL_START 4: NSFW error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, + "Failed to Publish Service Availability Notification:0x%x", eStatus); + // LCOV_EXCL_STOP 4: NSFW error case. + } + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return eStatus; +} + +// Called at process termination +/******************************************************** + * EFrameworkunifiedStatus FrameworkunifiedOnDestroy + ********************************************************/ +EFrameworkunifiedStatus FrameworkunifiedOnDestroy(HANDLE hApp) { // LCOV_EXCL_START 14 Resident process, not called by NSFW + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return eStatus; +} +// LCOV_EXCL_STOP 14 Resident process, not called by NSFW +/******************************************************** + * EFrameworkunifiedStatus FrameworkunifiedOnDebugDump + ********************************************************/ +EFrameworkunifiedStatus FrameworkunifiedOnDebugDump(HANDLE hApp) { //LCOV_EXCL_START 7:debug code + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} +//LCOV_EXCL_STOP 7:debug code +/******************************************************** + * EFrameworkunifiedStatus FrameworkunifiedOnStart(HANDLE hApp) + ********************************************************/ +EFrameworkunifiedStatus FrameworkunifiedOnStart(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} + +/******************************************************** + * EFrameworkunifiedStatus FrameworkunifiedOnStop(HANDLE hApp) + ********************************************************/ +EFrameworkunifiedStatus FrameworkunifiedOnStop(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FlushMemInfo(); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} + +/******************************************************** + * EFrameworkunifiedStatus FrameworkunifiedOnPreStart(HANDLE hApp) + ********************************************************/ +EFrameworkunifiedStatus FrameworkunifiedOnPreStart(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} + +/******************************************************** + * EFrameworkunifiedStatus FrameworkunifiedOnPreStop(HANDLE hApp) + ********************************************************/ +EFrameworkunifiedStatus FrameworkunifiedOnPreStop(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} + +/******************************************************** + * EFrameworkunifiedStatus FrameworkunifiedOnBackgroundStart(HANDLE hApp) + ********************************************************/ +EFrameworkunifiedStatus FrameworkunifiedOnBackgroundStart(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} + +/******************************************************** + * EFrameworkunifiedStatus FrameworkunifiedOnBackgroundStop(HANDLE hApp) + ********************************************************/ +EFrameworkunifiedStatus FrameworkunifiedOnBackgroundStop(HANDLE hApp) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} + +/******************************************************** + * EFrameworkunifiedStatus FrameworkunifiedCreateStateMachine(HANDLE hApp) + ********************************************************/ +EFrameworkunifiedStatus FrameworkunifiedCreateStateMachine(HANDLE hApp) { // LCOV_EXCL_START 8: not use StateMachine + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+"); + FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-"); + return l_eStatus; +} +// LCOV_EXCL_STOP 8: not use StateMachine +// EOF -- cgit 1.2.3-korg