blob: 0c93d31e5b2f883259659487e56c1d2dbac45425 [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
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053052 if (this->enabled())
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053053 {
54 // timer may have already expired and disabled
55 if (timer.getEnabled() != SD_EVENT_OFF)
56 {
57 // the one-shot timer does not expire yet
58 auto expiry = duration_cast<milliseconds>(
59 timer.getRemaining());
60
61 // convert to msec per interface expectation.
62 auto timeNow = duration_cast<milliseconds>(
63 Timer::getCurrentTime());
64
65 // Its possible that timer may have expired by now.
66 // So need to cross verify.
67 timeRemain = (expiry > timeNow) ?
68 (expiry - timeNow).count() : 0;
69 }
70 }
71 return timeRemain;
72}
73
74// Reset the timer to a new expiration value
75uint64_t Watchdog::timeRemaining(uint64_t value)
76{
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053077 if (this->enabled())
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053078 {
79 // Disable the timer
80 timer.setEnabled<std::false_type>();
81
82 // Timer handles all in microseconds and hence converting
83 auto usec = duration_cast<microseconds>(
84 milliseconds(value));
85 // Update new expiration
86 timer.start(usec);
87
88 // Enable the timer.
89 timer.setEnabled<std::true_type>();
90
Vishwanatha Subbannaf2309dd2017-06-06 23:15:19 +053091 // Update Interval in Base class.
92 this->interval(value);
93
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053094 // Update Base class data.
95 return WatchdogInherits::timeRemaining(value);
96 }
97 return 0;
98}
99
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +0530100// Optional callback function on timer expiration
101void Watchdog::timeOutHandler()
102{
Vishwanatha Subbanna3473d702017-05-30 16:38:50 +0530103 if (!target.empty())
104 {
105 auto method = bus.new_method_call(SYSTEMD_SERVICE,
106 SYSTEMD_ROOT,
107 SYSTEMD_INTERFACE,
108 "StartUnit");
109 method.append(target);
110 method.append("replace");
111
112 bus.call_noreply(method);
113 }
114 return;
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +0530115}
116
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530117} // namespace watchdog
118} // namepsace phosphor