From 51762660ab87bf1b2eabe0f20546638f2560a7e2 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 22 Mar 2018 17:02:45 +0900 Subject: [PATCH 01/16] core: device-notifier: Remove unused notifier definition DEVICE_NOTIFIER_POWER_OFF notifier definition is not used. Remove it. Change-Id: I30ab609c55aa0f43b8b1a4fefcb6db2a716161a5 Signed-off-by: Chanwoo Choi --- include/pass/device-notifier.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/pass/device-notifier.h b/include/pass/device-notifier.h index 77c571f..f045abc 100644 --- a/include/pass/device-notifier.h +++ b/include/pass/device-notifier.h @@ -25,7 +25,6 @@ enum device_notifier_type { DEVICE_NOTIFIER_BOOTING_DONE, DEVICE_NOTIFIER_PMQOS, - DEVICE_NOTIFIER_POWEROFF, DEVICE_NOTIFIER_MAX, }; -- 2.7.4 From fedc0928b15f6ac1917d9be4186078e1730feb26 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 22 Mar 2018 18:31:31 +0900 Subject: [PATCH 02/16] core: device-notifier: Add new DEVICE_NOTIFIER_THERMAL DEVICE_NOTIFIER_THERMAL is used to notify the thermal level. Change-Id: I46e19f32b347ce70626876be5f8e8f7993795879 Signed-off-by: Chanwoo Choi --- include/pass/device-notifier.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/pass/device-notifier.h b/include/pass/device-notifier.h index f045abc..d95a6db 100644 --- a/include/pass/device-notifier.h +++ b/include/pass/device-notifier.h @@ -25,6 +25,7 @@ enum device_notifier_type { DEVICE_NOTIFIER_BOOTING_DONE, DEVICE_NOTIFIER_PMQOS, + DEVICE_NOTIFIER_THERMAL, DEVICE_NOTIFIER_MAX, }; -- 2.7.4 From f770e15a4e52ac4c7b4b6aedcf977a7a32ee1fbd Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 20 Mar 2018 16:59:34 +0900 Subject: [PATCH 03/16] core: gdbus: Add new gdbus function to send broadcast signal Add new following new function in order to send broadcast signal through d-bus interface: - int pass_gdbus_send_broadcast_signal(char *path, char *interface, char *method, GVariant *arg) Change-Id: I4e08a984f234fb4557e94f446e2d0aea86afc768 Signed-off-by: Chanwoo Choi --- include/pass/gdbus-util.h | 4 ++++ src/core/gdbus-util.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/pass/gdbus-util.h b/include/pass/gdbus-util.h index 306e859..f6be0b9 100644 --- a/include/pass/gdbus-util.h +++ b/include/pass/gdbus-util.h @@ -19,6 +19,7 @@ #ifndef __GDBUS_UTIL_H__ #define __GDBUS_UTIL_H__ +#include #include #include @@ -51,6 +52,9 @@ int pass_gdbus_connect_signal(gpointer instance, int num_signals, struct pass_gdbus_signal_info *signal_infos); void pass_gdbus_disconnect_signal(gpointer instance, int num_signals, struct pass_gdbus_signal_info *signal_infos); +int pass_gdbus_send_broadcast_signal(char *path, char *interface, + char *method, GVariant *arg); + SystemPassCore *pass_gdbus_get_instance_core(void); void pass_gdbus_put_instance_core(SystemPassCore **instance); SystemPassPmqos *pass_gdbus_get_instance_pmqos(void); diff --git a/src/core/gdbus-util.c b/src/core/gdbus-util.c index 42d21b8..6a672db 100644 --- a/src/core/gdbus-util.c +++ b/src/core/gdbus-util.c @@ -188,6 +188,45 @@ void pass_gdbus_disconnect_signal(gpointer instance, int num_signals, } } +int pass_gdbus_send_broadcast_signal(char *path, char *interface, char *method, + GVariant *arg) +{ + GDBusMessage *message = NULL; + GError *err = NULL; + int ret; + + if (!path || !interface || !method || !arg) { + _E("invalid parameter\n"); + return -EINVAL; + } + + if (!g_dbus_sys_conn) { + _E("cannot get the dbus connection to system message bus\n"); + return -ENOSYS; + } + + /* Make the dbus message to send broadcast signal */ + message = g_dbus_message_new_signal(path, interface, method); + if (!message) { + _E("failed to allocate new %s.%s signal", interface, method); + return -EPERM; + } + g_dbus_message_set_body(message, arg); + + /* Send broadcast signal */ + ret = g_dbus_connection_send_message(g_dbus_sys_conn, message, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err); + if (!ret) { + _E("failed to broadcast [%s][%d]", method, arg); + g_object_unref(message); + return -ECOMM; + } + + g_object_unref(message); + + return 0; +} + static void put_instance(gpointer *instance) { g_object_unref(*instance); -- 2.7.4 From bc00af81b9b9376069e66fbd9eb68f6988a83240 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 20 Mar 2018 15:29:31 +0900 Subject: [PATCH 04/16] scripts: Add pass-thermal.conf configuration Thermal Monitor is able to define the multiple scenario indicating the thermal status. Thermal Monitor uses the defined scenarios when reporting the current system status according to raw temperature. pass-thermal.conf contains the supported scenarios of Themral Monitor. It will be located in "/etc/pass/pass-thermal.conf" Change-Id: I98e4a109b47f1a4d398dfbf1cc4cdb08efa596e7 Signed-off-by: Chanwoo Choi --- CMakeLists.txt | 1 + packaging/pass.spec | 1 + scripts/pass-thermal.conf | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 scripts/pass-thermal.conf diff --git a/CMakeLists.txt b/CMakeLists.txt index f787e45..26cab5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,6 +156,7 @@ TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} "-ldl" "-lm") INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/${PROJECT_NAME}.conf DESTINATION /etc/dbus-1/system.d) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-pmqos.conf DESTINATION /etc/pass) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-thermal.conf DESTINATION /etc/pass) CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) diff --git a/packaging/pass.spec b/packaging/pass.spec index 8c1ffc8..f274516 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -86,6 +86,7 @@ systemctl daemon-reload %license LICENSE %config %{_sysconfdir}/dbus-1/system.d/%{daemon_name}.conf %config %{_sysconfdir}/pass/pass-pmqos.conf +%config %{_sysconfdir}/pass/pass-thermal.conf %{_bindir}/%{daemon_name} %{_unitdir}/multi-user.target.wants/%{daemon_name}.service %{_unitdir}/%{daemon_name}.service diff --git a/scripts/pass-thermal.conf b/scripts/pass-thermal.conf new file mode 100644 index 0000000..ad0f02d --- /dev/null +++ b/scripts/pass-thermal.conf @@ -0,0 +1,25 @@ +[thermal] +# set to "yes" thermal_support (Default value is no) +# set thermal_number_of_scenario to be tested +thermal_support=yes +thermal_number_of_scenario=4 + +# describe the scenario section as follows +#[Scenario0] +#name=ReleaseAction +#support=yes +[thermal.scenario0] +name=ReleaseAction +support=yes + +[thermal.scenario1] +name=WarningAction +support=yes + +[thermal.scenario2] +name=LimitAction +support=yes + +[thermal.scenario3] +name=ShutdownAction +support=yes -- 2.7.4 From 49f1f60714bb1efb691f7677eefb404de14173b7 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 22 Mar 2018 18:34:13 +0900 Subject: [PATCH 05/16] thermal: Add new Thermal Monitor module PASS can monitor the various h/w resource such as CPU/GPU and so on. The thermal information is one of them. Require the thermal monitoring and then notify the meaningful data of thermal. So, Thermal Monitor is required. Thermal Monitor supports the configuration file in order to define the thermal scenarios (e.g., ReleaseAction, ShutdownAction) according to the user definition. It is very flexible to define the multiple thermal scenarios. Thermal Monitor monitors the thermal information using following two methods: - uevent-based thermal monitoring (interrupt method) - timer-baesd thermal monitoring (polling method) [d-bus interface] - d-bus interface: "org.tizen.system.pass.monitor.thermal" - d-bus method : "thermal_scenario" - configuration : /etc/pass/pass-thermal.conf Change-Id: I63c138d33350f6e17f9ad9bb73bd837b4f2a278e Signed-off-by: Chanwoo Choi --- CMakeLists.txt | 11 ++ include/pass/gdbus-util.h | 4 + scripts/thermal-dbus.xml | 11 ++ src/core/gdbus-util.c | 10 ++ src/thermal/thermal-parser.c | 163 ++++++++++++++++++++++++ src/thermal/thermal.c | 286 +++++++++++++++++++++++++++++++++++++++++++ src/thermal/thermal.h | 40 ++++++ 7 files changed, 525 insertions(+) create mode 100644 scripts/thermal-dbus.xml create mode 100644 src/thermal/thermal-parser.c create mode 100644 src/thermal/thermal.c create mode 100644 src/thermal/thermal.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 26cab5a..b57486a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,8 @@ SET(SRCS src/pass/pass-pmqos.c src/pmqos/pmqos.c src/pmqos/pmqos-parser.c + src/thermal/thermal.c + src/thermal/thermal-parser.c src/hal/hal.c src/core/common.c src/core/config-parser.c @@ -85,6 +87,8 @@ SET(SRCS src/pass/pass-dbus-stub.c #Generated by a custom command 'gdbus-codegen' below src/pmqos/pmqos-dbus-stub.c + #Generated by a custom command 'gdbus-codegen' below + src/thermal/thermal-dbus-stub.c ) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) @@ -150,6 +154,13 @@ ADD_CUSTOM_COMMAND( --output-directory src/pmqos/ scripts/pmqos-dbus.xml COMMENT "Generating GDBus stub for pmqos interface") +ADD_CUSTOM_COMMAND( + OUTPUT src/thermal/thermal-dbus-stub.c + COMMAND gdbus-codegen --interface-prefix org.tizen. + --generate-c-code thermal-dbus-stub + --output-directory src/thermal/ + scripts/thermal-dbus.xml + COMMENT "Generating GDBus stub for thermal interface") ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} "-ldl" "-lm") diff --git a/include/pass/gdbus-util.h b/include/pass/gdbus-util.h index f6be0b9..eaa09ea 100644 --- a/include/pass/gdbus-util.h +++ b/include/pass/gdbus-util.h @@ -25,6 +25,7 @@ #include "pass/pass-dbus-stub.h" #include "pmqos/pmqos-dbus-stub.h" +#include "thermal/thermal-dbus-stub.h" #define SYSTEMD_DBUS_NAME "org.freedesktop.systemd1" #define SYSTEMD_DBUS_OBJECT_PATH "/org/freedesktop/systemd1" @@ -59,6 +60,9 @@ SystemPassCore *pass_gdbus_get_instance_core(void); void pass_gdbus_put_instance_core(SystemPassCore **instance); SystemPassPmqos *pass_gdbus_get_instance_pmqos(void); void pass_gdbus_put_instance_pmqos(SystemPassPmqos **instance); +SystemPassMonitorThermal *pass_gdbus_get_instance_thermal(void); +void pass_gdbus_put_instance_thermal(SystemPassMonitorThermal **instance); + int pass_gdbus_get_system_connection(void); void pass_gdbus_put_system_connection(void); #endif /* __GDBUS_UTIL_H__ */ diff --git a/scripts/thermal-dbus.xml b/scripts/thermal-dbus.xml new file mode 100644 index 0000000..0b4b6f1 --- /dev/null +++ b/scripts/thermal-dbus.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/core/gdbus-util.c b/src/core/gdbus-util.c index 6a672db..d18137c 100644 --- a/src/core/gdbus-util.c +++ b/src/core/gdbus-util.c @@ -253,6 +253,16 @@ void pass_gdbus_put_instance_pmqos(SystemPassPmqos **instance) put_instance((gpointer *)instance); } +SystemPassMonitorThermal *pass_gdbus_get_instance_thermal(void) +{ + return system_pass_monitor_thermal_skeleton_new(); +} + +void pass_gdbus_put_instance_thermal(SystemPassMonitorThermal **instance) +{ + put_instance((gpointer *)instance); +} + int pass_gdbus_get_system_connection(void) { GError *error = NULL; diff --git a/src/thermal/thermal-parser.c b/src/thermal/thermal-parser.c new file mode 100644 index 0000000..3dab8b5 --- /dev/null +++ b/src/thermal/thermal-parser.c @@ -0,0 +1,163 @@ +/* + * PASS (Power Aware System Service) - Parser for Thermal Monitor + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * based on src/pmqos/pmqos-parser.c + * + * 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 "thermal.h" + +#define MAX_NUM_OF_SCENARIOS 255 + +static bool is_supported(const char *value) +{ + assert(value); + + if (MATCH(value, "yes")) + return true; + return false; +} + +static int thermal_parse_scenario(struct parse_result *result, void *user_data, + unsigned int index) +{ + struct thermal_scenario *scenarios = (struct thermal_scenario *)user_data; + + assert(result); + assert(result->section && result->name && result->value); + + /* Parse 'thermal' section */ + if (MATCH(result->section, "thermal")) { + if (MATCH(result->name, "thermal_support")) + scenarios->support = is_supported(result->value); + else if (MATCH(result->name, "thermal_number_of_scenario")) { + int num = atoi(result->value); + + if (num > MAX_NUM_OF_SCENARIOS) + return -EINVAL; + + if (num > 0) { + scenarios->list = calloc(num, + sizeof(struct scenario)); + if (!scenarios->list) { + _E("failed to allocate scenario memory"); + return -errno; + } + + scenarios->num = num; + } + } + } + + if (!scenarios->support || !scenarios->num) + return 0; + + if (index > scenarios->num) + return 0; + + /* Parse 'Scenario' section */ + if (MATCH(result->name, "name")) + snprintf(scenarios->list[index].name, + strlen(result->value) + 1, "%s", result->value); + else if (MATCH(result->name, "support")) + scenarios->list[index].support = is_supported(result->value); + + return 0; +} + +static int thermal_load_config(struct parse_result *result, void *user_data) +{ + struct thermal_scenario *scenarios + = (struct thermal_scenario *)user_data; + char name[NAME_MAX]; + int ret; + static int index; + + if (!result) + return 0; + + if (!result->section || !result->name || !result->value) + return 0; + + /* Parsing 'thermal' section */ + if (MATCH(result->section, "thermal")) { + ret = thermal_parse_scenario(result, user_data, -1); + if (ret < 0) { + _E("failed to parse [thermal] section : %d", ret); + return ret; + } + goto out; + } + + /* Parsing 'thermal.scenario' section */ + for (index = 0; index < scenarios->num; ++index) { + snprintf(name, sizeof(name), "thermal.scenario%d", index); + + if (MATCH(result->section, name)) { + ret = thermal_parse_scenario(result, user_data, index); + if (ret < 0) { + _E("failed to parse [thermal.scenario%d] section : %d", + index, ret); + return ret; + } + goto out; + } + } + +out: + return 0; +} + +int thermal_put_scenario(struct thermal_scenario *scenarios) +{ + if (!scenarios) + return -EINVAL; + + if (scenarios->num > 0 && scenarios->list) { + scenarios->num = 0; + free(scenarios->list); + scenarios->list = NULL; + } + + return 0; +} + +int thermal_get_scenario(const char *path, struct thermal_scenario *scenarios) +{ + int ret; + + /* Initialize the variables before parsing the pass-thermal.conf */ + scenarios->num = 0; + + /* get configuration file */ + ret = config_parse(path, thermal_load_config, scenarios); + if (ret < 0) { + thermal_put_scenario(scenarios); + return ret; + } + + return 0; +} diff --git a/src/thermal/thermal.c b/src/thermal/thermal.c new file mode 100644 index 0000000..274635f --- /dev/null +++ b/src/thermal/thermal.c @@ -0,0 +1,286 @@ +/* + * PASS (Power Aware System Service) - Thermal Monitor + * + * Copyright (c) 2018 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 +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "thermal.h" + +#define THERMAL_CONF_PATH "/etc/pass/pass-thermal.conf" + +#define DBUS_THERMAL_I_START_HANDLER "handle_start" +#define DBUS_THERMAL_I_STOP_HANDLER "handle_stop" +#define DBUS_THERMAL_INTERFACE "org.tizen.system.pass.monitor.thermal" +#define DBUS_THERMAL_PATH "/Org/Tizen/System/Pass/Monitor/Thermal" +#define DBUS_THERMAL_METHOD "thermal_scenario" + +static SystemPassMonitorThermal *g_gdbus_instance = NULL; +static struct thermal_scenario *g_thermal = NULL; + +static void thermal_free(void) +{ + int ret; + + ret = thermal_put_scenario(g_thermal); + if (ret < 0) + _E("failed to pet Thermal Monitor scenario\n"); + + free(g_thermal); + g_thermal = NULL; +} + +static int thermal_init_done(void *data, void *user_data) +{ + int *booting_done; + int ret; + int i; + + /* + * As a callback function for the booting-done event, it is notified + * with the result of the booting_finished() function by using the + * first argument, void *data. When it is successfully booted up, an int + * value, 1 is passed with the first argument. + */ + booting_done = (int *)data; + if (!(*booting_done)) + return -EINVAL; + + if (g_thermal) + return 0; + + g_thermal = calloc(1, sizeof(struct thermal_scenario)); + if (!g_thermal) { + _E("failed to allocate the memory for thermal monitor\n"); + return -ENOMEM; + } + + ret = thermal_get_scenario(THERMAL_CONF_PATH, g_thermal); + if (ret < 0) { + _E("failed to get Thermal Monitor scenario\n"); + return ret; + } + + if (!g_thermal->support || g_thermal->num <= 0) { + ret = thermal_put_scenario(g_thermal); + if (ret < 0) + _E("failed to pet Thermal Monitor scenario\n"); + return ret; + } + + for (i = 0; i < g_thermal->num; i++) + if (g_thermal->list[i].support) + _I("Support \'%s\' scenario", g_thermal->list[i].name); + + return 0; +} + +static gboolean dbus_cb_thermal_start(SystemPassMonitorThermal *obj, + GDBusMethodInvocation *invoc, gpointer user_data) +{ + int ret = 0; + int booting_done = 1; + + if (g_thermal) + _I("Thermal Monitor is already started\n"); + else + ret = thermal_init_done(&booting_done, NULL); + + g_dbus_method_invocation_return_value(invoc, g_variant_new("(i)", ret)); + + if (!ret) + return TRUE; + + _E("failed to initialize Thermal Monitor of the daemon " + "in dbus callback for a start message\n"); + return FALSE; +} + +static gboolean dbus_cb_thermal_stop(SystemPassMonitorThermal *obj, + GDBusMethodInvocation *invoc, gpointer user_data) +{ + if (!g_thermal) + _I("Thermal Monitor is already stopped\n"); + else + thermal_free(); + + g_dbus_method_invocation_return_value(invoc, g_variant_new("(i)", 0)); + + return TRUE; +} + + +static struct pass_gdbus_signal_info g_gdbus_signal_infos[] = { + { + .handler = DBUS_THERMAL_I_START_HANDLER, + .cb = G_CALLBACK(dbus_cb_thermal_start), + .cb_data = NULL, + .ret_id = 0, + }, { + .handler = DBUS_THERMAL_I_STOP_HANDLER, + .cb = G_CALLBACK(dbus_cb_thermal_stop), + .cb_data = NULL, + .ret_id = 0, + }, +}; + +/* + * data: thermal action string + * user_data: instance of struct pass_resource + */ +static int thermal_notifier_cb(void *data, void *user_data) +{ + GVariant *gvar; + int ret; + int i; + + if (!g_thermal || !g_thermal->support || g_thermal->num <= 0) { + _I("Thermal Monitor is stopped\n"); + return 0; + } + + if (!data) + return -EINVAL; + + /* Find the available thermal scenario */ + for (i = 0; i < g_thermal->num; i++) { + if (!g_thermal->list[i].support) + continue; + if (!strncmp(g_thermal->list[i].name, data, strlen(data))) + break; + } + + /* If there is no available thermal scenario, just return */ + if (i >= g_thermal->num) { + _I("Not supported \'%s\' scenario", data); + return 0; + } + + /* If there is available thermal scenario, send the broadcast signal */ + gvar = g_variant_new("(s)", data); + ret = pass_gdbus_send_broadcast_signal(DBUS_THERMAL_PATH, + DBUS_THERMAL_INTERFACE, + DBUS_THERMAL_METHOD, + gvar); + if (ret < 0) { + _E("failed to send broadcast signal of thermal monitor(%d)\n", + ret); + } + + return 0; +} + +static void thermal_init(void *data) +{ + /* This is the case of daemon creation: DO NOTHING */ + return; +} + +static void thermal_exit(void *data) +{ + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, + thermal_init_done, NULL); + + pass_gdbus_disconnect_signal(g_gdbus_instance, + ARRAY_SIZE(g_gdbus_signal_infos), g_gdbus_signal_infos); + pass_gdbus_put_instance_thermal(&g_gdbus_instance); + + thermal_free(); +} + +static int thermal_probe(void *data) +{ + int ret = 0; + + /* Initialize the d-bus interface for Thermal Monitor */ + g_gdbus_instance = pass_gdbus_get_instance_thermal(); + if (!g_gdbus_instance) { + _E("failed to get a dbus instance for the %s interface\n", + DBUS_THERMAL_INTERFACE); + return -ENOSYS; + } + + ret = pass_gdbus_connect_signal(g_gdbus_instance, + ARRAY_SIZE(g_gdbus_signal_infos), g_gdbus_signal_infos); + if (ret < 0) { + _E("failed to register callbacks as the dbus method invocation " + "handlers\n"); + ret = -ENOSYS; + goto out; + } + + ret = pass_gdbus_export_interface(g_gdbus_instance, DBUS_THERMAL_PATH); + if (ret < 0) { + _E("failed to export the dbus interface '%s' " + "at the object path '%s'\n", + DBUS_THERMAL_INTERFACE, + DBUS_THERMAL_PATH); + ret = -ENOSYS; + goto out_disconnect; + } + + /* + * Register a notifier for the booting-done event. The actual + * initialization of the daemon is performed by this notifier after + * booting is completely done. + */ + ret = register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, + thermal_init_done, NULL); + if (ret < 0) { + _E("failed to register a callback function \ + for the booting-done event (%d)\n", ret); + goto out_disconnect; + } + + /* Register DEVICE_NOTIFIER_THERMAL */ + ret = register_notifier(DEVICE_NOTIFIER_THERMAL, thermal_notifier_cb, + NULL); + if (ret < 0) { + _E("failed to register notifier for thermal monitor (%d)\n", + ret); + goto out_booting_done; + } + + return 0; + +out_booting_done: + unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, + thermal_init_done, NULL); +out_disconnect: + pass_gdbus_disconnect_signal(g_gdbus_instance, + ARRAY_SIZE(g_gdbus_signal_infos), g_gdbus_signal_infos); +out: + pass_gdbus_put_instance_thermal(&g_gdbus_instance); + + return ret; +} + +static const struct device_ops thermal_device_ops = { + .name = "thermal", + .probe = thermal_probe, + .init = thermal_init, + .exit = thermal_exit, +}; +DEVICE_OPS_REGISTER(&thermal_device_ops) diff --git a/src/thermal/thermal.h b/src/thermal/thermal.h new file mode 100644 index 0000000..9da0cdc --- /dev/null +++ b/src/thermal/thermal.h @@ -0,0 +1,40 @@ +/* + * PASS (Power Aware System Service) - Thermal Monitor + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * based on src/thermal/thermal-parser.c + * + * 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 __THERMAL_H__ +#define __THERMAL_H__ + +#include +#include + +struct thermal_scenario { + struct scenario { + char name[NAME_MAX]; + bool support; + } *list; + + int num; + bool support; +}; + +int thermal_get_scenario(const char *path, struct thermal_scenario *scenarios); +int thermal_put_scenario(struct thermal_scenario *scenarios); + +#endif /* __THERMAL_H__ */ -- 2.7.4 From 821baa23cfbf89ccc414dfde698794b70a60aa4d Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 22 Mar 2018 19:30:54 +0900 Subject: [PATCH 06/16] pass: pmqos: Group the private data of PMQoS module into struct pmqos PASS uses the 'scenario' expression which indicates the unique user-scnaerio or the specific situation. 'struct pass_pmqos' is used to handle 'scenario'. 'struct pass_pmqos' is used on multiple modules and then it might have both common variables and specific variables used on particular PASS module. So, group the private data of PMQOS module into the 'struct pmqos'. Change-Id: I65111779ecd2dca7ff2ecbc5ace1d6e16f1824c8 Signed-off-by: Chanwoo Choi --- src/pass/pass-parser.c | 4 ++-- src/pass/pass-pmqos.c | 20 ++++++++++---------- src/pass/pass.h | 19 +++++++++++-------- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/pass/pass-parser.c b/src/pass/pass-parser.c index 37b4595..c14f27f 100644 --- a/src/pass/pass-parser.c +++ b/src/pass/pass-parser.c @@ -92,9 +92,9 @@ static int parse_scenario(struct parse_result *result, if (scenario->state < 0) return -EINVAL; } else if (MATCH(result->name, "min_level")) { - scenario->min_level = atoi(result->value); + scenario->pmqos.min_level = atoi(result->value); } else if (MATCH(result->name, "max_level")) { - scenario->max_level = atoi(result->value); + scenario->pmqos.max_level = atoi(result->value); } return 0; diff --git a/src/pass/pass-pmqos.c b/src/pass/pass-pmqos.c index 2e7d4aa..0625699 100644 --- a/src/pass/pass-pmqos.c +++ b/src/pass/pass-pmqos.c @@ -120,26 +120,26 @@ static int pmqos_notifier_cb(void *data, void *user_data) * Compare locked state of scenario with * if state is same as existing state */ - if (scn->locked == locked) { + if (scn->pmqos.locked == locked) { _E("'%s' scenario is already %s for '%s' resource\n", name, (locked == PASS_ON) ? "Locked" : "Unlocked", config_data->res_name); return 0; } - scn->locked = locked; + scn->pmqos.locked = locked; - if (scn->locked) { + if (scn->pmqos.locked) { if (pmqos->num_locked_scenarios == 0) new_level = pmqos->init_level = res->rescon.curr_level; else new_level = pmqos->curr_level; - min_level = MAX(scn->min_level, pmqos->min_level); - max_level = MAX(scn->max_level, pmqos->max_level); + min_level = MAX(scn->pmqos.min_level, pmqos->min_level); + max_level = MAX(scn->pmqos.max_level, pmqos->max_level); if (new_level < min_level) new_level = min_level; else if (new_level > max_level) - new_level = scn->max_level; + new_level = scn->pmqos.max_level; pmqos->curr_level = new_level; pmqos->min_level = min_level; @@ -166,17 +166,17 @@ static int pmqos_notifier_cb(void *data, void *user_data) pass_rescon_set_level_scope(res, new_level, min_level, max_level, data); - if (scn->locked) { + if (scn->pmqos.locked) { _I("Lock '%s' scenario for '%s' resource\n", name, config_data->res_name); - pmqos->scenarios[index].locked_time = get_time_ms(); + pmqos->scenarios[index].pmqos.locked_time = get_time_ms(); } else { _I("UnLock '%s' scenario for '%s' resource (%lldms)\n", name, config_data->res_name, - (get_time_ms() - pmqos->scenarios[index].locked_time)); + (get_time_ms() - pmqos->scenarios[index].pmqos.locked_time)); - pmqos->scenarios[index].locked_time = 0; + pmqos->scenarios[index].pmqos.locked_time = 0; } return 0; diff --git a/src/pass/pass.h b/src/pass/pass.h index 59b2265..7d6db7c 100644 --- a/src/pass/pass.h +++ b/src/pass/pass.h @@ -163,19 +163,22 @@ struct pass_level { * * @name: the unique scenario name. * @state: the state of the scenario (either supported or not). - * @locked: the locked state of scenario (either locked or unlocked). - * @locked_time: the requiired locking time of scenario. - * @min_level: the required minimum PASS's level. - * @max_level: the required maximum PASS's level. + * @pmqos: the private data for PASS_MODULE_PMQOS + * - locked: the locked state of scenario (either locked or unlocked). + * - locked_time: the requiired locking time of scenario. + * - min_level: the required minimum PASS's level. + * - max_level: the required maximum PASS's level. */ struct pass_scenario { char name[BUFF_MAX]; enum pass_state state; - enum pass_state locked; - int64_t locked_time; - unsigned int min_level; - unsigned int max_level; + struct { + enum pass_state locked; + int64_t locked_time; + unsigned int min_level; + unsigned int max_level; + } pmqos; }; /****************************************************** -- 2.7.4 From fa7aef0bf0c7fba9e3fa4627dcb7f22d6855f728 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 22 Mar 2018 19:56:26 +0900 Subject: [PATCH 07/16] pass: parser: Add support of thermal monitor for each h/w resource In order to use/support Thermal Monitor, each h/w resource (e.g., CPU/GPU) have to write the configuration such as thermal scenario name, temperature and timer interval for each thermal scenario. Parse the property for Thermal Monitor. Change-Id: I3aa08bcfbbb037897fff42cfe24aabc732610e05 Signed-off-by: Chanwoo Choi --- src/pass/pass-parser.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/pass/pass.h | 33 +++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/src/pass/pass-parser.c b/src/pass/pass-parser.c index c14f27f..cedbf76 100644 --- a/src/pass/pass-parser.c +++ b/src/pass/pass-parser.c @@ -91,10 +91,18 @@ static int parse_scenario(struct parse_result *result, scenario->state = is_supported(result->value); if (scenario->state < 0) return -EINVAL; + + /* Parse properties for only PASS_MODULE_PMQOS */ } else if (MATCH(result->name, "min_level")) { scenario->pmqos.min_level = atoi(result->value); } else if (MATCH(result->name, "max_level")) { scenario->pmqos.max_level = atoi(result->value); + + /* Parse properties for only PASS_MODULE_THERMAL */ + } else if (MATCH(result->name, "temperature")) { + scenario->thermal.temperature = atoi(result->value); + } else if (MATCH(result->name, "timer_interval_ms")) { + scenario->thermal.timer_interval = atoi(result->value); } return 0; @@ -221,6 +229,47 @@ static int parse_pmqos(struct parse_result *result, void *user_data) return 0; } +static int parse_thermal(struct parse_result *result, void *user_data) +{ + struct pass_resource *res = user_data; + struct pass_thermal *thermal = &res->thermal; + + if (!result) + return 0; + + if (!result->section || !result->name || !result->value) + return 0; + + /* Parse 'thermal' section */ + if (MATCH(result->name, "thermal_support")) { + thermal->state = is_supported(result->value); + if (thermal->state < 0) + return -EINVAL; + } else if (MATCH(result->name, "thermal_number_of_scenario")) { + unsigned int num_scenarios; + + num_scenarios = atoi(result->value); + if (num_scenarios > MAX_NUM) { + _E("cannot parse %s\n", result->name); + return -EINVAL; + } + + if (num_scenarios > 0 && !thermal->scenarios) { + thermal->scenarios = calloc(num_scenarios, + sizeof(struct pass_scenario)); + if (!thermal->scenarios) { + _E("cannot allocate memory for Scenario\n"); + return -EINVAL; + } + thermal->num_scenarios = num_scenarios; + } + } else if (MATCH(result->name, "thermal_timer_interval_ms")) { + thermal->timer_interval = atoi(result->value); + } + + return 0; +} + static int parse_core(struct parse_result *result, void *user_data) { struct pass_resource *res = user_data; @@ -279,6 +328,7 @@ static int parse_each_resource(struct parse_result *result, void *user_data) { struct pass_resource *res = user_data; struct pass_pmqos *pmqos = &res->pmqos; + struct pass_thermal *thermal = &res->thermal; char section_name[BUFF_MAX]; int i, ret; @@ -340,6 +390,32 @@ static int parse_each_resource(struct parse_result *result, void *user_data) } } + /* Parsing 'thermal' section */ + if (MATCH(result->section, "thermal")) { + ret = parse_thermal(result, user_data); + if (ret < 0) { + _E("cannot parse 'thermal' section\n"); + return ret; + } + + goto out; + } + + /* Parsing 'thermal.scenario' section */ + for (i = 0; i < thermal->num_scenarios; i++) { + ret = snprintf(section_name, BUFF_MAX, "thermal.scenario%d", i); + + if (MATCH(result->section, section_name)) { + ret = parse_scenario(result, &thermal->scenarios[i]); + if (ret < 0) { + _E("cannot parse 'thermal.scenario%d' section\n", i); + return ret; + } + + goto out; + } + } + out: return 0; } @@ -544,6 +620,7 @@ int pass_get_each_resource_config(struct pass_resource *res, char *path) { struct pass_cpuhp *cpuhp; struct pass_pmqos *pmqos; + struct pass_thermal *thermal; int ret; if (!res) @@ -551,6 +628,7 @@ int pass_get_each_resource_config(struct pass_resource *res, char *path) cpuhp = &res->cpuhp; pmqos = &res->pmqos; + thermal = &res->thermal; res->config_data.state = PASS_UNUSED; res->config_data.gov_type = 0; @@ -573,6 +651,9 @@ int pass_get_each_resource_config(struct pass_resource *res, char *path) /* Initialize the PMQoS's data */ pmqos->state = PASS_UNUSED; + /* Initialize the Thermal's data */ + thermal->state = PASS_UNUSED; + ret = config_parse(path, parse_each_resource, res); if (ret < 0) { _E("cannot parse %s\n", path); @@ -612,5 +693,11 @@ void pass_put_each_resource_config(struct pass_resource *res) res->pmqos.scenarios = NULL; } + if (res->thermal.scenarios) { + free(res->thermal.scenarios); + res->thermal.scenarios = NULL; + res->thermal.num_scenarios = 0; + } + res->pmqos.num_scenarios = 0; } diff --git a/src/pass/pass.h b/src/pass/pass.h index 7d6db7c..55c147a 100644 --- a/src/pass/pass.h +++ b/src/pass/pass.h @@ -168,6 +168,9 @@ struct pass_level { * - locked_time: the requiired locking time of scenario. * - min_level: the required minimum PASS's level. * - max_level: the required maximum PASS's level. + * @pmqos: the private data for PASS_MODULE_THERMAL + * - temperature: the temperature of the scenario. + * - timer_interval: the interval of timer-based monitor (unit: millisecond). */ struct pass_scenario { char name[BUFF_MAX]; @@ -179,6 +182,11 @@ struct pass_scenario { unsigned int min_level; unsigned int max_level; } pmqos; + + struct { + int temperature; + int timer_interval; + } thermal; }; /****************************************************** @@ -284,6 +292,29 @@ struct pass_cpuhp { struct pass_hotplug *hotplug; }; +/* + * struct pass_thermal - Represent Thermal Monitor module + * + * @state: the state of Thermal Monitor (either enabled or disabled). + * @num_scenarios: the number of scenarios. + * @scenarios: the list of scenarios. + * @timer_interval: the interval of timer-based monitor (unit: millisecond). + * @curr_scenario_idx: the index of current thermal scenario. + * @curr_temp: the current temperature. + * + * Thermal Monitor may be enabled or disabled according to configuration. + */ +struct pass_thermal { + enum pass_state state; + + unsigned int num_scenarios; + struct pass_scenario *scenarios; + + unsigned int timer_interval; + int curr_scenario_idx; + int curr_temp; +}; + /****************************************************** * PASS Resource * ******************************************************/ @@ -412,6 +443,7 @@ struct pass_resource_init_data { * @resmon: represents ResMon (Resource Monitor) module. * @cpuhp: represents CPUHP (CPU Hotplug Manager) module. * @pmqos: represents PMQoS module. + * @thermal: represents Thermal Monitor module. */ struct pass_resource { enum pass_state state; @@ -432,6 +464,7 @@ struct pass_resource { struct pass_cpuhp cpuhp; struct pass_pmqos pmqos; + struct pass_thermal thermal; }; /****************************************************** -- 2.7.4 From cf17199cdf78dd3acc49c09a8e94d0db5dec385a Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 22 Mar 2018 19:57:07 +0900 Subject: [PATCH 08/16] pass: thermal: Add support of Thermal Monitor of each h/w resource In order to use Thermal Monitor, each h/w resource (e.g. CPU/GPU) monitors the thermal information with timer-based and uevent-based resource monitors. If the monitored temperature is included in the range of defined thermal scenario, it send the notification to Thermal Monitor module. The pass-thermal.c is the developerment for each h/w resource. Change-Id: I0dbf77202e1c3d7bc54803b064c9d29d687b661b Signed-off-by: Chanwoo Choi --- CMakeLists.txt | 1 + src/pass/pass-thermal.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++ src/pass/pass.c | 28 ++++++- src/pass/pass.h | 2 + 4 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 src/pass/pass-thermal.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b57486a..6ed9f45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,7 @@ SET(SRCS src/pass/pass-resmon.c src/pass/pass-resmon-source.c src/pass/pass-pmqos.c + src/pass/pass-thermal.c src/pmqos/pmqos.c src/pmqos/pmqos-parser.c src/thermal/thermal.c diff --git a/src/pass/pass-thermal.c b/src/pass/pass-thermal.c new file mode 100644 index 0000000..4de164b --- /dev/null +++ b/src/pass/pass-thermal.c @@ -0,0 +1,189 @@ +/* + * PASS (Power Aware System Service) Thermal Monitor with RESMON + * + * Copyright (c) 2018 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 +#include +#include + +#include "pass.h" +#include "pass-resmon.h" + +#define DEFAULT_TEMPERATURE (-1000) + +static int thermal_monitor_func(void *result, void *user_data) +{ + struct pass_resource *res = user_data; + struct resmon_result_src_thermal *thermal_result = result; + struct pass_thermal *thermal; + int timer_interval_of_scenario, timer_interval; + int curr_temp, prev_temp; + int temp; + int ret; + int i, scenario_idx; + + if (!res || !thermal_result) { + _E("invalid parameter for thermal monitor\n"); + return -EINVAL; + } + + thermal = &res->thermal; + prev_temp = thermal->curr_temp; + curr_temp = thermal_result->temp; + + if (prev_temp == curr_temp) + return 0; + + scenario_idx = -1; + for (i = 0; i < thermal->num_scenarios; i++) { + temp = thermal->scenarios[i].thermal.temperature; + + if (thermal->scenarios[i].state != PASS_ON) + continue; + + if (scenario_idx < 0 && curr_temp < temp) + scenario_idx = i; + else if (temp <= curr_temp) + scenario_idx = i; + } + + /* + * If temperature is lower than defined temperature in configuration + * or if there are no scearnio with 'support=yes', + * just return without notification. + */ + if (scenario_idx < 0) + return 0; + + if (thermal->curr_scenario_idx == scenario_idx) + return 0; + + /* + * Send notification with thermal scenario name according to + * measured temperature of each h/w resource. + */ + device_notify(DEVICE_NOTIFIER_THERMAL, + (void *)thermal->scenarios[scenario_idx].name); + + _I("Monitor '%s' scenario for '%s' resource ('%d' degrees Celsius)\n", + thermal->scenarios[scenario_idx].name, + res->config_data.res_name, curr_temp); + + /* Get the new timer interval of each scenario */ + timer_interval_of_scenario + = thermal->scenarios[scenario_idx].thermal.timer_interval; + if (timer_interval_of_scenario > 0) + timer_interval = timer_interval_of_scenario; + else + timer_interval = res->thermal.timer_interval; + + ret = pass_resmon_update_timer_interval(res, RESMON_SRC_THERMAL, + timer_interval); + if (ret < 0) { + _W("failed to update interval of timer-based monitor " \ + "(res_name:%s, src_type: 0x%x)\n", + res->config_data.res_name, RESMON_SRC_THERMAL); + } + + thermal->curr_temp = curr_temp; + thermal->curr_scenario_idx = scenario_idx; + + return 0; +} + +int pass_thermal_init(struct pass_resource *res) +{ + int ret; + + if (!res) + return -EINVAL; + if (res->thermal.state != PASS_ON) + return 0; + + /* + * Register timer-based resource monitor to monitor thermal info. + * Have to do the first monitoring as soon as possible. Register + * timer-based resource monitor with 1000 millisecond and then + * update the timer interval with the required value + * after first monitoring is finished. + */ + ret = pass_resmon_register_timer(res, RESMON_SRC_THERMAL, + RESMON_TIMER_PERIODIC, 1000, + thermal_monitor_func, res); + if (ret < 0) { + _E("failed to register timer-based monitor " \ + "(res_name:%s, src_type: 0x%x)\n", + res->config_data.res_name, RESMON_SRC_THERMAL); + return -EINVAL; + } + + /* Register uevent-based resource monitor to monitor thermal info. */ + ret = pass_resmon_register_uevent(res, RESMON_SRC_THERMAL, + thermal_monitor_func, res); + if (ret < 0) { + _E("failed to register uevent-based monitor " \ + "(res_name:%s, src_type: 0x%x)\n", + res->config_data.res_name, RESMON_SRC_THERMAL); + goto err_timer; + } + + /* Initialize the default scenario index */ + res->thermal.curr_scenario_idx = -1; + res->thermal.curr_temp = DEFAULT_TEMPERATURE; + + return 0; + +err_timer: + ret = pass_resmon_unregister_timer(res, RESMON_SRC_THERMAL); + if (ret < 0) { + _E("failed to unregister timer-based monitor " \ + "(res_name:%s, src_type: 0x%x)\n", + res->config_data.res_name, RESMON_SRC_THERMAL); + } + + return -EINVAL; +} + +int pass_thermal_exit(struct pass_resource *res) +{ + int ret; + + if (!res) + return -EINVAL; + if (res->thermal.state != PASS_ON) + return -EINVAL; + + ret = pass_resmon_unregister_uevent(res, RESMON_SRC_THERMAL); + if (ret < 0) { + _E("failed to unregister uevent-based monitor " \ + "(res_name:%s, src_type: 0x%x)\n", + res->config_data.res_name, RESMON_SRC_THERMAL); + } + + ret = pass_resmon_unregister_timer(res, RESMON_SRC_THERMAL); + if (ret < 0) { + _E("failed to unregister timer-based monitor " \ + "(res_name:%s, src_type: 0x%x)\n", + res->config_data.res_name, RESMON_SRC_THERMAL); + } + + /* Initialize the default scenario index */ + res->thermal.curr_scenario_idx = -1; + res->thermal.curr_temp = DEFAULT_TEMPERATURE; + + return 0; +} diff --git a/src/pass/pass.c b/src/pass/pass.c index b599787..aa86b14 100644 --- a/src/pass/pass.c +++ b/src/pass/pass.c @@ -44,7 +44,8 @@ static uint64 supported_module[] = { | PASS_MODULE_RESCON | PASS_MODULE_RESMON | PASS_MODULE_PMQOS - | PASS_MODULE_CPUHP, + | PASS_MODULE_CPUHP + | PASS_MODULE_THERMAL, [PASS_RESOURCE_BUS_ID] = PASS_MODULE_PARSER | PASS_MODULE_RESCON @@ -54,7 +55,8 @@ static uint64 supported_module[] = { [PASS_RESOURCE_GPU_ID] = PASS_MODULE_PARSER | PASS_MODULE_RESCON | PASS_MODULE_RESMON - | PASS_MODULE_PMQOS, + | PASS_MODULE_PMQOS + | PASS_MODULE_THERMAL, [PASS_RESOURCE_MEMORY_ID] = PASS_MODULE_PARSER | PASS_MODULE_RESCON @@ -73,6 +75,8 @@ extern int pass_cpuhp_init(struct pass_resource *res); extern int pass_cpuhp_exit(struct pass_resource *res); extern int pass_pmqos_init(struct pass_resource *res); extern int pass_pmqos_exit(struct pass_resource *res); +extern int pass_thermal_init(struct pass_resource *res); +extern int pass_thermal_exit(struct pass_resource *res); static struct pass g_pass; static SystemPassCore *g_gdbus_instance = NULL; @@ -207,8 +211,20 @@ static int pass_init_resource(struct pass_resource *res) } } + if (is_supported_module(res, PASS_MODULE_THERMAL)) { + ret = pass_thermal_init(res); + if (ret < 0) { + _E("cannot initialize PASS Thermal Monitor"); + goto err_thermal; + } + } + return 0; +err_thermal: + if (is_supported_module(res, PASS_MODULE_PMQOS)) + if (pass_pmqos_exit(res) < 0) + _E("cannot exit PASS PMQoS"); err_pmqos: if (is_supported_module(res, PASS_MODULE_CPUHP)) if (pass_cpuhp_exit(res) < 0) @@ -248,6 +264,14 @@ static int pass_exit_resource(struct pass_resource *res) } } + if (is_supported_module(res, PASS_MODULE_THERMAL)) { + ret = pass_thermal_exit(res); + if (ret < 0) { + _E("cannot exit PASS Thermal Monitor"); + return ret; + } + } + /* * Have to exit ResCon (Resource-Controller) and ResMon * (Resource Monitor) after called exit() function of modules. diff --git a/src/pass/pass.h b/src/pass/pass.h index 55c147a..8a07cf8 100644 --- a/src/pass/pass.h +++ b/src/pass/pass.h @@ -41,6 +41,7 @@ struct pass_cpuhp_governor; * PASS_MODULE_RESMON: Represents the Resource Controller module * PASS_MODULE_PMQOS: Represents the Scenario-based PMQoS module * PASS_MODULE_CPUHP: Represents the CPU Hotplug Manager module + * PASS_MODULE_THERMAL: Represents the Thermal Monitor module */ enum pass_module_type { PASS_MODULE_UNKNOWN = 0x0, @@ -50,6 +51,7 @@ enum pass_module_type { PASS_MODULE_RESMON = 0x4, PASS_MODULE_PMQOS = 0x8, PASS_MODULE_CPUHP = 0x10, + PASS_MODULE_THERMAL = 0x20, }; /* -- 2.7.4 From f5d9f156f0de346436607536616c79c09622cd83 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 4 Apr 2018 13:05:54 +0900 Subject: [PATCH 09/16] pass: resmon: Remove duplicate free operation of monitor instance Change-Id: Ibbaa488ec6d42e1f566ec9bab847411fed992ba0 Signed-off-by: Chanwoo Choi --- src/pass/pass-resmon.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/pass/pass-resmon.c b/src/pass/pass-resmon.c index 9736870..fe45b5f 100644 --- a/src/pass/pass-resmon.c +++ b/src/pass/pass-resmon.c @@ -172,6 +172,9 @@ static int resmon_timer_delete(struct resmon *monitor) resmon->timer_list = g_list_remove(resmon->timer_list, (gpointer)monitor); + free(monitor); + monitor = NULL; + return 0; } @@ -218,9 +221,6 @@ static gboolean resmon_timer_func(gpointer data) res->config_data.res_name, monitor->src_type); return false; } - - free(monitor); - monitor = NULL; break; case RESMON_TIMER_PERIODIC: break; @@ -338,10 +338,6 @@ int pass_resmon_unregister_timer(struct pass_resource *res, res->config_data.res_type, src_type); } - /* Free the memory of resource monitor */ - free(monitor); - monitor = NULL; - return 0; } -- 2.7.4 From 83052f4b42d5402b517f42f8e32af203cdfffa9d Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 25 Apr 2018 17:15:45 +0900 Subject: [PATCH 10/16] scripts: Simplify the deny permission for PASS dbus interface Prior to that PASS denies the each d-bus interface for pmqos/pass core. Deny the parent dbus interface instead of each d-bus interface when user is not root and unauthorized user. Change-Id: I29a400178535222de637738d44e0269e0b282c72 Signed-off-by: Chanwoo Choi --- scripts/pass.conf | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/pass.conf b/scripts/pass.conf index 9c63d7b..aa07ffd 100644 --- a/scripts/pass.conf +++ b/scripts/pass.conf @@ -10,9 +10,7 @@ send_interface="org.tizen.system.pass.pmqos"/> - - + + -- 2.7.4 From 7807b1f6e776f57ee0fc747645f7931fe15513ae Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 10 May 2018 13:04:07 +0900 Subject: [PATCH 11/16] scripts: Fix dbus issue to get dbus well-known name The commit 83052f4b42d5 ("scripts: Simplify the deny permission for PASS dbus interface") causes the dbus deny issue such as AppLaunch request. Fix dbus issue to get dbus well-known name. Change-Id: Id20941500249e6b6c753730fde336aedce4cfbdf Fixes: 83052f4b42d5 ("scripts: Simplify the deny permission for PASS dbus interface") Suggested-by: Sanghyeok Oh Signed-off-by: Chanwoo Choi --- scripts/pass.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/pass.conf b/scripts/pass.conf index aa07ffd..e622253 100644 --- a/scripts/pass.conf +++ b/scripts/pass.conf @@ -5,6 +5,10 @@ + + + + -- 2.7.4 From 92b030f5613c29d84b5574315dfc509b2a4a3629 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 9 May 2018 19:23:15 +0900 Subject: [PATCH 12/16] Remove dependency of unneeded libtzplatform-config package Change-Id: Ifd1a7b230ebd138bd3e991221bb7d066a02d0d01 Signed-off-by: Chanwoo Choi --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ed9f45..05a959b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,6 @@ SET(PKG_MODULES gio-2.0 gio-unix-2.0 libudev - libtzplatform-config ) INCLUDE(FindPkgConfig) -- 2.7.4 From cf2cceefd6c8695283178dd09451c1f22b8f95f7 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 10 May 2018 14:06:50 +0900 Subject: [PATCH 13/16] pass: thermal: Fix issue during stop PASS daemon thermal->state indicates the "thermal_support" property in the configuration. If user doesn't want to use thermal monitor with "thermal_support=no", thermal->state is 0 (PASS_OFF). It is not error when thermal->state is zero. Just return zero value instead of error. Change-Id: I04f76774afb3b811d56dc0ebfb3f0888541e649f Signed-off-by: Chanwoo Choi --- src/pass/pass-thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pass/pass-thermal.c b/src/pass/pass-thermal.c index 4de164b..290950b 100644 --- a/src/pass/pass-thermal.c +++ b/src/pass/pass-thermal.c @@ -165,7 +165,7 @@ int pass_thermal_exit(struct pass_resource *res) if (!res) return -EINVAL; if (res->thermal.state != PASS_ON) - return -EINVAL; + return 0; ret = pass_resmon_unregister_uevent(res, RESMON_SRC_THERMAL); if (ret < 0) { -- 2.7.4 From bf7fdcf95b0cbb3517e874292f788a6c40cd1f7b Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Fri, 11 May 2018 17:50:33 +0900 Subject: [PATCH 14/16] packaging: Remove unneeded package's dependency Change-Id: I7a641708123de7f02c68aa36685e8cb1fa1aed3c Signed-off-by: Chanwoo Choi --- packaging/pass.spec | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packaging/pass.spec b/packaging/pass.spec index f274516..8f64774 100644 --- a/packaging/pass.spec +++ b/packaging/pass.spec @@ -14,19 +14,12 @@ Source1: %{name}.manifest Source2: %{hal_name}.manifest BuildRequires: cmake -BuildRequires: libattr-devel -BuildRequires: gettext-devel -BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(dlog) -BuildRequires: pkgconfig(device-node) -BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(dbus-1) BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(gio-unix-2.0) BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(eventsystem) BuildRequires: pkgconfig(libudev) -BuildRequires: pkgconfig(libtzplatform-config) %description PASS (Power-Aware System Service) -- 2.7.4 From 7623f121b200e02949e1a73dacc87e2f20f61d14 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Fri, 1 Jun 2018 10:25:46 +0900 Subject: [PATCH 15/16] core: Remove unused helper functions Change-Id: I70c130c7715dab70f11294547889022a44ff93ce Signed-off-by: Chanwoo Choi --- include/pass/common.h | 57 ---------------------------- src/core/common.c | 102 -------------------------------------------------- 2 files changed, 159 deletions(-) diff --git a/include/pass/common.h b/include/pass/common.h index 9de28a3..b11571d 100644 --- a/include/pass/common.h +++ b/include/pass/common.h @@ -77,16 +77,6 @@ typedef unsigned long long uint64; }) #endif -#ifndef clamp -#define clamp(x, low, high) \ - __extension__ ({ \ - typeof(x) _x = (x); \ - typeof(low) _low = (low); \ - typeof(high) _high = (high); \ - ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \ - }) -#endif - #ifndef SEC_TO_MSEC #define SEC_TO_MSEC(x) ((x)*1000) #endif @@ -100,54 +90,7 @@ typedef unsigned long long uint64; #define USEC_TO_MSEC(x) ((double)x/1000) #endif -#define NANO_SECOND_MULTIPLIER 1000000 /* 1ms = 1,000,000 nsec */ - -#ifndef safe_free -#define safe_free(x) safe_free_memory((void**)&(x)) -#endif - -static inline void safe_free_memory(void** mem) -{ - if (mem && *mem) { - free(*mem); - *mem = NULL; - } -} - -#define ret_value_if(expr, val) do { \ - if (expr) { \ - _E("(%s)", #expr); \ - return (val); \ - } \ -} while (0) - -#define ret_value_msg_if(expr, val, fmt, arg...) do { \ - if (expr) { \ - _E(fmt, ##arg); \ - return val; \ - } \ -} while (0) - -#define ret_msg_if(expr, fmt, arg...) do { \ - if (expr) { \ - _E(fmt, ##arg); \ - return; \ - } \ -} while (0) - -FILE * open_proc_oom_score_adj_file(int pid, const char *mode); -int get_exec_pid(const char *execpath); -int get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size); -int is_vip(int pid); -int remove_dir(const char *path, int del_dir); -int sys_check_node(char *path); int sys_get_int(char *fname, int *val); -int sys_set_int(char *fname, int val); int sys_get_str(char *fname, char *str); -int sys_set_str(char *fname, char *val); -int terminate_process(const char *partition, bool force); -int mount_check(const char* path); -void print_time(const char *prefix); -int get_privilege(pid_t pid, char *name, size_t len); #endif /* __CORE_COMMON_H__ */ diff --git a/src/core/common.c b/src/core/common.c index a0ee779..6e2150a 100644 --- a/src/core/common.c +++ b/src/core/common.c @@ -39,64 +39,6 @@ #define BUFF_MAX 255 -int get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size) -{ - int fd, ret; - char buf[PATH_MAX + 1]; - char *filename; - - if (!cmdline_size) - return -1; - - snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); - fd = open(buf, O_RDONLY); - if (fd < 0) { - errno = ESRCH; - return -1; - } - - ret = read(fd, buf, PATH_MAX); - close(fd); - if ((ret >= 0) && (ret <= PATH_MAX)) { - buf[ret] = '\0'; - } else { - errno = EIO; - return -1; - } - - filename = strrchr(buf, '/'); - if (filename == NULL) - filename = buf; - else - filename = filename + 1; - - if ((cmdline_size - 1) < strlen(filename)) { - errno = EOVERFLOW; - return -1; - } - - strncpy(cmdline, filename, cmdline_size - 1); - cmdline[cmdline_size - 1] = '\0'; - return 0; -} - -/* - * Helper function - * - Read from sysfs entry - * - Write to sysfs entry - */ -int sys_check_node(char *path) -{ - int fd; - - fd = open(path, O_RDONLY); - if (fd == -1) - return -1; - - close(fd); - return 0; -} - static int sys_read_buf(char *file, char *buf) { int fd; @@ -118,25 +60,6 @@ static int sys_read_buf(char *file, char *buf) return ret; } -static int sys_write_buf(char *file, char *buf) -{ - int fd; - int r; - int ret = 0; - - fd = open(file, O_WRONLY); - if (fd == -1) - return -ENOENT; - - r = write(fd, buf, strlen(buf)); - if (r < 0) - ret = -EIO; - - close(fd); - - return ret; -} - int sys_get_int(char *fname, int *val) { char buf[BUFF_MAX]; @@ -152,19 +75,6 @@ int sys_get_int(char *fname, int *val) return ret; } -int sys_set_int(char *fname, int val) -{ - char buf[BUFF_MAX]; - int ret = 0; - - snprintf(buf, sizeof(buf), "%d", val); - - if (sys_write_buf(fname, buf) != 0) - ret = -EIO; - - return ret; -} - int sys_get_str(char *fname, char *str) { char buf[BUFF_MAX] = {0}; @@ -176,15 +86,3 @@ int sys_get_str(char *fname, char *str) return -1; } - -int sys_set_str(char *fname, char *val) -{ - int r = -1; - - if (val != NULL) { - if (sys_write_buf(fname, val) == 0) - r = 0; - } - - return r; -} -- 2.7.4 From cc9043745b44afd3adf1296eb67f31ab34e56d81 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 17 Jul 2018 18:12:13 +0900 Subject: [PATCH 16/16] packaging: Remove unused libpass.manifest file Change-Id: I62564514c93b12f7211f37427207aa898e315092 Signed-off-by: Chanwoo Choi --- packaging/libpass.manifest | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 packaging/libpass.manifest diff --git a/packaging/libpass.manifest b/packaging/libpass.manifest deleted file mode 100644 index 97e8c31..0000000 --- a/packaging/libpass.manifest +++ /dev/null @@ -1,5 +0,0 @@ - - - - - -- 2.7.4