summaryrefslogtreecommitdiffstats
path: root/src/sleep
diff options
context:
space:
mode:
authorSonali Srivastava <srivastava.sonali1@gmail.com>2022-07-20 11:17:04 +0200
committerSonali Srivastava <srivastava.sonali1@gmail.com>2022-07-20 14:09:07 +0200
commit91ea7ebcdfac18137a1f3d1e89d99917ad66d87f (patch)
tree696d22a49f7ccad2cf14321da2f50c821854f92d /src/sleep
parentsleep: use current charge level to decide suspension (diff)
downloadsystemd-91ea7ebcdfac18137a1f3d1e89d99917ad66d87f.tar.xz
systemd-91ea7ebcdfac18137a1f3d1e89d99917ad66d87f.zip
sleep: store battery discharge rate/hour with hash
Estimated battery discharge rate per hour is stored in : /var/lib/systemd/sleep/battery_discharge_percentage_rate_per_hour This value is used to determine the initial suspend interval. In case this file is not available or value is invalid, HibernateDelaySec interval is used. After wakeup from initial suspend, this value is again estimated and written to file if value is in range of 1-199. Logs for reference : HibernateDelaySec=15min - Updated in /etc/systemd/sleep.conf Jul 14 19:17:58 localhost systemd-sleep[567]: Current battery charge percentage: 100% Jul 14 19:17:58 localhost systemd-sleep[567]: Failed to read discharge rate from /var/lib/systemd/sleep/batt ery_discharge_percentage_rate_per_hour: No such file or directory Jul 14 19:17:58 localhost systemd-sleep[567]: Set timerfd wake alarm for 15min Jul 14 19:33:00 localhost systemd-sleep[567]: Current battery charge percentage after wakeup: 90% Jul 14 19:33:00 localhost systemd-sleep[567]: Attempting to estimate battery discharge rate after wakeup from 15min sleep Jul 14 19:33:00 localhost systemd-sleep[567]: product_id does not exist: No such file or directory Jul 14 19:33:00 localhost systemd-sleep[567]: Estimated discharge rate 39 successfully updated to /var/lib/systemd/sleep/battery_discharge_percentage_rate_per_hour Jul 14 19:33:00 localhost systemd-sleep[567]: Current battery charge percentage: 90% Jul 14 19:33:00 localhost systemd-sleep[567]: product_id does not exist: No such file or directory Jul 14 19:33:00 localhost systemd-sleep[567]: Set timerfd wake alarm for 1h 48min 27s Jul 14 21:21:30 localhost systemd-sleep[567]: Current battery charge percentage after wakeup: 90% Jul 14 21:21:30 localhost systemd-sleep[567]: Battery was not discharged during suspension
Diffstat (limited to 'src/sleep')
-rw-r--r--src/sleep/sleep.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index 8e36933de2..a1905dbc27 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -272,7 +272,7 @@ static int execute_s2h(const SleepConfig *sleep_config) {
struct itimerspec ts = {};
usec_t suspend_interval = sleep_config->hibernate_delay_sec, before_timestamp = 0, after_timestamp = 0;
bool woken_by_timer;
- int last_capacity = 0, current_capacity = 0, estimated_discharge_rate = 0;
+ int last_capacity = 0, current_capacity = 0, previous_discharge_rate, estimated_discharge_rate = 0;
tfd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK|TFD_CLOEXEC);
if (tfd < 0)
@@ -290,6 +290,22 @@ static int execute_s2h(const SleepConfig *sleep_config) {
else
return log_error_errno(r, "Error fetching battery capacity percentage: %m");
+ r = get_battery_discharge_rate();
+ if (r < 0)
+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, "Failed to get discharge rate, ignoring: %m");
+ else if (last_capacity * 2 <= r) {
+ /* System should hibernate in case discharge rate is higher than double of battery current capacity
+ * why double : Because while calculating suspend interval, we have taken a buffer of 30 minute and
+ * discharge_rate is calculated on per 60 minute basis which is double. Also suspend_interval > 0 */
+ log_debug("Current battery percentage capacity too low to suspend, so invoking hibernation");
+ break;
+ } else {
+ previous_discharge_rate = r;
+ assert(previous_discharge_rate != 0);
+ suspend_interval = usec_sub_unsigned(last_capacity * USEC_PER_HOUR / previous_discharge_rate, 30 * USEC_PER_MINUTE);
+ /* The previous discharge rate is stored in per hour basis so converted to minutes.
+ * Substracted 30 minutes from the result to keep a buffer of 30 minutes before battery gets critical */
+ }
log_debug("Set timerfd wake alarm for %s", FORMAT_TIMESPAN(suspend_interval, USEC_PER_SEC));
/* Wake alarm for system with or without battery to hibernate or estimate discharge rate whichever is applicable */
timespec_store(&ts.it_value, suspend_interval);
@@ -325,6 +341,9 @@ static int execute_s2h(const SleepConfig *sleep_config) {
log_debug("Attempting to estimate battery discharge rate after wakeup from %s sleep", FORMAT_TIMESPAN(after_timestamp - before_timestamp, USEC_PER_HOUR));
estimated_discharge_rate = (last_capacity - current_capacity) * USEC_PER_HOUR / (after_timestamp - before_timestamp);
+ r = put_battery_discharge_rate(estimated_discharge_rate);
+ if (r < 0)
+ log_warning_errno(r, "Failed to update battery discharge rate, ignoring: %m");
}
if (!woken_by_timer)