blob: 12631a62911cea964064335cb42447a7f97e92d3 [file] [log] [blame]
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +05301#include <chrono>
2#include <phosphor-logging/log.hpp>
3#include "watchdog.hpp"
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +05304namespace phosphor
5{
6namespace watchdog
7{
8using namespace std::chrono;
9using namespace std::chrono_literals;
10using namespace phosphor::logging;
11
Vishwanatha Subbanna3473d702017-05-30 16:38:50 +053012// systemd service to kick start a target.
13constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
14constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
15constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
16
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053017// Enable or disable watchdog
18bool Watchdog::enabled(bool value)
19{
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053020 if (this->enabled() != value)
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053021 {
22 if (value)
23 {
24 // Start ONESHOT timer. Timer handles all in usec
25 auto usec = duration_cast<microseconds>(
26 milliseconds(this->interval()));
27 // Update new expiration
28 timer.start(usec);
29
30 // Enable timer
31 timer.setEnabled<std::true_type>();
32
33 log<level::INFO>("watchdog: enabled and started",
34 entry("INTERVAL=%llu", this->interval()));
35 }
36 else
37 {
38 timer.setEnabled<std::false_type>();
Patrick Venture09eebe32017-08-11 15:23:17 -070039 timer.clearExpired();
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053040 log<level::INFO>("watchdog: disabled");
41 }
42 }
43 return WatchdogInherits::enabled(value);
44}
45
46// Get the remaining time before timer expires.
47// If the timer is disabled, returns 0
48uint64_t Watchdog::timeRemaining() const
49{
50 uint64_t timeRemain = 0;
51
William A. Kennington III1c9515f2018-02-27 18:54:36 -080052 // timer may have already expired and disabled
William A. Kennington III0650a3f2018-03-01 10:53:25 -080053 if (timerEnabled())
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053054 {
William A. Kennington III1c9515f2018-02-27 18:54:36 -080055 // the one-shot timer does not expire yet
56 auto expiry = duration_cast<milliseconds>(
57 timer.getRemaining());
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053058
William A. Kennington III1c9515f2018-02-27 18:54:36 -080059 // convert to msec per interface expectation.
60 auto timeNow = duration_cast<milliseconds>(
61 Timer::getCurrentTime());
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053062
William A. Kennington III1c9515f2018-02-27 18:54:36 -080063 // Its possible that timer may have expired by now.
64 // So need to cross verify.
65 timeRemain = (expiry > timeNow) ?
66 (expiry - timeNow).count() : 0;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053067 }
68 return timeRemain;
69}
70
71// Reset the timer to a new expiration value
72uint64_t Watchdog::timeRemaining(uint64_t value)
73{
William A. Kennington III0650a3f2018-03-01 10:53:25 -080074 if (!timerEnabled())
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053075 {
William A. Kennington III5e3f8772018-02-27 18:59:58 -080076 // We don't need to update the timer because it is off
77 return 0;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053078 }
William A. Kennington III5e3f8772018-02-27 18:59:58 -080079
80 // Update new expiration
81 auto usec = duration_cast<microseconds>(milliseconds(value));
82 timer.start(usec);
83
84 // Update Base class data.
85 return WatchdogInherits::timeRemaining(value);
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053086}
87
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +053088// Optional callback function on timer expiration
89void Watchdog::timeOutHandler()
90{
William A. Kennington III1232a152018-02-02 15:57:34 -080091 auto action = expireAction();
92 auto target = actionTargets.find(action);
Vishwanatha Subbanna3473d702017-05-30 16:38:50 +053093
William A. Kennington III1232a152018-02-02 15:57:34 -080094 if (target == actionTargets.end())
95 {
96 log<level::INFO>("watchdog: Timed out with no target",
97 entry("ACTION=%s", convertForMessage(action).c_str()));
98 return;
Vishwanatha Subbanna3473d702017-05-30 16:38:50 +053099 }
William A. Kennington III1232a152018-02-02 15:57:34 -0800100
101 auto method = bus.new_method_call(SYSTEMD_SERVICE,
102 SYSTEMD_ROOT,
103 SYSTEMD_INTERFACE,
104 "StartUnit");
105 method.append(target->second);
106 method.append("replace");
107
108 log<level::INFO>("watchdog: Timed out",
109 entry("ACTION=%s", convertForMessage(action).c_str()),
110 entry("TARGET=%s", target->second.c_str()));
111 bus.call_noreply(method);
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +0530112}
113
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530114} // namespace watchdog
115} // namepsace phosphor