blob: 0c82df15593b97e8c74ce32dd33c9d41acde022a [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>();
39 log<level::INFO>("watchdog: disabled");
40 }
41 }
42 return WatchdogInherits::enabled(value);
43}
44
45// Get the remaining time before timer expires.
46// If the timer is disabled, returns 0
47uint64_t Watchdog::timeRemaining() const
48{
49 uint64_t timeRemain = 0;
50
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053051 if (this->enabled())
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053052 {
53 // timer may have already expired and disabled
54 if (timer.getEnabled() != SD_EVENT_OFF)
55 {
56 // the one-shot timer does not expire yet
57 auto expiry = duration_cast<milliseconds>(
58 timer.getRemaining());
59
60 // convert to msec per interface expectation.
61 auto timeNow = duration_cast<milliseconds>(
62 Timer::getCurrentTime());
63
64 // Its possible that timer may have expired by now.
65 // So need to cross verify.
66 timeRemain = (expiry > timeNow) ?
67 (expiry - timeNow).count() : 0;
68 }
69 }
70 return timeRemain;
71}
72
73// Reset the timer to a new expiration value
74uint64_t Watchdog::timeRemaining(uint64_t value)
75{
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053076 if (this->enabled())
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053077 {
78 // Disable the timer
79 timer.setEnabled<std::false_type>();
80
81 // Timer handles all in microseconds and hence converting
82 auto usec = duration_cast<microseconds>(
83 milliseconds(value));
84 // Update new expiration
85 timer.start(usec);
86
87 // Enable the timer.
88 timer.setEnabled<std::true_type>();
89
90 log<level::INFO>("watchdog: reset timer",
91 entry("VALUE=%llu", value));
92
93 // Update Base class data.
94 return WatchdogInherits::timeRemaining(value);
95 }
96 return 0;
97}
98
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +053099// Optional callback function on timer expiration
100void Watchdog::timeOutHandler()
101{
Vishwanatha Subbanna3473d702017-05-30 16:38:50 +0530102 if (!target.empty())
103 {
104 auto method = bus.new_method_call(SYSTEMD_SERVICE,
105 SYSTEMD_ROOT,
106 SYSTEMD_INTERFACE,
107 "StartUnit");
108 method.append(target);
109 method.append("replace");
110
111 bus.call_noreply(method);
112 }
113 return;
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +0530114}
115
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530116} // namespace watchdog
117} // namepsace phosphor