resource-monitor: Add system-resource-monitor tool 25/279425/4 accepted/tizen/unified/20220817.153748 submit/tizen/20220812.041529 submit/tizen/20220813.034544 submit/tizen/20220817.021541
authorChanwoo Choi <cw00.choi@samsung.com>
Tue, 9 Aug 2022 04:36:30 +0000 (13:36 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Thu, 11 Aug 2022 09:47:09 +0000 (18:47 +0900)
Add system-resource-monitor cli tool to print the supported resources
and resource attributes. Also, monitor the resource attribute data.

[Example of system-resource-monitor]
-------------------------------------------------------------------------------------------------------------------------------
  :  |                            Resource Attribute Name |                 Resource Attribute Value | Unit  | Resource Attribute Description
-------------------------------------------------------------------------------------------------------------------------------
 0: 0|              RESOURCE_MONITOR_SYSTEM_ATTR_CPU_UTIL |                                     0.74 | %     | CPU average utilization
 0: 1|         RESOURCE_MONITOR_SYSTEM_ATTR_CPU_USER_UTIL |                                     0.25 | %     | CPU average utilization on user
 0: 2|          RESOURCE_MONITOR_SYSTEM_ATTR_CPU_SYS_UTIL |                                     0.50 | %     | CPU average utilization on system
 0: 3|          RESOURCE_MONITOR_SYSTEM_ATTR_PER_CPU_UTIL |                     0.99 0.99 0.99 0.00  | %     | Per-CPU utilization
 0: 4|     RESOURCE_MONITOR_SYSTEM_ATTR_PER_CPU_USER_UTIL |                     0.99 0.00 0.00 0.00  | %     | Per-CPU utilization on user
 0: 5|      RESOURCE_MONITOR_SYSTEM_ATTR_PER_CPU_SYS_UTIL |                     0.00 0.99 0.99 0.00  | %     | Per-CPU utilization on system
 0: 6|          RESOURCE_MONITOR_SYSTEM_ATTR_POSSIBLE_CPU |                                        4 | ea    | Number of possible CPU
 0: 7|            RESOURCE_MONITOR_SYSTEM_ATTR_ONLINE_CPU |                                        4 | ea    | Number of online CPU

 1: 0|                 RESOURCE_MONITOR_MEMORY_ATTR_TOTAL |                               1051213824 | kB    | Memory total size
 1: 1|             RESOURCE_MONITOR_MEMORY_ATTR_AVAILABLE |                                783130624 | kB    | Memory available size
 1: 2|                  RESOURCE_MONITOR_MEMORY_ATTR_FREE |                                545079296 | kB    | Memory free size
 1: 3|                RESOURCE_MONITOR_MEMORY_ATTR_BUFFER |                                 16211968 | kB    | Memorry buffer size
 1: 4|                RESOURCE_MONITOR_MEMORY_ATTR_CACHED |                                224661504 | kB    | Memory cached size
 1: 5|             RESOURCE_MONITOR_MEMORY_ATTR_CMA_TOTAL |                                        0 | kB    | CMA memory total size
 1: 6|              RESOURCE_MONITOR_MEMORY_ATTR_CMA_FREE |                                        0 | kB    | CMA memory free size
 1: 7|            RESOURCE_MONITOR_MEMORY_ATTR_SWAP_TOTAL |                               4294963200 | kB    | Swap memory total size
 1: 8|             RESOURCE_MONITOR_MEMORY_ATTR_SWAP_FREE |                               4294963200 | kB    | Swap memory free size

 2: 0|                 RESOURCE_MONITOR_DISPLAY_ATTR_NAME |                                      lcd |       | Display device name
 2: 1|                  RESOURCE_MONITOR_DISPLAY_ATTR_FPS |                                     0.00 | fps   | Frame per second

 3: 0|             RESOURCE_MONITOR_BATTERY_ATTR_CAPACITY |                                       50 | %     | Battery capacity
 3: 1|               RESOURCE_MONITOR_BATTERY_ATTR_STATUS |                            Not Supported |       | Battery status
 3: 2|          RESOURCE_MONITOR_BATTERY_ATTR_TEMPERATURE |                            Not Supported |       | Battery temperature
 3: 3|          RESOURCE_MONITOR_BATTERY_ATTR_VOLTAGE_NOW |                            Not Supported | uV    | Battery voltage figure
 3: 4|          RESOURCE_MONITOR_BATTERY_ATTR_CURRENT_NOW |                            Not Supported | uA    | Battery current figure
 3: 5|              RESOURCE_MONITOR_BATTERY_ATTR_PRESENT |                            Not Supported |       | Battery connected status
 3: 6|               RESOURCE_MONITOR_BATTERY_ATTR_ONLINE |                            Not Supported |       | Battery Charger connector status

 4: 0|                     RESOURCE_MONITOR_CPU_ATTR_NAME |                                     cpu0 |       | CPU cluster name
 4: 1|                 RESOURCE_MONITOR_CPU_ATTR_CUR_FREQ |                            Not Supported | kHz   | Current CPU frequency
 4: 2|                 RESOURCE_MONITOR_CPU_ATTR_MIN_FREQ |                            Not Supported | kHz   | Current CPU minimum frequency
 4: 3|                 RESOURCE_MONITOR_CPU_ATTR_MAX_FREQ |                            Not Supported | kHz   | Current CPU maximum frequency
 4: 4|       RESOURCE_MONITOR_CPU_ATTR_AVAILABLE_MIN_FREQ |                            Not Supported | kHz   | Available CPU minimum frequency
 4: 5|       RESOURCE_MONITOR_CPU_ATTR_AVAILABLE_MAX_FREQ |                            Not Supported | kHz   | Available CPU maximum frequency
 4: 6|             RESOURCE_MONITOR_CPU_ATTR_CUR_GOVERNOR |                            Not Supported |       | Current CPU frequency governor name

 5: 0|                    RESOURCE_MONITOR_DISK_ATTR_NAME |                                      vda |       | Disk device name
 5: 1|            RESOURCE_MONITOR_DISK_ATTR_READ_PER_SEC |                                     0.00 | kB/s  | Disk read per second
 5: 2|           RESOURCE_MONITOR_DISK_ATTR_WRITE_PER_SEC |                                     0.00 | kB/s  | Disk write per second
 5: 3|              RESOURCE_MONITOR_DISK_ATTR_READ_TOTAL |                                   485198 | kB    | Disk read total size
 5: 4|             RESOURCE_MONITOR_DISK_ATTR_WRITE_TOTAL |                                    24352 | kB    | Disk write total size

Change-Id: Ibf7e1f0fb380feb54b36c874a09df64ee493ea7c
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
CMakeLists.txt
packaging/capi-system-resource-monitor.spec
src/resouce-monitor.c [deleted file]
src/resource-monitor.c [new file with mode: 0644]
test/CMakeLists.txt
tools/system-resource-monitor/CMakeLists.txt [new file with mode: 0644]
tools/system-resource-monitor/system-resource-monitor.c [new file with mode: 0644]

index 2ca3a9adf68fbce0b61102e3051de30cd1f57f06..4e565af0dc9c896ff86c64b3aa1948130e482c0a 100644 (file)
@@ -81,6 +81,7 @@ CONFIGURE_FILE(
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
 
 ADD_SUBDIRECTORY(test)
+ADD_SUBDIRECTORY(tools/system-resource-monitor)
 
 IF(UNIX)
 
index 9e16ef55f578231eaf15464f93207f317485837b..687dac8543b2c7c9191395344a6fa0554544558a 100644 (file)
@@ -32,12 +32,12 @@ Group: Development/System
 Collection of files related to line coverage using gcov.
 %endif
 
-%package tool
+%package tools
 Summary:  An Resource Monitor library in Tizen Native API (Tool)
 Group:    System / Kernel
 Requires: %{name} = %{version}-%{release}
 
-%description tool
+%description tools
 An Resource Monitor library in Tizen Native API (Tool)
 
 %prep
@@ -85,9 +85,9 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj/%{name}
 %{_libdir}/pkgconfig/*.pc
 %{_libdir}/libcapi-system-resource-monitor.so
 
-%files tool
+%files tools
 %manifest %{name}.manifest
-%{_prefix}/bin/resource-monitor-test
+%{_prefix}/bin/system-resource-monitor
 
 %if 0%{?gcov:1}
 %files gcov
diff --git a/src/resouce-monitor.c b/src/resouce-monitor.c
deleted file mode 100644 (file)
index 043e3e5..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-* Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* 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 <dlog.h>
-#include "resource-monitor.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "TIZEN_N_RESOURCE_MONITOR"
-
-int resource_monitor_init(void)
-{
-       return pass_resource_monitor_init();
-}
-
-int resource_monitor_exit(int id)
-{
-       return pass_resource_monitor_exit(id);
-}
-
-int resource_monitor_get_resource_count(int id, int resource_type, int *resource_count)
-{
-       return pass_resource_monitor_get_resource_count(id, resource_type, resource_count);
-}
-
-int resource_monitor_create_resource(int id, int resource_type)
-{
-       return pass_resource_monitor_create_resource(id, resource_type);
-}
-
-int resource_monitor_delete_resource(int id, int resource_id)
-{
-       return pass_resource_monitor_delete_resource(id, resource_id);
-}
-
-int resource_monitor_set_resource_ctrl(int id, int resource_id, u_int64_t ctrl_id, int value)
-{
-       return pass_resource_monitor_set_resource_ctrl(id, resource_id, ctrl_id, value);
-}
-
-int resource_monitor_set_resource_attr(int id, int resource_id, u_int64_t attr_mask)
-{
-       return pass_resource_monitor_set_resource_attr(id, resource_id, attr_mask);
-}
-
-int resource_monitor_unset_resource_attr(int id, int resource_id, u_int64_t attr_mask)
-{
-       return pass_resource_monitor_unset_resource_attr(id, resource_id, attr_mask);
-}
-
-bool resource_monitor_is_resource_attr_supported(int id, int resource_id, u_int64_t attr_id)
-{
-       return pass_resource_monitor_is_resource_attr_supported(id, resource_id, attr_id);
-}
-
-int resource_monitor_update(int id)
-{
-       return pass_resource_monitor_update(id);
-}
-
-int resource_monitor_update_resource(int id, int resource_id)
-{
-       return resource_monitor_update_resource(id, resource_id);
-}
-
-int resource_monitor_get_value_int(int id, int resource_id, u_int64_t attr, int32_t *value)
-{
-       return pass_resource_monitor_get_value_int(id, resource_id, attr, value);
-}
-
-int resource_monitor_get_value_int64(int id, int resource_id, u_int64_t attr, int64_t *value)
-{
-       return pass_resource_monitor_get_value_int64(id, resource_id, attr, value);
-}
-
-int resource_monitor_get_value_uint(int id, int resource_id, u_int64_t attr, u_int32_t *value)
-{
-       return pass_resource_monitor_get_value_uint(id, resource_id, attr, value);
-}
-
-int resource_monitor_get_value_uint64(int id, int resource_id, u_int64_t attr, u_int64_t *value)
-{
-       return pass_resource_monitor_get_value_uint64(id, resource_id, attr, value);
-}
-
-int resource_monitor_get_value_double(int id, int resource_id, u_int64_t attr, double *value)
-{
-       return pass_resource_monitor_get_value_double(id, resource_id, attr, value);
-}
-
-int resource_monitor_get_value_string(int id, int resource_id, u_int64_t attr, char **value)
-{
-       return pass_resource_monitor_get_value_string(id, resource_id, attr, value);
-}
-
-int resource_monitor_get_array_int(int id, int res_id, u_int64_t attr, int32_t **array, int *length)
-{
-       return pass_resource_monitor_get_array_int(id, res_id, attr, array, length);
-}
-
-int resource_monitor_get_array_int64(int id, int res_id, u_int64_t attr, int64_t **array, int *length)
-{
-       return pass_resource_monitor_get_array_int64(id, res_id, attr, array, length);
-}
-
-int resource_monitor_get_array_uint(int id, int res_id, u_int64_t attr, u_int32_t **array, int *length)
-{
-       return pass_resource_monitor_get_array_uint(id, res_id, attr, array, length);
-}
-
-int resource_monitor_get_array_uint64(int id, int res_id, u_int64_t attr, u_int64_t **array, int *length)
-{
-       return pass_resource_monitor_get_array_uint64(id, res_id, attr, array, length);
-}
-
-int resource_monitor_get_array_double(int id, int res_id, u_int64_t attr, double **array, int *length)
-{
-       return pass_resource_monitor_get_array_double(id, res_id, attr, array, length);
-}
-
-int resource_monitor_get_array_string(int id, int res_id, u_int64_t attr, char ***array, int *length)
-{
-       return pass_resource_monitor_get_array_string(id, res_id, attr, array, length);
-}
diff --git a/src/resource-monitor.c b/src/resource-monitor.c
new file mode 100644 (file)
index 0000000..043e3e5
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+* Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* 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 <dlog.h>
+#include "resource-monitor.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "TIZEN_N_RESOURCE_MONITOR"
+
+int resource_monitor_init(void)
+{
+       return pass_resource_monitor_init();
+}
+
+int resource_monitor_exit(int id)
+{
+       return pass_resource_monitor_exit(id);
+}
+
+int resource_monitor_get_resource_count(int id, int resource_type, int *resource_count)
+{
+       return pass_resource_monitor_get_resource_count(id, resource_type, resource_count);
+}
+
+int resource_monitor_create_resource(int id, int resource_type)
+{
+       return pass_resource_monitor_create_resource(id, resource_type);
+}
+
+int resource_monitor_delete_resource(int id, int resource_id)
+{
+       return pass_resource_monitor_delete_resource(id, resource_id);
+}
+
+int resource_monitor_set_resource_ctrl(int id, int resource_id, u_int64_t ctrl_id, int value)
+{
+       return pass_resource_monitor_set_resource_ctrl(id, resource_id, ctrl_id, value);
+}
+
+int resource_monitor_set_resource_attr(int id, int resource_id, u_int64_t attr_mask)
+{
+       return pass_resource_monitor_set_resource_attr(id, resource_id, attr_mask);
+}
+
+int resource_monitor_unset_resource_attr(int id, int resource_id, u_int64_t attr_mask)
+{
+       return pass_resource_monitor_unset_resource_attr(id, resource_id, attr_mask);
+}
+
+bool resource_monitor_is_resource_attr_supported(int id, int resource_id, u_int64_t attr_id)
+{
+       return pass_resource_monitor_is_resource_attr_supported(id, resource_id, attr_id);
+}
+
+int resource_monitor_update(int id)
+{
+       return pass_resource_monitor_update(id);
+}
+
+int resource_monitor_update_resource(int id, int resource_id)
+{
+       return resource_monitor_update_resource(id, resource_id);
+}
+
+int resource_monitor_get_value_int(int id, int resource_id, u_int64_t attr, int32_t *value)
+{
+       return pass_resource_monitor_get_value_int(id, resource_id, attr, value);
+}
+
+int resource_monitor_get_value_int64(int id, int resource_id, u_int64_t attr, int64_t *value)
+{
+       return pass_resource_monitor_get_value_int64(id, resource_id, attr, value);
+}
+
+int resource_monitor_get_value_uint(int id, int resource_id, u_int64_t attr, u_int32_t *value)
+{
+       return pass_resource_monitor_get_value_uint(id, resource_id, attr, value);
+}
+
+int resource_monitor_get_value_uint64(int id, int resource_id, u_int64_t attr, u_int64_t *value)
+{
+       return pass_resource_monitor_get_value_uint64(id, resource_id, attr, value);
+}
+
+int resource_monitor_get_value_double(int id, int resource_id, u_int64_t attr, double *value)
+{
+       return pass_resource_monitor_get_value_double(id, resource_id, attr, value);
+}
+
+int resource_monitor_get_value_string(int id, int resource_id, u_int64_t attr, char **value)
+{
+       return pass_resource_monitor_get_value_string(id, resource_id, attr, value);
+}
+
+int resource_monitor_get_array_int(int id, int res_id, u_int64_t attr, int32_t **array, int *length)
+{
+       return pass_resource_monitor_get_array_int(id, res_id, attr, array, length);
+}
+
+int resource_monitor_get_array_int64(int id, int res_id, u_int64_t attr, int64_t **array, int *length)
+{
+       return pass_resource_monitor_get_array_int64(id, res_id, attr, array, length);
+}
+
+int resource_monitor_get_array_uint(int id, int res_id, u_int64_t attr, u_int32_t **array, int *length)
+{
+       return pass_resource_monitor_get_array_uint(id, res_id, attr, array, length);
+}
+
+int resource_monitor_get_array_uint64(int id, int res_id, u_int64_t attr, u_int64_t **array, int *length)
+{
+       return pass_resource_monitor_get_array_uint64(id, res_id, attr, array, length);
+}
+
+int resource_monitor_get_array_double(int id, int res_id, u_int64_t attr, double **array, int *length)
+{
+       return pass_resource_monitor_get_array_double(id, res_id, attr, array, length);
+}
+
+int resource_monitor_get_array_string(int id, int res_id, u_int64_t attr, char ***array, int *length)
+{
+       return pass_resource_monitor_get_array_string(id, res_id, attr, array, length);
+}
index 4d570191db2ec433c12711c0e27ac2d6afff0647..8e3340296e238cbf9202f2ce1e745f3c0f4a5b7f 100644 (file)
@@ -5,7 +5,7 @@ FOREACH(flag ${${fw_test}_CFLAGS})
     SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
 
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall -fPIE -fPIC")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall -fPIE")
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}")
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
@@ -17,5 +17,3 @@ FOREACH(src ${sources})
     ADD_EXECUTABLE(${src_name} ${src})
     TARGET_LINK_LIBRARIES(${src_name} ${fw_name} ${${fw_test}_LDFLAGS} -lm -pthread)
 ENDFOREACH()
-
-INSTALL(TARGETS resource-monitor-test DESTINATION bin)
diff --git a/tools/system-resource-monitor/CMakeLists.txt b/tools/system-resource-monitor/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ab8deb8
--- /dev/null
@@ -0,0 +1,28 @@
+PROJECT(capi-system-resource-monitor C CXX)
+
+SET(SRCS ${CMAKE_SOURCE_DIR}/src/resource-monitor.c)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(tools_pkgs REQUIRED
+       libpass-resource-monitor
+)
+
+FOREACH(flag ${tools_pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall -fPIE")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
+
+SET(src ${CMAKE_SOURCE_DIR}/tools/system-resource-monitor/system-resource-monitor.c)
+GET_FILENAME_COMPONENT(src_name ${src} NAME_WE)
+MESSAGE("${src_name}")
+ADD_EXECUTABLE(${src_name} ${SRCS} ${src})
+TARGET_LINK_LIBRARIES(${src_name} ${tools_LDFLAGS} ${tools_pkgs_LDFLAGS} -ldl -L${LIBDIR}/hal)
+INSTALL(TARGETS ${src_name} DESTINATION /usr/bin/)
diff --git a/tools/system-resource-monitor/system-resource-monitor.c b/tools/system-resource-monitor/system-resource-monitor.c
new file mode 100644 (file)
index 0000000..bed0b96
--- /dev/null
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * 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 <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include "resource-monitor.h"
+
+#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
+
+#define BUFF_MAX       255
+#define MAX_RESOURCE   100
+#define MAX_ATTR       64
+
+/*
+ * FIXME: Never change the following enumeration
+ *        because they should be defined on resource-monior daemon
+ *        and then are used on here. Define them with the same value
+ *        for testing.
+ */
+enum resource_data_type {
+       DATA_TYPE_UNKNOWN = 0,
+       DATA_TYPE_INT,
+       DATA_TYPE_INT64,
+       DATA_TYPE_UINT,
+       DATA_TYPE_UINT64,
+       DATA_TYPE_DOUBLE,
+       DATA_TYPE_STRING,
+       DATA_TYPE_ARRAY,
+       DATA_TYPE_PTR,
+       DATA_TYPE_BOOLEAN,
+       DATA_TYPE_NUM
+};
+
+struct resource_attr_data {
+       const u_int64_t id;
+       const int type;
+       const int array_type;
+       const char *name;
+       const char *unit;
+       const char *desc;
+
+       u_int32_t value_uint32;
+       u_int64_t value_uint64;
+       int32_t value_int32;
+       int64_t value_int64;
+       double value_double;
+       char *value_string;
+};
+
+static struct resource_attr_data cpu_attrs[] = {
+       { .id = RESOURCE_MONITOR_CPU_ATTR_NAME,                         .type = DATA_TYPE_STRING,       .name = "RESOURCE_MONITOR_CPU_ATTR_NAME",                       .unit = "",             .desc = "CPU cluster name", },
+       { .id = RESOURCE_MONITOR_CPU_ATTR_CUR_FREQ,                     .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_CPU_ATTR_CUR_FREQ",                   .unit = "kHz",          .desc = "Current CPU frequency", },
+       { .id = RESOURCE_MONITOR_CPU_ATTR_MIN_FREQ,                     .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_CPU_ATTR_MIN_FREQ",                   .unit = "kHz",          .desc = "Current CPU minimum frequency", },
+       { .id = RESOURCE_MONITOR_CPU_ATTR_MAX_FREQ,                     .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_CPU_ATTR_MAX_FREQ",                   .unit = "kHz",          .desc = "Current CPU maximum frequency", },
+       { .id = RESOURCE_MONITOR_CPU_ATTR_AVAILABLE_MIN_FREQ,           .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_CPU_ATTR_AVAILABLE_MIN_FREQ",         .unit = "kHz",          .desc = "Available CPU minimum frequency", },
+       { .id = RESOURCE_MONITOR_CPU_ATTR_AVAILABLE_MAX_FREQ,           .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_CPU_ATTR_AVAILABLE_MAX_FREQ",         .unit = "kHz",          .desc = "Available CPU maximum frequency", },
+       { .id = RESOURCE_MONITOR_CPU_ATTR_CUR_GOVERNOR,                 .type = DATA_TYPE_STRING,       .name = "RESOURCE_MONITOR_CPU_ATTR_CUR_GOVERNOR",               .unit = "",             .desc = "Current CPU frequency governor name", },
+};
+
+static struct resource_attr_data bus_attrs[] = {
+       { .id = RESOURCE_MONITOR_BUS_ATTR_NAME,                         .type = DATA_TYPE_STRING,       .name = "RESOURCE_MONITOR_BUS_ATTR_NAME",                       .unit = "",             .desc = "Bus device name", },
+       { .id = RESOURCE_MONITOR_BUS_ATTR_CUR_FREQ,                     .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BUS_ATTR_CUR_FREQ",                   .unit = "kHz",          .desc = "Current bus frequency", },
+       { .id = RESOURCE_MONITOR_BUS_ATTR_MIN_FREQ,                     .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BUS_ATTR_MIN_FREQ",                   .unit = "kHz",          .desc = "Current bus minimum frequency", },
+       { .id = RESOURCE_MONITOR_BUS_ATTR_MAX_FREQ,                     .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BUS_ATTR_MAX_FREQ",                   .unit = "kHz",          .desc = "Current bus maximum frequency", },
+       { .id = RESOURCE_MONITOR_BUS_ATTR_AVAILABLE_MIN_FREQ,           .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BUS_ATTR_AVAILABLE_MIN_FREQ",         .unit = "kHz",          .desc = "Available bus minimum frequency", },
+       { .id = RESOURCE_MONITOR_BUS_ATTR_AVAILABLE_MAX_FREQ,           .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BUS_ATTR_AVAILABLE_MAX_FREQ",         .unit = "kHz",          .desc = "Available bus maximum frequency", },
+       { .id = RESOURCE_MONITOR_BUS_ATTR_CUR_GOVERNOR,                 .type = DATA_TYPE_STRING,       .name = "RESOURCE_MONITOR_BUS_ATTR_CUR_GOVERNOR",               .unit = "",             .desc = "Current bus frequency governor name", },
+};
+
+static struct resource_attr_data gpu_attrs[] = {
+       { .id = RESOURCE_MONITOR_GPU_ATTR_NAME,                         .type = DATA_TYPE_STRING,       .name = "RESOURCE_MONITOR_GPU_ATTR_NAME",                       .unit = "",             .desc = "GPU device name", },
+       { .id = RESOURCE_MONITOR_GPU_ATTR_CUR_FREQ,                     .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_GPU_ATTR_CUR_FREQ",                   .unit = "kHz",          .desc = "Current GPU frequency", },
+       { .id = RESOURCE_MONITOR_GPU_ATTR_MIN_FREQ,                     .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_GPU_ATTR_MIN_FREQ",                   .unit = "kHz",          .desc = "Current GPU minimum frequency", },
+       { .id = RESOURCE_MONITOR_GPU_ATTR_MAX_FREQ,                     .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_GPU_ATTR_MAX_FREQ",                   .unit = "kHz",          .desc = "Current GPU maximum frequency", },
+       { .id = RESOURCE_MONITOR_GPU_ATTR_AVAILABLE_MIN_FREQ,           .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_GPU_ATTR_AVAILABLE_MIN_FREQ",         .unit = "kHz",          .desc = "Available GPU minimum frequency", },
+       { .id = RESOURCE_MONITOR_GPU_ATTR_AVAILABLE_MAX_FREQ,           .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_GPU_ATTR_AVAILABLE_MAX_FREQ",         .unit = "kHz",          .desc = "Available GPU maximum frequency", },
+       { .id = RESOURCE_MONITOR_GPU_ATTR_CUR_GOVERNOR,                 .type = DATA_TYPE_STRING,       .name = "RESOURCE_MONITOR_GPU_ATTR_CUR_GOVERNOR",               .unit = "",             .desc = "Current GPU frequency governor name", },
+};
+
+static struct resource_attr_data memory_attrs[] = {
+       { .id = RESOURCE_MONITOR_MEMORY_ATTR_TOTAL,                     .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_MEMORY_ATTR_TOTAL",                   .unit = "kB",           .desc = "Memory total size", },
+       { .id = RESOURCE_MONITOR_MEMORY_ATTR_AVAILABLE,                 .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_MEMORY_ATTR_AVAILABLE",               .unit = "kB",           .desc = "Memory available size", },
+       { .id = RESOURCE_MONITOR_MEMORY_ATTR_FREE,                      .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_MEMORY_ATTR_FREE",                    .unit = "kB",           .desc = "Memory free size", },
+       { .id = RESOURCE_MONITOR_MEMORY_ATTR_BUFFER,                    .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_MEMORY_ATTR_BUFFER",                  .unit = "kB",           .desc = "Memorry buffer size", },
+       { .id = RESOURCE_MONITOR_MEMORY_ATTR_CACHED,                    .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_MEMORY_ATTR_CACHED",                  .unit = "kB",           .desc = "Memory cached size", },
+       { .id = RESOURCE_MONITOR_MEMORY_ATTR_CMA_TOTAL,                 .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_MEMORY_ATTR_CMA_TOTAL",               .unit = "kB",           .desc = "CMA memory total size", },
+       { .id = RESOURCE_MONITOR_MEMORY_ATTR_CMA_FREE,                  .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_MEMORY_ATTR_CMA_FREE",                .unit = "kB",           .desc = "CMA memory free size", },
+       { .id = RESOURCE_MONITOR_MEMORY_ATTR_SWAP_TOTAL,                .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_MEMORY_ATTR_SWAP_TOTAL",              .unit = "kB",           .desc = "Swap memory total size", },
+       { .id = RESOURCE_MONITOR_MEMORY_ATTR_SWAP_FREE,                 .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_MEMORY_ATTR_SWAP_FREE",               .unit = "kB",           .desc = "Swap memory free size", },
+};
+
+static struct resource_attr_data battery_attrs[] = {
+       { .id = RESOURCE_MONITOR_BATTERY_ATTR_CAPACITY,                 .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BATTERY_ATTR_CAPACITY",               .unit = "%",            .desc = "Battery capacity", },
+       { .id = RESOURCE_MONITOR_BATTERY_ATTR_STATUS,                   .type = DATA_TYPE_STRING,       .name = "RESOURCE_MONITOR_BATTERY_ATTR_STATUS",                 .unit = "",             .desc = "Battery status", },
+       { .id = RESOURCE_MONITOR_BATTERY_ATTR_TEMPERATURE,              .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BATTERY_ATTR_TEMPERATURE",            .unit = "",             .desc = "Battery temperature", },
+       { .id = RESOURCE_MONITOR_BATTERY_ATTR_VOLTAGE_NOW,              .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BATTERY_ATTR_VOLTAGE_NOW",            .unit = "uV",           .desc = "Battery voltage figure", },
+       { .id = RESOURCE_MONITOR_BATTERY_ATTR_CURRENT_NOW,              .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BATTERY_ATTR_CURRENT_NOW",            .unit = "uA",           .desc = "Battery current figure", },
+       { .id = RESOURCE_MONITOR_BATTERY_ATTR_PRESENT,                  .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BATTERY_ATTR_PRESENT",                .unit = "",             .desc = "Battery connected status", },
+       { .id = RESOURCE_MONITOR_BATTERY_ATTR_ONLINE,                   .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_BATTERY_ATTR_ONLINE",                 .unit = "",             .desc = "Battery Charger connector status", },
+};
+
+static struct resource_attr_data display_attrs[] = {
+       { .id = RESOURCE_MONITOR_DISPLAY_ATTR_NAME,                     .type = DATA_TYPE_STRING,       .name = "RESOURCE_MONITOR_DISPLAY_ATTR_NAME",                   .unit = "",             .desc = "Display device name", },
+       { .id = RESOURCE_MONITOR_DISPLAY_ATTR_FPS,                      .type = DATA_TYPE_DOUBLE,       .name = "RESOURCE_MONITOR_DISPLAY_ATTR_FPS",                    .unit = "fps",          .desc = "Frame per second", },
+};
+
+static struct resource_attr_data system_attrs[] = {
+       { .id = RESOURCE_MONITOR_SYSTEM_ATTR_CPU_UTIL,                  .type = DATA_TYPE_DOUBLE,       .name = "RESOURCE_MONITOR_SYSTEM_ATTR_CPU_UTIL",                .unit = "%",            .desc = "CPU average utilization", },
+       { .id = RESOURCE_MONITOR_SYSTEM_ATTR_CPU_USER_UTIL,             .type = DATA_TYPE_DOUBLE,       .name = "RESOURCE_MONITOR_SYSTEM_ATTR_CPU_USER_UTIL",           .unit = "%",            .desc = "CPU average utilization on user", },
+       { .id = RESOURCE_MONITOR_SYSTEM_ATTR_CPU_SYS_UTIL,              .type = DATA_TYPE_DOUBLE,       .name = "RESOURCE_MONITOR_SYSTEM_ATTR_CPU_SYS_UTIL",            .unit = "%",            .desc = "CPU average utilization on system", },
+       { .id = RESOURCE_MONITOR_SYSTEM_ATTR_PER_CPU_UTIL,              .type = DATA_TYPE_ARRAY,        .name = "RESOURCE_MONITOR_SYSTEM_ATTR_PER_CPU_UTIL",            .unit = "%",            .desc = "Per-CPU utilization",                  .array_type = DATA_TYPE_DOUBLE, },
+       { .id = RESOURCE_MONITOR_SYSTEM_ATTR_PER_CPU_USER_UTIL,         .type = DATA_TYPE_ARRAY,        .name = "RESOURCE_MONITOR_SYSTEM_ATTR_PER_CPU_USER_UTIL",       .unit = "%",            .desc = "Per-CPU utilization on user",          .array_type = DATA_TYPE_DOUBLE, },
+       { .id = RESOURCE_MONITOR_SYSTEM_ATTR_PER_CPU_SYS_UTIL,          .type = DATA_TYPE_ARRAY,        .name = "RESOURCE_MONITOR_SYSTEM_ATTR_PER_CPU_SYS_UTIL",        .unit = "%",            .desc = "Per-CPU utilization on system",        .array_type = DATA_TYPE_DOUBLE, },
+       { .id = RESOURCE_MONITOR_SYSTEM_ATTR_POSSIBLE_CPU,              .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_SYSTEM_ATTR_POSSIBLE_CPU",            .unit = "ea",           .desc = "Number of possible CPU", },
+       { .id = RESOURCE_MONITOR_SYSTEM_ATTR_ONLINE_CPU,                .type = DATA_TYPE_INT,          .name = "RESOURCE_MONITOR_SYSTEM_ATTR_ONLINE_CPU",              .unit = "ea",           .desc = "Number of online CPU", },
+};
+
+struct resource_attr_data disk_attrs[] = {
+       { .id = RESOURCE_MONITOR_DISK_ATTR_NAME,                        .type = DATA_TYPE_STRING,       .name = "RESOURCE_MONITOR_DISK_ATTR_NAME",                      .unit = "",             .desc = "Disk device name", },
+       { .id = RESOURCE_MONITOR_DISK_ATTR_READ_PER_SEC,                .type = DATA_TYPE_DOUBLE,       .name = "RESOURCE_MONITOR_DISK_ATTR_READ_PER_SEC",              .unit = "kB/s",         .desc = "Disk read per second", },
+       { .id = RESOURCE_MONITOR_DISK_ATTR_WRITE_PER_SEC,               .type = DATA_TYPE_DOUBLE,       .name = "RESOURCE_MONITOR_DISK_ATTR_WRITE_PER_SEC",             .unit = "kB/s",         .desc = "Disk write per second", },
+       { .id = RESOURCE_MONITOR_DISK_ATTR_READ_TOTAL,                  .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_DISK_ATTR_READ_TOTAL",                .unit = "kB",           .desc = "Disk read total size", },
+       { .id = RESOURCE_MONITOR_DISK_ATTR_WRITE_TOTAL,                 .type = DATA_TYPE_UINT64,       .name = "RESOURCE_MONITOR_DISK_ATTR_WRITE_TOTAL",               .unit = "kB",           .desc = "Disk write total size", },
+};
+
+struct resource_data {
+       int mon_id;
+       int res_index;
+       int res_id;
+       u_int64_t mask;
+
+       /* Copy data from g_resource_type */
+       int type;
+       u_int64_t ctrl_id;
+       int ctrl_val;
+       int num_attrs;
+       struct resource_attr_data attrs[MAX_ATTR];
+};
+
+struct resource_monitor_data {
+       unsigned int secs;
+       unsigned int max;
+
+       int mon_id;
+       int num_res;
+       struct resource_data res[MAX_RESOURCE];
+} g_data;
+
+struct __resource_type {
+       int type;
+       u_int64_t ctrl_id;
+       int ctrl_val;
+       int num_attrs;
+       struct resource_attr_data *attrs;
+
+       int res_count;
+} g_resource_type[] = {
+       {
+               .type           = RESOURCE_MONITOR_TYPE_SYSTEM,
+               .ctrl_id        = 0,
+               .attrs          = system_attrs,
+               .num_attrs      = ARRAY_SIZE(system_attrs),
+       }, {
+               .type           = RESOURCE_MONITOR_TYPE_MEMORY,
+               .ctrl_id        = 0,
+               .attrs          = memory_attrs,
+               .num_attrs      = ARRAY_SIZE(memory_attrs),
+       }, {
+               .type           = RESOURCE_MONITOR_TYPE_DISPLAY,
+               .ctrl_id        = RESOURCE_MONITOR_DISPLAY_CTRL_DEVICE_ID,
+               .attrs          = display_attrs,
+               .num_attrs      = ARRAY_SIZE(display_attrs),
+       }, {
+               .type           = RESOURCE_MONITOR_TYPE_BATTERY,
+               .ctrl_id        = 0,
+               .attrs          = battery_attrs,
+               .num_attrs      = ARRAY_SIZE(battery_attrs),
+       }, {
+               .type           = RESOURCE_MONITOR_TYPE_CPU,
+               .ctrl_id        = RESOURCE_MONITOR_CPU_CTRL_CLUSTER_ID,
+               .attrs          = cpu_attrs,
+               .num_attrs      = ARRAY_SIZE(cpu_attrs),
+       }, {
+               .type           = RESOURCE_MONITOR_TYPE_BUS,
+               .ctrl_id        = RESOURCE_MONITOR_BUS_CTRL_DEVICE_ID,
+               .attrs          = bus_attrs,
+               .num_attrs      = ARRAY_SIZE(bus_attrs),
+       }, {
+               .type           = RESOURCE_MONITOR_TYPE_GPU,
+               .ctrl_id        = RESOURCE_MONITOR_GPU_CTRL_DEVICE_ID,
+               .attrs          = gpu_attrs,
+               .num_attrs      = ARRAY_SIZE(gpu_attrs),
+       }, {
+               .type           = RESOURCE_MONITOR_TYPE_DISK,
+               .ctrl_id        = RESOURCE_MONITOR_DISK_CTRL_DEVICE_ID,
+               .attrs          = disk_attrs,
+               .num_attrs      = ARRAY_SIZE(disk_attrs),
+       },
+};
+
+static inline void create_resource_and_set_attrs(struct resource_data *res, int ctrl_val)
+{
+       int i;
+
+       if (!res)
+               return;
+
+       res->res_id = resource_monitor_create_resource(res->mon_id, res->type);
+
+       if (res->ctrl_id)
+               resource_monitor_set_resource_ctrl(
+                               res->mon_id, res->res_id, res->ctrl_id, ctrl_val);
+
+       for (i = 0; i < res->num_attrs; i++) {
+               if (resource_monitor_is_resource_attr_supported(
+                               res->mon_id, res->res_id, res->attrs[i].id))
+                       res->mask |= res->attrs[i].id;
+       }
+
+       resource_monitor_set_resource_attr(res->mon_id, res->res_id, res->mask);
+}
+
+static inline void unset_attrs_and_delete_resource(struct resource_data *res)
+{
+       if (!res)
+               return;
+
+       resource_monitor_unset_resource_attr(res->mon_id, res->res_id, res->mask);
+       resource_monitor_delete_resource(res->mon_id, res->res_id);
+}
+
+static inline int get_resource_attr_array_value(struct resource_data *res, int idx)
+{
+       int i;
+       int ret = 0;
+       int length;
+       double *array = NULL;
+       char buf[BUFF_MAX];
+       char temp[10];
+
+       if (!res)
+               return -1;
+
+       switch (res->attrs[idx].array_type) {
+       case DATA_TYPE_DOUBLE:
+               ret = resource_monitor_get_array_double(
+                               res->mon_id, res->res_id,
+                               res->attrs[idx].id, &array, &length);
+
+               if (ret < 0) break;
+
+               memset(buf, 0, BUFF_MAX);
+               for (i = 0; i < length; i++) {
+                       snprintf(temp, 10, "%2.2f ", array[i]);
+                       strcat(buf, temp);
+               }
+
+               printf("%40s | %-5s | %s", buf, res->attrs[idx].unit, res->attrs[idx].desc);
+
+               free(array);
+               break;
+       case DATA_TYPE_INT:
+       case DATA_TYPE_INT64:
+       case DATA_TYPE_UINT:
+       case DATA_TYPE_UINT64:
+       case DATA_TYPE_STRING:
+               printf("%40s | %-5s | %s", "Not Implemented",
+                               res->attrs[idx].unit, res->attrs[idx].desc);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static inline void get_resource_attr_value(struct resource_data *res, int i)
+{
+       bool supported;
+       int ret = 0;
+
+       supported = resource_monitor_is_resource_attr_supported(
+                                               res->mon_id, res->res_id,
+                                               res->attrs[i].id);
+       if (!supported) {
+               printf("%40s | %-5s | %s", "Not Supported",
+                               res->attrs[i].unit, res->attrs[i].desc);
+               return;
+       }
+
+       switch (res->attrs[i].type) {
+       case DATA_TYPE_INT:
+               ret = resource_monitor_get_value_int(
+                                               res->mon_id, res->res_id,
+                                               res->attrs[i].id,
+                                               &(res->attrs[i].value_int32));
+               if (ret < 0) break;
+
+               printf("%40d | %-5s | %s",
+                               res->attrs[i].value_int32,
+                               res->attrs[i].unit, res->attrs[i].desc);
+               break;
+       case DATA_TYPE_INT64:
+               ret = resource_monitor_get_value_int64(
+                                               res->mon_id, res->res_id,
+                                               res->attrs[i].id,
+                                               &(res->attrs[i].value_int64));
+               if (ret < 0) break;
+
+               printf("%40"PRId64" | %-5s | %s",
+                               res->attrs[i].value_int64,
+                               res->attrs[i].unit, res->attrs[i].desc);
+               break;
+       case DATA_TYPE_UINT:
+               ret = resource_monitor_get_value_uint(
+                                               res->mon_id, res->res_id,
+                                               res->attrs[i].id,
+                                               &(res->attrs[i].value_uint32));
+               if (ret < 0) break;
+
+               printf("%40u | %-5s | %s",
+                               res->attrs[i].value_uint32,
+                               res->attrs[i].unit, res->attrs[i].desc);
+               break;
+       case DATA_TYPE_UINT64:
+               ret = resource_monitor_get_value_uint64(
+                                               res->mon_id, res->res_id,
+                                               res->attrs[i].id,
+                                               &(res->attrs[i].value_uint64));
+               if (ret < 0) break;
+
+               printf("%40"PRId64" | %-5s | %s",
+                               res->attrs[i].value_uint64,
+                               res->attrs[i].unit, res->attrs[i].desc);
+               break;
+       case DATA_TYPE_DOUBLE:
+               ret = resource_monitor_get_value_double(
+                                               res->mon_id, res->res_id,
+                                               res->attrs[i].id,
+                                               &(res->attrs[i].value_double));
+               if (ret < 0) break;
+
+               printf("%40.2f | %-5s | %s",
+                               res->attrs[i].value_double,
+                               res->attrs[i].unit, res->attrs[i].desc);
+               break;
+       case DATA_TYPE_STRING:
+               ret = resource_monitor_get_value_string(
+                                               res->mon_id, res->res_id,
+                                               res->attrs[i].id,
+                                               &res->attrs[i].value_string);
+               if (ret < 0) break;
+
+               printf("%40s | %-5s | %s",
+                               res->attrs[i].value_string,
+                               res->attrs[i].unit, res->attrs[i].desc);
+               free(res->attrs[i].value_string);
+               break;
+       case DATA_TYPE_ARRAY:
+               ret = get_resource_attr_array_value(res, i);
+               break;
+       case DATA_TYPE_PTR:
+       case DATA_TYPE_BOOLEAN:
+               printf("(%40s) | %-5s | %s", "Not Implemented",
+                               res->attrs[i].unit, res->attrs[i].desc);
+               break;
+       default:
+               printf("(%40s)", "Unknown Data Type");
+               break;
+       }
+
+       if (ret < 0)
+               printf("%40s | %-5s | %s", "Failed to Get Value",
+                               res->attrs[i].unit, res->attrs[i].desc);
+}
+
+static void system_resource_monitor_exit(int signal)
+{
+       int i;
+
+       for (i = 0; i < g_data.num_res; i++)
+               unset_attrs_and_delete_resource(&g_data.res[i]);
+
+       resource_monitor_exit(g_data.mon_id);
+
+       printf("Exit system-resource-monitor\n");
+       exit(0);
+}
+
+static int system_resource_monitor_init(void)
+{
+       int id, i, j, count, ret;
+
+       /* 1. Initialize resource-monitor */
+       id = resource_monitor_init();
+       g_data.mon_id = id;
+
+       /* 2. Get resource count */
+       for (i = 0; i < ARRAY_SIZE(g_resource_type); i++) {
+               if (g_resource_type[i].res_count) {
+                       count = g_resource_type[i].res_count;
+               } else {
+                       ret =  resource_monitor_get_resource_count(id, g_resource_type[i].type, &count);
+                       if (ret < 0)
+                               continue;
+               }
+
+               if (g_resource_type[i].ctrl_val < 0)
+                       continue;
+
+               for (j = 0; j < count; j++) {
+                       struct resource_data *res = &g_data.res[g_data.num_res++];
+
+                       res->mon_id = g_data.mon_id;
+                       res->res_index = j;
+                       res->type = g_resource_type[i].type;
+                       res->ctrl_id = g_resource_type[i].ctrl_id;
+                       res->num_attrs = g_resource_type[i].num_attrs;
+                       memcpy(res->attrs, g_resource_type[i].attrs, sizeof(struct resource_attr_data) * res->num_attrs);
+                       res->ctrl_val = g_resource_type[i].ctrl_val;
+               }
+       }
+
+       for (i = 0; i < g_data.num_res; i++) {
+               struct resource_data *res = &g_data.res[i];
+
+               if (res->ctrl_val > 0)
+                       create_resource_and_set_attrs(res, res->ctrl_val);
+               else
+                       create_resource_and_set_attrs(res, res->res_index);
+       }
+
+       return 0;
+}
+
+static void system_resource_monitor(void)
+{
+       int id = g_data.mon_id;
+       int count = 0;
+       int i, j;
+
+       while (1) {
+               if (g_data.max != -1 && g_data.max <= count++)
+                       break;
+
+               /* 4. Update resource attribute value */
+               resource_monitor_update(id);
+
+               printf("-------------------------------------------------------------------------------------------------------------------------------\n");
+               printf("%2s:%2s| %50s | %40s | %-5s | %s\n",
+                               "", "", "Resource Attribute Name", "Resource Attribute Value", "Unit", "Resource Attribute Description");
+               printf("-------------------------------------------------------------------------------------------------------------------------------\n");
+
+               for (i = 0; i < g_data.num_res; i++) {
+                       struct resource_data *res = &g_data.res[i];
+
+                       for (j = 0; j < res->num_attrs; j++) {
+                               printf("%2d:%2d| %50s | ", i, j, res->attrs[j].name);
+                               get_resource_attr_value(res, j);
+                               printf("\n");
+                       }
+                       printf("\n");
+               }
+               sleep(g_data.secs);
+       }
+       system_resource_monitor_exit(0);
+}
+
+static void usage()
+{
+       printf("Usage:\n");
+       printf("    resource-moniotr -h | -d secs -n max\n");
+}
+
+int main(int argc, char *argv[])
+{
+       int i;
+       int opt = 1;
+
+       /* Initialize default value and parse command line */
+       g_data.secs = 1;        /* default sampling rate is 1 second. */
+       g_data.max = -1;        /* default count is infinite. */
+
+       while (opt < argc) {
+               if (!strncmp(argv[opt], "-", 1)) {
+                       for (i = 1; *(argv[opt] + i); i++) {
+                               switch (*(argv[opt] + i)) {
+                               case 'd':
+                                       g_data.secs = atoi(argv[opt + 1]);
+                                       break;
+                               case 'n':
+                                       g_data.max = atoi(argv[opt + 1]);
+                                       break;
+                               case 'h':
+                                       usage();
+                                       exit(0);
+                               default:
+                                       usage();
+                               }
+                       }
+               }
+               opt++;
+       }
+
+       /* Register signal handler for freeing resources */
+       signal(SIGINT, system_resource_monitor_exit);
+
+       /* Initialize available resources and resource attributes */
+       system_resource_monitor_init();
+
+       /* Start resource monitor */
+       system_resource_monitor();
+
+       return 0;
+}